1/* 2 * Copyright (c) 2010 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24#include <CoreFoundation/CoreFoundation.h> 25#include <CoreFoundation/CFDateFormatter.h> 26 27#include <SystemConfiguration/SystemConfiguration.h> 28#include <SystemConfiguration/SCValidation.h> 29 30#include <IOKit/IOMessage.h> 31#include <IOKit/pwr_mgt/IOPM.h> 32#include <IOKit/pwr_mgt/IOPMLib.h> 33#include <IOKit/pwr_mgt/IOPMLibPrivate.h> 34#include <IOKit/pwr_mgt/IOPMUPSPrivate.h> 35#include <IOKit/ps/IOPSKeys.h> 36#include <IOKit/ps/IOPowerSources.h> 37#include <IOKit/ps/IOPowerSourcesPrivate.h> 38#include <IOKit/IOCFSerialize.h> 39 40#if TARGET_OS_EMBEDDED 41 #define PLATFORM_HAS_DISPLAYSERVICES 0 42#else 43 #define PLATFORM_HAS_DISPLAYSERVICES 1 44 // ResentAmbientLightAll is defined in <DisplayServices/DisplayServices.h> 45 // and implemented by DisplayServices.framework 46 IOReturn DisplayServicesResetAmbientLightAll( void ); 47#endif 48 49#include "../pmconfigd/PrivateLib.h" 50 51// dynamically mig generated 52#include "powermanagement.h" 53 54#include <IOKit/IOHibernatePrivate.h> 55#include <IOKit/IOReportTypes.h> 56#include <IOReport.h> 57 58#include <servers/bootstrap.h> 59#include <bootstrap_priv.h> 60#include <mach/mach_port.h> 61#include <string.h> 62#include <ctype.h> 63#include <unistd.h> 64#include <notify.h> 65#include <asl.h> 66#include <asl_private.h> 67#include <asl_core.h> 68#include <asl_file.h> 69#include <asl_store.h> 70#include <dirent.h> 71#include <sysexits.h> 72 73/* 74 * This is the command line interface to Energy Saver Preferences in 75 * /Library/Preferences/SystemConfiguration/com.apple.PowerManagement.plist 76 * 77 * pmset does many things, but here are a few of them: 78 * 79 Usage: pmset [-b | -c | -a] <action> <minutes> [[<opts>] <action> <minutes> ...] 80 -c adjust settings used while connected to a charger 81 -b adjust settings used when running off a battery 82 -a (default) adjust settings for both 83 <action> is one of: dim, sleep, spindown, slower, womp* (* flag = 1/0) 84 eg. pmset womp 1 -c dim 5 sleep 15 -b dim 3 spindown 5 sleep 8 85 */ 86 87// Settings options 88#define ARG_DIM "dim" 89#define ARG_DISPLAYSLEEP "displaysleep" 90#define ARG_SLEEP "sleep" 91#define ARG_SPINDOWN "spindown" 92#define ARG_DISKSLEEP "disksleep" 93#define ARG_WOMP "womp" 94#define ARG_LIDWAKE "lidwake" 95 96#define ARG_HIBERNATEMODE "hibernatemode" 97#define ARG_HIBERNATEFILE "hibernatefile" 98#define ARG_HIBERNATEFREERATIO "hibernatefreeratio" 99#define ARG_HIBERNATEFREETIME "hibernatefreetime" 100#define ARG_AUTOPOWEROFF "autopoweroff" 101#define ARG_AUTOPOWEROFFDELAY "autopoweroffdelay" 102 103#define ARG_RING "ring" 104#define ARG_AUTORESTART "autorestart" 105#define ARG_WAKEONACCHANGE "acwake" 106#define ARG_REDUCEBRIGHT "lessbright" 107#define ARG_SLEEPUSESDIM "halfdim" 108#define ARG_MOTIONSENSOR "sms" 109#define ARG_MOTIONSENSOR2 "ams" 110#define ARG_TTYKEEPAWAKE "ttyskeepawake" 111#define ARG_GPU "gpuswitch" 112#define ARG_NETAVAILABLE "networkoversleep" 113#define ARG_DEEPSLEEP "standby" 114#define ARG_DEEPSLEEPDELAY "standbydelay" 115#define ARG_DARKWAKES "darkwakes" 116 117// Scheduling options 118#define ARG_SCHEDULE "schedule" 119#define ARG_SCHED "sched" 120#define ARG_REPEAT "repeat" 121#define ARG_CANCEL "cancel" 122#define ARG_RELATIVE "relative" 123//#define ARG_SLEEP "sleep" 124#define ARG_SHUTDOWN "shutdown" 125#define ARG_RESTART "restart" 126#define ARG_WAKE "wake" 127#define ARG_POWERON "poweron" 128#define ARG_WAKEORPOWERON "wakeorpoweron" 129 130// UPS options 131#define ARG_HALTLEVEL "haltlevel" 132#define ARG_HALTAFTER "haltafter" 133#define ARG_HALTREMAIN "haltremain" 134 135// get options 136#define ARG_CAP "cap" 137#define ARG_DISK "disk" 138#define ARG_CUSTOM "custom" 139#define ARG_LIVE "live" 140#define ARG_SCHED "sched" 141#define ARG_UPS "ups" 142#define ARG_SYS_PROFILES "profiles" 143#define ARG_ADAPTER_AC "ac" 144#define ARG_ADAPTER "adapter" 145#define ARG_BATT "batt" 146#define ARG_PS "ps" 147#define ARG_PSLOG "pslog" 148#define ARG_TRCOLUMNS "trcolumns" 149#define ARG_BATTRAW "rawbatt" 150#define ARG_PSRAW "rawlog" 151#define ARG_THERM "therm" 152#define ARG_THERMLOG "thermlog" 153#define ARG_ASSERTIONS "assertions" 154#define ARG_ASSERTIONSLOG "assertionslog" 155#define ARG_SYSLOAD "sysload" 156#define ARG_SYSLOADLOG "sysloadlog" 157#define ARG_USERACTIVITYLOG "useractivitylog" 158#define ARG_USERACTIVITY "useractivity" 159#define ARG_LOG "log" 160#define ARG_LISTEN "listen" 161#define ARG_HISTORY "history" 162#define ARG_HISTORY_DETAILED "historydetailed" 163#define ARG_HID_NULL "hidnull" 164#define ARG_BOOKMARK "bookmark" 165#define ARG_CLEAR_HISTORY "clearpmhistory" 166#define ARG_SEARCH "searchforuuid" 167#define ARG_USERCLIENTS "userclients" 168#define ARG_UUID "uuid" 169#define ARG_UUID_LOG "uuidlog" 170#define ARG_EVERYTHING "everything" 171#define ARG_PRINT_GETTERS "getters" 172#define ARG_POWERSTATE "powerstate" 173#define ARG_POWERSTATELOG "powerstatelog" 174#define ARG_RDSTATS "stats" 175#define ARG_SYSSTATE "systemstate" 176 177// special 178#define ARG_BOOT "boot" 179#define ARG_UNBOOT "unboot" 180#define ARG_POLLBOOT "readboot" 181#define ARG_POLLALL "readall" 182#define ARG_POLLUSER "readuser" 183#define ARG_FORCE "force" 184#define ARG_TOUCH "touch" 185#define ARG_NOIDLE "noidle" 186#define ARG_SLEEPNOW "sleepnow" 187#define ARG_DISPLAYSLEEPNOW "displaysleepnow" 188#define ARG_DEBUGTRIG "debugTrig" 189#define ARG_RESETDISPLAYAMBIENTPARAMS "resetdisplayambientparams" 190#define ARG_DISABLEASSERTION "disableassertion" 191#define ARG_ENABLEASSERTION "enableassertion" 192#define ARG_RDAP "rdap" 193#define ARG_DEBUGFLAGS "debugflags" 194#define ARG_BTINTERVAL "btinterval" 195#define ARG_DWLINTERVAL "dwlinterval" 196#define ARG_MT2BOOK "mt2book" 197#define ARG_SETSAAFLAGS "saaflags" 198#define ARG_NOPOLL "nopoll" 199 200// special system 201#define ARG_DISABLESLEEP "disablesleep" 202#define ARG_DISABLEFDEKEYSTORE "destroyfvkeyonstandby" 203 204// return values for parseArgs 205#define kParseSuccess 0 // success 206#define kParseBadArgs -1 // error 207#define kParseInternalError -2 // error 208 209// bitfield for tracking what's been modified in parseArgs() 210#define kModSettings (1<<0) 211#define kModProfiles (1<<1) 212#define kModUPSThresholds (1<<2) 213#define kModSched (1<<3) 214#define kModRepeat (1<<4) 215#define kModSystemSettings (1<<5) 216 217// return values for idleSettingsNotConsistent 218#define kInconsistentDisplaySetting 1 219#define kInconsistentDiskSetting 2 220#define kConsistentSleepSettings 0 221 222// day-of-week constants for repeating power events 223#define daily_mask ( kIOPMMonday | kIOPMTuesday | kIOPMWednesday \ 224 | kIOPMThursday | kIOPMFriday | kIOPMSaturday \ 225 | kIOPMSunday) 226#define weekday_mask ( kIOPMMonday | kIOPMTuesday | kIOPMWednesday \ 227 | kIOPMThursday | kIOPMFriday ) 228#define weekend_mask ( kIOPMSaturday | kIOPMSunday ) 229 230#define kDateAndTimeFormat "MM/dd/yy HH:mm:ss" 231#define kTimeFormat "HH:mm:ss" 232 233#define kMaxLongStringLength 255 234 235static const size_t kMaxArgStringLength = 49; 236 237#define kUSecPerSec 1000000.0 238 239 240#ifndef kPMPowerStatesChID 241#define kPMPowerStatesChID IOREPORT_MAKEID('P','M','S','t','H','i','s','t') 242#endif 243 244#ifndef kPMCurrStateChID 245#define kPMCurrStateChID IOREPORT_MAKEID('P','M','C','u','r','S','t','\0' ) 246#endif 247 248/* RootDomain IOReporting channels */ 249#define kSleepCntChID IOREPORT_MAKEID('S','l','e','e','p','C','n','t') 250#define kDarkWkCntChID IOREPORT_MAKEID('G','U','I','W','k','C','n','t') 251#define kUserWkCntChID IOREPORT_MAKEID('D','r','k','W','k','C','n','t') 252 253typedef struct { 254 const char *name; 255 const char *displayAs; 256} PMFeature; 257 258/* list of all features */ 259PMFeature all_features[] = 260{ 261 { kIOPMDisplaySleepKey, ARG_DISPLAYSLEEP }, 262 { kIOPMDiskSleepKey, ARG_DISKSLEEP }, 263 { kIOPMSystemSleepKey, ARG_SLEEP }, 264 { kIOPMWakeOnLANKey, ARG_WOMP }, 265 { kIOPMWakeOnRingKey, ARG_RING }, 266 { kIOPMWakeOnACChangeKey, ARG_WAKEONACCHANGE }, 267 { kIOPMRestartOnPowerLossKey, ARG_AUTORESTART }, 268 { kIOPMWakeOnClamshellKey, ARG_LIDWAKE }, 269 { kIOPMReduceBrightnessKey, ARG_REDUCEBRIGHT }, 270 { kIOPMDisplaySleepUsesDimKey, ARG_SLEEPUSESDIM }, 271 { kIOPMMobileMotionModuleKey, ARG_MOTIONSENSOR }, 272 { kIOPMGPUSwitchKey, ARG_GPU }, 273 { kIOPMDeepSleepEnabledKey, ARG_DEEPSLEEP }, 274 { kIOPMDeepSleepDelayKey, ARG_DEEPSLEEPDELAY }, 275 { kIOPMDarkWakeBackgroundTaskKey, ARG_DARKWAKES }, 276 { kIOPMTTYSPreventSleepKey, ARG_TTYKEEPAWAKE }, 277 { kIOHibernateModeKey, ARG_HIBERNATEMODE }, 278 { kIOHibernateFileKey, ARG_HIBERNATEFILE }, 279 { kIOPMAutoPowerOffEnabledKey, ARG_AUTOPOWEROFF }, 280 { kIOPMAutoPowerOffDelayKey, ARG_AUTOPOWEROFFDELAY } 281}; 282 283#define kNUM_PM_FEATURES (sizeof(all_features)/sizeof(PMFeature)) 284 285enum ArgumentType { 286 kApplyToBattery = 1, 287 kApplyToCharger = 2, 288 kApplyToUPS = 4, 289 kShowColumns = 8 290}; 291 292enum AssertionBitField { 293 kAssertionCPU = 1, 294 kAssertionInflow = 2, 295 kAssertionCharge = 4, 296 kAssertionIdle = 8 297}; 298 299// ack port for sleep/wake callback 300static io_connect_t gPMAckPort = MACH_PORT_NULL; 301 302 303enum SleepCallbackBehavior { 304 kLogSleepEvents = (1<<0), 305 kCancelSleepEvents = (1<<1) 306}; 307 308/* pmset commands */ 309enum PMCommandType { 310 kPMCommandSleepNow = 1, 311 kPMCommandTouch, 312 kPMCommandNoIdle, 313 kPMCommandDisplaySleepNow, 314 kPMCommandDebugTrig 315}; 316 317/* check and set int value multiplier */ 318enum { 319 kNoMultiplier = 0, 320 kMillisecondsMultiplier = 1000 321}; 322 323typedef struct { 324 CFStringRef who; 325 CFDateRef when; 326 CFStringRef which; 327} ScheduledEventReturnType; 328 329 330#define RING_SIZE 100 331typedef struct { 332 aslmsg msgRing[RING_SIZE]; 333 uint32_t readIdx; 334 uint32_t writeIdx; 335} MsgCache; 336 337MsgCache *msgCache = NULL; 338 339// function declarations 340static void usage(void); 341static IOReturn setRootDomainProperty(CFStringRef key, CFTypeRef val); 342static io_registry_entry_t copyRootDomainRef(void); 343static IOReturn _pm_connect(mach_port_t *newConnection); 344static IOReturn _pm_disconnect(mach_port_t connection); 345 346static void show_pm_settings_dict( 347 CFDictionaryRef d, 348 int indent, 349 bool log_overrides, 350 bool prune_unsupported); 351static void show_system_power_settings(void); 352static void show_supported_pm_features(void); 353static void show_custom_pm_settings(void); 354static void show_live_pm_settings(void); 355static void show_ups_settings(void); 356static void show_active_profiles(void); 357static void show_system_profiles(void); 358static void show_scheduled_events(void); 359static void show_active_assertions(uint32_t which); 360static void show_power_sources(int which); 361static bool prevent_idle_sleep(void); 362static void show_assertions(const char *); 363static void log_assertions(void); 364static void show_systemload(void); 365static void log_systemload(void); 366static void log_useractivitylog(void); 367static void log_useractivity(void); 368static void show_log(void); 369static void show_uuid(bool keep_running); 370static void listen_for_everything(void); 371static bool is_display_dim_captured(void); 372static void show_power_adapter(void); 373static void show_getters(void); 374static void show_power_state(char **argv); 375static void show_power_statelog(char **argv); 376static void show_rdStats(char **argv); 377static void show_sysstate(char **argv); 378static void show_everything(char **); 379 380static void show_power_event_history(void); 381static void show_power_event_history_detailed(void); 382static void set_new_power_bookmark(void); 383static void set_debugFlags(char **argv); 384static void set_btInterval(char **argv); 385static void set_dwlInterval(char **argv); 386static void set_saaFlags(char **argv); 387static void show_details_for_UUID(char **UUID_string); 388static void show_NULL_HID_events(void); 389static void show_root_domain_user_clients(void); 390static void mt2bookmark(void); 391static bool isBatteryPollingStopped(void); 392static void set_nopoll(void); 393 394static void print_pretty_date(CFAbsoluteTime t, bool newline); 395static void print_short_date(CFAbsoluteTime t, bool newline); 396static void print_date_with_style(const char *, CFDateFormatterStyle dayStyle, CFDateFormatterStyle timeStyle, CFAbsoluteTime t, bool newline); 397 398static void sleepWakeCallback( 399 void *refcon, 400 io_service_t y __unused, 401 natural_t messageType, 402 void * messageArgument); 403 404static void install_listen_for_notify_system_power(void); 405static void install_listen_PM_connection(void); 406static void install_listen_IORegisterForSystemPower(void); 407static void install_listen_com_apple_powermanagement_sleepservices_notify(void); 408 409static void log_ps_change_handler(void *); 410static int install_listen_for_power_sources(uintptr_t which); 411static int log_raw_power_source_changes(void); 412static void log_raw_battery_interest( 413 void *refcon, 414 io_service_t batt, 415 natural_t messageType, 416 void *messageArgument); 417static void log_raw_battery_match( 418 void *refcon, 419 io_iterator_t b_iter); 420 421static void log_thermal_events(void); 422static void show_systempower_notify(void); 423static void show_thermal_warning_level(void); 424static void show_thermal_cpu_power_level(void); 425 426static void print_raw_battery_state(io_registry_entry_t b_reg); 427static void print_setting_value(CFTypeRef a, int divider); 428static void print_override_pids(int assertion_type); 429static void print_time_of_day_to_buf(int m, char *buf, int buflen); 430static void print_days_to_buf(int d, char *buf, int buflen); 431static void print_repeating_report(CFDictionaryRef repeat); 432static void print_scheduled_report(CFArrayRef events); 433 434static CFDictionaryRef getPowerEvent(int type, CFDictionaryRef events); 435static int getRepeatingDictionaryMinutes(CFDictionaryRef event); 436static int getRepeatingDictionaryDayMask(CFDictionaryRef event); 437static CFStringRef getRepeatingDictionaryType(CFDictionaryRef event); 438static int arePowerSourceSettingsInconsistent(CFDictionaryRef set); 439static void checkSettingConsistency(CFDictionaryRef profiles); 440static ScheduledEventReturnType *scheduled_event_struct_create(void); 441static void scheduled_event_struct_destroy(ScheduledEventReturnType *); 442static void string_tolower(char *lower_me, char *dst); 443static void string_toupper(char *upper_me, char *dst); 444static int checkAndSetIntValue( 445 char *valstr, 446 CFStringRef settingKey, 447 int apply, 448 int isOnOffSetting, 449 int multiplier, 450 CFMutableDictionaryRef ac, 451 CFMutableDictionaryRef batt, 452 CFMutableDictionaryRef ups); 453static int setUPSValue( 454 char *valstr, 455 CFStringRef whichUPS, 456 CFStringRef settingKey, 457 int apply, 458 CFMutableDictionaryRef thresholds); 459static int parseScheduledEvent( 460 char **argv, 461 int *num_args_parsed, 462 ScheduledEventReturnType *local_scheduled_event, 463 bool *cancel_scheduled_event, 464 bool is_relative_event); 465static int parseRepeatingEvent( 466 char **argv, 467 int *num_args_parsed, 468 CFMutableDictionaryRef local_repeating_event, 469 bool *local_cancel_repeating); 470static int parseArgs( 471 int argc, 472 char* argv[], 473 CFDictionaryRef *settings, 474 int *modified_power_sources, 475 bool *force_activate_settings, 476 CFDictionaryRef *active_profiles, 477 CFDictionaryRef *system_power_settings, 478 CFDictionaryRef *ups_thresholds, 479 ScheduledEventReturnType **scheduled_event, 480 bool *cancel_scheduled_event, 481 CFDictionaryRef *repeating_event, 482 bool *cancel_repeating_event, 483 uint32_t *pmCmd); 484static void displaySleepNow(); 485static void swd_debugTrig(); 486 487static const char *getCanonicalArgForSynonym(char *pass) 488{ 489 if (!pass || 0 == strlen(pass)) 490 return ARG_LIVE; 491 if (!strncmp(ARG_DISK, pass, kMaxArgStringLength)) 492 return ARG_CUSTOM; 493 if (!strncmp(ARG_ADAPTER_AC, pass, kMaxArgStringLength)) 494 return ARG_ADAPTER; 495 if (!strncmp(ARG_BATT, pass, kMaxArgStringLength)) 496 return ARG_PS; 497 return pass; 498} 499 500typedef enum { 501 kActionGetOnceNoArgs, 502 kActionGetLog, 503 kActionRecursiveBeCareful 504} CommandActionType; 505 506typedef struct { 507 CommandActionType actionType; 508 const char *arg; 509 void (^action)(char **); 510} CommandAndAction; 511 512static CommandAndAction the_getters[] = 513 { 514 {kActionGetOnceNoArgs, ARG_LIVE, ^(char **arg){ show_system_power_settings(); show_active_profiles(); show_live_pm_settings();}}, 515 {kActionGetOnceNoArgs, ARG_CUSTOM, ^(char **arg){ show_custom_pm_settings(); }}, 516 {kActionGetOnceNoArgs, ARG_CAP, ^(char **arg){ show_supported_pm_features(); }}, 517 {kActionGetOnceNoArgs, ARG_SCHED, ^(char **arg){ show_scheduled_events(); }}, 518 {kActionGetOnceNoArgs, ARG_UPS, ^(char **arg){ show_ups_settings(); }}, 519 {kActionGetOnceNoArgs, ARG_SYS_PROFILES, ^(char **arg){ show_active_profiles(); show_system_profiles(); }}, 520 {kActionGetOnceNoArgs, ARG_ADAPTER, ^(char **arg){ show_power_adapter(); }}, 521 {kActionGetOnceNoArgs, ARG_PS, ^(char **arg){ show_power_sources(kApplyToBattery | kApplyToUPS); }}, 522 {kActionGetLog, ARG_PSLOG, ^(char **arg){ install_listen_IORegisterForSystemPower(); 523 install_listen_for_power_sources(kApplyToBattery | kApplyToUPS); 524 CFRunLoopRun(); }}, 525 {kActionGetLog, ARG_TRCOLUMNS, ^(char **arg){ install_listen_IORegisterForSystemPower(); 526 install_listen_for_power_sources(kShowColumns); 527 CFRunLoopRun(); }}, 528 {kActionGetLog, ARG_PSRAW, ^(char **arg){ log_raw_power_source_changes(); }}, 529 {kActionGetOnceNoArgs, ARG_BATTRAW, ^(char **arg){ print_raw_battery_state(IO_OBJECT_NULL); }}, 530 {kActionGetOnceNoArgs, ARG_THERM, ^(char **arg){ show_thermal_warning_level(); show_thermal_cpu_power_level(); }}, 531 {kActionGetLog, ARG_THERMLOG, ^(char **arg){ log_thermal_events(); }}, 532 {kActionGetOnceNoArgs, ARG_ASSERTIONS, ^(char **arg){ show_assertions(NULL); }}, 533 {kActionGetLog, ARG_ASSERTIONSLOG, ^(char **arg){ log_assertions(); }}, 534 {kActionGetOnceNoArgs, ARG_SYSLOAD, ^(char **arg){ show_systemload(); }}, 535 {kActionGetLog, ARG_SYSLOADLOG, ^(char **arg){ log_systemload(); }}, 536 {kActionGetLog, ARG_USERACTIVITYLOG,^(char **arg){ log_useractivitylog(); }}, 537 {kActionGetOnceNoArgs, ARG_USERACTIVITY ,^(char **arg){ log_useractivity(); }}, 538 {kActionGetOnceNoArgs, ARG_LOG, ^(char **arg){ show_log(); }}, 539 {kActionGetLog, ARG_LISTEN, ^(char **arg){ listen_for_everything(); }}, 540 {kActionGetOnceNoArgs, ARG_HISTORY, ^(char **arg){ show_power_event_history(); }}, 541 {kActionGetOnceNoArgs, ARG_HISTORY_DETAILED, ^(char **arg){ show_power_event_history_detailed(); }}, 542 {kActionGetOnceNoArgs, ARG_HID_NULL, ^(char **arg){ show_NULL_HID_events(); }}, 543 {kActionGetOnceNoArgs, ARG_USERCLIENTS, ^(char **arg){ show_root_domain_user_clients(); }}, 544 {kActionGetOnceNoArgs, ARG_UUID, ^(char **arg){ show_uuid(kActionGetOnceNoArgs); }}, 545 {kActionGetLog, ARG_UUID_LOG, ^(char **arg){ show_uuid(kActionGetLog); }}, 546 {kActionGetOnceNoArgs, ARG_PRINT_GETTERS, ^(char **arg){ show_getters(); }}, 547 {kActionGetLog, ARG_SEARCH, ^(char **arg){show_details_for_UUID(arg); }}, 548 {kActionGetOnceNoArgs, ARG_POWERSTATE, ^(char **arg){show_power_state(arg); }}, 549 {kActionGetLog, ARG_POWERSTATELOG, ^(char **arg){show_power_statelog(arg); }}, 550 {kActionGetOnceNoArgs, ARG_RDSTATS, ^(char **arg){show_rdStats(arg); }}, 551 {kActionGetOnceNoArgs, ARG_SYSSTATE, ^(char **arg){show_sysstate(arg); }}, 552 {kActionRecursiveBeCareful, ARG_EVERYTHING, ^(char **arg){ show_everything(arg); }} 553 }; 554 555 556static const int the_getters_count = (sizeof(the_getters) / sizeof(CommandAndAction)); 557 558 559//**************************** 560//**************************** 561//**************************** 562 563static void usage(void) 564{ 565 printf("Usage: pmset <options>\n"); 566 printf("See pmset(1) for details: \'man pmset\'\n"); 567} 568 569 570 571int main(int argc, char *argv[]) { 572 IOReturn ret, ret1, err; 573 io_connect_t fb; 574 CFDictionaryRef es_custom_settings = 0; 575 int modified_power_sources = 0; 576 bool force_it = 0; 577 CFDictionaryRef ups_thresholds = 0; 578 CFDictionaryRef system_power_settings = 0; 579 CFDictionaryRef active_profiles = 0; 580 ScheduledEventReturnType *scheduled_event_return = 0; 581 bool cancel_scheduled_event = 0; 582 CFDictionaryRef repeating_event_return = 0; 583 bool cancel_repeating_event = 0; 584 uint32_t pmCommand = 0; 585 586 ret = parseArgs(argc, argv, 587 &es_custom_settings, &modified_power_sources, &force_it, 588 &active_profiles, 589 &system_power_settings, 590 &ups_thresholds, 591 &scheduled_event_return, &cancel_scheduled_event, 592 &repeating_event_return, &cancel_repeating_event, 593 &pmCommand); 594 595 if(ret == kParseBadArgs) 596 { 597 //printf("pmset: error in parseArgs!\n"); 598 usage(); 599 exit(1); 600 } 601 602 if(ret == kParseInternalError) 603 { 604 fprintf(stderr, "%s: internal error!\n", argv[0]); fflush(stdout); 605 exit(1); 606 } 607 608 switch ( pmCommand ) 609 { 610 /*************** Sleep now *************************************/ 611 case kPMCommandSleepNow: 612 fb = IOPMFindPowerManagement(MACH_PORT_NULL); 613 if ( MACH_PORT_NULL != fb ) { 614 err = IOPMSleepSystem ( fb ); 615 616 if( kIOReturnNotPrivileged == err ) 617 { 618 printf("Sleep error 0x%08x; You must run this as root.\n", err); 619 exit(EX_NOPERM); 620 } else if ( (MACH_PORT_NULL == fb) || (kIOReturnSuccess != err) ) 621 { 622 printf("Unable to sleep system: error 0x%08x\n", err); 623 exit(EX_OSERR); 624 } else { 625 printf("Sleeping now...\n"); 626 } 627 } 628 629 return 0; 630 631 /*************** Display Sleep now *************************************/ 632 case kPMCommandDisplaySleepNow: 633 displaySleepNow(); 634 break; 635 636 case kPMCommandDebugTrig: 637 swd_debugTrig(); 638 break; 639 640 /*************** Touch settings *************************************/ 641 case kPMCommandTouch: 642 printf("touching prefs file on disk...\n"); 643 644 ret = IOPMSetPMPreferences(NULL); 645 if(kIOReturnSuccess != ret) 646 { 647 printf("\'%s\' must be run as root...\n", argv[0]); 648 } 649 650 return 0; 651 652 /*************** Prevent idle sleep **********************************/ 653 case kPMCommandNoIdle: 654 if(!prevent_idle_sleep()) 655 { 656 printf("Error preventing idle sleep\n"); 657 } 658 return 1; 659 660 default: 661 // If no command is specified, execution continues with processing 662 // other command-line arguments 663 break; 664 } 665 666 if(force_it && es_custom_settings) 667 { 668 669 mach_port_t pm_server = MACH_PORT_NULL; 670 CFDataRef settings_data; 671 int32_t return_code; 672 kern_return_t kern_result; 673 674 /* 675 * Step 1 - send these forced settings over to powerd. 676 * 677 */ 678 err = _pm_connect(&pm_server); 679 if (kIOReturnSuccess == err) { 680 settings_data = IOCFSerialize(es_custom_settings, 0); 681 682 if (settings_data) 683 { 684 kern_result = io_pm_force_active_settings( 685 pm_server, 686 (vm_offset_t)CFDataGetBytePtr(settings_data), 687 CFDataGetLength(settings_data), 688 &return_code); 689 690 if( KERN_SUCCESS != kern_result ) { 691 printf("exit kern_result = 0x%08x\n", kern_result); 692 } 693 if( kIOReturnSuccess != return_code ) { 694 printf("exit return_code = 0x%08x\n", return_code); 695 } 696 697 CFRelease(settings_data); 698 699 if (KERN_SUCCESS != kern_result || kIOReturnSuccess != return_code) { 700 exit(1); 701 } 702 } 703 _pm_disconnect(pm_server); 704 } 705 706 /* 707 * Step 2 - this code might be running in a partilially uninitialized OS, 708 * and powerd might not be running. e.g. at Installer context. 709 * Since powerd may not be running, we also activate these settings directly 710 * to the controlling drivers in the kernel. 711 * 712 */ 713 CFTypeRef powersources = IOPSCopyPowerSourcesInfo(); 714 CFStringRef activePowerSource = NULL; 715 CFDictionaryRef useSettings = NULL; 716 if (powersources) { 717 activePowerSource = IOPSGetProvidingPowerSourceType(powersources); 718 if (!activePowerSource) { 719 activePowerSource = CFSTR(kIOPMACPowerKey); 720 } 721 useSettings = CFDictionaryGetValue(es_custom_settings, activePowerSource); 722 if (useSettings) { 723 ActivatePMSettings(useSettings, true); 724 } 725 CFRelease(powersources); 726 } 727 728 // Return here. If this is a 'force' call we do _not_ want 729 // to attempt to write any settings to the disk, or to try anything 730 // else at all, as our environment may be unwritable / diskless 731 // (booted from install CD) 732 return 0; 733 } 734 735 if(es_custom_settings) 736 { 737 CFNumberRef neg1 = NULL; 738 int tmp_int = -1; 739 CFDictionaryRef tmp_dict = NULL; 740 CFMutableDictionaryRef customize_active_profiles = NULL; 741 742 // Send pmset changes out to disk 743 if(kIOReturnSuccess != (ret1 = IOPMSetPMPreferences(es_custom_settings))) 744 { 745 if(ret1 == kIOReturnNotPrivileged) 746 { 747 printf("\'%s\' must be run as root...\n", argv[0]); 748 } else { 749 printf("Error 0x%08x writing Energy Saver preferences to disk\n", ret1); 750 } 751 exit(1); 752 } 753 754 // Also need to change the active profile to -1 (Custom) 755 // We assume the user intended to activate these new custom settings. 756 neg1 = CFNumberCreate(0, kCFNumberIntType, &tmp_int); 757 tmp_dict = IOPMCopyActivePowerProfiles(); 758 if(!tmp_dict) { 759 printf("Custom profile set; unable to update active profile to -1.\n"); 760 exit(1); 761 } 762 customize_active_profiles = CFDictionaryCreateMutableCopy(0, 0, tmp_dict); 763 if(!customize_active_profiles) { 764 printf("Internal error\n"); 765 exit(1); 766 } 767 // For each power source we modified settings for, flip that 768 // source's profile to -1 769 if(modified_power_sources & kApplyToCharger) { 770 CFDictionarySetValue( customize_active_profiles, 771 CFSTR(kIOPMACPowerKey), neg1); 772 } 773 if(modified_power_sources & kApplyToBattery) { 774 CFDictionarySetValue( customize_active_profiles, 775 CFSTR(kIOPMBatteryPowerKey), neg1); 776 } 777 if(modified_power_sources & kApplyToUPS) { 778 CFDictionarySetValue( customize_active_profiles, 779 CFSTR(kIOPMUPSPowerKey), neg1); 780 } 781 782 ret = IOPMSetActivePowerProfiles(customize_active_profiles); 783 if(kIOReturnSuccess != ret) { 784 printf("Error 0x%08x writing customized power profiles to disk\n", ret); 785 exit(1); 786 } 787 CFRelease(neg1); 788 CFRelease(tmp_dict); 789 CFRelease(customize_active_profiles); 790 791 792 // Print a warning to stderr if idle sleep settings won't 793 // produce expected result; i.e. sleep < (display | dim) 794 checkSettingConsistency(es_custom_settings); 795 CFRelease(es_custom_settings); 796 } 797 798 if(active_profiles) 799 { 800 ret = IOPMSetActivePowerProfiles(active_profiles); 801 if(kIOReturnSuccess != ret) { 802 printf("Error 0x%08x writing active power profiles to disk\n", ret); 803 exit(1); 804 } 805 806 CFRelease(active_profiles); 807 } 808 809 if(system_power_settings) 810 { 811 int iii; 812 int sys_setting_count = 0; 813 814 if( isA_CFDictionary(system_power_settings)) { 815 sys_setting_count = CFDictionaryGetCount(system_power_settings); 816 } 817 818 if (0 != sys_setting_count) 819 { 820 CFStringRef *keys = malloc(sizeof(CFStringRef) * sys_setting_count); 821 CFTypeRef *vals = malloc(sizeof(CFTypeRef) * sys_setting_count); 822 823 if(keys && vals) 824 { 825 CFDictionaryGetKeysAndValues( system_power_settings, 826 (const void **)keys, (const void **)vals); 827 828 for(iii=0; iii<sys_setting_count; iii++) 829 { 830 // We write the settings to disk here; PM configd picks them up and 831 // sends them to xnu from configd space. 832 ret = IOPMSetSystemPowerSetting(keys[iii], vals[iii]); 833 if(kIOReturnNotPrivileged == ret) 834 { 835 printf("\'%s\' must be run as root...\n", argv[0]); 836 } 837 else if (kIOReturnSuccess != ret) 838 { 839 printf("\'%s\' failed to set the value.\n", argv[0]); 840 } 841 } 842 } 843 844 if (keys) free (keys); 845 if (vals) free (vals); 846 } 847 848 CFRelease(system_power_settings); 849 } 850 851 // Did the user change UPS settings too? 852 if(ups_thresholds) 853 { 854 // Only write out UPS settings if thresholds were changed. 855 // * UPS sleep timers & energy settings have already been 856 // written with IOPMSetPMPreferences() regardless. 857 ret1 = IOPMSetUPSShutdownLevels( 858 CFSTR(kIOPMDefaultUPSThresholds), 859 ups_thresholds); 860 if(kIOReturnSuccess != ret1) 861 { 862 if(ret1 == kIOReturnNotPrivileged) 863 printf("\'%s\' must be run as root...\n", argv[0]); 864 if(ret1 == kIOReturnError 865 || ret1 == kIOReturnBadArgument) 866 printf("Error writing UPS preferences to disk\n"); 867 exit(1); 868 } 869 CFRelease(ups_thresholds); 870 } 871 872 873 if(scheduled_event_return) 874 { 875 if(cancel_scheduled_event) 876 { 877 // cancel the event described by scheduled_event_return 878 ret = IOPMCancelScheduledPowerEvent( 879 scheduled_event_return->when, 880 scheduled_event_return->who, 881 scheduled_event_return->which); 882 } else { 883 ret = IOPMSchedulePowerEvent( 884 scheduled_event_return->when, 885 scheduled_event_return->who, 886 scheduled_event_return->which); 887 } 888 889 if(kIOReturnNotPrivileged == ret) { 890 fprintf(stderr, "%s: This operation must be run as root\n", argv[0]); 891 fflush(stderr); 892 exit(1); 893 } 894 if(kIOReturnSuccess != ret) { 895 fprintf(stderr, "%s: Error in scheduling operation\n", argv[0]); 896 fflush(stderr); 897 exit(1); 898 } 899 900 // free individual members 901 scheduled_event_struct_destroy(scheduled_event_return); 902 } 903 904 if(cancel_repeating_event) 905 { 906 ret = IOPMCancelAllRepeatingPowerEvents(); 907 if(kIOReturnSuccess != ret) { 908 if(kIOReturnNotPrivileged == ret) { 909 fprintf(stderr, "pmset: Must be run as root to modify settings\n"); 910 } else { 911 fprintf(stderr, "pmset: Error 0x%08x cancelling repeating events\n", ret); 912 } 913 fflush(stderr); 914 exit(1); 915 } 916 } 917 918 if(repeating_event_return) 919 { 920 ret = IOPMScheduleRepeatingPowerEvent(repeating_event_return); 921 if(kIOReturnSuccess != ret) { 922 if(kIOReturnNotPrivileged == ret) { 923 fprintf(stderr, "pmset: Must be run as root to modify settings\n"); 924 } else { 925 fprintf(stderr, "pmset: Error 0x%08x scheduling repeating events\n", ret); 926 } 927 fflush(stderr); 928 exit(1); 929 } 930 CFRelease(repeating_event_return); 931 } 932 933 934 return 0; 935} 936 937//**************************** 938//**************************** 939//**************************** 940 941 942io_registry_entry_t _getRootDomain(void) 943{ 944 static io_registry_entry_t gRoot = MACH_PORT_NULL; 945 946 if (MACH_PORT_NULL == gRoot) 947 gRoot = IORegistryEntryFromPath( kIOMasterPortDefault, 948 kIOPowerPlane ":/IOPowerConnection/IOPMrootDomain"); 949 950 return gRoot; 951} 952 953 954static void swd_debugTrig() 955{ 956 io_service_t rootDomainService = IO_OBJECT_NULL; 957 io_connect_t gRootDomainConnect = IO_OBJECT_NULL; 958 kern_return_t kr = 0; 959 IOReturn ret; 960 961 // Find it 962 rootDomainService = _getRootDomain(); 963 if (IO_OBJECT_NULL == rootDomainService) { 964 goto exit; 965 } 966 967 // Open it 968 kr = IOServiceOpen(rootDomainService, mach_task_self(), 0, &gRootDomainConnect); 969 if (KERN_SUCCESS != kr) { 970 printf("Failed to connect to rootDomain. rc=0x%x\n", kr); 971 goto exit; 972 } 973 974 ret = IOConnectCallMethod(gRootDomainConnect, kPMSleepWakeDebugTrig, 975 NULL, 0, 976 NULL, 0, NULL, 977 NULL, NULL, NULL); 978 979 if (kIOReturnSuccess != ret) 980 { 981 printf("Failed to trigger a sleep wake kernel log collection. rc=0x%x\n", ret); 982 goto exit; 983 } 984 985exit: 986 if (IO_OBJECT_NULL != gRootDomainConnect) 987 IOServiceClose(gRootDomainConnect); 988 return; 989 990} 991 992 993static void displaySleepNow() 994{ 995 io_registry_entry_t disp_wrangler = IO_OBJECT_NULL; 996 kern_return_t kr; 997 998 disp_wrangler = IORegistryEntryFromPath( 999 kIOMasterPortDefault, 1000 kIOServicePlane ":/IOResources/IODisplayWrangler"); 1001 if(disp_wrangler == IO_OBJECT_NULL) 1002 return ; 1003 1004 kr = IORegistryEntrySetCFProperty( disp_wrangler, CFSTR("IORequestIdle"),kCFBooleanTrue); 1005 1006 if(kr) 1007 fprintf(stderr, "pmset: Failed to set the display to sleep(err:0x%x)\n", kr); 1008 1009 IOObjectRelease(disp_wrangler); 1010 1011 return ; 1012 1013} 1014 1015static CFTypeRef copyRootDomainProperty(CFStringRef key) 1016{ 1017 static io_object_t rd = IO_OBJECT_NULL; 1018 1019 if (IO_OBJECT_NULL == rd) { 1020 rd = copyRootDomainRef(); 1021 } 1022 1023 return IORegistryEntryCreateCFProperty(rd, key, 0, 0); 1024} 1025 1026static IOReturn setRootDomainProperty(CFStringRef key, CFTypeRef val) 1027{ 1028 io_registry_entry_t root_domain = copyRootDomainRef(); 1029 IOReturn ret; 1030 1031 if(!root_domain) return kIOReturnError; 1032 1033 ret = IORegistryEntrySetCFProperty(root_domain, key, val); 1034 1035 IOObjectRelease(root_domain); 1036 return ret; 1037} 1038 1039static io_registry_entry_t copyRootDomainRef(void) 1040{ 1041 return (io_registry_entry_t)IOServiceGetMatchingService( 1042 MACH_PORT_NULL, IOServiceNameMatching("IOPMrootDomain")); 1043 } 1044 1045static void print_setting_value(CFTypeRef a, int divider) 1046{ 1047 int n; 1048 1049 if(isA_CFNumber(a)) 1050 { 1051 CFNumberGetValue(a, kCFNumberIntType, (void *)&n); 1052 1053 if( 0 != divider ) n/=divider; 1054 1055 printf("%d", n); 1056 } else if(isA_CFBoolean(a)) 1057 { 1058 printf("%d", CFBooleanGetValue(a)); 1059 } else if(isA_CFString(a)) 1060 { 1061 char buf[100]; 1062 if(CFStringGetCString(a, buf, 100, kCFStringEncodingUTF8)) 1063 { 1064 printf("%s", buf); 1065 } 1066 } else printf("oops - print_setting_value unknown data type\n"); 1067} 1068 1069// Arguments to print_override_pids 1070enum { 1071 _kIOPMAssertionDisplayOn = 5, 1072 _kIOPMAssertionSystemOn = 6 1073}; 1074 1075static void show_pm_settings_dict( 1076 CFDictionaryRef d, 1077 int indent, 1078 bool show_overrides, 1079 bool prune_unsupported) 1080{ 1081 int count; 1082 int i; 1083 int j; 1084 int divider = 0; 1085 char ps[kMaxArgStringLength]; 1086 CFStringRef *keys; 1087 CFTypeRef *vals; 1088 CFTypeRef ps_blob; 1089 CFStringRef activeps = NULL; 1090 int show_override_type = 0; 1091 bool show_display_dim = false; 1092 1093 ps_blob = IOPSCopyPowerSourcesInfo(); 1094 if(ps_blob) { 1095 activeps = IOPSGetProvidingPowerSourceType(ps_blob); 1096 } 1097 if(!activeps) activeps = CFSTR(kIOPMACPowerKey); 1098 if(activeps) CFRetain(activeps); 1099 1100 count = CFDictionaryGetCount(d); 1101 keys = (CFStringRef *)malloc(count * sizeof(CFStringRef)); 1102 vals = (CFTypeRef *)malloc(count * sizeof(CFTypeRef)); 1103 if(!keys || !vals) 1104 goto exit; 1105 CFDictionaryGetKeysAndValues(d, (const void **)keys, (const void **)vals); 1106 1107 for(i=0; i<count; i++) 1108 { 1109 show_override_type = 0; 1110 1111 if (!CFStringGetCString(keys[i], ps, sizeof(ps), kCFStringEncodingMacRoman)) 1112 continue; 1113 1114 if( prune_unsupported 1115 && !IOPMFeatureIsAvailable(keys[i], CFSTR(kIOPMACPowerKey)) ) 1116 { 1117 // unsupported setting for the current power source! 1118 // do not show it! 1119 continue; 1120 } 1121 1122 for(j=0; j<indent;j++) printf(" "); 1123 1124 divider = 0; 1125 1126 if (strcmp(ps, kIOPMPrioritizeNetworkReachabilityOverSleepKey) == 0) 1127 { 1128 printf(" %-20s ", ARG_NETAVAILABLE); 1129 } else if (strcmp(ps, kIOPMDisplaySleepKey) == 0) { 1130 printf(" %-20s ", "displaysleep"); 1131 if(show_overrides) { 1132 show_override_type = _kIOPMAssertionDisplayOn; 1133 } 1134 show_display_dim = true; 1135 } else if (strcmp(ps, kIOPMSystemSleepKey) == 0) { 1136 printf(" %-20s ", "sleep"); 1137 if(show_overrides) { 1138 show_override_type = _kIOPMAssertionSystemOn; 1139 } 1140 } else { 1141 for(j=0; j<kNUM_PM_FEATURES; j++) { 1142 if (!strncmp(ps, all_features[j].name, kMaxArgStringLength)) { 1143 printf(" %-20s ", all_features[j].displayAs); 1144 break; 1145 } 1146 } 1147 if (j==kNUM_PM_FEATURES) 1148 printf(" %-20s ",ps); 1149 } 1150 1151 print_setting_value(vals[i], divider); 1152 1153 if(show_override_type) 1154 print_override_pids(show_override_type); 1155 if(show_display_dim) { 1156 if( is_display_dim_captured() ) 1157 printf(" (Graphics dim captured)"); 1158 show_display_dim = false; 1159 } 1160 printf("\n"); 1161 } 1162 1163exit: 1164 if (ps_blob) CFRelease(ps_blob); 1165 if (activeps) CFRelease(activeps); 1166 free(keys); 1167 free(vals); 1168} 1169 1170static void show_system_power_settings(void) 1171{ 1172 CFDictionaryRef system_power_settings = NULL; 1173 CFBooleanRef b; 1174 1175 system_power_settings = IOPMCopySystemPowerSettings(); 1176 if(!isA_CFDictionary(system_power_settings)) { 1177 goto exit; 1178 } 1179 1180 printf("System-wide power settings:\n"); 1181 1182 if((b = CFDictionaryGetValue(system_power_settings, kIOPMSleepDisabledKey))) 1183 { 1184 printf(" SleepDisabled\t\t%d\n", (b==kCFBooleanTrue) ? 1:0); 1185 } 1186 1187 if((b = CFDictionaryGetValue(system_power_settings, CFSTR(kIOPMDestroyFVKeyOnStandbyKey)))) 1188 { 1189 printf(" DestroyFVKeyOnStandby\t\t%d\n", (b==kCFBooleanTrue) ? 1:0); 1190 } 1191exit: 1192 if (system_power_settings) 1193 CFRelease(system_power_settings); 1194} 1195 1196 1197 1198static void print_override_pids(int assertionType) 1199{ 1200 CFDictionaryRef assertions_pids = NULL; 1201 CFDictionaryRef assertions_state = NULL; 1202 CFNumberRef assertion_value; 1203 IOReturn ret; 1204 char display_string[kMaxLongStringLength] = "\0"; 1205 int length = 0; 1206 int bgTaskLevel = 0, pushTaskLevel = 0, preventSleepLevel = 0; 1207 int proxyLevel = 0; 1208 1209 /* 1210 * Early pre-screening - don't dive into the assertions data 1211 * unless we know that there's an active assertion somewhere in there. 1212 */ 1213 1214 ret = IOPMCopyAssertionsStatus(&assertions_state); 1215 if( (kIOReturnSuccess != ret) || !isA_CFDictionary(assertions_state)) { 1216 goto bail; 1217 } 1218 1219 if (_kIOPMAssertionDisplayOn == assertionType) 1220 { 1221 int userIdleLevel = 0; 1222 int noDisplayLevel = 0; 1223 int displayWake = 0; 1224 1225 assertion_value = CFDictionaryGetValue(assertions_state, kIOPMAssertionTypePreventUserIdleDisplaySleep); 1226 if(assertion_value) 1227 CFNumberGetValue(assertion_value, kCFNumberIntType, &userIdleLevel); 1228 1229 assertion_value = CFDictionaryGetValue(assertions_state, kIOPMAssertionTypeNoDisplaySleep); 1230 if(assertion_value) 1231 CFNumberGetValue(assertion_value, kCFNumberIntType, &noDisplayLevel); 1232 1233 assertion_value = CFDictionaryGetValue(assertions_state, kIOPMAssertDisplayWake); 1234 if(assertion_value) 1235 CFNumberGetValue(assertion_value, kCFNumberIntType, &displayWake); 1236 1237 if ((kIOPMAssertionLevelOff == userIdleLevel) 1238 && (kIOPMAssertionLevelOff == noDisplayLevel) 1239 && (kIOPMAssertionLevelOff == displayWake)) 1240 { 1241 goto bail; 1242 } 1243 snprintf(display_string, kMaxLongStringLength, " (display sleep prevented by "); 1244 length = strlen(display_string); 1245 } 1246 1247 1248 if (_kIOPMAssertionSystemOn == assertionType) 1249 { 1250 int noIdleLevel = 0; 1251 int userIdleLevel = 0; 1252 1253 assertion_value = CFDictionaryGetValue(assertions_state, kIOPMAssertionTypeNoIdleSleep); 1254 if(assertion_value) 1255 CFNumberGetValue(assertion_value, kCFNumberIntType, &noIdleLevel); 1256 1257 assertion_value = CFDictionaryGetValue(assertions_state, kIOPMAssertionTypePreventSystemSleep); 1258 if(assertion_value) 1259 CFNumberGetValue(assertion_value, kCFNumberIntType, &preventSleepLevel); 1260 1261 assertion_value = CFDictionaryGetValue(assertions_state, kIOPMAssertionTypePreventUserIdleSystemSleep); 1262 if(assertion_value) 1263 CFNumberGetValue(assertion_value, kCFNumberIntType, &userIdleLevel); 1264 1265 assertion_value = CFDictionaryGetValue(assertions_state, kIOPMAssertionTypeBackgroundTask); 1266 if(assertion_value) 1267 CFNumberGetValue(assertion_value, kCFNumberIntType, &bgTaskLevel); 1268 1269 assertion_value = CFDictionaryGetValue(assertions_state, kIOPMAssertInternalPreventSleep); 1270 if(assertion_value) 1271 CFNumberGetValue(assertion_value, kCFNumberIntType, &proxyLevel); 1272 1273 assertion_value = CFDictionaryGetValue(assertions_state, kIOPMAssertionTypeApplePushServiceTask); 1274 if(assertion_value) 1275 CFNumberGetValue(assertion_value, kCFNumberIntType, &pushTaskLevel); 1276 if ((kIOPMAssertionLevelOff == noIdleLevel) 1277 && (kIOPMAssertionLevelOff == preventSleepLevel) 1278 && (kIOPMAssertionLevelOff == bgTaskLevel) 1279 && (kIOPMAssertionLevelOff == pushTaskLevel) 1280 && (kIOPMAssertionLevelOff == userIdleLevel)) 1281 { 1282 goto bail; 1283 } 1284 1285 snprintf(display_string, kMaxLongStringLength, " (sleep prevented by "); 1286 length = strlen(display_string); 1287 } 1288 1289 1290 /* 1291 * Find out which pids have asserted this and print 'em out 1292 * We conclude that at least one pid is forcing a relevant assertion. 1293 */ 1294 CFNumberRef *pids = NULL; 1295 CFArrayRef *assertions = NULL; 1296 int process_count; 1297 int this_is_the_first = 1; 1298 int i; 1299 1300 1301 ret = IOPMCopyAssertionsByProcess(&assertions_pids); 1302 if( (kIOReturnSuccess != ret) || !isA_CFDictionary(assertions_pids) ) { 1303 goto bail; 1304 } 1305 1306 1307 process_count = CFDictionaryGetCount(assertions_pids); 1308 pids = malloc(sizeof(CFNumberRef)*process_count); 1309 assertions = malloc(sizeof(CFArrayRef)*process_count); 1310 CFDictionaryGetKeysAndValues(assertions_pids, 1311 (const void **)pids, 1312 (const void **)assertions); 1313 for(i=0; i<process_count; i++) 1314 { 1315 int j; 1316 1317 for(j=0; j<CFArrayGetCount(assertions[i]); j++) 1318 { 1319 CFDictionaryRef tmp_assertion = NULL; 1320 CFNumberRef tmp_level = NULL; 1321 CFStringRef tmp_type = NULL; 1322 CFStringRef process_name = NULL; 1323 char pnameBuf[kProcNameBufLen]; 1324 int level = kIOPMAssertionLevelOff; 1325 bool print_this_pid = false; 1326 1327 tmp_assertion = CFArrayGetValueAtIndex(assertions[i], j); 1328 1329 if (!tmp_assertion || (kCFBooleanFalse == (CFBooleanRef)tmp_assertion)) 1330 { 1331 continue; 1332 } 1333 1334 if ( (tmp_type = CFDictionaryGetValue(tmp_assertion, kIOPMAssertionTrueTypeKey)) == NULL) 1335 tmp_type = CFDictionaryGetValue(tmp_assertion, kIOPMAssertionTypeKey); 1336 tmp_level = CFDictionaryGetValue(tmp_assertion, kIOPMAssertionLevelKey); 1337 process_name = CFDictionaryGetValue(tmp_assertion, CFSTR("Process Name")); 1338 1339 level = kIOPMAssertionLevelOff; 1340 if (tmp_level) { 1341 CFNumberGetValue(tmp_level, kCFNumberIntType, &level); 1342 } 1343 1344 if (level != kIOPMAssertionLevelOn) continue; 1345 1346 if (_kIOPMAssertionSystemOn == assertionType) { 1347 if (CFEqual(tmp_type, kIOPMAssertionTypePreventUserIdleSystemSleep)) { 1348 /* Found an assertion that keeps the system on */ 1349 print_this_pid = true; 1350 } 1351 else if ( (preventSleepLevel) && 1352 (CFEqual(tmp_type, kIOPMAssertionTypePreventSystemSleep)) ) { 1353 print_this_pid = true; 1354 } 1355 else if ( (bgTaskLevel) && 1356 (CFEqual(tmp_type, kIOPMAssertionTypeBackgroundTask)) ) 1357 { 1358 print_this_pid = true; 1359 } 1360 else if ( (pushTaskLevel) && 1361 (CFEqual(tmp_type, kIOPMAssertionTypeApplePushServiceTask)) ) 1362 { 1363 print_this_pid = true; 1364 } 1365 else if ( (proxyLevel) && 1366 (CFEqual(tmp_type, kIOPMAssertInternalPreventSleep )) ) 1367 { 1368 print_this_pid = true; 1369 } 1370 } 1371 else if ((_kIOPMAssertionDisplayOn == assertionType) 1372 && CFEqual(tmp_type, kIOPMAssertionTypePreventUserIdleDisplaySleep) ) 1373 { 1374 /* Found an assertion that keeps the display on */ 1375 print_this_pid = true; 1376 } 1377 else if ((_kIOPMAssertionDisplayOn == assertionType) 1378 && CFEqual(tmp_type, kIOPMAssertDisplayWake) ) 1379 { 1380 /* Found an assertion that keeps the display on */ 1381 print_this_pid = true; 1382 } 1383 if (print_this_pid) 1384 { 1385 if (this_is_the_first) { 1386 this_is_the_first = 0; 1387 } else { 1388 strncat(display_string, ", ", kMaxLongStringLength-length-1); 1389 length = strlen(display_string); 1390 } 1391 1392 if (process_name && CFStringGetCString(process_name, pnameBuf, sizeof(pnameBuf), kCFStringEncodingUTF8)) 1393 { 1394 strncat(display_string, pnameBuf, kMaxLongStringLength-length-1); 1395 length = strlen(display_string); 1396 } 1397 } 1398 } 1399 } 1400 1401 strncat(display_string, ")", sizeof(display_string)-strlen(display_string)-1); 1402 1403 printf("%s", display_string); 1404 1405 free(pids); 1406 free(assertions); 1407 1408bail: 1409 if(assertions_state) CFRelease(assertions_state); 1410 if(assertions_pids) CFRelease(assertions_pids); 1411 return; 1412} 1413 1414static void show_supported_pm_features(void) 1415{ 1416 CFStringRef feature; 1417 CFTypeRef ps_info = IOPSCopyPowerSourcesInfo(); 1418 CFStringRef source; 1419 char ps_buf[40]; 1420 int i; 1421 1422 if(!ps_info) { 1423 source = CFSTR(kIOPMACPowerKey); 1424 } else { 1425 source = IOPSGetProvidingPowerSourceType(ps_info); 1426 } 1427 if(!isA_CFString(source) || 1428 !CFStringGetCString(source, ps_buf, 40, kCFStringEncodingMacRoman)) { 1429 printf("internal supported features string error!\n"); 1430 } 1431 1432 printf("Capabilities for %s:\n", ps_buf); 1433 // iterate the list of all features 1434 for(i=0; i<kNUM_PM_FEATURES; i++) 1435 { 1436 feature = CFStringCreateWithCStringNoCopy(NULL, all_features[i].name, 1437 kCFStringEncodingMacRoman, kCFAllocatorNull); 1438 if (feature) 1439 { 1440 if (IOPMFeatureIsAvailable(feature, source)) 1441 { 1442 printf(" %s\n", all_features[i].displayAs); 1443 } 1444 CFRelease(feature); 1445 } 1446 } 1447 if(ps_info) { 1448 CFRelease(ps_info); 1449 } 1450} 1451 1452static void show_power_profile( 1453 CFDictionaryRef es, 1454 int indent) 1455{ 1456 int num_profiles; 1457 int i, j; 1458 char ps[kMaxArgStringLength]; 1459 CFStringRef *keys; 1460 CFDictionaryRef *values; 1461 1462 if(indent<0 || indent>30) indent=0; 1463 1464 num_profiles = CFDictionaryGetCount(es); 1465 keys = (CFStringRef *)malloc(num_profiles * sizeof(CFStringRef)); 1466 values = (CFDictionaryRef *)malloc(num_profiles * sizeof(CFDictionaryRef)); 1467 if(keys && values) 1468 { 1469 CFDictionaryGetKeysAndValues(es, (const void **)keys, (const void **)values); 1470 1471 for(i=0; i<num_profiles; i++) 1472 { 1473 if(!isA_CFDictionary(values[i])) 1474 continue; 1475 1476 if(!CFStringGetCString(keys[i], ps, sizeof(ps), kCFStringEncodingMacRoman)) 1477 continue; // with for loop 1478 1479 for(j=0; j<indent; j++) { 1480 printf(" "); 1481 } 1482 printf("%s:\n", ps); 1483 show_pm_settings_dict(values[i], indent, 0, false); 1484 } 1485 } 1486 if (keys) free(keys); 1487 if (values) free(values); 1488} 1489 1490static void show_custom_pm_settings(void) 1491{ 1492 CFDictionaryRef es = NULL; 1493 1494 // read settings file from /Library/Preferences/SystemConfiguration/com.apple.PowerManagement.plist 1495 es = IOPMCopyPMPreferences(); 1496 if(!es) 1497 return; 1498 show_power_profile(es, 0); 1499 CFRelease(es); 1500} 1501 1502static void show_live_pm_settings(void) 1503{ 1504 SCDynamicStoreRef ds; 1505 CFDictionaryRef live; 1506 1507 ds = SCDynamicStoreCreate(NULL, CFSTR("pmset"), NULL, NULL); 1508 1509 // read current settings from SCDynamicStore key 1510 live = SCDynamicStoreCopyValue(ds, CFSTR(kIOPMDynamicStoreSettingsKey)); 1511 if(!live) 1512 return; 1513 printf("Currently in use:\n"); 1514 show_pm_settings_dict(live, 0, true, true); 1515 1516 CFRelease(live); 1517 CFRelease(ds); 1518} 1519 1520static void show_ups_settings(void) 1521{ 1522 CFDictionaryRef thresholds; 1523 CFDictionaryRef d; 1524 CFNumberRef n_val; 1525 int val; 1526 CFBooleanRef b; 1527 1528 thresholds = IOPMCopyUPSShutdownLevels(CFSTR(kIOPMDefaultUPSThresholds)); 1529 if(!thresholds) 1530 return; 1531 1532 printf("UPS settings:\n"); 1533 1534 if((d = CFDictionaryGetValue(thresholds, CFSTR(kIOUPSShutdownAtLevelKey)))) 1535 { 1536 b = CFDictionaryGetValue(d, CFSTR(kIOUPSShutdownLevelEnabledKey)); 1537 n_val = CFDictionaryGetValue(d, CFSTR(kIOUPSShutdownLevelValueKey)); 1538 CFNumberGetValue(n_val, kCFNumberIntType, &val); 1539 printf(" %s\t%s\t%d\n", ARG_HALTLEVEL, (kCFBooleanTrue==b)?"on":"off", val); 1540 } 1541 if((d = CFDictionaryGetValue(thresholds, CFSTR(kIOUPSShutdownAfterMinutesOn)))) 1542 { 1543 b = CFDictionaryGetValue(d, CFSTR(kIOUPSShutdownLevelEnabledKey)); 1544 n_val = CFDictionaryGetValue(d, CFSTR(kIOUPSShutdownLevelValueKey)); 1545 CFNumberGetValue(n_val, kCFNumberIntType, &val); 1546 printf(" %s\t%s\t%d\n", ARG_HALTAFTER, (kCFBooleanTrue==b)?"on":"off", val); 1547 } 1548 if((d = CFDictionaryGetValue(thresholds, CFSTR(kIOUPSShutdownAtMinutesLeft)))) 1549 { 1550 b = CFDictionaryGetValue(d, CFSTR(kIOUPSShutdownLevelEnabledKey)); 1551 n_val = CFDictionaryGetValue(d, CFSTR(kIOUPSShutdownLevelValueKey)); 1552 CFNumberGetValue(n_val, kCFNumberIntType, &val); 1553 printf(" %s\t%s\t%d\n", ARG_HALTREMAIN, (kCFBooleanTrue==b)?"on":"off", val); 1554 } 1555 CFRelease(thresholds); 1556} 1557 1558static void 1559show_active_profiles(void) 1560{ 1561 CFDictionaryRef active_prof = 0; 1562 int i; 1563 int count; 1564 int val; 1565 CFNumberRef *prof_val = 0; 1566 CFStringRef *ps = NULL; 1567 char ps_str[40]; 1568 1569 CFTypeRef ps_info = 0; 1570 CFStringRef current_ps = 0; 1571 1572 ps_info = IOPSCopyPowerSourcesInfo(); 1573 if(ps_info) current_ps = IOPSGetProvidingPowerSourceType(ps_info); 1574 if(!ps_info || !current_ps) current_ps = CFSTR(kIOPMACPowerKey); 1575 1576 active_prof = IOPMCopyActivePowerProfiles(); 1577 if(!active_prof) { 1578 printf("PM system error - no active profiles found\n"); 1579 goto exit; 1580 } 1581 1582 count = CFDictionaryGetCount(active_prof); 1583 prof_val = (CFNumberRef *)malloc(sizeof(CFNumberRef)*count); 1584 ps = (CFStringRef *)malloc(sizeof(CFStringRef)*count); 1585 if(!prof_val || !ps) goto exit; 1586 1587 printf("Active Profiles:\n"); 1588 1589 CFDictionaryGetKeysAndValues(active_prof, (const void **)ps, (const void **)prof_val); 1590 for(i=0; i<count; i++) 1591 { 1592 if( CFStringGetCString(ps[i], ps_str, 40, kCFStringEncodingMacRoman) 1593 && CFNumberGetValue(prof_val[i], kCFNumberIntType, &val)) { 1594 printf("%s\t\t%d", ps_str, val); 1595 1596 // Put a * next to the currently active power supply 1597 if( current_ps && (kCFCompareEqualTo == CFStringCompare(ps[i], current_ps, 0))) { 1598 printf("*"); 1599 } 1600 1601 printf("\n"); 1602 } 1603 } 1604 1605exit: 1606 if(active_prof) CFRelease(active_prof); 1607 if(ps_info) CFRelease(ps_info); 1608 if(prof_val) free(prof_val); 1609 if(ps) free(ps); 1610} 1611 1612static void 1613show_system_profiles(void) 1614{ 1615 CFArrayRef sys_prof; 1616 int prof_count; 1617 int i; 1618 1619 sys_prof = IOPMCopyPowerProfiles(); 1620 if(!sys_prof) { 1621 printf("No system profiles found\n"); 1622 return; 1623 } 1624 1625 prof_count = CFArrayGetCount(sys_prof); 1626 for(i=0; i<prof_count;i++) 1627 { 1628 printf("=== Profile %d ===\n", i); 1629 show_power_profile( CFArrayGetValueAtIndex(sys_prof, i), 0 ); 1630 if(i!=(prof_count-1)) printf("\n"); 1631 } 1632 1633 CFRelease(sys_prof); 1634} 1635 1636static CFDictionaryRef 1637getPowerEvent(int type, CFDictionaryRef events) 1638{ 1639 if(type) 1640 return (CFDictionaryRef)isA_CFDictionary(CFDictionaryGetValue(events, CFSTR(kIOPMRepeatingPowerOnKey))); 1641 else 1642 return (CFDictionaryRef)isA_CFDictionary(CFDictionaryGetValue(events, CFSTR(kIOPMRepeatingPowerOffKey))); 1643} 1644static int 1645getRepeatingDictionaryMinutes(CFDictionaryRef event) 1646{ 1647 int val; 1648 CFNumberRef tmp_num; 1649 tmp_num = (CFNumberRef)CFDictionaryGetValue(event, CFSTR(kIOPMPowerEventTimeKey)); 1650 CFNumberGetValue(tmp_num, kCFNumberIntType, &val); 1651 return val; 1652} 1653static int 1654getRepeatingDictionaryDayMask(CFDictionaryRef event) 1655{ 1656 int val; 1657 CFNumberRef tmp_num; 1658 tmp_num = (CFNumberRef)CFDictionaryGetValue(event, CFSTR(kIOPMDaysOfWeekKey)); 1659 CFNumberGetValue(tmp_num, kCFNumberIntType, &val); 1660 return val; 1661} 1662static CFStringRef 1663getRepeatingDictionaryType(CFDictionaryRef event) 1664{ 1665 return (CFStringRef)CFDictionaryGetValue(event, CFSTR(kIOPMPowerEventTypeKey)); 1666} 1667 1668static void 1669print_time_of_day_to_buf(int m, char *buf, int buflen) 1670{ 1671 int hours, minutes, afternoon; 1672 1673 hours = m/60; 1674 minutes = m%60; 1675 afternoon = 0; 1676 if(hours >= 12) afternoon = 1; 1677 if(hours > 12) hours-=12; 1678 1679 snprintf(buf, buflen, "%d:%d%d%cM", hours, 1680 minutes/10, minutes%10, 1681 (afternoon? 'P':'A')); 1682} 1683 1684static void 1685print_days_to_buf(int d, char *buf, int buflen) 1686{ 1687 switch(d) { 1688 case daily_mask: 1689 snprintf(buf, buflen, "every day"); 1690 break; 1691 1692 case weekday_mask: 1693 snprintf(buf, buflen, "weekdays only"); 1694 break; 1695 1696 case weekend_mask: 1697 snprintf(buf, buflen, "weekends only"); 1698 break; 1699 1700 case 0x01 : 1701 snprintf(buf, buflen, "Monday"); 1702 break; 1703 1704 case 0x02 : 1705 snprintf(buf, buflen, "Tuesday"); 1706 break; 1707 1708 case 0x04 : 1709 snprintf(buf, buflen, "Wednesday"); 1710 break; 1711 1712 case 0x08 : 1713 snprintf(buf, buflen, "Thursday"); 1714 break; 1715 1716 case 0x10 : 1717 snprintf(buf, buflen, "Friday"); 1718 break; 1719 1720 case 0x20 : 1721 snprintf(buf, buflen, "Saturday"); 1722 break; 1723 1724 case 0x40 : 1725 snprintf(buf, buflen, "Sunday"); 1726 break; 1727 1728 default: 1729 snprintf(buf, buflen, "Some days"); 1730 break; 1731 } 1732} 1733 1734#define kMaxDaysOfWeekLength 20 1735static void print_repeating_report(CFDictionaryRef repeat) 1736{ 1737 CFDictionaryRef on, off; 1738 char time_buf[kMaxDaysOfWeekLength]; 1739 char day_buf[kMaxDaysOfWeekLength]; 1740 CFStringRef type_str = NULL; 1741 char type_buf[kMaxArgStringLength]; 1742 1743 // assumes validly formatted dictionary - doesn't do any error checking 1744 on = getPowerEvent(1, repeat); 1745 off = getPowerEvent(0, repeat); 1746 1747 if(on || off) 1748 { 1749 printf("Repeating power events:\n"); 1750 if(on) 1751 { 1752 print_time_of_day_to_buf(getRepeatingDictionaryMinutes(on), time_buf, kMaxDaysOfWeekLength); 1753 print_days_to_buf(getRepeatingDictionaryDayMask(on), day_buf, kMaxDaysOfWeekLength); 1754 1755 type_str = getRepeatingDictionaryType(on); 1756 if (type_str) { 1757 CFStringGetCString(type_str, type_buf, sizeof(type_buf), kCFStringEncodingMacRoman); 1758 } else { 1759 snprintf(type_buf, sizeof(type_buf), "?type?"); 1760 } 1761 1762 printf(" %s at %s %s\n", type_buf, time_buf, day_buf); 1763 } 1764 1765 if(off) 1766 { 1767 print_time_of_day_to_buf(getRepeatingDictionaryMinutes(off), time_buf, kMaxDaysOfWeekLength); 1768 print_days_to_buf(getRepeatingDictionaryDayMask(off), day_buf, kMaxDaysOfWeekLength); 1769 1770 type_str = getRepeatingDictionaryType(off); 1771 if (type_str) { 1772 CFStringGetCString(type_str, type_buf, sizeof(type_buf), kCFStringEncodingMacRoman); 1773 } else { 1774 snprintf(type_buf, sizeof(type_buf), "?type?"); 1775 } 1776 1777 printf(" %s at %s %s\n", type_buf, time_buf, day_buf); 1778 } 1779 fflush(stdout); 1780 } 1781} 1782 1783static void 1784print_scheduled_report(CFArrayRef events) 1785{ 1786 CFDictionaryRef ev; 1787 int count, i; 1788 char date_buf[40]; 1789 char name_buf[255]; 1790 char type_buf[40]; 1791 char *type_ptr = NULL; 1792 CFStringRef type = NULL; 1793 CFStringRef author = NULL; 1794 CFDateFormatterRef formatter = NULL; 1795 CFStringRef cf_str_date = NULL; 1796 1797 if(!events || !(count = CFArrayGetCount(events))) return; 1798 1799 formatter = CFDateFormatterCreate(kCFAllocatorDefault, CFLocaleGetSystem(), 1800 kCFDateFormatterShortStyle, kCFDateFormatterMediumStyle); 1801 CFDateFormatterSetFormat(formatter, CFSTR(kDateAndTimeFormat)); 1802 1803 printf("Scheduled power events:\n"); 1804 for(i=0; i<count; i++) 1805 { 1806 ev = (CFDictionaryRef)CFArrayGetValueAtIndex(events, i); 1807 1808 cf_str_date = CFDateFormatterCreateStringWithDate(kCFAllocatorDefault, 1809 formatter, CFDictionaryGetValue(ev, CFSTR(kIOPMPowerEventTimeKey))); 1810 date_buf[0] = 0; 1811 if(cf_str_date) { 1812 CFStringGetCString(cf_str_date, date_buf, 40, kCFStringEncodingMacRoman); 1813 CFRelease(cf_str_date); 1814 } 1815 1816 author = CFDictionaryGetValue(ev, CFSTR(kIOPMPowerEventAppNameKey)); 1817 name_buf[0] = 0; 1818 if(isA_CFString(author)) 1819 CFStringGetCString(author, name_buf, 255, kCFStringEncodingMacRoman); 1820 1821 type = CFDictionaryGetValue(ev, CFSTR(kIOPMPowerEventTypeKey)); 1822 type_buf[0] = 0; 1823 if(isA_CFString(type)) 1824 CFStringGetCString(type, type_buf, 40, kCFStringEncodingMacRoman); 1825 1826 // rename "wakepoweron" to "wakeorpoweron" to make things consistent between 1827 // "pmset -g" and "pmset sched" 1828 if(!strcmp(type_buf, kIOPMAutoWakeOrPowerOn)) 1829 type_ptr = ARG_WAKEORPOWERON; 1830 else 1831 type_ptr = type_buf; 1832 1833 printf(" [%d] %s at %s", i, type_ptr, date_buf); 1834 if(name_buf[0]) printf(" by %s", name_buf); 1835 printf("\n"); 1836 } 1837 1838 if (formatter) 1839 CFRelease(formatter); 1840} 1841 1842static void show_scheduled_events(void) 1843{ 1844 CFDictionaryRef repeatingEvents; 1845 CFArrayRef scheduledEvents; 1846 1847 repeatingEvents = IOPMCopyRepeatingPowerEvents(); 1848 scheduledEvents = IOPMCopyScheduledPowerEvents(); 1849 1850 if(!repeatingEvents && !scheduledEvents) { 1851 printf("No scheduled events.\n"); fflush(stdout); 1852 return; 1853 } 1854 1855 if(repeatingEvents) { 1856 print_repeating_report(repeatingEvents); 1857 CFRelease(repeatingEvents); 1858 } 1859 1860 if(scheduledEvents) { 1861 print_scheduled_report(scheduledEvents); 1862 CFRelease(scheduledEvents); 1863 } 1864} 1865 1866static bool matchingAssertion(CFDictionaryRef asst_dict, CFStringRef asst) 1867{ 1868 if(!asst_dict || (kCFBooleanFalse == (CFTypeRef)asst_dict)) return false; 1869 1870 return CFEqual(asst, 1871 CFDictionaryGetValue(asst_dict, kIOPMAssertionTypeKey)); 1872} 1873 1874 1875static void show_active_assertions(uint32_t which) 1876{ 1877 // Print active DisableInflow or ChargeInhibit assertions on the 1878 // following line 1879 CFDictionaryRef assertions_status = NULL; 1880 CFDictionaryRef assertions_by_pid = NULL; 1881 CFStringRef *assertionNames = NULL; 1882 CFNumberRef *assertionValues = NULL; 1883 CFNumberRef *pids = NULL; 1884 CFArrayRef *pidAssertions = NULL; 1885 char name[50]; 1886 int val; 1887 int total_assertion_count; 1888 int pid_count; 1889 IOReturn ret; 1890 int i, j, k; 1891 1892 if(0 == which) return; 1893 1894 ret = IOPMCopyAssertionsStatus(&assertions_status); 1895 if(kIOReturnSuccess != ret || !assertions_status) 1896 return; 1897 1898 ret = IOPMCopyAssertionsByProcess(&assertions_by_pid); 1899 if(kIOReturnSuccess != ret || !assertions_by_pid) 1900 return; 1901 1902 // Grab out the total/aggregate sate of the assertions 1903 total_assertion_count = CFDictionaryGetCount(assertions_status); 1904 if(0 == total_assertion_count) 1905 return; 1906 1907 assertionNames = (CFStringRef *)malloc( 1908 sizeof(CFStringRef) * total_assertion_count); 1909 assertionValues = (CFNumberRef *)malloc( 1910 sizeof(CFNumberRef) * total_assertion_count); 1911 CFDictionaryGetKeysAndValues(assertions_status, 1912 (const void **)assertionNames, 1913 (const void **)assertionValues); 1914 1915 // Grab the list of activated assertions per-process 1916 pid_count = CFDictionaryGetCount(assertions_by_pid); 1917 if(0 == pid_count) 1918 return; 1919 1920 pids = malloc(sizeof(CFNumberRef) * pid_count); 1921 pidAssertions = malloc(sizeof(CFArrayRef) * pid_count); 1922 1923 CFDictionaryGetKeysAndValues(assertions_by_pid, 1924 (const void **)pids, 1925 (const void **)pidAssertions); 1926 1927 if ( assertionNames && assertionValues && pidAssertions && pids) 1928 { 1929 1930 for(i=0; i<total_assertion_count; i++) 1931 { 1932 CFStringGetCString(assertionNames[i], name, 50, kCFStringEncodingMacRoman); 1933 CFNumberGetValue(assertionValues[i], kCFNumberIntType, &val); 1934 1935 // Determine if we want to display this assertion 1936 if( !( ( (which & kAssertionCPU) && 1937 CFEqual(assertionNames[i], kIOPMCPUBoundAssertion)) 1938 || ( (which & kAssertionInflow) && 1939 CFEqual(assertionNames[i], kIOPMInflowDisableAssertion)) 1940 || ( (which & kAssertionCharge) && 1941 CFEqual(assertionNames[i], kIOPMChargeInhibitAssertion)) 1942 || ( (which & kAssertionIdle) && 1943 CFEqual(assertionNames[i], kIOPMAssertionTypeNoIdleSleep)) ) ) 1944 { 1945 // If the caller wasn't interested is this assertion, we pass 1946 continue; 1947 } 1948 1949 if(val) 1950 { 1951 printf("\t'%s':\t", name); 1952 for(j=0; j<pid_count; j++) 1953 { 1954 for(k=0; k<CFArrayGetCount(pidAssertions[j]); k++) 1955 { 1956 CFDictionaryRef obj; 1957 if( (obj = (CFDictionaryRef)CFArrayGetValueAtIndex( 1958 pidAssertions[j], k))) 1959 { 1960 if(matchingAssertion(obj, assertionNames[i])) 1961 { 1962 int pid_num = 0; 1963 CFNumberGetValue(pids[j], kCFNumberIntType, &pid_num); 1964 printf("%d ", pid_num); 1965 } 1966 } 1967 } 1968 } 1969 printf("\n"); fflush(stdout); 1970 } 1971 } 1972 } 1973 if (assertionNames) free(assertionNames); 1974 if (assertionValues) free(assertionValues); 1975 if (pidAssertions) free(pidAssertions); 1976 if (pids) free(pids); 1977 if (assertions_status) CFRelease(assertions_status); 1978 if (assertions_by_pid) CFRelease(assertions_by_pid); 1979 1980 return; 1981} 1982 1983/******************************************************************************/ 1984/* */ 1985/* BLOCK IDLE SLEEP */ 1986/* */ 1987/******************************************************************************/ 1988 1989static bool prevent_idle_sleep(void) 1990{ 1991 IOPMAssertionID neverSleep; 1992 1993 if (kIOReturnSuccess != 1994 IOPMAssertionCreateWithName(kIOPMAssertionTypeNoIdleSleep, 1995 kIOPMAssertionLevelOn, 1996 CFSTR("pmset prevent sleep"), 1997 &neverSleep)) 1998 { 1999 // Failure 2000 return false; 2001 } 2002 2003 printf("Preventing idle sleep (^C to exit)...\n"); 2004 2005 // ctrl-c at command-line exits 2006 while(1) { 2007 sleep(100); 2008 } 2009 2010 return true; 2011} 2012enum { 2013 kPrintLotsOfThings = 0, 2014 kJustPrintSleep = 1, 2015 kJustPrintWake = 2 2016}; 2017 2018static void printSleepAndWakeReasons(int just_do_it) 2019{ 2020 CFStringRef lastSleepReason = copyRootDomainProperty(CFSTR("Last Sleep Reason")); 2021 CFStringRef wakeReason = copyRootDomainProperty(CFSTR("Wake Reason")); 2022 CFStringRef wakeType = copyRootDomainProperty(CFSTR("Wake Type")); 2023 char buf[100]; 2024 2025 if (just_do_it != kJustPrintWake) 2026 { 2027 if (lastSleepReason) { 2028 CFStringGetCString(lastSleepReason, buf, sizeof(buf), kCFStringEncodingUTF8); 2029 printf(" Last Sleep Reason = %s\n", buf); 2030 } 2031 } 2032 2033 if (just_do_it != kJustPrintSleep) 2034 { 2035 if (wakeReason) { 2036 CFStringGetCString(wakeReason, buf, sizeof(buf), kCFStringEncodingUTF8); 2037 printf(" Wake Reason = %s\n", buf); 2038 } 2039 if (wakeType) { 2040 CFStringGetCString(wakeType, buf, sizeof(buf), kCFStringEncodingUTF8); 2041 printf(" wakeType = %s\n", buf); 2042 } 2043 } 2044 2045 if (lastSleepReason) { CFRelease(lastSleepReason); } 2046 if (wakeReason) { CFRelease(wakeReason); } 2047 if (wakeType) { CFRelease(wakeType); } 2048 2049 return; 2050} 2051 2052 2053/* sleepWakeCallback 2054 * 2055 * Receives notifications on system sleep and system wake. 2056 */ 2057static void 2058sleepWakeCallback( 2059 void *refcon, 2060 io_service_t y __unused, 2061 natural_t messageType, 2062 void * messageArgument) 2063{ 2064 uint32_t behavior = (uintptr_t)refcon; 2065 2066 switch ( messageType ) { 2067 case kIOMessageSystemWillSleep: 2068 if ( behavior & kLogSleepEvents ) 2069 { 2070 printf("\n"); 2071 print_pretty_date(CFAbsoluteTimeGetCurrent(), false); 2072 printf("IORegisterForSystemPower: ...Sleeping...\n"); 2073// printSleepAndWakeReasons(kJustPrintSleep); 2074 fflush(stdout); 2075 } 2076 2077 IOAllowPowerChange(gPMAckPort, (long)messageArgument); 2078 break; 2079 2080 case kIOMessageCanSystemSleep: 2081 if( behavior & kCancelSleepEvents ) 2082 { 2083 IOCancelPowerChange(gPMAckPort, (long)messageArgument); 2084 printf("\n"); 2085 print_pretty_date(CFAbsoluteTimeGetCurrent(), false); 2086 printf("IORegisterForSystemPower: ...Cancelling...\n"); 2087// printSleepAndWakeReasons(kJustPrintSleep); 2088 } else { 2089 IOAllowPowerChange(gPMAckPort, (long)messageArgument); 2090 } 2091 break; 2092 2093 case kIOMessageSystemHasPoweredOn: 2094 if ( behavior & kLogSleepEvents ) 2095 { 2096 printf("\n"); 2097 print_pretty_date(CFAbsoluteTimeGetCurrent(), false); // false == no newline 2098 printf("IORegisterForSystemPower: ...HasPoweredOn...\n"); 2099 printSleepAndWakeReasons(kJustPrintWake); 2100 fflush(stdout); 2101 } 2102 break; 2103 } 2104 2105 return; 2106} 2107 2108 2109 2110/******************************************************************************/ 2111/* */ 2112/* PS LOGGING */ 2113/* */ 2114/******************************************************************************/ 2115 2116#define kMaxHealthLength 10 2117#define kMaxNameLength 60 2118 2119static void show_power_sources(int which) 2120{ 2121 CFTypeRef ps_info = IOPSCopyPowerSourcesInfo(); 2122 CFArrayRef list = NULL; 2123 CFStringRef ps_name = NULL; 2124 static CFStringRef last_ps = NULL; 2125 static CFAbsoluteTime invocationTime = 0.0; 2126 CFDictionaryRef one_ps = NULL; 2127 char strbuf[kMaxLongStringLength]; 2128 int count; 2129 int i; 2130 int show_time_estimate; 2131 CFNumberRef remaining, charge, capacity; 2132 CFBooleanRef charging; 2133 CFBooleanRef charged; 2134 CFBooleanRef finishingCharge; 2135 CFBooleanRef present; 2136 CFStringRef name; 2137 CFStringRef state; 2138 CFStringRef transport; 2139 CFStringRef health; 2140 CFStringRef confidence; 2141 CFStringRef failure; 2142 char _health[kMaxHealthLength]; 2143 char _confidence[kMaxHealthLength]; 2144 char _name[kMaxNameLength]; 2145 char _failure[kMaxLongStringLength]; 2146 int _hours = 0; 2147 int _minutes = 0; 2148 int _charge = 0; 2149 int _FCCap = 0; 2150 bool _charging = false; 2151 bool _charged = false; 2152 bool _finishingCharge = false; 2153 int _warningLevel = 0; 2154 CFArrayRef permFailuresArray = NULL; 2155 CFStringRef pfString = NULL; 2156 2157 if(!ps_info) { 2158 printf("No power source info available\n"); 2159 return; 2160 } 2161 2162 if (isBatteryPollingStopped()) { 2163 printf("* Battery Polling is Stopped by \"pmset nopoll\" *\n"); 2164 } 2165 2166 /* Output path for Time Remaining Columns 2167 * - Only displays battery 2168 */ 2169 if (kShowColumns & which) 2170 { 2171 CFTypeRef one_ps_descriptor = NULL; 2172 CFAbsoluteTime nowTime = CFAbsoluteTimeGetCurrent(); 2173 uint32_t minutesSinceInvocation = 0; 2174 int32_t estimatedMinutesRemaining = 0; 2175 2176 if (invocationTime == 0.0) { 2177 invocationTime = nowTime; 2178 } 2179 2180 // Note: We assume a one-battery system. 2181 one_ps_descriptor = IOPSGetActiveBattery(ps_info); 2182 if (one_ps_descriptor) { 2183 one_ps = IOPSGetPowerSourceDescription(ps_info, one_ps_descriptor); 2184 } 2185 if(!one_ps) { 2186 printf("Logging power sources: unable to locate battery.\n"); 2187 goto exit; 2188 }; 2189 2190 charging = CFDictionaryGetValue(one_ps, CFSTR(kIOPSIsChargingKey)); 2191 state = CFDictionaryGetValue(one_ps, CFSTR(kIOPSPowerSourceStateKey)); 2192 if (CFEqual(state, CFSTR(kIOPSBatteryPowerValue))) 2193 { 2194 remaining = CFDictionaryGetValue(one_ps, CFSTR(kIOPSTimeToEmptyKey)); 2195 } else { 2196 remaining = CFDictionaryGetValue(one_ps, CFSTR(kIOPSTimeToFullChargeKey)); 2197 } 2198 2199 if (remaining) { 2200 CFNumberGetValue(remaining, kCFNumberIntType, &estimatedMinutesRemaining); 2201 } else { 2202 estimatedMinutesRemaining = -1; 2203 } 2204 2205 minutesSinceInvocation = (nowTime - invocationTime)/60; 2206 2207 charge = CFDictionaryGetValue(one_ps, CFSTR(kIOPSCurrentCapacityKey)); 2208 if(charge) CFNumberGetValue(charge, kCFNumberIntType, &_charge); 2209 2210 // "Elapsed", "TimeRemaining", "Percent""Charge", "Timestamp"); 2211 printf("%10d\t%15d\t%10d%%\t%10s\t", minutesSinceInvocation, estimatedMinutesRemaining, 2212 _charge, (kCFBooleanTrue == charging) ? "charge" : "discharge"); 2213 print_pretty_date(CFAbsoluteTimeGetCurrent(), true); 2214 2215 goto exit; 2216 } 2217 /* Completed output path 2218 */ 2219 2220 ps_name = IOPSGetProvidingPowerSourceType(ps_info); 2221 if(!ps_name || !CFStringGetCString(ps_name, strbuf, kMaxLongStringLength, kCFStringEncodingUTF8)) 2222 { 2223 goto exit; 2224 } 2225 if(!last_ps || kCFCompareEqualTo != CFStringCompare(last_ps, ps_name, 0)) 2226 { 2227 printf("Now drawing from '%s'\n", strbuf); 2228 } 2229 if(last_ps) CFRelease(last_ps); 2230 last_ps = CFStringCreateCopy(kCFAllocatorDefault, ps_name); 2231 2232 list = IOPSCopyPowerSourcesList(ps_info); 2233 if(!list) goto exit; 2234 count = CFArrayGetCount(list); 2235 for(i=0; i<count; i++) 2236 { 2237 bzero(_health, sizeof(_health)); 2238 bzero(_confidence, sizeof(_confidence)); 2239 bzero(_name, sizeof(_name)); 2240 bzero(_failure, sizeof(_failure)); 2241 _hours = _minutes = _charge = _FCCap = 0; 2242 _charging = _charged = _finishingCharge = false; 2243 2244 one_ps = IOPSGetPowerSourceDescription(ps_info, CFArrayGetValueAtIndex(list, i)); 2245 if(!one_ps) break; 2246 2247 // Only display settings for power sources we want to show 2248 transport = CFDictionaryGetValue(one_ps, CFSTR(kIOPSTransportTypeKey)); 2249 if(!transport) continue; 2250 if(kCFCompareEqualTo != CFStringCompare(transport, CFSTR(kIOPSInternalType), 0)) 2251 { 2252 // Internal transport means internal battery 2253 if(!(which & kApplyToBattery)) continue; 2254 } else { 2255 // Any specified non-Internal transport is a UPS 2256 if(!(which & kApplyToUPS)) continue; 2257 } 2258 2259 charging = CFDictionaryGetValue(one_ps, CFSTR(kIOPSIsChargingKey)); 2260 state = CFDictionaryGetValue(one_ps, CFSTR(kIOPSPowerSourceStateKey)); 2261 if(kCFCompareEqualTo == CFStringCompare(state, CFSTR(kIOPSBatteryPowerValue), 0)) 2262 { 2263 remaining = CFDictionaryGetValue(one_ps, CFSTR(kIOPSTimeToEmptyKey)); 2264 } else { 2265 remaining = CFDictionaryGetValue(one_ps, CFSTR(kIOPSTimeToFullChargeKey)); 2266 } 2267 name = CFDictionaryGetValue(one_ps, CFSTR(kIOPSNameKey)); 2268 charge = CFDictionaryGetValue(one_ps, CFSTR(kIOPSCurrentCapacityKey)); 2269 capacity = CFDictionaryGetValue(one_ps, CFSTR(kIOPSMaxCapacityKey)); 2270 present = CFDictionaryGetValue(one_ps, CFSTR(kIOPSIsPresentKey)); 2271 health = CFDictionaryGetValue(one_ps, CFSTR(kIOPSBatteryHealthKey)); 2272 confidence = CFDictionaryGetValue(one_ps, CFSTR(kIOPSHealthConfidenceKey)); 2273 failure = CFDictionaryGetValue(one_ps, CFSTR("Failure")); 2274 charged = CFDictionaryGetValue(one_ps, CFSTR(kIOPSIsChargedKey)); 2275 finishingCharge = CFDictionaryGetValue(one_ps, CFSTR(kIOPSIsFinishingChargeKey)); 2276 2277 permFailuresArray = CFDictionaryGetValue(one_ps, CFSTR(kIOPSBatteryFailureModesKey)); 2278 2279 if(name) CFStringGetCString(name, _name, 2280 kMaxNameLength, kCFStringEncodingMacRoman); 2281 if(health) CFStringGetCString(health, _health, 2282 kMaxHealthLength, kCFStringEncodingMacRoman); 2283 if(confidence) CFStringGetCString(confidence, _confidence, 2284 kMaxHealthLength, kCFStringEncodingMacRoman); 2285 if(failure) CFStringGetCString(failure, _failure, 2286 kMaxLongStringLength, kCFStringEncodingMacRoman); 2287 if(charge) CFNumberGetValue(charge, kCFNumberIntType, &_charge); 2288 if(capacity) CFNumberGetValue(capacity, kCFNumberIntType, &_FCCap); 2289 if(remaining) 2290 { 2291 CFNumberGetValue(remaining, kCFNumberIntType, &_minutes); 2292 if(-1 != _minutes) { 2293 _hours = _minutes/60; 2294 _minutes = _minutes%60; 2295 } 2296 } 2297 if(charging) _charging = (kCFBooleanTrue == charging); 2298 if (charged) _charged = (kCFBooleanTrue == charged); 2299 if (finishingCharge) _finishingCharge = (kCFBooleanTrue == finishingCharge); 2300 2301 _warningLevel = IOPSGetBatteryWarningLevel(); 2302 2303 show_time_estimate = 1; 2304 2305 printf(" -"); 2306 if(name) printf("%s\t", _name); 2307 if(present && (kCFBooleanTrue == present)) 2308 { 2309 if(charge && _FCCap) printf("%d%%; ", _charge*100/_FCCap); 2310 if(charging) { 2311 if (_finishingCharge) { 2312 printf("finishing charge"); 2313 } else if (_charged) { 2314 printf("charged"); 2315 } else if(_charging) { 2316 printf("charging"); 2317 } else { 2318 if(kCFCompareEqualTo == CFStringCompare(state, CFSTR(kIOPSACPowerValue), 0)) { 2319 printf("AC attached; not charging"); 2320 show_time_estimate = 0; 2321 } else { 2322 printf("discharging"); 2323 } 2324 } 2325 } 2326 if(show_time_estimate && remaining) { 2327 if(-1 != _minutes) { 2328 printf("; %d:%d%d remaining", _hours, _minutes/10, _minutes%10); 2329 } else { 2330 printf("; (no estimate)"); 2331 } 2332 } 2333 if (health && confidence 2334 && !CFEqual(CFSTR("Good"), health)) { 2335 printf(" (%s/%s)", _health, _confidence); 2336 } 2337 if(failure) { 2338 printf("\n\tfailure: \"%s\"", _failure); 2339 } 2340 if (permFailuresArray) { 2341 int failure_count = CFArrayGetCount(permFailuresArray); 2342 int m = 0; 2343 2344 printf("\n\tDetailed failures:"); 2345 2346 for(m=0; m<failure_count; m++) { 2347 pfString = CFArrayGetValueAtIndex(permFailuresArray, m); 2348 if (pfString) 2349 { 2350 CFStringGetCString(pfString, strbuf, kMaxLongStringLength, kCFStringEncodingMacRoman); 2351 printf(" \"%s\"", strbuf); 2352 } 2353 if (m != failure_count - 1) 2354 printf(","); 2355 } 2356 } 2357 printf("\n"); fflush(stdout); 2358 2359 // Show batery warnings on a new line: 2360 if (kIOPSLowBatteryWarningEarly == _warningLevel) { 2361 printf("\tBattery Warning: Early\n"); 2362 } else if (kIOPSLowBatteryWarningFinal == _warningLevel) { 2363 printf("\tBattery Warning: Final\n"); 2364 } 2365 } else { 2366 printf(" (removed)\n"); 2367 } 2368 2369 2370 } 2371 2372 // Display the battery-specific assertions that are affecting the system 2373 show_active_assertions( kAssertionInflow | kAssertionCharge ); 2374 2375exit: 2376 if(ps_info) CFRelease(ps_info); 2377 if(list) CFRelease(list); 2378 return; 2379} 2380 2381static void print_pretty_date(CFAbsoluteTime t, bool newline) 2382{ 2383 print_date_with_style("%-24.24s ", kCFDateFormatterShortStyle, kCFDateFormatterLongStyle, t, newline); 2384} 2385 2386static void print_short_date(CFAbsoluteTime t, bool newline) 2387{ 2388 print_date_with_style("%s ", kCFDateFormatterShortStyle, kCFDateFormatterShortStyle, t, newline); 2389} 2390 2391 2392static void print_date_with_style(const char *dsf, CFDateFormatterStyle dayStyle, CFDateFormatterStyle timeStyle, CFAbsoluteTime t, bool newline) 2393{ 2394 CFDateFormatterRef date_format; 2395 CFTimeZoneRef tz; 2396 CFStringRef time_date; 2397 CFLocaleRef loc; 2398 char _date[60]; 2399 2400 loc = CFLocaleCopyCurrent(); 2401 date_format = CFDateFormatterCreate(kCFAllocatorDefault, loc, 2402 dayStyle, timeStyle); 2403 CFRelease(loc); 2404 tz = CFTimeZoneCopySystem(); 2405 CFDateFormatterSetProperty(date_format, kCFDateFormatterTimeZone, tz); 2406 CFRelease(tz); 2407 time_date = CFDateFormatterCreateStringWithAbsoluteTime(kCFAllocatorDefault, 2408 date_format, t); 2409 CFRelease(date_format); 2410 2411 if(time_date) 2412 { 2413 CFStringGetCString(time_date, _date, 60, kCFStringEncodingMacRoman); 2414 printf(dsf, _date); fflush(stdout); 2415 if(newline) printf("\n"); 2416 CFRelease(time_date); 2417 } 2418} 2419 2420/******************************************************************************/ 2421 2422static void show_assertions_system_aggregates(void) 2423{ 2424 /* 2425 * Copy aggregates 2426 */ 2427 CFStringRef *assertionNames = NULL; 2428 CFNumberRef *assertionValues = NULL; 2429 char name[50]; 2430 int val; 2431 int count; 2432 CFDictionaryRef assertions_status; 2433 IOReturn ret; 2434 int i; 2435 2436 ret = IOPMCopyAssertionsStatus(&assertions_status); 2437 if ((kIOReturnSuccess != ret) || (NULL == assertions_status)) 2438 { 2439 printf("No assertions.\n"); 2440 return; 2441 } 2442 2443 count = CFDictionaryGetCount(assertions_status); 2444 if (0 == count) 2445 { 2446 return; 2447 } 2448 2449 assertionNames = (CFStringRef *)malloc(sizeof(void *)*count); 2450 assertionValues = (CFNumberRef *)malloc(sizeof(void *)*count); 2451 CFDictionaryGetKeysAndValues(assertions_status, 2452 (const void **)assertionNames, (const void **)assertionValues); 2453 2454 printf("Assertion status system-wide:\n"); 2455 for (i=0; i<count; i++) 2456 { 2457 CFNumberGetValue(assertionValues[i], kCFNumberIntType, &val); 2458 if ((kCFCompareEqualTo == CFStringCompare(assertionNames[i], kIOPMAssertionTypeNeedsCPU, 0)) || 2459 (kCFCompareEqualTo == CFStringCompare(assertionNames[i], kIOPMAssertionTypeDisableInflow, 0)) || 2460 (kCFCompareEqualTo == CFStringCompare(assertionNames[i], kIOPMAssertionTypeInhibitCharging, 0)) || 2461 (kCFCompareEqualTo == CFStringCompare(assertionNames[i], kIOPMAssertionTypeDisableLowBatteryWarnings, 0)) || 2462 (kCFCompareEqualTo == CFStringCompare(assertionNames[i], kIOPMAssertInternalPreventSleep, 0)) || 2463 (kCFCompareEqualTo == CFStringCompare(assertionNames[i], kIOPMAssertInternalPreventDisplaySleep, 0)) || 2464 (kCFCompareEqualTo == CFStringCompare(assertionNames[i], kIOPMAssertDisplayWake, 0)) || 2465 (kCFCompareEqualTo == CFStringCompare(assertionNames[i], kIOPMAssertionTypeDisableRealPowerSources_Debug, 0))) 2466 { 2467 /* These are rarely used. So, print only if they are set */ 2468 if (val == 0) 2469 continue; 2470 } 2471 2472#if !TARGET_OS_EMBEDDED 2473 if ((kCFCompareEqualTo == CFStringCompare(assertionNames[i], kIOPMAssertionTypeEnableIdleSleep, 0)) || 2474 (kCFCompareEqualTo == CFStringCompare(assertionNames[i], kIOPMAssertionTypeSystemIsActive, 0))) 2475 continue; 2476#endif 2477 2478 CFStringGetCString(assertionNames[i], name, 50, kCFStringEncodingMacRoman); 2479 printf(" %-30s %d\n", name, val); 2480 } 2481 2482 free(assertionNames); 2483 free(assertionValues); 2484 CFRelease(assertions_status); 2485} 2486 2487static void show_assertions_individually(void) 2488{ 2489 CFDictionaryRef assertions_info = NULL; 2490 IOReturn ret; 2491 2492 ret = IOPMCopyAssertionsByProcess(&assertions_info); 2493 if ((kIOReturnSuccess != ret) || !assertions_info) { 2494 return; 2495 } 2496 2497// printf("\nListed by owning process:\n"); 2498 printf("Listed by owning process:\n"); 2499 if (!assertions_info) { 2500 printf(" None\n"); 2501 } else { 2502 2503 CFNumberRef *pids = NULL; 2504 CFArrayRef *assertions = NULL; 2505 int process_count; 2506 int i; 2507 2508 process_count = CFDictionaryGetCount(assertions_info); 2509 pids = malloc(sizeof(CFNumberRef)*process_count); 2510 assertions = malloc(sizeof(CFArrayRef *)*process_count); 2511 CFDictionaryGetKeysAndValues(assertions_info, 2512 (const void **)pids, 2513 (const void **)assertions); 2514 2515 for(i=0; i<process_count; i++) 2516 { 2517 int the_pid; 2518 int j; 2519 2520 CFNumberGetValue(pids[i], kCFNumberIntType, &the_pid); 2521 2522 for(j=0; j<CFArrayGetCount(assertions[i]); j++) 2523 { 2524 CFDictionaryRef tmp_dict = NULL; 2525 CFStringRef val_string = NULL; 2526 CFStringRef raw_localizable_string = NULL; 2527 CFStringRef localized_string = NULL; 2528 CFStringRef bundlePath = NULL; 2529 CFBundleRef bundle = NULL; 2530 CFURLRef _url = NULL; 2531 CFNumberRef uniqueID = NULL; 2532 CFBooleanRef power_limits = NULL; 2533 uint64_t uniqueID_int = 0; 2534 CFDateRef createdDate = NULL; 2535 CFAbsoluteTime createdCFTime = 0.0; 2536 char ageString[40]; 2537 CFStringRef pidName = NULL; 2538 char pid_name_buf[100]; 2539 2540 char all_assertions_buf[400]; 2541 char val_buf[300]; 2542 bool timed_out = false; 2543 2544 tmp_dict = CFArrayGetValueAtIndex(assertions[i], j); 2545 if(!tmp_dict) { 2546 goto exit; 2547 } 2548 2549 bzero(all_assertions_buf, sizeof(all_assertions_buf)); 2550 2551 val_string = CFDictionaryGetValue(tmp_dict, kIOPMAssertionTypeKey); 2552 if (val_string) { 2553 CFStringGetCString(val_string, all_assertions_buf, sizeof(all_assertions_buf), kCFStringEncodingMacRoman); 2554 } else { 2555 snprintf(all_assertions_buf, sizeof(all_assertions_buf), "Missing AssertType property"); 2556 } 2557 2558 val_string = CFDictionaryGetValue(tmp_dict, kIOPMAssertionNameKey); 2559 if (val_string) { 2560 CFStringGetCString(val_string, val_buf, sizeof(val_buf), kCFStringEncodingMacRoman); 2561 } 2562 2563 timed_out = CFDictionaryGetValue(tmp_dict, kIOPMAssertionTimedOutDateKey); 2564 2565 uniqueID = CFDictionaryGetValue(tmp_dict, kIOPMAssertionGlobalUniqueIDKey); 2566 if (uniqueID) { 2567 CFNumberGetValue(uniqueID, kCFNumberSInt64Type, &uniqueID_int); 2568 } 2569 2570 if ((createdDate = CFDictionaryGetValue(tmp_dict, kIOPMAssertionCreateDateKey))) 2571 { 2572 createdCFTime = CFDateGetAbsoluteTime(createdDate); 2573 int createdSince = (int)(CFAbsoluteTimeGetCurrent() - createdCFTime); 2574 int hours = createdSince / 3600; 2575 int minutes = (createdSince / 60) % 60; 2576 int seconds = createdSince % 60; 2577 snprintf(ageString, sizeof(ageString), "%02d:%02d:%02d ", hours, minutes, seconds); 2578 } 2579 2580 if ((pidName = CFDictionaryGetValue(tmp_dict, kIOPMAssertionProcessNameKey))) 2581 { 2582 CFStringGetCString(pidName, pid_name_buf, sizeof(pid_name_buf), kCFStringEncodingUTF8); 2583 } 2584 2585 printf(" pid %d(%s): [0x%016llx] %s%s named: \"%s\" %s\n", 2586 the_pid, pidName?pid_name_buf:"?", 2587 uniqueID_int, 2588 createdDate ? ageString:"", 2589 all_assertions_buf, 2590 val_string ? val_buf : "(error - no name)", 2591 timed_out ? "(timed out)" : ""); 2592 2593 val_string = CFDictionaryGetValue(tmp_dict, kIOPMAssertionDetailsKey); 2594 if (val_string) { 2595 CFStringGetCString(val_string, val_buf, sizeof(val_buf), kCFStringEncodingMacRoman); 2596 printf("\tDetails: %s\n", val_buf); 2597 } 2598 2599 raw_localizable_string = CFDictionaryGetValue(tmp_dict, kIOPMAssertionHumanReadableReasonKey); 2600 bundlePath = CFDictionaryGetValue(tmp_dict, kIOPMAssertionLocalizationBundlePathKey); 2601 2602 if (raw_localizable_string && bundlePath) { 2603 _url = CFURLCreateWithFileSystemPath(0, bundlePath, kCFURLPOSIXPathStyle, TRUE); 2604 if (_url) { 2605 bundle = CFBundleCreate(0, _url); 2606 CFRelease(_url); 2607 } 2608 if (bundle) { 2609 2610 localized_string = CFBundleCopyLocalizedString(bundle, raw_localizable_string, NULL, NULL); 2611 2612 if (localized_string) { 2613 if (CFStringGetCString(localized_string, val_buf, sizeof(val_buf), kCFStringEncodingUTF8)) { 2614 printf("\tLocalized=%s\n", val_buf); 2615 } 2616 CFRelease(localized_string); 2617 } 2618 } 2619 } // Localize & display human readable string 2620 2621 if ( (power_limits = CFDictionaryGetValue(tmp_dict, 2622 kIOPMAssertionAppliesToLimitedPowerKey)) ) { 2623 if ((CFBooleanGetValue(power_limits))) 2624 printf("\tAssertion applied on Battery power also\n"); 2625 else 2626 printf("\tAssertion applied on AC power only\n"); 2627 } 2628 2629 CFNumberRef timeoutNumCF = NULL; 2630 uint64_t timeout = 0; 2631 CFStringRef actionStr = NULL; 2632 char actionBuf[55]; 2633 CFDateRef updateDate = NULL; 2634 CFAbsoluteTime updateTime = 0; 2635 CFTimeInterval timeLeft = 0; 2636 CFAbsoluteTime now = CFAbsoluteTimeGetCurrent(); 2637 2638 if ( (timeoutNumCF = CFDictionaryGetValue(tmp_dict, kIOPMAssertionTimeoutTimeLeftKey))) 2639 { 2640 CFNumberGetValue(timeoutNumCF, kCFNumberIntType, &timeout); 2641 2642 updateDate = CFDictionaryGetValue(tmp_dict, kIOPMAssertionTimeoutUpdateTimeKey); 2643 if (updateDate) { 2644 updateTime = CFDateGetAbsoluteTime(updateDate); 2645 } 2646 2647 if (timeout && updateDate && ((timeLeft = updateTime+timeout-now) > 0)) { 2648 2649 actionStr = CFDictionaryGetValue(tmp_dict, kIOPMAssertionTimeoutActionKey); 2650 if (actionStr) { 2651 CFStringGetCString(actionStr, actionBuf, sizeof(actionBuf), kCFStringEncodingUTF8); 2652 } 2653 2654 printf("\tTimeout will fire in %.0f secs Action=%s\n", 2655 timeLeft, actionStr ? actionBuf : "<unknown action>"); 2656 } 2657 } 2658 } 2659 } 2660 } 2661 2662exit: 2663 if(assertions_info) 2664 CFRelease(assertions_info); 2665} 2666 2667static void print_descriptive_kernel_assertions(uint32_t val32) 2668{ 2669 bool first = false; 2670 if (0!= val32) 2671 printf("="); 2672 if (val32&kIOPMDriverAssertionCPUBit) { 2673 printf("CPU"); 2674 first = true; 2675 } 2676 if (val32&kIOPMDriverAssertionUSBExternalDeviceBit) { 2677 if (first) printf(","); 2678 first=true; 2679 printf("USB"); 2680 } 2681 if (val32&kIOPMDriverAssertionBluetoothHIDDevicePairedBit) { 2682 if (first) printf(","); 2683 first=true; 2684 printf("BT-HID"); 2685 } 2686 if (val32&kIOPMDriverAssertionExternalMediaMountedBit) { 2687 if (first) printf(","); 2688 first=true; 2689 printf("MEDIA"); 2690 } 2691 if (val32&kIOPMDriverAssertionReservedBit5) { 2692 if (first) printf(","); 2693 first=true; 2694 printf("THNDR"); 2695 } 2696 if (val32&kIOPMDriverAssertionPreventDisplaySleepBit) { 2697 if (first) printf(","); 2698 first=true; 2699 printf("DSPLY"); 2700 } 2701 if (val32&kIOPMDriverAssertionReservedBit7) { 2702 if (first) printf(","); 2703 first=true; 2704 printf("STORAGE"); 2705 } 2706 if (val32&kIOPMDriverAssertionMagicPacketWakeEnabledBit) { 2707 if (first) printf(","); 2708 first=true; 2709 printf("MAGICWAKE"); 2710 } 2711 return; 2712} 2713 2714static void show_assertions_in_kernel(void) 2715{ 2716 CFMutableDictionaryRef rootDomainProperties = NULL; 2717 2718 CFArrayRef kernelAssertionsArray = NULL; 2719 CFNumberRef kernelAssertions = NULL; 2720 int kernelAssertionsSum = 0; 2721 int count; 2722 int i; 2723 io_registry_entry_t rootDomain = copyRootDomainRef(); 2724 2725 IORegistryEntryCreateCFProperties(rootDomain, &rootDomainProperties, 0, 0); 2726 2727 if (rootDomainProperties) 2728 { 2729 kernelAssertions = CFDictionaryGetValue(rootDomainProperties, CFSTR(kIOPMAssertionsDriverKey)); 2730 if (kernelAssertions) { 2731 CFNumberGetValue(kernelAssertions, kCFNumberIntType, &kernelAssertionsSum); 2732 } 2733 2734 kernelAssertionsArray = CFDictionaryGetValue(rootDomainProperties, CFSTR(kIOPMAssertionsDriverDetailedKey)); 2735 } 2736 2737 if (0 == kernelAssertionsSum) { 2738 printf("No kernel assertions.\n"); 2739// printf("\nNo kernel assertions.\n"); 2740 return; 2741 } 2742 2743 printf("Kernel Assertions: 0x%x", kernelAssertionsSum); 2744// printf("\nKernel Assertions: 0x%x", kernelAssertionsSum); 2745 print_descriptive_kernel_assertions(kernelAssertionsSum); 2746 printf("\n"); 2747 2748 if (!kernelAssertionsArray 2749 || !(count = CFArrayGetCount(kernelAssertionsArray))) 2750 { 2751 printf(" None"); 2752 } else { 2753 CFDictionaryRef whichAssertion = NULL; 2754 CFStringRef ownerString = NULL; 2755 char ownerBuf[100]; 2756 io_name_t serviceNameBuf; 2757 CFNumberRef registryEntryID = NULL; 2758 CFNumberRef n_id = NULL; 2759 CFNumberRef n_modified = NULL; 2760 CFNumberRef n_owner = NULL; 2761 CFNumberRef n_level = NULL; 2762 CFNumberRef n_asserted = NULL; 2763 uint64_t val64=0; 2764 uint32_t val32=0; 2765 2766 for (i=0; i<count; i++) 2767 { 2768 whichAssertion = isA_CFDictionary(CFArrayGetValueAtIndex(kernelAssertionsArray, i)); 2769 if (!whichAssertion) 2770 continue; 2771#ifndef kIOPMDriverRegistryEntryIDKey 2772#define kIOPMDriverRegistryEntryIDKey "RegistryEntryID" 2773#endif 2774 ownerString = CFDictionaryGetValue(whichAssertion, CFSTR(kIOPMDriverAssertionOwnerStringKey)); 2775 registryEntryID = CFDictionaryGetValue(whichAssertion, CFSTR(kIOPMDriverRegistryEntryIDKey)); 2776 n_id = CFDictionaryGetValue(whichAssertion, CFSTR(kIOPMDriverAssertionIDKey)); 2777 n_modified = CFDictionaryGetValue(whichAssertion, CFSTR(kIOPMDriverAssertionModifiedTimeKey)); 2778 n_owner = CFDictionaryGetValue(whichAssertion, CFSTR(kIOPMDriverAssertionOwnerServiceKey)); 2779 n_level = CFDictionaryGetValue(whichAssertion, CFSTR(kIOPMDriverAssertionLevelKey)); 2780 n_asserted = CFDictionaryGetValue(whichAssertion, CFSTR(kIOPMDriverAssertionAssertedKey)); 2781 2782 2783 CFAbsoluteTime modifiedTime = 1.0; 2784 uint32_t level = 0; 2785 2786 if (n_modified && CFNumberGetValue(n_modified, kCFNumberSInt64Type, &val64)) { 2787 modifiedTime = _CFAbsoluteTimeFromPMEventTimeStamp(val64); 2788 } 2789 if (n_level) { 2790 CFNumberGetValue(n_level, kCFNumberSInt32Type, &level); 2791 } 2792 2793 if (level != kIOPMAssertionLevelOff) 2794 { 2795 if (n_id && CFNumberGetValue(n_id, kCFNumberSInt64Type, &val64)) { 2796 printf(" id=%ld ", (long)val64); 2797 } 2798 if (n_owner && CFNumberGetValue(n_owner, kCFNumberSInt64Type, &val64)) { 2799 printf("by [0x%016lx]", (unsigned long)val64); 2800 } 2801 2802 if (n_asserted) { 2803 if (CFNumberGetValue(n_asserted, kCFNumberSInt32Type, &val32)) { 2804 printf(" level=%d 0x%x", level, val32); 2805 print_descriptive_kernel_assertions(val32); 2806 } 2807 } 2808 printf(" mod="); 2809 print_short_date(modifiedTime, false); 2810 if (ownerString && 2811 CFStringGetCString(ownerString, ownerBuf, sizeof(ownerBuf), kCFStringEncodingUTF8)) 2812 { 2813 printf("description=%s ", ownerBuf); 2814 } 2815 2816 if (registryEntryID && CFNumberGetValue(registryEntryID, kCFNumberSInt64Type, &val64)) 2817 { 2818 io_service_t match = IO_OBJECT_NULL; 2819 match = IOServiceGetMatchingService(kIOMasterPortDefault, IORegistryEntryIDMatching(val64)); 2820 if (match) { 2821 IORegistryEntryGetName(match, serviceNameBuf); 2822 printf("owner=%s", serviceNameBuf); 2823 IOObjectRelease(match); 2824 } 2825 } 2826 printf("\n"); 2827 } 2828 } 2829 } 2830 CFRelease(rootDomainProperties); 2831} 2832static void show_assertions(const char *decorate) 2833{ 2834 print_pretty_date(CFAbsoluteTimeGetCurrent(), decorate?false:true); 2835 if (decorate) { 2836 printf("%s\n", decorate); 2837 } 2838 2839 show_assertions_system_aggregates(); 2840 show_assertions_individually(); 2841 show_assertions_in_kernel(); 2842 2843 return; 2844} 2845 2846static void log_assertions(void) 2847{ 2848 int token; 2849 int notify_status; 2850 2851 IOPMAssertionNotify(kIOPMAssertionsAnyChangedNotifyString, kIOPMNotifyRegister); 2852 notify_status = notify_register_dispatch( 2853 kIOPMAssertionsAnyChangedNotifyString, 2854 &token, 2855 dispatch_get_main_queue(), 2856 ^(int t) { 2857 show_assertions(NULL); 2858 }); 2859 2860 if (NOTIFY_STATUS_OK != notify_status) { 2861 printf("Could not get notification for %s. Exiting.\n", 2862 kIOPMAssertionsAnyChangedNotifyString); 2863 return; 2864 } 2865 2866 printf("Logging all assertion changes.\n"); 2867 show_assertions(NULL); 2868 2869 dispatch_main(); 2870} 2871 2872/******************************************************************************/ 2873 2874static const char *stringForGTLevel(int gtl) 2875{ 2876 if (kIOSystemLoadAdvisoryLevelGreat == gtl) { 2877 return "Great"; 2878 } else if (kIOSystemLoadAdvisoryLevelOK == gtl) { 2879 return "OK"; 2880 } else if (kIOSystemLoadAdvisoryLevelBad == gtl) { 2881 return "Bad"; 2882 } 2883 return "(Unknown system load level)"; 2884} 2885 2886static void show_systemload(void) 2887{ 2888 CFDictionaryRef detailed = NULL; 2889 CFNumberRef n = NULL; 2890 int userLevel = kIOSystemLoadAdvisoryLevelOK; 2891 int batteryLevel = kIOSystemLoadAdvisoryLevelOK; 2892 int thermalLevel = kIOSystemLoadAdvisoryLevelOK; 2893 int combinedLevel = kIOSystemLoadAdvisoryLevelOK; 2894 2895 print_pretty_date(CFAbsoluteTimeGetCurrent(), true); 2896 2897 combinedLevel = IOGetSystemLoadAdvisory(); 2898 if (0 == combinedLevel) { 2899 printf("- Internal error: IOGetSystemLoadAdvisory returns error value %d\n", combinedLevel); 2900 return; 2901 } 2902 2903 detailed = IOCopySystemLoadAdvisoryDetailed(); 2904 if (!detailed) { 2905 printf("- Internal error: Invalid dictionary %p returned from IOCopySystemLoadAdvisoryDetailed.\n", detailed); 2906 return; 2907 } 2908 2909 n = CFDictionaryGetValue(detailed, kIOSystemLoadAdvisoryUserLevelKey); 2910 if (n) { 2911 CFNumberGetValue(n, kCFNumberIntType, &userLevel); 2912 } 2913 n = CFDictionaryGetValue(detailed, kIOSystemLoadAdvisoryBatteryLevelKey); 2914 if (n) { 2915 CFNumberGetValue(n, kCFNumberIntType, &batteryLevel); 2916 } 2917 n = CFDictionaryGetValue(detailed, kIOSystemLoadAdvisoryThermalLevelKey); 2918 if (n) { 2919 CFNumberGetValue(n, kCFNumberIntType, &thermalLevel); 2920 } 2921 CFRelease(detailed); 2922 2923 printf(" combined level = %s\n", stringForGTLevel(combinedLevel)); 2924 printf(" - user level = %s\n", stringForGTLevel(userLevel)); 2925 printf(" - battery level = %s\n", stringForGTLevel(batteryLevel)); 2926 printf(" - thermal level = %s\n", stringForGTLevel(thermalLevel)); 2927 fflush(stdout); 2928 2929 return; 2930} 2931 2932static void log_systemload(void) 2933{ 2934 int token = 0; 2935 uint32_t notify_status = 0; 2936 2937 show_systemload(); 2938 2939 notify_status = notify_register_dispatch( 2940 kIOSystemLoadAdvisoryNotifyName, 2941 &token, 2942 dispatch_get_main_queue(), 2943 ^(int t) { 2944 show_systemload(); 2945 }); 2946 2947 if (NOTIFY_STATUS_OK != notify_status) 2948 { 2949 printf("LogSystemLoad: notify_register_dispatch returns error %d; Exiting.\n", notify_status); 2950 return; 2951 } 2952 2953 dispatch_main(); 2954} 2955 2956static void log_useractivity() 2957{ 2958 int notifyToken = 0; 2959 int status; 2960 uint64_t newVal=0xabcd; 2961 2962 status = notify_register_check(kIOUserActivityNotifyName, ¬ifyToken); 2963 if (NOTIFY_STATUS_OK == status) 2964 { 2965 notify_get_state(notifyToken, &newVal); 2966 notify_cancel(notifyToken); 2967 2968 print_pretty_date(CFAbsoluteTimeGetCurrent(), false); 2969 if (newVal == kIOUserIsIdle) 2970 printf("User is idle on the system\n"); 2971 else 2972 printf("User is active on the system\n"); 2973 } 2974 2975} 2976 2977static void log_useractivitylog() 2978{ 2979 int token = 0; 2980 uint32_t notify_status = 0; 2981 int notifyToken = 0; 2982 int status; 2983 uint64_t newVal=0xabcd; 2984 2985 status = notify_register_check(kIOUserActivityNotifyName, ¬ifyToken); 2986 if (NOTIFY_STATUS_OK == status) 2987 { 2988 notify_get_state(notifyToken, &newVal); 2989 notify_cancel(notifyToken); 2990 2991 print_pretty_date(CFAbsoluteTimeGetCurrent(), false); 2992 if (newVal == kIOUserIsIdle) 2993 printf("User is idle on the system\n"); 2994 else 2995 printf("User is active on the system\n"); 2996 } 2997 2998 notify_status = notify_register_dispatch( 2999 kIOUserActivityNotifyName, 3000 &token, 3001 dispatch_get_main_queue(), 3002 ^(int t) { 3003 uint64_t newVal; 3004 notify_get_state(t, &newVal); 3005 3006 print_pretty_date(CFAbsoluteTimeGetCurrent(), false); 3007 if (newVal == kIOUserIsIdle) 3008 printf("User is idle on the system\n"); 3009 else 3010 printf("User is active on the system\n"); 3011 }); 3012 3013 if (NOTIFY_STATUS_OK != notify_status) 3014 { 3015 printf("LogSystemLoad: notify_register_dispatch returns error %d; Exiting.\n", notify_status); 3016 return; 3017 } 3018 3019 3020 3021 dispatch_main(); 3022 3023} 3024 3025/******************************************************************************/ 3026 3027static void log_ps_change_handler(void *info) 3028{ 3029 int which = (uintptr_t)info; 3030 3031 if (!(which & kShowColumns)) { 3032 print_pretty_date(CFAbsoluteTimeGetCurrent(), false); 3033 printf("IOPSNotificationCreateRunLoopSource\n"); 3034 } 3035 show_power_sources(which); 3036} 3037 3038static int install_listen_for_power_sources(uintptr_t which) 3039{ 3040 CFRunLoopSourceRef rls = NULL; 3041 3042 /* Log changes to all attached power sources */ 3043 rls = IOPSNotificationCreateRunLoopSource(log_ps_change_handler, (void *)which); 3044 if(!rls) { 3045 printf("Error - IOPSNotificationCreateRunLoopSource failure.\n"); 3046 return kParseInternalError; 3047 } else { 3048 CFRunLoopAddSource(CFRunLoopGetCurrent(), rls, kCFRunLoopDefaultMode); 3049 CFRelease(rls); 3050 3051 printf("pmset is in logging mode now. Hit ctrl-c to exit.\n"); 3052 3053 if (kShowColumns & which) 3054 { 3055 printf("%10s\t%15s\t%10s\t%10s\t%20s\n", 3056 "Elapsed", "TimeRemaining", "Charge", "Charging", "Timestamp"); 3057 } 3058 3059 // and show initial power source state: 3060 log_ps_change_handler((void *)which); 3061 } 3062 3063 if (!(which & kShowColumns)) { 3064 int tokenA, tokenB, tokenC; 3065 3066 notify_register_dispatch(kIOPSNotifyLowBattery, 3067 &tokenA, dispatch_get_main_queue(), 3068 ^(int t) { 3069 print_pretty_date(CFAbsoluteTimeGetCurrent(), false); 3070 printf("%s\n", kIOPSNotifyLowBattery); 3071 }); 3072 3073 notify_register_dispatch(kIOPSNotifyTimeRemaining, 3074 &tokenB, dispatch_get_main_queue(), 3075 ^(int t) { 3076 print_pretty_date(CFAbsoluteTimeGetCurrent(), false); 3077 printf("%s\n", kIOPSNotifyTimeRemaining); 3078 }); 3079 notify_register_dispatch(kIOPSNotifyPowerSource, 3080 &tokenC, dispatch_get_main_queue(), 3081 ^(int t) { 3082 print_pretty_date(CFAbsoluteTimeGetCurrent(), false); 3083 printf("%s\n", kIOPSNotifyPowerSource); 3084 }); 3085 notify_register_dispatch(kIOPSNotifyAttach, 3086 &tokenC, dispatch_get_main_queue(), 3087 ^(int t) { 3088 print_pretty_date(CFAbsoluteTimeGetCurrent(), false); 3089 printf("%s\n", kIOPSNotifyAttach); 3090 }); 3091 notify_register_dispatch(kIOPSNotifyAnyPowerSource, 3092 &tokenC, dispatch_get_main_queue(), 3093 ^(int t) { 3094 print_pretty_date(CFAbsoluteTimeGetCurrent(), false); 3095 printf("%s\n", kIOPSNotifyAnyPowerSource); 3096 }); 3097 } 3098 3099 return 0; 3100} 3101 3102 3103 3104 3105/******************************************************************************/ 3106/* */ 3107/* RAW PS LOGGING */ 3108/* */ 3109/******************************************************************************/ 3110 3111static CFAbsoluteTime getAbsoluteTimeForProperty(CFDictionaryRef d, CFStringRef key) 3112{ 3113 CFNumberRef secSince1970 = NULL; 3114 uint32_t secs = 0; 3115 CFAbsoluteTime return_val = 0.0; 3116 3117 if (d && key) 3118 { 3119 secSince1970 = CFDictionaryGetValue(d, key); 3120 if (secSince1970) { 3121 CFNumberGetValue(secSince1970, kCFNumberIntType, &secs); 3122 return_val = (CFAbsoluteTime)secs - kCFAbsoluteTimeIntervalSince1970; 3123 CFRelease(secSince1970); 3124 } 3125 } 3126 3127 return return_val; 3128} 3129 3130static void print_raw_battery_state(io_registry_entry_t b_reg) 3131{ 3132 CFDateFormatterRef date_format; 3133 CFTimeZoneRef tz; 3134 CFStringRef time_date; 3135 CFLocaleRef loc; 3136 char _date[60]; 3137 3138 CFStringRef failure; 3139 char _failure[200]; 3140 CFBooleanRef boo; 3141 CFNumberRef n; 3142 int tmp; 3143 int cur_cap = -1; 3144 int max_cap = -1; 3145 int design_cap = -1; 3146 int cur_cycles = -1; 3147 CFMutableDictionaryRef prop = NULL; 3148 IOReturn ret; 3149 3150 loc = CFLocaleCopyCurrent(); 3151 date_format = CFDateFormatterCreate(kCFAllocatorDefault, loc, 3152 kCFDateFormatterShortStyle, kCFDateFormatterLongStyle); 3153 CFRelease(loc); 3154 tz = CFTimeZoneCopySystem(); 3155 CFDateFormatterSetProperty(date_format, kCFDateFormatterTimeZone, tz); 3156 CFRelease(tz); 3157 CFDateFormatterSetFormat(date_format, CFSTR(kDateAndTimeFormat)); 3158 time_date = CFDateFormatterCreateStringWithAbsoluteTime(kCFAllocatorDefault, 3159 date_format, CFAbsoluteTimeGetCurrent()); 3160 3161 if(time_date) 3162 { 3163 CFStringGetCString(time_date, _date, 60, kCFStringEncodingMacRoman); 3164 printf("%s\n", _date); fflush(stdout); 3165 CFRelease(time_date); 3166 } 3167 3168 if (IO_OBJECT_NULL == b_reg) { 3169 b_reg = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("AppleSmartBattery")); 3170 } 3171 3172 ret = IORegistryEntryCreateCFProperties(b_reg, &prop, 0, 0); 3173 if( (kIOReturnSuccess != ret) || (NULL == prop) ) 3174 { 3175 printf("Couldn't read battery status; error = 0%08x\n", ret); 3176 return; 3177 } 3178 3179 boo = CFDictionaryGetValue(prop, CFSTR(kIOPMPSExternalConnectedKey)); 3180 printf(" %s; ", (kCFBooleanTrue == boo) ? "AC" : "No AC"); 3181 3182 boo = CFDictionaryGetValue(prop, CFSTR(kIOPMPSBatteryInstalledKey)); 3183 printf("%s", (kCFBooleanTrue == boo) ? "" : "No battery; "); 3184 3185 boo = CFDictionaryGetValue(prop, CFSTR(kIOPMPSIsChargingKey)); 3186 printf("%s; ", (kCFBooleanTrue == boo) ? "Charging" : "Not Charging"); 3187 3188 n = CFDictionaryGetValue(prop, CFSTR(kIOPMPSCurrentCapacityKey)); 3189 if(n) { 3190 CFNumberGetValue(n, kCFNumberIntType, &cur_cap); 3191 } 3192 n = CFDictionaryGetValue(prop, CFSTR(kIOPMPSMaxCapacityKey)); 3193 if(n) { 3194 CFNumberGetValue(n, kCFNumberIntType, &max_cap); 3195 } 3196 n = CFDictionaryGetValue(prop, CFSTR(kIOPMPSDesignCapacityKey)); 3197 if(n) { 3198 CFNumberGetValue(n, kCFNumberIntType, &design_cap); 3199 } 3200 3201 if( (-1 != cur_cap) && (-1 != max_cap) ) 3202 { 3203 if (0 == max_cap) { 3204 printf("NaN%%; Cap=%d: FCC=%d; Design=%d; ", cur_cap, max_cap, design_cap); 3205 } else { 3206 printf("%d%%; Cap=%d: FCC=%d; Design=%d; ", (cur_cap*100)/max_cap, cur_cap, max_cap, design_cap); 3207 } 3208 } 3209 3210 n = CFDictionaryGetValue(prop, CFSTR(kIOPMPSTimeRemainingKey)); 3211 if(n) { 3212 CFNumberGetValue(n, kCFNumberIntType, &tmp); 3213 printf("Time=%d:%02d; ", tmp/60, tmp%60); 3214 } 3215 n = CFDictionaryGetValue(prop, CFSTR(kIOPMPSAmperageKey)); 3216 if(n) { 3217 CFNumberGetValue(n, kCFNumberIntType, &tmp); 3218 printf("%dmA; ", tmp); 3219 } 3220 n = CFDictionaryGetValue(prop, CFSTR(kIOPMPSCycleCountKey)); 3221 if(n) { 3222 CFNumberGetValue(n, kCFNumberIntType, &cur_cycles); 3223 } 3224 3225 printf("Cycles=%d", cur_cycles); 3226 n = CFDictionaryGetValue(prop, CFSTR(kIOPMPSLocationKey)); 3227 if(n) { 3228 CFNumberGetValue(n, kCFNumberIntType, &tmp); 3229 printf("; Location=%d; ", tmp); 3230 } 3231 3232 failure = CFDictionaryGetValue(prop, CFSTR("ErrorCondition")); 3233 if(failure) { 3234 CFStringGetCString(failure, _failure, 200, kCFStringEncodingMacRoman); 3235 printf("\n Failure=\"%s\"", _failure); 3236 } 3237 3238#ifndef kIOBatteryBootPathKey 3239#define kIOBatteryBootPathKey "BootPathUpdated" 3240#define kIOBatteryFullPathKey "FullPathUpdated" 3241#define kIOBatterykUserVisPathKey "UserVisiblePathUpdated" 3242#endif 3243 3244 printf("\n"); 3245 CFAbsoluteTime since = 0.0; 3246 CFStringRef since_string = NULL; 3247 char since_str[65]; 3248 since = getAbsoluteTimeForProperty(prop, CFSTR(kIOBatteryBootPathKey)); 3249 if (0.0 != since) { 3250 since_string = CFDateFormatterCreateStringWithAbsoluteTime(0, date_format, since); 3251 CFStringGetCString(since_string, since_str, sizeof(since_str), kCFStringEncodingUTF8); 3252 printf(" Polled boot=%s", since_str); 3253 CFRelease(since_string); 3254 } 3255 since = getAbsoluteTimeForProperty(prop, CFSTR(kIOBatteryFullPathKey)); 3256 if (0.0 != since) { 3257 since_string = CFDateFormatterCreateStringWithAbsoluteTime(0, date_format, since); 3258 CFStringGetCString(since_string, since_str, sizeof(since_str), kCFStringEncodingUTF8); 3259 printf("; Full=%s", since_str); 3260 CFRelease(since_string); 3261 } 3262 since = getAbsoluteTimeForProperty(prop, CFSTR(kIOBatterykUserVisPathKey)); 3263 if (0.0 != since) { 3264 since_string = CFDateFormatterCreateStringWithAbsoluteTime(0, date_format, since); 3265 CFStringGetCString(since_string, since_str, sizeof(since_str), kCFStringEncodingUTF8); 3266 printf("; User visible=%s", since_str); 3267 CFRelease(since_string); 3268 } 3269 printf("\n"); fflush(stdout); 3270 3271 CFRelease(date_format); 3272 CFRelease(prop); 3273 return; 3274} 3275 3276 3277static void log_raw_battery_match( 3278 void *refcon, 3279 io_iterator_t b_iter) 3280{ 3281 IONotificationPortRef notify = *((IONotificationPortRef *)refcon); 3282 io_registry_entry_t battery; 3283 io_object_t notification_ref; 3284 int found = false; 3285 3286 while ((battery = (io_registry_entry_t)IOIteratorNext(b_iter))) 3287 { 3288 found = true; 3289 printf(" * Battery matched at registry = %d\n", (int32_t)battery); 3290 3291 print_raw_battery_state(battery); 3292 3293 // And install an interest notification on it 3294 IOServiceAddInterestNotification(notify, battery, 3295 kIOGeneralInterest, log_raw_battery_interest, 3296 NULL, ¬ification_ref); 3297 3298 IOObjectRelease(battery); 3299 } 3300 3301 if(!found) { 3302 printf(" (no batteries found; waiting)\n"); 3303 } 3304} 3305 3306 3307static void log_raw_battery_interest( 3308 void *refcon, 3309 io_service_t batt, 3310 natural_t messageType, 3311 void *messageArgument) 3312{ 3313 if(kIOPMMessageBatteryStatusHasChanged == messageType) 3314 { 3315 print_raw_battery_state((io_registry_entry_t)batt); 3316 3317 } 3318 return; 3319} 3320 3321static int log_raw_power_source_changes(void) 3322{ 3323 IONotificationPortRef notify_port = 0; 3324 io_iterator_t battery_iter = 0; 3325 CFRunLoopSourceRef rlser = 0; 3326 IOReturn ret; 3327 3328 printf("pmset is in RAW logging mode now. Hit ctrl-c to exit.\n"); 3329 3330 notify_port = IONotificationPortCreate(0); 3331 rlser = IONotificationPortGetRunLoopSource(notify_port); 3332 if(!rlser) return 0; 3333 CFRunLoopAddSource(CFRunLoopGetCurrent(), rlser, kCFRunLoopDefaultMode); 3334 3335 3336 ret = IOServiceAddMatchingNotification( 3337 notify_port, 3338 kIOFirstMatchNotification, 3339 IOServiceMatching("IOPMPowerSource"), 3340 log_raw_battery_match, 3341 (void *)¬ify_port, 3342 &battery_iter); 3343 if(KERN_SUCCESS != ret){ 3344 printf("!!Error prevented matching notifications; err = 0x%08x\n", ret); 3345 } 3346 3347 // Install notifications on existing instances. 3348 log_raw_battery_match((void *)¬ify_port, battery_iter); 3349 3350 CFRunLoopRun(); 3351 3352 // should never return from CFRunLoopRun 3353 return 0; 3354} 3355 3356 3357static void show_systempower_notify(void) 3358{ 3359 IOPMCapabilityBits b; 3360 char stateDescriptionStr[100]; 3361 3362 b = IOPMConnectionGetSystemCapabilities(); 3363 3364 IOPMGetCapabilitiesDescription(stateDescriptionStr, sizeof(stateDescriptionStr), b); 3365 3366 print_pretty_date(CFAbsoluteTimeGetCurrent(), false); 3367 printf("com.apple.powermanagement.systempowerstate=%s\n", stateDescriptionStr); 3368 3369 return; 3370} 3371 3372static void install_listen_for_notify_system_power(void) 3373{ 3374 uint32_t status; 3375 int token; 3376 3377 printf("Logging: com.apple.powermanagement.systempowerstate\n"); 3378 3379 status = notify_register_dispatch( 3380 kIOSystemLoadAdvisoryNotifyName, 3381 &token, 3382 dispatch_get_main_queue(), 3383 ^(int t) { 3384 show_systempower_notify(); 3385 }); 3386 3387 if (NOTIFY_STATUS_OK != status) { 3388 fprintf(stderr, "Registration failed for \"%s\" with (%u)\n", 3389 kIOPMSystemPowerStateNotify, status); 3390 } 3391 3392} 3393 3394/*************************************************************************/ 3395 3396void myPMConnectionHandler( 3397 void *param, 3398 IOPMConnection connection, 3399 IOPMConnectionMessageToken token, 3400 IOPMSystemPowerStateCapabilities capabilities) 3401{ 3402#if TARGET_OS_EMBEDDED 3403 return; 3404#else 3405 char stateDescriptionStr[100]; 3406 IOReturn ret; 3407 3408 printf("\n"); 3409 print_pretty_date(CFAbsoluteTimeGetCurrent(), true); 3410 IOPMGetCapabilitiesDescription(stateDescriptionStr, sizeof(stateDescriptionStr), (uint64_t)capabilities); 3411 3412 printf("PMConnection: %s caps:0x%x\n", stateDescriptionStr, capabilities); 3413 3414 IOPMSystemPowerStateCapabilities fromAPI = IOPMConnectionGetSystemCapabilities(); 3415 if (capabilities != fromAPI) 3416 { 3417 printf("PMConnection: API IOPMConnectionGetSystemCapabilities() returns 0x%04x, should have returned 0x%04x\n", (uint32_t)fromAPI, (uint32_t)capabilities); 3418 } 3419 3420 if (!(kIOPMCapabilityCPU & capabilities)) 3421 { 3422 printSleepAndWakeReasons(kJustPrintSleep); 3423 } else { 3424 printSleepAndWakeReasons(kJustPrintWake); 3425 } 3426 3427 ret = IOPMConnectionAcknowledgeEvent(connection, token); 3428 if (kIOReturnSuccess != ret) 3429 { 3430 printf("\t-> PM Connection acknowledgement error 0x%08x\n", ret); 3431 } 3432#endif /* TARGET_OS_EMBEDDED */ 3433} 3434 3435static void install_listen_PM_connection(void) 3436{ 3437#if TARGET_OS_EMBEDDED 3438 return; 3439#else 3440 IOPMConnection myConnection; 3441 IOReturn ret; 3442 3443 printf("Logging IOPMConnection\n"); 3444 3445 ret = IOPMConnectionCreate( 3446 CFSTR("SleepWakeLogTool"), 3447 kIOPMEarlyWakeNotification 3448 | kIOPMCapabilityCPU 3449 | kIOPMCapabilityDisk 3450 | kIOPMCapabilityNetwork 3451 | kIOPMCapabilityAudio 3452 | kIOPMCapabilityVideo 3453 | kIOPMCapabilityPushServiceTask 3454 | kIOPMCapabilityBackgroundTask 3455 | kIOPMCapabilitySilentRunning, 3456 &myConnection); 3457 3458 if (kIOReturnSuccess != ret) { 3459 printf("IOPMConnectionCreate Create: Error 0x%08x\n", ret); 3460 return; 3461 } 3462 3463 ret = IOPMConnectionSetNotification( 3464 myConnection, NULL, 3465 (IOPMEventHandlerType)myPMConnectionHandler); 3466 3467 if (kIOReturnSuccess != ret) { 3468 printf("IOPMConnectionCreate SetNotification: Error 0x%08x\n", ret); 3469 return; 3470 } 3471 3472 ret = IOPMConnectionScheduleWithRunLoop( 3473 myConnection, CFRunLoopGetCurrent(), 3474 kCFRunLoopDefaultMode); 3475 3476 if (kIOReturnSuccess != ret) { 3477 printf("IOPMConnection ScheduleWithRunloop: Error 0x%08x\n", ret); 3478 return; 3479 } 3480#endif /* TARGET_OS_EMBEDDED */ 3481} 3482 3483static void install_listen_com_apple_powermanagement_sleepservices_notify(void) 3484{ 3485 int token; 3486 int status; 3487 3488 status = notify_register_dispatch(kIOPMSleepServiceActiveNotifyName, &token, dispatch_get_main_queue(), 3489 ^(int t) { 3490 if (IOPMGetSleepServicesActive()) { 3491 printf("SleepServices are: ON\n"); 3492 } else { 3493 printf("SleepServices are: OFF\n"); 3494 } 3495 }); 3496 3497 3498 if (NOTIFY_STATUS_OK != status) { 3499 fprintf(stderr, "Registration failed for \"%s\" with (%u)\n", 3500 kIOPMSleepServiceActiveNotifyName, status); 3501 } 3502 3503 if (IOPMGetSleepServicesActive()) { 3504 printf("SleepServices are: ON\n"); 3505 } else { 3506 printf("SleepServices are: OFF\n"); 3507 } 3508} 3509 3510static void install_listen_IORegisterForSystemPower(void) 3511{ 3512 io_object_t root_notifier = MACH_PORT_NULL; 3513 IONotificationPortRef notify = NULL; 3514 3515 printf("Logging IORegisterForSystemPower sleep/wake messages\n"); 3516 3517 /* Log sleep/wake messages */ 3518 gPMAckPort = IORegisterForSystemPower ( 3519 (void *)kLogSleepEvents, ¬ify, 3520 sleepWakeCallback, &root_notifier); 3521 3522 if( notify && (MACH_PORT_NULL != gPMAckPort) ) 3523 { 3524 CFRunLoopAddSource(CFRunLoopGetCurrent(), 3525 IONotificationPortGetRunLoopSource(notify), 3526 kCFRunLoopDefaultMode); 3527 } 3528 3529 return; 3530} 3531 3532static void listen_for_everything(void) 3533{ 3534 install_listen_for_power_sources(kApplyToBattery | kApplyToUPS); 3535 install_listen_for_notify_system_power(); 3536 install_listen_PM_connection(); 3537 install_listen_IORegisterForSystemPower(); 3538 install_listen_com_apple_powermanagement_sleepservices_notify(); 3539 3540 CFRunLoopRun(); 3541 // should never return from CFRunLoopRun 3542} 3543 3544static void log_thermal_events(void) 3545{ 3546 int powerConstraintNotifyToken = 0; 3547 int cpuPowerNotifyToken = 0; 3548 3549 uint32_t status; 3550 3551 3552 status = notify_register_dispatch( 3553 kIOPMCPUPowerNotificationKey, 3554 &cpuPowerNotifyToken, 3555 dispatch_get_main_queue(), 3556 ^(int t) { 3557 show_thermal_cpu_power_level(); 3558 }); 3559 3560 3561 if (NOTIFY_STATUS_OK != status) { 3562 fprintf(stderr, "Registration failed for \"%s\" with (%u)\n", 3563 kIOPMCPUPowerNotificationKey, status); 3564 } 3565 3566 3567 status = notify_register_dispatch( 3568 kIOPMThermalWarningNotificationKey, 3569 &powerConstraintNotifyToken, 3570 dispatch_get_main_queue(), 3571 ^(int t) { 3572 show_thermal_warning_level(); 3573 }); 3574 3575 3576 if (NOTIFY_STATUS_OK != status) 3577 { 3578 fprintf(stderr, "Registration failed for \"%s\" with (%u)\n", 3579 kIOPMThermalWarningNotificationKey, status); 3580 } 3581 3582 show_thermal_warning_level(); 3583 show_thermal_cpu_power_level(); 3584 3585 dispatch_main(); 3586} 3587 3588 3589static void show_thermal_warning_level(void) 3590{ 3591 uint32_t warn = -1; 3592 IOReturn ret; 3593 3594 ret = IOPMGetThermalWarningLevel(&warn); 3595 3596 if (kIOReturnNotFound == ret) { 3597 printf("Note: No thermal warning level has been recorded\n"); 3598 return; 3599 } 3600 3601 if (kIOReturnSuccess != ret) 3602 { 3603 printf("Error: No thermal warning level with error code 0x%08x\n", ret); 3604 return; 3605 } 3606 3607 // successfully found warning level 3608 print_pretty_date(CFAbsoluteTimeGetCurrent(), false); 3609 printf("Thermal Warning Level = %d\n", warn); 3610 return; 3611} 3612 3613 3614static void show_thermal_cpu_power_level(void) 3615{ 3616 CFDictionaryRef cpuStatus; 3617 CFStringRef *keys = NULL; 3618 CFNumberRef *vals = NULL; 3619 int count = 0; 3620 int i; 3621 IOReturn ret; 3622 3623 ret = IOPMCopyCPUPowerStatus(&cpuStatus); 3624 3625 if (kIOReturnNotFound == ret) { 3626 printf("Note: No CPU power status has been recorded\n"); 3627 return; 3628 } 3629 3630 if (!cpuStatus || (kIOReturnSuccess != ret)) 3631 { 3632 printf("Error: No CPU power status with error code 0x%08x\n", ret); 3633 return; 3634 } 3635 3636 print_pretty_date(CFAbsoluteTimeGetCurrent(), false); 3637 fprintf(stderr, "CPU Power notify\n"), fflush(stderr); 3638 3639 count = CFDictionaryGetCount(cpuStatus); 3640 keys = (CFStringRef *)malloc(count*sizeof(CFStringRef)); 3641 vals = (CFNumberRef *)malloc(count*sizeof(CFNumberRef)); 3642 if (!keys||!vals) 3643 goto exit; 3644 3645 CFDictionaryGetKeysAndValues(cpuStatus, 3646 (const void **)keys, (const void **)vals); 3647 3648 for(i=0; i<count; i++) { 3649 char strbuf[125]; 3650 int valint; 3651 3652 CFStringGetCString(keys[i], strbuf, 125, kCFStringEncodingUTF8); 3653 CFNumberGetValue(vals[i], kCFNumberIntType, &valint); 3654 printf("\t%s \t= %d\n", strbuf, valint); 3655 } 3656 3657 3658exit: 3659 if (keys) 3660 free(keys); 3661 if (vals) 3662 free(vals); 3663 if (cpuStatus) 3664 CFRelease(cpuStatus); 3665 3666} 3667 3668static void show_power_adapter(void) 3669{ 3670 CFDictionaryRef acInfo = NULL; 3671 CFNumberRef valNum = NULL; 3672 int val; 3673 3674 acInfo = IOPSCopyExternalPowerAdapterDetails(); 3675 if (!acInfo) { 3676 printf("No adapter attached.\n"); 3677 return; 3678 } 3679 3680 valNum = CFDictionaryGetValue(acInfo, CFSTR(kIOPSPowerAdapterWattsKey)); 3681 if (valNum) { 3682 CFNumberGetValue(valNum, kCFNumberIntType, &val); 3683 printf(" Wattage = %dW\n", val); 3684 } 3685 3686 valNum = CFDictionaryGetValue(acInfo, CFSTR(kIOPSPowerAdapterSourceKey)); 3687 if (valNum) { 3688 // New format 3689 CFNumberGetValue(valNum, kCFNumberIntType, &val); 3690 printf(" SourceID = 0x%04x\n", val); 3691 3692 valNum = CFDictionaryGetValue(acInfo, CFSTR(kIOPSPowerAdapterCurrentKey)); 3693 if (valNum) { 3694 CFNumberGetValue(valNum, kCFNumberIntType, &val); 3695 printf(" Current = %dmA\n", val); 3696 } 3697 3698 if ((valNum = CFDictionaryGetValue(acInfo, CFSTR("Voltage")))) { 3699 CFNumberGetValue(valNum, kCFNumberIntType, &val); 3700 printf(" Voltage = %dmW\n", val); 3701 } 3702 } 3703 else { 3704 valNum = CFDictionaryGetValue(acInfo, CFSTR(kIOPSPowerAdapterRevisionKey)); 3705 if (valNum) { 3706 CFNumberGetValue(valNum, kCFNumberIntType, &val); 3707 printf(" Revision = 0x%04x\n", val); 3708 } 3709 } 3710 3711 // Legacy format 3712 valNum = CFDictionaryGetValue(acInfo, CFSTR(kIOPSPowerAdapterIDKey)); 3713 if (valNum) { 3714 CFNumberGetValue(valNum, kCFNumberIntType, &val); 3715 printf(" AdapterID = 0x%04x\n", val); 3716 } 3717 3718 valNum = CFDictionaryGetValue(acInfo, CFSTR(kIOPSPowerAdapterFamilyKey)); 3719 if (valNum) { 3720 CFNumberGetValue(valNum, kCFNumberIntType, &val); 3721 printf(" Family Code = 0x%04x\n", val); 3722 } 3723 3724 valNum = CFDictionaryGetValue(acInfo, CFSTR(kIOPSPowerAdapterSerialNumberKey)); 3725 if (valNum) { 3726 CFNumberGetValue(valNum, kCFNumberIntType, &val); 3727 printf(" Serial Number = 0x%08x\n", val); 3728 } 3729 CFRelease(acInfo); 3730} 3731 3732 3733/******************************************************************************/ 3734/* */ 3735/* BORING SETTINGS & PARSING */ 3736/* */ 3737/******************************************************************************/ 3738 3739 3740static int checkAndSetIntValue( 3741 char *valstr, 3742 CFStringRef settingKey, 3743 int apply, 3744 int isOnOffSetting, 3745 int multiplier, 3746 CFMutableDictionaryRef ac, 3747 CFMutableDictionaryRef batt, 3748 CFMutableDictionaryRef ups) 3749{ 3750 CFNumberRef cfnum; 3751 char *endptr = NULL; 3752 long val; 3753 int32_t val32; 3754 3755 if(!valstr) return -1; 3756 3757 val = strtol(valstr, &endptr, 0); 3758 3759 if(0 != *endptr) 3760 { 3761 // the string contained some non-numerical characters - bail 3762 return -1; 3763 } 3764 3765 // for on/off settings, turn any non-zero number into a 1 3766 if(isOnOffSetting) { 3767 val = (val?1:0); 3768 } else { 3769 // Numerical values may have multipliers (i.e. x1000 for sec -> msec) 3770 if(0 != multiplier) val *= multiplier; 3771 } 3772 // negative number? reject it 3773 if(val < 0) return -1; 3774 3775 val32 = (int32_t)val; 3776 cfnum = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &val32); 3777 if(!cfnum) return -1; 3778 if(apply & kApplyToBattery) 3779 CFDictionarySetValue(batt, settingKey, cfnum); 3780 if(apply & kApplyToCharger) 3781 CFDictionarySetValue(ac, settingKey, cfnum); 3782 if(apply & kApplyToUPS) 3783 CFDictionarySetValue(ups, settingKey, cfnum); 3784 CFRelease(cfnum); 3785 return 0; 3786} 3787 3788static int checkAndSetStrValue(char *valstr, CFStringRef settingKey, int apply, 3789 CFMutableDictionaryRef ac, CFMutableDictionaryRef batt, CFMutableDictionaryRef ups) 3790{ 3791 CFStringRef cfstr; 3792 3793 if(!valstr) return -1; 3794 3795 cfstr = CFStringCreateWithCString(kCFAllocatorDefault, 3796 valstr, kCFStringEncodingMacRoman); 3797 if(!cfstr) return -1; 3798 if(apply & kApplyToBattery) 3799 CFDictionarySetValue(batt, settingKey, cfstr); 3800 if(apply & kApplyToCharger) 3801 CFDictionarySetValue(ac, settingKey, cfstr); 3802 if(apply & kApplyToUPS) 3803 CFDictionarySetValue(ups, settingKey, cfstr); 3804 CFRelease(cfstr); 3805 return 0; 3806} 3807 3808 3809static int setUPSValue(char *valstr, 3810 CFStringRef whichUPS, 3811 CFStringRef settingKey, 3812 int apply, 3813 CFMutableDictionaryRef thresholds) 3814{ 3815 CFMutableDictionaryRef ups_setting = NULL; 3816 CFDictionaryRef tmp_ups_setting = NULL; 3817 CFNumberRef cfnum = NULL; 3818 CFBooleanRef on_off = kCFBooleanTrue; 3819 char *endptr = NULL; 3820 long val; 3821 int32_t val32; 3822 3823 if(!valstr) return -1; 3824 3825 val = strtol(valstr, &endptr, 10); 3826 3827 if(0 != *endptr) 3828 { 3829 // the string contained some non-numerical characters - bail 3830 return -1; 3831 } 3832 3833 if(-1 == val) 3834 { 3835 on_off = kCFBooleanFalse; 3836 } 3837 3838 // negative number? reject it 3839 if(val < 0) val = 0; 3840 3841 // if this should be a percentage, cap the value at 100% 3842 if(kCFCompareEqualTo == CFStringCompare(settingKey, CFSTR(kIOUPSShutdownAtLevelKey), 0)) 3843 { 3844 if(val > 100) val = 100; 3845 }; 3846 3847 // bail if -u or -a hasn't been specified: 3848 if(!(apply & kApplyToUPS)) return -1; 3849 3850 // Create the nested dictionaries of UPS settings 3851 tmp_ups_setting = CFDictionaryGetValue(thresholds, settingKey); 3852 ups_setting = CFDictionaryCreateMutableCopy(0, 0, tmp_ups_setting); 3853 if(!ups_setting) 3854 { 3855 ups_setting = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, 3856 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 3857 } 3858 3859 val32 = (int32_t)val; 3860 cfnum = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &val32); 3861 3862 if(kCFBooleanFalse == on_off) { 3863 // If user is turning this setting off, then preserve the existing value in there. 3864 // via CFDictionaryAddValue 3865 CFDictionaryAddValue(ups_setting, CFSTR(kIOUPSShutdownLevelValueKey), cfnum); 3866 } else { 3867 // If user is providing a new value for this setting, overwrite the existing value. 3868 CFDictionarySetValue(ups_setting, CFSTR(kIOUPSShutdownLevelValueKey), cfnum); 3869 } 3870 CFRelease(cfnum); 3871 CFDictionarySetValue(ups_setting, CFSTR(kIOUPSShutdownLevelEnabledKey), on_off); 3872 3873 CFDictionarySetValue(thresholds, settingKey, ups_setting); 3874 CFRelease(ups_setting); 3875 return 0; 3876} 3877 3878 3879// pmset repeat cancel 3880// pmset repeat <type> <days of week> <time> [<type> <days of week> <time>]\n"); 3881static int parseRepeatingEvent( 3882 char **argv, 3883 int *num_args_parsed, 3884 CFMutableDictionaryRef local_repeating_event, 3885 bool *local_cancel_repeating) 3886{ 3887 CFDateFormatterRef formatter = 0; 3888 CFTimeZoneRef tz = 0; 3889 CFStringRef cf_str_date = 0; 3890 int i = 0; 3891 int j = 0; 3892 int str_len = 0; 3893 int days_mask = 0; 3894 int on_off = 0; 3895 IOReturn ret = kParseInternalError; 3896 3897 CFStringRef the_type = 0; 3898 CFNumberRef the_days = 0; 3899 CFDateRef cf_date = 0; 3900 CFGregorianDate cf_greg_date; 3901 int event_time = 0; 3902 CFNumberRef the_time = 0; // in minutes from midnight 3903 CFMutableDictionaryRef one_repeating_event = 0; 3904 3905 formatter = CFDateFormatterCreate(kCFAllocatorDefault, CFLocaleGetSystem(), 3906 kCFDateFormatterShortStyle, kCFDateFormatterMediumStyle); 3907 if(!formatter) { 3908 ret = kParseInternalError; 3909 goto exit; 3910 } 3911 tz = CFTimeZoneCopySystem(); 3912 if(!tz) { 3913 ret = kParseInternalError; 3914 goto exit; 3915 } 3916 CFDateFormatterSetFormat(formatter, CFSTR(kTimeFormat)); 3917 if(!argv[i]) { 3918 ret = kParseBadArgs; 3919 goto exit; 3920 } 3921 // cancel ALL repeating events 3922 if(0 == strcmp(argv[i], ARG_CANCEL) ) { 3923 3924 *local_cancel_repeating = true; 3925 i++; 3926 ret = kParseSuccess; 3927 goto exit; 3928 } 3929 3930 while(argv[i]) 3931 { 3932 string_tolower(argv[i], argv[i]); 3933 3934 // type 3935 if(0 == strcmp(argv[i], ARG_SLEEP)) 3936 { 3937 on_off = 0; 3938 the_type = CFSTR(kIOPMAutoSleep); 3939 } else if(0 == strcmp(argv[i], ARG_SHUTDOWN)) 3940 { 3941 on_off = 0; 3942 the_type = CFSTR(kIOPMAutoShutdown); 3943 } else if(0 == strcmp(argv[i], ARG_RESTART)) 3944 { 3945 on_off = 0; 3946 the_type = CFSTR(kIOPMAutoRestart); 3947 } else if(0 == strcmp(argv[i], ARG_WAKE)) 3948 { 3949 on_off = 1; 3950 the_type = CFSTR(kIOPMAutoWake); 3951 } else if(0 == strcmp(argv[i], ARG_POWERON)) 3952 { 3953 on_off = 1; 3954 the_type = CFSTR(kIOPMAutoPowerOn); 3955 } else if(0 == strcmp(argv[i], ARG_WAKEORPOWERON)) 3956 { 3957 on_off = 1; 3958 the_type = CFSTR(kIOPMAutoWakeOrPowerOn); 3959 } else { 3960 printf("Error: Unspecified scheduled event type\n"); 3961 ret = kParseBadArgs; 3962 goto bail; 3963 } 3964 3965 i++; 3966 3967 // days of week 3968 // Expect argv[i] to be a NULL terminated string with a subset of: MTWRFSU 3969 // indicating the days of the week to schedule repeating wakeup 3970 // TODO: accept M-F style ranges 3971 if (!argv[i] || !argv[i+1]) { 3972 ret = kParseBadArgs; 3973 goto bail; 3974 } 3975 3976 string_tolower(argv[i], argv[i]); 3977 3978 days_mask = 0; 3979 str_len = strlen(argv[i]); 3980 for(j=0; j<str_len; j++) 3981 { 3982 if('m' == argv[i][j]) { 3983 days_mask |= kIOPMMonday; 3984 } else if('t' == argv[i][j]) { 3985 days_mask |= kIOPMTuesday; 3986 } else if('w' == argv[i][j]) { 3987 days_mask |= kIOPMWednesday; 3988 } else if('r' == argv[i][j]) { 3989 days_mask |= kIOPMThursday; 3990 } else if('f' == argv[i][j]) { 3991 days_mask |= kIOPMFriday; 3992 } else if('s' == argv[i][j]) { 3993 days_mask |= kIOPMSaturday; 3994 } else if('u' == argv[i][j]) { 3995 days_mask |= kIOPMSunday; 3996 } 3997 } 3998 if(0 == days_mask) { 3999 // something went awry; we expect a non-zero days mask. 4000 ret = kParseBadArgs; 4001 goto bail; 4002 } 4003 4004 i++; 4005 string_tolower(argv[i], argv[i]); 4006 4007 cf_str_date = CFStringCreateWithCString(kCFAllocatorDefault, 4008 argv[i], kCFStringEncodingMacRoman); 4009 if (!cf_str_date) { 4010 ret = kParseInternalError; 4011 goto bail; 4012 } 4013 cf_date = CFDateFormatterCreateDateFromString(0, formatter, cf_str_date, 0); 4014 CFRelease(cf_str_date); 4015 if (!cf_date) { 4016 ret = kParseBadArgs; 4017 goto bail; 4018 } 4019 cf_greg_date = CFAbsoluteTimeGetGregorianDate(CFDateGetAbsoluteTime(cf_date), tz); 4020 event_time = cf_greg_date.hour*60 + cf_greg_date.minute; 4021 the_time = CFNumberCreate(0, kCFNumberIntType, &event_time); 4022 4023 i++; 4024 4025 the_days = CFNumberCreate(0, kCFNumberIntType, &days_mask); 4026 4027 // check for existence of the_days, the_time, the_type 4028 // if this was a validly formatted dictionary, pack the repeating dict appropriately. 4029 if( isA_CFNumber(the_days) && isA_CFString(the_type) && isA_CFNumber(the_time) ) 4030 { 4031 one_repeating_event = CFDictionaryCreateMutable(0, 0, 4032 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 4033 if(one_repeating_event) 4034 { 4035 CFDictionarySetValue(one_repeating_event, CFSTR(kIOPMPowerEventTypeKey), the_type); 4036 CFDictionarySetValue(one_repeating_event, CFSTR(kIOPMDaysOfWeekKey), the_days); 4037 CFDictionarySetValue(one_repeating_event, CFSTR(kIOPMPowerEventTimeKey), the_time); 4038 4039 CFDictionarySetValue(local_repeating_event, 4040 (on_off ? CFSTR(kIOPMRepeatingPowerOnKey):CFSTR(kIOPMRepeatingPowerOffKey)), 4041 one_repeating_event); 4042 CFRelease(one_repeating_event); 4043 } 4044 } 4045 if (the_days) 4046 CFRelease(the_days); 4047 if (the_time) 4048 CFRelease(the_time); 4049 if (cf_date) 4050 CFRelease(cf_date); 4051 4052 } // while loop 4053 4054 ret = kParseSuccess; 4055 goto exit; 4056 4057bail: 4058 fprintf(stderr, "Error: badly formatted repeating power event\n"); 4059 fflush(stderr); 4060 4061exit: 4062 if (the_type) 4063 CFRelease(the_type); 4064 if(num_args_parsed) 4065 *num_args_parsed = i; 4066 if(tz) 4067 CFRelease(tz); 4068 if(formatter) 4069 CFRelease(formatter); 4070 return ret; 4071} 4072 4073 4074// pmset sched wake "4/27/04 1:00:00 PM" "Ethan Bold" 4075// pmset sched cancel sleep "4/27/04 1:00:00 PM" "MyAlarmClock" 4076// pmset sched cancel shutdown "4/27/04 1:00:00 PM" 4077static int parseScheduledEvent( 4078 char **argv, 4079 int *num_args_parsed, 4080 ScheduledEventReturnType *local_scheduled_event, 4081 bool *cancel_scheduled_event, 4082 bool is_relative_event) 4083{ 4084 CFDateFormatterRef formatter = 0; 4085 CFStringRef cf_str_date = 0; 4086 int i = 0; 4087 IOReturn ret = kParseInternalError; 4088 4089 formatter = CFDateFormatterCreate(kCFAllocatorDefault, CFLocaleGetSystem(), 4090 kCFDateFormatterShortStyle, kCFDateFormatterMediumStyle); 4091 if(!formatter) 4092 return kParseInternalError; 4093 4094 *num_args_parsed = 0; 4095 4096 // We manually set the format (as recommended by header comments) 4097 // to ensure it doesn't vary from release to release or from locale 4098 // to locale. 4099 CFDateFormatterSetFormat(formatter, CFSTR(kDateAndTimeFormat)); 4100 if(!argv[i]) { 4101 ret = kParseInternalError; 4102 goto exit; 4103 } 4104 4105 string_tolower(argv[i], argv[i]); 4106 4107 // cancel 4108 if(!is_relative_event && (0 == strcmp(argv[i], ARG_CANCEL))) { 4109 char *endptr = NULL; 4110 long val; 4111 CFArrayRef all_events = 0; 4112 CFDictionaryRef the_event = 0; 4113 4114 *cancel_scheduled_event = true; 4115 i++; 4116 4117 // See if the next field is an integer. If so, we cancel the event 4118 // indicated by the indices printed in "pmset -g sched" 4119 // If not, parse out the rest of the entry for a full-description 4120 // of the event to cancel. 4121 if(!argv[i]) { 4122 goto exit; 4123 } 4124 4125 val = strtol(argv[i], &endptr, 10); 4126 4127 if(0 == *endptr) 4128 { 4129 all_events = IOPMCopyScheduledPowerEvents(); 4130 if(!all_events) { 4131 ret = kParseInternalError; 4132 goto exit; 4133 } 4134 if(val >= 0 && val < CFArrayGetCount(all_events)) { 4135 4136 // the string was indeed a number 4137 the_event = isA_CFDictionary(CFArrayGetValueAtIndex(all_events, val)); 4138 if(!the_event) { 4139 ret = kParseInternalError; 4140 } else { 4141 local_scheduled_event->when = CFRetain( 4142 CFDictionaryGetValue(the_event, CFSTR(kIOPMPowerEventTimeKey))); 4143 local_scheduled_event->who = CFRetain( 4144 CFDictionaryGetValue(the_event, CFSTR(kIOPMPowerEventAppNameKey))); 4145 local_scheduled_event->which = CFRetain( 4146 CFDictionaryGetValue(the_event, CFSTR(kIOPMPowerEventTypeKey))); 4147 ret = kParseSuccess; 4148 } 4149 4150 i++; 4151 } else { 4152 ret = kParseBadArgs; 4153 } 4154 4155 CFRelease(all_events); 4156 goto exit; 4157 } 4158 } 4159 4160 string_tolower(argv[i], argv[i]); 4161 4162 // type 4163 if(0 == strcmp(argv[i], ARG_SLEEP)) 4164 { 4165 local_scheduled_event->which = (!is_relative_event) ? 4166 CFStringCreateWithCString(0, kIOPMAutoSleep, kCFStringEncodingMacRoman) : 0; 4167 i++; 4168 } else if(0 == strcmp(argv[i], ARG_SHUTDOWN)) 4169 { 4170 local_scheduled_event->which = (!is_relative_event) ? 4171 CFStringCreateWithCString(0, kIOPMAutoShutdown, kCFStringEncodingMacRoman) : 0; 4172 i++; 4173 } else if(0 == strcmp(argv[i], ARG_RESTART)) 4174 { 4175 local_scheduled_event->which = (!is_relative_event) ? 4176 CFStringCreateWithCString(0, kIOPMAutoRestart, kCFStringEncodingMacRoman) : 0; 4177 i++; 4178 } else if(0 == strcmp(argv[i], ARG_WAKE)) 4179 { 4180 local_scheduled_event->which = (!is_relative_event) ? 4181 CFStringCreateWithCString(0, kIOPMAutoWake, kCFStringEncodingMacRoman) : 4182 CFStringCreateWithCString(0, kIOPMAutoWakeRelativeSeconds, kCFStringEncodingMacRoman); 4183 i++; 4184 } else if(0 == strcmp(argv[i], ARG_POWERON)) 4185 { 4186 local_scheduled_event->which = (!is_relative_event) ? 4187 CFStringCreateWithCString(0, kIOPMAutoPowerOn, kCFStringEncodingMacRoman) : 0; 4188 i++; 4189 } else if(0 == strcmp(argv[i], ARG_WAKEORPOWERON)) 4190 { 4191 local_scheduled_event->which = (!is_relative_event) ? 4192 CFStringCreateWithCString(0, kIOPMAutoWakeOrPowerOn, kCFStringEncodingMacRoman) : 0; 4193 i++; 4194 } else { 4195 printf("Error: Unspecified scheduled event type\n"); 4196 ret = kParseBadArgs; 4197 goto exit; 4198 } 4199 4200 if(0 == local_scheduled_event->which) { 4201 printf("Error: Unspecified scheduled event type (2)\n"); 4202 ret = kParseBadArgs; 4203 goto exit; 4204 } 4205 4206 // date & time 4207 if(argv[i]) { 4208 if (is_relative_event) { 4209 char *endptr = NULL; 4210 long secs; 4211 4212 secs = strtol(argv[i], &endptr, 10); 4213 if ((0 != *endptr) || !secs) { 4214 ret = kParseBadArgs; 4215 goto exit; 4216 } 4217 4218 local_scheduled_event->when = CFDateCreate(0, CFAbsoluteTimeGetCurrent() + secs); 4219 i++; 4220 } else { 4221 string_tolower(argv[i], argv[i]); 4222 4223 cf_str_date = CFStringCreateWithCString(kCFAllocatorDefault, 4224 argv[i], kCFStringEncodingMacRoman); 4225 if(!cf_str_date) { 4226 local_scheduled_event->when = NULL; 4227 ret = kParseInternalError; 4228 goto exit; 4229 } 4230 local_scheduled_event->when = 4231 CFDateFormatterCreateDateFromString( 4232 0, 4233 formatter, 4234 cf_str_date, 4235 NULL); 4236 CFRelease(cf_str_date); 4237 i++; 4238 } 4239 } else { 4240 printf("Error: Badly formatted date\n"); 4241 ret = kParseBadArgs; 4242 goto exit; 4243 } 4244 4245 if(0 == local_scheduled_event->when) { 4246 printf("Error: Badly formatted date (2)\n"); 4247 ret = kParseBadArgs; 4248 goto exit; 4249 } 4250 4251 // Author. Please preserve case - do not lowercase - this argument. 4252 if(argv[i]) { 4253 local_scheduled_event->who = CFStringCreateWithCString(0, argv[i], kCFStringEncodingMacRoman); 4254 i++; 4255 } else { 4256 local_scheduled_event->who = 0; 4257 } 4258 4259 ret = kParseSuccess; 4260 4261exit: 4262 if(num_args_parsed) *num_args_parsed = i; 4263 4264 if(formatter) CFRelease(formatter); 4265 4266 if (kParseSuccess != ret) { 4267 exit(EX_SOFTWARE); 4268 } 4269 4270 return ret; 4271} 4272 4273static void string_tolower(char *lower_me, char *dst) 4274{ 4275 int length = strlen(lower_me); 4276 int j = 0; 4277 4278 for (j=0; j<length; j++) 4279 { 4280 dst[j] = tolower(lower_me[j]); 4281 } 4282} 4283 4284static void string_toupper(char *upper_me, char *dst) 4285{ 4286 int length = strlen(upper_me); 4287 int j = 0; 4288 4289 for (j=0; j<length; j++) 4290 { 4291 dst[j] = toupper(upper_me[j]); 4292 } 4293} 4294 4295/* 4296 * parseArgs - parse argv input stream into executable commands 4297 * and returns executable commands. 4298 * INPUTS: 4299 * int argc, 4300 * char* argv[], 4301 * OUTPUTS: 4302 * If these pointers are specified on exit, that means parseArgs modified these settings 4303 * and they should be written out to persistent store by the caller. 4304 * settings: Energy Saver settings 4305 * modified_power_sources: which power sources the modified Energy Saver settings apply to 4306 * (only valid if settings is defined) 4307 * active_profiles: Changes the active profile 4308 * system_power_settings: system-wide settings, not tied to power source. like "disablesleep" 4309 * ups_thresholds: UPS shutdown thresholds 4310 * scheduled_event: Description of a one-time power event 4311 * cancel_scheduled_event: true = cancel the scheduled event/false = schedule the event 4312 * (only valid if scheduled_event is defined) 4313 * repeating_event: Description of a repeating power event 4314 * cancel_repeating_event: true = cancel the repeating event/false = schedule the repeating event 4315 * (only valid if repeating_event is defined) 4316*/ 4317 4318static int parseArgs(int argc, 4319 char* argv[], 4320 CFDictionaryRef *settings, 4321 int *modified_power_sources, 4322 bool *force_activate_settings, 4323 CFDictionaryRef *active_profiles, 4324 CFDictionaryRef *system_power_settings, 4325 CFDictionaryRef *ups_thresholds, 4326 ScheduledEventReturnType **scheduled_event, 4327 bool *cancel_scheduled_event, 4328 CFDictionaryRef *repeating_event, 4329 bool *cancel_repeating_event, 4330 uint32_t *pmCmd) 4331{ 4332 int i = 1; 4333 int apply = 0; 4334 int ret = kParseSuccess; 4335 int modified = 0; 4336 IOReturn kr; 4337 ScheduledEventReturnType *local_scheduled_event = 0; 4338 bool local_cancel_event = false; 4339 CFMutableDictionaryRef local_repeating_event = 0; 4340 bool local_cancel_repeating = false; 4341 CFDictionaryRef tmp_profiles = 0; 4342 CFMutableDictionaryRef local_profiles = 0; 4343 CFDictionaryRef tmp_ups_settings = 0; 4344 CFMutableDictionaryRef local_ups_settings = 0; 4345 CFDictionaryRef tmp_settings = 0; 4346 CFMutableDictionaryRef local_settings = 0; 4347 CFMutableDictionaryRef local_system_power_settings = 0; 4348 CFDictionaryRef tmp_battery = 0; 4349 CFMutableDictionaryRef battery = 0; 4350 CFDictionaryRef tmp_ac = 0; 4351 CFMutableDictionaryRef ac = 0; 4352 CFDictionaryRef tmp_ups = 0; 4353 CFMutableDictionaryRef ups = 0; 4354 4355 if(argc == 1) { 4356 return kParseBadArgs; 4357 } 4358 4359 4360/* 4361 * Check for any commands 4362 * Commands may not be combined with any other flags 4363 * 4364 */ 4365 if(0 == strcmp(argv[1], ARG_TOUCH)) 4366 { 4367 *pmCmd = kPMCommandTouch; 4368 return kIOReturnSuccess; 4369 } else if(0 == strcmp(argv[1], ARG_NOIDLE)) 4370 { 4371 *pmCmd = kPMCommandNoIdle; 4372 return kIOReturnSuccess; 4373 } else if(0 == strcmp(argv[1], ARG_SLEEPNOW)) 4374 { 4375 *pmCmd = kPMCommandSleepNow; 4376 return kIOReturnSuccess; 4377 } else if(0 == strcmp(argv[1], ARG_DISPLAYSLEEPNOW)) 4378 { 4379 *pmCmd = kPMCommandDisplaySleepNow; 4380 return kIOReturnSuccess; 4381 } else if(0 == strcmp(argv[1], ARG_DEBUGTRIG)) 4382 { 4383 *pmCmd = kPMCommandDebugTrig; 4384 return kIOReturnSuccess; 4385 } else if ((0 == strcmp(argv[1], ARG_RESETDISPLAYAMBIENTPARAMS)) 4386 || (0 == strcmp(argv[1], ARG_RDAP)) ) 4387 { 4388 #if PLATFORM_HAS_DISPLAYSERVICES 4389 { 4390 IOReturn ret = DisplayServicesResetAmbientLightAll(); 4391 4392 if (kIOReturnSuccess == ret) { 4393 printf("Success.\n"); 4394 } else if (kIOReturnNoDevice == ret) { 4395 printf("Error: No supported displays found for pmset argument \"%s\"\n", argv[1]); 4396 } else { 4397 printf("Error: Failure 0%08x setting display ambient parameters.\n", ret); 4398 } 4399 } 4400 #else 4401 { 4402 printf("Error: this command isn't supported on this platform (no DisplayServices).\n"); 4403 exit (EX_UNAVAILABLE); 4404 } 4405 #endif 4406 4407 return kIOReturnSuccess; 4408 } 4409 4410 4411/*********** 4412 * Setup mutable PM preferences 4413 ***********/ 4414 tmp_settings = IOPMCopyActivePMPreferences(); 4415 if(!tmp_settings) { 4416 ret = kParseInternalError; 4417 goto exit; 4418 } 4419 local_settings = CFDictionaryCreateMutableCopy(0, 0, tmp_settings); 4420 CFRelease(tmp_settings); 4421 if(!local_settings) { 4422 ret = kParseInternalError; 4423 goto exit; 4424 } 4425 4426 // Either battery or AC settings may not exist if the system doesn't support it. 4427 tmp_battery = isA_CFDictionary(CFDictionaryGetValue(local_settings, CFSTR(kIOPMBatteryPowerKey))); 4428 if(tmp_battery) { 4429 battery = CFDictionaryCreateMutableCopy(0, 0, tmp_battery); 4430 if(battery) { 4431 CFDictionarySetValue(local_settings, CFSTR(kIOPMBatteryPowerKey), battery); 4432 CFRelease(battery); 4433 } 4434 } 4435 tmp_ac = isA_CFDictionary(CFDictionaryGetValue(local_settings, CFSTR(kIOPMACPowerKey))); 4436 if(tmp_ac) { 4437 ac = CFDictionaryCreateMutableCopy(0, 0, tmp_ac); 4438 if(ac) { 4439 CFDictionarySetValue(local_settings, CFSTR(kIOPMACPowerKey), ac); 4440 CFRelease(ac); 4441 } 4442 } 4443 tmp_ups = isA_CFDictionary(CFDictionaryGetValue(local_settings, CFSTR(kIOPMUPSPowerKey))); 4444 if(tmp_ups) { 4445 ups = CFDictionaryCreateMutableCopy(0, 0, tmp_ups); 4446 if(ups) { 4447 CFDictionarySetValue(local_settings, CFSTR(kIOPMUPSPowerKey), ups); 4448 CFRelease(ups); 4449 } 4450 } 4451/*********** 4452 * Setup mutable UPS thersholds 4453 ***********/ 4454 tmp_ups_settings = IOPMCopyUPSShutdownLevels(CFSTR(kIOPMDefaultUPSThresholds)); 4455 if(tmp_ups_settings) { 4456 local_ups_settings = CFDictionaryCreateMutableCopy(0, 0, tmp_ups_settings); 4457 CFRelease(tmp_ups_settings); 4458 } 4459 4460/*********** 4461 * Setup mutable Active profiles 4462 ***********/ 4463 tmp_profiles = IOPMCopyActivePowerProfiles(); 4464 if(tmp_profiles) { 4465 local_profiles = CFDictionaryCreateMutableCopy(0, 0, tmp_profiles); 4466 CFRelease(tmp_profiles); 4467 } 4468 4469/************ 4470 * Setup system power settings holder dictionary 4471 ************/ 4472 local_system_power_settings = CFDictionaryCreateMutable(0, 0, 4473 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 4474 4475 // Unless specified, apply changes to both battery and AC 4476 if(battery) apply |= kApplyToBattery; 4477 if(ac) apply |= kApplyToCharger; 4478 if(ups) apply |= kApplyToUPS; 4479 4480 i=1; 4481 while(i < argc) 4482 { 4483 string_tolower(argv[i], argv[i]); // in place 4484 4485 if( (argv[i][0] == '-') 4486 && ('1' != argv[i][1]) ) // don't try to process it as a abcg argument if it's a -1 4487 // the profiles parsing code below is expecting the -1 4488 { 4489 // Process -a/-b/-c/-g arguments 4490 apply = 0; 4491 switch (argv[i][1]) 4492 { 4493 case 'a': 4494 if(battery) apply |= kApplyToBattery; 4495 if(ac) apply |= kApplyToCharger; 4496 if(ups) apply |= kApplyToUPS; 4497 break; 4498 case 'b': 4499 if(battery) apply = kApplyToBattery; 4500 break; 4501 case 'c': 4502 if(ac) apply = kApplyToCharger; 4503 break; 4504 case 'u': 4505 if(ups) apply = kApplyToUPS; 4506 break; 4507 case 'g': 4508 // One of the "getters" 4509 if('\0' != argv[i][2]) { 4510 ret = kParseBadArgs; 4511 goto exit; 4512 } 4513 i++; 4514 4515 const char *canonical_arg = getCanonicalArgForSynonym(argv[i]); 4516 if (!canonical_arg) { 4517 ret = kParseBadArgs; 4518 goto exit; 4519 } 4520 4521 int getter_iterator; 4522 bool handled_getter_arg = false; 4523 for (getter_iterator=0; getter_iterator<the_getters_count; getter_iterator++) { 4524 if (!strncmp(the_getters[getter_iterator].arg, canonical_arg, kMaxArgStringLength)) { 4525 the_getters[getter_iterator].action(&argv[i+1]); 4526 handled_getter_arg = true; 4527 break; 4528 } 4529 } 4530 if (!handled_getter_arg) 4531 { 4532#if 0 4533 // TODO: ARG_SEARCH is the only getter that's not described in the 4534 // "the_getters" array. If possible, we should fit it in there too. 4535 if (!strncmp(canonical_arg, ARG_SEARCH, kMaxArgStringLength) && argv[i+1] ) 4536 { 4537 string_toupper(argv[i+1], argv[i+1]); 4538 show_details_for_UUID(argv[i+1]); 4539 goto exit; 4540 } 4541#endif 4542 } 4543 4544 // return immediately - don't handle any more setting arguments 4545 ret = kParseSuccess; 4546 goto exit; 4547 break; 4548 default: 4549 // bad! 4550 ret = kParseBadArgs; 4551 goto exit; 4552 break; 4553 } 4554 4555 i++; 4556 } else if( (0 == strncmp(argv[i], ARG_SCHEDULE, kMaxArgStringLength)) 4557 || (0 == strncmp(argv[i], ARG_SCHED, kMaxArgStringLength)) ) 4558 { 4559 // Process rest of input as a cancel/schedule power event 4560 int args_parsed; 4561 4562 local_scheduled_event = scheduled_event_struct_create(); 4563 if(!local_scheduled_event) { 4564 ret = kParseInternalError; 4565 goto exit; 4566 } 4567 i += 1; 4568 ret = parseScheduledEvent( 4569 &(argv[i]), 4570 &args_parsed, 4571 local_scheduled_event, 4572 &local_cancel_event, 4573 false); 4574 if(kParseSuccess != ret) 4575 { 4576 goto exit; 4577 } 4578 4579 i += args_parsed; 4580 modified |= kModSched; 4581 } else if(0 == strncmp(argv[i], ARG_RELATIVE, kMaxArgStringLength)) 4582 { 4583 // Process rest of input as a relative power event 4584 int args_parsed; 4585 4586 local_scheduled_event = scheduled_event_struct_create(); 4587 if(!local_scheduled_event) { 4588 ret = kParseInternalError; 4589 goto exit; 4590 } 4591 i += 1; 4592 ret = parseScheduledEvent( 4593 &(argv[i]), 4594 &args_parsed, 4595 local_scheduled_event, 4596 &local_cancel_event, 4597 true); 4598 if(kParseSuccess != ret) 4599 { 4600 goto exit; 4601 } 4602 4603 i += args_parsed; 4604 modified |= kModSched; 4605 } else if(0 == strncmp(argv[i], ARG_REPEAT, kMaxArgStringLength)) 4606 { 4607 int args_parsed; 4608 4609 local_repeating_event = CFDictionaryCreateMutable(0, 0, 4610 &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); 4611 if(!local_repeating_event) { 4612 ret = kParseInternalError; 4613 goto exit; 4614 } 4615 i+=1; 4616 ret = parseRepeatingEvent( 4617 &(argv[i]), 4618 &args_parsed, 4619 local_repeating_event, 4620 &local_cancel_repeating); 4621 4622 if(kParseSuccess == ret) 4623 { 4624 modified |= kModRepeat; 4625 } else { 4626 ret = kParseBadArgs; 4627 } 4628 goto exit; 4629 } else 4630 { 4631 // Process the settings 4632 if(!strncmp(argv[i], ARG_BOOKMARK, kMaxArgStringLength)) 4633 { 4634 set_new_power_bookmark(); 4635 goto exit; 4636 } else if(0 == strncmp(argv[i], ARG_DEBUGFLAGS, kMaxArgStringLength)) 4637 { 4638 if (argv[i+1]) 4639 set_debugFlags(&argv[i+1]); 4640 else 4641 printf("Error: You need to specify debug flags value\n"); 4642 goto exit; 4643 } else if(0 == strncmp(argv[i], ARG_BTINTERVAL, kMaxArgStringLength)) 4644 { 4645 if(argv[i+1]) 4646 set_btInterval(&argv[i+1]); 4647 else 4648 printf("Error: You need to specify an interval in seconds\n"); 4649 goto exit; 4650 } else if(0 == strncmp(argv[i], ARG_DWLINTERVAL, kMaxArgStringLength)) 4651 { 4652 if(argv[i+1]) 4653 set_dwlInterval(&argv[i+1]); 4654 else 4655 printf("Error: You need to specify an interval in seconds\n"); 4656 goto exit; 4657 } else if(0 == strncmp(argv[i], ARG_DISABLEASSERTION, kMaxArgStringLength)) 4658 { 4659 if(argc <= 2) { 4660 printf("Error: Assertion type to disable is missing\n"); 4661 goto exit; 4662 } 4663 kr = IOPMCtlAssertionType(argv[i+1], kIOPMDisableAssertionType); 4664 if (kr == kIOReturnNotPrivileged) 4665 printf("\'%s\' must be run as root to disable assertions\n", argv[0]); 4666 else if (kr != kIOReturnSuccess) 4667 printf("Failed to disable assertions with err code 0x%x\n", kr); 4668 goto exit; 4669 } else if(0 == strncmp(argv[i], ARG_ENABLEASSERTION, kMaxArgStringLength)) 4670 { 4671 if(argc <= 2) { 4672 printf("Error: Assertion type to enable is missing\n"); 4673 goto exit; 4674 } 4675 kr = IOPMCtlAssertionType(argv[i+1], kIOPMEnableAssertionType); 4676 if (kr == kIOReturnNotPrivileged) 4677 printf("\'%s\' must be run as root to enable assertions\n", argv[0]); 4678 else if (kr != kIOReturnSuccess) 4679 printf("Failed to enable assertions with err code 0x%x\n", kr); 4680 goto exit; 4681 4682 } else if (0 == strncmp(argv[i], ARG_MT2BOOK, kMaxArgStringLength)) 4683 { 4684 mt2bookmark(); 4685 goto exit; 4686 } else if (0 == strncmp(argv[i], ARG_SETSAAFLAGS, kMaxArgStringLength)) 4687 { 4688 if(argv[i+1]) 4689 set_saaFlags(&argv[i+1]); 4690 else 4691 printf("Error: You need to specify an integer flag value\n"); 4692 goto exit; 4693 } else if (0 == strncmp(argv[i], ARG_NOPOLL, kMaxArgStringLength)) 4694 { 4695 set_nopoll(); 4696 goto exit; 4697 } else if(0 == strncmp(argv[i], ARG_BOOT, kMaxArgStringLength)) 4698 { 4699 // Tell kernel power management that bootup is complete 4700 kr = setRootDomainProperty(CFSTR("System Boot Complete"), kCFBooleanTrue); 4701 if(kr == kIOReturnSuccess) { 4702 printf("Setting boot completed.\n"); 4703 } else { 4704 fprintf(stderr, "pmset: Error 0x%x setting boot property\n", kr); 4705 fflush(stderr); 4706 } 4707 4708 i++; 4709 } else if(0 == strncmp(argv[i], ARG_UNBOOT, kMaxArgStringLength)) 4710 { 4711 // Tell kernel power management that bootup is complete 4712 kr = setRootDomainProperty(CFSTR("System Shutdown"), kCFBooleanTrue); 4713 if(kr == kIOReturnSuccess) { 4714 printf("Setting shutdown true.\n"); 4715 } else { 4716 fprintf(stderr, "pmset: Error 0x%x setting boot property\n", kr); 4717 fflush(stderr); 4718 } 4719 4720 i++; 4721 } else if (0 == strncmp(argv[i], ARG_POLLBOOT, kMaxArgStringLength)) { 4722 ret = IOPSRequestBatteryUpdate(kIOPSReadSystemBoot); 4723 if (kIOReturnSuccess != ret) { 4724 fprintf(stderr, "pmset: Must be run as root.\n"); 4725 } 4726 goto exit; 4727 } else if (0 == strncmp(argv[i], ARG_POLLALL, kMaxArgStringLength)) { 4728 ret = IOPSRequestBatteryUpdate(kIOPSReadAll); 4729 if (kIOReturnSuccess != ret) { 4730 fprintf(stderr, "pmset: Must be run as root.\n"); 4731 } 4732 goto exit; 4733 } else if (0 == strncmp(argv[i], ARG_POLLUSER, kMaxArgStringLength)) { 4734 ret = IOPSRequestBatteryUpdate(kIOPSReadUserVisible); 4735 if (kIOReturnSuccess != ret) { 4736 fprintf(stderr, "pmset: Must be run as root.\n"); 4737 } 4738 goto exit; 4739 } else if(0 == strncmp(argv[i], ARG_FORCE, kMaxArgStringLength)) 4740 { 4741 *force_activate_settings = true; 4742 i++; 4743 } else if( (0 == strncmp(argv[i], ARG_DIM, kMaxArgStringLength)) || 4744 (0 == strncmp(argv[i], ARG_DISPLAYSLEEP, kMaxArgStringLength)) ) 4745 { 4746 // either 'dim' or 'displaysleep' argument sets minutes until display dims 4747 if(-1 == checkAndSetIntValue( argv[i+1], 4748 CFSTR(kIOPMDisplaySleepKey), 4749 apply, false, kNoMultiplier, 4750 ac, battery, ups)) 4751 { 4752 ret = kParseBadArgs; 4753 goto exit; 4754 } 4755 modified |= kModSettings; 4756 i+=2; 4757 } else if( (0 == strncmp(argv[i], ARG_SPINDOWN, kMaxArgStringLength)) || 4758 (0 == strncmp(argv[i], ARG_DISKSLEEP, kMaxArgStringLength))) 4759 { 4760 // either 'spindown' or 'disksleep' argument sets minutes until disk spindown 4761 if(-1 == checkAndSetIntValue( argv[i+1], 4762 CFSTR(kIOPMDiskSleepKey), 4763 apply, false, kNoMultiplier, 4764 ac, battery, ups)) 4765 { 4766 ret = kParseBadArgs; 4767 goto exit; 4768 } 4769 modified |= kModSettings; 4770 i+=2; 4771 } else if(0 == strncmp(argv[i], ARG_SLEEP, kMaxArgStringLength)) 4772 { 4773 if(-1 == checkAndSetIntValue( argv[i+1], 4774 CFSTR(kIOPMSystemSleepKey), 4775 apply, false, kNoMultiplier, 4776 ac, battery, ups)) 4777 { 4778 ret = kParseBadArgs; 4779 goto exit; 4780 } 4781 modified |= kModSettings; 4782 i+=2; 4783 } else if(0 == strncmp(argv[i], ARG_WOMP, kMaxArgStringLength)) 4784 { 4785 if(-1 == checkAndSetIntValue(argv[i+1], CFSTR(kIOPMWakeOnLANKey), 4786 apply, true, kNoMultiplier, 4787 ac, battery, ups)) 4788 { 4789 ret = kParseBadArgs; 4790 goto exit; 4791 } 4792 modified |= kModSettings; 4793 i+=2; 4794 } else if(0 == strncmp(argv[i], ARG_RING, kMaxArgStringLength)) 4795 { 4796 if(-1 == checkAndSetIntValue(argv[i+1], CFSTR(kIOPMWakeOnRingKey), 4797 apply, true, kNoMultiplier, 4798 ac, battery, ups)) 4799 { 4800 ret = kParseBadArgs; 4801 goto exit; 4802 } 4803 modified |= kModSettings; 4804 i+=2; 4805 } else if(0 == strncmp(argv[i], ARG_AUTORESTART, kMaxArgStringLength)) 4806 { 4807 if(-1 == checkAndSetIntValue(argv[i+1], CFSTR(kIOPMRestartOnPowerLossKey), 4808 apply, true, kNoMultiplier, 4809 ac, battery, ups)) 4810 { 4811 ret = kParseBadArgs; 4812 goto exit; 4813 } 4814 modified |= kModSettings; 4815 i+=2; 4816 } else if(0 == strncmp(argv[i], ARG_WAKEONACCHANGE, kMaxArgStringLength)) 4817 { 4818 if(-1 == checkAndSetIntValue(argv[i+1], CFSTR(kIOPMWakeOnACChangeKey), 4819 apply, true, kNoMultiplier, 4820 ac, battery, ups)) 4821 { 4822 ret = kParseBadArgs; 4823 goto exit; 4824 } 4825 modified |= kModSettings; 4826 i+=2; 4827 } else if(0 == strncmp(argv[i], ARG_LIDWAKE, kMaxArgStringLength)) 4828 { 4829 if(-1 == checkAndSetIntValue(argv[i+1], CFSTR(kIOPMWakeOnClamshellKey), 4830 apply, true, kNoMultiplier, 4831 ac, battery, ups)) 4832 { 4833 ret = kParseBadArgs; 4834 goto exit; 4835 } 4836 modified |= kModSettings; 4837 i+=2; 4838 } else if(0 == strncmp(argv[i], ARG_REDUCEBRIGHT, kMaxArgStringLength)) 4839 { 4840 if(-1 == checkAndSetIntValue(argv[i+1], CFSTR(kIOPMReduceBrightnessKey), 4841 apply, true, kNoMultiplier, 4842 ac, battery, ups)) 4843 { 4844 ret = kParseBadArgs; 4845 goto exit; 4846 } 4847 modified |= kModSettings; 4848 i+=2; 4849 } else if(0 == strncmp(argv[i], ARG_SLEEPUSESDIM, kMaxArgStringLength)) 4850 { 4851 if(-1 == checkAndSetIntValue(argv[i+1], CFSTR(kIOPMDisplaySleepUsesDimKey), 4852 apply, true, kNoMultiplier, 4853 ac, battery, ups)) 4854 { 4855 ret = kParseBadArgs; 4856 goto exit; 4857 } 4858 modified |= kModSettings; 4859 i+=2; 4860 } else if((0 == strncmp(argv[i], ARG_MOTIONSENSOR, kMaxArgStringLength)) 4861 || (0 == strncmp(argv[i], ARG_MOTIONSENSOR2, kMaxArgStringLength)) ) 4862 { 4863 if(-1 == checkAndSetIntValue(argv[i+1], CFSTR(kIOPMMobileMotionModuleKey), 4864 apply, true, kNoMultiplier, 4865 ac, battery, ups)) 4866 { 4867 ret = kParseBadArgs; 4868 goto exit; 4869 } 4870 modified |= kModSettings; 4871 i+=2; 4872 } else if(0 == strncmp(argv[i], ARG_TTYKEEPAWAKE, kMaxArgStringLength)) 4873 { 4874 if(-1 == checkAndSetIntValue(argv[i+1], CFSTR(kIOPMTTYSPreventSleepKey), 4875 apply, true, kNoMultiplier, 4876 ac, battery, ups)) 4877 { 4878 ret = kParseBadArgs; 4879 goto exit; 4880 } 4881 modified |= kModSettings; 4882 i+=2; 4883 } else if(0 == strncmp(argv[i], ARG_DISABLESLEEP, kMaxArgStringLength)) 4884 { 4885 char *endptr = NULL; 4886 long val; 4887 4888 if( argv[i+1] ) 4889 { 4890 val = strtol(argv[i+1], &endptr, 10); 4891 4892 if(0 != *endptr) 4893 { 4894 // the string contained some non-numerical characters - bail 4895 ret = kParseBadArgs; 4896 goto exit; 4897 } 4898 4899 // Any non-zero value of val (preferably 1) means DISABLE sleep. 4900 // A zero value means ENABLE sleep. 4901 4902 CFDictionarySetValue( local_system_power_settings, 4903 kIOPMSleepDisabledKey, 4904 val ? kCFBooleanTrue : kCFBooleanFalse); 4905 4906 modified |= kModSystemSettings; 4907 } 4908 i+=2; 4909 } else if(0 == strncmp(argv[i], ARG_DISABLEFDEKEYSTORE, kMaxArgStringLength)) 4910 { 4911 char *endptr = NULL; 4912 long val; 4913 4914 if( argv[i+1] ) 4915 { 4916 val = strtol(argv[i+1], &endptr, 10); 4917 4918 if(0 != *endptr) 4919 { 4920 // the string contained some non-numerical characters - bail 4921 ret = kParseBadArgs; 4922 goto exit; 4923 } 4924 4925 // Any non-zero value of val (preferably 1) means Allow storing 4926 // FDE Keys to hardware 4927 // A zero value means Avoid storing keys to hardware 4928 4929 CFDictionarySetValue( local_system_power_settings, 4930 CFSTR(kIOPMDestroyFVKeyOnStandbyKey), 4931 val ? kCFBooleanTrue : kCFBooleanFalse ); 4932 4933 modified |= kModSystemSettings; 4934 } 4935 i+=2; 4936 4937 } else if(0 == strncmp(argv[i], ARG_HALTLEVEL, kMaxArgStringLength)) 4938 { 4939 if(-1 == setUPSValue(argv[i+1], CFSTR(kIOPMDefaultUPSThresholds), 4940 CFSTR(kIOUPSShutdownAtLevelKey), 4941 apply, local_ups_settings)) 4942 { 4943 ret = kParseBadArgs; 4944 goto exit; 4945 } 4946 modified |= kModUPSThresholds; 4947 i+=2; 4948 } else if(0 == strncmp(argv[i], ARG_HALTAFTER, kMaxArgStringLength)) 4949 { 4950 if(-1 == setUPSValue(argv[i+1], CFSTR(kIOPMDefaultUPSThresholds), 4951 CFSTR(kIOUPSShutdownAfterMinutesOn), 4952 apply, local_ups_settings)) 4953 { 4954 ret = kParseBadArgs; 4955 goto exit; 4956 } 4957 modified |= kModUPSThresholds; 4958 i+=2; 4959 } else if(0 == strncmp(argv[i], ARG_HALTREMAIN, kMaxArgStringLength)) 4960 { 4961 if(-1 == setUPSValue(argv[i+1], CFSTR(kIOPMDefaultUPSThresholds), 4962 CFSTR(kIOUPSShutdownAtMinutesLeft), 4963 apply, local_ups_settings)) 4964 { 4965 ret = kParseBadArgs; 4966 goto exit; 4967 } 4968 modified |= kModUPSThresholds; 4969 i+=2; 4970 } else if(0 == strncmp(argv[i], ARG_HIBERNATEMODE, kMaxArgStringLength)) 4971 { 4972 if(-1 == checkAndSetIntValue(argv[i+1], CFSTR(kIOHibernateModeKey), 4973 apply, false, kNoMultiplier, 4974 ac, battery, ups)) 4975 { 4976 ret = kParseBadArgs; 4977 goto exit; 4978 } 4979 modified |= kModSettings; 4980 i+=2; 4981 } else if(0 == strncmp(argv[i], ARG_HIBERNATEFREERATIO, kMaxArgStringLength)) 4982 { 4983 if(-1 == checkAndSetIntValue(argv[i+1], CFSTR(kIOHibernateFreeRatioKey), 4984 apply, false, kNoMultiplier, 4985 ac, battery, ups)) 4986 { 4987 ret = kParseBadArgs; 4988 goto exit; 4989 } 4990 modified |= kModSettings; 4991 i+=2; 4992 } else if(0 == strncmp(argv[i], ARG_HIBERNATEFREETIME, kMaxArgStringLength)) 4993 { 4994 if(-1 == checkAndSetIntValue(argv[i+1], CFSTR(kIOHibernateFreeTimeKey), 4995 apply, false, kNoMultiplier, 4996 ac, battery, ups)) 4997 { 4998 ret = kParseBadArgs; 4999 goto exit; 5000 } 5001 modified |= kModSettings; 5002 i+=2; 5003 } else if(0 == strncmp(argv[i], ARG_HIBERNATEFILE, kMaxArgStringLength)) 5004 { 5005 if(-1 == checkAndSetStrValue(argv[i+1], CFSTR(kIOHibernateFileKey), 5006 apply, ac, battery, ups)) 5007 { 5008 ret = kParseBadArgs; 5009 goto exit; 5010 } 5011 modified |= kModSettings; 5012 i+=2; 5013 } else if(0 == strncmp(argv[i], ARG_GPU, kMaxArgStringLength)) 5014 { 5015 if(-1 == checkAndSetIntValue(argv[i+1], CFSTR(kIOPMGPUSwitchKey), 5016 apply, false, kNoMultiplier, 5017 ac, battery, ups)) 5018 { 5019 ret = kParseBadArgs; 5020 goto exit; 5021 } 5022 modified |= kModSettings; 5023 i+=2; 5024 } else if(0 == strncmp(argv[i], ARG_NETAVAILABLE, kMaxArgStringLength)) 5025 { 5026 if(-1 == checkAndSetIntValue(argv[i+1], 5027 CFSTR(kIOPMPrioritizeNetworkReachabilityOverSleepKey), 5028 apply, false, kNoMultiplier, 5029 ac, battery, ups)) 5030 { 5031 ret = kParseBadArgs; 5032 goto exit; 5033 } 5034 modified |= kModSettings; 5035 i+=2; 5036 } else if(0 == strncmp(argv[i], ARG_DEEPSLEEP, kMaxArgStringLength)) 5037 { 5038 if(-1 == checkAndSetIntValue(argv[i+1], CFSTR(kIOPMDeepSleepEnabledKey), 5039 apply, false, kNoMultiplier, 5040 ac, battery, ups)) 5041 { 5042 ret = kParseBadArgs; 5043 goto exit; 5044 } 5045 modified |= kModSettings; 5046 i+=2; 5047 } else if(0 == strncmp(argv[i], ARG_DEEPSLEEPDELAY, kMaxArgStringLength)) 5048 { 5049 if(-1 == checkAndSetIntValue(argv[i+1], CFSTR(kIOPMDeepSleepDelayKey), 5050 apply, false, kNoMultiplier, 5051 ac, battery, ups)) 5052 { 5053 ret = kParseBadArgs; 5054 goto exit; 5055 } 5056 modified |= kModSettings; 5057 i+=2; 5058 } else if(0 == strncmp(argv[i], ARG_DARKWAKES, kMaxArgStringLength)) 5059 { 5060 if((-1 == checkAndSetIntValue(argv[i+1], 5061 CFSTR(kIOPMDarkWakeBackgroundTaskKey), apply, 5062 false, kNoMultiplier, ac, battery, ups)) || 5063 (-1 == checkAndSetIntValue(argv[i+1], 5064 CFSTR(kIOPMSleepServicesKey), apply, false, 5065 kNoMultiplier, ac, battery, ups))) 5066 { 5067 ret = kParseBadArgs; 5068 goto exit; 5069 } 5070 modified |= kModSettings; 5071 i+=2; 5072 } else if(0 == strncmp(argv[i], ARG_AUTOPOWEROFF, kMaxArgStringLength)) 5073 { 5074 if(-1 == checkAndSetIntValue(argv[i+1], CFSTR(kIOPMAutoPowerOffEnabledKey), 5075 apply, false, kNoMultiplier, 5076 ac, battery, ups)) 5077 return kParseBadArgs; 5078 modified |= kModSettings; 5079 i+=2; 5080 } else if(0 == strncmp(argv[i], ARG_AUTOPOWEROFFDELAY, kMaxArgStringLength)) 5081 { 5082 if(-1 == checkAndSetIntValue(argv[i+1], CFSTR(kIOPMAutoPowerOffDelayKey), 5083 apply, false, kNoMultiplier, 5084 ac, battery, ups)) 5085 return kParseBadArgs; 5086 modified |= kModSettings; 5087 i+=2; 5088 } else { 5089 // Determine if this is a number. 5090 // If so, the user is setting the active power profile 5091 // for the power sources specified in applyTo 5092 // If not, bail with bad input. 5093 char *endptr = 0; 5094 long val; 5095 CFNumberRef prof_val = 0; 5096 5097 if(!local_profiles) { 5098 ret = kParseInternalError; 5099 goto exit; 5100 } 5101 5102 val = strtol(argv[i], &endptr, 10); 5103 5104 if(0 != *endptr || (val < -1) || (val > 4) ) 5105 { 5106 // the string contained some non-numerical characters 5107 // or the profile number was out of the expected range 5108 ret = kParseBadArgs; 5109 goto exit; 5110 } 5111 prof_val = CFNumberCreate(0, kCFNumberIntType, &val); 5112 if(!prof_val) { 5113 ret = kParseInternalError; 5114 } else { 5115 // setting a profile 5116 if(kApplyToBattery & apply) { 5117 CFDictionarySetValue(local_profiles, CFSTR(kIOPMBatteryPowerKey), prof_val); 5118 } 5119 if(kApplyToCharger & apply) { 5120 CFDictionarySetValue(local_profiles, CFSTR(kIOPMACPowerKey), prof_val); 5121 } 5122 if(kApplyToUPS & apply) { 5123 CFDictionarySetValue(local_profiles, CFSTR(kIOPMUPSPowerKey), prof_val); 5124 } 5125 CFRelease(prof_val); 5126 5127 modified |= kModProfiles; 5128 } 5129 goto exit; 5130 } 5131 } // if 5132 } // while 5133 5134exit: 5135 if(modified & kModSettings) { 5136 *settings = local_settings; 5137 *modified_power_sources = apply; 5138 } else { 5139 if(local_settings) CFRelease(local_settings); 5140 } 5141 5142 if(modified & kModSystemSettings) { 5143 *system_power_settings = local_system_power_settings; 5144 } else { 5145 if(local_system_power_settings) CFRelease(local_system_power_settings); 5146 } 5147 5148 if(modified & kModProfiles) { 5149 *active_profiles = local_profiles; 5150 } else { 5151 if(local_profiles) CFRelease(local_profiles); 5152 } 5153 5154 if(modified & kModUPSThresholds) { 5155 if(ups_thresholds) *ups_thresholds = local_ups_settings; 5156 } else { 5157 if(local_ups_settings) CFRelease(local_ups_settings); 5158 } 5159 5160 if(modified & kModSched) { 5161 *scheduled_event = local_scheduled_event; 5162 *cancel_scheduled_event = local_cancel_event; 5163 } 5164 5165 if(modified & kModRepeat) { 5166 *repeating_event = local_repeating_event; 5167 *cancel_repeating_event = local_cancel_repeating; 5168 } else { 5169 if(local_repeating_event) CFRelease(local_repeating_event); 5170 } 5171 5172 return ret; 5173} 5174 5175// int arePowerSourceSettingsInconsistent(CFDictionaryRef) 5176// Function - determine if the settings will produce the "intended" idle sleep consequences 5177// Parameter - The CFDictionary contains energy saver settings of 5178// CFStringRef keys and CFNumber/CFBoolean values 5179// Return - non-zero bitfield, each bit indicating a setting inconsistency 5180// 0 if settings will produce expected result 5181// -1 in case of other error 5182static int arePowerSourceSettingsInconsistent(CFDictionaryRef set) 5183{ 5184 int sleep_time, disk_time, dim_time; 5185 CFNumberRef num; 5186 int ret = 0; 5187 5188 num = isA_CFNumber(CFDictionaryGetValue(set, CFSTR(kIOPMSystemSleepKey))); 5189 if(!num || !CFNumberGetValue(num, kCFNumberIntType, &sleep_time)) return -1; 5190 5191 num = isA_CFNumber(CFDictionaryGetValue(set, CFSTR(kIOPMDisplaySleepKey))); 5192 if(!num || !CFNumberGetValue(num, kCFNumberIntType, &dim_time)) return -1; 5193 5194 num = isA_CFNumber(CFDictionaryGetValue(set, CFSTR(kIOPMDiskSleepKey))); 5195 if(!num || !CFNumberGetValue(num, kCFNumberIntType, &disk_time)) return -1; 5196 5197 // For system sleep to occur around the time you set it to, the disk and display 5198 // sleep timers must conform to these rules: 5199 // 1. display sleep <= system sleep 5200 // 2. If system sleep != Never, then disk sleep can not be == Never 5201 // 2a. It is, however, OK for disk sleep > system sleep. A funky hack in 5202 // the kernel IOPMrootDomain allows this. 5203 // and note: a time of zero means "never power down" 5204 5205 if(sleep_time != 0) 5206 { 5207 if(dim_time > sleep_time || dim_time == 0) ret |= kInconsistentDisplaySetting; 5208 5209 if(disk_time == 0) ret |= kInconsistentDiskSetting; 5210 } 5211 5212 return ret; 5213} 5214 5215// void checkSettingConsistency(CFDictionaryRef) 5216// Checks ES settings profile by profile 5217// Prints a user warning if any idle timer settings violate the kernel's assumptions 5218// about idle, disk, and display sleep timers. 5219// Parameter - a CFDictionary of energy settings "profiles", usually one per power supply 5220static void checkSettingConsistency(CFDictionaryRef profiles) 5221{ 5222 int num_profiles; 5223 int i; 5224 int ret; 5225 char buf[kMaxLongStringLength]; 5226 CFStringRef *keys; 5227 CFDictionaryRef *values; 5228 5229 num_profiles = CFDictionaryGetCount(profiles); 5230 keys = (CFStringRef *)malloc(num_profiles * sizeof(void *)); 5231 values = (CFDictionaryRef *)malloc(num_profiles * sizeof(void *)); 5232 if(!keys || !values) return; 5233 CFDictionaryGetKeysAndValues(profiles, (const void **)keys, (const void **)values); 5234 5235// TODO: Warn user if 1) they have just changed the custom settings 5236// 2) their active profile is _NOT_ custom 5237 5238 for(i=0; i<num_profiles; i++) 5239 { 5240 // Check settings profile by profile 5241 if( isA_CFDictionary(values[i]) 5242 && (ret = arePowerSourceSettingsInconsistent(values[i])) ) 5243 { 5244 // get profile name 5245 if(!CFStringGetCString(keys[i], buf, kMaxLongStringLength, kCFStringEncodingMacRoman)) break; 5246 5247 fprintf(stderr, "Warning: Idle sleep timings for \"%s\" may not behave as expected.\n", buf); 5248 if(ret & kInconsistentDisplaySetting) 5249 { 5250 fprintf(stderr, "- Display sleep should have a lower timeout than system sleep.\n"); 5251 } 5252 if(ret & kInconsistentDiskSetting) 5253 { 5254 fprintf(stderr, "- Disk sleep should be non-zero whenever system sleep is non-zero.\n"); 5255 } 5256 fflush(stderr); 5257 } 5258 } 5259 5260 free(keys); 5261 free(values); 5262} 5263 5264static ScheduledEventReturnType *scheduled_event_struct_create(void) 5265{ 5266 ScheduledEventReturnType *ret = malloc(sizeof(ScheduledEventReturnType)); 5267 if(!ret) return NULL; 5268 ret->who = 0; 5269 ret->when = 0; 5270 ret->which = 0; 5271 return ret; 5272} 5273 5274static void scheduled_event_struct_destroy( 5275 ScheduledEventReturnType *free_me) 5276{ 5277 if( (0 == free_me) ) return; 5278 if(free_me->who) { 5279 CFRelease(free_me->who); 5280 free_me->who = 0; 5281 } 5282 if(free_me->when) { 5283 CFRelease(free_me->when); 5284 free_me->when = 0; 5285 } 5286 if((free_me)->which) { 5287 CFRelease(free_me->which); 5288 free_me->which = 0; 5289 } 5290 free(free_me); 5291} 5292 5293 5294static IOReturn _pm_connect(mach_port_t *newConnection) 5295{ 5296 kern_return_t kern_result = KERN_SUCCESS; 5297 5298 if(!newConnection) return kIOReturnBadArgument; 5299 5300 // open reference to PM configd 5301 kern_result = bootstrap_look_up2(bootstrap_port, 5302 kIOPMServerBootstrapName, 5303 newConnection, 5304 0, 5305 BOOTSTRAP_PRIVILEGED_SERVER); 5306 5307 if(KERN_SUCCESS != kern_result) { 5308 return kIOReturnError; 5309 } 5310 return kIOReturnSuccess; 5311} 5312 5313static IOReturn _pm_disconnect(mach_port_t connection) 5314{ 5315 if(!connection) return kIOReturnBadArgument; 5316 mach_port_destroy(mach_task_self(), connection); 5317 return kIOReturnSuccess; 5318} 5319 5320/******************************************************************************/ 5321/* */ 5322/* ASL & MESSAGETRACER & HISTORY */ 5323/* */ 5324/******************************************************************************/ 5325 5326/* 5327 * Cache the message in a temp ring buffer. 5328 * 5329 * ASL doesn't allow re-positioning the current read pointer into 5330 * aslresponse. There is no aslresponse_prev() API. So, we 5331 * store the message retrieved from aslreponse in a ring 5332 * buffer. 5333 */ 5334static aslmsg _cacheAndGetMsg(aslresponse pmresponse) 5335{ 5336 aslmsg msg = NULL; 5337 5338 if (msgCache == NULL) 5339 { 5340 msgCache = calloc(1, sizeof(MsgCache)); 5341 if (!msgCache) return NULL; 5342 } 5343 5344 if (((msgCache->writeIdx+1) % RING_SIZE) == msgCache->readIdx) 5345 return NULL; /* overflow */ 5346 5347 msg = aslresponse_next(pmresponse); 5348 if (!msg) return NULL; 5349 5350 msgCache->msgRing[msgCache->writeIdx] = msg; 5351 5352 msgCache->writeIdx = (msgCache->writeIdx+1) % RING_SIZE; 5353 return msg; 5354} 5355 5356static aslmsg _my_next_response(aslresponse pmresponse) 5357{ 5358 aslmsg next_msg = 0; 5359 5360 /* 5361 * _my_next_response returns messages from our cache 5362 * until there aren't any more messages in it. 5363 * Then it returns messages from the PM ASL store, via pmresponse. 5364 */ 5365 if (msgCache && (msgCache->readIdx != msgCache->writeIdx)) 5366 { 5367 next_msg = msgCache->msgRing[msgCache->readIdx]; 5368 msgCache->readIdx = (msgCache->readIdx+1) % RING_SIZE; 5369 } 5370 5371 /* 5372 * If the cache is empty, then we pull messages straight from the ASL store. 5373 */ 5374 if (0 == next_msg) { 5375 next_msg = aslresponse_next(pmresponse); 5376 } 5377 5378 return next_msg; 5379} 5380 5381/* 5382 * Called when current event is 'Sleep', to find out 5383 * the time stamp of next wake event. 5384 * 5385 * Possible transitions: 5386 * Sleep -> Wake 5387 * Sleep -> DarkWake 5388 */ 5389 5390static int32_t _getNextWakeTime(aslresponse pmresponse) 5391{ 5392 const char *domain = NULL; 5393 const char *timeStr = NULL; 5394 int32_t wakeTime = -1; 5395 aslmsg next; 5396 5397 do { 5398 5399 if ((next = _cacheAndGetMsg(pmresponse)) == NULL) break; 5400 5401 domain = asl_get(next, kPMASLDomainKey); 5402 if (!domain) break; 5403 5404 if ( (!strncmp(kPMASLDomainPMWake, domain, sizeof(kPMASLDomainPMWake) )) || 5405 (!strncmp(kPMASLDomainPMDarkWake, domain, sizeof(kPMASLDomainPMDarkWake) )) ) 5406 { 5407 timeStr = asl_get(next, ASL_KEY_TIME); 5408 if (timeStr) 5409 wakeTime = atol(timeStr); 5410 break; 5411 } 5412 else if (!strncmp(kPMASLDomainPMSleep, domain, sizeof(kPMASLDomainPMSleep) )) 5413 { 5414 /* Came across another sleep trace. Wake trace is missing */ 5415 break; 5416 } 5417 } while(1); 5418 5419 return wakeTime; 5420} 5421 5422/* 5423 * Called when current event is 'wake/darkWake', to find out 5424 * the time stamp of next sleep/wake event. 5425 * 5426 * Possible transitions: 5427 * Wake -> Sleep 5428 * DarkWake -> Sleep 5429 * DarkWake -> Wake 5430 */ 5431static int32_t _getNextSleepTime(aslresponse pmresponse, const char *curr_domain) 5432{ 5433 const char *domain = NULL; 5434 const char *timeStr = NULL; 5435 int32_t sleepTime = -1; 5436 uint32_t sleepCnt = 0; 5437 aslmsg next; 5438 5439 do { 5440 5441 5442 if ((next = _cacheAndGetMsg(pmresponse)) == NULL) break; 5443 domain = asl_get(next, kPMASLDomainKey); 5444 if (!domain) continue; 5445 5446 /* Check for events with unexpected transitions */ 5447 if (( !strncmp(kPMASLDomainPMWake, curr_domain, sizeof(kPMASLDomainPMWake) )) && 5448 ( (!strncmp(kPMASLDomainPMWake, domain, sizeof(kPMASLDomainPMWake) )) || 5449 (!strncmp(kPMASLDomainPMDarkWake, domain, sizeof(kPMASLDomainPMDarkWake)) ) 5450 )) 5451 { 5452 /* Wake -> Wake or Wake -> DarkWake is unexpected */ 5453 break; 5454 } 5455 5456 else if ((!strncmp(kPMASLDomainPMDarkWake, curr_domain, sizeof(kPMASLDomainPMDarkWake))) && 5457 (!strncmp(kPMASLDomainPMDarkWake, domain, sizeof(kPMASLDomainPMDarkWake)) )) 5458 { 5459 /* DarkWake -> DarkWake is unexpected */ 5460 break; 5461 } 5462 5463 if ( (!strncmp(kPMASLDomainPMSleep, domain, sizeof(kPMASLDomainPMSleep) )) || 5464 (!strncmp(kPMASLDomainPMWake, domain, sizeof(kPMASLDomainPMWake) )) ) 5465 { 5466 const char *value1 = asl_get(next, kPMASLValueKey); 5467 if (value1) { 5468 sleepCnt = strtol(value1, NULL, 0); 5469 5470 if (sleepCnt == 1) 5471 break; /* System rebooted at this point */ 5472 } 5473 5474 timeStr = asl_get(next, ASL_KEY_TIME); 5475 if (timeStr) 5476 sleepTime = atol(timeStr); 5477 break; 5478 } 5479 } while(1); 5480 5481 return sleepTime; 5482} 5483 5484#define kPMASLStorePath "/var/log/powermanagement" 5485 5486static aslresponse open_pm_asl_store(int *result) 5487{ 5488 aslresponse query = NULL; 5489 aslresponse response = NULL; 5490 asl_store_t *pmstore = NULL; 5491 uint64_t endMessageID; 5492 5493 query = (aslresponse)calloc(1, sizeof(asl_search_result_t)); 5494 if (query != NULL) 5495 { 5496 query->msg = (asl_msg_t **)calloc(1, sizeof(asl_msg_t *)); 5497 if (query->msg != NULL) 5498 { 5499 asl_msg_t *cq = (asl_msg_t *)asl_new(ASL_TYPE_QUERY); 5500 if (cq != NULL) 5501 { 5502 query->msg[0] = cq; 5503 query->count = 1; 5504 asl_set_query((aslmsg)cq, ASL_KEY_FACILITY, kPMFacility, ASL_QUERY_OP_EQUAL); 5505 5506 *result = asl_store_open_read(kPMASLStorePath, &pmstore); 5507 if (0 == *result) { 5508 *result = asl_store_match(pmstore, query, &response, &endMessageID, 0, 0, 1); 5509 } 5510 asl_free((aslmsg)cq); 5511 } 5512 free(query->msg); 5513 } 5514 free(query); 5515 } 5516 5517 return response; 5518} 5519 5520/* All PM messages in ASL log */ 5521static void show_log(void) 5522{ 5523 aslmsg m = 0; 5524 char uuid[100]; 5525 long sleep_cnt = 0; 5526 int dark_wake_cnt = 0; 5527 bool first_iter = true; 5528 CFAbsoluteTime boot_time = 0; 5529 5530 int asl_result = -1; 5531 aslresponse response = NULL; 5532 5533 response = open_pm_asl_store(&asl_result); 5534 if (!response) 5535 { 5536 printf("Error(%d) - no messages found in PM ASL data store at: %s\n", asl_result, kPMASLStorePath); 5537 return; 5538 } else { 5539 printf("PM ASL data store: %s\n", kPMASLStorePath); 5540 } 5541 5542 uuid[0] = 0; 5543 5544 while ((m = _my_next_response(response))) 5545 { 5546 const char *val = NULL; 5547 int32_t print_duration_time = 0; 5548 uint32_t time_read = 0; 5549 char buf[40]; 5550 bool new_boot_cycle = false; 5551 5552 if ((val = asl_get(m, kPMASLDomainKey))) 5553 { 5554 if (!strncmp(val, kPMASLDomainPMStart, sizeof(kPMASLDomainPMStart)-1)) { 5555 new_boot_cycle = true; 5556 } 5557 } 5558 5559 if (((val = asl_get(m, kPMASLUUIDKey)) && (strncmp( val, uuid, sizeof(uuid)) != 0)) || new_boot_cycle ) 5560 { 5561 // New Sleep cycle is about to begin 5562 // Print Sleep cnt and dark wake cnt of previous sleep/wake cycle 5563 if ( !first_iter ) 5564 { 5565 printf("Sleep/Wakes since boot"); 5566 if (boot_time) { 5567 printf(" at "); 5568 print_pretty_date(boot_time, false); 5569 5570 } 5571 printf(":%ld Dark Wake Count in this sleep cycle:%d\n", sleep_cnt, dark_wake_cnt); 5572 } 5573 first_iter = false; 5574 5575 printf("\n"); // Extra line to seperate from previous sleep/wake cycles 5576 dark_wake_cnt = 0; 5577 5578 // Print the header for each column 5579 printf("%-25s %-20s\t%-75s\t%-10s\t%-10s\n", "Time stamp", "Domain", "Message", "Duration", "Delay"); 5580 printf("%-25s %-20s\t%-75s\t%-10s\t%-10s\n", "==========", "======", "=======", "========", "====="); 5581 5582 // Print and save UUID of the new cycle 5583 snprintf(uuid, sizeof(uuid), "%s", val); 5584 printf("UUID: %s\n", val); 5585 sleep_cnt = 0; 5586 } 5587 5588 // Time 5589 if ((val = asl_get(m, ASL_KEY_TIME))) 5590 { 5591 time_read = atol(val); 5592 CFAbsoluteTime abs_time = (CFAbsoluteTime)(time_read - kCFAbsoluteTimeIntervalSince1970); 5593 print_pretty_date(abs_time, false); 5594 if (new_boot_cycle) 5595 boot_time = abs_time; 5596 } 5597 5598 5599 // Domain 5600 if ((val = asl_get(m, kPMASLDomainKey))) 5601 { 5602 const char *value1 = asl_get(m, kPMASLValueKey); 5603 5604 if (strnstr(val, "Response.", strlen(val))) { 5605 printf("%-20s\t", ((char *)val + (uintptr_t)strlen("Response."))); 5606 } else { 5607 printf("%-20s\t", (char *)val); 5608 } 5609 5610 if (!strncmp(kPMASLDomainPMSleep, val, sizeof(kPMASLDomainPMSleep) )) 5611 { 5612 if (value1) { 5613 sleep_cnt = strtol(value1, NULL, 0); 5614 5615 } 5616 if ( (print_duration_time = _getNextWakeTime(response)) != -1) { 5617 print_duration_time -= time_read; 5618 } else { 5619 print_duration_time = 0; 5620 } 5621 } 5622 else if (!strncmp(kPMASLDomainPMDarkWake, val, sizeof(kPMASLDomainPMDarkWake) )) 5623 { 5624 if (value1) { 5625 dark_wake_cnt = strtol(value1, NULL, 0); 5626 } 5627 5628 if( (print_duration_time = _getNextSleepTime(response, val)) != -1) { 5629 print_duration_time -= time_read; 5630 } else { 5631 print_duration_time = 0; 5632 } 5633 } 5634 else if (!strncmp(kPMASLDomainPMWake, val, sizeof(kPMASLDomainPMWake) )) 5635 { 5636 if ( (print_duration_time = _getNextSleepTime(response, val)) != -1) { 5637 print_duration_time -= time_read; 5638 } else { 5639 print_duration_time = 0; 5640 } 5641 } 5642/* else if (!strnstr(val, kPMASLDomainSummaryPrefix, strlen(kPMASLDomainSummaryPrefix))) 5643 { 5644 print_duration_time = value1; 5645 } 5646 */ 5647 } 5648 else 5649 { 5650 printf("%-20s\t", " "); 5651 } 5652 5653 // Message 5654 if ((val = asl_get(m, ASL_KEY_MSG))) { 5655 printf("%-75s\t", val); 5656 } else { 5657 printf("%-75s\t", " "); 5658 } 5659 5660 // Duration/Delay 5661 if (0 != print_duration_time) { 5662 snprintf(buf, sizeof(buf), "%d secs", print_duration_time); 5663 } else { 5664 buf[0] = 0; 5665 } 5666 printf("%-10s", buf); 5667 5668 if ((val = asl_get(m, kPMASLDelayKey))) 5669 { 5670 printf("%-10s\t", val); 5671 } 5672 5673 printf("\n"); 5674 } 5675 5676 if (sleep_cnt || dark_wake_cnt) { 5677 printf("\nTotal Sleep/Wakes since boot"); 5678 if (boot_time) { 5679 printf(" at "); 5680 print_pretty_date(boot_time, false); 5681 } 5682 printf(":%ld\n", sleep_cnt); 5683 } 5684 printf("\n"); 5685 show_assertions("Showing all currently held IOKit power assertions"); 5686} 5687 5688 5689static void show_power_event_history(void) 5690{ 5691 IOReturn ret; 5692 CFArrayRef powpowHistory = NULL; 5693 CFStringRef uuid = NULL; 5694 CFDictionaryRef uuid_details; 5695 char uuid_cstr[255]; 5696 int uuid_index; 5697 int uuid_count; 5698 //CFAbsoluteTime set_time = 0.0; 5699 //CFAbsoluteTime clear_time = 0.0; 5700 //CFNumberRef timestamp; 5701 CFStringRef timestamp; 5702 char st[60]; 5703 char ct[60]; 5704 5705 ret = IOPMCopyPowerHistory(&powpowHistory); 5706 5707 if (kIOReturnSuccess != ret || NULL == powpowHistory) 5708 { 5709 printf("Error - no power history found. (IOPMCopyPowerHistory error = 0x%08x)\n", ret); 5710 goto exit; 5711 } 5712 5713 uuid_count = CFArrayGetCount(powpowHistory); 5714 printf("Power History Summary (%d UUIDs)\n", uuid_count); 5715 5716 int i = 0; 5717 for(; i < 9; i++) 5718 printf("----------"); 5719 printf("\n"); 5720 5721 printf("%-40s|%-24s|%-24s|\n", "UUID", "Set Time", "Clear Time"); 5722 5723 i = 0; 5724 for(; i < 9; i++) 5725 printf("----------"); 5726 printf("\n"); 5727 5728 for (uuid_index = 0; uuid_index < uuid_count; uuid_index++) 5729 { 5730 uuid_details = isA_CFDictionary(CFArrayGetValueAtIndex(powpowHistory, uuid_index)); 5731 if (uuid_details) { 5732 uuid = CFDictionaryGetValue( 5733 uuid_details, 5734 CFSTR(kIOPMPowerHistoryUUIDKey)); 5735 CFStringGetCString(uuid, uuid_cstr, sizeof(uuid_cstr), kCFStringEncodingUTF8); 5736 5737 printf("%-40s|", uuid_cstr); 5738 5739 timestamp = CFDictionaryGetValue(uuid_details, 5740 CFSTR(kIOPMPowerHistoryTimestampKey)); 5741 CFStringGetCString(timestamp, st, sizeof(st), kCFStringEncodingUTF8); 5742 5743 timestamp = CFDictionaryGetValue(uuid_details, 5744 CFSTR(kIOPMPowerHistoryTimestampCompletedKey)); 5745 CFStringGetCString(timestamp, ct, sizeof(ct), kCFStringEncodingUTF8); 5746 5747 printf("%-24.24s|%-24.24s|\n", st, ct); 5748 } 5749 } 5750 i = 0; 5751 for(; i < 9; i++) 5752 printf("----------"); 5753 printf("\n"); 5754exit: 5755 return; 5756} 5757 5758 5759static void printHistoryDetailedEventDictionary(CFDictionaryRef event) 5760{ 5761 CFStringRef evTypeString = NULL; 5762 CFNumberRef evReasonNum = NULL; 5763 CFNumberRef evResultNum = NULL; 5764 CFStringRef evDeviceNameString = NULL; 5765 CFStringRef evUUIDString = NULL; 5766 CFStringRef evInterestedDeviceNameString = NULL; 5767 CFNumberRef evTimestampAbsTime = NULL; 5768 CFNumberRef evElapsedTimeMicroSec = NULL; 5769 CFNumberRef evOldState = NULL; 5770 CFNumberRef evNewState = NULL; 5771 5772 CFAbsoluteTime ts = 0.0; 5773 int foo = 0; 5774 int bar = 0; 5775 char buf_cstr[40]; 5776 char *display_cstr = NULL; 5777 5778 evTypeString = isA_CFString(CFDictionaryGetValue(event, CFSTR(kIOPMPowerHistoryEventTypeKey))); 5779 evReasonNum = isA_CFNumber(CFDictionaryGetValue(event, CFSTR(kIOPMPowerHistoryEventReasonKey))); 5780 evResultNum = isA_CFNumber(CFDictionaryGetValue(event, CFSTR(kIOPMPowerHistoryEventResultKey))); 5781 evDeviceNameString = isA_CFString(CFDictionaryGetValue(event, CFSTR(kIOPMPowerHistoryDeviceNameKey))); 5782 evUUIDString = isA_CFString(CFDictionaryGetValue(event, CFSTR(kIOPMPowerHistoryUUIDKey))); 5783 evInterestedDeviceNameString = isA_CFString(CFDictionaryGetValue(event, CFSTR(kIOPMPowerHistoryInterestedDeviceNameKey))); 5784 evTimestampAbsTime = isA_CFNumber(CFDictionaryGetValue(event, CFSTR(kIOPMPowerHistoryTimestampKey))); 5785 evOldState = isA_CFNumber(CFDictionaryGetValue(event, CFSTR(kIOPMPowerHistoryOldStateKey))); 5786 evNewState = isA_CFNumber(CFDictionaryGetValue(event, CFSTR(kIOPMPowerHistoryNewStateKey))); 5787 evElapsedTimeMicroSec = isA_CFNumber(CFDictionaryGetValue(event, CFSTR(kIOPMPowerHistoryElapsedTimeUSKey))); 5788 5789 // Timestamp 5790 if (evTimestampAbsTime) { 5791 CFNumberGetValue(evTimestampAbsTime, kCFNumberDoubleType, &ts); 5792 print_pretty_date(ts, false); 5793 printf("|"); 5794 } 5795 else 5796 printf("\t"); 5797 5798 bool systemEvent = false; 5799 5800 //Event Type 5801 if (evTypeString) { 5802 if (CFStringGetCString(evTypeString, buf_cstr, sizeof(buf_cstr), kCFStringEncodingUTF8)) { 5803 display_cstr = buf_cstr; 5804 } else { 5805 display_cstr = "String encoding error"; 5806 } 5807 5808 if( !strcmp(display_cstr, "UUIDSet") 5809 || !strcmp(display_cstr, "UUIDClear") 5810 || !strcmp(display_cstr, "Sleep") 5811 || !strcmp(display_cstr, "SleepDone") 5812 || !strcmp(display_cstr, "Wake") 5813 || !strcmp(display_cstr, "WakeDone") ) { 5814 5815 systemEvent = true; 5816 5817 // Prints bold lettering on supported systems 5818 printf("%c[1m", (char)27); 5819 } 5820 printf("%-25.25s", display_cstr); 5821 if( systemEvent ) { 5822 printf("%c[0m", (char)27); 5823 } 5824 printf("|"); 5825 } 5826 else { 5827 printf("%-25s", " "); 5828 } 5829 5830 // Power State Change 5831 if (evOldState && evNewState) { 5832 CFNumberGetValue(evOldState, kCFNumberIntType, &foo); 5833 CFNumberGetValue(evNewState, kCFNumberIntType, &bar); 5834 printf("%d to %d |", foo, bar); 5835 } 5836 else 5837 printf("%-7s|", " "); 5838 5839 // Reason number 5840 if (evReasonNum) { 5841 CFNumberGetValue(evReasonNum, kCFNumberIntType, &foo); 5842 printf("%-7d|", foo); 5843 } 5844 else 5845 printf("%-7s|", " "); 5846 5847 // Result Number 5848 if (evResultNum) { 5849 CFNumberGetValue(evResultNum, kCFNumberIntType, &foo); 5850 printf("%-7d|", foo); 5851 } 5852 else 5853 printf("%-7s|", " "); 5854 5855 // Device Name 5856 if (evDeviceNameString) { 5857 if (CFStringGetCString(evDeviceNameString, buf_cstr, sizeof(buf_cstr), kCFStringEncodingUTF8)) { 5858 display_cstr = buf_cstr; 5859 } else { 5860 display_cstr = "String encoding error"; 5861 } 5862 5863 printf("%-30.30s|", display_cstr); 5864 } 5865 else { 5866 if ( !systemEvent ) { 5867 printf("%-30s|", " "); 5868 } 5869 } 5870 5871 // Event UUID, for system events 5872 if (evUUIDString) { 5873 if (CFStringGetCString(evUUIDString, buf_cstr, sizeof(buf_cstr), kCFStringEncodingUTF8)) { 5874 display_cstr = buf_cstr; 5875 } else { 5876 display_cstr = "String encoding error"; 5877 } 5878 // Bold lettering, in supported systems 5879 printf("%c[1m", (char)27); 5880 printf("%-61s", display_cstr); 5881 printf("%c[0m", (char)27); 5882 5883 printf("|"); 5884 } 5885 5886 // Interested Device 5887 if (evInterestedDeviceNameString) { 5888 if (CFStringGetCString(evInterestedDeviceNameString, buf_cstr, sizeof(buf_cstr), kCFStringEncodingUTF8)) { 5889 display_cstr = buf_cstr; 5890 } else { 5891 display_cstr = "String encoding error"; 5892 } 5893 5894 printf("%-30.30s|", display_cstr); 5895 } 5896 else { 5897 if( !systemEvent ) { 5898 printf("%-30s|", " "); 5899 } 5900 } 5901 5902 // Time Elapsed 5903 if (evElapsedTimeMicroSec) { 5904 CFNumberGetValue(evElapsedTimeMicroSec, kCFNumberIntType, &foo); 5905 printf("%-7d |", foo); 5906 } 5907 else 5908 printf("%-7s|", " "); 5909 5910 printf("\n"); 5911} 5912 5913static void mt2bookmark(void) 5914{ 5915 mach_port_t connectIt = MACH_PORT_NULL; 5916 int disregard; 5917 5918 if (kIOReturnSuccess == _pm_connect(&connectIt)) 5919 { 5920 io_pm_get_value_int(connectIt, kIOPMMT2Bookmark, &disregard); 5921 _pm_disconnect(connectIt); 5922 } 5923 return; 5924} 5925 5926 5927static void show_power_event_history_detailed(void) 5928{ 5929 IOReturn ret; 5930 CFArrayRef powpowHistory = NULL; 5931 CFStringRef uuid = NULL; 5932 char uuid_cstr[50]; 5933 CFDictionaryRef uuid_details; 5934 int uuid_index; 5935 int uuid_count; 5936 5937 ret = IOPMCopyPowerHistory(&powpowHistory); 5938 5939 if (kIOReturnSuccess == kIOReturnNotFound) 5940 { 5941 printf("No power management history to display. (See 'man pmset' to turn on history logging.)\n"); 5942 goto exit; 5943 } else if (kIOReturnSuccess != ret) 5944 { 5945 printf("Error reading power management history (0x%08x)\n", ret); 5946 goto exit; 5947 } 5948 5949 uuid_count = CFArrayGetCount(powpowHistory); 5950 5951 //Bold lettering, on supported systems 5952 printf("%c[1m", (char)27); 5953 printf("Power History Detailed:\n"); 5954 printf("%c[0m", (char)27); 5955 5956 for (uuid_index = 0; uuid_index < uuid_count; uuid_index++) 5957 { 5958 uuid_details = isA_CFDictionary(CFArrayGetValueAtIndex(powpowHistory, uuid_index)); 5959 assert(uuid_details); 5960 if (!uuid_details) { 5961 continue; 5962 } 5963 5964 uuid = CFDictionaryGetValue(uuid_details, 5965 CFSTR(kIOPMPowerHistoryUUIDKey)); 5966 CFStringGetCString(uuid, uuid_cstr, 5967 sizeof(uuid_cstr), kCFStringEncodingUTF8); 5968 show_details_for_UUID( (char **)&uuid_cstr ); 5969 } 5970 5971 CFRelease(powpowHistory); 5972exit: 5973 return; 5974} 5975 5976static void set_debugFlags(char **argv) 5977{ 5978 uint32_t newFlags, oldFlags; 5979 IOReturn err; 5980 5981 newFlags = strtol(argv[0], NULL, 0); 5982 if (errno == EINVAL ) { 5983 printf("Invalid argument\n"); 5984 return; 5985 } 5986 err = IOPMSetDebugFlags(newFlags, &oldFlags); 5987 if (err == kIOReturnSuccess) 5988 printf("Debug flags changed from 0x%x to 0x%x\n", 5989 oldFlags, newFlags); 5990 else 5991 printf("Failed to change debugFlags. err=0x%x\n", err); 5992 5993} 5994 5995static void set_btInterval(char **argv) 5996{ 5997 uint32_t newInterval, oldInterval; 5998 IOReturn err; 5999 6000 newInterval = strtol(argv[0], NULL, 0); 6001 if (errno == EINVAL) { 6002 printf("Invalid argument\n"); 6003 return; 6004 } 6005 err = IOPMSetBTWakeInterval(newInterval, &oldInterval); 6006 if (err == kIOReturnSuccess) 6007 printf("Background task wake interval changed from %d secs to %d secs\n", 6008 oldInterval, newInterval); 6009 else 6010 printf("Failed to change Background task wake interval. err=0x%x\n", err); 6011 6012} 6013 6014static void set_dwlInterval(char **argv) 6015{ 6016 uint32_t newInterval, oldInterval; 6017 IOReturn err; 6018 6019 newInterval = strtol(argv[0], NULL, 0); 6020 if(errno == EINVAL) { 6021 printf("Invalid argument\n"); 6022 return; 6023 } 6024 err = IOPMSetDWLingerInterval(newInterval, &oldInterval); 6025 if(err == kIOReturnSuccess) 6026 printf("DarkWake linger interval changed from %d secs to %d secs\n", 6027 oldInterval, newInterval); 6028 else 6029 printf("Failed to change DarkWake linger interval. err=0x%x\n", err); 6030} 6031 6032static void set_saaFlags(char **argv) 6033{ 6034 uint32_t newFlags, oldFlags; 6035 IOReturn err; 6036 6037 newFlags = strtol(argv[0], NULL, 0); 6038 if(errno == EINVAL) { 6039 printf("Invalid argument\n"); 6040 return; 6041 } 6042 6043 err = IOPMChangeSystemActivityAssertionBehavior(newFlags, &oldFlags); 6044 if(err == kIOReturnSuccess) 6045 printf("System activity assertion behvior changed from %u to %u\n", 6046 oldFlags, newFlags); 6047 else 6048 printf("Failed to change system activity assertion behavior. err=0x%x\n", err); 6049} 6050 6051static bool isBatteryPollingStopped(void) 6052{ 6053 int myNotifyToken = 0; 6054 uint64_t packedBatteryData = 0; 6055 int myNotifyStatus = 0; 6056 6057 myNotifyStatus = notify_register_check(kIOPSTimeRemainingNotificationKey, &myNotifyToken); 6058 6059 if (NOTIFY_STATUS_OK == myNotifyStatus) { 6060 notify_get_state(myNotifyToken, &packedBatteryData); 6061 notify_cancel(myNotifyToken); 6062 } 6063 6064 return (packedBatteryData & kPSTimeRemainingNotifyNoPollBit) ? 1:0; 6065} 6066 6067static void set_nopoll(void) 6068{ 6069 mach_port_t connectIt = MACH_PORT_NULL; 6070 bool old_nopoll = isBatteryPollingStopped(); 6071 6072 if (kIOReturnSuccess == _pm_connect(&connectIt)) 6073 { 6074 printf("Turning battery polling: %s\n", old_nopoll ? "On":"Off"); 6075 io_pm_set_value_int(connectIt, kIOPMSetNoPoll, old_nopoll ? 0:1); 6076 _pm_disconnect(connectIt); 6077 } else { 6078 printf("Error: could not connect to powerd.\n"); 6079 } 6080 6081 if (!old_nopoll) { 6082 printf("Battery updates are stopped. Run \"pmset nopoll\" again, or reboot the system to resume.\n"); 6083 } 6084} 6085 6086static void set_new_power_bookmark(void) { 6087 printf("Bookmarked: Deprecated. Did not set a bookmark. \n"); 6088} 6089 6090static void show_details_for_UUID( char **argv ) { 6091 6092 char *uuid_cstr = argv[0]; 6093 6094 if (!uuid_cstr) return; 6095 6096 string_toupper(uuid_cstr, uuid_cstr); 6097 CFStringRef uuid = CFStringCreateWithCString( kCFAllocatorDefault, 6098 uuid_cstr, 6099 kCFStringEncodingUTF8); 6100 if( uuid == NULL ) 6101 return; 6102 6103 CFArrayRef event_array; 6104 CFDictionaryRef uuid_details; 6105 6106 IOReturn ret = IOPMCopyPowerHistoryDetailed(uuid, &uuid_details); 6107 if (kIOReturnSuccess != ret) 6108 { 6109 printf("No power management history to display for this UUID! \n"); 6110 CFRelease(uuid); 6111 return; 6112 } 6113 if (!uuid_details) 6114 { 6115 printf("No power management history available for this UUID! \n"); 6116 CFRelease(uuid); 6117 return; 6118 } 6119 6120 CFNumberRef timestamp; 6121 CFAbsoluteTime set_time = 0.0; 6122 CFAbsoluteTime clear_time = 0.0; 6123 6124 timestamp = isA_CFNumber( 6125 CFDictionaryGetValue(uuid_details, 6126 CFSTR(kIOPMPowerHistoryTimestampKey))); 6127 6128 CFNumberGetValue(timestamp, kCFNumberDoubleType, &set_time); 6129 6130 timestamp = isA_CFNumber( 6131 CFDictionaryGetValue( 6132 uuid_details, 6133 CFSTR(kIOPMPowerHistoryTimestampCompletedKey))); 6134 6135 CFNumberGetValue(timestamp, kCFNumberDoubleType, &clear_time); 6136 //Bold lettering, on supported systems 6137 6138 printf("%c[1m", (char)27); 6139 6140 // Hacky way of centering the UUID title 6141 printf("\t\t\t\t\t *UUID = %s\n", uuid_cstr); 6142 // No more bold lettering 6143 printf("%c[0m", (char)27); 6144 6145 // Print column headers, make nice table to display 6146 // power events under this UUID 6147 int i = 0; 6148 for(; i < 144; i+= 12) 6149 printf("------------"); 6150 printf("--\n"); 6151 6152 printf("%-24s|", "Timestamp"); 6153 printf("%-25s|", "Event Type"); 6154 printf("%-7s|", "Change"); 6155 printf("%-7s|", "Reason"); 6156 printf("%-7s|", "Result"); 6157 printf("%-30s|","Device Name"); 6158 printf("%-30s|","Interested Device"); 6159 printf("Time(uS)|"); 6160 printf("\n"); 6161 6162 i = 0; 6163 for(; i < 144; i+= 12) 6164 printf("------------"); 6165 printf("--\n"); 6166 6167 event_array = CFDictionaryGetValue(uuid_details, 6168 CFSTR(kIOPMPowerHistoryEventArrayKey)); 6169 int event_count = CFArrayGetCount(event_array); 6170 int event_index; 6171 CFDictionaryRef an_event; 6172 6173 // Print out individual event details 6174 for (event_index = 0; event_index < event_count; event_index++) 6175 { 6176 an_event = isA_CFDictionary(CFArrayGetValueAtIndex(event_array, event_index)); 6177 assert(an_event); 6178 if (!an_event) 6179 continue; 6180 printHistoryDetailedEventDictionary(an_event); 6181 } 6182 6183 i = 0; 6184 for(; i < 144; i+= 12) 6185 printf("------------"); 6186 printf("--\n"); 6187 6188 printf("\t Total of "); 6189 6190 printf("%c[1m", (char)27); // Bold letters 6191 printf("%d ", event_count); 6192 printf("%c[0m", (char)27); // Un-bold letters 6193 6194 printf("events under UUID "); 6195 6196 printf("%c[1m", (char)27); // Bold letters 6197 printf("%s ", uuid_cstr); 6198 printf("%c[0m", (char)27); // Un-bold letters 6199 printf("from "); 6200 printf("%c[1m", (char)27); 6201 print_pretty_date(set_time, false); 6202 printf("%c[0m", (char)27); 6203 printf("to "); 6204 printf("%c[1m", (char)27); 6205 print_pretty_date(clear_time, true); 6206 printf("%c[0m", (char)27); 6207 6208 // Done with our CFObjects. Don't want to own them anymore 6209 CFRelease(event_array); 6210 CFRelease(uuid); 6211} 6212 6213static void _print_uuid_string(){ 6214 CFStringRef _uuid = IOPMSleepWakeCopyUUID(); 6215 char str[kMaxLongStringLength]; 6216 6217 if (!_uuid) { 6218 printf("(NULL)\n"); 6219 return; 6220 } 6221 6222 CFStringGetCString(_uuid, str, sizeof(str), kCFStringEncodingUTF8); 6223 printf("%s\n", str); 6224 CFRelease(_uuid); 6225} 6226static void _show_uuid_handler( 6227 void *refcon, 6228 io_service_t batt, 6229 natural_t messageType, 6230 void *messageArgument) 6231{ 6232 if (messageType != kIOPMMessageSleepWakeUUIDChange) 6233 return; 6234 6235 print_pretty_date(CFAbsoluteTimeGetCurrent(), false); 6236 6237 if (messageArgument == (void *)kIOPMMessageSleepWakeUUIDCleared) { 6238 printf("Cleared.\n"); 6239 } else if (messageArgument == (void *)kIOPMMessageSleepWakeUUIDSet) { 6240 _print_uuid_string(); 6241 } 6242} 6243 6244static void show_uuid(bool keep_running) 6245{ 6246 if (!keep_running) { 6247 _print_uuid_string(); 6248 return; 6249 } 6250 6251 io_registry_entry_t rd = copyRootDomainRef(); 6252 IONotificationPortRef notify = NULL; 6253 io_object_t notification_ref = IO_OBJECT_NULL; 6254 6255 notify = IONotificationPortCreate(kIOMasterPortDefault); 6256 IONotificationPortSetDispatchQueue(notify, dispatch_get_main_queue()); 6257 6258 IOServiceAddInterestNotification(notify, rd, 6259 kIOGeneralInterest, _show_uuid_handler, 6260 NULL, ¬ification_ref); 6261 install_listen_IORegisterForSystemPower(); 6262 printf("Logging UUID changes.\n"); 6263 6264 print_pretty_date(CFAbsoluteTimeGetCurrent(), false); 6265 _print_uuid_string(); 6266 6267 CFRunLoopRun(); 6268} 6269 6270 6271static void show_NULL_HID_events(void) 6272{ 6273 CFArrayRef systemHIDEvents = NULL; 6274 IOReturn ret; 6275 int topLevelCount = 0; 6276 6277 ret = IOPMCopyHIDPostEventHistory(&systemHIDEvents); 6278 if (kIOReturnNotFound == ret) { 6279 // System is not collecting HID event history. 6280 // Assuming this is a setting that you can turn off with a hidden pmset flag, 6281 // then kIOReturnNotFound indicates it's turned off. 6282 printf("FAIL: ret=0x%08x kIOReturnNotFound - HID event capturing is OFF\n", ret); 6283 goto exit; 6284 } else if (kIOReturnSuccess != ret) { 6285 // Any other non-success return indicates a failure. 6286 printf("FAIL: ret=0x%08x - unexpected error\n", ret); 6287 return; 6288 } 6289 6290 if (!systemHIDEvents || (0 == (topLevelCount = CFArrayGetCount(systemHIDEvents)))) 6291 { 6292 printf("PASS: kIOReturnSuccess with %s\n", systemHIDEvents?"zero events":"no returned dictionary"); 6293 goto exit; 6294 } 6295 6296 int i; 6297 for (i=0; i<topLevelCount; i++) 6298 { 6299 CFDictionaryRef d = CFArrayGetValueAtIndex(systemHIDEvents, i); 6300 char app_path_string[1024]; 6301 CFStringRef appPathString = NULL; 6302 CFArrayRef dataList = NULL; 6303 CFDataRef dataChunk = NULL; 6304 IOPMHIDPostEventActivityWindow *bucket = NULL; 6305 CFNumberRef pidNum = NULL; 6306 int _pid = 0; 6307 6308 printf("\n"); 6309 6310 pidNum = CFDictionaryGetValue(d, kIOPMHIDAppPIDKey); 6311 CFNumberGetValue(pidNum, kCFNumberIntType, &_pid); 6312 printf("* PID = %d\n", _pid); 6313 6314 appPathString = CFDictionaryGetValue(d, kIOPMHIDAppPathKey); 6315 if (appPathString 6316 && CFStringGetCString(appPathString, app_path_string, sizeof(app_path_string), kCFStringEncodingMacRoman)) 6317 { 6318 printf(" Name = %s\n", app_path_string); 6319 } else { 6320 printf(" Name = unknown\n"); 6321 } 6322 6323 dataList = CFDictionaryGetValue(d, kIOPMHIDHistoryArrayKey); 6324 int j; 6325 for (j=0; j<CFArrayGetCount(dataList); j++) 6326 { 6327 dataChunk = CFArrayGetValueAtIndex(dataList, j); 6328 bucket = (IOPMHIDPostEventActivityWindow *)CFDataGetBytePtr(dataChunk); 6329 printf(" Bucket (5 minute) starts: "); 6330 print_pretty_date(bucket->eventWindowStart, true); 6331 printf(" NULL events = %d\n", bucket->nullEventCount); 6332 printf(" Non-NULL events = %d\n", bucket->hidEventCount); 6333 } 6334 6335 } 6336 6337exit: 6338 if (systemHIDEvents) 6339 CFRelease(systemHIDEvents); 6340 return; 6341} 6342static bool is_display_dim_captured(void) 6343{ 6344 io_registry_entry_t disp_wrangler = IO_OBJECT_NULL; 6345 CFBooleanRef dimCaptured = NULL; 6346 bool ret = false; 6347 6348 disp_wrangler = IORegistryEntryFromPath( 6349 kIOMasterPortDefault, 6350 kIOServicePlane ":/IOResources/IODisplayWrangler"); 6351 if(!disp_wrangler) 6352 return false; 6353 6354 dimCaptured = IORegistryEntryCreateCFProperty( 6355 disp_wrangler, 6356 CFSTR("DimCaptured"), 6357 kCFAllocatorDefault, 6358 kNilOptions); 6359 6360 if(dimCaptured) 6361 { 6362 ret = (kCFBooleanTrue == dimCaptured); 6363 CFRelease(dimCaptured); 6364 } 6365 6366 IOObjectRelease(disp_wrangler); 6367 6368 return ret; 6369} 6370#define kRootDomainUserClientClass "RootDomainUserClient" 6371static void show_root_domain_user_clients(void) 6372{ 6373 io_registry_entry_t _rootdomain = copyRootDomainRef(); 6374 io_iterator_t _matchingUserClients = IO_OBJECT_NULL; 6375 io_registry_entry_t _iter = IO_OBJECT_NULL; 6376 kern_return_t kr; 6377 6378 if (!_rootdomain) { 6379 printf("Internal Error - can't find root domain."); 6380 return; 6381 } 6382 6383 kr = IORegistryEntryGetChildIterator(_rootdomain, kIOServicePlane, &_matchingUserClients); 6384 if (kr != KERN_SUCCESS || !_matchingUserClients) { 6385 printf("Internal Error - can't find user clients. (kern_return_t error = %d)", kr); 6386 return; 6387 } 6388 6389 while ( ( _iter = IOIteratorNext(_matchingUserClients) ) ) 6390 { 6391 io_name_t objectClass; 6392 6393 IOObjectGetClass((io_object_t)_iter, objectClass); 6394 if (!strncmp(objectClass, kRootDomainUserClientClass, strlen(kRootDomainUserClientClass))) 6395 { 6396 CFStringRef creatorString = NULL; 6397 char stringBuf[kMaxLongStringLength]; 6398 6399 creatorString = (CFStringRef)IORegistryEntryCreateCFProperty(_iter, CFSTR(kIOUserClientCreatorKey), 0, 0); 6400 if (creatorString 6401 && CFStringGetCString(creatorString, stringBuf, sizeof(stringBuf), kCFStringEncodingMacRoman)) 6402 { 6403 printf(" - %s\n", stringBuf); 6404 } 6405 6406 if(creatorString) 6407 CFRelease(creatorString); 6408 } 6409 } 6410 6411 IOObjectRelease(_matchingUserClients); 6412 IOObjectRelease(_rootdomain); 6413 6414 return; 6415} 6416 6417static void show_getters(void) 6418{ 6419 int i = 0; 6420 for (i=0; i<the_getters_count; i++) 6421 { 6422 if (the_getters[i].actionType == kActionGetOnceNoArgs) { 6423 printf("%s\n", the_getters[i].arg); 6424 } 6425 } 6426} 6427 6428void fetchChannelData( char *object, 6429 uint64_t channel_id, 6430 bool print_error, 6431 void (^processChannelData)(uint64_t, CFStringRef)) 6432{ 6433 CFMutableDictionaryRef desiredChs = NULL, subbedChs = NULL; 6434 CFDictionaryRef mdict = NULL; 6435 IOReportSubscriptionRef iorsub = NULL; 6436 CFDictionaryRef samples = NULL; 6437 6438 6439 if (!(mdict = IOServiceMatching(object))) { 6440 printf("Failed to match an object with name %s in registry\n", object); 6441 goto exit; 6442 } 6443 desiredChs = IOReportCopyChannelsWithID(mdict, channel_id, NULL); 6444 if (!desiredChs) { 6445 if (print_error) 6446 printf("Failed to find channel reporting power state for the object %s\n", object); 6447 goto exit; 6448 } 6449 if (!(iorsub = IOReportCreateSubscription(nil, desiredChs, &subbedChs, 0, NULL))) { 6450 if (print_error) 6451 printf("Internal failure: Failed to get power state information\n"); 6452 goto exit; 6453 } 6454 6455 6456 if ((samples = IOReportCreateSamples(iorsub, subbedChs, NULL))) { 6457 IOReportIterate(samples, ^(IOReportSampleRef ch) { 6458 6459 uint64_t curstate = IOReportSimpleGetIntegerValue(ch, NULL); 6460 CFStringRef drv_name = IOReportChannelGetDriverName(ch); 6461 6462 processChannelData(curstate, drv_name); 6463 return kIOReportIterOk; 6464 }); 6465 } 6466 else { 6467 if (print_error) 6468 printf("Internal failure: Failed to get power state information\n"); 6469 goto exit; 6470 } 6471 6472 6473exit: 6474 if (iorsub) CFRelease(iorsub); 6475 if (subbedChs) CFRelease(subbedChs); 6476 if (desiredChs) CFRelease(desiredChs); 6477 if (mdict) CFRelease(mdict); 6478 6479 6480 return; 6481 6482} 6483 6484 6485void display_powerstate( char *object, bool print_error) 6486{ 6487 static bool row1 = true; 6488 6489 6490 if (row1) { 6491 printf("\n%15s %13s %9s %s\n", "Driver ID", "Current State", "Max State", "Current State Description"); 6492 row1= false; 6493 } 6494 6495 fetchChannelData(object, kPMCurrStateChID, print_error, ^(uint64_t state_id, CFStringRef drv_name) { 6496 bool is_on = false, is_usable = false, is_lowpower = false; 6497 uint32_t cur_st=0, max_st=0; 6498 CFNumberRef objRef = NULL; 6499 const char *dname_cstr; 6500 char dname_buf[25], *spcptr; 6501 6502 // making this name useful is one reason this code might be better 6503 // in ioreg :P 6504 dname_cstr = CFStringGetCStringPtr(drv_name, kCFStringEncodingUTF8); 6505 if (!dname_cstr) dname_cstr = "missing"; 6506 snprintf(dname_buf, sizeof(dname_buf), "%s", dname_cstr); 6507 if ((spcptr = strchr(dname_buf, ' '))) *spcptr = '\0'; 6508 6509 6510 CFDictionaryRef dict = IOPMCopyPowerStateInfo(state_id); 6511 if (!dict) { 6512 printf("Internal error: Failed to obtain power state information for driver %s\n", dname_cstr); 6513 return ; 6514 } 6515 objRef = CFDictionaryGetValue(dict, kIOPMNodeCurrentState); 6516 if (objRef) 6517 CFNumberGetValue(objRef, kCFNumberIntType, &cur_st); 6518 6519 objRef = CFDictionaryGetValue(dict, kIOPMNodeMaxState); 6520 if (objRef) 6521 CFNumberGetValue(objRef, kCFNumberIntType, &max_st); 6522 6523 is_on = (CFDictionaryGetValue(dict, kIOPMNodeIsPowerOn) == kCFBooleanTrue) ? true : false; 6524 is_usable = (CFDictionaryGetValue(dict, kIOPMNodeIsDeviceUsable) == kCFBooleanTrue) ? true : false; 6525 is_lowpower = (CFDictionaryGetValue(dict, kIOPMNodeIsLowPower) == kCFBooleanTrue) ? true : false; 6526 6527 6528 6529 printf("%-25s %3d %9d ", dname_buf, cur_st, max_st); 6530 if ( (is_on || is_usable || is_lowpower) == false) printf("None\n"); 6531 else { 6532 bool comma = false; 6533 if (is_on) { 6534 printf("ON"); 6535 comma = true; 6536 } 6537 if (is_usable) { 6538 if (comma) printf(","); 6539 printf("USEABLE"); 6540 comma = true; 6541 } 6542 if (is_lowpower) { 6543 if (comma) printf(","); 6544 printf("LOW_POWER"); 6545 } 6546 printf("\n"); 6547 } 6548 if (dict) CFRelease(dict); 6549 return ; 6550 }); 6551 6552 6553 return; 6554} 6555 6556 6557 6558void scan_powerplane(io_registry_entry_t service) 6559{ 6560 io_registry_entry_t child = 0; // (needs release) 6561 io_registry_entry_t childUpNext = 0; // (don't release) 6562 io_iterator_t children = 0; // (needs release) 6563 io_name_t name; 6564 kern_return_t status = KERN_SUCCESS; 6565 6566 6567 status = IORegistryEntryGetChildIterator(service, "IOPower", &children); 6568 if (status != KERN_SUCCESS) { 6569 return; 6570 } 6571 6572 childUpNext = IOIteratorNext(children); 6573 6574 status = IORegistryEntryGetNameInPlane(service, "IOPower", name); 6575 6576 if (strncmp(name, "IOPowerConnection", sizeof("IOPowerConnection"))) { 6577 6578 display_powerstate(name, false); 6579 } 6580 6581 6582 while (childUpNext) { 6583 child = childUpNext; 6584 childUpNext = IOIteratorNext(children); 6585 6586 scan_powerplane(child); 6587 6588 IOObjectRelease(child); 6589 } 6590 6591 IOObjectRelease(children); 6592 6593} 6594static void show_power_state(char **argv) 6595{ 6596 char *object = NULL; 6597 int i = 0, cnt = 0; 6598 io_registry_entry_t service = 0; 6599 6600 if (argv[i] != NULL) { 6601 object = argv[i++]; 6602 6603 do { 6604 display_powerstate(object, true); 6605 cnt++; 6606 } while ((object = argv[i++]) != NULL); 6607 if (cnt == 0) goto exit; 6608 } 6609 else if ((service = IORegistryGetRootEntry(kIOMasterPortDefault)) != 0) { 6610 scan_powerplane(service); 6611 IOObjectRelease(service); 6612 goto exit; 6613 } 6614 else { 6615 printf("Internal failure: Failed to get the registry root entry\n"); 6616 goto exit; 6617 } 6618 6619exit: 6620 ; // C doesn't allow labels at the end of functions? 6621} 6622 6623static void display_statelog(IOReportChannelRef ch, int nobjects) 6624{ 6625 uint32_t nstates, i; 6626 uint64_t state_id, transitions, ticks; 6627 uint64_t drv_name = IOReportChannelGetDriverName(ch); 6628 const char *dname_cstr; 6629 char dname_buf[22], *spcptr; 6630 uint32_t max_st=0; 6631 CFNumberRef objRef = NULL; 6632 CFDictionaryRef dict; 6633 static int max_states = 0; 6634 static int cnt = 0; 6635 int cur_state; 6636 6637 6638 nstates = IOReportStateGetCount(ch); 6639 if (cnt < nobjects) { 6640 for (i=0; i<nstates; i++) { 6641 state_id = IOReportStateGetIDForIndex(ch, i); 6642 6643 dict = IOPMCopyPowerStateInfo(state_id); 6644 if (!dict) continue; 6645 6646 objRef = CFDictionaryGetValue(dict, kIOPMNodeMaxState); 6647 if (objRef) { 6648 CFNumberGetValue(objRef, kCFNumberIntType, &max_st); 6649 if (max_st+1 > max_states) max_states=max_st+1; 6650 } 6651 6652 CFRelease(dict); 6653 } 6654 6655 cnt++; 6656 return; 6657 } 6658 6659 cur_state = IOReportStateGetCurrent(ch); 6660 if ((cnt-nobjects) % (10*nobjects) == 0) { 6661 printf("\n"); 6662 print_pretty_date(CFAbsoluteTimeGetCurrent(), true); 6663 printf("%-18s ", " Driver"); 6664 for (i=0; i < max_states; i++) { 6665 printf("%8s[%d] ", "Time", i); 6666 } 6667 printf(" "); 6668 for (i=0; i < max_states; i++) { 6669 printf("%8s[%d] ", "Entries", i); 6670 } 6671 printf("\n"); 6672 } 6673 6674 // making this name useful is one reason this code might be better 6675 // in ioreg :P 6676 dname_cstr = CFStringGetCStringPtr(drv_name, kCFStringEncodingUTF8); 6677 if (!dname_cstr) dname_cstr = "missing"; 6678 snprintf(dname_buf, sizeof(dname_buf), "%s", dname_cstr); 6679 if ((spcptr = strchr(dname_buf, ' '))) *spcptr = '\0'; 6680 6681 6682 printf("%-22s ", dname_buf); 6683 for (i=0; i<nstates; i++) { 6684 ticks = IOReportStateGetResidency(ch, i); 6685 if (cur_state == i) 6686 printf("*%#-11llx", ticks); 6687 else 6688 printf("%#-12llx", ticks); 6689 } 6690 for (;i < max_states; i++) { 6691 printf("%-12s ", " "); 6692 } 6693 printf(" "); 6694 for (i=0; i<nstates; i++) { 6695 transitions = IOReportStateGetInTransitions(ch, i); 6696 printf("%-11lld ", transitions); 6697 } 6698 for (;i < max_states; i++) { 6699 printf("%-11s ", " "); 6700 } 6701 6702 printf("\n"); 6703 6704 cnt++; 6705} 6706 6707 6708static void show_power_statelog(char **argv) 6709{ 6710 CFDictionaryRef mdict = NULL; 6711 IOReportSubscriptionRef sub = NULL; 6712 CFMutableDictionaryRef desiredChs = NULL, subbedChs = NULL; 6713 CFDictionaryRef current = NULL, diff = NULL; 6714 CFDictionaryRef prev = NULL; 6715 char *object = NULL; 6716 int i = 0, nobjects = 0; 6717 int interval = 0; 6718 6719 if (argv[i] != NULL) { 6720 if (!strncmp(argv[i], "-i", sizeof("-i"))) { 6721 interval = strtol(argv[i+1], NULL, 0); 6722 i += 2; 6723 } 6724 } 6725 6726 if (argv[i] != NULL) 6727 object = argv[i++]; 6728 else 6729 object = "IOPMrootDomain"; 6730 6731 if (!interval) interval = 5; 6732 do { 6733 if (!(mdict = IOServiceMatching(object))) { 6734 printf("Failed to match an object with name %s in registry\n", object); 6735 continue; 6736 } 6737 6738 desiredChs = IOReportCopyChannelsWithID(mdict, kPMPowerStatesChID, NULL); 6739 CFRelease(mdict); mdict = NULL; 6740 6741 if (!desiredChs) { 6742 printf("Failed to find channel reporting power state for the object %s\n", object); 6743 continue; 6744 } 6745 nobjects++; 6746 } while ((object = argv[i++]) != NULL); 6747 6748 if (nobjects == 0) goto exit; 6749 6750 if (!(sub = IOReportCreateSubscription(nil, desiredChs, &subbedChs, 0, NULL))) { 6751 printf("Internal failure: Failed to get power state information\n"); 6752 goto exit; 6753 } 6754 6755 printf("Polling at %d secs interval\n", interval); 6756 while ((current = IOReportCreateSamples(sub, subbedChs, NULL))) { 6757 if (prev) { 6758 diff = IOReportCreateSamplesDelta(prev, current, NULL); 6759 if (!diff) { 6760 printf("failed to compare power state to previous state"); 6761 goto exit; 6762 } 6763 CFRelease(prev); 6764 prev = current; 6765 // samples = diff; 6766 } 6767 else { 6768 prev = current; 6769 } 6770 IOReportIterate(diff, ^(IOReportChannelRef ch) { 6771 display_statelog(ch, nobjects); 6772 6773 return kIOReportIterOk; 6774 }); 6775 6776 sleep(interval); 6777 } 6778 6779exit: 6780 if (sub) CFRelease(sub); 6781 if (desiredChs) CFRelease(desiredChs); 6782 if (subbedChs) CFRelease(subbedChs); 6783} 6784 6785static void show_rdStats(char **argv) 6786{ 6787 6788 fetchChannelData("IOPMrootDomain", kSleepCntChID, true, 6789 ^(uint64_t state_id, CFStringRef drv_name){ printf("Sleep Count:%lld\n", state_id); } ); 6790 6791 fetchChannelData("IOPMrootDomain", kDarkWkCntChID, true, 6792 ^(uint64_t state_id, CFStringRef drv_name){ printf("Dark Wake Count:%lld\n", state_id); } ); 6793 6794 fetchChannelData("IOPMrootDomain", kUserWkCntChID, true, 6795 ^(uint64_t state_id, CFStringRef drv_name){ printf("User Wake Count:%lld\n", state_id); } ); 6796 6797} 6798 6799 6800#define kIOPMSystemCapabilitiesKey "System Capabilities" 6801#define kPwrMgtKey "IOPowerManagement" 6802static void show_sysstate(char **argv) 6803{ 6804 CFMutableDictionaryRef rdProps = NULL; 6805 CFDictionaryRef states = NULL; 6806 io_registry_entry_t rootDomain = copyRootDomainRef(); 6807 CFNumberRef caps_cf = NULL, currSt_cf = NULL, desiredSt_cf = NULL; 6808 uint32_t caps; 6809 unsigned long currSt, desiredSt; 6810 6811 IORegistryEntryCreateCFProperties(rootDomain, &rdProps, 0, 0); 6812 6813 if (!rdProps) { 6814 printf("Internal error: Failed to get IOPMrootDomain properties\n"); 6815 goto exit; 6816 } 6817 6818 caps_cf = CFDictionaryGetValue(rdProps, CFSTR(kIOPMSystemCapabilitiesKey)); 6819 if (caps_cf) { 6820 CFNumberGetValue(caps_cf, kCFNumberIntType, &caps); 6821 printf("Current System Capabilities are: "); 6822 if (caps) { 6823 if (caps & kIOPMSystemCapabilityCPU) printf("CPU "); 6824 if (caps & kIOPMSystemCapabilityGraphics) printf("Graphics "); 6825 if (caps & kIOPMSystemCapabilityAudio) printf("Audio "); 6826 if (caps & kIOPMSystemCapabilityNetwork) printf("Network "); 6827 } 6828 else { 6829 printf("None"); 6830 } 6831 printf("\n"); 6832 } 6833 6834 states = CFDictionaryGetValue(rdProps, CFSTR(kPwrMgtKey)); 6835 if (!states) goto exit; 6836 6837 currSt_cf = CFDictionaryGetValue(states, CFSTR("CurrentPowerState")); 6838 if (currSt_cf) { 6839 CFNumberGetValue(currSt_cf, kCFNumberLongType, &currSt); 6840 printf("Current Power State: %lu\n", currSt); 6841 } 6842 desiredSt_cf = CFDictionaryGetValue(states, CFSTR("DesiredPowerState")); 6843 if (desiredSt_cf) { 6844 CFNumberGetValue(desiredSt_cf, kCFNumberLongType, &desiredSt); 6845 if (desiredSt != currSt) { 6846 printf("Desired State: %lu\n", desiredSt); 6847 if (desiredSt == 1) 6848 printf("System restart is in progress\n"); 6849 else if(desiredSt == 2) 6850 printf("System State is changing to Sleep\n"); 6851 else if (desiredSt == 3) 6852 printf("System is waking from sleep\n"); 6853 } 6854 } 6855 6856exit: 6857 if (rootDomain) IOObjectRelease(rootDomain); 6858 if (rdProps) CFRelease(rdProps); 6859 6860} 6861 6862static void show_everything(char **argv) 6863{ 6864 printf("pmset is invoking all non-blocking -g arguments"); 6865 int i=0; 6866 for (i=0; i<the_getters_count; i++) { 6867 if (the_getters[i].actionType == kActionGetOnceNoArgs) { 6868 printf("\nINVOKE: pmset -g %s\n", the_getters[i].arg); 6869 the_getters[i].action(argv); 6870 } 6871 } 6872} 6873 6874