Changeset 355 for trunk/Cocoa/Pester/Source/PSPowerManager.m
- Timestamp:
- 11/23/07 04:58:05 (17 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Cocoa/Pester/Source/PSPowerManager.m
r119 r355 11 11 #import <IOKit/pwr_mgt/IOPMLib.h> 12 12 #import <IOKit/IOMessage.h> 13 #import <CoreFoundation/CoreFoundation.h>14 15 /*16 * Copyright (c) 2002 Apple Computer, Inc. All rights reserved.17 *18 * @APPLE_LICENSE_HEADER_START@19 *20 * The contents of this file constitute Original Code as defined in and21 * are subject to the Apple Public Source License Version 1.1 (the22 * "License"). You may not use this file except in compliance with the23 * License. Please obtain a copy of the License at24 * http://www.apple.com/publicsource and read it before using this file.25 *26 * This Original Code and all software distributed under the License are27 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER28 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,29 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,30 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the31 * License for the specific language governing rights and limitations32 * under the License.33 *34 * @APPLE_LICENSE_HEADER_END@35 */36 37 /* Sample code to set an automatic wakeup timer to wake machines from sleep.38 39 When a machine is asleep, most hardware (including the processor) is40 powered off. The PMU chip is one of the few things left powered on, and it's41 able to generate a wakeup event on a timer.42 This code shows how to set the wakeup timer within the PMU.43 */44 45 // From autowake.cpp:46 47 // #define kAppleVIAUserClientMagicCookie 0x101face // or 0x101beef -- for PMU48 // #define kAppleVIAUserClientMagicCookie 0x101beef // or 0x101face -- for PMU49 50 // The difference is 101beef is only for superusers and 101face works for51 // non-privileged users. I have not determined which calls are only available52 // for superusers53 54 #define PMU_MAGIC_PASSWORD 0x0101FACE55 56 /* ==========================================57 * Close a device user client58 * =========================================== */59 static kern_return_t60 closeDevice(io_connect_t con)61 {62 kern_return_t ret = IOServiceClose(con);63 64 NSCAssert1(ret == kIOReturnSuccess, @"closeDevice: IOServiceClose returned an error of type %08lx", (unsigned long)ret);65 66 return ret;67 }68 69 /* ==========================================70 * Open an IORegistry device user client71 * =========================================== */72 static void73 openDevice(io_object_t obj, unsigned int type, io_connect_t * con)74 {75 kern_return_t ret = IOServiceOpen(obj, mach_task_self(), type, con);76 77 NSCAssert1(ret == kIOReturnSuccess, @"openDevice: IOServiceOpen returned an error of type %08lx", (unsigned long)ret);78 }79 80 /* ===========================================81 * Changes the string for a registry82 * property.83 * =========================================== */84 void85 writeDataProperty(io_object_t handle, CFStringRef name,86 unsigned char * bytes, unsigned int size)87 {88 kern_return_t kr = kIOReturnNoMemory;89 CFDataRef data;90 91 data = CFDataCreate(kCFAllocatorDefault, bytes, size);92 NSCAssert(data != NULL, @"writeDataProperty: CFDataCreate failed");93 [(NSData *)data autorelease];94 95 kr = IOConnectSetCFProperty(handle, name, data);96 NSCAssert1(kr == KERN_SUCCESS, @"writeDataProperty: IOConnectSetCFProperty returned an error of type %08lx", (unsigned long)kr);97 }98 99 /* ==========================================100 * Write a data property to the PMU driver101 * Arguments102 * pmuReference - the IORegistry device to write to103 * propertyName - Name of the property to write to104 * data - Data to write105 * dataSize - Data size106 * =========================================== */107 void108 writePMUProperty(io_object_t pmuReference, CFStringRef propertyName, void *data, size_t dataSize)109 {110 io_connect_t conObj;111 openDevice(pmuReference, PMU_MAGIC_PASSWORD, &conObj);112 writeDataProperty(conObj, propertyName, (unsigned char *)data, dataSize);113 closeDevice(conObj);114 }115 116 117 /* ==========================================118 * Look through the registry and search for an119 * IONetworkInterface objects with the given120 * name.121 * If a match is found, the object is returned.122 * =========================================== */123 124 io_service_t125 getInterfaceWithName(mach_port_t masterPort, char *className)126 {127 io_service_t obj;128 129 obj = IOServiceGetMatchingService(masterPort, IOServiceMatching(className));130 131 NSCAssert(obj != NULL, @"getInterfaceWithName: IOServiceGetMatchingService returned NULL");132 133 return obj;134 }135 136 /* ==========================================137 * Find the PMU in the IORegistry138 * =========================================== */139 io_service_t140 openPMUComPort(void)141 {142 static mach_port_t masterPort;143 kern_return_t kr;144 145 // Get a master port to talk with the mach_kernel146 kr = IOMasterPort(bootstrap_port, &masterPort);147 NSCAssert1(kr == KERN_SUCCESS, @"openPMUComPort: IOMasterPort returned an error of type %08lx", (unsigned long)kr);148 149 return getInterfaceWithName(masterPort, "ApplePMU");150 }151 152 153 /* ==========================================154 * Release our reference to the PMU in the IORegistry155 * =========================================== */156 void157 closePMUComPort(io_object_t pmuRef)158 {159 IOObjectRelease(pmuRef);160 }161 13 162 14 @implementation PSPowerManager … … 164 16 + (BOOL)autoWakeSupported; 165 17 { 166 io_service_t pmuReference = openPMUComPort(); 167 if (pmuReference == NULL) return NO; 168 closePMUComPort(pmuReference); 18 // XXX imagine it's supported on all machines that support 10.4 169 19 return YES; 170 20 } 171 21 172 + ( io_service_t)_pmuReference;22 + (void)setWakeTime:(NSDate *)time; 173 23 { 174 io_service_t pmuReference = openPMUComPort(); 175 NSAssert(pmuReference != NULL, NSLocalizedString(@"Couldn't find PMU in IORegistry. This computer may not support automatic wake from sleep.", "Assertion message: couldn't open ApplePMU")); 176 return pmuReference; 177 } 178 179 + (NSDate *)wakeTime; 180 { 181 io_service_t pmuReference = [self _pmuReference]; 182 NSNumber *autoWakeTime; 183 unsigned long long rawWakeTime; 184 185 autoWakeTime = (NSNumber *)IORegistryEntryCreateCFProperty(pmuReference, CFSTR("AutoWake"), NULL, 0); 186 closePMUComPort(pmuReference); 187 188 if (autoWakeTime == nil) return nil; 189 rawWakeTime = [autoWakeTime unsignedLongLongValue]; 190 if (rawWakeTime == 0) return nil; 191 // XXX no idea what the epoch is supposed to be, but this works... 192 return [NSDate dateWithTimeIntervalSinceReferenceDate: rawWakeTime - [[NSTimeZone systemTimeZone] secondsFromGMT] - 18446744072475736320LLU]; 193 } 194 195 + (void)setWakeInterval:(unsigned long)wakeInterval; 196 { 197 io_service_t pmuReference = [self _pmuReference]; 198 writePMUProperty(pmuReference, CFSTR("AutoWake"), (unsigned long *)&wakeInterval, sizeof(wakeInterval)); 199 closePMUComPort(pmuReference); 200 } 201 202 + (void)setWakeTime:(NSDate *)time overrideIfEarlier:(BOOL)override; 203 { 204 unsigned long wakeInterval; 205 206 if (time == nil) { 207 wakeInterval = 0; 208 override = YES; 209 } else { 210 wakeInterval = [time timeIntervalSinceNow]; 211 if (wakeInterval == 0) wakeInterval++; // 0 will disable 212 if (!override) { 213 NSDate *wakeTime = [self wakeTime]; 214 override = (wakeTime == nil || [wakeTime compare: time] == NSOrderedAscending); 215 } 216 } 217 218 if (override) { 219 [self setWakeInterval: wakeInterval]; 220 } 24 IOPMSchedulePowerEvent((CFDateRef)time, (CFStringRef)[[NSBundle mainBundle] bundleIdentifier], CFSTR(kIOPMAutoWake)); 221 25 } 222 26 223 27 + (void)clearWakeTime; 224 28 { 225 [self setWakeTime: nil overrideIfEarlier: YES];29 // XXX implement (IOPMCancelScheduledPowerEvent) 226 30 } 227 31 … … 266 70 delegate = [aDelegate retain]; 267 71 root_port = IORegisterForSystemPower(self, ¬ificationPort, powerCallback, ¬ifier); 268 NSAssert(root_port != NULL, @"IORegisterForSystemPower failed");72 NSAssert(root_port != 0, @"IORegisterForSystemPower failed"); 269 73 270 74 CFRunLoopAddSource(CFRunLoopGetCurrent(), IONotificationPortGetRunLoopSource(notificationPort), kCFRunLoopDefaultMode);
Note:
See TracChangeset
for help on using the changeset viewer.