diff --git a/repos/libports/src/app/acpica/sb.h b/repos/libports/src/app/acpica/sb.h index f48fab1e82..b9e8e25a20 100644 --- a/repos/libports/src/app/acpica/sb.h +++ b/repos/libports/src/app/acpica/sb.h @@ -11,35 +11,166 @@ * under the terms of the GNU Affero General Public License version 3. */ -class Battery : Acpica::Callback { - +class Battery : Acpica::Callback +{ private: Acpica::Reportstate * _report; ACPI_HANDLE _sb; + /* + * ACPI spec - 10.2.2.1 _BIF (Battery Information) + * (alternatively 10.2.2.2 _BIX could be used) + */ + Acpica::Buffer _battery; + Genode::String<16> _battery_name; + + void _init_static_info() + { + ACPI_STATUS res = AcpiEvaluateObjectTyped(_sb, ACPI_STRING("_BIF"), + nullptr, &_battery, + ACPI_TYPE_PACKAGE); + ACPI_OBJECT * obj = reinterpret_cast(_battery.object); + if (ACPI_FAILURE(res) || !obj || obj->Package.Count != 13) { + Genode::error("failed - '", __func__, "' _BIF res=", Genode::Hex(res)); + return; + } + + Acpica::Buffer battery_name; + res = AcpiGetName(_sb, ACPI_SINGLE_NAME, &battery_name); + if (ACPI_FAILURE(res)) { + _battery_name = Genode::String<16>("unknown"); + } else { + _battery_name = Genode::String<16>(battery_name.object); + } + } + + void _info(Genode::Xml_generator &xml) + { + xml.node("name", [&] { xml.append(_battery_name.string()); }); + + const char * node_name[] = { + "powerunit", "design_capacity", "last_full_capacity", + "technology", "voltage", "warning_capacity", "low_capacity", + "granularity1", "granularity2", "serial", "model", "type", + "oem" + }; + + ACPI_OBJECT * obj = reinterpret_cast(_battery.object); + + if (sizeof(node_name) / sizeof(node_name[0]) != obj->Package.Count) + return; + + for (unsigned i = 0; i < 9; i++) { + ACPI_OBJECT * v = &obj->Package.Elements[i]; + + xml.node(node_name[i], [&] { + if (v->Type != ACPI_TYPE_INTEGER) { + xml.append("unknown"); + return; + } + + xml.attribute("value", v->Integer.Value); + + if (i == 0) + xml.append(v->Integer.Value == 0 ? "mW/mWh" : + v->Integer.Value == 1 ? "mA/mAh" : + "unknown"); + if (i == 3) + xml.append(v->Integer.Value == 0 ? "primary" : + v->Integer.Value == 1 ? "secondary" : + "unknown"); + }); + } + + for (unsigned i = 9; i < obj->Package.Count; i++) { + ACPI_OBJECT * v = &obj->Package.Elements[i]; + + xml.node(node_name[i], [&] { + + if (v->Type != ACPI_TYPE_STRING) + return; + + xml.append(v->String.Pointer); + }); + } + } + + void _status(Genode::Xml_generator &xml) + { + /* 10.2.2.6 _BST (Battery Status) */ + Acpica::Buffer dynamic; + ACPI_STATUS res = AcpiEvaluateObjectTyped(_sb, ACPI_STRING("_BST"), + nullptr, &dynamic, + ACPI_TYPE_PACKAGE); + ACPI_OBJECT * obj = reinterpret_cast(dynamic.object); + if (ACPI_FAILURE(res) || !obj || + obj->Package.Count != 4) { + Genode::error("failed - '", __func__, "' _BST res=", Genode::Hex(res)); + return; + } + + Acpica::Buffer sta; + res = AcpiEvaluateObjectTyped(_sb, ACPI_STRING("_STA"), nullptr, + &sta, ACPI_TYPE_INTEGER); + if (ACPI_FAILURE(res)) { + xml.node("status", [&] { xml.append("unknown"); }); + } else + xml.node("status", [&] { + xml.attribute("value", sta.object.Integer.Value); + /* see "6.3.7 _STA" for more human readable decoding */ + if (!(sta.object.Integer.Value & ACPI_STA_BATTERY_PRESENT)) + xml.append("battery not present"); + }); + + const char * node_name[] = { + "state", "present_rate", "remaining_capacity", + "present_voltage" + }; + + if (sizeof(node_name) / sizeof(node_name[0]) != obj->Package.Count) + return; + + for (unsigned i = 0; i < obj->Package.Count; i++) { + ACPI_OBJECT * v = &obj->Package.Elements[i]; + + xml.node(node_name[i], [&] { + if (v->Type != ACPI_TYPE_INTEGER) { + xml.append("unknown"); + return; + } + + xml.attribute("value", v->Integer.Value); + + if (i != 0) + return; + + if (v->Integer.Value & 0x1) xml.append("discharging"); + if (v->Integer.Value & 0x2) xml.append("charging"); + if (v->Integer.Value & 0x4) xml.append("critical low"); + }); + } + } + public: Battery(void * report, ACPI_HANDLE sb) : _report(reinterpret_cast(report)), _sb(sb) { + _init_static_info(); if (_report) _report->add_notify(this); } - void handle(ACPI_HANDLE sb, UINT32 value) - { - if (_report) - _report->battery_event(); - } - static ACPI_STATUS detect(ACPI_HANDLE sb, UINT32, void *m, void **) { Acpica::Main * main = reinterpret_cast(m); Battery * dev_obj = new (main->heap) Battery(main->report, sb); - ACPI_STATUS res = AcpiInstallNotifyHandler (sb, ACPI_DEVICE_NOTIFY, - handler, dev_obj); + ACPI_STATUS res = + AcpiInstallNotifyHandler(sb, ACPI_DEVICE_NOTIFY, + Acpica::Callback::handler, + dev_obj); if (ACPI_FAILURE(res)) { Genode::error("failed - '", __func__, "' " "res=", Genode::Hex(res)); @@ -48,7 +179,7 @@ class Battery : Acpica::Callback { } Acpica::Buffer battery_name; - AcpiGetName (sb, ACPI_SINGLE_NAME, &battery_name); + res = AcpiGetName (sb, ACPI_SINGLE_NAME, &battery_name); if (ACPI_FAILURE(res)) { Genode::error("failed - '", __func__, "' battery name " "res=", Genode::Hex(res)); @@ -106,130 +237,19 @@ class Battery : Acpica::Callback { return AE_OK; } + /* + * Acpica::Callback<> interface + */ + + void handle(ACPI_HANDLE sb, UINT32 value) + { + if (_report) + _report->battery_event(); + } + void generate(Genode::Xml_generator &xml) { - info(xml); - status(xml); - } - - void info(Genode::Xml_generator &xml) - { - /* ACPI spec - 10.2.2.1 _BIF (Battery Information) */ - Acpica::Buffer battery; - ACPI_STATUS res = AcpiEvaluateObjectTyped(_sb, ACPI_STRING("_BIF"), - nullptr, &battery, - ACPI_TYPE_PACKAGE); - ACPI_OBJECT * obj = reinterpret_cast(battery.object); - if (ACPI_FAILURE(res) || !obj || obj->Package.Count != 13) { - Genode::error("failed - '", __func__, "' _BIF res=", Genode::Hex(res)); - return; - } - - Acpica::Buffer battery_name; - AcpiGetName (_sb, ACPI_SINGLE_NAME, &battery_name); - if (ACPI_FAILURE(res)) - xml.node("name", [&] { xml.append("unknown"); }); - else - xml.node("name", [&] { xml.append(battery_name.object); }); - - const char * node_name[] = { - "powerunit", "design_capacity", "last_full_capacity", - "technology", "voltage", "warning_capacity", "low_capacity", - "granularity1", "granularity2", "serial", "model", "type", - "oem" - }; - - if (sizeof(node_name) / sizeof(node_name[0]) != obj->Package.Count) - return; - - for (unsigned i = 0; i < 9; i++) { - ACPI_OBJECT * v = &obj->Package.Elements[i]; - - xml.node(node_name[i], [&] { - if (v->Type != ACPI_TYPE_INTEGER) { - xml.append("unknown"); - return; - } - - xml.attribute("value", v->Integer.Value); - - if (i == 0) - xml.append(v->Integer.Value == 0 ? "mW/mWh" : - v->Integer.Value == 1 ? "mA/mAh" : - "unknown"); - if (i == 3) - xml.append(v->Integer.Value == 0 ? "primary" : - v->Integer.Value == 1 ? "secondary" : - "unknown"); - }); - } - - for (unsigned i = 9; i < obj->Package.Count; i++) { - ACPI_OBJECT * v = &obj->Package.Elements[i]; - - xml.node(node_name[i], [&] { - - if (v->Type != ACPI_TYPE_STRING) - return; - - xml.append(v->String.Pointer); - }); - } - } - - void status(Genode::Xml_generator &xml) - { - /* 10.2.2.6 _BST (Battery Status) */ - Acpica::Buffer dynamic; - ACPI_STATUS res = AcpiEvaluateObjectTyped(_sb, ACPI_STRING("_BST"), - nullptr, &dynamic, - ACPI_TYPE_PACKAGE); - ACPI_OBJECT * obj = reinterpret_cast(dynamic.object); - if (ACPI_FAILURE(res) || !obj || - obj->Package.Count != 4) { - Genode::error("failed - '", __func__, "' _BST res=", Genode::Hex(res)); - return; - } - - Acpica::Buffer sta; - res = AcpiEvaluateObjectTyped(_sb, ACPI_STRING("_STA"), nullptr, - &sta, ACPI_TYPE_INTEGER); - if (ACPI_FAILURE(res)) { - xml.node("status", [&] { xml.append("unknown"); }); - } else - xml.node("status", [&] { - xml.attribute("value", sta.object.Integer.Value); - /* see "6.3.7 _STA" for more human readable decoding */ - if (!(sta.object.Integer.Value & ACPI_STA_BATTERY_PRESENT)) - xml.append("battery not present"); - }); - - const char * node_name[] = { - "state", "present_rate", "remaining_capacity", - "present_voltage" - }; - - if (sizeof(node_name) / sizeof(node_name[0]) != obj->Package.Count) - return; - - for (unsigned i = 0; i < obj->Package.Count; i++) { - ACPI_OBJECT * v = &obj->Package.Elements[i]; - - xml.node(node_name[i], [&] { - if (v->Type != ACPI_TYPE_INTEGER) { - xml.append("unknown"); - return; - } - - xml.attribute("value", v->Integer.Value); - - if (i != 0) - return; - - if (v->Integer.Value & 0x1) xml.append("discharging"); - if (v->Integer.Value & 0x2) xml.append("charging"); - if (v->Integer.Value & 0x4) xml.append("critical low"); - }); - } + _info(xml); + _status(xml); } };