VirtualBox

Changeset 14710 in vbox for trunk/src/VBox/Devices


Ignore:
Timestamp:
Nov 27, 2008 3:13:46 PM (16 years ago)
Author:
vboxsync
Message:

Devices-OSX: added ACPI power reporting (#3342)

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/PC/DrvACPI.cpp

    r14464 r14710  
    4141#endif
    4242
     43#ifdef RT_OS_DARWIN
     44# include <Carbon/Carbon.h>
     45# include <IOKit/ps/IOPowerSources.h>
     46# include <IOKit/ps/IOPSKeys.h>
     47#endif
     48
    4349#include "Builtins.h"
    4450
     
    179185        fclose(statusFile);
    180186    }
    181 #else /* !RT_OS_LINUX either - what could this be? */
     187#elif defined (RT_OS_DARWIN) /* !RT_OS_LINUX */
     188    *pPowerSource = PDM_ACPI_POWER_SOURCE_UNKNOWN;
     189
     190    CFTypeRef pBlob = IOPSCopyPowerSourcesInfo();
     191    CFArrayRef pSources = IOPSCopyPowerSourcesList(pBlob);
     192
     193    CFDictionaryRef pSource = NULL;
     194    const void *psValue;
     195    bool result;
     196
     197    if (CFArrayGetCount(pSources) > 0)
     198    {
     199        for(int i = 0; i < CFArrayGetCount(pSources); ++i)
     200        {
     201            pSource = IOPSGetPowerSourceDescription(pBlob, CFArrayGetValueAtIndex(pSources, i));
     202            /* If the source is empty skip over to the next one. */
     203            if(!pSource)
     204                continue;
     205            /* Skip all power sources which are currently not present like a
     206             * second battery. */
     207            if (CFDictionaryGetValue(pSource, CFSTR(kIOPSIsPresentKey)) == kCFBooleanFalse)
     208                continue;
     209            /* Only internal power types are of interest. */
     210            result = CFDictionaryGetValueIfPresent(pSource, CFSTR(kIOPSTransportTypeKey), &psValue);
     211            if (result &&
     212                CFStringCompare((CFStringRef)psValue, CFSTR(kIOPSInternalType), 0) == kCFCompareEqualTo)
     213            {
     214                /* Check which power source we are connect on. */
     215                result = CFDictionaryGetValueIfPresent(pSource, CFSTR(kIOPSPowerSourceStateKey), &psValue);
     216                if (result &&
     217                    CFStringCompare((CFStringRef)psValue, CFSTR(kIOPSACPowerValue), 0) == kCFCompareEqualTo)
     218                    *pPowerSource = PDM_ACPI_POWER_SOURCE_OUTLET;
     219                else if (result &&
     220                         CFStringCompare((CFStringRef)psValue, CFSTR(kIOPSBatteryPowerValue), 0) == kCFCompareEqualTo)
     221                    *pPowerSource = PDM_ACPI_POWER_SOURCE_BATTERY;
     222            }
     223        }
     224    }
     225    CFRelease(pBlob);
     226    CFRelease(pSources);
     227#else /* !RT_OS_DARWIN either - what could this be? */
    182228    *pPowerSource = PDM_ACPI_POWER_SOURCE_OUTLET;
    183229#endif /* !RT_OS_WINDOWS */
     
    413459        *pu32PresentRate = (uint32_t)(((float)presentRateTotal / (float)maxCapacityTotal) * 1000);
    414460    }
    415 #endif /* RT_OS_LINUX */
     461#elif defined(RT_OS_DARWIN)
     462    CFTypeRef pBlob = IOPSCopyPowerSourcesInfo();
     463    CFArrayRef pSources = IOPSCopyPowerSourcesList(pBlob);
     464
     465    CFDictionaryRef pSource = NULL;
     466    const void *psValue;
     467    bool result;
     468
     469    if (CFArrayGetCount(pSources) > 0)
     470    {
     471        for(int i = 0; i < CFArrayGetCount(pSources); ++i)
     472        {
     473            pSource = IOPSGetPowerSourceDescription(pBlob, CFArrayGetValueAtIndex(pSources, i));
     474            /* If the source is empty skip over to the next one. */
     475            if(!pSource)
     476                continue;
     477            /* Skip all power sources which are currently not present like a
     478             * second battery. */
     479            if (CFDictionaryGetValue(pSource, CFSTR(kIOPSIsPresentKey)) == kCFBooleanFalse)
     480                continue;
     481            /* Only internal power types are of interest. */
     482            result = CFDictionaryGetValueIfPresent(pSource, CFSTR(kIOPSTransportTypeKey), &psValue);
     483            if (result &&
     484                CFStringCompare((CFStringRef)psValue, CFSTR(kIOPSInternalType), 0) == kCFCompareEqualTo)
     485            {
     486                PDMACPIPOWERSOURCE powerSource = PDM_ACPI_POWER_SOURCE_UNKNOWN;
     487                /* First check which power source we are connect on. */
     488                result = CFDictionaryGetValueIfPresent(pSource, CFSTR(kIOPSPowerSourceStateKey), &psValue);
     489                if (result &&
     490                    CFStringCompare((CFStringRef)psValue, CFSTR(kIOPSACPowerValue), 0) == kCFCompareEqualTo)
     491                    powerSource = PDM_ACPI_POWER_SOURCE_OUTLET;
     492                else if (result &&
     493                         CFStringCompare((CFStringRef)psValue, CFSTR(kIOPSBatteryPowerValue), 0) == kCFCompareEqualTo)
     494                    powerSource = PDM_ACPI_POWER_SOURCE_BATTERY;
     495
     496                /* At this point the power source is present. */
     497                *pfPresent = true;
     498                *penmBatteryState = PDM_ACPI_BAT_STATE_CHARGED;
     499
     500                int curCapacity = 0;
     501                int maxCapacity = 1;
     502                float remCapacity = 0.0f;
     503
     504                /* Fetch the current capacity value of the power source */
     505                result = CFDictionaryGetValueIfPresent(pSource, CFSTR(kIOPSCurrentCapacityKey), &psValue);
     506                if (result)
     507                    CFNumberGetValue((CFNumberRef)psValue, kCFNumberSInt32Type, &curCapacity);
     508                /* Fetch the maximum capacity value of the power source */
     509                result = CFDictionaryGetValueIfPresent(pSource, CFSTR(kIOPSMaxCapacityKey), &psValue);
     510                if (result)
     511                    CFNumberGetValue((CFNumberRef)psValue, kCFNumberSInt32Type, &maxCapacity);
     512
     513                /* Calculate the remaining capacity in percent */
     514                remCapacity = ((float)curCapacity/(float)maxCapacity * PDM_ACPI_BAT_CAPACITY_MAX);
     515                *penmRemainingCapacity = (PDMACPIBATCAPACITY)remCapacity;
     516
     517                if (powerSource == PDM_ACPI_POWER_SOURCE_BATTERY)
     518                {
     519                    /* If we are on battery power we are discharging in every
     520                     * case */
     521                    *penmBatteryState = PDM_ACPI_BAT_STATE_DISCHARGING;
     522                    int timeToEmpty = -1;
     523                    /* Get the time till the battery source will be empty */
     524                    result = CFDictionaryGetValueIfPresent(pSource, CFSTR(kIOPSTimeToEmptyKey), &psValue);
     525                    if (result)
     526                        CFNumberGetValue((CFNumberRef)psValue, kCFNumberSInt32Type, &timeToEmpty);
     527                    if (timeToEmpty != -1)
     528                        /* 0...1000 */
     529                        *pu32PresentRate = (uint32_t)roundf((remCapacity / ((float)timeToEmpty/60.0)) * 10.0);
     530                }
     531
     532                if (powerSource == PDM_ACPI_POWER_SOURCE_OUTLET &&
     533                    CFDictionaryGetValueIfPresent(pSource, CFSTR(kIOPSIsChargingKey), &psValue))
     534                {
     535                    /* We are running on an AC power source, but we also have a
     536                     * battery power source present. */
     537                    if (CFBooleanGetValue((CFBooleanRef)psValue) > 0)
     538                    {
     539                        /* This means charging. */
     540                        *penmBatteryState = PDM_ACPI_BAT_STATE_CHARGING;
     541                        int timeToFull = -1;
     542                        /* Get the time till the battery source will be charged */
     543                        result = CFDictionaryGetValueIfPresent(pSource, CFSTR(kIOPSTimeToFullChargeKey), &psValue);
     544                        if (result)
     545                            CFNumberGetValue((CFNumberRef)psValue, kCFNumberSInt32Type, &timeToFull);
     546                        if (timeToFull != -1)
     547                            /* 0...1000 */
     548                            *pu32PresentRate = (uint32_t)roundf((100.0-(float)remCapacity) / ((float)timeToFull/60.0)) * 10.0;
     549                    }
     550                }
     551
     552                /* Check for critical */
     553                int criticalValue = 20;
     554                result = CFDictionaryGetValueIfPresent(pSource, CFSTR(kIOPSDeadWarnLevelKey), &psValue);
     555                if (result)
     556                    CFNumberGetValue((CFNumberRef)psValue, kCFNumberSInt32Type, &criticalValue);
     557                if (remCapacity < criticalValue)
     558                    *penmBatteryState = (PDMACPIBATSTATE)(*penmBatteryState | PDM_ACPI_BAT_STATE_CRITICAL);
     559            }
     560        }
     561    }
     562    CFRelease(pBlob);
     563    CFRelease(pSources);
     564#endif /* RT_OS_DARWIN */
    416565    return VINF_SUCCESS;
    417566}
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette