/* * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved. * * @APPLE_LICENSE_HEADER_START@ * * The contents of this file constitute Original Code as defined in and * are subject to the Apple Public Source License Version 1.1 (the * "License"). You may not use this file except in compliance with the * License. Please obtain a copy of the License at * http://www.apple.com/publicsource and read it before using this file. * * This Original Code and all software distributed under the License are * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the * License for the specific language governing rights and limitations * under the License. * * @APPLE_LICENSE_HEADER_END@ */ /* * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved. * */ // $Log: AppleHWControl.cpp,v $ // Revision 1.5 2004/06/03 21:32:07 eem // [3671325] Remember control's "safe-value" property // // Revision 1.4 2004/04/21 21:13:39 dirty // If max-value or min-value properties exist in the device tree node, then add // them to the IOHWControl registration dictionary. // // Revision 1.3 2004/02/12 01:17:01 eem // Merge Rohan changes from tag MERGED-FROM-rohan-branch-TO-TOT-1 // // Revision 1.2 2004/01/30 23:52:00 eem // [3542678] IOHWSensor/IOHWControl should use "reg" with version 2 thermal parameters // Remove AppleSMUSensor/AppleSMUFan since that code will be in AppleSMUDevice class. // Fix IOHWMonitor, AppleMaxim6690, AppleAD741x to use setPowerState() API instead of // unsynchronized powerStateWIllChangeTo() API. // // Revision 1.1.4.1 2004/02/10 09:58:00 eem // 3548562, 3554178 - prevent extra OSNumber allocations // // Revision 1.1 2003/10/23 20:08:18 wgulland // Adding IOHWControl and a base class for IOHWSensor and IOHWControl // // #include #include #include "AppleHWControl.h" static const OSSymbol *sControlID; static const OSSymbol *sCurrentValue; static const OSSymbol *sGetCurrentValue; static const OSSymbol *sTargetValue; static const OSSymbol *sGetTargetValue; static const OSSymbol *sSetTargetValue; static const OSSymbol *sForceUpdate; static const OSSymbol *sMinValue; static const OSSymbol *sMaxValue; static const OSSymbol *sSafeValue; OSDefineMetaClassAndStructors(IOHWControl,IOHWMonitor) bool IOHWControl::start(IOService *provider) { OSDictionary *dict; IOReturn ret; if ( !(IOHWMonitor::start(provider)) ) return false; DLOG("IOHWControl::start(%s) - entered\n", fDebugID); // initialize symbols if(!sControlID) sControlID = OSSymbol::withCString("control-id"); if(!sCurrentValue) sCurrentValue = OSSymbol::withCString("current-value"); if(!sGetCurrentValue) sGetCurrentValue = OSSymbol::withCString("getCurrentValue"); if(!sTargetValue) sTargetValue = OSSymbol::withCString("target-value"); if(!sGetTargetValue) sGetTargetValue = OSSymbol::withCString("getTargetValue"); if(!sSetTargetValue) sSetTargetValue = OSSymbol::withCString("setTargetValue"); if(!sForceUpdate) sForceUpdate = OSSymbol::withCString("force-update"); if(!sMinValue) sMinValue = OSSymbol::withCString("min-value"); if(!sMaxValue) sMaxValue = OSSymbol::withCString("max-value"); if(!sSafeValue) sSafeValue = OSSymbol::withCString("safe-value"); // Copy over the properties from our provider DLOG("IOHWControl::start(%s) - parsing Control nub properties\n", fDebugID); bool parseSuccess = FALSE; OSNumber *num; OSData *data; do { // Control id - required data = OSDynamicCast(OSData, provider->getProperty(sControlID)); if (!data) { IOLog("IOHWControl - no Control ID !!\n"); break; } fID = *(UInt32 *)data->getBytesNoCopy(); num = OSNumber::withNumber(fID, 32); if (!num) { IOLog("IOHWControl - can't set Control ID !!\n"); break; } setProperty(sControlID, num); num->release(); // If min-value/max-value/safe-value exist, add them as properties. if ( ( data = OSDynamicCast(OSData, provider->getProperty( sMinValue ) ) ) != NULL ) { UInt32 minValue; minValue = *( UInt32 * ) data->getBytesNoCopy(); if ( ( num = OSNumber::withNumber( minValue, 32 ) ) == NULL ) break; setProperty( sMinValue, num ); num->release(); } if ( ( data = OSDynamicCast(OSData, provider->getProperty( sMaxValue ) ) ) != NULL ) { UInt32 maxValue; maxValue = *( UInt32 * ) data->getBytesNoCopy(); if ( ( num = OSNumber::withNumber( maxValue, 32 ) ) == NULL ) break; setProperty( sMaxValue, num ); num->release(); } if ( ( data = OSDynamicCast(OSData, provider->getProperty( sSafeValue ) ) ) != NULL ) { UInt32 safeValue; safeValue = *( UInt32 * ) data->getBytesNoCopy(); if ( ( num = OSNumber::withNumber( safeValue, 32 ) ) == NULL ) break; setProperty( sSafeValue, num ); num->release(); } // set the channel id // If we've got version 1 encoding, channel id is sensor id // if we've got version 2 encoding, channel id is reg property num = (OSNumber *)getProperty("version"); if (num->unsigned32BitValue() == 1) { fChannel = fID; } else if (num->unsigned32BitValue() == 2) { data = OSDynamicCast(OSData, provider->getProperty("reg")); if (!data) break; fChannel = *(UInt32 *)data->getBytesNoCopy(); } else { IOLog("IOHWControl - version 2 but no reg property !!\n"); break; } // all required properties found parseSuccess = TRUE; } while (0); if (parseSuccess == FALSE) { return(false); } DLOG("IOHWControl::start(%s) - polling initial current value\n", fDebugID); ret = updateCurrentValue(); if(ret != kIOReturnSuccess) { IOLog("AppleHWControl::start failed to read initial current value: 0x%x!\n", ret); return(false); } ret = updateTargetValue(); if(ret != kIOReturnSuccess) { IOLog("AppleHWControl::start failed to read initial target value!\n"); return(false); } DLOG("IOHWControl::start(%s) - messaging pmon\n", fDebugID); // create the registration message dictionary dict = OSDictionary::withDictionary(getPropertyTable()); if(fIOPMon) messageClient(kRegisterControl, fIOPMon, dict); dict->release(); // make us findable by applications registerService(); DLOG("IOHWControl::start(%s) - done\n", fDebugID); return true; } // Override to allow setting of some properties // A dictionary is expected, containing the new properties IOReturn IOHWControl::setProperties( OSObject * properties ) { OSDictionary * dict = OSDynamicCast(OSDictionary, properties); OSNumber *num; if(!dict) return kIOReturnBadArgument; if (sleeping) return(kIOReturnOffline); if(dict->getObject(sCurrentValue) || dict->getObject(sForceUpdate)) updateCurrentValue(); num = OSDynamicCast(OSNumber, dict->getObject(sTargetValue)); if(num) setTargetValue(num); return kIOReturnSuccess; } IOReturn IOHWControl::updateCurrentValue() { return updateValue(sGetCurrentValue, sCurrentValue); } IOReturn IOHWControl::updateTargetValue() { return updateValue(sGetTargetValue, sTargetValue); } IOReturn IOHWControl::setTargetValue(OSNumber *val) { IOReturn ret; /* * If the system is going to sleep or waking from sleep, do nothing - leave the value unchanged * * This prevents untimely I/O during sleep/wake */ if (sleeping || systemIsRestarting) return kIOReturnOffline; busy = true; ret = callPlatformFunction(sSetTargetValue, FALSE, (void *)fChannel, (void *)val->unsigned32BitValue(), NULL, NULL); busy = false; /* * If PM called us while we were reading the sensor, then sleeping may now be true * in which case we have to ack the PM so it knows we can sleep. */ if (sleeping && powerPolicyMaker) powerPolicyMaker->acknowledgePowerChange (this); if(ret == kIOReturnSuccess) setNumber(sTargetValue, val->unsigned32BitValue()); return ret; }