app/acpi_event: update coding style

Remove exceptions, replace pointer lookup by with_ pattern,
use Xml_node::attribute_value, constness, naming of signal handlers

Issue #5245
This commit is contained in:
Norman Feske 2024-06-13 12:49:43 +02:00
parent 8a0689d832
commit dcddeccccc

View File

@ -82,303 +82,213 @@ class Transform::Keys : public Avl_node<Transform::Keys>
return diff;
}
static Keys * find_by(Avl_tree<Keys> &map, uint64_t acpi_code)
static auto with_key(Avl_tree<Keys> &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<Main> _dispatch_acpi_ac;
Signal_handler<Main> _dispatch_acpi_battery;
Signal_handler<Main> _dispatch_acpi_ec;
Signal_handler<Main> _dispatch_acpi_fixed;
Signal_handler<Main> _dispatch_acpi_lid;
Signal_handler<Main> _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<Main>
_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<Keys> _map_ec { };
Avl_tree<Keys> _map_hid { };
Avl_tree<Keys> _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<char>(), _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<Keys> &map,
char const * const name)
{
rom.update();
if (!rom.valid()) return;
Xml_node event(rom.local_addr<char>(), 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<char>(), _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<char>(),
_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<char>(), _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<char>(), _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);
}
};