Implementation of GetSystemPowerStatus using ACPI (real submission)
David Lee Lambert
lamber45 at cse.msu.edu
Tue May 17 23:21:49 CDT 2005
On Tue, May 17, 2005 at 11:56:22PM -0400, David Lee Lambert wrote:
> WinSCP2 calls this function, but I don't know why. I also wrote a
> command-line Win32 app to make this call.
>
> Perhaps someone with an APM kernel can backport this...
>
> I know it looks like it's doing a lot, but on a system without these two
> ACPI devices (ac_adapter and battery) it will make two unsuccessful
> opendir() calls and return a default value.
The previous patch had a debugging-statement left in by mistake. Sorry.
Changelog:
implemented GetSystemPowerStatus
--
David Lee Lambert (also as4109 at wayne.edu) cell ph# 586-873-8813
PGP key at http://www.cse.msu.edu/~lamber45/newmail.htm#GPGKey
resume at http://www.cse.msu.edu/~lamber45/resume.htm
-------------- next part --------------
--- dlls/kernel/powermgnt.c.v1_3 Tue May 17 13:26:38 2005
+++ dlls/kernel/powermgnt.c Wed May 18 00:16:31 2005
@@ -17,7 +17,12 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#include <dirent.h>
+#include <math.h>
+#include <stdio.h>
#include <stdarg.h>
+#include <string.h>
+#include <sys/types.h>
#include "windef.h"
#include "winbase.h"
@@ -39,8 +44,131 @@
*/
BOOL WINAPI GetSystemPowerStatus(LPSYSTEM_POWER_STATUS sps_ptr)
{
- FIXME("(): stub, harmless.\n");
- return FALSE; /* no power management support */
+ const char * ac = "/proc/acpi/ac_adapter/";
+ const char *batt= "/proc/acpi/battery/";
+ DIR * batt_dir,*ac_dir;
+ struct dirent * ent;
+ char fnbuf[40]; /* longer than len(ac)+len(HEXDIGIT*4)+len({state|info}) */
+ FILE * file;
+ char line[80],key[40],arg[40];
+ const char * pattern = " %39[^:]: %39[ -~]"; /* for sscanf */
+
+ /* set defaults */
+ sps_ptr->ACLineStatus = 255;
+ sps_ptr->BatteryFlag = 255;
+ sps_ptr->BatteryLifePercent = 255;
+ sps_ptr->Reserved1 = 0;
+ sps_ptr->BatteryLifeTime = 0xFFFFFFFF;
+ sps_ptr->BatteryFullLifeTime = 0xFFFFFFFF;
+
+ /* check ac adapter */
+ ac_dir = opendir(ac);
+ if (ac_dir) {
+ while ((ent=readdir(ac_dir))) {
+ if (ent->d_name[0]=='.') continue;
+ snprintf(fnbuf,40,"%s%s/state",ac,ent->d_name);
+ file = fopen(fnbuf,"r");
+ if (file) {
+ while (fgets(line,80,file) &&
+ 2==sscanf(line,pattern,key,arg)) {
+ if (strcmp(key,"state")==0) {
+ if (strcmp(arg,"on-line")==0) {
+ sps_ptr->ACLineStatus = 1;
+ }
+ if (strcmp(arg,"off-line")==0) {
+ sps_ptr->ACLineStatus = 0;
+ }}}
+ fclose(file);
+ }}
+ closedir(ac_dir);
+ }
+
+ /* check batteries */
+ batt_dir = opendir(batt);
+ if (batt_dir) {
+ float x,design_capacity=0.0,
+ design_capacity_warning=0.0,design_capacity_low=0.0,
+ remaining_capacity=0.0,present_rate=0.0;
+ BOOL any_charging=FALSE;
+ while ((ent=readdir(batt_dir))) {
+ if (ent->d_name[0]=='.') continue;
+ snprintf(fnbuf,40,"%s%s/info",batt,ent->d_name);
+ file = fopen(fnbuf,"r");
+ if (file) {
+ while (fgets(line,80,file) &&
+ 2==sscanf(line,pattern,key,arg)) {
+ if (strcmp(key,"design capacity")==0 &&
+ sscanf(arg,"%g",&x)==1) {
+ design_capacity += x;
+ }
+ if (strcmp(key,"design capacity warning")==0 &&
+ sscanf(arg,"%g",&x)==1) {
+ design_capacity_warning += x;
+ }
+ if (strcmp(key,"design capacity low")==0 &&
+ sscanf(arg,"%g",&x)==1) {
+ design_capacity_low += x;
+ }
+ }
+ fclose(file);
+ }
+ snprintf(fnbuf,40,"%s%s/state",batt,ent->d_name);
+ file = fopen(fnbuf,"r");
+ if (file) {
+ int charging = 0;
+ while (fgets(line,80,file) &&
+ 2==sscanf(line,pattern,key,arg)) {
+ if (strcmp(key,"charging state")==0) {
+ if (strcmp(arg,"charged")==0) {
+ } else if (strcmp(arg,"discharging")==0) {
+ charging = -1;
+ } else if (strcmp(arg,"charging")==0) {
+ charging = 1;
+ any_charging = TRUE;
+ } else {
+ WARN("Unknown line in %s, '%s: %s'\n",fnbuf,key,arg);
+ }
+ } else if (strcmp(key,"present rate")==0
+ && sscanf(arg,"%g",&x)==1) {
+ present_rate += charging*x;
+ } else if (strcmp(key,"remaining capacity")==0
+ && sscanf(arg,"%g:",&x)==1) {
+ remaining_capacity += x;
+ }
+ }
+ fclose(file);
+ }}
+ if (design_capacity > 0.0) {
+ if (remaining_capacity > design_capacity_warning) {
+ sps_ptr->BatteryFlag = 1;
+ } else if (remaining_capacity > design_capacity_low) {
+ sps_ptr->BatteryFlag = 2;
+ } else {
+ sps_ptr->BatteryFlag = 4;
+ }
+ if (any_charging) {
+ sps_ptr->BatteryFlag |= 8;
+ }
+ sps_ptr->BatteryLifePercent = floorf(( remaining_capacity/design_capacity*100.0) + 0.499 );
+ if (present_rate < 0.0) {
+ /* Linux specifies rates in mWh or mAh */
+ sps_ptr->BatteryLifeTime =
+ floorf( remaining_capacity/(-present_rate)
+ * 3600.0 );
+ sps_ptr->BatteryFullLifeTime =
+ floorf( design_capacity/(-present_rate)
+ * 3600.0 );
+ }
+ }
+ closedir(batt_dir);
+ }
+
+ /* if we have ACPI but no battery... */
+ if (sps_ptr->ACLineStatus != 255 && sps_ptr->BatteryFlag == 255) {
+ sps_ptr->BatteryFlag = 128;
+ }
+
+ return TRUE;
}
/***********************************************************************
More information about the wine-patches
mailing list