source: branches/branch-1-0/src/helpers/acpih.c@ 408

Last change on this file since 408 was 408, checked in by pr, 13 years ago

Remove unspeakably hacky code.

  • Property svn:eol-style set to CRLF
  • Property svn:keywords set to Author Date Id Revision
File size: 10.7 KB
Line 
1
2/*
3 *@@sourcefile apcih.c:
4 * contains helpers for accessing ACPI.
5 *
6 * Usage: All OS/2 programs.
7 *
8 * Function prefixes:
9 * -- acpih* ACPI helper functions
10 *
11 * Note: Version numbering in this file relates to XWorkplace version
12 * numbering.
13 *
14 *@@header "helpers\acpih.h"
15 *@@added V1.0.5 (2006-06-26) [pr]
16 */
17
18/*
19 * Copyright (C) 2006-2009 Paul Ratcliffe.
20 * This file is part of the "XWorkplace helpers" source package.
21 * This is free software; you can redistribute it and/or modify
22 * it under the terms of the GNU General Public License as published
23 * by the Free Software Foundation, in version 2 as it comes in the
24 * "COPYING" file of the XWorkplace main distribution.
25 * This program is distributed in the hope that it will be useful,
26 * but WITHOUT ANY WARRANTY; without even the implied warranty of
27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 * GNU General Public License for more details.
29 */
30
31#define OS2EMX_PLAIN_CHAR
32 // this is needed for "os2emx.h"; if this is defined,
33 // emx will define PSZ as _signed_ char, otherwise
34 // as unsigned char
35
36#define INCL_DOSMODULEMGR
37#define INCL_DOSERRORS
38#include <os2.h>
39
40#include "setup.h" // code generation and debugging options
41
42#include "helpers\apmh.h" // @@added V1.0.9 (2012-02-20) [slevine]
43#include "helpers\acpih.h"
44#include "helpers\standards.h"
45
46/* ******************************************************************
47 *
48 * Globals
49 *
50 ********************************************************************/
51
52HMODULE G_hmodACPI = NULLHANDLE;
53ULONG 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;
60
61ACPISTARTAPI *pAcpiStartApi = NULL;
62ACPIENDAPI *pAcpiEndApi = NULL;
63ACPIGOTOSLEEP *pAcpiGoToSleep = NULL;
64
65ACPITKGETOBJECTINFOALLOC *pAcpiTkGetObjectInfoAlloc = NULL;
66ACPITKGETHANDLE *pAcpiTkGetHandle = NULL;
67ACPITKOSFREE *pAcpiTkOsFree = NULL;
68ACPITKWALKNAMESPACE *pAcpiTkWalkNamespace = NULL;
69ACPITKEVALUATEOBJECT *pAcpiTkEvaluateObject = NULL;
70
71/*
72 *@@category: Helpers\Control program helpers\ACPI
73 * See acpih.c.
74 */
75
76/*
77 *@@ acpihOpen:
78 * resolves the ACPI entrypoints and loads the ACPI DLL.
79 */
80
81APIRET acpihOpen(ACPI_API_HANDLE *phACPI)
82{
83 APIRET arc = NO_ERROR;
84
85 if (!G_hmodACPI)
86 {
87 if (!(arc = DosLoadModule(NULL,
88 0,
89 "ACPI32",
90 &G_hmodACPI)))
91 {
92 arc = DosQueryProcAddr(G_hmodACPI,
93 ORD_ACPISTARTAPI,
94 NULL,
95 (PFN *) &pAcpiStartApi);
96 if (!arc)
97 arc = DosQueryProcAddr(G_hmodACPI,
98 ORD_ACPIENDAPI,
99 NULL,
100 (PFN *) &pAcpiEndApi);
101
102 if (!arc)
103 arc = DosQueryProcAddr(G_hmodACPI,
104 ORD_ACPIGOTOSLEEP,
105 NULL,
106 (PFN *) &pAcpiGoToSleep);
107 if (arc)
108 {
109 DosFreeModule(G_hmodACPI);
110 G_hmodACPI = NULLHANDLE;
111 pAcpiStartApi = NULL;
112 pAcpiEndApi = NULL;
113 pAcpiGoToSleep = NULL;
114 return(arc);
115 }
116
117 // @@added V1.0.9 (2012-02-20) [slevine]: additional ACPI support, code from David Azarewicz
118 DosQueryProcAddr(G_hmodACPI, ORD_ACPITKGETOBJECTINFOALLOC, NULL, (PFN *) &pAcpiTkGetObjectInfoAlloc);
119 DosQueryProcAddr(G_hmodACPI, ORD_ACPITKGETHANDLE, NULL, (PFN *) &pAcpiTkGetHandle);
120 DosQueryProcAddr(G_hmodACPI, ORD_ACPITKOSFREE, NULL, (PFN *) &pAcpiTkOsFree);
121 DosQueryProcAddr(G_hmodACPI, ORD_ACPITKWALKNAMESPACE, NULL, (PFN *) &pAcpiTkWalkNamespace);
122 DosQueryProcAddr(G_hmodACPI, ORD_ACPITKEVALUATEOBJECT, NULL, (PFN *) &pAcpiTkEvaluateObject);
123 }
124 }
125
126 if (arc)
127 return(arc);
128 else
129 {
130 G_ulCount++;
131 return(pAcpiStartApi(phACPI));
132 }
133}
134
135/*
136 *@@ acpihClose:
137 * unloads the ACPI DLL.
138 */
139
140VOID acpihClose(ACPI_API_HANDLE *phACPI)
141{
142 if (pAcpiEndApi)
143 {
144 pAcpiEndApi(phACPI);
145 G_ulCount--;
146 }
147
148 if (!G_ulCount)
149 {
150 DosFreeModule(G_hmodACPI);
151 G_hmodACPI = NULLHANDLE;
152 pAcpiStartApi = NULL;
153 pAcpiEndApi = NULL;
154 pAcpiGoToSleep = NULL;
155 }
156}
157
158/*
159 *@@ acpihGoToSleep:
160 * changes the Power State.
161 */
162
163APIRET acpihGoToSleep(ACPI_API_HANDLE *phACPI, UCHAR ucState)
164{
165 if (pAcpiGoToSleep)
166 return(pAcpiGoToSleep(phACPI, ucState));
167 else
168 return(ERROR_PROTECTION_VIOLATION);
169}
170
171
172/**
173 *@@ AcpiCallbackWidget:
174 * ACPI callback helper for battery and power status queries.
175 * Code provided by David Azarewicz
176 *@@added V1.0.9 (2012-02-20) [slevine]: code from David Azarewicz
177 */
178
179#define AE_DEPTH AE_OK
180
181ACPI_STATUS AcpiCallbackWidget( ACPI_HANDLE ObjHandle, UINT32 NestingLevel, void *Context, void **ReturnValue )
182{
183 ACPI_STATUS Status;
184 ACPI_DEVICE_INFO *pDevInfo;
185
186 pDevInfo = NULL;
187 Status = pAcpiTkGetObjectInfoAlloc( ObjHandle, &pDevInfo );
188
189 if (Status == AE_OK)
190 {
191 if (pDevInfo->Type != ACPI_TYPE_DEVICE) return AE_DEPTH;
192 if (!(pDevInfo->Valid & ACPI_VALID_HID)) return AE_DEPTH;
193 if (!pDevInfo->HardwareId.String ) return AE_DEPTH;
194
195 if (strncmp(pDevInfo->HardwareId.String, "ACPI0003", 8)==0)
196 { /* AC Power */
197 Status = pAcpiTkGetHandle(ObjHandle, "_PSR", &G_ahAC);
198 if (Status) G_ahAC = 0;
199 return AE_DEPTH;
200 }
201
202 if (strncmp(pDevInfo->HardwareId.String, "PNP0C0A", 7)==0)
203 { /* Smart battery */
204 if (G_uiBatteryCount >= MAX_BATTERY_COUNT) return AE_DEPTH;
205 G_ahBat[G_uiBatteryCount] = ObjHandle;
206 G_uiBatteryCount++;
207 return AE_DEPTH;
208 }
209 }
210
211 if (pDevInfo) pAcpiTkOsFree(pDevInfo);
212
213 return AE_OK;
214}
215
216/**
217 *@@ acpihGetPowerStatus:
218 * Returns power and battery status in caller provided buffers.
219 * Returns zero if success, non-zero if fail.
220 * Code provided by David Azarewicz
221 *@@added V1.0.9 (2012-02-20) [slevine]: code from David Azarewicz
222 */
223APIRET acpihGetPowerStatus(PAPM pApm, PBOOL pfChanged)
224{
225 ACPI_STATUS Status;
226 ACPI_BUFFER Result;
227 ACPI_OBJECT *Obj, Object[20];
228 UINT32 uiI;
229 ULONG ulTmp, BRemaining, LastFull;
230 BOOL fChanged;
231
232 if (pAcpiTkWalkNamespace==NULL) return 1;
233 if (pApm==NULL) return 1;
234
235 if (!G_uiAlreadyWalked)
236 {
237 Status = pAcpiTkWalkNamespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, ACPI_UINT32_MAX, AcpiCallbackWidget, pApm, NULL);
238 G_uiAlreadyWalked = 1;
239 }
240
241 fChanged = FALSE;
242
243 // VAC 3.08 long long compatibility support
244# ifdef INCL_LONGLONG // VAC 3.6.5 - compiler supports long long
245# define OBJECT_VALUE(index) (Object[index].Integer.Value)
246# else // VAC 3.08 - compiler does not support long long
247# define OBJECT_VALUE(index) (Object[index].Integer.Value.ulLo)
248# endif
249
250 if (G_ahAC)
251 {
252 Result.Length = sizeof(Object);
253 Result.Pointer = Object;
254 Status = pAcpiTkEvaluateObject(G_ahAC, NULL, NULL, &Result);
255 if (Status != AE_OK) ulTmp = 2;
256 if (Object[0].Type != ACPI_TYPE_INTEGER) ulTmp = 2;
257
258 ulTmp = OBJECT_VALUE(0);
259 if (pApm->fUsingAC != ulTmp)
260 {
261 pApm->fUsingAC = ulTmp;
262 fChanged = TRUE;
263 }
264 }
265
266 for (uiI=0; uiI<G_uiBatteryCount; uiI++)
267 {
268 if (G_ahBat[uiI] == 0) continue;
269
270 Result.Length = sizeof(Object);
271 Result.Pointer = Object;
272 Status = pAcpiTkEvaluateObject(G_ahBat[uiI], "_BIF", NULL, &Result);
273 if (Status != AE_OK)
274 {
275 G_ahBat[uiI] = 0;
276 continue;
277 }
278
279 Obj = Result.Pointer;
280 Obj = (ACPI_OBJECT *)Obj[0].Package.Elements;
281 LastFull = (UINT32)OBJECT_VALUE(2);
282 if (LastFull == 0xffffffff)
283 {
284 G_ahBat[uiI] = 0;
285 continue;
286 }
287
288 Result.Length = sizeof(Object);
289 Result.Pointer = Object;
290 Status = pAcpiTkEvaluateObject(G_ahBat[uiI], "_BST", NULL, &Result);
291 if (Status != AE_OK)
292 {
293 G_ahBat[uiI] = 0;
294 continue;
295 }
296
297 Obj = Result.Pointer;
298 Obj = (ACPI_OBJECT *)Obj[0].Package.Elements;
299
300 if (OBJECT_VALUE(2) != 0xffffffff)
301 {
302 BRemaining = (UINT32)OBJECT_VALUE(2);
303 }
304
305 if (OBJECT_VALUE(0) != 0xffffffff)
306 {
307 if (BRemaining > (LastFull >> 1)) // > 50% is high. < 50% is low
308 {
309 ulTmp = 1; // High
310 }
311 else
312 {
313 ulTmp = 2; // Low
314 }
315
316 if (OBJECT_VALUE(0) & 4)
317 {
318 ulTmp = 2; // Critical
319 }
320 // If battery charging - it can't be critical
321 if (OBJECT_VALUE(0) & 2)
322 {
323 ulTmp = 3; // Charging
324 }
325 if (pApm->bBatteryStatus != ulTmp)
326 {
327 pApm->bBatteryStatus = ulTmp;
328 fChanged = TRUE;
329 }
330 }
331
332 ulTmp = (BRemaining*100)/LastFull;
333 if (ulTmp > 100) ulTmp = 100;
334 if (pApm->bBatteryLife != ulTmp)
335 {
336 pApm->bBatteryLife = ulTmp;
337 fChanged = TRUE;
338 }
339 }
340
341 if (pfChanged) *pfChanged = fChanged;
342 pApm->fAlreadyRead = FALSE;
343
344 return 0;
345
346# undef OBJECT_VALUE
347}
348
349/*
350 *@@ acpihHasBattery:
351 * quick'n'dirty helper which returns TRUE only
352 * if ACPI is supported on the system and the
353 * system actually has a battery (i.e. is a laptop).
354 * Code provided by David Azarewicz.
355 * @@added V1.0.9 (2012-02-20) [slevine]: code from David Azarewicz
356 */
357BOOL acpihHasBattery(VOID)
358{
359 BOOL brc = FALSE;
360 ACPI_API_HANDLE hACPI;
361 APM Apm;
362
363 if (!acpihOpen(&hACPI))
364 {
365 Apm.bBatteryStatus = 0xff;
366 if (!acpihGetPowerStatus(&Apm, NULL)) brc = (Apm.bBatteryStatus != 0xFF);
367 acpihClose(&hACPI);
368 }
369
370 return brc;
371}
Note: See TracBrowser for help on using the repository browser.