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