int getPowerSource (void) // returns one of the three #defines above { int result = POWER_SOURCE_ERROR; CFTypeRef info = NULL; CFArrayRef powerSources = NULL; CFTypeRef source = NULL; CFDictionaryRef description = NULL; CFStringRef powerSourceState = NULL; info = IOPSCopyPowerSourcesInfo(); if (! info) goto ret; powerSources = IOPSCopyPowerSourcesList(info); if (! powerSources) goto ret; if (CFArrayGetCount(powerSources) == 0) goto ret; source = CFArrayGetValueAtIndex(powerSources, 0); if (! source) goto ret; description = IOPSGetPowerSourceDescription(info, source); if (! description) goto ret; powerSourceState = CFDictionaryGetValue(description, CFSTR(kIOPSPowerSourceStateKey)); if (! powerSourceState) goto ret; result = (CFStringCompare(powerSourceState, CFSTR(kIOPSACPowerValue), 0) == kCFCompareEqualTo) ? POWER_SOURCE_AC : POWER_SOURCE_BATTERY; ret : if (info) CFRelease (info); if (powerSources) CFRelease (powerSources); //if (source) CFRelease (source); //if (description) CFRelease (description); //if (powerSourceState) CFRelease (powerSourceState); return result; }
/*! Copy the current power dictionary. * * Caller must release power dictionary when finished with it. */ static CFDictionaryRef copy_power_dictionary(CFTypeRef power_key) { CFTypeRef power_blob; CFDictionaryRef power_dictionary; power_blob = IOPSCopyPowerSourcesInfo(); assert(power_blob); upsdebugx(6, "%s: Got power_blob:", __func__); if(nut_debug_level >= 6) CFShow(power_blob); upsdebugx(5, "power_key = "); if(nut_debug_level >= 5) CFShow(power_key); upsdebugx(6, "end power_key"); power_dictionary = IOPSGetPowerSourceDescription(power_blob, power_key); upsdebugx(5, "Asserting 'power_dictionary': %p", power_dictionary); assert(power_dictionary); upsdebugx(5, "CFShowing 'power_dictionary'"); if(nut_debug_level >= 5) CFShow(power_dictionary); CFRetain(power_dictionary); /* Get a new power_blob next time: */ CFRelease(power_blob); return power_dictionary; }
static double getBatData() { CFTypeRef sourceInfo = IOPSCopyPowerSourcesInfo(); CFArrayRef sourceList = IOPSCopyPowerSourcesList(sourceInfo); // Loop through sources, find the first battery int count = CFArrayGetCount(sourceList); CFDictionaryRef source = NULL; for(int i=0; i < count; i++) { source = IOPSGetPowerSourceDescription(sourceInfo, CFArrayGetValueAtIndex(sourceList, i)); // Is this a battery? CFStringRef type = (CFStringRef)CFDictionaryGetValue(source, CFSTR(kIOPSTransportTypeKey)); if(kCFCompareEqualTo == CFStringCompare(type, CFSTR(kIOPSInternalType), 0)) { break; } } float percent = 0; if(source != NULL) { int curCapacity; CFNumberGetValue(CFDictionaryGetValue(source, CFSTR(kIOPSCurrentCapacityKey)), kCFNumberIntType, &curCapacity); int maxCapacity; CFNumberGetValue(CFDictionaryGetValue(source, CFSTR(kIOPSMaxCapacityKey)), kCFNumberIntType, &maxCapacity); percent = curCapacity / (float)maxCapacity*100.f; } CFRelease(sourceInfo); CFRelease(sourceList); return percent; }
static ACPresence chkIsOnline() { CFTypeRef sourceInfo = IOPSCopyPowerSourcesInfo(); CFArrayRef sourceList = IOPSCopyPowerSourcesList(sourceInfo); // Loop through sources, find the first battery int count = CFArrayGetCount(sourceList); CFDictionaryRef source = NULL; for(int i=0; i < count; i++) { source = IOPSGetPowerSourceDescription(sourceInfo, CFArrayGetValueAtIndex(sourceList, i)); // Is this a battery? CFStringRef type = (CFStringRef)CFDictionaryGetValue(source, CFSTR(kIOPSTransportTypeKey)); if(kCFCompareEqualTo == CFStringCompare(type, CFSTR(kIOPSInternalType), 0)) { break; } } ACPresence isOn = AC_ERROR; if(source != NULL) { CFStringRef state = CFDictionaryGetValue(source, CFSTR(kIOPSPowerSourceStateKey)); if(kCFCompareEqualTo == CFStringCompare(state, CFSTR(kIOPSACPowerValue), 0)) { isOn = AC_PRESENT; } else { isOn = AC_ABSENT; } } CFRelease(sourceInfo); CFRelease(sourceList); return isOn; }
static void _itIsLaterNow(CFRunLoopTimerRef tmr, void *info) { CFTypeRef snap = IOPSCopyPowerSourcesInfo(); PSLowPowerPSChange(snap); CFRelease(snap); return; }
static void get_via_io_power_sources(double *ret_charge, /* {{{ */ double *ret_current, double *ret_voltage) { CFTypeRef ps_raw; CFArrayRef ps_array; int ps_array_len; CFDictionaryRef ps_dict; CFTypeRef ps_obj; double temp_double; ps_raw = IOPSCopyPowerSourcesInfo(); ps_array = IOPSCopyPowerSourcesList(ps_raw); ps_array_len = CFArrayGetCount(ps_array); DEBUG("ps_array_len == %i", ps_array_len); for (int i = 0; i < ps_array_len; i++) { ps_obj = CFArrayGetValueAtIndex(ps_array, i); ps_dict = IOPSGetPowerSourceDescription(ps_raw, ps_obj); if (ps_dict == NULL) { DEBUG("IOPSGetPowerSourceDescription failed."); continue; } if (CFGetTypeID(ps_dict) != CFDictionaryGetTypeID()) { DEBUG("IOPSGetPowerSourceDescription did not return a CFDictionaryRef"); continue; } /* FIXME: Check if this is really an internal battery */ if (isnan(*ret_charge)) { /* This is the charge in percent. */ temp_double = dict_get_double(ps_dict, kIOPSCurrentCapacityKey); if (!isnan((temp_double)) && (temp_double >= 0.0) && (temp_double <= 100.0)) *ret_charge = temp_double; } if (isnan(*ret_current)) { temp_double = dict_get_double(ps_dict, kIOPSCurrentKey); if (!isnan(temp_double)) *ret_current = temp_double / 1000.0; } if (isnan(*ret_voltage)) { temp_double = dict_get_double(ps_dict, kIOPSVoltageKey); if (!isnan(temp_double)) *ret_voltage = temp_double / 1000.0; } } CFRelease(ps_array); CFRelease(ps_raw); } /* }}} void get_via_io_power_sources */
void CCocoaPowerSyscall::OSPowerSourceCallBack(void *refcon) { #if !defined(TARGET_DARWIN_IOS) // Called whenever any power source is added, removed, or changes. // When on battery, we get called periodically as battery level changes. CCocoaAutoPool autopool; CCocoaPowerSyscall *ctx = (CCocoaPowerSyscall*)refcon; CFTypeRef power_sources_info = IOPSCopyPowerSourcesInfo(); CFArrayRef power_sources_list = IOPSCopyPowerSourcesList(power_sources_info); for (int i = 0; i < CFArrayGetCount(power_sources_list); i++) { CFTypeRef power_source; CFDictionaryRef description; power_source = CFArrayGetValueAtIndex(power_sources_list, i); description = IOPSGetPowerSourceDescription(power_sources_info, power_source); // skip power sources that are not present (i.e. an absent second battery in a 2-battery machine) if ((CFBooleanRef)CFDictionaryGetValue(description, CFSTR(kIOPSIsPresentKey)) == kCFBooleanFalse) continue; if (stringsAreEqual((CFStringRef)CFDictionaryGetValue(description, CFSTR (kIOPSTransportTypeKey)), CFSTR (kIOPSInternalType))) { CFStringRef currentState = (CFStringRef)CFDictionaryGetValue(description, CFSTR (kIOPSPowerSourceStateKey)); if (stringsAreEqual (currentState, CFSTR (kIOPSACPowerValue))) { ctx->m_OnBattery = false; ctx->m_BatteryPercent = 100; ctx->m_SentBatteryMessage = false; } else if (stringsAreEqual (currentState, CFSTR (kIOPSBatteryPowerValue))) { CFNumberRef cf_number_ref; int32_t curCapacity, maxCapacity; cf_number_ref = (CFNumberRef)CFDictionaryGetValue(description, CFSTR(kIOPSCurrentCapacityKey)); CFNumberGetValue(cf_number_ref, kCFNumberSInt32Type, &curCapacity); cf_number_ref = (CFNumberRef)CFDictionaryGetValue(description, CFSTR(kIOPSMaxCapacityKey)); CFNumberGetValue(cf_number_ref, kCFNumberSInt32Type, &maxCapacity); ctx->m_OnBattery = true; ctx->m_BatteryPercent = (int)((double)curCapacity/(double)maxCapacity * 100); } } } CFRelease(power_sources_list); CFRelease(power_sources_info); #endif }
SDL_bool SDL_GetPowerInfo_MacOSX(SDL_PowerState * state, int *seconds, int *percent) { CFTypeRef blob = IOPSCopyPowerSourcesInfo(); *seconds = -1; *percent = -1; *state = SDL_POWERSTATE_UNKNOWN; if (blob != NULL) { CFArrayRef list = IOPSCopyPowerSourcesList(blob); if (list != NULL) { /* don't CFRelease() the list items, or dictionaries! */ SDL_bool have_ac = SDL_FALSE; SDL_bool have_battery = SDL_FALSE; SDL_bool charging = SDL_FALSE; const CFIndex total = CFArrayGetCount(list); CFIndex i; for (i = 0; i < total; i++) { CFTypeRef ps = (CFTypeRef) CFArrayGetValueAtIndex(list, i); CFDictionaryRef dict = IOPSGetPowerSourceDescription(blob, ps); if (dict != NULL) { checkps(dict, &have_ac, &have_battery, &charging, seconds, percent); } } if (!have_battery) { *state = SDL_POWERSTATE_NO_BATTERY; } else if (charging) { *state = SDL_POWERSTATE_CHARGING; } else if (have_ac) { *state = SDL_POWERSTATE_CHARGED; } else { *state = SDL_POWERSTATE_ON_BATTERY; } CFRelease(list); } CFRelease(blob); } return SDL_TRUE; /* always the definitive answer on Mac OS X. */ }
// CODE CHUNK IMPORTED FROM SDL 2.0 bool power_osx::GetPowerInfo_MacOSX() { CFTypeRef blob = IOPSCopyPowerSourcesInfo(); nsecs_left = -1; percent_left = -1; power_state = OS::POWERSTATE_UNKNOWN; if (blob != NULL) { CFArrayRef list = IOPSCopyPowerSourcesList(blob); if (list != NULL) { /* don't CFRelease() the list items, or dictionaries! */ bool have_ac = false; bool have_battery = false; bool charging = false; const CFIndex total = CFArrayGetCount(list); CFIndex i; for (i = 0; i < total; i++) { CFTypeRef ps = (CFTypeRef)CFArrayGetValueAtIndex(list, i); CFDictionaryRef dict = IOPSGetPowerSourceDescription(blob, ps); if (dict != NULL) { checkps(dict, &have_ac, &have_battery, &charging); } } if (!have_battery) { power_state = OS::POWERSTATE_NO_BATTERY; } else if (charging) { power_state = OS::POWERSTATE_CHARGING; } else if (have_ac) { power_state = OS::POWERSTATE_CHARGED; } else { power_state = OS::POWERSTATE_ON_BATTERY; } CFRelease(list); } CFRelease(blob); } return true; /* always the definitive answer on Mac OS X. */ }
bool CScreensaver::Host_is_running_on_batteries() { CFDictionaryRef pSource = NULL; CFStringRef psState; int i; bool retval = false; CFTypeRef blob = IOPSCopyPowerSourcesInfo(); CFArrayRef list = IOPSCopyPowerSourcesList(blob); for (i=0; i<CFArrayGetCount(list); i++) { pSource = IOPSGetPowerSourceDescription(blob, CFArrayGetValueAtIndex(list, i)); if(!pSource) break; psState = (CFStringRef)CFDictionaryGetValue(pSource, CFSTR(kIOPSPowerSourceStateKey)); if(!CFStringCompare(psState,CFSTR(kIOPSBatteryPowerValue),0)) retval = true; } CFRelease(blob); CFRelease(list); return retval; }
/* Main program */ int main (int argc, const char * argv[]) { enum suspend_type {soft, dump, hard}; int vmmib[2] = {CTL_VM, VM_SWAPUSAGE}; int osmib[2] = {CTL_KERN, KERN_OSRELEASE}; int original_mode; int target_mode; int default_mode; int original_profile; int target_profile = -1; void *refCon; struct xsw_usage swap; size_t swlen = sizeof(swap); size_t oslen; char *kernel_version; int major_version = 0; int minor_version = 0; struct stat sleepimage; /* By default, */ int do_sleep = 1; /* send the sleep call, */ int repair = 0; /* do not check the validity of the original hibernation mode, */ int check_hibernation = 1; /* check if the hibernation file is present, */ int check_os = 1; /* check if the operating system is supported, */ enum suspend_type target_suspend = soft; /* send computer to software suspend mode, */ int restore = 1; /* restore the original mode, */ if (argc >= 2) { if (!strcmp(argv[1], "-v")) { /* Display version number if invoked with -v */ printf("deepsleep build %s\n", VERSION); return 0; } else if (!strcmp(argv[1], "-h")) { printf("deepsleep usage: deepsleep [-bdhrvsu] [hard|dump|soft]\n"); printf(" -b : bypass the hibernation file check\n"); printf(" -d : debug mode - be verbose\n"); printf(" -h : display this help screen\n"); printf(" -m : mute - be silent\n"); printf(" -o : do not restore the original hibernation mode\n"); printf(" -r : repair the default hibernation mode if needed\n"); printf(" -s : simulation - do not send the computer to sleep\n"); printf(" -v : display version number\n"); printf(" -u : perform operations even on unsupported OS revisions\n"); printf(" hard : send computer to hardware suspend mode\n"); printf(" dump : send computer to safe hardware suspend mode\n"); printf(" soft : send computer to software suspend mode (by default)\n"); return 0; } else { if (argc >= 3) { if (strstr(argv[1], "b")) /* Do not check the existence of the hibernation file if invoked with -b */ check_hibernation = 0; if (strstr(argv[1], "d")) /* Print debug information if invoked with -d */ debug = 1; if (strstr(argv[1], "o")) /* Do not restore the original hibernation mode if invoked with -o */ restore = 0; if (strstr(argv[1], "r")) /* Check for the validity of the original hibernation mode if invoked with -r*/ repair = 1; if (strstr(argv[1], "s")) /* Do not send the sleep call if invoked with -s */ do_sleep = 0; if (strstr(argv[1], "u")) /* Do not care about OS revision if invoked with -u */ check_os = 0; if (strstr(argv[1], "m")) mute = 1; } if (strstr(argv[argc-1], "hard")) /* Send computer to hardware suspend mode instead of software suspend mode if the hard argument is present */ target_suspend = hard; else if (strstr(argv[argc-1], "dump")) /* Send computer to safe hardware suspend mode instead of software suspend mode if the safe argument is present */ target_suspend = dump; } } if (sysctl(osmib, 2, NULL, &oslen, NULL, 0) == -1) { /* Get the operating system revision length */ printf("Failed to get the operating system revision\n"); /* On failure: quit */ return 1; } else { kernel_version = malloc(oslen * sizeof(char)); sysctl(osmib, 2, kernel_version, &oslen, NULL, 0); /* Get the operating system revision length */ sscanf(kernel_version, "%d.%d", &major_version, &minor_version); free(kernel_version); } if (debug) { printf("OS revision: %d.%d", major_version, minor_version); if (!check_os) printf(" (ignored)"); printf("\n"); } if (check_os && (major_version != 8 || minor_version < 3) && (major_version <= 8)) { /* If needed, check if major version is 8 (Mac OS X 10.4) and minor version is greater or equal than 3. Mac OS X 10.5 is also supported.*/ printf("This operating system is not supported\n"); /* On failure: quit */ return 1; } if (check_hibernation && stat("/private/var/vm/sleepimage", &sleepimage)) { /* If needed, check if the hibernation file (/private/var/vm/sleepimage) exists */ printf("Hibernation file is missing\n"); /* On failure: quit */ return 1; } if (sysctl(vmmib, 2, &swap, &swlen, NULL, 0) == -1) { /* Get the current virtual memory parameters */ printf("Failed to get the virtual memory information\n"); /* On failure: quit */ return 1; } else { default_mode = 3; if (target_suspend == dump) { target_mode = default_mode; /* we will use the regular mode 3 for safe hardware suspsend */ } else /*if (target_suspend == soft)*/ { target_mode = 25; /* or the regular mode 25 for software suspsend */ } if (target_suspend == hard) /* If we only want to perform basic hardware suspend */ target_mode = 0; /* we will sleep with hibernate mode 0 */ if (debug) printf("target mode: %d\n", target_mode); } ps_info = IOPSCopyPowerSourcesInfo(); /* Get the power source information */ if (ps_info) { current_ps = IOPSGetProvidingPowerSourceType(ps_info); /* On success, store the active power source */ } else { printf("Failed to get the power source information\n"); /* On failure: quit */ return 1; } if (debug) printf("target power source: %s\n", CFStringGetCStringPtr(current_ps, kCFStringEncodingMacRoman)); active_prof = IOPMCopyActivePowerProfiles(); /* Get the power profiles */ if (!active_prof) { printf("Failed to get the active profile\n"); CFCleanup(); return 1; } if (CFDictionaryContainsKey(active_prof, current_ps)) { /* Get the active profile corresponding to the current power source */ profile_ref = (CFNumberRef) CFDictionaryGetValue(active_prof, current_ps); profile_type = CFNumberGetType(profile_ref); CFNumberGetValue(profile_ref, profile_type, &original_profile); /* On succes, store its value */ if (debug) printf("original profile: %d\n", original_profile); } else { printf("Failed to get the power management settings\n"); /* On failure: quit */ CFCleanup(); return 1; } ds = SCDynamicStoreCreate(NULL, CFSTR("deepsleep"), NULL, NULL); /* Create a new dynamic store */ live_settings = SCDynamicStoreCopyValue(ds, CFSTR(kIOPMDynamicStoreSettingsKey)); /* Read current settings */ if(!isA_CFDictionary(live_settings)) { /* We did not get the settings: quit */ printf("Failed to get the power management settings\n"); CFCleanup(); return 1; } if (CFDictionaryContainsKey(live_settings, CFSTR("Hibernate Mode"))) { /* Check if the hibernate mode key exists */ hm_ref = (CFNumberRef) CFDictionaryGetValue(live_settings, CFSTR("Hibernate Mode")); /* On success, get its value */ hm_type = CFNumberGetType(hm_ref); CFNumberGetValue(hm_ref, hm_type, &original_mode); if (debug) printf("original mode: %d\n", original_mode); } else { /* On failure, cleanup and quit */ printf("Failed to get the hibernation mode\n"); CFCleanup(); return 1; } if (repair && original_mode == target_mode) { /* If the original mode is the same as the target mode */ original_mode = default_mode; /* A crash has probably happened during hibernation: we will set back the hibernation mode to its default value after wakeup */ if (debug) printf("repair mode to: %d\n", default_mode); } root_power_port = IORegisterForSystemPower(refCon, ¬ifyPortRef, PowerCallBack, ¬ifierObject); /* Register to the Root Power Domain IOService: notifications will be handled by the PowerCallBack functions */ if (!root_power_port) { /* Registering failed: quit */ printf("Failed to register to the Root Power Domain IOService\n"); CFCleanup(); return 1; } CFRunLoopAddSource(CFRunLoopGetCurrent(), IONotificationPortGetRunLoopSource(notifyPortRef), kCFRunLoopCommonModes); /* Add the notification port to the run loop */ if (SetActiveProfile(target_profile, current_ps, active_prof)) { /* Set the active power profile to custom (-1) */ printf("Failed to set the active profile\n"); PortsCleanup(); CFCleanup(); return 1; } if (SetHibernateMode(target_mode, current_ps)) { /* Set the hibernate mode to target mode */ printf("Failed to set the hibernation mode\n"); SetActiveProfile(original_profile, current_ps, active_prof); PortsCleanup(); CFCleanup(); return 1; } if (do_sleep) { /* If we are not in simulation mode */ sleep(3); /* Wait for 3s to allow settings to settle down */ if (IOPMSleepSystem(root_power_port) == kIOReturnSuccess) /* Request the system to sleep */ CFRunLoopRun(); /* On success, start the run loop */ else perror("Failed to send the sleep request\n"); /* On failure, do not start it */ } /* The run loop has stopped: system has woken up */ if (restore) { /* If we are asked to restore the original hibernate mode */ if (SetHibernateMode(original_mode, current_ps)) { /* Restore the original hibernate mode */ printf("Failed to set the hibernation mode\n"); SetActiveProfile(original_profile, current_ps, active_prof); PortsCleanup(); CFCleanup(); return 1; } if (SetActiveProfile(original_profile, current_ps, active_prof)) { /* Restore the original power profile */ printf("Failed to set the active profile\n"); PortsCleanup(); CFCleanup(); return 1; } } PortsCleanup(); /* Cleanup */ CFCleanup(); return 0; }
static void darwin_check(void) { const void *values; int device_num, device_count; int currentval = 0, maxval = 0; char buf[4096]; CFTypeRef blob; CFArrayRef sources; CFDictionaryRef device_dict; time_left = -1; battery_full = -1; have_battery = 0; have_power = 0; /* Retrieve the power source data and the array of sources. */ blob = IOPSCopyPowerSourcesInfo(); sources = IOPSCopyPowerSourcesList(blob); device_count = CFArrayGetCount(sources); for (device_num = 0; device_num < device_count; device_num++) { CFTypeRef ps; /* Retrieve a dictionary of values for this device and the count of keys in the dictionary. */ ps = CFArrayGetValueAtIndex(sources, device_num); device_dict = IOPSGetPowerSourceDescription(blob, ps); /* Retrieve the charging key and save the present charging value if one exists. */ if (CFDictionaryGetValueIfPresent(device_dict, CFSTR(kIOPSIsChargingKey), &values)) { have_battery = 1; if (CFBooleanGetValue(values) > 0) have_power = 1; break; } } if (!have_battery) { CFRelease(sources); CFRelease(blob); have_power = 1; return; } /* Retrieve the current capacity key. */ values = CFDictionaryGetValue(device_dict, CFSTR(kIOPSCurrentCapacityKey)); CFNumberGetValue(values, kCFNumberSInt32Type, ¤tval); /* Retrieve the max capacity key. */ values = CFDictionaryGetValue(device_dict, CFSTR(kIOPSMaxCapacityKey)); CFNumberGetValue(values, kCFNumberSInt32Type, &maxval); /* Calculate the percentage charged. */ battery_full = (currentval * 100) / maxval; /* Retrieve the remaining battery power or time until charged in minutes. */ if (!have_power) { values = CFDictionaryGetValue(device_dict, CFSTR(kIOPSTimeToEmptyKey)); CFNumberGetValue(values, kCFNumberSInt32Type, ¤tval); time_left = currentval * 60; } else { values = CFDictionaryGetValue(device_dict, CFSTR(kIOPSTimeToFullChargeKey)); CFNumberGetValue(values, kCFNumberSInt32Type, ¤tval); time_left = currentval * 60; } CFRelease(sources); CFRelease(blob); }
PowerInfo GetPowerState() { PowerInfo info; info.state = PowerInfo::STATE_UNKNOWN; info.seconds = 0; info.percent = 0.0f; #if defined(TARGET_OSX) CFTypeRef blob = IOPSCopyPowerSourcesInfo(); if (blob != NULL) { CFArrayRef list = IOPSCopyPowerSourcesList(blob); if (list != NULL) { /* don't CFRelease() the list items, or dictionaries! */ bool have_ac = false; bool have_battery = false; bool charging = false; const CFIndex total = CFArrayGetCount(list); CFIndex i; for (i = 0; i < total; i++) { CFTypeRef ps = (CFTypeRef) CFArrayGetValueAtIndex(list, i); CFDictionaryRef dict = IOPSGetPowerSourceDescription(blob, ps); if (dict != NULL) { checkps(dict, &have_ac, &have_battery, &charging, &info.seconds, &info.percent); } } if (!have_battery) { info.state = PowerInfo::STATE_NO_BATTERY; } else if (charging) { info.state = PowerInfo::STATE_CHARGING; } else if (have_ac) { info.state = PowerInfo::STATE_CHARGED; } else { info.state = PowerInfo::STATE_ON_BATTERY; } CFRelease(list); } CFRelease(blob); } #elif defined(TARGET_LINUX) #else #endif return info; }
int OnBattery (void) { #if defined (__APPLE__) /* The following copyright applies to the battery detection code below. I did modify */ /* substantially as it did far more than I needed. */ /* Copyright (c) 2003 Thomas Runge ([email protected]) * Mach and Darwin specific code is Copyright (c) 2006 Eric Pooch ([email protected]) * * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the author nor the names of its contributors * may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ CFTypeRef blob = IOPSCopyPowerSourcesInfo(); CFArrayRef sources = IOPSCopyPowerSourcesList(blob); int i, acstat; CFDictionaryRef pSource = NULL; const void *psValue; acstat = TRUE; for(i = 0; i < CFArrayGetCount(sources); i++) { pSource = IOPSGetPowerSourceDescription(blob, CFArrayGetValueAtIndex(sources, i)); if(!pSource) break; psValue = (CFStringRef)CFDictionaryGetValue(pSource, CFSTR(kIOPSNameKey)); if (CFDictionaryGetValueIfPresent(pSource, CFSTR(kIOPSIsPresentKey), &psValue) && (CFBooleanGetValue(psValue) > 0)) { psValue = (CFStringRef)CFDictionaryGetValue(pSource, CFSTR(kIOPSPowerSourceStateKey)); if (CFStringCompare(psValue,CFSTR(kIOPSBatteryPowerValue),0)==kCFCompareEqualTo) { /* We are running on a battery power source. */ acstat = FALSE; } } } CFRelease(blob); CFRelease(sources); return(!acstat); #elif defined (__linux__) FILE *fd; char buf[180]; int ac_state; ac_state = -1; fd = fopen ("/proc/acpi/battery/BAT0/state", "r"); if (fd != NULL) { while (fgets (buf, sizeof (buf), fd) != NULL) { char *p; p = strstr (buf, "charging state:"); if (p == NULL) continue; if (strstr (p+14, "discharging") != NULL) ac_state = 0; else if (strstr (p+14, "charging") != NULL) ac_state = 1; else if (strstr (p+14, "charged") != NULL) ac_state = 1; } fclose (fd); } return (ac_state == 0); #else return (FALSE); /* Assume we're on AC power */ #endif }
int machine_get_battstat(int *acstat, int *battflag, int *percent) { CFTypeRef blob = IOPSCopyPowerSourcesInfo(); CFArrayRef sources = IOPSCopyPowerSourcesList(blob); int i; CFDictionaryRef pSource = NULL; const void *psValue; *acstat = LCDP_AC_ON; *battflag = LCDP_BATT_ABSENT; *percent = 100; if (CFArrayGetCount(sources) == 0) return (FALSE); for (i = 0; i < CFArrayGetCount(sources); i++) { pSource = IOPSGetPowerSourceDescription(blob, CFArrayGetValueAtIndex(sources, i)); if (!pSource) break; psValue = (CFStringRef) CFDictionaryGetValue(pSource, CFSTR(kIOPSNameKey)); if (CFDictionaryGetValueIfPresent(pSource, CFSTR(kIOPSIsPresentKey), &psValue) && (CFBooleanGetValue(psValue) > 0)) { psValue = (CFStringRef) CFDictionaryGetValue(pSource, CFSTR(kIOPSPowerSourceStateKey)); if (CFStringCompare(psValue, CFSTR(kIOPSBatteryPowerValue), 0) == kCFCompareEqualTo) { /* We are running on a battery power source. */ *battflag = LCDP_BATT_UNKNOWN; *acstat = LCDP_AC_OFF; } else if (CFDictionaryGetValueIfPresent(pSource, CFSTR(kIOPSIsChargingKey), &psValue)) { /* * We are running on an AC power source, but * we also have a battery power source * present. */ if (CFBooleanGetValue(psValue) > 0) *battflag = LCDP_BATT_CHARGING; else *battflag = LCDP_BATT_UNKNOWN; } if (*battflag != LCDP_BATT_ABSENT) { int curCapacity = 0; int maxCapacity = 0; psValue = CFDictionaryGetValue(pSource, CFSTR(kIOPSCurrentCapacityKey)); CFNumberGetValue(psValue, kCFNumberSInt32Type, &curCapacity); psValue = CFDictionaryGetValue(pSource, CFSTR(kIOPSMaxCapacityKey)); CFNumberGetValue(psValue, kCFNumberSInt32Type, &maxCapacity); *percent = (int)((double)curCapacity / (double)maxCapacity * 100); /* * There is a way to check this through the * IOKit, but I am not sure what gets * returned for kIOPSLowWarnLevelKey and * kIOPSDeadWarnLevelKey, and this is easier. */ if (*battflag == LCDP_BATT_UNKNOWN) { if (*percent > 50) *battflag = LCDP_BATT_HIGH; else if (*percent > 2) *battflag = LCDP_BATT_LOW; else *battflag = LCDP_BATT_CRITICAL; } /* printf ("powerSource %d of %d: percent: %d/%d %d\n", i, CFArrayGetCount(sources), curCapacity, maxCapacity, *percent);*/ } } } CFRelease(blob); CFRelease(sources); return (TRUE); }
void upsdrv_initups(void) { CFArrayRef power_source_key_list; CFIndex num_keys, index; CFDictionaryRef power_dictionary; CFTypeRef power_blob; CFStringRef potential_key, potential_model; char *device_name = device_path, *model_name; /* regex(3) */ char potential_device_name[80], potential_model_name[80]; regex_t name_regex, model_regex; int ret; upsdebugx(3, "upsdrv_initups(): Power Sources blob:"); /* upsfd = ser_open(device_path); */ /* ser_set_speed(upsfd, device_path, B1200); */ power_blob = IOPSCopyPowerSourcesInfo(); if(!power_blob) { fatalx(EXIT_FAILURE, "Couldn't retrieve Power Sources blob"); } if(nut_debug_level >= 3) CFShow(power_blob); if(!strcmp(device_name, "auto")) { device_name = "/UPS"; } upsdebugx(2, "Matching power supply key names against regex '%s'", device_name); ret = regcomp(&name_regex, device_name, REG_EXTENDED|REG_NOSUB|REG_ICASE); if(ret) { fatalx(EXIT_FAILURE, "Failed to compile regex from 'port' parameter: '%s'.", device_name); } if((model_name = getval("model"))) { upsdebugx(2, "Matching power supply model names against regex '%s'", model_name); ret = regcomp(&model_regex, model_name, REG_EXTENDED|REG_NOSUB|REG_ICASE); if(ret) { fatalx(EXIT_FAILURE, "Failed to compile regex from 'model' parameter: '%s'.", model_name); } } power_source_key_list = IOPSCopyPowerSourcesList(power_blob); num_keys = CFArrayGetCount(power_source_key_list); upsdebugx(1, "Number of power supplies found: %d", (int)num_keys); if(nut_debug_level >= 3) CFShow(power_source_key_list); if(num_keys < 1) { /* bail */ fatalx(EXIT_FAILURE, "Couldn't find any UPS or battery"); } for(index=0; index < num_keys; index++) { potential_key = CFArrayGetValueAtIndex(power_source_key_list, index); CFStringGetCString(potential_key, potential_device_name, sizeof(potential_device_name), kCFStringEncodingUTF8); upsdebugx(1, " Power supply: %s", potential_device_name); ret = regexec(&name_regex, potential_device_name, 0,0,0); power_dictionary = copy_power_dictionary(potential_key); upsdebugx(2, "Getting 'Name' key (UPS model)"); potential_model = CFDictionaryGetValue(power_dictionary, CFSTR(kIOPSNameKey)); CFStringGetCString(potential_model, potential_model_name, sizeof(potential_model_name), kCFStringEncodingUTF8); upsdebugx(1, " model name: %s", potential_model_name); CFRelease(power_dictionary); /* Does key match? Check model: */ if (!ret) { if(model_name) { ret = regexec(&model_regex, potential_model_name, 0,0,0); if(!ret) { upsdebugx(2, "Matched model name"); break; } } else { upsdebugx(2, "Matched key name"); break; } } } regfree(&name_regex); if(model_name) { regfree(&model_regex); } if(ret) { fatalx(EXIT_FAILURE, "Couldn't find UPS or battery matching both 'port' (%s) and 'model' (%s)", device_name, model_name); } g_power_key = potential_key; CFRetain(g_power_key); upsdebugx(2, "g_power_key = "); if(nut_debug_level >= 2) CFShow(g_power_key); upsdebugx(2, "end g_power_key."); power_dictionary = copy_power_dictionary(g_power_key); assert(power_dictionary); if(nut_debug_level >= 3) CFShow(power_dictionary); /* the upsh handlers can't be done here, as they get initialized * shortly after upsdrv_initups returns to main. */ /* don't try to detect the UPS here */ /* do stuff */ CFRelease(power_dictionary); }
void HostPowerServiceDarwin::checkBatteryCriticalLevel(bool *pfCriticalChanged) { CFTypeRef pBlob = IOPSCopyPowerSourcesInfo(); CFArrayRef pSources = IOPSCopyPowerSourcesList(pBlob); CFDictionaryRef pSource = NULL; const void *psValue; bool result; int powerSource = POWER_SOURCE_OUTLET; bool critical = false; if (CFArrayGetCount(pSources) > 0) { for (int i = 0; i < CFArrayGetCount(pSources); ++i) { pSource = IOPSGetPowerSourceDescription(pBlob, CFArrayGetValueAtIndex(pSources, i)); /* If the source is empty skip over to the next one. */ if (!pSource) continue; /* Skip all power sources which are currently not present like a * second battery. */ if (CFDictionaryGetValue(pSource, CFSTR(kIOPSIsPresentKey)) == kCFBooleanFalse) continue; /* Only internal power types are of interest. */ result = CFDictionaryGetValueIfPresent(pSource, CFSTR(kIOPSTransportTypeKey), &psValue); if (result && CFStringCompare((CFStringRef)psValue, CFSTR(kIOPSInternalType), 0) == kCFCompareEqualTo) { /* First check which power source we are connect on. */ result = CFDictionaryGetValueIfPresent(pSource, CFSTR(kIOPSPowerSourceStateKey), &psValue); if (result && CFStringCompare((CFStringRef)psValue, CFSTR(kIOPSACPowerValue), 0) == kCFCompareEqualTo) powerSource = POWER_SOURCE_OUTLET; else if (result && CFStringCompare((CFStringRef)psValue, CFSTR(kIOPSBatteryPowerValue), 0) == kCFCompareEqualTo) powerSource = POWER_SOURCE_BATTERY; int curCapacity = 0; int maxCapacity = 1; float remCapacity = 0.0f; /* Fetch the current capacity value of the power source */ result = CFDictionaryGetValueIfPresent(pSource, CFSTR(kIOPSCurrentCapacityKey), &psValue); if (result) CFNumberGetValue((CFNumberRef)psValue, kCFNumberSInt32Type, &curCapacity); /* Fetch the maximum capacity value of the power source */ result = CFDictionaryGetValueIfPresent(pSource, CFSTR(kIOPSMaxCapacityKey), &psValue); if (result) CFNumberGetValue((CFNumberRef)psValue, kCFNumberSInt32Type, &maxCapacity); /* Calculate the remaining capacity in percent */ remCapacity = ((float)curCapacity/(float)maxCapacity * 100.0); /* Check for critical. 5 percent is default. */ int criticalValue = 5; result = CFDictionaryGetValueIfPresent(pSource, CFSTR(kIOPSDeadWarnLevelKey), &psValue); if (result) CFNumberGetValue((CFNumberRef)psValue, kCFNumberSInt32Type, &criticalValue); critical = (remCapacity < criticalValue); /* We have to take action only if we are on battery, the * previous state wasn't critical, the state has changed & the * user requested that info. */ if (powerSource == POWER_SOURCE_BATTERY && mCritical == false && mCritical != critical && pfCriticalChanged) *pfCriticalChanged = true; Log(("checkBatteryCriticalLevel: Remains: %d.%d%% Critical: %d Critical State Changed: %d\n", (int)remCapacity, (int)(remCapacity * 10) % 10, critical, pfCriticalChanged?*pfCriticalChanged:-1)); } } } /* Save the new state */ mCritical = critical; CFRelease(pBlob); CFRelease(pSources); }
static void powerSourceChanged(void *context) { #pragma unused(context) CFTypeRef powerBlob = IOPSCopyPowerSourcesInfo(); CFArrayRef powerSourcesList = IOPSCopyPowerSourcesList(powerBlob); CFIndex count = CFArrayGetCount(powerSourcesList); for (CFIndex i = 0; i < count; ++i) { CFTypeRef powerSource; CFDictionaryRef description; HGPowerSource hgPowerSource; CFBooleanRef charging = kCFBooleanFalse; CFIndex batteryTime = -1; CFIndex percentageCapacity = -1; powerSource = CFArrayGetValueAtIndex(powerSourcesList, i); description = IOPSGetPowerSourceDescription(powerBlob, powerSource); //Don't display anything for power sources that aren't present (i.e. an absent second battery in a 2-battery machine) if (CFDictionaryGetValue(description, CFSTR(kIOPSIsPresentKey)) == kCFBooleanFalse) continue; //We only know how to handle internal (battery, a/c power) transport types. The other values indicate UPS usage. if (stringsAreEqual(CFDictionaryGetValue(description, CFSTR(kIOPSTransportTypeKey)), CFSTR(kIOPSInternalType))) { CFStringRef currentState = CFDictionaryGetValue(description, CFSTR(kIOPSPowerSourceStateKey)); if (stringsAreEqual(currentState, CFSTR(kIOPSACPowerValue))) hgPowerSource = HGACPower; else if (stringsAreEqual(currentState, CFSTR(kIOPSBatteryPowerValue))) hgPowerSource = HGBatteryPower; else hgPowerSource = HGUnknownPower; //Battery power if (CFDictionaryGetValue(description, CFSTR(kIOPSIsChargingKey)) == kCFBooleanTrue) { //Charging charging = kCFBooleanTrue; CFNumberRef timeToChargeNum = CFDictionaryGetValue(description, CFSTR(kIOPSTimeToFullChargeKey)); CFIndex timeToCharge; if (CFNumberGetValue(timeToChargeNum, kCFNumberCFIndexType, &timeToCharge)) batteryTime = timeToCharge; } else { //Not charging charging = kCFBooleanFalse; CFNumberRef timeToEmptyNum = CFDictionaryGetValue(description, CFSTR(kIOPSTimeToEmptyKey)); CFIndex timeToEmpty; if (CFNumberGetValue(timeToEmptyNum, kCFNumberCFIndexType, &timeToEmpty)) batteryTime = timeToEmpty; } /* Capacity */ CFNumberRef currentCapacityNum = CFDictionaryGetValue(description, CFSTR(kIOPSCurrentCapacityKey)); CFNumberRef maxCapacityNum = CFDictionaryGetValue(description, CFSTR(kIOPSMaxCapacityKey)); CFIndex currentCapacity, maxCapacity; if (CFNumberGetValue(currentCapacityNum, kCFNumberCFIndexType, ¤tCapacity) && CFNumberGetValue(maxCapacityNum, kCFNumberCFIndexType, &maxCapacity)) percentageCapacity = roundf((currentCapacity / (float)maxCapacity) * 100.0f); } else { //UPS power hgPowerSource = HGUPSPower; } //Avoid sending notifications on the same power source multiple times, unless the charging state or presence/absence of a time estimate has changed. if (lastPowerSource != hgPowerSource || lastChargingState != charging || (lastBatteryTime == -1) != (batteryTime == -1)) { lastPowerSource = hgPowerSource; lastChargingState = charging; lastBatteryTime = batteryTime; AppController_powerSwitched(hgPowerSource, charging, batteryTime, percentageCapacity); } } CFRelease(powerSourcesList); CFRelease(powerBlob); }