1// 2// main.c 3// IOPSCreatePowerSource-simple 4// 5// 6// 7 8#include <CoreFoundation/CoreFoundation.h> 9#include <IOKit/ps/IOPowerSources.h> 10#include <IOKit/ps/IOPowerSourcesPrivate.h> 11#include <IOKit/ps/IOPSKeys.h> 12#include <IOKit/IOCFSerialize.h> 13 14static CFDictionaryRef copyNextPSDictionary(void); 15static CFStringRef copyNextPSType(void); 16 17static void iterateCreateSetRelease(int iterations); 18static bool verifyThatAPublishedPowerSourceIsNamed(CFStringRef checkname); 19static void createAndCheckForExistence(CFStringRef useName); 20static void fillAndReleaseAllPowerSourceSlots(int count); 21 22static const int kTryDictionaries = 5; 23static const int kMaxPSCount = 7; 24 25int main(int argc, const char * argv[]) 26{ 27 for (int i = 0; i< 3; i++) 28 { 29 iterateCreateSetRelease(kTryDictionaries); 30 createAndCheckForExistence(CFSTR("Snaggletooth")); 31 fillAndReleaseAllPowerSourceSlots(kMaxPSCount * 2); 32 } 33} 34 35 36//****************************************************************************** 37//****************************************************************************** 38//****************************************************************************** 39 40static void createAndCheckForExistence(CFStringRef useName) 41{ 42 CFDictionaryRef useDictionary = NULL; 43 CFMutableDictionaryRef setDictionary = NULL; 44 IOReturn ret; 45 IOPSPowerSourceID psid = 0; 46 47 char buf[255]; 48 CFStringGetCString(useName, buf, sizeof(buf), kCFStringEncodingUTF8); 49 50 51 useDictionary = copyNextPSDictionary(); 52 if (useDictionary) { 53 setDictionary = CFDictionaryCreateMutableCopy(0, 0, useDictionary); 54 if (setDictionary) { 55 CFDictionarySetValue(setDictionary, CFSTR(kIOPSNameKey), useName); 56 } 57 CFRelease(useDictionary); 58 } 59 60 if (!setDictionary) { 61 printf("FAIL: createAndCheckForExistence couldn't create PS dictionary\n"); 62 return; 63 } 64 65 ret = IOPSCreatePowerSource(&psid); 66 if (kIOReturnSuccess != ret) { 67 printf("FAIL: createAndCheckForExistence couldn't create PS power source 0x%08x\n", ret); 68 return; 69 } 70 71 ret = IOPSSetPowerSourceDetails(psid, setDictionary); 72 if (kIOReturnSuccess != ret) { 73 printf("[FAIL] Failure return 0x%08x from IOPSSetPowerSourceDetails\n", ret); 74 exit(1); 75 } 76 CFRelease(setDictionary); 77 78 if (verifyThatAPublishedPowerSourceIsNamed(useName)) 79 { 80 printf("[PASS] Successfully created, then found, a power source named %s\n", buf); 81 } else { 82 printf("[FAIL] createAndCheckForExistence couldn't locate a power source named %s\n", buf); 83 system("pmset -g ps"); 84 } 85 86 IOPSReleasePowerSource(psid); 87 88 // We want to wait a second to let the release power source percolate through powerd 89 // before we check if the Release worked. 90 sleep(1); 91 92 if (!verifyThatAPublishedPowerSourceIsNamed(useName)) 93 { 94 printf("[PASS] Successfully RELEASED (it's not published any more), a power source named %s\n", buf); 95 } else { 96 printf("[FAIL] createAndCheckForExistence just released a power source, but it's still published %s\n", buf); 97 system("pmset -g ps"); 98 } 99 100 fflush(stdout); 101 return; 102} 103 104static bool verifyThatAPublishedPowerSourceIsNamed(CFStringRef checkname) 105{ 106 CFTypeRef blob = NULL; 107 CFArrayRef arr = NULL; 108 CFDictionaryRef details = NULL; 109 bool doMatch = false; 110 111 blob = IOPSCopyPowerSourcesInfo(); 112 if (blob) { 113 arr = IOPSCopyPowerSourcesList(blob); 114 } 115 116 if (!arr) { 117 return false; 118 } 119 120 for (int i=0; i<CFArrayGetCount(arr); i++) { 121 details = CFArrayGetValueAtIndex(arr, i); 122 if (!details) { 123 continue; 124 } 125 126 CFStringRef hasName = NULL; 127 hasName = CFDictionaryGetValue(details, CFSTR(kIOPSNameKey)); 128 if (hasName && CFEqual(checkname, hasName)) { 129 doMatch = true; 130 break; 131 } 132 } 133 134 if (arr) { 135 CFRelease(arr); 136 } 137 if (blob) { 138 CFRelease(blob); 139 } 140 return doMatch; 141} 142 143 144static void fillAndReleaseAllPowerSourceSlots(int count) 145{ 146 IOReturn ret; 147 148 IOPSPowerSourceID *ids = calloc(count, sizeof(IOPSPowerSourceID)); 149 150 for (int i=0; i<count; i++) 151 { 152 153 CFStringRef pstype = copyNextPSType(); 154 if (!pstype) { 155 printf("[FAIL] internal error generating testing ps type"); 156 exit(1); 157 } 158 159 /* 160 * Create 161 */ 162 ret = IOPSCreatePowerSource(&ids[i]); 163 164 printf("Creating %d power sources to exceed limits (%d returns 0x%08x)\n", count, i, ret); 165 if (ret != kIOReturnSuccess 166 && ret != kIOReturnNoSpace) 167 { 168 printf("[FAIL] IOPSCreatePowerSource return value was 0x%08x, should have been Success or NoSpace.\n", ret); 169 } 170 fflush(stdout); 171 } 172 173 174 for (int i=0; i<count; i++) 175 { 176 /* 177 * Release 178 */ 179 ret = IOPSReleasePowerSource(ids[i]); 180 if (kIOReturnSuccess != ret) { 181 printf("[FAIL] Failure return 0x%08x from IOPSReleasePowerSource\n", ret); 182 } 183 printf("Release %d power sources to exceed limits (%d returns 0x%08x)\n", count, i, ret); 184 fflush(stdout); 185 } 186 187} 188 189static void iterateCreateSetRelease(int iterations) 190{ 191 IOReturn ret; 192 193 IOPSPowerSourceID psid = NULL; 194 195 for (int i=0; i<iterations; i++) 196 { 197 printf("Big iteration %d of %d\n", i, iterations); 198 199 CFStringRef pstype = copyNextPSType(); 200 if (!pstype) { 201 printf("[FAIL] internal error generating testing ps type"); 202 exit(1); 203 } 204 205 /* 206 * Create 207 */ 208 ret = IOPSCreatePowerSource(&psid); 209 if (kIOReturnSuccess != ret) { 210 printf("[FAIL] Failure return 0x%08x from IOPSCreatePowerSource\n", ret); 211 exit(1); 212 } 213 214 /* 215 * Set 216 */ 217 CFDictionaryRef psdict = NULL; 218 psdict = copyNextPSDictionary(); 219 220 if (!psdict) { 221 printf("[FAIL] internal error generating testing dictionary"); 222 exit(1); 223 } 224 ret = IOPSSetPowerSourceDetails(psid, psdict); 225 if (kIOReturnSuccess != ret) { 226 printf("[FAIL] Failure return 0x%08x from IOPSSetPowerSourceDetails\n", ret); 227 exit(1); 228 } 229 CFRelease(psdict); 230 231 /* 232 * Release 233 */ 234 ret = IOPSReleasePowerSource(psid); 235 if (kIOReturnSuccess != ret) { 236 printf("[FAIL] Failure return 0x%08x from IOPSReleasePowerSource\n", ret); 237 exit(1); 238 } 239 240 fflush(stdout); 241 242 } 243 244} 245 246 247//****************************************************************************** 248//****************************************************************************** 249//****************************************************************************** 250 251static CFStringRef copyNextPSType(void) 252{ 253 static int t = 0; 254 CFStringRef _types[] = { 255 CFSTR(kIOPSInternalBatteryType), 256 CFSTR(kIOPSUPSType) 257// CFSTR("HenryThe8thBogus") 258 }; 259 260 return _types[t++ % (sizeof(_types)/sizeof(_types[0]))]; 261} 262 263//****************************************************************************** 264enum { 265 kCurrentCapacity = 0, 266 kMaxCapacity, 267 kName, 268 kTimeToEmpty, 269 kTimeToFull, 270 kTimeRemaining, 271 kIsCharged, 272 kIsCharging, 273 kIsPresent, 274 kDesignCap, 275 kVoltage, 276 kIsFinishingCharge, 277 kTransportType 278}; 279 280//****************************************************************************** 281static CFDictionaryRef copyNextPSDictionary(void) 282{ 283 const CFStringRef keys[] = { 284 CFSTR(kIOPSCurrentCapacityKey), 285 CFSTR(kIOPSMaxCapacityKey), 286 CFSTR(kIOPSNameKey), 287 CFSTR(kIOPSTimeToEmptyKey), 288 CFSTR(kIOPSTimeToFullChargeKey), 289 CFSTR(kIOPSTimeRemainingNotificationKey), 290 CFSTR(kIOPSIsChargedKey), 291 CFSTR(kIOPSIsChargingKey), 292 CFSTR(kIOPSIsPresentKey), 293 CFSTR(kIOPSDesignCapacityKey), 294 CFSTR(kIOPSVoltageKey), 295 CFSTR(kIOPSIsFinishingChargeKey), 296 CFSTR(kIOPSTransportTypeKey) 297 }; 298 299 CFTypeRef *values = NULL; 300 int tmpInt = 0; 301 302 int count = sizeof(keys)/sizeof(CFTypeRef); 303 values = calloc(1, sizeof(keys)); 304 305 tmpInt = 6000; 306 values[kCurrentCapacity] = CFNumberCreate(0, kCFNumberIntType, &tmpInt); 307 values[kMaxCapacity] = CFNumberCreate(0, kCFNumberIntType, &tmpInt); 308 values[kName] = CFSTR("com.iokit.IOPSCreatePowerSource"); 309 tmpInt = 25; 310 values[kTimeToEmpty] = CFNumberCreate(0, kCFNumberIntType, &tmpInt); 311 tmpInt = 0; 312 values[kTimeToFull] = CFNumberCreate(0, kCFNumberIntType, &tmpInt); 313 values[kTimeRemaining] = CFNumberCreate(0, kCFNumberIntType, &tmpInt); 314 values[kIsCharged] = CFRetain(kCFBooleanTrue); 315 values[kIsCharging] = CFRetain(kCFBooleanTrue); 316 values[kIsPresent] = CFRetain(kCFBooleanTrue); 317 tmpInt = 7000; 318 values[kDesignCap] = CFNumberCreate(0, kCFNumberIntType, &tmpInt); 319 tmpInt = 1100; 320 values[kVoltage] = CFNumberCreate(0, kCFNumberIntType, &tmpInt); 321 values[kIsFinishingCharge] = CFRetain(kCFBooleanTrue); 322 values[kTransportType] = CFSTR(kIOPSUSBTransportType); 323 324 return CFDictionaryCreate(0, (const void **)keys, (const void **)values, count, 325 &kCFTypeDictionaryKeyCallBacks, 326 &kCFTypeDictionaryValueCallBacks); 327 328} 329