From: Vincent Hanquez Date: Sat, 23 May 2009 17:35:31 +0000 (+0100) Subject: Merge branch 'master' of git://git.uk.xensource.com/xenclient/xen-pq X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=01cc93d9c28c26e5c418f64ae04d7393240c7527;p=xenclient%2Fxen-pq.git Merge branch 'master' of git://git.uk.xensource.com/xenclient/xen-pq --- 01cc93d9c28c26e5c418f64ae04d7393240c7527 diff --cc master/power-management-enhancement index b9bdb77,0000000..299d3c0 mode 100644,000000..100644 --- a/master/power-management-enhancement +++ b/master/power-management-enhancement @@@ -1,1066 -1,0 +1,1065 @@@ +diff --git a/tools/firmware/hvmloader/acpi/Makefile b/tools/firmware/hvmloader/acpi/Makefile +index c282d01..f9f6bc3 100644 +--- a/tools/firmware/hvmloader/acpi/Makefile ++++ b/tools/firmware/hvmloader/acpi/Makefile +@@ -19,17 +19,30 @@ XEN_ROOT = ../../../.. + include $(XEN_ROOT)/tools/firmware/Rules.mk + + C_SRC = build.c dsdt.c static_tables.c +-H_SRC = $(wildcard *.h) ++H_SRC = $(wildcard *.h) ssdt_pm.h ssdt_tpm.h + OBJS = $(patsubst %.c,%.o,$(C_SRC)) + ++build.o: $(H_SRC) build.c ++ ++IASL_VER = acpica-unix-20080729 ++IASL_URL = http://acpica.org/download/$(IASL_VER).tar.gz ++ + CFLAGS += -I. -I.. $(CFLAGS_include) + + vpath iasl $(PATH) + all: acpi.a + +-ssdt_pm.h ssdt_tpm.h: %.h: %.asl ++ssdt_pm.h: ssdt_pm.asl ++ $(MAKE) iasl ++ iasl -tc $< ++ sed -i'' -re 's/AmlCode/AmlCode_PM/g' $*.hex ++ mv $*.hex $@ ++ rm -f *.aml ++ ++ssdt_tpm.h: ssdt_tpm.asl + $(MAKE) iasl + iasl -tc $< ++ sed -i'' -re 's/AmlCode/AmlCode_TPM/g' $*.hex + mv $*.hex $@ + rm -f *.aml + +diff --git a/tools/firmware/hvmloader/acpi/build.c b/tools/firmware/hvmloader/acpi/build.c +index 82510fc..97dcdb5 100644 +--- a/tools/firmware/hvmloader/acpi/build.c ++++ b/tools/firmware/hvmloader/acpi/build.c +@@ -50,7 +50,13 @@ static void set_checksum( + + static uint8_t battery_port_exists(void) + { +- return (inb(0x88) == 0x1F); ++ uint8_t val; ++ ++ val = inb(0x88); ++ if ( (val == 0xff) || (val == 0x0) ) ++ return 0; ++ ++ return 1; + } + + static int construct_madt(struct acpi_20_madt *madt) +diff --git a/tools/firmware/hvmloader/acpi/ssdt_pm.asl b/tools/firmware/hvmloader/acpi/ssdt_pm.asl +index afb78b6..8f2d7a7 100644 +--- a/tools/firmware/hvmloader/acpi/ssdt_pm.asl ++++ b/tools/firmware/hvmloader/acpi/ssdt_pm.asl +@@ -95,6 +95,13 @@ DefinitionBlock ("SSDT_PM.aml", "SSDT", 2, "Xen", "HVM", 0) + P88, 8 + } + ++ /* OperationRegion for Power Button */ ++ OperationRegion (PBOP, SystemIO, 0x200, 0x01) ++ Field (PBOP, ByteAcc, NoLock, WriteAsZeros) ++ { ++ SLP, 1, ++ WAK, 1 ++ } + + Mutex (SYNC, 0x01) + Name (BUF0, Buffer (0x0100) {}) +@@ -291,8 +298,99 @@ DefinitionBlock ("SSDT_PM.aml", "SSDT", 2, "Xen", "HVM", 0) + Release (SYNC) + } + +- /* Future patches will extend AC object to better account for +- * AC to DC transition and more. */ ++ Method (E0, 0, NotSerialized) ++ { ++ If (\_SB.SLP) ++ { ++ Store (One, \_SB.SLP) ++ Notify (\_SB.SLPB, 0x80) ++ } ++ ++ if (\_SB.WAK) ++ { ++ Store (One, \_SB.WAK) ++ Notify (\_SB.SLPB, 0x2) ++ } ++ } ++ ++ Method (E1, 0, NotSerialized) ++ { ++ If (\_SB.SLP) ++ { ++ Store (One, \_SB.SLP) ++ Notify (\_SB.PBTN, 0x80) ++ } ++ ++ if (\_SB.WAK) ++ { ++ Store (One, \_SB.WAK) ++ Notify (\_SB.PBTN, 0x2) ++ } ++ } ++ ++ Method (E1C, 0, NotSerialized) ++ { ++ Notify (\_SB.AC, 0x80) ++ } ++ ++ Method (E17, 0, NotSerialized) ++ { ++ Notify (\_SB.LID, 0x80) ++ } ++ ++ Device (LID) ++ { ++ Name (_HID, EisaId ("PNP0C0D")) ++ Method (_LID, 0, NotSerialized) ++ { ++ Store (\_SB.P88, Local0) ++ If (And (Local0, 0x4)) ++ { ++ Return (0x1) ++ } ++ ++ Return (0x0) ++ } ++ ++ Name (_PRW, Package (0x02) ++ { ++ 0x17, ++ 0x03 ++ }) ++ ++ Method (_PSW, 1, NotSerialized) ++ { ++ Store (\_SB.P88, Local0) ++ If (And (Local0, 0x4)) ++ { ++ Return (0x1) ++ } ++ Return (0x0) ++ } ++ } ++ ++ Device (PBTN) ++ { ++ Name (_HID, EisaId ("PNP0C0C")) ++ ++ Name (_PRW, Package (0x02) ++ { ++ 0x01, ++ 0x04 ++ }) ++ } ++ ++ Device (SLPB) ++ { ++ Name (_HID, EisaId ("PNP0C0E")) ++ ++ Name (_PRW, Package (0x02) ++ { ++ 0x01, ++ 0x04 ++ }) ++ } ++ + Device (AC) + { + Name (_HID, "ACPI0003") +@@ -304,6 +402,12 @@ DefinitionBlock ("SSDT_PM.aml", "SSDT", 2, "Xen", "HVM", 0) + }) + Method (_PSR, 0, NotSerialized) + { ++ Store (\_SB.P88, Local0) ++ If (And (Local0, 0x1)) ++ { ++ Return (0x1) ++ } ++ + Return (0x0) + } + +@@ -348,11 +452,16 @@ DefinitionBlock ("SSDT_PM.aml", "SSDT", 2, "Xen", "HVM", 0) + \_SB + }) + +- /* Always returns 0x1f indicating battery present. */ ++ /* Returning 0x1F indicates battery present */ + Method (_STA, 0, NotSerialized) + { + Store (\_SB.P88, Local0) +- Return ( Local0 ) ++ If (And (Local0, 0x2)) ++ { ++ Return (0x1F) ++ } ++ ++ Return (0x0F) + } + + /* Battery generic info: design capacity, voltage, model # etc. */ +@@ -367,7 +476,7 @@ DefinitionBlock ("SSDT_PM.aml", "SSDT", 2, "Xen", "HVM", 0) + /* Battery status including battery charging/discharging rate. */ + Method (_BST, 0, NotSerialized) + { +- Store (1, \_SB.DBG1) ++ /* Store (1, \_SB.DBG1) */ + ACQR () + INIT (0x02) + INIT (0x01) +@@ -378,7 +487,7 @@ DefinitionBlock ("SSDT_PM.aml", "SSDT", 2, "Xen", "HVM", 0) + Store (HLP7 (), Index (BST0, 0x02)) + Store (HLP7 (), Index (BST0, 0x03)) + REL () +- Store (2, \_SB.DBG1) ++ /* Store (2, \_SB.DBG1) */ + Return (BST0) + } + } +@@ -419,5 +528,31 @@ DefinitionBlock ("SSDT_PM.aml", "SSDT", 2, "Xen", "HVM", 0) + } + } + } ++ ++ /* Wire GPE events to notify power state ++ * changes like ac power to battery use etc. ++ */ ++ Scope (\_GPE) ++ { ++ Method (_L00, 0, NotSerialized) ++ { ++ \_SB.E0() ++ } ++ ++ Method (_L01, 0, NotSerialized) ++ { ++ \_SB.E1() ++ } ++ ++ Method (_L1C, 0, NotSerialized) ++ { ++ \_SB.E1C() ++ } ++ ++ Method (_L17, 0, NotSerialized) ++ { ++ \_SB.E17() ++ } ++ } + } + +diff --git a/tools/firmware/hvmloader/acpi/ssdt_pm.h b/tools/firmware/hvmloader/acpi/ssdt_pm.h +index 020af0b..f277767 100644 +--- a/tools/firmware/hvmloader/acpi/ssdt_pm.h ++++ b/tools/firmware/hvmloader/acpi/ssdt_pm.h +@@ -1,22 +1,22 @@ + /* + * + * Intel ACPI Component Architecture +- * ASL Optimizing Compiler version 20061109 [May 18 2007] +- * Copyright (C) 2000 - 2006 Intel Corporation ++ * ASL Optimizing Compiler version 20080729 [Nov 24 2008] ++ * Copyright (C) 2000 - 2008 Intel Corporation + * Supports ACPI Specification Revision 3.0a + * +- * Compilation of "ssdt_pm.asl" - Sun Oct 12 23:57:51 2008 ++ * Compilation of "ssdt_pm.asl" - Thu May 14 12:24:23 2009 + * + * C source code output + * + */ + unsigned char AmlCode_PM[] = + { +- 0x53,0x53,0x44,0x54,0xD6,0x05,0x00,0x00, /* 00000000 "SSDT...." */ +- 0x02,0xD9,0x58,0x65,0x6E,0x00,0x00,0x00, /* 00000008 "..Xen..." */ ++ 0x53,0x53,0x44,0x54,0xA4,0x07,0x00,0x00, /* 00000000 "SSDT...." */ ++ 0x02,0x15,0x58,0x65,0x6E,0x00,0x00,0x00, /* 00000008 "..Xen..." */ + 0x48,0x56,0x4D,0x00,0x00,0x00,0x00,0x00, /* 00000010 "HVM....." */ + 0x00,0x00,0x00,0x00,0x49,0x4E,0x54,0x4C, /* 00000018 "....INTL" */ +- 0x09,0x11,0x06,0x20,0x10,0x41,0x5B,0x5C, /* 00000020 "... .A[\" */ ++ 0x29,0x07,0x08,0x20,0x10,0x43,0x73,0x5C, /* 00000020 ").. .Cs\" */ + 0x5F,0x53,0x42,0x5F,0x5B,0x80,0x44,0x42, /* 00000028 "_SB_[.DB" */ + 0x47,0x41,0x01,0x0B,0x40,0xB0,0x01,0x5B, /* 00000030 "GA..@..[" */ + 0x81,0x0B,0x44,0x42,0x47,0x41,0x01,0x44, /* 00000038 "..DBGA.D" */ +@@ -39,164 +39,222 @@ unsigned char AmlCode_PM[] = + 0x5B,0x80,0x50,0x52,0x54,0x33,0x01,0x0A, /* 000000C0 "[.PRT3.." */ + 0x88,0x01,0x5B,0x81,0x0B,0x50,0x52,0x54, /* 000000C8 "..[..PRT" */ + 0x33,0x01,0x50,0x38,0x38,0x5F,0x08,0x5B, /* 000000D0 "3.P88_.[" */ +- 0x01,0x53,0x59,0x4E,0x43,0x01,0x08,0x42, /* 000000D8 ".SYNC..B" */ +- 0x55,0x46,0x30,0x11,0x04,0x0B,0x00,0x01, /* 000000E0 "UF0....." */ +- 0x08,0x42,0x55,0x46,0x31,0x11,0x03,0x0A, /* 000000E8 ".BUF1..." */ +- 0x08,0x8B,0x42,0x55,0x46,0x31,0x00,0x42, /* 000000F0 "..BUF1.B" */ +- 0x55,0x46,0x41,0x8B,0x42,0x55,0x46,0x31, /* 000000F8 "UFA.BUF1" */ +- 0x0A,0x04,0x42,0x55,0x46,0x42,0x14,0x14, /* 00000100 "..BUFB.." */ +- 0x41,0x43,0x51,0x52,0x00,0x5B,0x23,0x53, /* 00000108 "ACQR.[#S" */ +- 0x59,0x4E,0x43,0xFF,0xFF,0x70,0x00,0x42, /* 00000110 "YNC..p.B" */ +- 0x55,0x46,0x41,0x14,0x31,0x49,0x4E,0x49, /* 00000118 "UFA.1INI" */ +- 0x54,0x01,0x70,0x42,0x55,0x46,0x41,0x60, /* 00000120 "T.pBUFA`" */ +- 0x75,0x60,0xA0,0x22,0x92,0x94,0x60,0x87, /* 00000128 "u`."..`." */ +- 0x42,0x55,0x46,0x30,0x8C,0x42,0x55,0x46, /* 00000130 "BUF0.BUF" */ +- 0x30,0x42,0x55,0x46,0x41,0x54,0x4D,0x50, /* 00000138 "0BUFATMP" */ +- 0x31,0x70,0x68,0x54,0x4D,0x50,0x31,0x70, /* 00000140 "1phTMP1p" */ +- 0x60,0x42,0x55,0x46,0x41,0x14,0x48,0x07, /* 00000148 "`BUFA.H." */ +- 0x57,0x50,0x52,0x54,0x02,0x70,0x69,0x5C, /* 00000150 "WPRT.pi\" */ +- 0x2E,0x5F,0x53,0x42,0x5F,0x50,0x38,0x36, /* 00000158 "._SB_P86" */ +- 0x5F,0x70,0x68,0x5C,0x2E,0x5F,0x53,0x42, /* 00000160 "_ph\._SB" */ +- 0x5F,0x50,0x42,0x32,0x5F,0x70,0x68,0x5C, /* 00000168 "_PB2_ph\" */ +- 0x2E,0x5F,0x53,0x42,0x5F,0x44,0x42,0x47, /* 00000170 "._SB_DBG" */ +- 0x32,0x70,0x69,0x5C,0x2E,0x5F,0x53,0x42, /* 00000178 "2pi\._SB" */ +- 0x5F,0x44,0x42,0x47,0x34,0x70,0x5C,0x2E, /* 00000180 "_DBG4p\." */ +- 0x5F,0x53,0x42,0x5F,0x50,0x42,0x32,0x5F, /* 00000188 "_SB_PB2_" */ +- 0x60,0xA2,0x11,0x92,0x93,0x60,0x00,0x70, /* 00000190 "`....`.p" */ +- 0x5C,0x2E,0x5F,0x53,0x42,0x5F,0x50,0x42, /* 00000198 "\._SB_PB" */ +- 0x32,0x5F,0x60,0x70,0x5C,0x2E,0x5F,0x53, /* 000001A0 "2_`p\._S" */ +- 0x42,0x5F,0x50,0x38,0x36,0x5F,0x61,0x70, /* 000001A8 "B_P86_ap" */ +- 0x61,0x5C,0x2E,0x5F,0x53,0x42,0x5F,0x44, /* 000001B0 "a\._SB_D" */ +- 0x42,0x47,0x33,0xA4,0x5C,0x2E,0x5F,0x53, /* 000001B8 "BG3.\._S" */ +- 0x42,0x5F,0x50,0x38,0x36,0x5F,0x14,0x1D, /* 000001C0 "B_P86_.." */ +- 0x48,0x4C,0x50,0x31,0x02,0xA0,0x16,0x95, /* 000001C8 "HLP1...." */ +- 0x69,0x87,0x68,0x8C,0x68,0x69,0x54,0x4D, /* 000001D0 "i.h.hiTM" */ +- 0x50,0x31,0x57,0x50,0x52,0x54,0x0A,0x7C, /* 000001D8 "P1WPRT.|" */ +- 0x54,0x4D,0x50,0x31,0x14,0x23,0x48,0x4C, /* 000001E0 "TMP1.#HL" */ +- 0x50,0x32,0x00,0x57,0x50,0x52,0x54,0x0A, /* 000001E8 "P2.WPRT." */ +- 0x7B,0x00,0x70,0x00,0x60,0xA2,0x12,0x95, /* 000001F0 "{.p.`..." */ +- 0x60,0x42,0x55,0x46,0x41,0x48,0x4C,0x50, /* 000001F8 "`BUFAHLP" */ +- 0x31,0x42,0x55,0x46,0x30,0x60,0x75,0x60, /* 00000200 "1BUF0`u`" */ +- 0x14,0x1F,0x48,0x4C,0x50,0x33,0x02,0xA0, /* 00000208 "..HLP3.." */ +- 0x18,0x95,0x69,0x87,0x68,0x8C,0x68,0x69, /* 00000210 "..i.h.hi" */ +- 0x54,0x4D,0x50,0x31,0x70,0x57,0x50,0x52, /* 00000218 "TMP1pWPR" */ +- 0x54,0x0A,0x7D,0x00,0x54,0x4D,0x50,0x31, /* 00000220 "T.}.TMP1" */ +- 0x14,0x23,0x48,0x4C,0x50,0x34,0x00,0x70, /* 00000228 ".#HLP4.p" */ +- 0x00,0x60,0xA2,0x19,0x95,0x60,0x42,0x55, /* 00000230 ".`...`BU" */ +- 0x46,0x42,0x72,0x42,0x55,0x46,0x41,0x60, /* 00000238 "FBrBUFA`" */ +- 0x61,0x48,0x4C,0x50,0x33,0x42,0x55,0x46, /* 00000240 "aHLP3BUF" */ +- 0x30,0x61,0x75,0x60,0x14,0x42,0x04,0x48, /* 00000248 "0au`.B.H" */ +- 0x4C,0x50,0x35,0x00,0x48,0x4C,0x50,0x32, /* 00000250 "LP5.HLP2" */ +- 0x70,0x57,0x50,0x52,0x54,0x0A,0x79,0x00, /* 00000258 "pWPRT.y." */ +- 0x42,0x55,0x46,0x42,0x72,0x42,0x55,0x46, /* 00000260 "BUFBrBUF" */ +- 0x41,0x42,0x55,0x46,0x42,0x60,0xA0,0x1C, /* 00000268 "ABUFB`.." */ +- 0x95,0x87,0x42,0x55,0x46,0x30,0x60,0x70, /* 00000270 "..BUF0`p" */ +- 0x87,0x42,0x55,0x46,0x30,0x60,0x74,0x60, /* 00000278 ".BUF0`t`" */ +- 0x42,0x55,0x46,0x41,0x60,0x70,0x60,0x42, /* 00000280 "BUFA`p`B" */ +- 0x55,0x46,0x42,0x48,0x4C,0x50,0x34,0x14, /* 00000288 "UFBHLP4." */ +- 0x32,0x48,0x4C,0x50,0x36,0x00,0x70,0x42, /* 00000290 "2HLP6.pB" */ +- 0x55,0x46,0x41,0x60,0x75,0x60,0xA0,0x21, /* 00000298 "UFA`u`.!" */ +- 0x92,0x94,0x60,0x87,0x42,0x55,0x46,0x30, /* 000002A0 "..`.BUF0" */ +- 0x8C,0x42,0x55,0x46,0x30,0x42,0x55,0x46, /* 000002A8 ".BUF0BUF" */ +- 0x41,0x54,0x4D,0x50,0x31,0x70,0x60,0x42, /* 000002B0 "ATMP1p`B" */ +- 0x55,0x46,0x41,0xA4,0x54,0x4D,0x50,0x31, /* 000002B8 "UFA.TMP1" */ +- 0xA4,0x00,0x14,0x35,0x48,0x4C,0x50,0x37, /* 000002C0 "...5HLP7" */ +- 0x00,0x70,0x42,0x55,0x46,0x41,0x60,0x72, /* 000002C8 ".pBUFA`r" */ +- 0x60,0x0A,0x04,0x60,0xA0,0x21,0x92,0x94, /* 000002D0 "`..`.!.." */ +- 0x60,0x87,0x42,0x55,0x46,0x30,0x8A,0x42, /* 000002D8 "`.BUF0.B" */ +- 0x55,0x46,0x30,0x42,0x55,0x46,0x41,0x53, /* 000002E0 "UF0BUFAS" */ +- 0x58,0x32,0x32,0x70,0x60,0x42,0x55,0x46, /* 000002E8 "X22p`BUF" */ +- 0x41,0xA4,0x53,0x58,0x32,0x32,0xA4,0x00, /* 000002F0 "A.SX22.." */ +- 0x14,0x1C,0x48,0x4C,0x50,0x38,0x02,0xA0, /* 000002F8 "..HLP8.." */ +- 0x15,0x95,0x69,0x87,0x68,0x8C,0x68,0x69, /* 00000300 "..i.h.hi" */ +- 0x54,0x4D,0x50,0x31,0x70,0x48,0x4C,0x50, /* 00000308 "TMP1pHLP" */ +- 0x36,0x54,0x4D,0x50,0x31,0x14,0x16,0x48, /* 00000310 "6TMP1..H" */ +- 0x4C,0x50,0x39,0x02,0x70,0x00,0x60,0xA2, /* 00000318 "LP9.p.`." */ +- 0x0C,0x95,0x60,0x69,0x48,0x4C,0x50,0x38, /* 00000320 "..`iHLP8" */ +- 0x68,0x60,0x75,0x60,0x14,0x22,0x48,0x4C, /* 00000328 "h`u`."HL" */ +- 0x50,0x41,0x00,0x70,0x48,0x4C,0x50,0x36, /* 00000330 "PA.pHLP6" */ +- 0x60,0x08,0x54,0x4D,0x50,0x5F,0x11,0x02, /* 00000338 "`.TMP_.." */ +- 0x60,0x48,0x4C,0x50,0x39,0x54,0x4D,0x50, /* 00000340 "`HLP9TMP" */ +- 0x5F,0x60,0xA4,0x54,0x4D,0x50,0x5F,0x14, /* 00000348 "_`.TMP_." */ +- 0x0C,0x52,0x45,0x4C,0x5F,0x00,0x5B,0x27, /* 00000350 ".REL_.['" */ +- 0x53,0x59,0x4E,0x43,0x5B,0x82,0x3C,0x41, /* 00000358 "SYNC[. ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define AC_ADAPTER_STATE_FILE_PATH "/proc/acpi/ac_adapter/AC/state" ++#define LID_STATE_FILE_PATH "/proc/acpi/button/lid/LID/state" ++#define ACPID_SOCKET_PATH "/var/run/acpid.socket" ++ ++#define XS_AC_ADAPTER_STATE_PATH "/pm/ac_adapter" ++#define XS_LID_STATE_PATH "/pm/lid_state" ++ ++#define XS_AC_ADAPTER_EVENT_PATH "/pm/events/acadapterstatechanged" ++#define XS_LID_EVENT_PATH "/pm/events/lidstatechanged" ++#define XS_PBTN_EVENT_PATH "/pm/events/powerbuttonpressed" ++#define XS_SBTN_EVENT_PATH "/pm/events/sleepbuttonpressed" ++ ++static int socket_fd; ++static pthread_t acpi_thread; ++extern struct xs_handle *xs; ++ ++void write_state_info_in_xenstore(char *file_path, char *xenstore_path, ++ char *search_str, char *default_value, char *alternate_value) ++{ ++ FILE *file; ++ char file_data[1024]; ++ ++ xs_write(xs, XBT_NULL, xenstore_path, default_value, strlen(default_value)); ++ file = fopen(file_path, "r"); ++ if ( file == NULL ) ++ return; ++ ++ memset(file_data, 0, 1024); ++ fgets(file_data, 1024, file); ++ if ( strstr(file_data, search_str) ) ++ xs_write(xs, XBT_NULL, xenstore_path, alternate_value, ++ strlen(alternate_value)); ++ fclose(file); ++} ++ ++void initialize_system_state_info(void) ++{ ++ write_state_info_in_xenstore(AC_ADAPTER_STATE_FILE_PATH, ++ XS_AC_ADAPTER_STATE_PATH, "off-line", "1", "0"); ++ write_state_info_in_xenstore(LID_STATE_FILE_PATH, XS_LID_STATE_PATH, ++ "closed", "1", "0"); ++} ++ ++void handle_ac_adapter_state_change(void) ++{ ++ write_state_info_in_xenstore(AC_ADAPTER_STATE_FILE_PATH, ++ XS_AC_ADAPTER_STATE_PATH, "off-line", "1", "0"); ++ xs_write(xs, XBT_NULL, XS_AC_ADAPTER_EVENT_PATH, "1", 1); ++} ++ ++void handle_lid_state_change(void) ++{ ++ write_state_info_in_xenstore(LID_STATE_FILE_PATH, XS_LID_STATE_PATH, ++ "closed", "1", "0"); ++ xs_write(xs, XBT_NULL, XS_LID_EVENT_PATH, "1", 1); ++} ++ ++void handle_pbtn_pressed_event(void) ++{ ++ xs_write(xs, XBT_NULL, XS_PBTN_EVENT_PATH, "1", 1); ++} ++ ++void handle_sbtn_pressed_event(void) ++{ ++ xs_write(xs, XBT_NULL, XS_SBTN_EVENT_PATH, "1", 1); ++} ++ ++void process_acpi_message(char *acpi_buffer) ++{ ++ if ( strstr(acpi_buffer, "ac_adapter") ) ++ { ++ handle_ac_adapter_state_change(); ++ return; ++ } ++ ++ if ( strstr(acpi_buffer, "LID") ) ++ { ++ handle_lid_state_change(); ++ return; ++ } ++ ++ if ( (strstr(acpi_buffer, "PBTN")) || ++ (strstr(acpi_buffer, "PWRF")) ) ++ { ++ handle_pbtn_pressed_event(); ++ return; ++ } ++ ++ if ( strstr(acpi_buffer, "SBTN") ) ++ handle_sbtn_pressed_event(); ++} ++ ++static void *acpi_events_thread(void *arg) ++{ ++ int ret; ++ struct sockaddr_un addr; ++ char acpi_buffer[1024]; ++ ++ socket_fd = socket(PF_UNIX, SOCK_STREAM, 0); ++ if ( socket_fd == -1) ++ return (void *)socket_fd; ++ ++ addr.sun_family = AF_UNIX; ++ strncpy(addr.sun_path, ACPID_SOCKET_PATH, strlen(ACPID_SOCKET_PATH)); ++ addr.sun_path[strlen(ACPID_SOCKET_PATH)] = '\0'; ++ ret = connect(socket_fd, (struct sockaddr *)&addr, sizeof(addr)); ++ if ( ret == -1 ) ++ return (void *)ret; ++ ++ while( 1 ) ++ { ++ memset(acpi_buffer, 0, sizeof(acpi_buffer)); ++ ret = recv(socket_fd, acpi_buffer, sizeof(acpi_buffer), 0); ++ if ( ret == 0 ) ++ continue; ++ ++ process_acpi_message(acpi_buffer); ++ } ++ ++ return (void *)1; ++} ++ ++void monitor_acpi_events(void) ++{ ++ pthread_create(&acpi_thread, NULL, &acpi_events_thread, NULL); ++} ++ ++void acpi_events_cleanup(void) ++{ ++ if ( socket_fd != -1 ) ++ close(socket_fd); ++ ++ pthread_cancel(acpi_thread); ++} ++ +diff --git a/tools/xenpmd/xenpmd.c b/tools/xenpmd/xenpmd.c - index 28de744..9bc0cc1 100644 ++index 28de744..db8e292 100644 +--- a/tools/xenpmd/xenpmd.c ++++ b/tools/xenpmd/xenpmd.c +@@ -40,10 +40,11 @@ + #include + #include + #include ++#include + #include + + /* #define RUN_STANDALONE */ +-#define RUN_IN_SIMULATE_MODE ++/* #define RUN_IN_SIMULATE_MODE */ + + enum BATTERY_INFO_TYPE { + BIF, +@@ -84,7 +85,12 @@ struct battery_status { + unsigned long present_voltage; + }; + +-static struct xs_handle *xs; ++struct xs_handle *xs; ++static pthread_t worker_thread; ++ ++extern void initialize_system_state_info(void); ++extern void monitor_acpi_events(void); ++extern void acpi_events_cleanup(void); + + #ifdef RUN_IN_SIMULATE_MODE + #define BATTERY_DIR_PATH "/tmp/battery" +@@ -218,11 +224,19 @@ void set_attribute_battery_status(char *attrib_name, + { + if ( strstr(attrib_name, "charging state") ) + { +- /* Check this, below is half baked */ +- if ( strstr(attrib_value, "charged") ) +- status->state = 0; +- else +- status->state = 1; ++ if ( strstr(attrib_value, "charging/discharging") ) ++ status->state |= 0x3; ++ else if ( strstr(attrib_value, "discharging") ) ++ status->state |= 0x1; ++ else if ( strstr(attrib_value, "charging") ) ++ status->state |= 0x2; ++ return; ++ } ++ ++ if ( strstr(attrib_name, "capacity state") ) ++ { ++ if ( strstr(attrib_value, "ok") ) ++ status->state |= 4; + return; + } + +@@ -292,11 +306,12 @@ int get_next_battery_info_or_status(DIR *battery_dir, + void *info_or_status) + { + FILE *file; +- char line_info[256]; ++ char line_info[1024]; + + if ( !info_or_status ) + return 0; + ++ memset(line_info, 0, sizeof (line_info)); + if (type == BIF) + memset(info_or_status, 0, sizeof(struct battery_info)); + else +@@ -306,8 +321,11 @@ int get_next_battery_info_or_status(DIR *battery_dir, + if ( !file ) + return 0; + +- while ( fgets(line_info, sizeof(line_info), file) != NULL ) ++ while ( fgets(line_info, sizeof (line_info), file) != NULL ) ++ { + parse_battery_info_or_status(line_info, type, info_or_status); ++ memset(line_info, 0, sizeof (line_info)); ++ } + + fclose(file); + return 1; +@@ -317,14 +335,14 @@ int get_next_battery_info_or_status(DIR *battery_dir, + void print_battery_info(struct battery_info *info) + { + printf("present: %d\n", info->present); +- printf("design capacity: %d\n", info->design_capacity); +- printf("last full capacity: %d\n", info->last_full_capacity); ++ printf("design capacity: %d\n", (int) info->design_capacity); ++ printf("last full capacity: %d\n", (int) info->last_full_capacity); + printf("battery technology: %d\n", info->battery_technology); +- printf("design voltage: %d\n", info->design_voltage); +- printf("design capacity warning:%d\n", info->design_capacity_warning); +- printf("design capacity low: %d\n", info->design_capacity_low); +- printf("capacity granularity 1: %d\n", info->capacity_granularity_1); +- printf("capacity granularity 2: %d\n", info->capacity_granularity_2); ++ printf("design voltage: %d\n", (int) info->design_voltage); ++ printf("design capacity warning:%d\n", (int) info->design_capacity_warning); ++ printf("design capacity low: %d\n", (int) info->design_capacity_low); ++ printf("capacity granularity 1: %d\n", (int) info->capacity_granularity_1); ++ printf("capacity granularity 2: %d\n", (int) info->capacity_granularity_2); + printf("model number: %s\n", info->model_number); + printf("serial number: %s\n", info->serial_number); + printf("battery type: %s\n", info->battery_type); +@@ -406,10 +424,11 @@ int write_one_time_battery_info(void) + void print_battery_status(struct battery_status *status) + { + printf("present: %d\n", status->present); +- printf("Battery state %d\n", status->state); +- printf("Battery present rate %d\n", status->present_rate); +- printf("Battery remining capacity %d\n", status->remaining_capacity); +- printf("Battery present voltage %d\n", status->present_voltage); ++ printf("Battery state %d\n", (int) status->state); ++ printf("Battery present rate %d\n", (int) status->present_rate); ++ printf("Battery remining capacity %d\n", ++ (int) status->remaining_capacity); ++ printf("Battery present voltage %d\n", (int) status->present_voltage); + } + #endif /*RUN_STANDALONE*/ + +@@ -469,6 +488,7 @@ int wait_for_and_update_battery_status_request(void) + return ret; + } + ++#ifndef RUN_STANDALONE + /* Borrowed daemonize from xenstored - Initially written by Stevens. */ + static void daemonize(void) + { - @@ -493,24 +513,57 @@ static void daemonize(void) ++@@ -493,24 +513,53 @@ static void daemonize(void) + + umask(0); + } ++#endif + +-int main(int argc, char *argv[]) ++/* ++ * IMPORTANT: From the child process, we create a new thread ++ * to monitor acpid events. However, due to a bug in uClibc, ++ * the child process main thread does not get time slice ++ * after spawning a new thread. To work around this, we create ++ * a worker thread and then create an acpid monitor thread from ++ * this worker thread. This way both the worker thread and acpid ++ * thread will get time slices. This workaround will be removed ++ * once uClibc bug is fixed. ++ */ ++static void *worker_thread_routine(void *arg) + { - #ifndef RUN_STANDALONE - daemonize(); - #endif ++-#ifndef RUN_STANDALONE ++- daemonize(); ++-#endif + xs = (struct xs_handle *)xs_daemon_open(); +- if ( xs == NULL ) +- return -1; +- +- if ( write_one_time_battery_info() == 0 ) ++ if ( xs == NULL ) ++ return NULL; ++ if ( xs == NULL ) ++ return NULL; ++ - + if ( write_one_time_battery_info() == 0 ) ++ initialize_system_state_info(); ++ monitor_acpi_events(); ++ if ( write_one_time_battery_info() == 0 ) + { + xs_daemon_close(xs); +- return -1; ++ return NULL; + } + + wait_for_and_update_battery_status_request(); ++ acpi_events_cleanup(); + xs_daemon_close(xs); +- return 0; ++ return NULL; + } + ++ ++int main(int argc, char *argv[]) ++{ ++#ifndef RUN_STANDALONE ++ daemonize(); ++#endif ++ ++ /* Refer to worker_thread_routine for why we create additional thread */ ++ pthread_create(&worker_thread, NULL, &worker_thread_routine, NULL); ++ ++ /* below won't get a time slice because of uClibc bug. */ ++ while ( 1 ) ++ sleep(60); ++ ++ return 0; ++}