OSDictionary *FakeSMCPlugin::getConfigurationNode(OSDictionary *root, const char *name) { OSDictionary *configuration = NULL; if (root && name) { OSString *nameNode = OSString::withCStringNoCopy(name); configuration = getConfigurationNode(root, nameNode); OSSafeReleaseNULL(nameNode); } return configuration; }
OSDictionary *FakeSMCPlugin::getConfigurationNode(OSDictionary *root, OSString *name) { OSDictionary *configuration = NULL; if (root && name) { HWSensorsDebugLog("looking up for configuration node: %s", name->getCStringNoCopy()); if (!(configuration = OSDynamicCast(OSDictionary, root->getObject(name)))) if (OSString *link = OSDynamicCast(OSString, root->getObject(name))) configuration = getConfigurationNode(root, link); } return configuration; }
bool ACPIProbe::start(IOService * provider) { ACPISensorsDebugLog("starting..."); if (!super::start(provider)) return false; if (!(acpiDevice = OSDynamicCast(IOACPIPlatformDevice, provider))) { ACPISensorsFatalLog("ACPI device not ready"); return false; } methods = OSArray::withCapacity(0); OSNumber *interval = NULL; OSNumber *timeout = NULL; OSBoolean *logging = NULL; OSArray *list = NULL; // Try to load configuration from info.plist first if (OSDictionary *configuration = getConfigurationNode()) { OSBoolean* disable = OSDynamicCast(OSBoolean, configuration->getObject("DisableDevice")); if (disable && disable->isTrue()) return false; interval = OSDynamicCast(OSNumber, configuration->getObject("PollingInterval")); timeout = OSDynamicCast(OSNumber, configuration->getObject("PollingTimeout")); logging = OSDynamicCast(OSBoolean, configuration->getObject("LoggingEnabled")); list = OSDynamicCast(OSArray, configuration->getObject("Methods")); } // Try to load configuration provided by ACPI device else { OSObject *object = NULL; if (kIOReturnSuccess == acpiDevice->evaluateObject("INVL", &object) && object) interval = OSDynamicCast(OSNumber, object); if (kIOReturnSuccess == acpiDevice->evaluateObject("TOUT", &object) && object) timeout = OSDynamicCast(OSNumber, object); if (kIOReturnSuccess == acpiDevice->evaluateObject("LOGG", &object) && object) { if (OSNumber *number = OSDynamicCast(OSNumber, object)) { logging = OSBoolean::withBoolean(number->unsigned8BitValue() == 1); } } if (kIOReturnSuccess == acpiDevice->evaluateObject("LIST", &object) && object) list = OSDynamicCast(OSArray, object); else ACPISensorsErrorLog("polling methods table (LIST) not found"); } if (interval) { pollingInterval = (double)interval->unsigned64BitValue() / (double)1000.0; ACPISensorsInfoLog("polling interval %lld ms", interval->unsigned64BitValue()); if (pollingInterval) { if (timeout) { pollingTimeout = (double)timeout->unsigned64BitValue() / 1000.0; ACPISensorsInfoLog("polling timeout %lld ms", timeout->unsigned64BitValue()); } if (logging) { loggingEnabled = logging->isTrue(); ACPISensorsInfoLog("logging %s", loggingEnabled ? "enabled" : "disabled"); } if (list) { for (unsigned int i = 0; i < list->getCount(); i++) { if (OSString *method = OSDynamicCast(OSString, list->getObject(i))) { if (method->getLength() && kIOReturnSuccess == acpiDevice->validateObject(method->getCStringNoCopy())) { methods->setObject(method); ACPISensorsInfoLog("method \"%s\" registered", method->getCStringNoCopy()); } else ACPISensorsErrorLog("unable to register method \"%s\"", method->getCStringNoCopy()); } } } } else ACPISensorsWarningLog("polling interval is set to zero, driver will be disabled"); } //REVIEW_REHABMAN: just bail if no methods to call... no need to stick around... if (!methods->getCount()) return false; if (methods->getCount()) { // woorkloop if (!(workloop = getWorkLoop())) { HWSensorsFatalLog("Failed to obtain workloop"); return false; } if (!(timerEventSource = IOTimerEventSource::timerEventSource( this, OSMemberFunctionCast(IOTimerEventSource::Action, this, &ACPIProbe::woorkloopTimerEvent)))) { ACPISensorsFatalLog("failed to initialize timer event source"); return false; } if (kIOReturnSuccess != workloop->addEventSource(timerEventSource)) { ACPISensorsFatalLog("failed to add timer event source into workloop"); return false; } timerEventSource->setTimeoutMS(100); //ACPISensorsInfoLog("%d method%s registered", methods->getCount(), methods->getCount() > 1 ? "s" : ""); } registerService(); ACPISensorsInfoLog("started"); return true; }
bool ACPISensors::start(IOService * provider) { ACPISensorsDebugLog("starting..."); if (!super::start(provider)) return false; if (!(acpiDevice = OSDynamicCast(IOACPIPlatformDevice, provider))) { ACPISensorsFatalLog("ACPI device not ready"); return false; } methods = OSArray::withCapacity(0); // Try to load configuration provided by ACPI device OSObject *object = NULL; // Use Kelvins? if (kIOReturnSuccess == acpiDevice->evaluateObject("KLVN", &object) && object) { if (OSNumber *kelvins = OSDynamicCast(OSNumber, object)) { useKelvins = kelvins->unsigned8BitValue() == 1; } OSSafeReleaseNULL(object); } // Allow the device to be completely disabled depending on Platform OSDictionary *configuration = getConfigurationNode(); if (configuration) { OSBoolean* disable = OSDynamicCast(OSBoolean, configuration->getObject("DisableDevice")); if (disable && disable->isTrue()) { return false; } } // Parse temperature table if (kIOReturnSuccess == acpiDevice->evaluateObject("TEMP", &object) && object) { addSensorsFromArray(OSDynamicCast(OSArray, object), kFakeSMCCategoryTemperature); OSSafeReleaseNULL(object); } else ACPISensorsDebugLog("temprerature description table (TEMP) not found"); // Parse voltage table if (kIOReturnSuccess == acpiDevice->evaluateObject("VOLT", &object) && object) { addSensorsFromArray(OSDynamicCast(OSArray, object), kFakeSMCCategoryVoltage); OSSafeReleaseNULL(object); } else ACPISensorsDebugLog("voltage description table (VOLT) not found"); // Parse amperage table if (kIOReturnSuccess == acpiDevice->evaluateObject("AMPR", &object) && object) { addSensorsFromArray(OSDynamicCast(OSArray, object), kFakeSMCCategoryCurrent); OSSafeReleaseNULL(object); } else ACPISensorsDebugLog("amperage description table (AMPR) not found"); // Parse power table if (kIOReturnSuccess == acpiDevice->evaluateObject("POWR", &object) && object) { addSensorsFromArray(OSDynamicCast(OSArray, object), kFakeSMCCategoryPower); OSSafeReleaseNULL(object); } else ACPISensorsDebugLog("power description table (POWR) not found"); // Parse tachometer table if (kIOReturnSuccess == acpiDevice->evaluateObject("TACH", &object) && object) { addSensorsFromArray(OSDynamicCast(OSArray, object), kFakeSMCCategoryFan); OSSafeReleaseNULL(object); } else ACPISensorsDebugLog("tachometer description table (TACH) not found"); // If nothing was found on ACPI device try to load configuration from info.plist if (object == NULL && configuration) { if (OSDictionary *temperatures = OSDynamicCast(OSDictionary, configuration->getObject("Temperatures"))) { if (OSBoolean *kelvins = OSDynamicCast(OSBoolean, temperatures->getObject("UseKelvins"))) { useKelvins = kelvins->isTrue(); } addSensorsFromDictionary(OSDynamicCast(OSDictionary, temperatures), kFakeSMCCategoryTemperature); } addSensorsFromDictionary(OSDynamicCast(OSDictionary, configuration->getObject("Voltages")), kFakeSMCCategoryVoltage); addSensorsFromDictionary(OSDynamicCast(OSDictionary, configuration->getObject("Currents")), kFakeSMCCategoryCurrent); addSensorsFromDictionary(OSDynamicCast(OSDictionary, configuration->getObject("Powers")), kFakeSMCCategoryPower); addSensorsFromDictionary(OSDynamicCast(OSDictionary, configuration->getObject("Tachometers")), kFakeSMCCategoryFan); } if (methods->getCount()) ACPISensorsInfoLog("%d sensor%s added", methods->getCount(), methods->getCount() > 1 ? "s" : ""); registerService(); ACPISensorsInfoLog("started"); return true; }
bool SuperIOPlugin::start(IOService *provider) { if (!super::start(provider)) return false; OSNumber *number = OSDynamicCast(OSNumber, provider->getProperty(kSuperIOHWMAddress)); if (!number || !(address = number->unsigned16BitValue())) { HWSensorsFatalLog("wrong address provided"); return false; } number = OSDynamicCast(OSNumber, provider->getProperty(kSuperIOControlPort)); if (!number || !(port = number->unsigned8BitValue())) { HWSensorsFatalLog("wrong port provided"); return false; } number = OSDynamicCast(OSNumber, provider->getProperty(kSuperIOModelValue)); if (!number || !(model = number->unsigned16BitValue())) { HWSensorsFatalLog("wrong model provided"); return false; } OSString *string = OSDynamicCast(OSString, provider->getProperty(kSuperIOModelName)); if (!string || !(modelName = string->getCStringNoCopy())) { HWSensorsFatalLog("wrong model name provided"); return false; } string = OSDynamicCast(OSString, provider->getProperty(kSuperIOVendorName)); if (!string || !(vendorName = string->getCStringNoCopy())) { HWSensorsFatalLog("wrong vendor name provided"); return false; } if (!initialize()) return false; OSString *modelString = OSString::withCString(modelName); if (OSDictionary *configuration = getConfigurationNode(modelString)) { addTemperatureSensors(configuration); addVoltageSensors(configuration); addTachometerSensors(configuration); } else HWSensorsWarningLog("no platform profile provided"); OSSafeReleaseNULL(modelString); registerService(); HWSensorsInfoLog("started"); return true; }
bool LPCSensors::start(IOService *provider) { if (!super::start(provider)) return false; OSNumber *number = OSDynamicCast(OSNumber, provider->getProperty(kSuperIOHWMAddress)); if (!number || !(address = number->unsigned16BitValue())) { HWSensorsFatalLog("wrong address provided"); return false; } number = OSDynamicCast(OSNumber, provider->getProperty(kSuperIOControlPort)); if (!number || !(port = number->unsigned8BitValue())) { HWSensorsFatalLog("wrong port provided"); return false; } number = OSDynamicCast(OSNumber, provider->getProperty(kSuperIOModelValue)); if (!number || !(model = number->unsigned16BitValue())) { HWSensorsFatalLog("wrong model provided"); return false; } OSString *string = OSDynamicCast(OSString, provider->getProperty(kSuperIOModelName)); if (!string || !(modelName = string->getCStringNoCopy())) { HWSensorsFatalLog("wrong model name provided"); return false; } string = OSDynamicCast(OSString, provider->getProperty(kSuperIOVendorName)); if (!string || !(vendorName = string->getCStringNoCopy())) { HWSensorsFatalLog("wrong vendor name provided"); return false; } if (!initialize()) return false; OSString *modelString = OSString::withCString(modelName); if (OSDictionary *configuration = getConfigurationNode(modelString)) { addTemperatureSensors(configuration); addVoltageSensors(configuration); addTachometerSensors(configuration); } else HWSensorsWarningLog("no platform profile provided"); OSSafeReleaseNULL(modelString); // woorkloop if (!(workloop = getWorkLoop())) { HWSensorsFatalLog("Failed to obtain workloop"); return false; } if (!(timerEventSource = IOTimerEventSource::timerEventSource(this, OSMemberFunctionCast(IOTimerEventSource::Action, this, &LPCSensors::woorkloopTimerEvent)))) { HWSensorsFatalLog("failed to initialize timer event source"); return false; } if (kIOReturnSuccess != workloop->addEventSource(timerEventSource)) { HWSensorsFatalLog("failed to add timer event source into workloop"); return false; } // two power states - off and on static const IOPMPowerState powerStates[2] = { { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 1, IOPMDeviceUsable, IOPMPowerOn, IOPMPowerOn, 0, 0, 0, 0, 0, 0, 0, 0 } }; // register interest in power state changes PMinit(); provider->joinPMtree(this); registerPowerDriver(this, (IOPMPowerState *)powerStates, 2); registerService(); HWSensorsInfoLog("started"); return true; }
bool ACPISensors::start(IOService * provider) { if (!super::start(provider)) return false; acpiDevice = (IOACPIPlatformDevice *)provider; if (!acpiDevice) { HWSensorsFatalLog("ACPI device not ready"); return false; } if (OSDictionary *configuration = getConfigurationNode()) { // Temperatures if (OSDictionary *temps = OSDynamicCast(OSDictionary, configuration->getObject("Temperatures"))) { temperatures = OSDictionary::withCapacity(0); OSCollectionIterator *iterator = OSCollectionIterator::withCollection(temps); UInt16 count = 0; while (OSString *key = OSDynamicCast(OSString, iterator->getNextObject())) { OSString *method = OSDynamicCast(OSString, temps->getObject(key)); if (method && kIOReturnSuccess == acpiDevice->validateObject(method->getCStringNoCopy())) { for (int i = 0; i < FakeSMCTemperatureCount; i++) { if (addSensorToList(temperatures, key, method, FakeSMCTemperature[i].name, FakeSMCTemperature[i].key, FakeSMCTemperature[i].type, FakeSMCTemperature[i].size, kFakeSMCTemperatureSensor, count)) { count++; break; } else HWSensorsErrorLog("Failed to register temperature sensor \"%s\" for method \"%s\"", key->getCStringNoCopy(), method->getCStringNoCopy()); } } }; if (count) HWSensorsInfoLog("%d temperature sensor%s added", count, count > 1 ? "s" : ""); } else return false; // Voltages if (OSDictionary *volts = OSDynamicCast(OSDictionary, configuration->getObject("Voltages"))) { voltages = OSDictionary::withCapacity(0); OSCollectionIterator *iterator = OSCollectionIterator::withCollection(volts); UInt16 count = 0; while (OSString *key = OSDynamicCast(OSString, iterator->getNextObject())) { OSString *method = OSDynamicCast(OSString, volts->getObject(key)); if (method && kIOReturnSuccess == acpiDevice->validateObject(method->getCStringNoCopy())) { for (int i = 0; i < FakeSMCVolatgeCount; i++) { if (addSensorToList(voltages, key, method, FakeSMCVolatge[i].name, FakeSMCVolatge[i].key, FakeSMCVolatge[i].type, FakeSMCVolatge[i].size, kFakeSMCVoltageSensor, count)) { count++; break; } else HWSensorsErrorLog("Failed to register voltage sensor \"%s\" for method \"%s\"", key->getCStringNoCopy(), method->getCStringNoCopy()); } } }; if (count) HWSensorsInfoLog("%d voltage sensor%s added", count, count > 1 ? "s" : ""); } else return false; // Tachometers if (OSDictionary *fans = OSDynamicCast(OSDictionary, configuration->getObject("Tachometers"))) { tachometers = OSDictionary::withCapacity(0); OSCollectionIterator *iterator = OSCollectionIterator::withCollection(fans); UInt16 count = 0; OSDictionary* fanNames = OSDynamicCast(OSDictionary, configuration->getObject("Fan Names")); while (OSString *key = OSDynamicCast(OSString, iterator->getNextObject())) { OSString *method = OSDynamicCast(OSString, fans->getObject(key)); if (method && kIOReturnSuccess == acpiDevice->validateObject(method->getCStringNoCopy())) { OSString* name = NULL; if (fanNames) name = OSDynamicCast(OSString, fanNames->getObject(key)); if (FakeSMCSensor *sensor = addTachometer(count, name ? name->getCStringNoCopy() : 0)) { tachometers->setObject(sensor->getKey(), method); count++; } else HWSensorsErrorLog("Failed to register tachometer sensor for method \"%s\"", method->getCStringNoCopy()); } }; if (count) HWSensorsInfoLog("%d tachometer sensor%s added", count, count > 1 ? "s" : ""); } else return false; } else HWSensorsErrorLog("no valid configuration provided"); registerService(); HWSensorsInfoLog("started"); return true; }
bool PTIDSensors::start(IOService * provider) { if (!super::start(provider)) return false; acpiDevice = (IOACPIPlatformDevice *)provider; if (!acpiDevice) { HWSensorsFatalLog("ACPI device not ready"); return false; } if (OSDictionary *configuration = getConfigurationNode()) { OSBoolean* disable = OSDynamicCast(OSBoolean, configuration->getObject("DisableDevice")); if (disable && disable->isTrue()) return false; } // On some computers (eg. RehabMan's ProBook 4530s), the system will hang on startup // if kernel cache is used, because of the early call to updateTemperatures and/or // updateTachometers. At least that is the case with an SSD and a valid pre-linked // kernel, along with kernel cache enabled. This 1000ms sleep seems to fix the problem, // enabling a clean boot with PTIDSensors enabled. IOSleep(1000); // Update timers temperaturesLastUpdated = ptimer_read() - NSEC_PER_SEC; tachometersLastUpdated = temperaturesLastUpdated; acpiDevice->evaluateInteger("IVER", &version); if (version == 0) { OSString *name = OSDynamicCast(OSString, provider->getProperty("name")); if (name && name->isEqualTo("INT3F0D")) version = 0x30000; else return false; } setProperty("version", version, 64); // Parse sensors switch (version) { case 0x30000: { OSObject *object = NULL; // Temperatures if(kIOReturnSuccess == acpiDevice->evaluateObject("TSDL", &object) && object) { if (OSArray *description = OSDynamicCast(OSArray, object)) { HWSensorsDebugLog("Parsing temperatures..."); for (UInt32 index = 1; index < description->getCount(); index += 2) { parseTemperatureName(OSDynamicCast(OSString, description->getObject(index)), (index - 1) / 2); } } else HWSensorsErrorLog("failed to parse TSDL table"); } else HWSensorsErrorLog("failed to evaluate TSDL table"); // Tachometers if(kIOReturnSuccess == acpiDevice->evaluateObject("OSDL", &object) && object) { if (OSArray *description = OSDynamicCast(OSArray, object)) { HWSensorsDebugLog("Parsing tachometers..."); for (UInt32 index = 2; index < description->getCount(); index += 3) { parseTachometerName(OSDynamicCast(OSString, description->getObject(index)), OSDynamicCast(OSString, description->getObject(index - 1)), (index - 2) / 3); } } else HWSensorsErrorLog("failed to parse OSDL table"); } else HWSensorsErrorLog("failed to evaluate OSDL table"); break; } case 0x20001: { OSObject *object = NULL; // Temperatures if(kIOReturnSuccess == acpiDevice->evaluateObject("TMPV", &object) && object) { if (OSArray *description = OSDynamicCast(OSArray, object)) { for (UInt32 index = 1; index < description->getCount(); index += 3) { parseTemperatureName(OSDynamicCast(OSString, description->getObject(index)), index + 1); } } else HWSensorsErrorLog("failed to parse TMPV table"); } else HWSensorsErrorLog("failed to evaluate TMPV table"); // Tachometers if(kIOReturnSuccess == acpiDevice->evaluateObject("OSDV", &object) && object) { if (OSArray *description = OSDynamicCast(OSArray, object)) { for (UInt32 index = 2; index < description->getCount(); index += 4) { parseTachometerName(OSDynamicCast(OSString, description->getObject(index)), OSDynamicCast(OSString, description->getObject(index - 1)), index + 1); } } else HWSensorsErrorLog("failed to parse OSDV table"); } else HWSensorsErrorLog("failed to evaluate OSDV table"); break; } default: HWSensorsFatalLog("usupported interface version: 0x%x", (unsigned int)version); break; } registerService(); HWSensorsInfoLog("started"); return true; }
bool ACPIProbe::start(IOService * provider) { ACPISensorsDebugLog("starting..."); if (!super::start(provider)) return false; if (!(acpiDevice = OSDynamicCast(IOACPIPlatformDevice, provider))) { ACPISensorsFatalLog("ACPI device not ready"); return false; } profiles = OSDictionary::withCapacity(0); profileList = OSArray::withCapacity(0); OSObject *object = NULL; // Try to load configuration provided by ACPI device if (kIOReturnSuccess == acpiDevice->evaluateObject("LIST", &object) && object) { if (OSArray *list = OSDynamicCast(OSArray, object)) { for (unsigned int i = 0; i < list->getCount(); i++) { if (OSString *method = OSDynamicCast(OSString, list->getObject(i))) { if (kIOReturnSuccess == acpiDevice->evaluateObject(method->getCStringNoCopy(), &object) && object) { if (OSArray *config = OSDynamicCast(OSArray, object)) { if (config->getCount() > 4) { OSString *pName = OSDynamicCast(OSString, config->getObject(0)); OSNumber *pInterval = OSDynamicCast(OSNumber, config->getObject(1)); OSNumber *pTimeout = OSDynamicCast(OSNumber, config->getObject(2)); OSNumber *pVerbose = OSDynamicCast(OSNumber, config->getObject(3)); OSArray *pMethods = OSArray::withCapacity(config->getCount() - 4); for (unsigned int offset = 4; offset < config->getCount(); offset++) { if (OSString *methodName = OSDynamicCast(OSString, config->getObject(offset))) { pMethods->setObject(methodName); } } addProfile(pName, pMethods, pInterval, pTimeout, pVerbose); } } OSSafeRelease(object); } } } OSSafeRelease(list); } } else { ACPISensorsErrorLog("profile definition table (LIST) not found"); } // Try to load configuration from info.plist if (profiles->getCount() == 0) { if (OSDictionary *configuration = getConfigurationNode()) { OSString *pName = OSDynamicCast(OSString, configuration->getObject("ProfileName")); OSNumber *pInterval = OSDynamicCast(OSNumber, configuration->getObject("PollingInterval")); OSNumber *pTimeout = OSDynamicCast(OSNumber, configuration->getObject("PollingTimeout")); OSBoolean *pVerboseBool = OSDynamicCast(OSBoolean, configuration->getObject("VerboseLog")); OSNumber *pVerbose = OSNumber::withNumber(pVerboseBool->getValue() ? 1 : 0, 8); OSArray *pMethods = OSDynamicCast(OSArray, configuration->getObject("MethodsToPoll")); addProfile(pName, pMethods, pInterval, pTimeout, pVerbose); } } if (this->profiles->getCount()) { // Parse active profile if (kIOReturnSuccess == acpiDevice->evaluateObject("ACTV", &object) && object) { if (OSString *method = OSDynamicCast(OSString, object)) { if (kIOReturnSuccess == acpiDevice->evaluateObject(method->getCStringNoCopy(), &object) && object) { if (OSArray *config = OSDynamicCast(OSArray, object)) { if (config->getCount() > 4) { if (OSString *profile = OSDynamicCast(OSString, config->getObject(0))) { if (!(activeProfile = (ACPIProbeProfile *)profiles->getObject(profile))) { activeProfile = (ACPIProbeProfile *)profileList->getObject(0); } } } } OSSafeRelease(object); } OSSafeRelease(method); } } // woorkloop if (!(workloop = getWorkLoop())) { HWSensorsFatalLog("Failed to obtain workloop"); return false; } if (!(timerEventSource = IOTimerEventSource::timerEventSource( this, OSMemberFunctionCast(IOTimerEventSource::Action, this, &ACPIProbe::woorkloopTimerEvent)))) { ACPISensorsFatalLog("failed to initialize timer event source"); return false; } if (kIOReturnSuccess != workloop->addEventSource(timerEventSource)) { ACPISensorsFatalLog("failed to add timer event source into workloop"); return false; } timerEventSource->setTimeoutMS(100); //ACPISensorsInfoLog("%d method%s registered", methods->getCount(), methods->getCount() > 1 ? "s" : ""); } // two power states - off and on static const IOPMPowerState powerStates[2] = { { 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, { 1, IOPMDeviceUsable, IOPMPowerOn, IOPMPowerOn, 0, 0, 0, 0, 0, 0, 0, 0 } }; // register interest in power state changes PMinit(); provider->joinPMtree(this); registerPowerDriver(this, (IOPMPowerState *)powerStates, 2); registerService(); ACPISensorsInfoLog("started"); return true; }