mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-19 05:37:54 +00:00
acpica: add limited support for FUJ02E3 ACPI dev
The keys, mute, touchpad toggle (Fn-F4) and rfkill may be reported by some Fujitsu machines via the ACPI FUJ02E3 ACPI device. With this commit limited support to detect the 3 keys are added and will be reported as Genode report.
This commit is contained in:
parent
d698e0876d
commit
1147f35972
195
repos/libports/src/app/acpica/fujitsu.h
Normal file
195
repos/libports/src/app/acpica/fujitsu.h
Normal file
@ -0,0 +1,195 @@
|
||||
/*
|
||||
* \brief Support some Fujitsu ACPI devices
|
||||
* \author Alexander Boettcher
|
||||
* \date 2021-01-06
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2020-2021 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
*/
|
||||
|
||||
class Fuj02e3 : public Acpica::Reporter, Acpica::Callback<Fuj02e3>
|
||||
{
|
||||
private:
|
||||
|
||||
enum {
|
||||
HID_FUJITSU_NOTIFY = 0x80,
|
||||
};
|
||||
|
||||
enum Softkeys {
|
||||
HID_FUJITSU_FLAG_RFKILL = 1u << 5,
|
||||
HID_FUJITSU_FLAG_TOUCHPAD_TOGGLE = 1u << 26,
|
||||
HID_FUJITSU_FLAG_MICROFON_MUTE = 1u << 29,
|
||||
|
||||
HID_FUJITSU_FLAG_SOFTKEYS = HID_FUJITSU_FLAG_RFKILL |
|
||||
HID_FUJITSU_FLAG_TOUCHPAD_TOGGLE |
|
||||
HID_FUJITSU_FLAG_MICROFON_MUTE
|
||||
};
|
||||
|
||||
enum Operation {
|
||||
HID_FUJITSU_FUNC_FLAGS = 1u << 12,
|
||||
HID_FUJITSU_FUNC_BUTTON = HID_FUJITSU_FUNC_FLAGS | 2,
|
||||
};
|
||||
|
||||
Acpica::Reportstate *_report;
|
||||
Genode::uint64_t _features { 0 };
|
||||
|
||||
struct Data
|
||||
{
|
||||
Genode::uint64_t count;
|
||||
Genode::uint64_t data;
|
||||
bool triggered;
|
||||
} _data[3] { };
|
||||
|
||||
template <typename RESULT>
|
||||
ACPI_STATUS _call_acpi_function(ACPI_HANDLE const hid,
|
||||
enum Operation const function,
|
||||
RESULT &result, unsigned const op,
|
||||
unsigned const feature,
|
||||
unsigned const state)
|
||||
{
|
||||
ACPI_OBJECT_LIST para_in;
|
||||
ACPI_OBJECT values[5];
|
||||
|
||||
values[0].Type = ACPI_TYPE_INTEGER;
|
||||
values[0].Integer.Value = function;
|
||||
values[1].Type = ACPI_TYPE_INTEGER;
|
||||
values[1].Integer.Value = op;
|
||||
values[2].Type = ACPI_TYPE_INTEGER;
|
||||
values[2].Integer.Value = feature;
|
||||
values[3].Type = ACPI_TYPE_INTEGER;
|
||||
values[3].Integer.Value = state;
|
||||
values[4].Type = 0;
|
||||
values[4].Integer.Value = 0;
|
||||
|
||||
para_in.Count = 4;
|
||||
para_in.Pointer = values;
|
||||
|
||||
return AcpiEvaluateObjectTyped(hid, ACPI_STRING("FUNC"),
|
||||
¶_in, &result,
|
||||
ACPI_TYPE_INTEGER);
|
||||
}
|
||||
|
||||
template <typename RESULT>
|
||||
ACPI_STATUS device_features(ACPI_HANDLE const hid, RESULT &result)
|
||||
{
|
||||
return _call_acpi_function(hid, HID_FUJITSU_FUNC_FLAGS, result,
|
||||
0, 0, 0);
|
||||
}
|
||||
|
||||
template <typename RESULT>
|
||||
ACPI_STATUS soft_keys(ACPI_HANDLE const hid, RESULT &result)
|
||||
{
|
||||
return _call_acpi_function(hid, HID_FUJITSU_FUNC_FLAGS, result,
|
||||
1, 0, 0);
|
||||
}
|
||||
|
||||
template <typename RESULT>
|
||||
ACPI_STATUS read_button(ACPI_HANDLE const hid, RESULT &result)
|
||||
{
|
||||
return _call_acpi_function(hid, HID_FUJITSU_FUNC_BUTTON, result,
|
||||
1, 0, 0);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Fuj02e3(void *report)
|
||||
: _report(reinterpret_cast<Acpica::Reportstate *>(report))
|
||||
{
|
||||
if (_report)
|
||||
_report->add_notify(this);
|
||||
}
|
||||
|
||||
void handle(ACPI_HANDLE const hid, UINT32 const value)
|
||||
{
|
||||
if (value != HID_FUJITSU_NOTIFY)
|
||||
return;
|
||||
|
||||
Acpica::Buffer<ACPI_OBJECT> irb;
|
||||
ACPI_STATUS res = read_button(hid, irb);
|
||||
if (ACPI_SUCCESS(res) && irb.object.Integer.Value != 0)
|
||||
Genode::error("not implemented - irb value=",
|
||||
Genode::Hex(irb.object.Integer.Value));
|
||||
|
||||
if (_features & HID_FUJITSU_FLAG_SOFTKEYS) {
|
||||
Acpica::Buffer<ACPI_OBJECT> feature;
|
||||
ACPI_STATUS res = soft_keys(hid, feature);
|
||||
|
||||
if (ACPI_SUCCESS(res))
|
||||
{
|
||||
UINT64 const value = feature.object.Integer.Value;
|
||||
|
||||
if (value & HID_FUJITSU_FLAG_RFKILL) {
|
||||
_data[0].data = HID_FUJITSU_FLAG_RFKILL;
|
||||
_data[0].triggered = true;
|
||||
_data[0].count ++;
|
||||
}
|
||||
|
||||
if (value & HID_FUJITSU_FLAG_TOUCHPAD_TOGGLE) {
|
||||
_data[1].data = HID_FUJITSU_FLAG_TOUCHPAD_TOGGLE;
|
||||
_data[1].triggered = true;
|
||||
_data[1].count ++;
|
||||
}
|
||||
|
||||
if (value & HID_FUJITSU_FLAG_MICROFON_MUTE) {
|
||||
_data[2].data = HID_FUJITSU_FLAG_MICROFON_MUTE;
|
||||
_data[2].triggered = true;
|
||||
_data[2].count ++;
|
||||
}
|
||||
|
||||
if (_report && (value & HID_FUJITSU_FLAG_SOFTKEYS))
|
||||
_report->hid_event();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static ACPI_STATUS detect(ACPI_HANDLE hid, UINT32, void *m, void **)
|
||||
{
|
||||
Acpica::Main *main = reinterpret_cast<Acpica::Main *>(m);
|
||||
Fuj02e3 *obj = new (main->heap) Fuj02e3(main->report);
|
||||
|
||||
ACPI_STATUS res = AcpiInstallNotifyHandler(hid, ACPI_DEVICE_NOTIFY,
|
||||
handler, obj);
|
||||
if (ACPI_FAILURE(res)) {
|
||||
Genode::log("failed - ", __func__, " "
|
||||
"res=", Genode::Hex(res), " Fujitsu adapter");
|
||||
delete obj;
|
||||
return AE_OK;
|
||||
}
|
||||
|
||||
Genode::log("detected - Fujitsu HID");
|
||||
|
||||
Acpica::Buffer<ACPI_OBJECT> features;
|
||||
res = obj->device_features(hid, features);
|
||||
if (ACPI_FAILURE(res)) {
|
||||
Genode::error("failed - '", __func__, "' "
|
||||
"res=", Genode::Hex(res), " features");
|
||||
}
|
||||
|
||||
obj->_features = features.object.Integer.Value;
|
||||
|
||||
return AE_OK;
|
||||
}
|
||||
|
||||
void generate(Genode::Xml_generator &xml) override
|
||||
{
|
||||
xml.node("hid", [&] {
|
||||
xml.attribute("device", "Fuj02e3");
|
||||
|
||||
for (unsigned i = 0; i < sizeof(_data) / sizeof(_data[0]); i++) {
|
||||
|
||||
xml.node("data", [&] {
|
||||
xml.attribute("value", Genode::String<12>(Genode::Hex(_data[i].data)));
|
||||
xml.attribute("count", _data[i].count);
|
||||
if (_data[i].triggered) {
|
||||
xml.append("triggered");
|
||||
_data[i].triggered = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
@ -210,6 +210,7 @@ struct Acpica::Main
|
||||
#include "sb.h"
|
||||
#include "ec.h"
|
||||
#include "bridge.h"
|
||||
#include "fujitsu.h"
|
||||
|
||||
ACPI_STATUS init_pic_mode()
|
||||
{
|
||||
@ -250,7 +251,12 @@ void Acpica::Main::init_acpica(Wait_acpi_ready wait_acpi_ready,
|
||||
Acpica::init(env, heap, wait_acpi_ready, act_as_acpi_drv);
|
||||
|
||||
/* enable debugging: */
|
||||
/* AcpiDbgLevel |= ACPI_LV_IO | ACPI_LV_INTERRUPTS | ACPI_LV_INIT_NAMES; */
|
||||
if (false) {
|
||||
AcpiDbgLevel |= ACPI_LV_IO | ACPI_LV_INTERRUPTS | ACPI_LV_INIT_NAMES;
|
||||
AcpiDbgLayer |= ACPI_TABLES;
|
||||
Genode::log("debugging level=", Genode::Hex(AcpiDbgLevel),
|
||||
" layers=", Genode::Hex(AcpiDbgLayer));
|
||||
}
|
||||
|
||||
ACPI_STATUS status = AcpiInitializeSubsystem();
|
||||
if (status != AE_OK) {
|
||||
@ -351,6 +357,13 @@ void Acpica::Main::init_acpica(Wait_acpi_ready wait_acpi_ready,
|
||||
return;
|
||||
}
|
||||
|
||||
/* Fujitsu HID device */
|
||||
status = AcpiGetDevices(ACPI_STRING("FUJ02E3"), Fuj02e3::detect, this, nullptr);
|
||||
if (status != AE_OK) {
|
||||
Genode::error("AcpiGetDevices (FUJ02E3) failed, status=", status);
|
||||
return;
|
||||
}
|
||||
|
||||
if (act_as_acpi_drv.enabled) {
|
||||
/* lookup PCI root bridge */
|
||||
void * pci_bridge = (void *)PCI_ROOT_HID_STRING;
|
||||
|
@ -6,7 +6,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2016-2017 Genode Labs GmbH
|
||||
* Copyright (C) 2016-2021 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
@ -18,6 +18,22 @@ class Ec;
|
||||
class Fixed;
|
||||
class Lid;
|
||||
|
||||
namespace Acpica {
|
||||
class Reportstate;
|
||||
class Reporter;
|
||||
};
|
||||
|
||||
class Acpica::Reporter : public Genode::List<Acpica::Reporter >::Element
|
||||
{
|
||||
public:
|
||||
|
||||
Reporter() { }
|
||||
|
||||
virtual void generate(Genode::Xml_generator &) = 0;
|
||||
virtual ~Reporter() { }
|
||||
};
|
||||
|
||||
|
||||
class Acpica::Reportstate {
|
||||
|
||||
private:
|
||||
@ -27,18 +43,21 @@ class Acpica::Reportstate {
|
||||
Genode::Reporter _reporter_sb;
|
||||
Genode::Reporter _reporter_ec;
|
||||
Genode::Reporter _reporter_fix;
|
||||
Genode::Reporter _reporter_hid;
|
||||
|
||||
bool _changed_lid = false;
|
||||
bool _changed_ac = false;
|
||||
bool _changed_sb = false;
|
||||
bool _changed_ec = false;
|
||||
bool _changed_fixed = false;
|
||||
bool _changed_hid = false;
|
||||
|
||||
Genode::List<Callback<Battery> > _list_sb;
|
||||
Genode::List<Callback<Ec> > _list_ec;
|
||||
Genode::List<Callback<Ac> > _list_ac;
|
||||
Callback<Fixed> * _fixed;
|
||||
Callback<Lid> * _lid;
|
||||
Genode::List<Callback<Battery> > _list_sb;
|
||||
Genode::List<Callback<Ec> > _list_ec;
|
||||
Genode::List<Callback<Ac> > _list_ac;
|
||||
Genode::List<Acpica::Reporter> _list_hid;
|
||||
Callback<Fixed> * _fixed;
|
||||
Callback<Lid> * _lid;
|
||||
|
||||
public:
|
||||
|
||||
@ -48,7 +67,8 @@ class Acpica::Reportstate {
|
||||
_reporter_ac (env, "acpi_ac"),
|
||||
_reporter_sb (env, "acpi_battery"),
|
||||
_reporter_ec (env, "acpi_ec"),
|
||||
_reporter_fix(env, "acpi_fixed")
|
||||
_reporter_fix(env, "acpi_fixed"),
|
||||
_reporter_hid(env, "acpi_hid")
|
||||
{ }
|
||||
|
||||
void add_notify(Acpica::Callback<Battery> * s) { _list_sb.insert(s); }
|
||||
@ -56,6 +76,7 @@ class Acpica::Reportstate {
|
||||
void add_notify(Acpica::Callback<Lid> * l) { _lid = l; }
|
||||
void add_notify(Acpica::Callback<Ec> * e) { _list_ec.insert(e); }
|
||||
void add_notify(Acpica::Callback<Ac> * a) { _list_ac.insert(a); }
|
||||
void add_notify(Acpica::Reporter * r) { _list_hid.insert(r); }
|
||||
|
||||
void enable() {
|
||||
_reporter_ac.enabled(true);
|
||||
@ -63,6 +84,7 @@ class Acpica::Reportstate {
|
||||
_reporter_sb.enabled(true);
|
||||
_reporter_lid.enabled(true);
|
||||
_reporter_fix.enabled(true);
|
||||
_reporter_hid.enabled(true);
|
||||
}
|
||||
|
||||
void battery_event() { _changed_sb = true; }
|
||||
@ -70,6 +92,7 @@ class Acpica::Reportstate {
|
||||
void fixed_event() { _changed_fixed = true; }
|
||||
void lid_event() { _changed_lid = true; }
|
||||
void ac_event() { _changed_ac = true; battery_event(); }
|
||||
void hid_event() { _changed_hid = true; }
|
||||
|
||||
bool generate_report(bool force = false)
|
||||
{
|
||||
@ -116,6 +139,16 @@ class Acpica::Reportstate {
|
||||
});
|
||||
}
|
||||
|
||||
if (_changed_hid || force) {
|
||||
_changed_hid = false;
|
||||
|
||||
if (_list_hid.first())
|
||||
Genode::Reporter::Xml_generator xml(_reporter_hid, [&] () {
|
||||
for (auto * hid = _list_hid.first(); hid; hid = hid->next())
|
||||
hid->generate(xml);
|
||||
});
|
||||
}
|
||||
|
||||
return changed;
|
||||
}
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user