IOReturn ACPIProbe::woorkloopTimerEvent(void)
{
    if (pollingTimeout > 0 && !startTime)
        startTime = ptimer_read_seconds();
    
    double time = ptimer_read_seconds();
    
    if (pollingTimeout == 0 || (time - startTime < pollingTimeout)) {
        
        OSDictionary *values = OSDictionary::withCapacity(0);
        
        for (unsigned int i = 0; i < methods->getCount(); i++) {
            if (OSString *method = (OSString*)methods->getObject(i)) {
                
                OSObject *object = NULL;
                IOReturn result = acpiDevice->evaluateObject(method->getCStringNoCopy(), &object);
                
                if (kIOReturnSuccess == result && object) {
                    values->setObject(method->getCStringNoCopy(), object);
                    
                    if (loggingEnabled)
                        logValue(method->getCStringNoCopy(), object);
                }
                else ACPISensorsErrorLog("failed to evaluate method \"%s\", return %d", method->getCStringNoCopy(), result);
            }
        }
        
        setProperty("Values", values);
        
        timerEventSource->setTimeoutMS((UInt32)(pollingInterval * 1000.0));
    }
    
    return kIOReturnSuccess;
}
示例#2
0
IOReturn ACPIProbe::woorkloopTimerEvent(void)
{
    double time = ptimer_read_seconds();

    if (activeProfile->timeout > 0 && activeProfile->startedAt == 0) {
        activeProfile->startedAt = time;
    }

    if (activeProfile && (activeProfile->timeout == 0 || (time - activeProfile->startedAt < activeProfile->timeout))) {
        
        OSDictionary *values = OSDictionary::withCapacity(0);
        
        for (unsigned int i = 0; i < activeProfile->methods->getCount(); i++) {

            if (OSString *method = (OSString*)activeProfile->methods->getObject(i)) {
                
                OSObject *object = NULL;

                IOReturn result = acpiDevice->evaluateObject(method->getCStringNoCopy(), &object);
                
                if (kIOReturnSuccess == result && object) {

                    values->setObject(method->getCStringNoCopy(), object);
                    
                    if (activeProfile->verbose)
                        logValue(method->getCStringNoCopy(), object);
                }
                else {
                    ACPISensorsErrorLog("failed to evaluate method \"%s\", return %d", method->getCStringNoCopy(), result);
                }
            }
        }
        
        setProperty("Values", values);
        
        timerEventSource->setTimeoutMS(activeProfile->interval);
    }
    
    return kIOReturnSuccess;
}
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;
}
void ACPISensors::addSensorsFromArray(OSArray *array, FakeSMCSensorCategory category)
{
    if (array) {
        
        UInt32 group = 0;
        const char *title = NULL;
        
        switch (category) {
            case kFakeSMCCategoryTemperature:
                group = kFakeSMCTemperatureSensor;
                title = "temperature";
                break;
                
            case kFakeSMCCategoryFrequency:
                group = kFakeSMCFrequencySensor;
                title = "frequency";
                break;
                
            case kFakeSMCCategoryVoltage:
                group = kFakeSMCVoltageSensor;
                title = "voltage";
                break;
                
            case kFakeSMCCategoryCurrent:
                group = kFakeSMCCurrentSensor;
                title = "amperage";
                break;
                
            case kFakeSMCCategoryPower:
                group = kFakeSMCPowerSensor;
                title = "power";
                break;
                
            case kFakeSMCCategoryFan:
                group = kFakeSMCTachometerSensor;
                title = "tachometer";
                break;
                
            default:
                return;
        }
        
        for (UInt32 index = 0; index + 1 < array->getCount(); index += 2) {
            if (OSString *key = OSDynamicCast(OSString, array->getObject(index))) {
                if (OSString *method = OSDynamicCast(OSString, array->getObject(index + 1))) {
                    FakeSMCSensor *sensor = NULL;
                    
                    if (category == kFakeSMCCategoryFan) {
                        sensor = addTachometer(methods->getCount(), key->getCStringNoCopy());
                    }
                    else {
                        sensor = addSensorFromNode(key, category, group, methods->getCount());
                    }
                    
                    if (sensor) {
                        methods->setObject(method);//sensor->getKey(), method);
                    }
                    else {
                        ACPISensorsErrorLog("Failed to register %s sensor \"%s\" for method \"%s\"", title, key->getCStringNoCopy(), method->getCStringNoCopy());
                    }
                }
            }
        }
    }
}
void ACPISensors::addSensorsFromDictionary(OSDictionary *dictionary, FakeSMCSensorCategory category)
{
    if (dictionary) {
        
        UInt32 group = 0;
        const char *title = NULL;
        
        switch (category) {
            case kFakeSMCCategoryTemperature:
                group = kFakeSMCTemperatureSensor;
                title = "temperature";
                break;
                
            case kFakeSMCCategoryFrequency:
                group = kFakeSMCFrequencySensor;
                title = "frequency";
                break;
                
            case kFakeSMCCategoryVoltage:
                group = kFakeSMCVoltageSensor;
                title = "voltage";
                break;
                
            case kFakeSMCCategoryCurrent:
                group = kFakeSMCCurrentSensor;
                title = "amperage";
                break;
                
            case kFakeSMCCategoryPower:
                group = kFakeSMCPowerSensor;
                title = "power";
                break;
                
            case kFakeSMCCategoryFan:
                group = kFakeSMCTachometerSensor;
                title = "tachometer";
                break;
                
            default:
                return;
        }
        
        OSCollectionIterator *iterator = OSCollectionIterator::withCollection(dictionary);
        
        while (OSString *key = OSDynamicCast(OSString, iterator->getNextObject())) {
            
            OSString *method = OSDynamicCast(OSString, dictionary->getObject(key));
            
            if (method && kIOReturnSuccess == acpiDevice->validateObject(method->getCStringNoCopy())) {
                FakeSMCSensor *sensor = NULL;
                
                if (category == kFakeSMCCategoryFan) {
                    sensor = addTachometer(methods->getCount(), key->getCStringNoCopy());
                }
                else {
                    sensor = addSensorFromNode(key, category, group, methods->getCount());
                }
                
                if (sensor) {
                    methods->setObject(method);//sensor->getKey(), method);
                }
                else {
                    ACPISensorsErrorLog("Failed to register %s sensor \"%s\" for method \"%s\"", title, key->getCStringNoCopy(), method->getCStringNoCopy());
                }
            }
        }
    }
}
示例#6
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;
}