Esempio n. 1
0
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;
}
Esempio n. 2
0
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;
}
Esempio n. 3
0
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;	
}
Esempio n. 5
0
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;
}
Esempio n. 6
0
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;
}
Esempio n. 7
0
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;	
}
Esempio n. 8
0
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;
}
Esempio n. 9
0
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;
}