697 lines
18 KiB
C
697 lines
18 KiB
C
/*
|
|
* Modified from industrialio buffer test code, and Lenovo Yoga (2 Pro) orientation helper
|
|
* Copyright (c) 2008 Jonathan Cameron
|
|
* Copyright (c) 2014 Peter F. Patel-Schneider
|
|
* Copyright (c) 2011, 2014 Bastien Nocera <hadess@hadess.net>
|
|
*
|
|
* Every 700 msec, read data from an IIO accelerometer, and
|
|
* from the accelerometer values, as well as the previous
|
|
* orientation, calculate the device's new orientation.
|
|
*
|
|
* Possible values are:
|
|
* * undefined
|
|
* * normal
|
|
* * bottom-up
|
|
* * left-up
|
|
* * right-up
|
|
*
|
|
* The property will be persistent across sessions, and the new
|
|
* orientations can be deducted from the previous one (it allows
|
|
* for a threshold for switching between opposite ends of the
|
|
* orientation).
|
|
*
|
|
* orientation_calc() from the sensorfw package
|
|
* Copyright (C) 2009-2010 Nokia Corporation
|
|
* Authors:
|
|
* Üstün Ergenoglu <ext-ustun.ergenoglu@nokia.com>
|
|
* Timo Rongas <ext-timo.2.rongas@nokia.com>
|
|
* Lihan Guo <lihan.guo@digia.com>
|
|
*
|
|
* 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.
|
|
*
|
|
*/
|
|
|
|
#define _GNU_SOURCE
|
|
|
|
#include <unistd.h>
|
|
#include <fcntl.h>
|
|
#include <errno.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
|
|
#include <gio/gio.h>
|
|
#include <gudev/gudev.h>
|
|
#include "drivers.h"
|
|
#include "orientation.h"
|
|
|
|
#include "iio-sensor-proxy-resources.h"
|
|
|
|
#define SENSOR_PROXY_DBUS_NAME "net.hadess.SensorProxy"
|
|
#define SENSOR_PROXY_DBUS_PATH "/net/hadess/SensorProxy"
|
|
|
|
#define NUM_SENSOR_TYPES DRIVER_TYPE_LIGHT + 1
|
|
|
|
typedef struct {
|
|
GMainLoop *loop;
|
|
GDBusNodeInfo *introspection_data;
|
|
GDBusConnection *connection;
|
|
guint name_id;
|
|
gboolean init_done;
|
|
|
|
SensorDriver *drivers[NUM_SENSOR_TYPES];
|
|
GUdevDevice *devices[NUM_SENSOR_TYPES];
|
|
GHashTable *clients[NUM_SENSOR_TYPES]; /* key = D-Bus name, value = watch ID */
|
|
|
|
/* Accelerometer */
|
|
int accel_x, accel_y, accel_z;
|
|
OrientationUp previous_orientation;
|
|
|
|
/* Light */
|
|
gdouble previous_level;
|
|
gboolean uses_lux;
|
|
} SensorData;
|
|
|
|
static const SensorDriver * const drivers[] = {
|
|
&iio_buffer_accel,
|
|
&iio_poll_accel,
|
|
&input_accel,
|
|
&iio_poll_light,
|
|
&iio_buffer_light,
|
|
&hwmon_light,
|
|
&fake_light
|
|
};
|
|
|
|
static ReadingsUpdateFunc driver_type_to_callback_func (DriverType type);
|
|
|
|
static const char *
|
|
driver_type_to_str (DriverType type)
|
|
{
|
|
switch (type) {
|
|
case DRIVER_TYPE_ACCEL:
|
|
return "accelerometer";
|
|
case DRIVER_TYPE_LIGHT:
|
|
return "ambient light sensor";
|
|
default:
|
|
g_assert_not_reached ();
|
|
}
|
|
}
|
|
|
|
#define DRIVER_FOR_TYPE(driver_type) data->drivers[driver_type]
|
|
#define DEVICE_FOR_TYPE(driver_type) data->devices[driver_type]
|
|
|
|
static gboolean
|
|
driver_type_exists (SensorData *data,
|
|
DriverType driver_type)
|
|
{
|
|
return (DRIVER_FOR_TYPE(driver_type) != NULL);
|
|
}
|
|
|
|
static gboolean
|
|
find_sensors (GUdevClient *client,
|
|
SensorData *data)
|
|
{
|
|
GList *devices, *input, *platform, *l;
|
|
gboolean found = FALSE;
|
|
|
|
devices = g_udev_client_query_by_subsystem (client, "iio");
|
|
input = g_udev_client_query_by_subsystem (client, "input");
|
|
platform = g_udev_client_query_by_subsystem (client, "platform");
|
|
devices = g_list_concat (devices, input);
|
|
devices = g_list_concat (devices, platform);
|
|
|
|
/* Find the devices */
|
|
for (l = devices; l != NULL; l = l->next) {
|
|
GUdevDevice *dev = l->data;
|
|
guint i;
|
|
|
|
for (i = 0; i < G_N_ELEMENTS(drivers); i++) {
|
|
SensorDriver *driver = (SensorDriver *) drivers[i];
|
|
if (!driver_type_exists(data, driver->type) &&
|
|
driver_discover (driver, dev)) {
|
|
g_debug ("Found device %s of type %s at %s",
|
|
g_udev_device_get_sysfs_path (dev),
|
|
driver_type_to_str (driver->type),
|
|
driver->name);
|
|
DEVICE_FOR_TYPE(driver->type) = g_object_ref (dev);
|
|
DRIVER_FOR_TYPE(driver->type) = (SensorDriver *) driver;
|
|
|
|
found = TRUE;
|
|
}
|
|
}
|
|
|
|
if (driver_type_exists (data, DRIVER_TYPE_ACCEL) &&
|
|
driver_type_exists (data, DRIVER_TYPE_LIGHT))
|
|
break;
|
|
}
|
|
|
|
g_list_free_full (devices, g_object_unref);
|
|
return found;
|
|
}
|
|
|
|
typedef enum {
|
|
PROP_HAS_ACCELEROMETER = 1 << 0,
|
|
PROP_ACCELEROMETER_ORIENTATION = 1 << 1,
|
|
PROP_HAS_AMBIENT_LIGHT = 1 << 2,
|
|
PROP_LIGHT_LEVEL = 1 << 3
|
|
} PropertiesMask;
|
|
|
|
#define PROP_ALL (PROP_HAS_ACCELEROMETER | PROP_ACCELEROMETER_ORIENTATION | PROP_HAS_AMBIENT_LIGHT | PROP_LIGHT_LEVEL)
|
|
|
|
static void
|
|
send_dbus_event (SensorData *data,
|
|
PropertiesMask mask)
|
|
{
|
|
GVariantBuilder props_builder;
|
|
GVariant *props_changed = NULL;
|
|
|
|
g_assert (data->connection);
|
|
|
|
if (mask == 0)
|
|
return;
|
|
|
|
g_variant_builder_init (&props_builder, G_VARIANT_TYPE ("a{sv}"));
|
|
|
|
if (mask & PROP_HAS_ACCELEROMETER) {
|
|
gboolean has_accel;
|
|
|
|
has_accel = driver_type_exists (data, DRIVER_TYPE_ACCEL);
|
|
g_variant_builder_add (&props_builder, "{sv}", "HasAccelerometer",
|
|
g_variant_new_boolean (has_accel));
|
|
|
|
/* Send the orientation when the device appears */
|
|
if (has_accel)
|
|
mask |= PROP_ACCELEROMETER_ORIENTATION;
|
|
else
|
|
data->previous_orientation = ORIENTATION_UNDEFINED;
|
|
}
|
|
|
|
if (mask & PROP_ACCELEROMETER_ORIENTATION) {
|
|
g_variant_builder_add (&props_builder, "{sv}", "AccelerometerOrientation",
|
|
g_variant_new_string (orientation_to_string (data->previous_orientation)));
|
|
}
|
|
|
|
if (mask & PROP_HAS_AMBIENT_LIGHT) {
|
|
gboolean has_als;
|
|
|
|
has_als = driver_type_exists (data, DRIVER_TYPE_LIGHT);
|
|
g_variant_builder_add (&props_builder, "{sv}", "HasAmbientLight",
|
|
g_variant_new_boolean (has_als));
|
|
|
|
/* Send the light level when the device appears */
|
|
if (has_als)
|
|
mask |= PROP_LIGHT_LEVEL;
|
|
}
|
|
|
|
if (mask & PROP_LIGHT_LEVEL) {
|
|
g_variant_builder_add (&props_builder, "{sv}", "LightLevelUnit",
|
|
g_variant_new_string (data->uses_lux ? "lux" : "vendor"));
|
|
g_variant_builder_add (&props_builder, "{sv}", "LightLevel",
|
|
g_variant_new_double (data->previous_level));
|
|
}
|
|
|
|
props_changed = g_variant_new ("(s@a{sv}@as)", SENSOR_PROXY_DBUS_NAME,
|
|
g_variant_builder_end (&props_builder),
|
|
g_variant_new_strv (NULL, 0));
|
|
|
|
g_dbus_connection_emit_signal (data->connection,
|
|
NULL,
|
|
SENSOR_PROXY_DBUS_PATH,
|
|
"org.freedesktop.DBus.Properties",
|
|
"PropertiesChanged",
|
|
props_changed, NULL);
|
|
}
|
|
|
|
static void
|
|
send_driver_changed_dbus_event (SensorData *data,
|
|
DriverType driver_type)
|
|
{
|
|
if (driver_type == DRIVER_TYPE_ACCEL)
|
|
send_dbus_event (data, PROP_HAS_ACCELEROMETER);
|
|
else if (driver_type == DRIVER_TYPE_LIGHT)
|
|
send_dbus_event (data, PROP_HAS_AMBIENT_LIGHT);
|
|
else
|
|
g_assert_not_reached ();
|
|
}
|
|
|
|
static gboolean
|
|
any_sensors_left (SensorData *data)
|
|
{
|
|
guint i;
|
|
gboolean exists = FALSE;
|
|
|
|
for (i = 0; i < NUM_SENSOR_TYPES; i++) {
|
|
if (driver_type_exists (data, i)) {
|
|
exists = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return exists;
|
|
}
|
|
|
|
static gboolean
|
|
client_release (SensorData *data,
|
|
const char *sender,
|
|
DriverType driver_type,
|
|
GDBusMethodInvocation *invocation)
|
|
{
|
|
GHashTable *ht;
|
|
guint watch_id;
|
|
|
|
ht = data->clients[driver_type];
|
|
|
|
watch_id = GPOINTER_TO_UINT (g_hash_table_lookup (ht, sender));
|
|
if (watch_id == 0) {
|
|
if (invocation) {
|
|
g_dbus_method_invocation_return_error (invocation,
|
|
G_DBUS_ERROR,
|
|
G_DBUS_ERROR_FAILED,
|
|
"D-Bus client '%s' is not monitoring %s",
|
|
sender, driver_type_to_str (driver_type));
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
g_bus_unwatch_name (watch_id);
|
|
g_hash_table_remove (ht, sender);
|
|
|
|
if (g_hash_table_size (ht) == 0)
|
|
driver_set_polling (DRIVER_FOR_TYPE(driver_type), FALSE);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
client_vanished_cb (GDBusConnection *connection,
|
|
const gchar *name,
|
|
gpointer user_data)
|
|
{
|
|
SensorData *data = user_data;
|
|
guint i;
|
|
char *sender;
|
|
|
|
if (name == NULL)
|
|
return;
|
|
|
|
sender = g_strdup (name);
|
|
|
|
for (i = 0; i < NUM_SENSOR_TYPES; i++) {
|
|
GHashTable *ht;
|
|
guint watch_id;
|
|
|
|
ht = data->clients[i];
|
|
g_assert (ht);
|
|
|
|
watch_id = GPOINTER_TO_UINT (g_hash_table_lookup (ht, sender));
|
|
if (watch_id > 0)
|
|
client_release (data, sender, i, NULL);
|
|
}
|
|
|
|
g_free (sender);
|
|
}
|
|
|
|
static void
|
|
handle_method_call (GDBusConnection *connection,
|
|
const gchar *sender,
|
|
const gchar *object_path,
|
|
const gchar *interface_name,
|
|
const gchar *method_name,
|
|
GVariant *parameters,
|
|
GDBusMethodInvocation *invocation,
|
|
gpointer user_data)
|
|
{
|
|
SensorData *data = user_data;
|
|
const char *driver_name;
|
|
DriverType driver_type;
|
|
GHashTable *ht;
|
|
guint watch_id;
|
|
|
|
if (g_strcmp0 (method_name, "Claim") != 0 &&
|
|
g_strcmp0 (method_name, "Release") != 0) {
|
|
g_dbus_method_invocation_return_error (invocation,
|
|
G_DBUS_ERROR,
|
|
G_DBUS_ERROR_UNKNOWN_METHOD,
|
|
"Method '%s' does not exist", method_name);
|
|
return;
|
|
}
|
|
|
|
/* Verify arguments */
|
|
g_variant_get_child (parameters, 0, "&s", &driver_name);
|
|
if (g_strcmp0 (driver_name, "accel") == 0) {
|
|
driver_type = DRIVER_TYPE_ACCEL;
|
|
} else if (g_strcmp0 (driver_name, "light") == 0) {
|
|
driver_type = DRIVER_TYPE_LIGHT;
|
|
} else {
|
|
g_dbus_method_invocation_return_error (invocation,
|
|
G_DBUS_ERROR,
|
|
G_DBUS_ERROR_INVALID_ARGS,
|
|
"Driver type '%s' is not supported", driver_name);
|
|
return;
|
|
}
|
|
|
|
/* Check if we have a sensor for that type */
|
|
if (!driver_type_exists (data, driver_type)) {
|
|
g_dbus_method_invocation_return_error (invocation,
|
|
G_DBUS_ERROR,
|
|
G_DBUS_ERROR_INVALID_ARGS,
|
|
"Driver type '%s' is not present", driver_name);
|
|
return;
|
|
}
|
|
|
|
ht = data->clients[driver_type];
|
|
|
|
if (g_strcmp0 (method_name, "Claim") == 0) {
|
|
watch_id = GPOINTER_TO_UINT (g_hash_table_lookup (ht, sender));
|
|
if (watch_id > 0) {
|
|
g_dbus_method_invocation_return_error (invocation,
|
|
G_DBUS_ERROR,
|
|
G_DBUS_ERROR_LIMITS_EXCEEDED,
|
|
"D-Bus client '%s' is already monitoring %s",
|
|
sender, driver_type_to_str (driver_type));
|
|
return;
|
|
}
|
|
|
|
/* No other clients for this sensor? Start it */
|
|
if (g_hash_table_size (ht) == 0)
|
|
driver_set_polling (DRIVER_FOR_TYPE(driver_type), TRUE);
|
|
|
|
watch_id = g_bus_watch_name_on_connection (data->connection,
|
|
sender,
|
|
G_BUS_NAME_WATCHER_FLAGS_NONE,
|
|
NULL,
|
|
client_vanished_cb,
|
|
data,
|
|
NULL);
|
|
g_hash_table_insert (ht, g_strdup (sender), GUINT_TO_POINTER (watch_id));
|
|
|
|
g_dbus_method_invocation_return_value (invocation, NULL);
|
|
} else if (g_strcmp0 (method_name, "Release") == 0) {
|
|
if (client_release (data, sender, driver_type, invocation))
|
|
g_dbus_method_invocation_return_value (invocation, NULL);
|
|
}
|
|
}
|
|
|
|
static GVariant *
|
|
handle_get_property (GDBusConnection *connection,
|
|
const gchar *sender,
|
|
const gchar *object_path,
|
|
const gchar *interface_name,
|
|
const gchar *property_name,
|
|
GError **error,
|
|
gpointer user_data)
|
|
{
|
|
SensorData *data = user_data;
|
|
|
|
g_assert (data->connection);
|
|
|
|
if (g_strcmp0 (property_name, "HasAccelerometer") == 0)
|
|
return g_variant_new_boolean (driver_type_exists (data, DRIVER_TYPE_ACCEL));
|
|
if (g_strcmp0 (property_name, "AccelerometerOrientation") == 0)
|
|
return g_variant_new_string (orientation_to_string (data->previous_orientation));
|
|
if (g_strcmp0 (property_name, "HasAmbientLight") == 0)
|
|
return g_variant_new_boolean (driver_type_exists (data, DRIVER_TYPE_LIGHT));
|
|
if (g_strcmp0 (property_name, "LightLevelUnit") == 0)
|
|
return g_variant_new_string (data->uses_lux ? "lux" : "vendor");
|
|
if (g_strcmp0 (property_name, "LightLevel") == 0)
|
|
return g_variant_new_double (data->previous_level);
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static const GDBusInterfaceVTable interface_vtable =
|
|
{
|
|
handle_method_call,
|
|
handle_get_property,
|
|
NULL
|
|
};
|
|
|
|
static void
|
|
name_lost_handler (GDBusConnection *connection,
|
|
const gchar *name,
|
|
gpointer user_data)
|
|
{
|
|
g_debug ("iio-sensor-proxy is already running");
|
|
exit (0);
|
|
}
|
|
|
|
static void
|
|
bus_acquired_handler (GDBusConnection *connection,
|
|
const gchar *name,
|
|
gpointer user_data)
|
|
{
|
|
SensorData *data = user_data;
|
|
|
|
g_dbus_connection_register_object (connection,
|
|
SENSOR_PROXY_DBUS_PATH,
|
|
data->introspection_data->interfaces[0],
|
|
&interface_vtable,
|
|
data,
|
|
NULL,
|
|
NULL);
|
|
|
|
data->connection = g_object_ref (connection);
|
|
}
|
|
|
|
static void
|
|
name_acquired_handler (GDBusConnection *connection,
|
|
const gchar *name,
|
|
gpointer user_data)
|
|
{
|
|
SensorData *data = user_data;
|
|
|
|
if (data->init_done)
|
|
send_dbus_event (data, PROP_ALL);
|
|
}
|
|
|
|
static gboolean
|
|
setup_dbus (SensorData *data)
|
|
{
|
|
GBytes *bytes;
|
|
|
|
bytes = g_resources_lookup_data ("/net/hadess/SensorProxy/net.hadess.SensorProxy.xml",
|
|
G_RESOURCE_LOOKUP_FLAGS_NONE,
|
|
NULL);
|
|
data->introspection_data = g_dbus_node_info_new_for_xml (g_bytes_get_data (bytes, NULL), NULL);
|
|
g_bytes_unref (bytes);
|
|
g_assert (data->introspection_data != NULL);
|
|
|
|
data->name_id = g_bus_own_name (G_BUS_TYPE_SYSTEM,
|
|
SENSOR_PROXY_DBUS_NAME,
|
|
G_BUS_NAME_OWNER_FLAGS_NONE,
|
|
bus_acquired_handler,
|
|
name_acquired_handler,
|
|
name_lost_handler,
|
|
data,
|
|
NULL);
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
accel_changed_func (SensorDriver *driver,
|
|
gpointer readings_data,
|
|
gpointer user_data)
|
|
{
|
|
SensorData *data = user_data;
|
|
AccelReadings *readings = (AccelReadings *) readings_data;
|
|
OrientationUp orientation = data->previous_orientation;
|
|
|
|
//FIXME handle errors
|
|
g_debug ("Accel sent by driver (quirk applied): %d, %d, %d", readings->accel_x, readings->accel_y, readings->accel_z);
|
|
|
|
orientation = orientation_calc (data->previous_orientation, readings->accel_x, readings->accel_y, readings->accel_z);
|
|
|
|
data->accel_x = readings->accel_x;
|
|
data->accel_y = readings->accel_y;
|
|
data->accel_z = readings->accel_z;
|
|
|
|
if (data->previous_orientation != orientation) {
|
|
OrientationUp tmp;
|
|
|
|
tmp = data->previous_orientation;
|
|
data->previous_orientation = orientation;
|
|
send_dbus_event (data, PROP_ACCELEROMETER_ORIENTATION);
|
|
g_debug ("Emitted orientation changed: from %s to %s",
|
|
orientation_to_string (tmp),
|
|
orientation_to_string (data->previous_orientation));
|
|
}
|
|
}
|
|
|
|
static void
|
|
light_changed_func (SensorDriver *driver,
|
|
gpointer readings_data,
|
|
gpointer user_data)
|
|
{
|
|
SensorData *data = user_data;
|
|
LightReadings *readings = (LightReadings *) readings_data;
|
|
|
|
//FIXME handle errors
|
|
g_debug ("Light level sent by driver (quirk applied): %lf (unit: %s)",
|
|
readings->level, data->uses_lux ? "lux" : "vendor");
|
|
|
|
if (data->previous_level != readings->level ||
|
|
data->uses_lux != readings->uses_lux) {
|
|
gdouble tmp;
|
|
|
|
tmp = data->previous_level;
|
|
data->previous_level = readings->level;
|
|
|
|
data->uses_lux = readings->uses_lux;
|
|
|
|
send_dbus_event (data, PROP_LIGHT_LEVEL);
|
|
g_debug ("Emitted light changed: from %lf to %lf",
|
|
tmp, data->previous_level);
|
|
}
|
|
}
|
|
|
|
static ReadingsUpdateFunc
|
|
driver_type_to_callback_func (DriverType type)
|
|
{
|
|
switch (type) {
|
|
case DRIVER_TYPE_ACCEL:
|
|
return accel_changed_func;
|
|
case DRIVER_TYPE_LIGHT:
|
|
return light_changed_func;
|
|
default:
|
|
g_assert_not_reached ();
|
|
}
|
|
}
|
|
|
|
static void
|
|
free_orientation_data (SensorData *data)
|
|
{
|
|
guint i;
|
|
|
|
if (data == NULL)
|
|
return;
|
|
|
|
if (data->name_id != 0) {
|
|
g_bus_unown_name (data->name_id);
|
|
data->name_id = 0;
|
|
}
|
|
|
|
for (i = 0; i < NUM_SENSOR_TYPES; i++) {
|
|
if (driver_type_exists (data, i))
|
|
driver_close (DRIVER_FOR_TYPE(i));
|
|
g_clear_object (&DEVICE_FOR_TYPE(i));
|
|
g_clear_pointer (&data->clients[i], g_hash_table_unref);
|
|
}
|
|
|
|
g_clear_pointer (&data->introspection_data, g_dbus_node_info_unref);
|
|
g_clear_object (&data->connection);
|
|
g_clear_pointer (&data->loop, g_main_loop_unref);
|
|
g_free (data);
|
|
}
|
|
|
|
static void
|
|
sensor_changes (GUdevClient *client,
|
|
gchar *action,
|
|
GUdevDevice *device,
|
|
SensorData *data)
|
|
{
|
|
guint i;
|
|
|
|
if (g_strcmp0 (action, "remove") == 0) {
|
|
for (i = 0; i < NUM_SENSOR_TYPES; i++) {
|
|
GUdevDevice *dev = DEVICE_FOR_TYPE(i);
|
|
|
|
if (!dev)
|
|
continue;
|
|
|
|
if (g_strcmp0 (g_udev_device_get_sysfs_path (device), g_udev_device_get_sysfs_path (dev)) == 0) {
|
|
g_debug ("Sensor type %s got removed (%s)",
|
|
driver_type_to_str (i),
|
|
g_udev_device_get_sysfs_path (dev));
|
|
g_clear_object (&DEVICE_FOR_TYPE(i));
|
|
DRIVER_FOR_TYPE(i) = NULL;
|
|
send_driver_changed_dbus_event (data, i);
|
|
}
|
|
}
|
|
|
|
if (!any_sensors_left (data))
|
|
g_main_loop_quit (data->loop);
|
|
} else if (g_strcmp0 (action, "add") == 0) {
|
|
guint i;
|
|
|
|
for (i = 0; i < G_N_ELEMENTS(drivers); i++) {
|
|
SensorDriver *driver = (SensorDriver *) drivers[i];
|
|
if (!driver_type_exists (data, driver->type) &&
|
|
driver_discover (driver, device)) {
|
|
g_debug ("Found hotplugged device %s of type %s at %s",
|
|
g_udev_device_get_sysfs_path (device),
|
|
driver_type_to_str (driver->type),
|
|
driver->name);
|
|
|
|
if (driver_open (driver, device,
|
|
driver_type_to_callback_func (driver->type), data)) {
|
|
DEVICE_FOR_TYPE(driver->type) = g_object_ref (device);
|
|
DRIVER_FOR_TYPE(driver->type) = (SensorDriver *) driver;
|
|
send_driver_changed_dbus_event (data, driver->type);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
int main (int argc, char **argv)
|
|
{
|
|
SensorData *data;
|
|
GUdevClient *client;
|
|
int ret = 0;
|
|
const gchar * const subsystems[] = { "iio", "input", "platform", NULL };
|
|
guint i;
|
|
|
|
/* g_setenv ("G_MESSAGES_DEBUG", "all", TRUE); */
|
|
|
|
data = g_new0 (SensorData, 1);
|
|
data->previous_orientation = ORIENTATION_UNDEFINED;
|
|
data->uses_lux = TRUE;
|
|
|
|
/* Set up D-Bus */
|
|
setup_dbus (data);
|
|
|
|
client = g_udev_client_new (subsystems);
|
|
if (!find_sensors (client, data)) {
|
|
g_debug ("Could not find any supported sensors");
|
|
return 0;
|
|
}
|
|
g_signal_connect (G_OBJECT (client), "uevent",
|
|
G_CALLBACK (sensor_changes), data);
|
|
|
|
for (i = 0; i < NUM_SENSOR_TYPES; i++) {
|
|
data->clients[i] = g_hash_table_new_full (g_str_hash,
|
|
g_str_equal,
|
|
g_free,
|
|
NULL);
|
|
|
|
if (!driver_type_exists (data, i))
|
|
continue;
|
|
|
|
if (!data->drivers[i]->open (DEVICE_FOR_TYPE(i),
|
|
driver_type_to_callback_func (data->drivers[i]->type),
|
|
data)) {
|
|
DRIVER_FOR_TYPE(i) = NULL;
|
|
g_clear_object (&DEVICE_FOR_TYPE(i));
|
|
}
|
|
}
|
|
|
|
if (!any_sensors_left (data))
|
|
goto out;
|
|
|
|
data->init_done = TRUE;
|
|
if (data->connection)
|
|
send_dbus_event (data, PROP_ALL);
|
|
|
|
data->loop = g_main_loop_new (NULL, TRUE);
|
|
g_main_loop_run (data->loop);
|
|
|
|
out:
|
|
free_orientation_data (data);
|
|
|
|
return ret;
|
|
}
|