diff --git a/repos/libports/src/app/acpi_event/main.cc b/repos/libports/src/app/acpi_event/main.cc index a879ca11e9..594ee95777 100644 --- a/repos/libports/src/app/acpi_event/main.cc +++ b/repos/libports/src/app/acpi_event/main.cc @@ -82,303 +82,213 @@ class Transform::Keys : public Avl_node return diff; } - static Keys * find_by(Avl_tree &map, uint64_t acpi_code) + static auto with_key(Avl_tree &map, uint64_t acpi_code, auto const &fn) { - Keys * head = map.first(); - if (!head) - return head; + if (!map.first()) + return; - return head->_find_by_acpi_value(acpi_code); + Keys * const key_ptr = map.first()->_find_by_acpi_value(acpi_code); + if (key_ptr) + fn(*key_ptr); } }; struct Transform::Main { + Env &_env; + enum { ACPI_POWER_BUTTON, ACPI_LID_OPEN, ACPI_LID_CLOSED, ACPI_AC_ONLINE, ACPI_AC_OFFLINE, ACPI_BATTERY }; - Heap _heap; + Heap _heap { _env.ram(), _env.rm() }; - Attached_rom_dataspace _config; - Attached_rom_dataspace _acpi_ac; - Attached_rom_dataspace _acpi_battery; - Attached_rom_dataspace _acpi_ec; - Attached_rom_dataspace _acpi_fixed; - Attached_rom_dataspace _acpi_lid; - Attached_rom_dataspace _acpi_hid; + Attached_rom_dataspace _config { _env, "config" }; - Signal_handler
_dispatch_acpi_ac; - Signal_handler
_dispatch_acpi_battery; - Signal_handler
_dispatch_acpi_ec; - Signal_handler
_dispatch_acpi_fixed; - Signal_handler
_dispatch_acpi_lid; - Signal_handler
_dispatch_acpi_hid; + Attached_rom_dataspace + _acpi_ac { _env, "acpi_ac" }, + _acpi_battery { _env, "acpi_battery" }, + _acpi_ec { _env, "acpi_ec" }, + _acpi_fixed { _env, "acpi_fixed" }, + _acpi_lid { _env, "acpi_lid" }, + _acpi_hid { _env, "acpi_hid" }; - Event::Connection _event; + Signal_handler
+ _acpi_ac_handler { _env.ep(), *this, &Main::_handle_acpi_ac }, + _acpi_battery_handler { _env.ep(), *this, &Main::_handle_acpi_battery }, + _acpi_ec_handler { _env.ep(), *this, &Main::_handle_acpi_ec }, + _acpi_fixed_handler { _env.ep(), *this, &Main::_handle_acpi_fixed }, + _acpi_lid_handler { _env.ep(), *this, &Main::_handle_acpi_lid }, + _acpi_hid_handler { _env.ep(), *this, &Main::_handle_acpi_hid }; + + Event::Connection _event { _env }; Avl_tree _map_ec { }; Avl_tree _map_hid { }; Avl_tree _map_special { }; - Main(Env &env) - : - _heap(env.ram(), env.rm()), - _config(env, "config"), - _acpi_ac(env, "acpi_ac"), - _acpi_battery(env, "acpi_battery"), - _acpi_ec(env, "acpi_ec"), - _acpi_fixed(env, "acpi_fixed"), - _acpi_lid(env, "acpi_lid"), - _acpi_hid(env, "acpi_hid"), - _dispatch_acpi_ac(env.ep(), *this, &Main::check_acpi_ac), - _dispatch_acpi_battery(env.ep(), *this, &Main::check_acpi_battery), - _dispatch_acpi_ec(env.ep(), *this, &Main::check_acpi_ec), - _dispatch_acpi_fixed(env.ep(), *this, &Main::check_acpi_fixed), - _dispatch_acpi_lid(env.ep(), *this, &Main::check_acpi_lid), - _dispatch_acpi_hid(env.ep(), *this, &Main::check_acpi_hid), - _event(env) + Main(Env &env) : _env(env) { - Xml_node config(_config.local_addr(), _config.size()); - config.for_each_sub_node("map", [&] (Xml_node map_node) { - try { - uint64_t acpi_value = 0; - String<8> acpi_type; - String<8> acpi_value_string; - Input::Key_name to_key; + _config.xml().for_each_sub_node("map", [&] (Xml_node const &map_node) { - String<16> key_type("PRESS_RELEASE"); - Keys::Type press_release = Keys::Type::PRESS_RELEASE; + auto const acpi_type = map_node.attribute_value("acpi", String<8>()); + auto const to_key = map_node.attribute_value("to_key", Input::Key_name()); + auto const value_string = map_node.attribute_value("value", String<8>()); + auto const key_type = map_node.attribute_value("as", String<16>("PRESS_RELEASE")); - map_node.attribute("acpi").value(acpi_type); - map_node.attribute("to_key").value(to_key); - try { - map_node.attribute("as").value(key_type); - if (key_type == "PRESS") - press_release = Keys::Type::PRESS; - else if (key_type == "RELEASE") - press_release = Keys::Type::RELEASE; - else if (key_type != "PRESS_RELEASE") - throw 0; - } catch (Xml_node::Nonexistent_attribute) { } + auto press_release = [&] () -> Keys::Type + { + if (key_type == "PRESS") return Keys::Type::PRESS; + if (key_type == "RELEASE") return Keys::Type::RELEASE; + warning("unsupported 'as' attribute value \"", key_type, "\""); + return Keys::Type::PRESS_RELEASE; + }; - if (acpi_type == "lid" || acpi_type == "ac") { - map_node.attribute("value").value(acpi_value_string); + auto acpi_value = [&] () -> uint64_t + { + if (acpi_type == "lid") { + if (value_string == "OPEN") return ACPI_LID_OPEN; + if (value_string == "CLOSED") return ACPI_LID_CLOSED; + warning("unsupported lid value \"", value_string, "\""); + } + if (acpi_type == "ac") { + if (value_string == "ONLINE") return ACPI_AC_ONLINE; + if (value_string == "OFFLINE") return ACPI_AC_OFFLINE; + warning("unsupported ac value \"", value_string, "\""); + } + return map_node.attribute_value("value", uint64_t(0)); + }; - if (acpi_type == "lid") { - if (acpi_value_string == "OPEN") - acpi_value = ACPI_LID_OPEN; - else if (acpi_value_string == "CLOSED") - acpi_value = ACPI_LID_CLOSED; - else throw 1; - } else - if (acpi_type == "ac") { - if (acpi_value_string == "ONLINE") - acpi_value = ACPI_AC_ONLINE; - else if (acpi_value_string == "OFFLINE") - acpi_value = ACPI_AC_OFFLINE; - else throw 2; - } else - throw 3; - } else - map_node.attribute("value").value(acpi_value); - - Input::Keycode key_code = Input::key_code(to_key); - - if (key_code == Input::Keycode::KEY_UNKNOWN) - throw 4; - - if (acpi_type == "ec") - _map_ec.insert(new (_heap) Keys(key_code, acpi_value, - press_release)); - else if (acpi_type == "fixed") - _map_special.insert(new (_heap) Keys(key_code, - ACPI_POWER_BUTTON, - press_release)); - else if (acpi_type == "lid" || acpi_type == "ac") - _map_special.insert(new (_heap) Keys(key_code, acpi_value, - press_release)); - else if (acpi_type == "battery") - _map_special.insert(new (_heap) Keys(key_code, - ACPI_BATTERY, - press_release)); - else if (acpi_type == "hid") - _map_hid.insert(new (_heap) Keys(key_code, acpi_value, - press_release)); - else - throw 5; - } catch (...) { - - /* abort on malformed configuration */ - error("map item '", map_node, "' Aborting..."); - env.parent().exit(1); + Input::Keycode const key_code = Input::key_code(to_key); + if (key_code == Input::Keycode::KEY_UNKNOWN) { + warning("unsupported 'to_key' attribute value \"", to_key, "\""); + return; } + + if (acpi_type == "ec") + _map_ec.insert(new (_heap) Keys(key_code, acpi_value(), + press_release())); + else if (acpi_type == "fixed") + _map_special.insert(new (_heap) Keys(key_code, + ACPI_POWER_BUTTON, + press_release())); + else if (acpi_type == "lid" || acpi_type == "ac") + _map_special.insert(new (_heap) Keys(key_code, acpi_value(), + press_release())); + else if (acpi_type == "battery") + _map_special.insert(new (_heap) Keys(key_code, + ACPI_BATTERY, + press_release())); + else if (acpi_type == "hid") + _map_hid.insert(new (_heap) Keys(key_code, acpi_value(), + press_release())); + else + warning("unsupported 'acpi' attribute value \"", acpi_type, "\""); }); - _acpi_ac.sigh(_dispatch_acpi_ac); - _acpi_battery.sigh(_dispatch_acpi_battery); - _acpi_ec.sigh(_dispatch_acpi_ec); - _acpi_fixed.sigh(_dispatch_acpi_fixed); - _acpi_lid.sigh(_dispatch_acpi_lid); - _acpi_hid.sigh(_dispatch_acpi_hid); + _acpi_ac .sigh(_acpi_ac_handler); + _acpi_battery.sigh(_acpi_battery_handler); + _acpi_ec .sigh(_acpi_ec_handler); + _acpi_fixed .sigh(_acpi_fixed_handler); + _acpi_lid .sigh(_acpi_lid_handler); + _acpi_hid .sigh(_acpi_hid_handler); /* check for initial valid ACPI data */ - check_acpi_ac(); - check_acpi_battery(); - check_acpi_ec(); - check_acpi_fixed(); - check_acpi_lid(); - check_acpi_hid(); + _handle_acpi_ac(); + _handle_acpi_battery(); + _handle_acpi_ec(); + _handle_acpi_fixed(); + _handle_acpi_lid(); + _handle_acpi_hid(); + } + + void submit_input(Keys &key) + { + _event.with_batch([&] (Event::Session_client::Batch &batch) { + + if (key.type() == Keys::Type::PRESS_RELEASE || + key.type() == Keys::Type::PRESS) + batch.submit(Input::Press{key.key_code()}); + + if (key.type() == Keys::Type::PRESS_RELEASE || + key.type() == Keys::Type::RELEASE) + batch.submit(Input::Release{key.key_code()}); + }); } void _check_acpi(Attached_rom_dataspace &rom, Avl_tree &map, char const * const name) { rom.update(); - - if (!rom.valid()) return; - - Xml_node event(rom.local_addr(), rom.size()); - - event.for_each_sub_node(name, [&] (Xml_node const &node) { + rom.xml().for_each_sub_node(name, [&] (Xml_node const &node) { node.for_each_sub_node("data", [&] (Xml_node const &data_node) { - try { - uint64_t acpi_value = 0; - uint64_t acpi_count = 0; + uint64_t const value = data_node.attribute_value("value", 0ULL); + uint64_t const count = data_node.attribute_value("count", 0ULL); - data_node.attribute("value").value(acpi_value); - data_node.attribute("count").value(acpi_count); - - Keys * key = Keys::find_by(map, acpi_value); - if (!key) - return; - - if (!key->update_count(acpi_count)) - return; - - submit_input(key); - } catch (...) { /* be robust - ignore ill-formated ACPI data */ } + Keys::with_key(map, value, [&] (Keys &key) { + if (key.update_count(count)) + submit_input(key); }); }); }); } - void check_acpi_ec() { _check_acpi(_acpi_ec, _map_ec, "ec"); } - - void check_acpi_hid() { _check_acpi(_acpi_hid, _map_hid, "hid"); } - - void submit_input(Keys * key) + void _check_acpi(Xml_node const &xml_node, const char * const sub_name, + unsigned const state_o, unsigned const state_c) { - _event.with_batch([&] (Event::Session_client::Batch &batch) { + xml_node.for_each_sub_node(sub_name, [&] (Xml_node const &node) { + uint64_t const value = node.attribute_value("value", 0ULL); + uint64_t const count = node.attribute_value("count", 0ULL); - if (!key) + uint64_t const STATE_C = 0, STATE_O = 1; + + if (value != STATE_O && value != STATE_C) return; - if (key->type() == Keys::Type::PRESS_RELEASE || - key->type() == Keys::Type::PRESS) - batch.submit(Input::Press{key->key_code()}); + unsigned const state = (value == STATE_O) ? state_o : state_c; - if (key->type() == Keys::Type::PRESS_RELEASE || - key->type() == Keys::Type::RELEASE) - batch.submit(Input::Release{key->key_code()}); + Keys::with_key(_map_special, state, [&] (Keys &key) { + if (key.update_count(count)) + submit_input(key); }); }); } - void check_acpi_fixed() + void _handle_acpi_ec() { _check_acpi(_acpi_ec, _map_ec, "ec"); } + + void _handle_acpi_hid() { _check_acpi(_acpi_hid, _map_hid, "hid"); } + + void _handle_acpi_fixed() { _acpi_fixed.update(); + Keys::with_key(_map_special, ACPI_POWER_BUTTON, [&] (Keys &key) { + _acpi_fixed.xml().for_each_sub_node("power_button", [&] (Xml_node const &pw) { + bool const pressed = pw.attribute_value("value", false); + uint64_t const count = pw.attribute_value("count", 0UL); - if (!_acpi_fixed.valid()) return; - - Xml_node fixed_event(_acpi_fixed.local_addr(), _acpi_fixed.size()); - - fixed_event.for_each_sub_node("power_button", [&] (Xml_node pw_node) { - try { - bool pressed = false; - uint64_t acpi_count = 0; - - pw_node.attribute("value").value(pressed); - pw_node.attribute("count").value(acpi_count); - - Keys * key = Keys::find_by(_map_special, ACPI_POWER_BUTTON); - if (!key) - return; - - if (!key->update_count(acpi_count) && pressed) - return; - - submit_input(key); - } catch (...) { /* be robust - ignore ill-formated ACPI data */ } + if (key.update_count(count) && pressed) + submit_input(key); + }); }); } - void check_acpi_battery() + void _handle_acpi_battery() { _acpi_battery.update(); - - if (!_acpi_battery.valid()) return; - - /* make use of it if we need to ... */ - Xml_node battery_node(_acpi_battery.local_addr(), - _acpi_battery.size()); - - submit_input(Keys::find_by(_map_special, ACPI_BATTERY)); + Keys::with_key(_map_special, ACPI_BATTERY, [&] (Keys &key) { + submit_input(key); }); } - void check_acpi_ac() + void _handle_acpi_ac() { _acpi_ac.update(); - - if (!_acpi_ac.valid()) return; - - Xml_node ac_node(_acpi_ac.local_addr(), _acpi_ac.size()); - - _check_acpi(ac_node, "ac", ACPI_AC_ONLINE, ACPI_AC_OFFLINE); + _check_acpi(_acpi_ac.xml(), "ac", ACPI_AC_ONLINE, ACPI_AC_OFFLINE); } - void check_acpi_lid() + void _handle_acpi_lid() { _acpi_lid.update(); - - if (!_acpi_lid.valid()) return; - - Xml_node lid_node(_acpi_lid.local_addr(), _acpi_lid.size()); - - _check_acpi(lid_node, "lid", ACPI_LID_OPEN, ACPI_LID_CLOSED); - } - - void _check_acpi(Xml_node &xml_node, const char * sub_name, - const unsigned state_o, const unsigned state_c) - { - xml_node.for_each_sub_node(sub_name, [&] (Xml_node node) { - try { - uint64_t acpi_value = 0; - uint64_t acpi_count = 0; - - node.attribute("value").value(acpi_value); - node.attribute("count").value(acpi_count); - - enum { STATE_C = 0, STATE_O = 1 }; - - Keys * key = nullptr; - if (acpi_value == STATE_O) - key = Keys::find_by(_map_special, state_o); - if (acpi_value == STATE_C) - key = Keys::find_by(_map_special, state_c); - if (!key) - return; - - if (!key->update_count(acpi_count)) - return; - - if (acpi_value == STATE_C) - submit_input(key); - - if (acpi_value == STATE_O) - submit_input(key); - } catch (...) { /* be robust - ignore ill-formated ACPI data */ } - }); + _check_acpi(_acpi_lid.xml(), "lid", ACPI_LID_OPEN, ACPI_LID_CLOSED); } };