This is an automated email from the git hooks/post-receive script.
git pushed a commit to branch master
in repository enlightenment.
View the commit online.
commit 512669d31d392f9b1c8e5a206be81d463b93976e
Author: Carsten Haitzler <ras...@rasterman.com>
AuthorDate: Sat Dec 14 20:33:39 2024 +0000
acpi - we no longer need acpid, e_system now does it for us
e_system does what acpid does - looks at inopuit devices on linux and
listens to them (only specific events/keycodes).
acpid now is no longer used/needed
---
src/bin/e_acpi.c | 485 ++++++++++++-----------------------------
src/bin/system/e_system.h | 3 +
src/bin/system/e_system_acpi.c | 246 +++++++++++++++++++++
src/bin/system/e_system_main.c | 2 +
src/bin/system/meson.build | 1 +
5 files changed, 396 insertions(+), 341 deletions(-)
diff --git a/src/bin/e_acpi.c b/src/bin/e_acpi.c
index 221a0592c..a39f33f82 100644
--- a/src/bin/e_acpi.c
+++ b/src/bin/e_acpi.c
@@ -1,20 +1,9 @@
#include "e.h"
-/* TODO:
- *
- * Sanatize data received from acpi for message status into something
- * meaningful (ie: 00000002 == LID_CLOSED, etc, etc).
- *
- * Find someone with a WIFI that actually emits ACPI events and add/debug the
- * E_EVENT_ACPI for wifi.
- *
- */
-
/* local structures */
/* for simple acpi device mapping */
typedef struct _E_ACPI_Device_Simple E_ACPI_Device_Simple;
typedef struct _E_ACPI_Device_Simple_State E_ACPI_Device_Simple_State;
-typedef struct _E_ACPI_Device_Multiplexed E_ACPI_Device_Multiplexed;
struct _E_ACPI_Device_Simple
{
@@ -32,34 +21,21 @@ struct _E_ACPI_Device_Simple_State
int type;
};
-struct _E_ACPI_Device_Multiplexed
-{
- const char *name;
- const char *bus;
- int status;
- // ->
- int type;
-};
-
/* local function prototypes */
-static Eina_Bool _e_acpi_cb_server_del(void *data EINA_UNUSED, int type EINA_UNUSED, void *event);
-static Eina_Bool _e_acpi_cb_server_data(void *data EINA_UNUSED, int type EINA_UNUSED, void *event);
static void _e_acpi_cb_event_free(void *data EINA_UNUSED, void *event);
static int _e_acpi_lid_status_get(const char *device, const char *bus);
static Eina_Bool _e_acpi_cb_event(void *data EINA_UNUSED, int type EINA_UNUSED, void *event);
/* local variables */
static int _e_acpi_events_frozen = 0;
-static Ecore_Con_Server *_e_acpid = NULL;
static Eina_List *_e_acpid_hdls = NULL;
-static Eina_Strbuf *acpibuf = NULL;
static int lid_is_closed = -1;
static E_ACPI_Device_Simple _devices_simple[] =
{
/* NB: DO NOT TRANSLATE THESE. */
- {"ac_adapter", E_ACPI_TYPE_AC_ADAPTER},
- {"battery", E_ACPI_TYPE_BATTERY},
+// {"ac_adapter", E_ACPI_TYPE_AC_ADAPTER},
+// {"battery", E_ACPI_TYPE_BATTERY},
{"button/lid", E_ACPI_TYPE_LID},
{"button/power", E_ACPI_TYPE_POWER},
{"button/sleep", E_ACPI_TYPE_SLEEP},
@@ -67,10 +43,10 @@ static E_ACPI_Device_Simple _devices_simple[] =
{"button/volumeup", E_ACPI_TYPE_VOLUME_UP},
{"button/mute", E_ACPI_TYPE_MUTE},
{"button/wlan", E_ACPI_TYPE_WIFI},
- {"fan", E_ACPI_TYPE_FAN},
- {"processor", E_ACPI_TYPE_PROCESSOR},
- {"thermal_zone", E_ACPI_TYPE_THERMAL},
- {"video", E_ACPI_TYPE_VIDEO},
+// {"fan", E_ACPI_TYPE_FAN},
+// {"processor", E_ACPI_TYPE_PROCESSOR},
+// {"thermal_zone", E_ACPI_TYPE_THERMAL},
+// {"video", E_ACPI_TYPE_VIDEO},
{"video/brightnessdown", E_ACPI_TYPE_BRIGHTNESS_DOWN},
{"video/brightnessup", E_ACPI_TYPE_BRIGHTNESS_UP},
{"video/switchmode", E_ACPI_TYPE_VIDEO},
@@ -97,50 +73,146 @@ static E_ACPI_Device_Simple_State _devices_simple_state[] =
{NULL, NULL, NULL, E_ACPI_TYPE_UNKNOWN}
};
-static E_ACPI_Device_Multiplexed _devices_multiplexed[] =
-{
- /* NB: DO NOT TRANSLATE THESE. */
-/* Sony VAIO - VPCF115FM / PCG-81114L - nvidia gfx */
- {"sony/hotkey", NULL, 0x10, E_ACPI_TYPE_BRIGHTNESS_DOWN},
- {"sony/hotkey", NULL, 0x11, E_ACPI_TYPE_BRIGHTNESS_UP},
- {"sony/hotkey", NULL, 0x12, E_ACPI_TYPE_VIDEO},
- {"sony/hotkey", NULL, 0x14, E_ACPI_TYPE_ZOOM_OUT},
- {"sony/hotkey", NULL, 0x15, E_ACPI_TYPE_ZOOM_IN},
- {"sony/hotkey", NULL, 0x17, E_ACPI_TYPE_HIBERNATE},
- {"sony/hotkey", NULL, 0xa6, E_ACPI_TYPE_ASSIST},
- {"sony/hotkey", NULL, 0x20, E_ACPI_TYPE_S1},
- {"sony/hotkey", NULL, 0xa5, E_ACPI_TYPE_VAIO},
-
-/* Sony VAIO - X505 - intel gfx */
- {"sony/hotkey", NULL, 0x0e, E_ACPI_TYPE_MUTE},
- {"sony/hotkey", NULL, 0x0f, E_ACPI_TYPE_VOLUME},
- {"sony/hotkey", NULL, 0x10, E_ACPI_TYPE_BRIGHTNESS},
- {"sony/hotkey", NULL, 0x12, E_ACPI_TYPE_VIDEO},
-
-/* HP Compaq Presario - CQ61 - intel gfx */
-/** interesting these get auto-mapped to keys in x11. here for documentation
-** but not enabled as we can use regular keybinds for these
- {"video", "DD03", 0x87, E_ACPI_TYPE_BRIGHTNESS_DOWN},
- {"video", "DD03", 0x86, E_ACPI_TYPE_BRIGHTNESS_UP},
- {"video", "OVGA", 0x80, E_ACPI_TYPE_VIDEO},
-*/
-/* END */
- {NULL, NULL, 0x00, E_ACPI_TYPE_UNKNOWN}
-};
-
/* public variables */
E_API int E_EVENT_ACPI = 0;
-static Eina_Bool
-_acpi_error_cb(void *data EINA_UNUSED)
+static void
+_cb_sys_acpi_event(void *data EINA_UNUSED, const char *params)
{
- e_util_dialog_show
- (_("ACPI Error"),
- _("You seem to have an ACPI based system, but<br>"
- "<hilight>acpid</hilight> does not seem to be running or<br>"
- "contactable. Perhaps enable the <hilight>acpid</hilight><br>"
- "service on your system?"));
- return EINA_FALSE;
+ E_Event_Acpi *acpi_event;
+ int sig, status, i, done = 0;
+ char device[1024], bus[1024], state[1024];
+
+ printf("ACPI: [%s]\n", params);
+ // parse out this acpi string into separate pieces
+ if (sscanf(params, "%1023s %1023s %x %x", device, bus, &sig, &status) != 4)
+ {
+ sig = -1;
+ status = -1;
+ if (sscanf(params, "%1023s %1023s", device, bus) != 2)
+ {
+ if (sscanf(params, "%1023s %1023s %1023s", device, bus, state) != 3)
+ return;
+ }
+ }
+ // create new event structure to raise
+ acpi_event = E_NEW(E_Event_Acpi, 1);
+ acpi_event->bus_id = eina_stringshare_add(bus);
+ acpi_event->signal = sig;
+ acpi_event->status = status;
+
+ if ((!done) && (state[0]))
+ {
+ for (i = 0; _devices_simple_state[i].name; i++)
+ {
+ if ((!strcmp(device, _devices_simple_state[i].name))
+ && ((!_devices_simple_state[i].bus)
+ || (!strcmp(bus, _devices_simple_state[i].bus)))
+ && (!strcmp(state, _devices_simple_state[i].state)))
+ {
+ acpi_event->type = _devices_simple_state[i].type;
+ done = 1;
+ break;
+ }
+ }
+ }
+ if (!done)
+ {
+ // if device name matches
+ for (i = 0; _devices_simple[i].name; i++)
+ {
+ if (!strcmp(device, _devices_simple[i].name))
+ {
+ acpi_event->type = _devices_simple[i].type;
+ done = 1;
+ break;
+ }
+ }
+ }
+ if (!done) free(acpi_event);
+ else
+ {
+ switch (acpi_event->type)
+ {
+ case E_ACPI_TYPE_LID:
+ acpi_event->status = _e_acpi_lid_status_get(device, bus);
+ printf("RRR: acpi event @%1.8f\n", ecore_time_get());
+ /* no change in lid state */
+ if (lid_is_closed == (acpi_event->status == E_ACPI_LID_CLOSED))
+ break;
+ lid_is_closed = (acpi_event->status == E_ACPI_LID_CLOSED);
+ printf("RRR: lid event for lid %i\n", lid_is_closed);
+ if (!e_randr2_cfg->ignore_acpi_events)
+ e_randr2_screen_refresh_queue(EINA_TRUE);
+ if (!lid_is_closed) e_powersave_defer_cancel();
+ break;
+ default:
+ break;
+ }
+ /* actually raise the event */
+ ecore_event_add(E_EVENT_ACPI, acpi_event, _e_acpi_cb_event_free,
+ NULL);
+ }
+}
+
+static void
+_e_acpi_cb_event_free(void *data EINA_UNUSED, void *event)
+{
+ E_Event_Acpi *ev = event;
+ if (!ev) return;
+ if (ev->device) eina_stringshare_del(ev->device);
+ if (ev->bus_id) eina_stringshare_del(ev->bus_id);
+ E_FREE(ev);
+}
+
+static int
+_e_acpi_lid_status_get(const char *device, const char *bus)
+{
+ FILE *f;
+ int i = 0;
+ char buff[PATH_MAX], *ret;
+
+ /* the acpi driver code in the kernel has a nice acpi function to return
+ * the lid status easily, but that function is not exposed for user_space
+ * so we need to check the proc fs to get the actual status */
+ // make sure we have a device and bus
+ if ((!device) || (!bus)) return E_ACPI_LID_UNKNOWN;
+ // open the state file from /proc
+ snprintf(buff, sizeof(buff), "/proc/acpi/%s/%s/state", device, bus);
+ if (!(f = fopen(buff, "r")))
+ {
+ /* hack around ppurka's Thinkpad (G460 + Linux) that reports lid
+ * state as "/proc/acpi/button/lid/LID0/state" but where the lid
+ * event says "button/lid LID close".
+ *
+ * so let's take the base device name "LID" and add a numeric like
+ * 0, 1, 2, 3 so we have LID0, LID1, LID2 etc. - try up to LID9
+ * and then give up.
+ */
+ for (i = 0; i < 10; i++)
+ {
+ snprintf(buff, sizeof(buff), "/proc/acpi/%s/%s%i/state",
+ device, bus, i);
+ if ((f = fopen(buff, "r"))) break;
+ f = NULL;
+ }
+ if (!f) return E_ACPI_LID_UNKNOWN;
+ }
+ // read the line from state file
+ ret = fgets(buff, sizeof(buff), f);
+ fclose(f);
+ if (!ret) return E_ACPI_LID_UNKNOWN;
+ // parse out state file
+ i = 0;
+ while (buff[i] != ':') i++;
+ while (!isalnum(buff[i])) i++;
+ ret = &(buff[i]);
+ while (isalnum(buff[i])) i++;
+ buff[i] = 0;
+ // compare value from state file and return something sane
+ if (!strcmp(ret, "open")) return E_ACPI_LID_OPEN;
+ else if (!strcmp(ret, "closed")) return E_ACPI_LID_CLOSED;
+ else return E_ACPI_LID_UNKNOWN;
}
/* public functions */
@@ -149,30 +221,8 @@ e_acpi_init(void)
{
E_EVENT_ACPI = ecore_event_type_new();
- /* check for running acpid */
- if (!ecore_file_exists("/var/run/acpid.socket"))
- {
- if (ecore_file_exists("/proc/acpi"))
- ecore_timer_add(5.0, _acpi_error_cb, NULL);
- return 1;
- }
-
- /* try to connect to acpid socket */
- _e_acpid = ecore_con_server_connect(ECORE_CON_LOCAL_SYSTEM,
- "/var/run/acpid.socket", -1, NULL);
- if (!_e_acpid) return 1;
-
- /* setup handlers */
- _e_acpid_hdls =
- eina_list_append(_e_acpid_hdls,
- ecore_event_handler_add(ECORE_CON_EVENT_SERVER_DEL,
- _e_acpi_cb_server_del, NULL));
- _e_acpid_hdls =
- eina_list_append(_e_acpid_hdls,
- ecore_event_handler_add(ECORE_CON_EVENT_SERVER_DATA,
- _e_acpi_cb_server_data, NULL));
-
- /* Add handlers for standard acpi events */
+ e_system_handler_add("acpi-event", _cb_sys_acpi_event, NULL);
+ // Add handlers for standard acpi events
_e_acpid_hdls =
eina_list_append(_e_acpid_hdls,
ecore_event_handler_add(E_EVENT_ACPI,
@@ -188,13 +238,6 @@ e_acpi_shutdown(void)
/* cleanup event handlers */
EINA_LIST_FREE(_e_acpid_hdls, hdl)
ecore_event_handler_del(hdl);
-
- /* kill the server if existing */
- if (_e_acpid)
- {
- ecore_con_server_del(_e_acpid);
- _e_acpid = NULL;
- }
return 1;
}
@@ -236,246 +279,6 @@ e_acpi_events_thaw(void)
if (_e_acpi_events_frozen < 0) _e_acpi_events_frozen = 0;
}
-/* local functions */
-static Eina_Bool
-_e_acpi_cb_server_del(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
-{
- Ecore_Con_Event_Server_Del *ev;
- Ecore_Event_Handler *hdl;
-
- ev = event;
- if (ev->server != _e_acpid) return ECORE_CALLBACK_PASS_ON;
-
- /* cleanup event handlers */
- EINA_LIST_FREE(_e_acpid_hdls, hdl)
- ecore_event_handler_del(hdl);
-
- /* kill the server if existing */
- if (_e_acpid)
- {
- ecore_con_server_del(_e_acpid);
- _e_acpid = NULL;
- }
- return ECORE_CALLBACK_PASS_ON;
-}
-
-static Eina_Bool
-_e_acpi_cb_server_data(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
-{
- Ecore_Con_Event_Server_Data *ev;
- E_Event_Acpi *acpi_event;
- int sig, status, i, done = 0;
- char device[1024], bus[1024], state[1024], *sdata;
- const char *str, *p;
-
- ev = event;
-
- if ((!ev->data) || (ev->size < 1)) return ECORE_CALLBACK_PASS_ON;
-
- /* write out actual acpi received data to stdout for debugging
- res = fwrite(ev->data, ev->size, 1, stdout);
- */
- /* data from a server isn't a string - its not 0 byte terminated. it's just
- * a blob of data. copy to string and 0 byte terminate it so it can be
- * string-swizzled/parsed etc. */
- if (!acpibuf) acpibuf = eina_strbuf_new();
- eina_strbuf_append_length(acpibuf, ev->data, ev->size);
- str = eina_strbuf_string_get(acpibuf);
- p = strchr(str, '\n');
- if (!p) return ECORE_CALLBACK_PASS_ON;
- while (p)
- {
- device[0] = bus[0] = state[0] = 0;
- sdata = alloca(p - str + 1);
- strncpy(sdata, str, (int)(p - str));
- sdata[p - str] = 0;
- /* parse out this acpi string into separate pieces */
- if (sscanf(sdata, "%1023s %1023s %x %x",
- device, bus, &sig, &status) != 4)
- {
- sig = -1;
- status = -1;
- if (sscanf(sdata, "%1023s %1023s", device, bus) != 2)
- {
- if (sscanf(sdata, "%1023s %1023s %1023s", device, bus, state) != 3)
- goto done_event;
- }
- }
-
- /* create new event structure to raise */
- acpi_event = E_NEW(E_Event_Acpi, 1);
- acpi_event->bus_id = eina_stringshare_add(bus);
- acpi_event->signal = sig;
- acpi_event->status = status;
-
- /* FIXME: add in a key faking layer */
- if ((!done) && (sig >= 0) && (status >= 0))
- {
- for (i = 0; _devices_multiplexed[i].name; i++)
- {
- // if device name matches
- if ((!strcmp(device, _devices_multiplexed[i].name)) &&
- // AND busname not set OR device name matches
- (!_devices_multiplexed[i].bus ||
- (_devices_multiplexed[i].bus &&
- (!strcmp(bus, _devices_multiplexed[i].bus)))) &&
- // AND status matches
- (_devices_multiplexed[i].status == status))
- {
- acpi_event->type = _devices_multiplexed[i].type;
- done = 1;
- break;
- }
- }
- }
- if ((!done) && (state[0]))
- {
- for (i = 0; _devices_simple_state[i].name; i++)
- {
- if ((!strcmp(device, _devices_simple_state[i].name)) &&
- ((!_devices_simple_state[i].bus) || (!strcmp(bus, _devices_simple_state[i].bus))) &&
- (!strcmp(state, _devices_simple_state[i].state)))
- {
- acpi_event->type = _devices_simple_state[i].type;
- done = 1;
- break;
- }
- }
- }
- if (!done)
- {
- // if device name matches
- for (i = 0; _devices_simple[i].name; i++)
- {
- if (!strcmp(device, _devices_simple[i].name))
- {
- acpi_event->type = _devices_simple[i].type;
- done = 1;
- break;
- }
- }
- }
- if (!done)
- {
- free(acpi_event);
- acpi_event = NULL;
- }
- else
- {
- switch (acpi_event->type)
- {
- case E_ACPI_TYPE_LID:
- acpi_event->status =
- _e_acpi_lid_status_get(device, bus);
- printf("RRR: acpi event @%1.8f\n", ecore_time_get());
- /* no change in lid state */
- if (lid_is_closed == (acpi_event->status == E_ACPI_LID_CLOSED)) break;
- lid_is_closed = (acpi_event->status == E_ACPI_LID_CLOSED);
- printf("RRR: lid event for lid %i\n", lid_is_closed);
- if (!e_randr2_cfg->ignore_acpi_events)
- e_randr2_screen_refresh_queue(EINA_TRUE);
- if (!lid_is_closed) e_powersave_defer_cancel();
- break;
-
- default:
- break;
- }
- /* actually raise the event */
- ecore_event_add(E_EVENT_ACPI, acpi_event,
- _e_acpi_cb_event_free, NULL);
- }
-done_event:
- str = p + 1;
- p = strchr(str, '\n');
- }
- if (str[0] == 0)
- {
- eina_strbuf_free(acpibuf);
- acpibuf = NULL;
- }
- else
- {
- Eina_Strbuf *newbuf;
-
- newbuf = eina_strbuf_new();
- eina_strbuf_append(newbuf, str);
- eina_strbuf_free(acpibuf);
- acpibuf = newbuf;
- }
- return ECORE_CALLBACK_PASS_ON;
-}
-
-static void
-_e_acpi_cb_event_free(void *data EINA_UNUSED, void *event)
-{
- E_Event_Acpi *ev;
-
- if (!(ev = event)) return;
- if (ev->device) eina_stringshare_del(ev->device);
- if (ev->bus_id) eina_stringshare_del(ev->bus_id);
- E_FREE(ev);
-}
-
-static int
-_e_acpi_lid_status_get(const char *device, const char *bus)
-{
- FILE *f;
- int i = 0;
- char buff[PATH_MAX], *ret;
-
- /* the acpi driver code in the kernel has a nice acpi function to return
- * the lid status easily, but that function is not exposed for user_space
- * so we need to check the proc fs to get the actual status */
-
- /* make sure we have a device and bus */
- if ((!device) || (!bus)) return E_ACPI_LID_UNKNOWN;
-
- /* open the state file from /proc */
- snprintf(buff, sizeof(buff), "/proc/acpi/%s/%s/state", device, bus);
- if (!(f = fopen(buff, "r")))
- {
- /* hack around ppurka's Thinkpad (G460 + Linux) that reports lid
- * state as "/proc/acpi/button/lid/LID0/state" but where the lid
- * event says "button/lid LID close".
- *
- * so let's take the base device name "LID" and add a numeric like
- * 0, 1, 2, 3 so we have LID0, LID1, LID2 etc. - try up to LID9
- * and then give up.
- */
- for (i = 0; i < 10; i++)
- {
- snprintf(buff, sizeof(buff), "/proc/acpi/%s/%s%i/state",
- device, bus, i);
- if ((f = fopen(buff, "r"))) break;
- f = NULL;
- }
- if (!f) return E_ACPI_LID_UNKNOWN;
- }
-
- /* read the line from state file */
- ret = fgets(buff, sizeof(buff), f);
- fclose(f);
- if (!ret)
- return E_ACPI_LID_UNKNOWN;
-
- /* parse out state file */
- i = 0;
- while (buff[i] != ':')
- i++;
- while (!isalnum(buff[i]))
- i++;
- ret = &(buff[i]);
- while (isalnum(buff[i]))
- i++;
- buff[i] = 0;
-
- /* compare value from state file and return something sane */
- if (!strcmp(ret, "open")) return E_ACPI_LID_OPEN;
- else if (!strcmp(ret, "closed"))
- return E_ACPI_LID_CLOSED;
- else return E_ACPI_LID_UNKNOWN;
-}
-
static Eina_Bool
_e_acpi_cb_event(void *data EINA_UNUSED, int type EINA_UNUSED, void *event)
{
diff --git a/src/bin/system/e_system.h b/src/bin/system/e_system.h
index 569699171..4eb4a5c33 100644
--- a/src/bin/system/e_system.h
+++ b/src/bin/system/e_system.h
@@ -126,6 +126,9 @@ void e_system_cpufreq_shutdown(void);
void e_system_ddc_init(void);
void e_system_ddc_shutdown(void);
+void e_system_acpi_init(void);
+void e_system_acpi_shutdown(void);
+
extern Ecore_Exe *e_system_run(const char *exe);
#endif
diff --git a/src/bin/system/e_system_acpi.c b/src/bin/system/e_system_acpi.c
new file mode 100644
index 000000000..26e0c5ddb
--- /dev/null
+++ b/src/bin/system/e_system_acpi.c
@@ -0,0 +1,246 @@
+#include "e_system.h"
+#if defined __OpenBSD__
+// no local funcs
+#elif defined __FreeBSD__
+// no local funcs
+#else
+# include <linux/input.h>
+# include <fcntl.h>
+
+typedef struct
+{
+ Ecore_Fd_Handler *handler;
+ char *name;
+ char *file;
+ int fd;
+} Dev;
+
+typedef struct
+{
+ unsigned short type;
+ unsigned short code;
+ int value;
+ const char *str;
+} Input_Dev_Map;
+
+static Eina_List *devices = NULL;
+static Eeze_Udev_Watch *watch[16] = { NULL };
+
+static const Input_Dev_Map devmap[] = {
+ { EV_KEY, KEY_POWER, 1, "button/power PBTN 00000080 00000000" },
+ { EV_KEY, KEY_SLEEP, 1, "button/sleep SBTN 00000080 00000000" },
+ { EV_SW, SW_LID, 1, "button/lid LID close" },
+ { EV_SW, SW_LID, 0, "button/lid LID open" },
+ { EV_SW, SW_TABLET_MODE, 0, "video/tabletmode TBLT 0000008A 00000000" },
+ { EV_SW, SW_TABLET_MODE, 1, "video/tabletmode TBLT 0000008A 00000001" },
+ { EV_KEY, KEY_ZOOM, 1, "button/zoom ZOOM 00000080 00000000" },
+ { EV_KEY, KEY_BRIGHTNESSDOWN, 1, "video/brightnessdown BRTDN 00000087 00000000"},
+ { EV_KEY, KEY_BRIGHTNESSUP, 1, "video/brightnessup BRTUP 00000086 00000000" },
+ { EV_KEY, KEY_SWITCHVIDEOMODE, 1, "video/switchmode VMOD 00000080 00000000" },
+ { EV_KEY, KEY_VOLUMEDOWN, 1, "button/volumedown VOLDN 00000080 00000000" },
+ { EV_KEY, KEY_VOLUMEUP, 1, "button/volumeup VOLUP 00000080 00000000" },
+ { EV_KEY, KEY_MUTE, 1, "button/mute MUTE 00000080 00000000" },
+ { EV_KEY, KEY_NEXTSONG, 1, "cd/next CDNEXT 00000080 00000000" },
+ { EV_KEY, KEY_PREVIOUSSONG, 1, "cd/prev CDPREV 00000080 00000000" },
+ { EV_KEY, KEY_PLAYPAUSE, 1, "cd/play CDPLAY 00000080 00000000" },
+ { EV_KEY, KEY_STOPCD, 1, "cd/stop CDSTOP 00000080 00000000" },
+ { EV_KEY, KEY_BATTERY, 1, "button/battery BAT 00000080 00000000" },
+ { EV_KEY, KEY_SCREENLOCK, 1, "button/screenlock SCRNLCK 00000080 00000000" },
+ { EV_KEY, KEY_WLAN, 1, "button/wlan WLAN 00000080 00000000" }
+};
+
+static Eina_Bool
+is_good(int fd)
+{
+# define LONGBITS (sizeof(long) * 8)
+# define NBITS(x) ((((x) - 1) / LONGBITS) + 1)
+# define OFF(x) ((x) % LONGBITS)
+# define LONG(x) ((x) / LONGBITS)
+# define HASBIT(b, arr) ((arr[LONG(b)] >> OFF(b)) & 1)
+ unsigned long bit[EV_MAX][NBITS(KEY_MAX)];
+ unsigned int i, type;
+
+ // get type of event supported
+ memset(bit, 0, sizeof(bit));
+ if (ioctl(fd, EVIOCGBIT(0, sizeof(bit[0])), bit[0]) < 0) return -1;
+ for (type = 0; type < EV_CNT; type++)
+ {
+ if (!HASBIT(type, bit[0])) continue; // skip
+ for (i = 0; i < (sizeof(devmap) / sizeof(devmap[0])); i++)
+ {
+ if (devmap[i].type != type) continue; // skip
+ // get every code supported
+ memset(bit, 0, sizeof(bit));
+ ioctl(fd, EVIOCGBIT(type, sizeof(bit[type])), bit[type]);
+ if (HASBIT(devmap[i].code, bit[type])) return EINA_TRUE;
+ }
+ }
+ return EINA_FALSE;
+}
+
+static Dev *
+dev_find(const char *file)
+{
+ Eina_List *l;
+ Dev *d;
+
+ EINA_LIST_FOREACH(devices, l, d)
+ {
+ if (!strcmp(file, d->file)) return d;
+ }
+ return NULL;
+}
+
+static Eina_Bool
+dev_have(const char *file)
+{
+ if (dev_find(file)) return EINA_TRUE;
+ return EINA_FALSE;
+}
+
+static void
+dev_del(Dev *d)
+{
+ if (!d) return;
+ devices = eina_list_remove(devices, d);
+ if (d->fd >= 0) close(d->fd);
+ if (d->handler) ecore_main_fd_handler_del(d->handler);
+ free(d->name);
+ free(d->file);
+ free(d);
+}
+
+static Eina_Bool
+cb_event_fd_active(void *data, Ecore_Fd_Handler *fd_handler)
+{
+ Dev *d = data;
+ struct input_event ev;
+ ssize_t size;
+ unsigned int i;
+ Eina_Bool lost;
+
+ if (ecore_main_fd_handler_active_get(fd_handler, ECORE_FD_READ))
+ {
+ lost = EINA_FALSE;
+ size = read(d->fd, &ev, sizeof(struct input_event));
+ if (size == sizeof(struct input_event))
+ {
+ for (i = 0; i < (sizeof(devmap) / sizeof(devmap[0])); i++)
+ {
+ if ((ev.type == devmap[i].type) &&
+ (ev.code == devmap[i].code) &&
+ (ev.value == devmap[i].value))
+ {
+ e_system_inout_command_send("acpi-event", "%s",
+ devmap[i].str);
+ break;
+ }
+ }
+ }
+ else
+ {
+ lost = ((errno == EIO) ||
+ (errno == EBADF) ||
+ (errno == EPIPE) ||
+ (errno == EINVAL) ||
+ (errno == ENOSPC) ||
+ (errno == ENODEV) ||
+ (errno == EISDIR) ||
+ (size > 0)
+ );
+ }
+ if (lost) dev_del(d);
+ }
+ return ECORE_CALLBACK_RENEW;
+}
+
+static Dev *
+dev_add(const char *file)
+{
+ int fd;
+ Dev *d = NULL;
+ char name[256];
+
+ if (ecore_file_is_dir(file)) return NULL;
+ fd = open(file, O_RDONLY | O_NONBLOCK | O_CLOEXEC);
+ if (fd < 0) return NULL;
+ if (!is_good(fd)) goto err;
+ d = calloc(1, sizeof(Dev));
+ if (!d) goto err;
+ d->fd = fd;
+ if (ioctl(fd, EVIOCGNAME(sizeof(name)), name) >= 0) d->name = strdup(name);
+ d->file = strdup(file);
+ if (!d->file) goto err;
+ d->handler = ecore_main_fd_handler_add(d->fd, ECORE_FD_READ,
+ cb_event_fd_active, d, NULL, NULL);
+ if (!d->handler) goto err;
+ return d;
+err:
+ close(fd);
+ if (d)
+ {
+ if (d->handler) ecore_main_fd_handler_del(d->handler);
+ free(d->name);
+ free(d->file);
+ free(d);
+ }
+ return NULL;
+}
+
+static void
+_cb_eeze(const char *str, Eeze_Udev_Event ev EINA_UNUSED,
+ void *data EINA_UNUSED, Eeze_Udev_Watch *w EINA_UNUSED)
+{
+ const char *file;
+ char buf[128];
+
+ if (!str) return;
+ file = ecore_file_file_get(str);
+ if (!file) return;
+ if (!!strncmp(file, "event", 5)) return;
+ if (strlen(file) > 100) return; // just stupidly too big
+ snprintf(buf, sizeof(buf), "/dev/input/%s", file);
+ if (!dev_have(buf)) dev_add(buf);
+}
+
+static void
+dev_open(void)
+{
+ Eina_Iterator *it;
+ Eina_File_Direct_Info *info;
+ int i = 0;
+
+# define WATCH(t) \
+ watch[i++] = eeze_udev_watch_add(t, EEZE_UDEV_EVENT_ADD, _cb_eeze, NULL)
+ WATCH(EEZE_UDEV_TYPE_KEYBOARD);
+ WATCH(EEZE_UDEV_TYPE_MOUSE);
+ WATCH(EEZE_UDEV_TYPE_TOUCHPAD);
+ WATCH(EEZE_UDEV_TYPE_POWER_AC);
+ WATCH(EEZE_UDEV_TYPE_BLUETOOTH);
+ WATCH(EEZE_UDEV_TYPE_JOYSTICK);
+ WATCH(EEZE_UDEV_TYPE_BACKLIGHT);
+ WATCH(EEZE_UDEV_TYPE_LEDS);
+ WATCH(EEZE_UDEV_TYPE_GPIO);
+ it = eina_file_direct_ls("/dev/input");
+ EINA_ITERATOR_FOREACH(it, info) dev_add(info->path);
+ eina_iterator_free(it);
+}
+#endif
+
+void
+e_system_acpi_init(void)
+{
+# if defined __OpenBSD__
+// no local funcs
+# elif defined __FreeBSD__
+// no local funcs
+# else
+ dev_open();
+#endif
+}
+
+void
+e_system_acpi_shutdown(void)
+{
+ // only shutdown things we really have to - no need to free mem etc.
+}
diff --git a/src/bin/system/e_system_main.c b/src/bin/system/e_system_main.c
index 111430a84..2c789d150 100644
--- a/src/bin/system/e_system_main.c
+++ b/src/bin/system/e_system_main.c
@@ -173,6 +173,7 @@ main(int argc EINA_UNUSED, const char **argv EINA_UNUSED)
CONF_INIT_CHECK("rfkill", e_system_rfkill_init, init_rfkill);
CONF_INIT_CHECK("l2ping", e_system_l2ping_init, init_l2ping);
CONF_INIT_CHECK("cpufreq", e_system_cpufreq_init, init_cpufreq);
+ CONF_INIT_CHECK("acpi", e_system_acpi_init, init_acpi);
if (systems == 0)
{
@@ -184,6 +185,7 @@ main(int argc EINA_UNUSED, const char **argv EINA_UNUSED)
ecore_main_loop_begin();
+ CONF_SHUTDOWN(e_system_acpi_shutdown, init_acpi);
CONF_SHUTDOWN(e_system_cpufreq_shutdown, init_cpufreq);
CONF_SHUTDOWN(e_system_l2ping_shutdown, init_l2ping);
CONF_SHUTDOWN(e_system_rfkill_shutdown, init_rfkill);
diff --git a/src/bin/system/meson.build b/src/bin/system/meson.build
index 0db4ca49c..d4c9fe17b 100644
--- a/src/bin/system/meson.build
+++ b/src/bin/system/meson.build
@@ -8,6 +8,7 @@ src = [
'e_system_rfkill.c',
'e_system_l2ping.c',
'e_system_cpufreq.c',
+ 'e_system_acpi.c',
'e_system.h',
]
executable('enlightenment_system', src,
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.