Ignore:
Timestamp:
Feb 26, 2013, 3:44:10 AM (12 years ago)
Author:
pr
Message:

ACPI sleep mods. from Steven.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/helpers/acpih.c

    r380 r414  
    1717
    1818/*
    19  *      Copyright (C) 2006-2009 Paul Ratcliffe.
     19 *      Copyright (C) 2006-2013 Paul Ratcliffe.
    2020 *      This file is part of the "XWorkplace helpers" source package.
    2121 *      This is free software; you can redistribute it and/or modify
     
    4040#include "setup.h"                      // code generation and debugging options
    4141
     42#include "helpers\apmh.h"               // @@added V1.0.9 (2012-02-20) [slevine]
    4243#include "helpers\acpih.h"
    4344#include "helpers\standards.h"
     
    5152HMODULE       G_hmodACPI = NULLHANDLE;
    5253ULONG         G_ulCount = 0;
     54// @@added V1.0.9 (2012-02-20) [slevine]: additional ACPI support, code from David Azarewicz
     55ACPI_HANDLE   G_ahAC = 0;
     56#define MAX_BATTERY_COUNT 4
     57ACPI_HANDLE   G_ahBat[MAX_BATTERY_COUNT];
     58ULONG         G_uiBatteryCount = 0;
     59ULONG         G_uiAlreadyWalked = 0;
    5360
    5461ACPISTARTAPI  *pAcpiStartApi = NULL;
     
    5663ACPIGOTOSLEEP *pAcpiGoToSleep = NULL;
    5764
     65ACPITKGETOBJECTINFOALLOC *pAcpiTkGetObjectInfoAlloc = NULL;
     66ACPITKGETHANDLE *pAcpiTkGetHandle = NULL;
     67ACPITKOSFREE *pAcpiTkOsFree = NULL;
     68ACPITKWALKNAMESPACE *pAcpiTkWalkNamespace = NULL;
     69ACPITKEVALUATEOBJECT *pAcpiTkEvaluateObject = NULL;
     70// @@added V1.0.9 (2012-12-10) [slevine]: additional ACPI support
     71ACPITKPREPARETOSLEEP *pAcpiTkPrepareToSleep = NULL;
     72
    5873/*
    5974 *@@category: Helpers\Control program helpers\ACPI
     
    7186
    7287    if (!G_hmodACPI)
     88    {
    7389        if (!(arc = DosLoadModule(NULL,
    7490                                  0,
     
    8298            if (!arc)
    8399                arc = DosQueryProcAddr(G_hmodACPI,
    84                                    ORD_ACPIENDAPI,
    85                                    NULL,
    86                                    (PFN *) &pAcpiEndApi);
     100                                       ORD_ACPIENDAPI,
     101                                       NULL,
     102                                       (PFN *) &pAcpiEndApi);
    87103
    88104            if (!arc)
    89105                arc = DosQueryProcAddr(G_hmodACPI,
    90                                    ORD_ACPIGOTOSLEEP,
    91                                    NULL,
    92                                    (PFN *) &pAcpiGoToSleep);
     106                                       ORD_ACPIGOTOSLEEP,
     107                                       NULL,
     108                                       (PFN *) &pAcpiGoToSleep);
    93109            if (arc)
    94110            {
     
    100116                return(arc);
    101117            }
    102         }
     118
     119            // @@added V1.0.9 (2012-02-20) [slevine]: additional ACPI support, code from David Azarewicz
     120            DosQueryProcAddr(G_hmodACPI, ORD_ACPITKGETOBJECTINFOALLOC,
     121                             NULL, (PFN *) &pAcpiTkGetObjectInfoAlloc);
     122            DosQueryProcAddr(G_hmodACPI, ORD_ACPITKGETHANDLE,
     123                             NULL, (PFN *) &pAcpiTkGetHandle);
     124            DosQueryProcAddr(G_hmodACPI, ORD_ACPITKOSFREE,
     125                             NULL, (PFN *) &pAcpiTkOsFree);
     126            DosQueryProcAddr(G_hmodACPI, ORD_ACPITKWALKNAMESPACE,
     127                             NULL, (PFN *) &pAcpiTkWalkNamespace);
     128            DosQueryProcAddr(G_hmodACPI, ORD_ACPITKEVALUATEOBJECT,
     129                             NULL, (PFN *) &pAcpiTkEvaluateObject);
     130            // @@added V1.0.9 (2012-12-10) [slevine]: additional ACPI support
     131            DosQueryProcAddr(G_hmodACPI, ORD_ACPITKPREPARETOSLEEP,
     132                             NULL, (PFN *) &pAcpiTkPrepareToSleep);
     133        }
     134    }
    103135
    104136    if (arc)
     
    107139    {
    108140        G_ulCount++;
     141
     142        // @@added V1.0.9 (2012-12-10) [slevine]: use AcpiTkPrepareToSleep rather than workaround
     143        /* This function does not exist in older versions of acpi
     144         * As a result the shutdown attempt will usually hang because
     145         * the required code has not been committed into memory.
     146         */
     147        if (pAcpiTkPrepareToSleep)
     148            pAcpiTkPrepareToSleep(ACPI_STATE_S5);
     149
    109150        return(pAcpiStartApi(phACPI));
    110151    }
     
    131172        pAcpiEndApi = NULL;
    132173        pAcpiGoToSleep = NULL;
     174        // @@added V1.0.9 (2012-12-10) [slevine]: additional ACPI support
     175        pAcpiTkPrepareToSleep = NULL;
    133176    }
    134177}
     
    147190}
    148191
     192
     193/**
     194 *@@ AcpiCallbackWidget:
     195 *      ACPI callback helper for battery and power status queries.
     196 *      Code provided by David Azarewicz
     197 *@@added V1.0.9 (2012-02-20) [slevine]: code from David Azarewicz
     198 */
     199
     200#define AE_DEPTH AE_OK
     201
     202ACPI_STATUS AcpiCallbackWidget( ACPI_HANDLE ObjHandle, UINT32 NestingLevel, void *Context, void **ReturnValue )
     203{
     204    ACPI_DEVICE_INFO *pDevInfo = NULL;
     205    ACPI_STATUS Status = pAcpiTkGetObjectInfoAlloc(ObjHandle, &pDevInfo);
     206
     207    if (Status == AE_OK)
     208    {
     209        if (pDevInfo->Type != ACPI_TYPE_DEVICE)
     210            return AE_DEPTH;
     211
     212        if (!(pDevInfo->Valid & ACPI_VALID_HID))
     213            return AE_DEPTH;
     214
     215        if (!pDevInfo->HardwareId.String)
     216            return AE_DEPTH;
     217
     218        if (strncmp(pDevInfo->HardwareId.String, "ACPI0003", 8) == 0)
     219        { /* AC Power */
     220            Status = pAcpiTkGetHandle(ObjHandle, "_PSR", &G_ahAC);
     221            if (Status)
     222                G_ahAC = 0;
     223
     224            return AE_DEPTH;
     225        }
     226
     227        if (strncmp(pDevInfo->HardwareId.String, "PNP0C0A", 7) == 0)
     228        { /* Smart battery */
     229            if (G_uiBatteryCount < MAX_BATTERY_COUNT)
     230                G_ahBat[G_uiBatteryCount++] = ObjHandle;
     231
     232            return AE_DEPTH;
     233        }
     234    }
     235
     236    if (pDevInfo)
     237        pAcpiTkOsFree(pDevInfo);
     238
     239    return AE_OK;
     240}
     241
     242/**
     243 *@@ acpihGetPowerStatus:
     244 *      Returns power and battery status in caller provided buffers.
     245 *      Returns zero if success, non-zero if fail.
     246 *      Code provided by David Azarewicz
     247 *@@added V1.0.9 (2012-02-20) [slevine]: code from David Azarewicz
     248 */
     249
     250APIRET acpihGetPowerStatus(PAPM pApm, PBOOL pfChanged)
     251{
     252    ACPI_STATUS Status;
     253    ACPI_BUFFER Result;
     254    ACPI_OBJECT *Obj, Object[20];
     255    UINT32 uiI;
     256    ULONG ulTmp, BRemaining, LastFull;
     257    BOOL fChanged;
     258
     259    /* Make sure all the functions we need have valid pointers.
     260     * @@added V1.0.9 (2012-02-25) [dazarewicz]: additional ACPI support
     261     */
     262    if (   (pAcpiTkWalkNamespace == NULL)
     263        || (pAcpiTkGetObjectInfoAlloc == NULL)
     264        || (pAcpiTkGetHandle == NULL)
     265        || (pAcpiTkOsFree == NULL)
     266        || (pAcpiTkEvaluateObject == NULL)
     267        || (pApm == NULL)
     268       )
     269        return 1;
     270
     271    if (!G_uiAlreadyWalked)
     272    {
     273        Status = pAcpiTkWalkNamespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
     274                                      ACPI_UINT32_MAX, AcpiCallbackWidget,
     275                                      pApm, NULL);
     276        G_uiAlreadyWalked = 1;
     277    }
     278
     279    fChanged = FALSE;
     280
     281    // VAC 3.08 long long compatibility support
     282#ifdef INCL_LONGLONG // VAC 3.6.5 - compiler supports long long
     283#define OBJECT_VALUE(index)  (Object[index].Integer.Value)
     284#define OBJ_VALUE(index)  (Obj[index].Integer.Value)
     285#else // VAC 3.08 - compiler does not support long long
     286#define OBJECT_VALUE(index)  (Object[index].Integer.Value.ulLo)
     287#define OBJ_VALUE(index)  (Obj[index].Integer.Value.ulLo)
     288#endif
     289
     290    if (G_ahAC)
     291    {
     292        // Have _PSR
     293        Result.Length = sizeof(Object);
     294        Result.Pointer = Object;
     295        Status = pAcpiTkEvaluateObject(G_ahAC, NULL, NULL, &Result);
     296        if (Status != AE_OK)
     297            ulTmp = 2;                  // assume on backup power
     298        else if (Object[0].Type != ACPI_TYPE_INTEGER)
     299            ulTmp = 2;                  // assume on backup power
     300            else
     301                ulTmp = (UINT32)OBJECT_VALUE(0);
     302
     303        if (pApm->fUsingAC != (BYTE) ulTmp)
     304        {
     305            pApm->fUsingAC = (BYTE) ulTmp;
     306            fChanged = TRUE;
     307        }
     308    }
     309
     310    for (uiI=0; uiI < G_uiBatteryCount; uiI++)
     311    {
     312        if (G_ahBat[uiI] == 0)
     313            continue;
     314
     315        Result.Length = sizeof(Object);
     316        Result.Pointer = Object;
     317        // Get battery info
     318        Status = pAcpiTkEvaluateObject(G_ahBat[uiI], "_BIF", NULL, &Result);
     319        if (Status != AE_OK)
     320        {
     321            G_ahBat[uiI] = 0;
     322            continue;
     323        }
     324
     325        Obj = Result.Pointer;
     326        Obj = (ACPI_OBJECT *)Obj[0].Package.Elements;   // Battery info package
     327        LastFull = (UINT32)OBJ_VALUE(2);
     328        if (LastFull == 0xffffffff)
     329        {
     330            G_ahBat[uiI] = 0;
     331            continue;
     332        }
     333
     334        Result.Length = sizeof(Object);
     335        Result.Pointer = Object;
     336        // Get battery status
     337        Status = pAcpiTkEvaluateObject(G_ahBat[uiI], "_BST", NULL, &Result);
     338        if (Status != AE_OK)
     339        {
     340            G_ahBat[uiI] = 0;
     341            continue;
     342        }
     343
     344        Obj = Result.Pointer;
     345        Obj = (ACPI_OBJECT *)Obj[0].Package.Elements;   // Battery status package
     346
     347        // If voltage known
     348        if ((UINT32)OBJ_VALUE(2) != 0xffffffff)
     349            BRemaining = (UINT32)OBJ_VALUE(2);
     350
     351        // If battery units are mWh or mAh
     352        // If not, it is a percentage
     353        if ((UINT32)OBJ_VALUE(0) != 0xffffffff)
     354        {
     355            if (BRemaining > (LastFull >> 1)) // > 50% is high. < 50% is low
     356                ulTmp = 1; // High
     357            else
     358                ulTmp = 2; // Low
     359
     360            if (OBJ_VALUE(0) & 4)
     361                ulTmp = 2; // Critical
     362
     363            // If battery charging - it can't be critical
     364            if (OBJ_VALUE(0) & 2)
     365                ulTmp = 3; // Charging
     366
     367            if (pApm->bBatteryStatus != ulTmp)
     368            {
     369                pApm->bBatteryStatus = (BYTE)ulTmp;
     370                fChanged = TRUE;
     371            }
     372        }
     373
     374        ulTmp = (BRemaining*100) / LastFull;
     375        if (ulTmp > 100)
     376            ulTmp = 100;
     377
     378        if (pApm->bBatteryLife != ulTmp)
     379        {
     380            pApm->bBatteryLife = (BYTE) ulTmp;
     381            fChanged = TRUE;
     382        }
     383    }
     384
     385    if (pfChanged)
     386        *pfChanged = fChanged;
     387
     388    pApm->fAlreadyRead = FALSE;
     389    return 0;
     390
     391#undef OBJECT_VALUE
     392#undef OBJ_VALUE
     393}
     394
     395/*
     396 *@@ acpihHasBattery:
     397 *      quick'n'dirty helper which returns TRUE only
     398 *      if ACPI is supported on the system and the
     399 *      system actually has a battery (i.e. is a laptop).
     400 *      Code provided by David Azarewicz.
     401 * @@added V1.0.9 (2012-02-20) [slevine]: code from David Azarewicz
     402 */
     403BOOL acpihHasBattery(VOID)
     404{
     405    BOOL brc = FALSE;
     406    ACPI_API_HANDLE hACPI;
     407    APM Apm;
     408
     409    if (!acpihOpen(&hACPI))
     410    {
     411        Apm.bBatteryStatus = 0xff;
     412        if (!acpihGetPowerStatus(&Apm, NULL))
     413            brc = (Apm.bBatteryStatus != 0xFF);
     414
     415        acpihClose(&hACPI);
     416    }
     417
     418    return brc;
     419}
     420
Note: See TracChangeset for help on using the changeset viewer.