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.

Reply via email to