/* * Copyright (c) 2010 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this * file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. * * @APPLE_LICENSE_HEADER_END@ */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if TARGET_OS_EMBEDDED #define PLATFORM_HAS_DISPLAYSERVICES 0 #else #define PLATFORM_HAS_DISPLAYSERVICES 1 // ResentAmbientLightAll is defined in // and implemented by DisplayServices.framework IOReturn DisplayServicesResetAmbientLightAll( void ); #endif #include "../pmconfigd/PrivateLib.h" // dynamically mig generated #include "powermanagement.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* * This is the command line interface to Energy Saver Preferences in * /Library/Preferences/SystemConfiguration/com.apple.PowerManagement.plist * * pmset does many things, but here are a few of them: * Usage: pmset [-b | -c | -a] [[] ...] -c adjust settings used while connected to a charger -b adjust settings used when running off a battery -a (default) adjust settings for both is one of: dim, sleep, spindown, slower, womp* (* flag = 1/0) eg. pmset womp 1 -c dim 5 sleep 15 -b dim 3 spindown 5 sleep 8 */ // Settings options #define ARG_DIM "dim" #define ARG_DISPLAYSLEEP "displaysleep" #define ARG_SLEEP "sleep" #define ARG_SPINDOWN "spindown" #define ARG_DISKSLEEP "disksleep" #define ARG_WOMP "womp" #define ARG_LIDWAKE "lidwake" #define ARG_HIBERNATEMODE "hibernatemode" #define ARG_HIBERNATEFILE "hibernatefile" #define ARG_HIBERNATEFREERATIO "hibernatefreeratio" #define ARG_HIBERNATEFREETIME "hibernatefreetime" #define ARG_AUTOPOWEROFF "autopoweroff" #define ARG_AUTOPOWEROFFDELAY "autopoweroffdelay" #define ARG_RING "ring" #define ARG_AUTORESTART "autorestart" #define ARG_WAKEONACCHANGE "acwake" #define ARG_REDUCEBRIGHT "lessbright" #define ARG_SLEEPUSESDIM "halfdim" #define ARG_MOTIONSENSOR "sms" #define ARG_MOTIONSENSOR2 "ams" #define ARG_TTYKEEPAWAKE "ttyskeepawake" #define ARG_GPU "gpuswitch" #define ARG_NETAVAILABLE "networkoversleep" #define ARG_DEEPSLEEP "standby" #define ARG_DEEPSLEEPDELAY "standbydelay" #define ARG_DARKWAKES "darkwakes" #define ARG_RESTOREDEFAULTS "restoredefaults" // Scheduling options #define ARG_SCHEDULE "schedule" #define ARG_SCHED "sched" #define ARG_REPEAT "repeat" #define ARG_CANCEL "cancel" #define ARG_RELATIVE "relative" //#define ARG_SLEEP "sleep" #define ARG_SHUTDOWN "shutdown" #define ARG_RESTART "restart" #define ARG_WAKE "wake" #define ARG_POWERON "poweron" #define ARG_WAKEORPOWERON "wakeorpoweron" // UPS options #define ARG_HALTLEVEL "haltlevel" #define ARG_HALTAFTER "haltafter" #define ARG_HALTREMAIN "haltremain" // get options #define ARG_CAP "cap" #define ARG_DISK "disk" #define ARG_CUSTOM "custom" #define ARG_LIVE "live" #define ARG_SCHED "sched" #define ARG_UPS "ups" #define ARG_SYS_PROFILES "profiles" #define ARG_ADAPTER_AC "ac" #define ARG_ADAPTER "adapter" #define ARG_BATT "batt" #define ARG_PS "ps" #define ARG_PSLOG "pslog" #define ARG_TRCOLUMNS "trcolumns" #define ARG_BATTRAW "rawbatt" #define ARG_PSRAW "rawlog" #define ARG_THERM "therm" #define ARG_THERMLOG "thermlog" #define ARG_ASSERTIONS "assertions" #define ARG_ASSERTIONSLOG "assertionslog" #define ARG_SYSLOAD "sysload" #define ARG_SYSLOADLOG "sysloadlog" #define ARG_USERACTIVITYLOG "useractivitylog" #define ARG_USERACTIVITY "useractivity" #define ARG_LOG "log" #define ARG_LISTEN "listen" #define ARG_HISTORY "history" #define ARG_HISTORY_DETAILED "historydetailed" #define ARG_HID_NULL "hidnull" #define ARG_BOOKMARK "bookmark" #define ARG_CLEAR_HISTORY "clearpmhistory" #define ARG_SEARCH "searchforuuid" #define ARG_USERCLIENTS "userclients" #define ARG_UUID "uuid" #define ARG_UUID_LOG "uuidlog" #define ARG_EVERYTHING "everything" #define ARG_PRINT_GETTERS "getters" #define ARG_POWERSTATE "powerstate" #define ARG_POWERSTATELOG "powerstatelog" #define ARG_RDSTATS "stats" #define ARG_SYSSTATE "systemstate" #define ARG_SLEEPBLOCKERS "sleepblockers" #define ARG_FBA "fba" // special #define ARG_BOOT "boot" #define ARG_UNBOOT "unboot" #define ARG_POLLBOOT "readboot" #define ARG_POLLALL "readall" #define ARG_POLLUSER "readuser" #define ARG_FORCE "force" #define ARG_TOUCH "touch" #define ARG_NOIDLE "noidle" #define ARG_SLEEPNOW "sleepnow" #define ARG_DISPLAYSLEEPNOW "displaysleepnow" #define ARG_DEBUGTRIG "debugTrig" #define ARG_RESETDISPLAYAMBIENTPARAMS "resetdisplayambientparams" #define ARG_DISABLEASSERTION "disableassertion" #define ARG_ENABLEASSERTION "enableassertion" #define ARG_RDAP "rdap" #define ARG_DEBUGFLAGS "debugflags" #define ARG_BTINTERVAL "btinterval" #define ARG_DWLINTERVAL "dwlinterval" #define ARG_MT2BOOK "mt2book" #define ARG_SETSAAFLAGS "saaflags" #define ARG_NOPOLL "nopoll" // special system #define ARG_DISABLESLEEP "disablesleep" #define ARG_DISABLEFDEKEYSTORE "destroyfvkeyonstandby" #define kProcNameBufLen (2*MAXCOMLEN) // return values for parseArgs #define kParseSuccess 0 // success #define kParseBadArgs -1 // error #define kParseInternalError -2 // error // bitfield for tracking what's been modified in parseArgs() #define kModSettings (1<<0) #define kModProfiles (1<<1) #define kModUPSThresholds (1<<2) #define kModSched (1<<3) #define kModRepeat (1<<4) #define kModSystemSettings (1<<5) // return values for idleSettingsNotConsistent #define kInconsistentDisplaySetting 1 #define kInconsistentDiskSetting 2 #define kConsistentSleepSettings 0 // day-of-week constants for repeating power events #define daily_mask ( kIOPMMonday | kIOPMTuesday | kIOPMWednesday \ | kIOPMThursday | kIOPMFriday | kIOPMSaturday \ | kIOPMSunday) #define weekday_mask ( kIOPMMonday | kIOPMTuesday | kIOPMWednesday \ | kIOPMThursday | kIOPMFriday ) #define weekend_mask ( kIOPMSaturday | kIOPMSunday ) #define kDateAndTimeFormat "MM/dd/yy HH:mm:ss" #define kTimeFormat "HH:mm:ss" #define kMaxLongStringLength 255 static const size_t kMaxArgStringLength = 49; #define kUSecPerSec 1000000.0 #ifndef kPMPowerStatesChID #define kPMPowerStatesChID IOREPORT_MAKEID('P','M','S','t','H','i','s','t') #endif #ifndef kPMCurrStateChID #define kPMCurrStateChID IOREPORT_MAKEID('P','M','C','u','r','S','t','\0' ) #endif /* RootDomain IOReporting channels */ #define kSleepCntChID IOREPORT_MAKEID('S','l','e','e','p','C','n','t') #define kDarkWkCntChID IOREPORT_MAKEID('G','U','I','W','k','C','n','t') #define kUserWkCntChID IOREPORT_MAKEID('D','r','k','W','k','C','n','t') typedef struct { const char *name; const char *displayAs; } PMFeature; /* list of all features */ PMFeature all_features[] = { { kIOPMDisplaySleepKey, ARG_DISPLAYSLEEP }, { kIOPMDiskSleepKey, ARG_DISKSLEEP }, { kIOPMSystemSleepKey, ARG_SLEEP }, { kIOPMWakeOnLANKey, ARG_WOMP }, { kIOPMWakeOnRingKey, ARG_RING }, { kIOPMWakeOnACChangeKey, ARG_WAKEONACCHANGE }, { kIOPMRestartOnPowerLossKey, ARG_AUTORESTART }, { kIOPMWakeOnClamshellKey, ARG_LIDWAKE }, { kIOPMReduceBrightnessKey, ARG_REDUCEBRIGHT }, { kIOPMDisplaySleepUsesDimKey, ARG_SLEEPUSESDIM }, { kIOPMMobileMotionModuleKey, ARG_MOTIONSENSOR }, { kIOPMGPUSwitchKey, ARG_GPU }, { kIOPMDeepSleepEnabledKey, ARG_DEEPSLEEP }, { kIOPMDeepSleepDelayKey, ARG_DEEPSLEEPDELAY }, { kIOPMDarkWakeBackgroundTaskKey, ARG_DARKWAKES }, { kIOPMTTYSPreventSleepKey, ARG_TTYKEEPAWAKE }, { kIOHibernateModeKey, ARG_HIBERNATEMODE }, { kIOHibernateFileKey, ARG_HIBERNATEFILE }, { kIOPMAutoPowerOffEnabledKey, ARG_AUTOPOWEROFF }, { kIOPMAutoPowerOffDelayKey, ARG_AUTOPOWEROFFDELAY } }; #define kNUM_PM_FEATURES (sizeof(all_features)/sizeof(PMFeature)) enum ArgumentType { kApplyToBattery = 1, kApplyToCharger = 2, kApplyToUPS = 4, kShowColumns = 8 }; enum AssertionBitField { kAssertionCPU = 1, kAssertionInflow = 2, kAssertionCharge = 4, kAssertionIdle = 8 }; // ack port for sleep/wake callback static io_connect_t gPMAckPort = MACH_PORT_NULL; enum SleepCallbackBehavior { kLogSleepEvents = (1<<0), kCancelSleepEvents = (1<<1) }; /* pmset commands */ enum PMCommandType { kPMCommandSleepNow = 1, kPMCommandTouch, kPMCommandNoIdle, kPMCommandDisplaySleepNow, kPMCommandDebugTrig }; /* check and set int value multiplier */ enum { kNoMultiplier = 0, kMillisecondsMultiplier = 1000 }; typedef struct { CFStringRef who; CFDateRef when; CFStringRef which; } ScheduledEventReturnType; #define RING_SIZE 100 typedef struct { asl_object_t msgRing[RING_SIZE]; uint32_t readIdx; uint32_t writeIdx; } MsgCache; MsgCache *msgCache = NULL; // function declarations static void usage(void); static IOReturn setRootDomainProperty(CFStringRef key, CFTypeRef val); static io_registry_entry_t copyRootDomainRef(void); static IOReturn _pm_connect(mach_port_t *newConnection); static IOReturn _pm_disconnect(mach_port_t connection); static void show_pm_settings_dict( CFDictionaryRef d, int indent, bool log_overrides, bool prune_unsupported); static void show_system_power_settings(void); static void show_supported_pm_features(void); static void show_custom_pm_settings(void); static void show_live_pm_settings(void); static void show_ups_settings(void); static void show_active_profiles(void); static void show_system_profiles(void); static void show_scheduled_events(void); static void show_active_assertions(uint32_t which); static void show_power_sources(int which); static bool prevent_idle_sleep(void); static void show_assertions(const char *); static void log_assertions(void); static void show_systemload(void); static void log_systemload(void); static const bool kRunOnce = true; static const bool kRunLoop = false; static void log_useractivity_presentActive(bool runOnce); static void log_useractivity_level(bool runOnce); static void show_useractivity_level(uint64_t lev, uint64_t msb); static void show_log(void); static void show_uuid(bool keep_running); static void listen_for_everything(void); static bool is_display_dim_captured(void); static void show_power_adapter(void); static void show_getters(void); static void show_power_state(char **argv); static void show_power_statelog(char **argv); static void show_rdStats(char **argv); static void show_sysstate(char **argv); static void show_sleep_blockers(char **argv); #if !TARGET_OS_EMBEDDED static void print_fba(char **argv); static void show_NULL_HID_events(void); #endif static void show_everything(char **); static void show_power_event_history(void); static void show_power_event_history_detailed(void); static void set_new_power_bookmark(void); static void set_debugFlags(char **argv); static void set_btInterval(char **argv); static void set_dwlInterval(char **argv); static void set_saaFlags(char **argv); static void show_details_for_UUID(char **UUID_string); static void show_root_domain_user_clients(void); static void mt2bookmark(void); static bool isBatteryPollingStopped(void); static void set_nopoll(void); static void print_pretty_date(CFAbsoluteTime t, bool newline); static void print_short_date(CFAbsoluteTime t, bool newline); static void print_date_with_style(const char *, CFDateFormatterStyle dayStyle, CFDateFormatterStyle timeStyle, CFAbsoluteTime t, bool newline); static void sleepWakeCallback( void *refcon, io_service_t y __unused, natural_t messageType, void * messageArgument); static void install_listen_for_notify_system_power(void); static void install_listen_PM_connection(void); static void install_listen_IORegisterForSystemPower(void); static void install_listen_com_apple_powermanagement_sleepservices_notify(void); static void log_ps_change_handler(void *); static int install_listen_for_power_sources(uintptr_t which); static int log_raw_power_source_changes(void); static void log_raw_battery_interest( void *refcon, io_service_t batt, natural_t messageType, void *messageArgument); static void log_raw_battery_match( void *refcon, io_iterator_t b_iter); static void log_thermal_events(void); static void show_systempower_notify(void); static void show_thermal_warning_level(void); static void show_thermal_cpu_power_level(void); static void print_raw_battery_state(io_registry_entry_t b_reg); static void print_setting_value(CFTypeRef a, int divider); static void print_override_pids(int assertion_type); static void print_time_of_day_to_buf(int m, char *buf, int buflen); static void print_days_to_buf(int d, char *buf, int buflen); static void print_repeating_report(CFDictionaryRef repeat); static void print_scheduled_report(CFArrayRef events); static CFDictionaryRef getPowerEvent(int type, CFDictionaryRef events); static int getRepeatingDictionaryMinutes(CFDictionaryRef event); static int getRepeatingDictionaryDayMask(CFDictionaryRef event); static CFStringRef getRepeatingDictionaryType(CFDictionaryRef event); static int arePowerSourceSettingsInconsistent(CFDictionaryRef set); static void checkSettingConsistency(CFDictionaryRef profiles); static ScheduledEventReturnType *scheduled_event_struct_create(void); static void scheduled_event_struct_destroy(ScheduledEventReturnType *); static void string_tolower(char *lower_me, char *dst); static void string_toupper(char *upper_me, char *dst); static int checkAndSetIntValue( char *valstr, CFStringRef settingKey, int apply, int isOnOffSetting, int multiplier, CFMutableDictionaryRef ac, CFMutableDictionaryRef batt, CFMutableDictionaryRef ups); static int setUPSValue( char *valstr, CFStringRef whichUPS, CFStringRef settingKey, int apply, CFMutableDictionaryRef thresholds); static int parseScheduledEvent( char **argv, int *num_args_parsed, ScheduledEventReturnType *local_scheduled_event, bool *cancel_scheduled_event, bool is_relative_event); static int parseRepeatingEvent( char **argv, int *num_args_parsed, CFMutableDictionaryRef local_repeating_event, bool *local_cancel_repeating); static int parseArgs( int argc, char* argv[], CFDictionaryRef *settings, int *modified_power_sources, bool *force_activate_settings, CFDictionaryRef *active_profiles, CFDictionaryRef *system_power_settings, CFDictionaryRef *ups_thresholds, ScheduledEventReturnType **scheduled_event, bool *cancel_scheduled_event, CFDictionaryRef *repeating_event, bool *cancel_repeating_event, uint32_t *pmCmd); static void displaySleepNow(); static void swd_debugTrig(); static const char *getCanonicalArgForSynonym(char *pass) { if (!pass || 0 == strlen(pass)) return ARG_LIVE; if (!strncmp(ARG_DISK, pass, kMaxArgStringLength)) return ARG_CUSTOM; if (!strncmp(ARG_ADAPTER_AC, pass, kMaxArgStringLength)) return ARG_ADAPTER; if (!strncmp(ARG_BATT, pass, kMaxArgStringLength)) return ARG_PS; return pass; } typedef enum { kActionGetOnceNoArgs, kActionGetLog, kActionNotForEverything } CommandActionType; typedef struct { CommandActionType actionType; const char *arg; void (^action)(char **); } CommandAndAction; static CommandAndAction the_getters[] = { {kActionGetOnceNoArgs, ARG_LIVE, ^(char **arg){ show_system_power_settings(); show_active_profiles(); show_live_pm_settings();}}, {kActionGetOnceNoArgs, ARG_CUSTOM, ^(char **arg){ show_custom_pm_settings(); }}, {kActionGetOnceNoArgs, ARG_CAP, ^(char **arg){ show_supported_pm_features(); }}, {kActionGetOnceNoArgs, ARG_SCHED, ^(char **arg){ show_scheduled_events(); }}, {kActionGetOnceNoArgs, ARG_UPS, ^(char **arg){ show_ups_settings(); }}, {kActionGetOnceNoArgs, ARG_SYS_PROFILES, ^(char **arg){ show_active_profiles(); show_system_profiles(); }}, {kActionGetOnceNoArgs, ARG_ADAPTER, ^(char **arg){ show_power_adapter(); }}, {kActionGetOnceNoArgs, ARG_PS, ^(char **arg){ show_power_sources(kApplyToBattery | kApplyToUPS); }}, {kActionGetLog, ARG_PSLOG, ^(char **arg){ install_listen_IORegisterForSystemPower(); install_listen_for_power_sources(kApplyToBattery | kApplyToUPS); CFRunLoopRun(); }}, {kActionGetLog, ARG_TRCOLUMNS, ^(char **arg){ install_listen_IORegisterForSystemPower(); install_listen_for_power_sources(kShowColumns); CFRunLoopRun(); }}, {kActionGetLog, ARG_PSRAW, ^(char **arg){ log_raw_power_source_changes(); }}, {kActionGetOnceNoArgs, ARG_BATTRAW, ^(char **arg){ print_raw_battery_state(IO_OBJECT_NULL); }}, {kActionGetOnceNoArgs, ARG_THERM, ^(char **arg){ show_thermal_warning_level(); show_thermal_cpu_power_level(); }}, {kActionGetLog, ARG_THERMLOG, ^(char **arg){ log_thermal_events(); }}, {kActionGetOnceNoArgs, ARG_ASSERTIONS, ^(char **arg){ show_assertions(NULL); }}, {kActionGetLog, ARG_ASSERTIONSLOG, ^(char **arg){ log_assertions(); }}, {kActionGetOnceNoArgs, ARG_SYSLOAD, ^(char **arg){ show_systemload(); }}, {kActionGetLog, ARG_SYSLOADLOG, ^(char **arg){ log_systemload(); }}, {kActionGetLog, ARG_USERACTIVITYLOG,^(char **arg){ log_useractivity_presentActive(kRunLoop); }}, {kActionGetOnceNoArgs, ARG_USERACTIVITY ,^(char **arg){ log_useractivity_presentActive(kRunOnce); }}, {kActionGetOnceNoArgs, ARG_LOG, ^(char **arg){ show_log(); }}, {kActionGetLog, ARG_LISTEN, ^(char **arg){ listen_for_everything(); }}, {kActionGetOnceNoArgs, ARG_HISTORY, ^(char **arg){ show_power_event_history(); }}, {kActionGetOnceNoArgs, ARG_HISTORY_DETAILED, ^(char **arg){ show_power_event_history_detailed(); }}, #if !TARGET_OS_EMBEDDED {kActionGetOnceNoArgs, ARG_HID_NULL, ^(char **arg){ show_NULL_HID_events(); }}, {kActionNotForEverything, ARG_FBA, ^(char **arg){print_fba(arg); }}, #endif {kActionGetOnceNoArgs, ARG_USERCLIENTS, ^(char **arg){ show_root_domain_user_clients(); }}, {kActionGetOnceNoArgs, ARG_UUID, ^(char **arg){ show_uuid(kActionGetOnceNoArgs); }}, {kActionGetLog, ARG_UUID_LOG, ^(char **arg){ show_uuid(kActionGetLog); }}, {kActionGetOnceNoArgs, ARG_PRINT_GETTERS, ^(char **arg){ show_getters(); }}, {kActionGetLog, ARG_SEARCH, ^(char **arg){show_details_for_UUID(arg); }}, {kActionGetOnceNoArgs, ARG_POWERSTATE, ^(char **arg){show_power_state(arg); }}, {kActionGetLog, ARG_POWERSTATELOG, ^(char **arg){show_power_statelog(arg); }}, {kActionGetOnceNoArgs, ARG_RDSTATS, ^(char **arg){show_rdStats(arg); }}, {kActionGetOnceNoArgs, ARG_SYSSTATE, ^(char **arg){show_sysstate(arg); }}, {kActionGetLog, ARG_SLEEPBLOCKERS, ^(char **arg){show_sleep_blockers(arg); }}, {kActionNotForEverything, ARG_EVERYTHING, ^(char **arg){show_everything(arg); }} }; static const int the_getters_count = (sizeof(the_getters) / sizeof(CommandAndAction)); //**************************** //**************************** //**************************** static void usage(void) { printf("Usage: pmset \n"); printf("See pmset(1) for details: \'man pmset\'\n"); } int main(int argc, char *argv[]) { IOReturn ret, ret1, err; io_connect_t fb; CFDictionaryRef es_custom_settings = 0; int modified_power_sources = 0; bool force_it = 0; CFDictionaryRef ups_thresholds = 0; CFDictionaryRef system_power_settings = 0; CFDictionaryRef active_profiles = 0; ScheduledEventReturnType *scheduled_event_return = 0; bool cancel_scheduled_event = 0; CFDictionaryRef repeating_event_return = 0; bool cancel_repeating_event = 0; uint32_t pmCommand = 0; ret = parseArgs(argc, argv, &es_custom_settings, &modified_power_sources, &force_it, &active_profiles, &system_power_settings, &ups_thresholds, &scheduled_event_return, &cancel_scheduled_event, &repeating_event_return, &cancel_repeating_event, &pmCommand); if(ret == kParseBadArgs) { //printf("pmset: error in parseArgs!\n"); usage(); exit(1); } if(ret == kParseInternalError) { fprintf(stderr, "%s: internal error!\n", argv[0]); fflush(stdout); exit(1); } switch ( pmCommand ) { /*************** Sleep now *************************************/ case kPMCommandSleepNow: fb = IOPMFindPowerManagement(MACH_PORT_NULL); if ( MACH_PORT_NULL != fb ) { err = IOPMSleepSystem ( fb ); if( kIOReturnNotPrivileged == err ) { printf("Sleep error 0x%08x; You must run this as root.\n", err); exit(EX_NOPERM); } else if ( (MACH_PORT_NULL == fb) || (kIOReturnSuccess != err) ) { printf("Unable to sleep system: error 0x%08x\n", err); exit(EX_OSERR); } else { printf("Sleeping now...\n"); } } return 0; /*************** Display Sleep now *************************************/ case kPMCommandDisplaySleepNow: displaySleepNow(); break; case kPMCommandDebugTrig: swd_debugTrig(); break; /*************** Touch settings *************************************/ case kPMCommandTouch: printf("touching prefs file on disk...\n"); ret = IOPMSetPMPreferences(NULL); if(kIOReturnSuccess != ret) { printf("\'%s\' must be run as root...\n", argv[0]); } return 0; /*************** Prevent idle sleep **********************************/ case kPMCommandNoIdle: if(!prevent_idle_sleep()) { printf("Error preventing idle sleep\n"); } return 1; default: // If no command is specified, execution continues with processing // other command-line arguments break; } if(force_it && es_custom_settings) { mach_port_t pm_server = MACH_PORT_NULL; CFDataRef settings_data; int32_t return_code; kern_return_t kern_result; /* * Step 1 - send these forced settings over to powerd. * */ err = _pm_connect(&pm_server); if (kIOReturnSuccess == err) { settings_data = IOCFSerialize(es_custom_settings, 0); if (settings_data) { kern_result = io_pm_force_active_settings( pm_server, (vm_offset_t)CFDataGetBytePtr(settings_data), (mach_msg_type_number_t)CFDataGetLength(settings_data), &return_code); if( KERN_SUCCESS != kern_result ) { printf("exit kern_result = 0x%08x\n", kern_result); } if( kIOReturnSuccess != return_code ) { printf("exit return_code = 0x%08x\n", return_code); } CFRelease(settings_data); if (KERN_SUCCESS != kern_result || kIOReturnSuccess != return_code) { exit(1); } } _pm_disconnect(pm_server); } /* * Step 2 - this code might be running in a partilially uninitialized OS, * and powerd might not be running. e.g. at Installer context. * Since powerd may not be running, we also activate these settings directly * to the controlling drivers in the kernel. * */ CFTypeRef powersources = IOPSCopyPowerSourcesInfo(); CFStringRef activePowerSource = NULL; CFDictionaryRef useSettings = NULL; if (powersources) { activePowerSource = IOPSGetProvidingPowerSourceType(powersources); if (!activePowerSource) { activePowerSource = CFSTR(kIOPMACPowerKey); } useSettings = CFDictionaryGetValue(es_custom_settings, activePowerSource); if (useSettings) { ActivatePMSettings(useSettings, true); } CFRelease(powersources); } // Return here. If this is a 'force' call we do _not_ want // to attempt to write any settings to the disk, or to try anything // else at all, as our environment may be unwritable / diskless // (booted from install CD) return 0; } if(es_custom_settings) { CFNumberRef neg1 = NULL; int tmp_int = -1; CFDictionaryRef tmp_dict = NULL; CFMutableDictionaryRef customize_active_profiles = NULL; // Send pmset changes out to disk if(kIOReturnSuccess != (ret1 = IOPMSetPMPreferences(es_custom_settings))) { if(ret1 == kIOReturnNotPrivileged) { printf("\'%s\' must be run as root...\n", argv[0]); } else { printf("Error 0x%08x writing Energy Saver preferences to disk\n", ret1); } exit(1); } // Also need to change the active profile to -1 (Custom) // We assume the user intended to activate these new custom settings. neg1 = CFNumberCreate(0, kCFNumberIntType, &tmp_int); tmp_dict = IOPMCopyActivePowerProfiles(); if(!tmp_dict) { printf("Custom profile set; unable to update active profile to -1.\n"); exit(1); } customize_active_profiles = CFDictionaryCreateMutableCopy(0, 0, tmp_dict); if(!customize_active_profiles) { printf("Internal error\n"); exit(1); } // For each power source we modified settings for, flip that // source's profile to -1 if(modified_power_sources & kApplyToCharger) { CFDictionarySetValue( customize_active_profiles, CFSTR(kIOPMACPowerKey), neg1); } if(modified_power_sources & kApplyToBattery) { CFDictionarySetValue( customize_active_profiles, CFSTR(kIOPMBatteryPowerKey), neg1); } if(modified_power_sources & kApplyToUPS) { CFDictionarySetValue( customize_active_profiles, CFSTR(kIOPMUPSPowerKey), neg1); } ret = IOPMSetActivePowerProfiles(customize_active_profiles); if(kIOReturnSuccess != ret) { printf("Error 0x%08x writing customized power profiles to disk\n", ret); exit(1); } CFRelease(neg1); CFRelease(tmp_dict); CFRelease(customize_active_profiles); // Print a warning to stderr if idle sleep settings won't // produce expected result; i.e. sleep < (display | dim) checkSettingConsistency(es_custom_settings); CFRelease(es_custom_settings); } if(active_profiles) { ret = IOPMSetActivePowerProfiles(active_profiles); if(kIOReturnSuccess != ret) { printf("Error 0x%08x writing active power profiles to disk\n", ret); exit(1); } CFRelease(active_profiles); } if(system_power_settings) { int iii; CFIndex sys_setting_count = 0; if( isA_CFDictionary(system_power_settings)) { sys_setting_count = CFDictionaryGetCount(system_power_settings); } if (0 != sys_setting_count) { CFStringRef *keys = malloc(sizeof(CFStringRef) * sys_setting_count); CFTypeRef *vals = malloc(sizeof(CFTypeRef) * sys_setting_count); if(keys && vals) { CFDictionaryGetKeysAndValues( system_power_settings, (const void **)keys, (const void **)vals); for(iii=0; iiiwhen, scheduled_event_return->who, scheduled_event_return->which); } else { ret = IOPMSchedulePowerEvent( scheduled_event_return->when, scheduled_event_return->who, scheduled_event_return->which); } if(kIOReturnNotPrivileged == ret) { fprintf(stderr, "%s: This operation must be run as root\n", argv[0]); fflush(stderr); exit(1); } if(kIOReturnSuccess != ret) { fprintf(stderr, "%s: Error in scheduling operation\n", argv[0]); fflush(stderr); exit(1); } // free individual members scheduled_event_struct_destroy(scheduled_event_return); } if(cancel_repeating_event) { ret = IOPMCancelAllRepeatingPowerEvents(); if(kIOReturnSuccess != ret) { if(kIOReturnNotPrivileged == ret) { fprintf(stderr, "pmset: Must be run as root to modify settings\n"); } else { fprintf(stderr, "pmset: Error 0x%08x cancelling repeating events\n", ret); } fflush(stderr); exit(1); } } if(repeating_event_return) { ret = IOPMScheduleRepeatingPowerEvent(repeating_event_return); if(kIOReturnSuccess != ret) { if(kIOReturnNotPrivileged == ret) { fprintf(stderr, "pmset: Must be run as root to modify settings\n"); } else { fprintf(stderr, "pmset: Error 0x%08x scheduling repeating events\n", ret); } fflush(stderr); exit(1); } CFRelease(repeating_event_return); } return 0; } //**************************** //**************************** //**************************** io_registry_entry_t _getRootDomain(void) { static io_registry_entry_t gRoot = MACH_PORT_NULL; if (MACH_PORT_NULL == gRoot) gRoot = IORegistryEntryFromPath( kIOMasterPortDefault, kIOPowerPlane ":/IOPowerConnection/IOPMrootDomain"); return gRoot; } static void swd_debugTrig() { io_service_t rootDomainService = IO_OBJECT_NULL; io_connect_t gRootDomainConnect = IO_OBJECT_NULL; kern_return_t kr = 0; IOReturn ret; // Find it rootDomainService = _getRootDomain(); if (IO_OBJECT_NULL == rootDomainService) { goto exit; } // Open it kr = IOServiceOpen(rootDomainService, mach_task_self(), 0, &gRootDomainConnect); if (KERN_SUCCESS != kr) { printf("Failed to connect to rootDomain. rc=0x%x\n", kr); goto exit; } ret = IOConnectCallMethod(gRootDomainConnect, kPMSleepWakeDebugTrig, NULL, 0, NULL, 0, NULL, NULL, NULL, NULL); if (kIOReturnSuccess != ret) { printf("Failed to trigger a sleep wake kernel log collection. rc=0x%x\n", ret); goto exit; } exit: if (IO_OBJECT_NULL != gRootDomainConnect) IOServiceClose(gRootDomainConnect); return; } static void displaySleepNow() { io_registry_entry_t disp_wrangler = IO_OBJECT_NULL; kern_return_t kr; disp_wrangler = IORegistryEntryFromPath( kIOMasterPortDefault, kIOServicePlane ":/IOResources/IODisplayWrangler"); if(disp_wrangler == IO_OBJECT_NULL) return ; kr = IORegistryEntrySetCFProperty( disp_wrangler, CFSTR("IORequestIdle"),kCFBooleanTrue); if(kr) fprintf(stderr, "pmset: Failed to set the display to sleep(err:0x%x)\n", kr); IOObjectRelease(disp_wrangler); return ; } static CFTypeRef copyRootDomainProperty(CFStringRef key) { static io_object_t rd = IO_OBJECT_NULL; if (IO_OBJECT_NULL == rd) { rd = copyRootDomainRef(); } return IORegistryEntryCreateCFProperty(rd, key, 0, 0); } static IOReturn setRootDomainProperty(CFStringRef key, CFTypeRef val) { io_registry_entry_t root_domain = copyRootDomainRef(); IOReturn ret; if(!root_domain) return kIOReturnError; ret = IORegistryEntrySetCFProperty(root_domain, key, val); IOObjectRelease(root_domain); return ret; } static io_registry_entry_t copyRootDomainRef(void) { return (io_registry_entry_t)IOServiceGetMatchingService( MACH_PORT_NULL, IOServiceNameMatching("IOPMrootDomain")); } static void print_setting_value(CFTypeRef a, int divider) { int n; if(isA_CFNumber(a)) { CFNumberGetValue(a, kCFNumberIntType, (void *)&n); if( 0 != divider ) n/=divider; printf("%d", n); } else if(isA_CFBoolean(a)) { printf("%d", CFBooleanGetValue(a)); } else if(isA_CFString(a)) { char buf[100]; if(CFStringGetCString(a, buf, 100, kCFStringEncodingUTF8)) { printf("%s", buf); } } else printf("oops - print_setting_value unknown data type\n"); } // Arguments to print_override_pids enum { _kIOPMAssertionDisplayOn = 5, _kIOPMAssertionSystemOn = 6 }; static void show_pm_settings_dict( CFDictionaryRef d, int indent, bool show_overrides, bool prune_unsupported) { CFIndex count; int i; int j; int divider = 0; char ps[kMaxArgStringLength]; CFStringRef *keys; CFTypeRef *vals; CFTypeRef ps_blob; CFStringRef activeps = NULL; int show_override_type = 0; bool show_display_dim = false; ps_blob = IOPSCopyPowerSourcesInfo(); if(ps_blob) { activeps = IOPSGetProvidingPowerSourceType(ps_blob); } if(!activeps) activeps = CFSTR(kIOPMACPowerKey); if(activeps) CFRetain(activeps); count = CFDictionaryGetCount(d); keys = (CFStringRef *)malloc(count * sizeof(CFStringRef)); vals = (CFTypeRef *)malloc(count * sizeof(CFTypeRef)); if(!keys || !vals) goto exit; CFDictionaryGetKeysAndValues(d, (const void **)keys, (const void **)vals); for(i=0; i30) indent=0; num_profiles = CFDictionaryGetCount(es); keys = (CFStringRef *)malloc(num_profiles * sizeof(CFStringRef)); values = (CFDictionaryRef *)malloc(num_profiles * sizeof(CFDictionaryRef)); if(keys && values) { CFDictionaryGetKeysAndValues(es, (const void **)keys, (const void **)values); for(i=0; i= 12) afternoon = 1; if(hours > 12) hours-=12; snprintf(buf, buflen, "%d:%d%d%cM", hours, minutes/10, minutes%10, (afternoon? 'P':'A')); } static void print_days_to_buf(int d, char *buf, int buflen) { switch(d) { case daily_mask: snprintf(buf, buflen, "every day"); break; case weekday_mask: snprintf(buf, buflen, "weekdays only"); break; case weekend_mask: snprintf(buf, buflen, "weekends only"); break; case 0x01 : snprintf(buf, buflen, "Monday"); break; case 0x02 : snprintf(buf, buflen, "Tuesday"); break; case 0x04 : snprintf(buf, buflen, "Wednesday"); break; case 0x08 : snprintf(buf, buflen, "Thursday"); break; case 0x10 : snprintf(buf, buflen, "Friday"); break; case 0x20 : snprintf(buf, buflen, "Saturday"); break; case 0x40 : snprintf(buf, buflen, "Sunday"); break; default: snprintf(buf, buflen, "Some days"); break; } } #define kMaxDaysOfWeekLength 20 static void print_repeating_report(CFDictionaryRef repeat) { CFDictionaryRef on, off; char time_buf[kMaxDaysOfWeekLength]; char day_buf[kMaxDaysOfWeekLength]; CFStringRef type_str = NULL; char type_buf[kMaxArgStringLength]; // assumes validly formatted dictionary - doesn't do any error checking on = getPowerEvent(1, repeat); off = getPowerEvent(0, repeat); if(on || off) { printf("Repeating power events:\n"); if(on) { print_time_of_day_to_buf(getRepeatingDictionaryMinutes(on), time_buf, kMaxDaysOfWeekLength); print_days_to_buf(getRepeatingDictionaryDayMask(on), day_buf, kMaxDaysOfWeekLength); type_str = getRepeatingDictionaryType(on); if (type_str) { CFStringGetCString(type_str, type_buf, sizeof(type_buf), kCFStringEncodingMacRoman); } else { snprintf(type_buf, sizeof(type_buf), "?type?"); } printf(" %s at %s %s\n", type_buf, time_buf, day_buf); } if(off) { print_time_of_day_to_buf(getRepeatingDictionaryMinutes(off), time_buf, kMaxDaysOfWeekLength); print_days_to_buf(getRepeatingDictionaryDayMask(off), day_buf, kMaxDaysOfWeekLength); type_str = getRepeatingDictionaryType(off); if (type_str) { CFStringGetCString(type_str, type_buf, sizeof(type_buf), kCFStringEncodingMacRoman); } else { snprintf(type_buf, sizeof(type_buf), "?type?"); } printf(" %s at %s %s\n", type_buf, time_buf, day_buf); } fflush(stdout); } } static void print_scheduled_report(CFArrayRef events) { CFDictionaryRef ev; CFIndex count, i; char date_buf[40]; char name_buf[255]; char type_buf[40]; char *type_ptr = NULL; CFStringRef type = NULL; CFStringRef author = NULL; CFDateFormatterRef formatter = NULL; CFStringRef cf_str_date = NULL; if(!events || !(count = CFArrayGetCount(events))) return; formatter = CFDateFormatterCreate(kCFAllocatorDefault, CFLocaleGetSystem(), kCFDateFormatterShortStyle, kCFDateFormatterMediumStyle); CFDateFormatterSetFormat(formatter, CFSTR(kDateAndTimeFormat)); printf("Scheduled power events:\n"); for(i=0; i sizeof(logStr)) { print_compact_date(CFAbsoluteTimeGetCurrent(), false); printf(" System wide status: %s\n", logStr); len = 0; logStr[0] = 0; } len += snprintf(logStr, sizeof(logStr), "%s%s: %d ", logStr, name, val); } } else { CFStringGetCString(assertionNames[i], name, 50, kCFStringEncodingMacRoman); printf(" %-30s %d\n", name, val); } } if (len != 0) { print_compact_date(CFAbsoluteTimeGetCurrent(), false); printf(" System wide status: %s\n", logStr); } if (prevAssertionNames) free(prevAssertionNames); if (prevAssertionValues) free(prevAssertionValues); if (prevAssertion_status) CFRelease(prevAssertion_status); prevAssertionNames = assertionNames; prevAssertionValues = assertionValues; prevAssertion_status = assertions_status; } static void show_assertions_individually(void (^printer)( char *pname, char *assertionType, char *assertionName, int createdSince)) { CFDictionaryRef assertions_info = NULL; IOReturn ret; ret = IOPMCopyAssertionsByProcess(&assertions_info); if ((kIOReturnSuccess != ret) || !assertions_info) { return; } // printf("\nListed by owning process:\n"); if (!printer) printf("Listed by owning process:\n"); if (!assertions_info) { if (!printer) printf(" None\n"); } else { CFNumberRef *pids = NULL; CFArrayRef *assertions = NULL; CFIndex process_count; int i; process_count = CFDictionaryGetCount(assertions_info); pids = malloc(sizeof(CFNumberRef)*process_count); assertions = (CFArrayRef *)malloc(sizeof(CFArrayRef *)*process_count); CFDictionaryGetKeysAndValues(assertions_info, (const void **)pids, (const void **)assertions); for(i=0; i 0)) { actionStr = CFDictionaryGetValue(tmp_dict, kIOPMAssertionTimeoutActionKey); if (actionStr) { CFStringGetCString(actionStr, actionBuf, sizeof(actionBuf), kCFStringEncodingUTF8); } if (!printer) printf("\tTimeout will fire in %.0f secs Action=%s\n", timeLeft, actionStr ? actionBuf : ""); } } CFArrayRef syms_cf = NULL;; CFStringRef frame_cf = NULL; char frame[200]; int index; syms_cf = CFDictionaryGetValue(tmp_dict, kIOPMAssertionCreatorBacktrace); if (syms_cf != NULL) { for (index = 0; index < CFArrayGetCount(syms_cf); index++) { frame_cf = CFArrayGetValueAtIndex(syms_cf, index); frame[0] = 0; CFStringGetCString(frame_cf, frame, sizeof(frame), kCFStringEncodingMacRoman); if (!printer) printf("%s \n", frame); } } if (printer) { printer(pid_name_buf, assertionType, assertionName, createdSince); } } } free(pids); free(assertions); } exit: if(assertions_info) CFRelease(assertions_info); } static void show_assertion_activity(bool init_only) { int num; CFIndex cnt = 0; char str[200]; bool of; uint64_t num64; CFDateRef time_cf = NULL; static int lines = 0; CFArrayRef log = NULL; CFNumberRef num_cf = NULL; CFStringRef str_cf = NULL; static uint32_t refCnt = UINT_MAX; CFDictionaryRef entry; IOReturn rc; pid_t beneficiary; rc = IOPMCopyAssertionActivityUpdate(&log, &of, &refCnt); if ((rc != kIOReturnSuccess) && (rc != kIOReturnNotFound)) { show_assertions("Showing all currently held IOKit power assertions"); return; } if (!log) { return; } if (init_only) goto exit; if (of) { show_assertions("Showing all currently held IOKit power assertions"); } cnt = isA_CFArray(log) ? CFArrayGetCount(log) : 0; for (int i=0; i < cnt; i++) { entry = CFArrayGetValueAtIndex(log, i); if (entry == NULL) continue; if ((lines++ % 30) == 0) { printf("\n%-17s%-12s%-30s%-20s%-20s%-50s\n", "Time","Action", "Type", "PID(Causing PID)", "ID", "Name"); printf("%-17s%-12s%-30s%-20s%-20s%-50s\n", "====","======", "====", "================", "==", "===="); } time_cf = CFDictionaryGetValue(entry, kIOPMAssertionActivityTime); if (time_cf) print_compact_date(CFDateGetAbsoluteTime(time_cf), false); printf(" "); str_cf = CFDictionaryGetValue(entry, kIOPMAssertionActivityAction); str[0]=0; if (isA_CFString(str_cf)) CFStringGetCString(str_cf, str, sizeof(str), kCFStringEncodingMacRoman); printf("%-12s", str); str_cf = CFDictionaryGetValue(entry, kIOPMAssertionTypeKey); str[0]=0; if (isA_CFString(str_cf)) CFStringGetCString(str_cf, str, sizeof(str), kCFStringEncodingMacRoman); printf("%-30s", str); num_cf = CFDictionaryGetValue(entry, kIOPMAssertionPIDKey); if (isA_CFNumber(num_cf)) { CFNumberGetValue(num_cf, kCFNumberIntType, &num); num_cf = CFDictionaryGetValue(entry, kIOPMAssertionOnBehalfOfPID); if (isA_CFNumber(num_cf)) { CFNumberGetValue(num_cf, kCFNumberIntType, &beneficiary); str[0] = 0; sprintf(str,"%d(%d)", num, beneficiary); printf("%-20s", str); } else printf("%-20d", num); } num_cf = CFDictionaryGetValue(entry, kIOPMAssertionGlobalUniqueIDKey); if (isA_CFNumber(num_cf)) { CFNumberGetValue(num_cf, kCFNumberSInt64Type, &num64); printf("0x%-18llx", num64); } str_cf = CFDictionaryGetValue(entry, kIOPMAssertionNameKey); str[0]=0; if (isA_CFString(str_cf)) { CFStringGetCString(str_cf, str, sizeof(str), kCFStringEncodingMacRoman); printf("%-50s", str); } printf("\n"); } exit: if (cnt) CFRelease(log); } static void print_descriptive_kernel_assertions(uint32_t val32) { bool first = false; if (0!= val32) printf("="); if (val32&kIOPMDriverAssertionCPUBit) { printf("CPU"); first = true; } if (val32&kIOPMDriverAssertionUSBExternalDeviceBit) { if (first) printf(","); first=true; printf("USB"); } if (val32&kIOPMDriverAssertionBluetoothHIDDevicePairedBit) { if (first) printf(","); first=true; printf("BT-HID"); } if (val32&kIOPMDriverAssertionExternalMediaMountedBit) { if (first) printf(","); first=true; printf("MEDIA"); } if (val32&kIOPMDriverAssertionReservedBit5) { if (first) printf(","); first=true; printf("THNDR"); } if (val32&kIOPMDriverAssertionPreventDisplaySleepBit) { if (first) printf(","); first=true; printf("DSPLY"); } if (val32&kIOPMDriverAssertionReservedBit7) { if (first) printf(","); first=true; printf("STORAGE"); } if (val32&kIOPMDriverAssertionMagicPacketWakeEnabledBit) { if (first) printf(","); first=true; printf("MAGICWAKE"); } return; } static void show_assertions_in_kernel(void) { CFMutableDictionaryRef rootDomainProperties = NULL; CFArrayRef kernelAssertionsArray = NULL; CFNumberRef kernelAssertions = NULL; int kernelAssertionsSum = 0; CFIndex count; int i; io_registry_entry_t rootDomain = copyRootDomainRef(); IORegistryEntryCreateCFProperties(rootDomain, &rootDomainProperties, 0, 0); if (rootDomainProperties) { kernelAssertions = CFDictionaryGetValue(rootDomainProperties, CFSTR(kIOPMAssertionsDriverKey)); if (kernelAssertions) { CFNumberGetValue(kernelAssertions, kCFNumberIntType, &kernelAssertionsSum); } kernelAssertionsArray = CFDictionaryGetValue(rootDomainProperties, CFSTR(kIOPMAssertionsDriverDetailedKey)); } if (0 == kernelAssertionsSum) { printf("No kernel assertions.\n"); // printf("\nNo kernel assertions.\n"); return; } printf("Kernel Assertions: 0x%x", kernelAssertionsSum); // printf("\nKernel Assertions: 0x%x", kernelAssertionsSum); print_descriptive_kernel_assertions(kernelAssertionsSum); printf("\n"); if (!kernelAssertionsArray || !(count = CFArrayGetCount(kernelAssertionsArray))) { printf(" None"); } else { CFDictionaryRef whichAssertion = NULL; CFStringRef ownerString = NULL; char ownerBuf[100]; io_name_t serviceNameBuf; CFNumberRef registryEntryID = NULL; CFNumberRef n_id = NULL; CFNumberRef n_modified = NULL; CFNumberRef n_owner = NULL; CFNumberRef n_level = NULL; CFNumberRef n_asserted = NULL; uint64_t val64=0; uint32_t val32=0; for (i=0; i Migrate UserActive SPI clients onto UserActivityLevel */ static void show_useractivity_presentActive(int notifyToken) { uint64_t newVal; notify_get_state(notifyToken, &newVal); print_pretty_date(CFAbsoluteTimeGetCurrent(), false); if (newVal == kIOUserIsIdle) { printf("[KernelDisplayEvent] User is idle on the system\n"); } else { printf("[KernelDisplayEvent] User is active on the system\n"); } } static void log_useractivity_presentActive(bool runOnce) { int token = 0; int status; status = notify_register_check(kIOUserActivityNotifyName, &token); if (NOTIFY_STATUS_OK == status) { show_useractivity_presentActive(token); notify_cancel(token); } log_useractivity_level(kRunOnce); if (runOnce == kRunOnce) { return; } status = notify_register_dispatch( kIOUserActivityNotifyName, &token, dispatch_get_main_queue(), ^(int t) { show_useractivity_presentActive(t); }); if (NOTIFY_STATUS_OK != status) { printf("LogUserActivity: notify_register_dispatch returns error %d; Exiting.\n", status); return; } log_useractivity_level(kRunLoop); dispatch_main(); } static void show_useractivity_level(uint64_t lev, uint64_t msb) { CFStringRef temp = NULL; char buf[200]; print_pretty_date(CFAbsoluteTimeGetCurrent(), false); printf("UserActivity Level=0x%02x\n", (unsigned int)lev); temp = IOPMCopyUserActivityLevelDescription(lev); if (!temp) { printf("[FAIL] IOPMCopyUserActivityLevelDescription(0x%02x) returned NULL", (unsigned int)lev); } else { CFStringGetCString(temp, buf, sizeof(buf), kCFStringEncodingUTF8); printf(" Level = \'%s\'\n", buf); CFRelease(temp); } temp = IOPMCopyUserActivityLevelDescription(msb); if (!temp) { printf("[FAIL] IOPMCopyUserActivityLevelDescription(0x%02x) returned NULL", (unsigned int)msb); } else { CFStringGetCString(temp, buf, sizeof(buf), kCFStringEncodingUTF8); printf(" MostSignificant = \'%s\'\n", buf); CFRelease(temp); } return; } static void log_useractivity_level(bool runOnce) { IOPMNotificationHandle pmHandle = NULL; uint64_t userLevel, significantLevel; IOReturn r; if (kRunOnce == runOnce) { r = IOPMGetUserActivityLevel(&userLevel, &significantLevel); if (kIOReturnSuccess == r) { show_useractivity_level(userLevel, significantLevel); } else { printf("[FAIL] IOPMGetUserActivityLevel returns error 0x%08x\n", r); return; } return; } pmHandle = IOPMScheduleUserActivityLevelNotification(dispatch_get_main_queue(), ^(uint64_t levels, uint64_t most) { show_useractivity_level(levels, most); }); if (!pmHandle) { printf("[FAIL] IOPMScheduleUserActivityLevelNotification returned NULL\n"); } // Share a run loop with the other useractivity listeners // dispatch_main(); } /******************************************************************************/ static void log_ps_change_handler(void *info) { int which = (int)info; if (!(which & kShowColumns)) { print_pretty_date(CFAbsoluteTimeGetCurrent(), false); printf("IOPSNotificationCreateRunLoopSource\n"); } show_power_sources(which); } static int install_listen_for_power_sources(uintptr_t which) { CFRunLoopSourceRef rls = NULL; /* Log changes to all attached power sources */ rls = IOPSNotificationCreateRunLoopSource(log_ps_change_handler, (void *)which); if(!rls) { printf("Error - IOPSNotificationCreateRunLoopSource failure.\n"); return kParseInternalError; } else { CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode); CFRelease(rls); printf("pmset is in logging mode now. Hit ctrl-c to exit.\n"); if (kShowColumns & which) { printf("%10s\t%15s\t%10s\t%10s\t%20s\n", "Elapsed", "TimeRemaining", "Charge", "Charging", "Timestamp"); } // and show initial power source state: log_ps_change_handler((void *)which); } if (!(which & kShowColumns)) { int tokenA, tokenB, tokenC, tokenD; notify_register_dispatch(kIOPSNotifyLowBattery, &tokenA, dispatch_get_main_queue(), ^(int t) { print_pretty_date(CFAbsoluteTimeGetCurrent(), false); printf("%s\n", kIOPSNotifyLowBattery); }); notify_register_dispatch(kIOPSNotifyTimeRemaining, &tokenB, dispatch_get_main_queue(), ^(int t) { print_pretty_date(CFAbsoluteTimeGetCurrent(), false); printf("%s\n", kIOPSNotifyTimeRemaining); }); notify_register_dispatch(kIOPSNotifyPowerSource, &tokenC, dispatch_get_main_queue(), ^(int t) { print_pretty_date(CFAbsoluteTimeGetCurrent(), false); printf("%s\n", kIOPSNotifyPowerSource); }); notify_register_dispatch(kIOPSNotifyAttach, &tokenC, dispatch_get_main_queue(), ^(int t) { print_pretty_date(CFAbsoluteTimeGetCurrent(), false); printf("%s\n", kIOPSNotifyAttach); }); notify_register_dispatch(kIOPSNotifyAnyPowerSource, &tokenC, dispatch_get_main_queue(), ^(int t) { print_pretty_date(CFAbsoluteTimeGetCurrent(), false); printf("%s\n", kIOPSNotifyAnyPowerSource); }); notify_register_dispatch(kIOPSNotifyPercentChange, &tokenD, dispatch_get_main_queue(), ^(int t) { print_pretty_date(CFAbsoluteTimeGetCurrent(), false); printf("%s\n", kIOPSNotifyPercentChange); }); } return 0; } /******************************************************************************/ /* */ /* RAW PS LOGGING */ /* */ /******************************************************************************/ static CFAbsoluteTime getAbsoluteTimeForProperty(CFDictionaryRef d, CFStringRef key) { CFNumberRef secSince1970 = NULL; uint32_t secs = 0; CFAbsoluteTime return_val = 0.0; if (d && key) { secSince1970 = CFDictionaryGetValue(d, key); if (secSince1970) { CFNumberGetValue(secSince1970, kCFNumberIntType, &secs); return_val = (CFAbsoluteTime)secs - kCFAbsoluteTimeIntervalSince1970; } } return return_val; } static void print_raw_battery_state(io_registry_entry_t b_reg) { CFDateFormatterRef date_format; CFTimeZoneRef tz; CFStringRef time_date; CFLocaleRef loc; char _date[60]; CFStringRef failure; char _failure[200]; CFBooleanRef boo; CFNumberRef n; int tmp; int cur_cap = -1; int max_cap = -1; int design_cap = -1; int cur_cycles = -1; CFMutableDictionaryRef prop = NULL; IOReturn ret; loc = CFLocaleCopyCurrent(); date_format = CFDateFormatterCreate(kCFAllocatorDefault, loc, kCFDateFormatterShortStyle, kCFDateFormatterLongStyle); CFRelease(loc); tz = CFTimeZoneCopySystem(); CFDateFormatterSetProperty(date_format, kCFDateFormatterTimeZone, tz); CFRelease(tz); CFDateFormatterSetFormat(date_format, CFSTR(kDateAndTimeFormat)); time_date = CFDateFormatterCreateStringWithAbsoluteTime(kCFAllocatorDefault, date_format, CFAbsoluteTimeGetCurrent()); if(time_date) { CFStringGetCString(time_date, _date, 60, kCFStringEncodingMacRoman); printf("%s\n", _date); fflush(stdout); CFRelease(time_date); } if (IO_OBJECT_NULL == b_reg) { b_reg = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("AppleSmartBattery")); } ret = IORegistryEntryCreateCFProperties(b_reg, &prop, 0, 0); if( (kIOReturnSuccess != ret) || (NULL == prop) ) { printf("Couldn't read battery status; error = 0%08x\n", ret); goto exit; } boo = CFDictionaryGetValue(prop, CFSTR(kIOPMPSExternalConnectedKey)); printf(" %s; ", (kCFBooleanTrue == boo) ? "AC" : "No AC"); boo = CFDictionaryGetValue(prop, CFSTR(kIOPMPSBatteryInstalledKey)); printf("%s", (kCFBooleanTrue == boo) ? "" : "No battery; "); boo = CFDictionaryGetValue(prop, CFSTR(kIOPMPSIsChargingKey)); printf("%s; ", (kCFBooleanTrue == boo) ? "Charging" : "Not Charging"); n = CFDictionaryGetValue(prop, CFSTR(kIOPMPSCurrentCapacityKey)); if(n) { CFNumberGetValue(n, kCFNumberIntType, &cur_cap); } n = CFDictionaryGetValue(prop, CFSTR(kIOPMPSMaxCapacityKey)); if(n) { CFNumberGetValue(n, kCFNumberIntType, &max_cap); } n = CFDictionaryGetValue(prop, CFSTR(kIOPMPSDesignCapacityKey)); if(n) { CFNumberGetValue(n, kCFNumberIntType, &design_cap); } if( (-1 != cur_cap) && (-1 != max_cap) ) { if (0 == max_cap) { printf("NaN%%; Cap=%d: FCC=%d; Design=%d; ", cur_cap, max_cap, design_cap); } else { printf("%d%%; Cap=%d: FCC=%d; Design=%d; ", (cur_cap*100)/max_cap, cur_cap, max_cap, design_cap); } } n = CFDictionaryGetValue(prop, CFSTR(kIOPMPSTimeRemainingKey)); if(n) { CFNumberGetValue(n, kCFNumberIntType, &tmp); printf("Time=%d:%02d; ", tmp/60, tmp%60); } n = CFDictionaryGetValue(prop, CFSTR(kIOPMPSAmperageKey)); if(n) { CFNumberGetValue(n, kCFNumberIntType, &tmp); printf("%dmA; ", tmp); } n = CFDictionaryGetValue(prop, CFSTR(kIOPMPSCycleCountKey)); if(n) { CFNumberGetValue(n, kCFNumberIntType, &cur_cycles); } printf("Cycles=%d", cur_cycles); n = CFDictionaryGetValue(prop, CFSTR(kIOPMPSLocationKey)); if(n) { CFNumberGetValue(n, kCFNumberIntType, &tmp); printf("; Location=%d; ", tmp); } failure = CFDictionaryGetValue(prop, CFSTR("ErrorCondition")); if(failure) { CFStringGetCString(failure, _failure, 200, kCFStringEncodingMacRoman); printf("\n Failure=\"%s\"", _failure); } #ifndef kIOBatteryBootPathKey #define kIOBatteryBootPathKey "BootPathUpdated" #define kIOBatteryFullPathKey "FullPathUpdated" #define kIOBatterykUserVisPathKey "UserVisiblePathUpdated" #endif printf("\n"); CFAbsoluteTime since = 0.0; CFStringRef since_string = NULL; char since_str[65]; since = getAbsoluteTimeForProperty(prop, CFSTR(kIOBatteryBootPathKey)); if (0.0 != since) { since_string = CFDateFormatterCreateStringWithAbsoluteTime(0, date_format, since); CFStringGetCString(since_string, since_str, sizeof(since_str), kCFStringEncodingUTF8); printf(" Polled boot=%s", since_str); CFRelease(since_string); } since = getAbsoluteTimeForProperty(prop, CFSTR(kIOBatteryFullPathKey)); if (0.0 != since) { since_string = CFDateFormatterCreateStringWithAbsoluteTime(0, date_format, since); CFStringGetCString(since_string, since_str, sizeof(since_str), kCFStringEncodingUTF8); printf("; Full=%s", since_str); CFRelease(since_string); } since = getAbsoluteTimeForProperty(prop, CFSTR(kIOBatterykUserVisPathKey)); if (0.0 != since) { since_string = CFDateFormatterCreateStringWithAbsoluteTime(0, date_format, since); CFStringGetCString(since_string, since_str, sizeof(since_str), kCFStringEncodingUTF8); printf("; User visible=%s", since_str); CFRelease(since_string); } printf("\n"); fflush(stdout); exit: if (date_format) { CFRelease(date_format); } if (prop) { CFRelease(prop); } return; } static void log_raw_battery_match( void *refcon, io_iterator_t b_iter) { IONotificationPortRef notify = *((IONotificationPortRef *)refcon); io_registry_entry_t battery; io_object_t notification_ref; int found = false; while ((battery = (io_registry_entry_t)IOIteratorNext(b_iter))) { found = true; printf(" * Battery matched at registry = %d\n", (int32_t)battery); print_raw_battery_state(battery); // And install an interest notification on it IOServiceAddInterestNotification(notify, battery, kIOGeneralInterest, log_raw_battery_interest, NULL, ¬ification_ref); IOObjectRelease(battery); } if(!found) { printf(" (no batteries found; waiting)\n"); } } static void log_raw_battery_interest( void *refcon, io_service_t batt, natural_t messageType, void *messageArgument) { if(kIOPMMessageBatteryStatusHasChanged == messageType) { print_raw_battery_state((io_registry_entry_t)batt); } return; } static int log_raw_power_source_changes(void) { IONotificationPortRef notify_port = 0; io_iterator_t battery_iter = 0; CFRunLoopSourceRef rlser = 0; IOReturn ret; printf("pmset is in RAW logging mode now. Hit ctrl-c to exit.\n"); notify_port = IONotificationPortCreate(0); rlser = IONotificationPortGetRunLoopSource(notify_port); if(!rlser) return 0; CFRunLoopAddSource(CFRunLoopGetCurrent(), rlser, kCFRunLoopDefaultMode); ret = IOServiceAddMatchingNotification( notify_port, kIOFirstMatchNotification, IOServiceMatching("IOPMPowerSource"), log_raw_battery_match, (void *)¬ify_port, &battery_iter); if(KERN_SUCCESS != ret){ printf("!!Error prevented matching notifications; err = 0x%08x\n", ret); } // Install notifications on existing instances. log_raw_battery_match((void *)¬ify_port, battery_iter); CFRunLoopRun(); // should never return from CFRunLoopRun return 0; } static void show_systempower_notify(void) { IOPMCapabilityBits b; char stateDescriptionStr[100]; b = IOPMConnectionGetSystemCapabilities(); IOPMGetCapabilitiesDescription(stateDescriptionStr, sizeof(stateDescriptionStr), b); print_pretty_date(CFAbsoluteTimeGetCurrent(), false); printf("com.apple.powermanagement.systempowerstate=%s\n", stateDescriptionStr); return; } static void install_listen_for_notify_system_power(void) { uint32_t status; int token; printf("Logging: com.apple.powermanagement.systempowerstate\n"); status = notify_register_dispatch( kIOSystemLoadAdvisoryNotifyName, &token, dispatch_get_main_queue(), ^(int t) { show_systempower_notify(); }); if (NOTIFY_STATUS_OK != status) { fprintf(stderr, "Registration failed for \"%s\" with (%u)\n", kIOPMSystemPowerStateNotify, status); } } /*************************************************************************/ void myPMConnectionHandler( void *param, IOPMConnection connection, IOPMConnectionMessageToken token, IOPMSystemPowerStateCapabilities capabilities) { #if TARGET_OS_EMBEDDED return; #else char stateDescriptionStr[100]; IOReturn ret; const char *earlyStr; printf("\n"); print_pretty_date(CFAbsoluteTimeGetCurrent(), true); IOPMGetCapabilitiesDescription(stateDescriptionStr, sizeof(stateDescriptionStr), (uint64_t)capabilities); if (kIOPMEarlyWakeNotification & capabilities) { earlyStr = "(Early)"; } else { earlyStr = ""; } printf("PMConnection: %s%s caps:0x%x\n", stateDescriptionStr, earlyStr, capabilities); IOPMSystemPowerStateCapabilities fromAPI = IOPMConnectionGetSystemCapabilities(); if (capabilities != fromAPI) { printf("PMConnection: API IOPMConnectionGetSystemCapabilities() = 0x%04x, and differs from PMConnectionHandler Arg = 0x%04x\n", (uint32_t)fromAPI, (uint32_t)capabilities); } if (!(kIOPMCapabilityCPU & capabilities)) { printSleepAndWakeReasons(kJustPrintSleep); } else { printSleepAndWakeReasons(kJustPrintWake); } ret = IOPMConnectionAcknowledgeEvent(connection, token); if (kIOReturnSuccess != ret) { printf("\t-> PM Connection acknowledgement error 0x%08x\n", ret); } #endif /* TARGET_OS_EMBEDDED */ } static void install_listen_PM_connection(void) { #if TARGET_OS_EMBEDDED return; #else IOPMConnection myConnection; IOReturn ret; printf("Logging IOPMConnection\n"); ret = IOPMConnectionCreate( CFSTR("SleepWakeLogTool"), kIOPMEarlyWakeNotification | kIOPMCapabilityCPU | kIOPMCapabilityDisk | kIOPMCapabilityNetwork | kIOPMCapabilityAudio | kIOPMCapabilityVideo | kIOPMCapabilityPushServiceTask | kIOPMCapabilityBackgroundTask | kIOPMCapabilitySilentRunning | kIOPMEarlyWakeNotification, &myConnection); if (kIOReturnSuccess != ret) { printf("IOPMConnectionCreate Create: Error 0x%08x\n", ret); return; } ret = IOPMConnectionSetNotification( myConnection, NULL, (IOPMEventHandlerType)myPMConnectionHandler); if (kIOReturnSuccess != ret) { printf("IOPMConnectionCreate SetNotification: Error 0x%08x\n", ret); return; } ret = IOPMConnectionScheduleWithRunLoop( myConnection, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode); if (kIOReturnSuccess != ret) { printf("IOPMConnection ScheduleWithRunloop: Error 0x%08x\n", ret); return; } #endif /* TARGET_OS_EMBEDDED */ } static void install_listen_com_apple_powermanagement_sleepservices_notify(void) { int token; int status; status = notify_register_dispatch(kIOPMSleepServiceActiveNotifyName, &token, dispatch_get_main_queue(), ^(int t) { if (IOPMGetSleepServicesActive()) { printf("SleepServices are: ON\n"); } else { printf("SleepServices are: OFF\n"); } }); if (NOTIFY_STATUS_OK != status) { fprintf(stderr, "Registration failed for \"%s\" with (%u)\n", kIOPMSleepServiceActiveNotifyName, status); } if (IOPMGetSleepServicesActive()) { printf("SleepServices are: ON\n"); } else { printf("SleepServices are: OFF\n"); } } static void install_listen_IORegisterForSystemPower(void) { io_object_t root_notifier = MACH_PORT_NULL; IONotificationPortRef notify = NULL; printf("Logging IORegisterForSystemPower sleep/wake messages\n"); /* Log sleep/wake messages */ gPMAckPort = IORegisterForSystemPower ( (void *)kLogSleepEvents, ¬ify, sleepWakeCallback, &root_notifier); if( notify && (MACH_PORT_NULL != gPMAckPort) ) { CFRunLoopAddSource(CFRunLoopGetCurrent(), IONotificationPortGetRunLoopSource(notify), kCFRunLoopDefaultMode); } return; } static void pmPrefsCallBack(void *context) { print_pretty_date(CFAbsoluteTimeGetCurrent(), false); printf("Prefs updated\n"); return; } static void listen_for_everything(void) { install_listen_for_power_sources(kApplyToBattery | kApplyToUPS); install_listen_for_notify_system_power(); install_listen_PM_connection(); install_listen_IORegisterForSystemPower(); install_listen_com_apple_powermanagement_sleepservices_notify(); CFRunLoopSourceRef prefsSrc = NULL; prefsSrc = IOPMPrefsNotificationCreateRunLoopSource(pmPrefsCallBack, NULL); if (prefsSrc) { CFRunLoopAddSource(CFRunLoopGetCurrent(), prefsSrc, kCFRunLoopDefaultMode); } CFRunLoopRun(); // should never return from CFRunLoopRun } static void log_thermal_events(void) { int powerConstraintNotifyToken = 0; int cpuPowerNotifyToken = 0; uint32_t status; status = notify_register_dispatch( kIOPMCPUPowerNotificationKey, &cpuPowerNotifyToken, dispatch_get_main_queue(), ^(int t) { show_thermal_cpu_power_level(); }); if (NOTIFY_STATUS_OK != status) { fprintf(stderr, "Registration failed for \"%s\" with (%u)\n", kIOPMCPUPowerNotificationKey, status); } status = notify_register_dispatch( kIOPMThermalWarningNotificationKey, &powerConstraintNotifyToken, dispatch_get_main_queue(), ^(int t) { show_thermal_warning_level(); }); if (NOTIFY_STATUS_OK != status) { fprintf(stderr, "Registration failed for \"%s\" with (%u)\n", kIOPMThermalWarningNotificationKey, status); } show_thermal_warning_level(); show_thermal_cpu_power_level(); dispatch_main(); } static void show_thermal_warning_level(void) { uint32_t warn = -1; IOReturn ret; ret = IOPMGetThermalWarningLevel(&warn); if (kIOReturnNotFound == ret) { printf("Note: No thermal warning level has been recorded\n"); return; } if (kIOReturnSuccess != ret) { printf("Error: No thermal warning level with error code 0x%08x\n", ret); return; } // successfully found warning level print_pretty_date(CFAbsoluteTimeGetCurrent(), false); printf("Thermal Warning Level = %d\n", warn); return; } static void show_thermal_cpu_power_level(void) { CFDictionaryRef cpuStatus; CFStringRef *keys = NULL; CFNumberRef *vals = NULL; CFIndex count = 0; int i; IOReturn ret; ret = IOPMCopyCPUPowerStatus(&cpuStatus); if (kIOReturnNotFound == ret) { printf("Note: No CPU power status has been recorded\n"); return; } if (!cpuStatus || (kIOReturnSuccess != ret)) { printf("Error: No CPU power status with error code 0x%08x\n", ret); return; } print_pretty_date(CFAbsoluteTimeGetCurrent(), false); fprintf(stderr, "CPU Power notify\n"), fflush(stderr); count = CFDictionaryGetCount(cpuStatus); keys = (CFStringRef *)malloc(count*sizeof(CFStringRef)); vals = (CFNumberRef *)malloc(count*sizeof(CFNumberRef)); if (!keys||!vals) goto exit; CFDictionaryGetKeysAndValues(cpuStatus, (const void **)keys, (const void **)vals); for(i=0; i msec) if(0 != multiplier) val *= multiplier; } // negative number? reject it if(val < 0) return -1; val32 = (int32_t)val; cfnum = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &val32); if(!cfnum) return -1; if(apply & kApplyToBattery) CFDictionarySetValue(batt, settingKey, cfnum); if(apply & kApplyToCharger) CFDictionarySetValue(ac, settingKey, cfnum); if(apply & kApplyToUPS) CFDictionarySetValue(ups, settingKey, cfnum); CFRelease(cfnum); return 0; } static int checkAndSetStrValue(char *valstr, CFStringRef settingKey, int apply, CFMutableDictionaryRef ac, CFMutableDictionaryRef batt, CFMutableDictionaryRef ups) { CFStringRef cfstr; if(!valstr) return -1; cfstr = CFStringCreateWithCString(kCFAllocatorDefault, valstr, kCFStringEncodingMacRoman); if(!cfstr) return -1; if(apply & kApplyToBattery) CFDictionarySetValue(batt, settingKey, cfstr); if(apply & kApplyToCharger) CFDictionarySetValue(ac, settingKey, cfstr); if(apply & kApplyToUPS) CFDictionarySetValue(ups, settingKey, cfstr); CFRelease(cfstr); return 0; } static int setUPSValue(char *valstr, CFStringRef whichUPS, CFStringRef settingKey, int apply, CFMutableDictionaryRef thresholds) { CFMutableDictionaryRef ups_setting = NULL; CFDictionaryRef tmp_ups_setting = NULL; CFNumberRef cfnum = NULL; CFBooleanRef on_off = kCFBooleanTrue; char *endptr = NULL; long val; int32_t val32; if(!valstr) return -1; val = strtol(valstr, &endptr, 10); if(0 != *endptr) { // the string contained some non-numerical characters - bail return -1; } if(-1 == val) { on_off = kCFBooleanFalse; } // negative number? reject it if(val < 0) val = 0; // if this should be a percentage, cap the value at 100% if(kCFCompareEqualTo == CFStringCompare(settingKey, CFSTR(kIOUPSShutdownAtLevelKey), 0)) { if(val > 100) val = 100; }; // bail if -u or -a hasn't been specified: if(!(apply & kApplyToUPS)) return -1; // Create the nested dictionaries of UPS settings tmp_ups_setting = CFDictionaryGetValue(thresholds, settingKey); ups_setting = CFDictionaryCreateMutableCopy(0, 0, tmp_ups_setting); if(!ups_setting) { ups_setting = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); } val32 = (int32_t)val; cfnum = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &val32); if(kCFBooleanFalse == on_off) { // If user is turning this setting off, then preserve the existing value in there. // via CFDictionaryAddValue CFDictionaryAddValue(ups_setting, CFSTR(kIOUPSShutdownLevelValueKey), cfnum); } else { // If user is providing a new value for this setting, overwrite the existing value. CFDictionarySetValue(ups_setting, CFSTR(kIOUPSShutdownLevelValueKey), cfnum); } CFRelease(cfnum); CFDictionarySetValue(ups_setting, CFSTR(kIOUPSShutdownLevelEnabledKey), on_off); CFDictionarySetValue(thresholds, settingKey, ups_setting); CFRelease(ups_setting); return 0; } // pmset repeat cancel // pmset repeat