Add a TODO list.

Create a device hash to match standard device names to types.
Cleanup E_EVENT_ACPI (add missing ones, remove not needed ones).
Actually parse out the ACPI data which we receive.

You can now actually use this ACPI code for event listening, but the
Status field of the event structure needs sanatizing yet (turn into
something meaningful).



SVN revision: 48928
This commit is contained in:
Christopher Michael 2010-05-17 00:03:55 +00:00
parent 7f9818b8a6
commit d823aba015
2 changed files with 141 additions and 33 deletions

View File

@ -1,5 +1,24 @@
#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.
*
* Add e_actions for bindings.
*/
/* local structures */
typedef struct _ACPIDevice ACPIDevice; // for mapping device names to type
struct _ACPIDevice
{
const char *name;
int type;
};
/* local function prototypes */
static int _e_acpi_cb_server_del(void *data __UNUSED__, int type __UNUSED__, void *event);
static int _e_acpi_cb_server_data(void *data __UNUSED__, int type __UNUSED__, void *event);
@ -8,22 +27,52 @@ static void _e_acpi_cb_event_free(void *data __UNUSED__, void *event);
/* local variables */
static Ecore_Con_Server *_e_acpid = NULL;
static Eina_List *_e_acpid_hdls = NULL;
static Eina_Hash *_e_acpid_devices = NULL;
static ACPIDevice _devices[] =
{
/* DO NOT TRANSLATE THESE. */
/* standardized ACPI device name, corresponding E_ACPI_TYPE */
{"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},
{"fan", E_ACPI_TYPE_FAN},
{"processor", E_ACPI_TYPE_PROCESSOR},
{"thermal_zone", E_ACPI_TYPE_THERMAL},
{"video", E_ACPI_TYPE_VIDEO},
{NULL, E_ACPI_TYPE_UNKNOWN}
};
/* public variables */
EAPI int E_EVENT_ACPI_LID = 0;
EAPI int E_EVENT_ACPI_UNKNOWN = 0;
EAPI int E_EVENT_ACPI_AC_ADAPTER = 0;
EAPI int E_EVENT_ACPI_BATTERY = 0;
EAPI int E_EVENT_ACPI_BUTTON = 0;
EAPI int E_EVENT_ACPI_FAN = 0;
EAPI int E_EVENT_ACPI_LID = 0;
EAPI int E_EVENT_ACPI_POWER = 0;
EAPI int E_EVENT_ACPI_PROCESSOR = 0;
EAPI int E_EVENT_ACPI_SLEEP = 0;
EAPI int E_EVENT_ACPI_THERMAL = 0;
EAPI int E_EVENT_ACPI_VIDEO = 0;
EAPI int E_EVENT_ACPI_WIFI = 0;
/* public functions */
EAPI int
e_acpi_init(void)
{
E_EVENT_ACPI_LID = ecore_event_type_new();
const ACPIDevice *dev;
E_EVENT_ACPI_UNKNOWN = ecore_event_type_new();
E_EVENT_ACPI_AC_ADAPTER = ecore_event_type_new();
E_EVENT_ACPI_BATTERY = ecore_event_type_new();
E_EVENT_ACPI_BUTTON = ecore_event_type_new();
E_EVENT_ACPI_FAN = ecore_event_type_new();
E_EVENT_ACPI_LID = ecore_event_type_new();
E_EVENT_ACPI_POWER = ecore_event_type_new();
E_EVENT_ACPI_PROCESSOR = ecore_event_type_new();
E_EVENT_ACPI_SLEEP = ecore_event_type_new();
E_EVENT_ACPI_THERMAL = ecore_event_type_new();
E_EVENT_ACPI_VIDEO = ecore_event_type_new();
E_EVENT_ACPI_WIFI = ecore_event_type_new();
/* check for running acpid */
@ -34,6 +83,11 @@ e_acpi_init(void)
"/var/run/acpid.socket", -1, NULL);
if (!_e_acpid) return 1;
/* create new device hash and fill it */
_e_acpid_devices = eina_hash_string_superfast_new(NULL);
for (dev = _devices; dev->type > E_ACPI_TYPE_UNKNOWN; dev++)
eina_hash_direct_add(_e_acpid_devices, dev->name, dev);
/* setup handlers */
_e_acpid_hdls =
eina_list_append(_e_acpid_hdls,
@ -51,6 +105,10 @@ e_acpi_shutdown(void)
{
Ecore_Event_Handler *hdl;
/* destroy the device hash */
if (_e_acpid_devices) eina_hash_free(_e_acpid_devices);
_e_acpid_devices = NULL;
/* cleanup event handlers */
EINA_LIST_FREE(_e_acpid_hdls, hdl)
ecore_event_handler_del(hdl);
@ -85,28 +143,81 @@ static int
_e_acpi_cb_server_data(void *data __UNUSED__, int type __UNUSED__, void *event)
{
Ecore_Con_Event_Server_Data *ev;
int res;
ACPIDevice *dev;
E_Event_Acpi *acpi_event;
int res, sig, status, event_type;
char device[1024], bus[1024];
ev = event;
/* parse out this acpi string into separate pieces */
if (!(sscanf(ev->data, "%s %4s %8d %8d", device, bus, &sig, &status)) == 4)
return 1;
/* write out acutal acpi received data to stdout for debugging */
res = fwrite(ev->data, ev->size, 1, stdout);
printf("Device: %s\n", device);
printf("Bus: %s\n", bus);
printf("Signal: %d\n", sig);
printf("Status: %d\n", status);
printf("\n");
/* TODO: Need to parse this data and raise events according to
* the type of acpi object. See ACPI notes below */
/* raise the event
E_Event_Acpi *acpi_event;
/* create new event structure to raise */
acpi_event = E_NEW(E_Event_Acpi, 1);
acpi_event->device = eina_stringshare_add("battery");
acpi_event->bus_id = eina_stringshare_add("BAT0");
acpi_event->event_type = E_ACPI_BATTERY_STATUS_CHANGED; // make these standard E_ACPI enums
acpi_event->event_data = 1; // change to something more meaningful
ecore_event_add(E_EVENT_ACPI_LID, acpi_event, _e_acpi_cb_event_free, NULL);
*/
acpi_event->bus_id = eina_stringshare_add(bus);
acpi_event->signal = sig;
acpi_event->status = status;
/* determine which device this event is for */
if ((dev = eina_hash_find(_e_acpid_devices, device)))
{
acpi_event->device = eina_stringshare_add(dev->name);
acpi_event->type = dev->type;
}
else
{
acpi_event->device = eina_stringshare_add("unknown");
acpi_event->type = E_ACPI_TYPE_UNKNOWN;
}
/* based on device type, determine the event to raise */
switch (acpi_event->type)
{
case E_ACPI_TYPE_AC_ADAPTER:
event_type = E_EVENT_ACPI_AC_ADAPTER;
break;
case E_ACPI_TYPE_BATTERY:
event_type = E_EVENT_ACPI_BATTERY;
break;
case E_ACPI_TYPE_FAN:
event_type = E_EVENT_ACPI_FAN;
break;
case E_ACPI_TYPE_LID:
event_type = E_EVENT_ACPI_LID;
break;
case E_ACPI_TYPE_POWER:
event_type = E_EVENT_ACPI_POWER;
break;
case E_ACPI_TYPE_PROCESSOR:
event_type = E_EVENT_ACPI_PROCESSOR;
break;
case E_ACPI_TYPE_SLEEP:
event_type = E_EVENT_ACPI_SLEEP;
break;
case E_ACPI_TYPE_THERMAL:
event_type = E_EVENT_ACPI_THERMAL;
break;
case E_ACPI_TYPE_VIDEO:
event_type = E_EVENT_ACPI_VIDEO;
break;
default:
event_type = E_EVENT_ACPI_UNKNOWN;
break;
}
/* actually raise the event */
ecore_event_add(event_type, acpi_event, _e_acpi_cb_event_free, NULL);
return 1;
}
@ -115,19 +226,8 @@ _e_acpi_cb_event_free(void *data __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);
}
/* ACPI NOTES
*
* http://www.columbia.edu/~ariel/acpi/acpi_howto.txt (Section 6.4)
*
* Typical data looks like:
* completed event "processor CPU0 00000080 00000004"
* received event "ac_adapter AC 00000080 00000001"
* received event "battery BAT0 00000080 00000001"
* received event "button/power PBTN 00000080 00000001"
*/

View File

@ -4,13 +4,14 @@
typedef enum _E_Acpi_Type
{
E_ACPI_TYPE_UNKNOWN = 0,
E_ACPI_TYPE_AC_ADAPTER,
E_ACPI_TYPE_BATTERY,
E_ACPI_TYPE_BUTTON,
E_ACPI_TYPE_FAN,
E_ACPI_TYPE_LID,
E_ACPI_TYPE_POWER,
E_ACPI_TYPE_PROCESSOR,
E_ACPI_TYPE_SLEEP,
E_ACPI_TYPE_POWER,
E_ACPI_TYPE_THERMAL,
E_ACPI_TYPE_VIDEO,
E_ACPI_TYPE_WIFI
@ -26,16 +27,23 @@ typedef struct _E_Event_Acpi E_Event_Acpi;
struct _E_Event_Acpi
{
const char *device, *bus_id;
int type, data;
int type, signal, status;
};
EAPI int e_acpi_init(void);
EAPI int e_acpi_shutdown(void);
extern EAPI int E_EVENT_ACPI_LID;
extern EAPI int E_EVENT_ACPI_UNKNOWN;
extern EAPI int E_EVENT_ACPI_AC_ADAPTER;
extern EAPI int E_EVENT_ACPI_BATTERY;
extern EAPI int E_EVENT_ACPI_BUTTON;
extern EAPI int E_EVENT_ACPI_FAN;
extern EAPI int E_EVENT_ACPI_LID;
extern EAPI int E_EVENT_ACPI_POWER;
extern EAPI int E_EVENT_ACPI_PROCESSOR;
extern EAPI int E_EVENT_ACPI_SLEEP;
extern EAPI int E_EVENT_ACPI_THERMAL;
extern EAPI int E_EVENT_ACPI_VIDEO;
extern EAPI int E_EVENT_ACPI_WIFI;
# endif