diff --git a/src/Makefile.am b/src/Makefile.am index be332a8..9820545 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -4,7 +4,8 @@ iio_sensor_proxy_SOURCES = \ iio-sensor-proxy.c \ drivers.h \ drv-iio-buffer-accel.c \ - drv-iio-poll-accel.c + drv-iio-poll-accel.c \ + drv-input-accel.c iio_sensor_proxy_CPPFLAGS = \ $(IIO_SENSOR_PROXY_CFLAGS) \ diff --git a/src/drivers.h b/src/drivers.h index a595630..d68c4d2 100644 --- a/src/drivers.h +++ b/src/drivers.h @@ -10,7 +10,8 @@ #include typedef enum { - DRIVER_TYPE_ACCEL_IIO + DRIVER_TYPE_ACCEL_IIO, + DRIVER_TYPE_ACCEL_INPUT } DriverType; typedef struct SensorDriver SensorDriver; @@ -34,3 +35,4 @@ struct SensorDriver { extern SensorDriver iio_buffer_accel; extern SensorDriver iio_poll_accel; +extern SensorDriver input_accel; diff --git a/src/drv-input-accel.c b/src/drv-input-accel.c new file mode 100644 index 0000000..b5e3edf --- /dev/null +++ b/src/drv-input-accel.c @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2014 Bastien Nocera + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 as published by + * the Free Software Foundation. + */ + +#include "drivers.h" + +#include +#include +#include +#include +#include + +#include + +typedef struct DrvData { + ReadingsUpdateFunc callback_func; + gpointer user_data; + + GUdevClient *client; + GUdevDevice *dev, *parent; + const char *dev_path; +} DrvData; + +static DrvData *drv_data = NULL; + +static gboolean +input_accel_discover (GUdevDevice *device) +{ + const char *path; + + if (!g_udev_device_get_property_as_boolean (device, "ID_INPUT_ACCELEROMETER")) + return FALSE; + + path = g_udev_device_get_device_file (device); + if (!path) + return FALSE; + if (strstr (path, "/event") == NULL) + return FALSE; + + g_debug ("Found input accel at %s", g_udev_device_get_sysfs_path (device)); + return TRUE; +} + +#define READ_AXIS(axis, var) { memzero(&abs_info, sizeof(abs_info)); r = ioctl(fd, EVIOCGABS(axis), &abs_info); if (r < 0) return; var = abs_info.value; } +#define memzero(x,l) (memset((x), 0, (l))) + +static void +accelerometer_changed (void) +{ + struct input_absinfo abs_info; + int accel_x = 0, accel_y = 0, accel_z = 0; + int fd, r; + + fd = open (drv_data->dev_path, O_RDONLY|O_CLOEXEC); + if (fd < 0) + return; + + READ_AXIS(ABS_X, accel_x); + READ_AXIS(ABS_Y, accel_y); + READ_AXIS(ABS_Z, accel_z); + + close (fd); + + drv_data->callback_func (&input_accel, accel_x, accel_y, accel_z, drv_data->user_data); +} + +static void +uevent_received (GUdevClient *client, + gchar *action, + GUdevDevice *device, + gpointer user_data) +{ + if (g_strcmp0 (action, "change") != 0) + return; + + if (g_strcmp0 (g_udev_device_get_sysfs_path (device), g_udev_device_get_sysfs_path (drv_data->parent)) != 0) + return; + + accelerometer_changed (); +} + +static gboolean +first_values (gpointer user_data) +{ + accelerometer_changed (); + return G_SOURCE_REMOVE; +} + +static gboolean +input_accel_open (GUdevDevice *device, + ReadingsUpdateFunc callback_func, + gpointer user_data) +{ + const gchar * const subsystems[] = { "input", NULL }; + + drv_data = g_new0 (DrvData, 1); + drv_data->dev = g_object_ref (device); + drv_data->parent = g_udev_device_get_parent (drv_data->dev); + drv_data->dev_path = g_udev_device_get_device_file (device); + drv_data->client = g_udev_client_new (subsystems); + + drv_data->callback_func = callback_func; + drv_data->user_data = user_data; + + g_signal_connect (drv_data->client, "uevent", + G_CALLBACK (uevent_received), NULL); + + g_idle_add (first_values, NULL); + + return TRUE; +} + +static void +input_accel_close (void) +{ + g_clear_object (&drv_data->client); + g_clear_object (&drv_data->dev); + g_clear_object (&drv_data->parent); + g_clear_pointer (&drv_data->dev_path, g_free); + + g_clear_pointer (&drv_data, g_free); +} + +SensorDriver input_accel = { + .name = "Input accelerometer", + .type = DRIVER_TYPE_ACCEL_INPUT, + + .discover = input_accel_discover, + .open = input_accel_open, + .close = input_accel_close, +}; diff --git a/src/iio-sensor-proxy.c b/src/iio-sensor-proxy.c index 487ec74..e59df1e 100644 --- a/src/iio-sensor-proxy.c +++ b/src/iio-sensor-proxy.c @@ -159,18 +159,21 @@ typedef struct { static const SensorDriver * const drivers[] = { &iio_buffer_accel, - &iio_poll_accel + &iio_poll_accel, + &input_accel }; static GUdevDevice * find_accel (GUdevClient *client, SensorDriver **driver) { - GList *devices, *l; + GList *devices, *input, *l; GUdevDevice *ret = NULL; *driver = NULL; devices = g_udev_client_query_by_subsystem (client, "iio"); + input = g_udev_client_query_by_subsystem (client, "input"); + devices = g_list_concat (devices, input); /* Find the accelerometer */ for (l = devices; l != NULL; l = l->next) { @@ -346,12 +349,11 @@ int main (int argc, char **argv) GUdevClient *client; GUdevDevice *dev; SensorDriver *driver; - const gchar * const subsystems[] = { "iio", NULL }; int ret = 0; /* g_setenv ("G_MESSAGES_DEBUG", "all", TRUE); */ - client = g_udev_client_new (subsystems); + client = g_udev_client_new (NULL); dev = find_accel (client, &driver); if (!dev) { g_debug ("Could not find IIO accelerometer");