From 035ad06eaefbc8471e993700bdf5f0dff62b465b Mon Sep 17 00:00:00 2001 From: Bastien Nocera Date: Thu, 21 May 2015 15:41:52 +0200 Subject: [PATCH] main: Make Claim* calls work before sensor is available It's tedious for clients to know whether they can call Release* when sensors disappear, or making sure that the device is claimed before releasing it when they go in power save mode. You can now claim the sensor whether it's available or not, and it will automatically start sending out the updates when it appears. Closes #23 --- src/iio-sensor-proxy.c | 72 ++++++++++++++++++---------------- src/monitor-sensor.c | 48 +++++++---------------- src/net.hadess.SensorProxy.xml | 12 ++++-- 3 files changed, 61 insertions(+), 71 deletions(-) diff --git a/src/iio-sensor-proxy.c b/src/iio-sensor-proxy.c index c69913c..2f4a172 100644 --- a/src/iio-sensor-proxy.c +++ b/src/iio-sensor-proxy.c @@ -132,6 +132,23 @@ find_sensors (GUdevClient *client, return found; } +static void +free_client_watch (gpointer data) +{ + guint watch_id = GPOINTER_TO_UINT (data); + + if (watch_id == 0) + return; + g_bus_unwatch_name (watch_id); +} + +static GHashTable * +create_clients_hash_table (void) +{ + return g_hash_table_new_full (g_str_hash, g_str_equal, + g_free, free_client_watch); +} + typedef enum { PROP_HAS_ACCELEROMETER = 1 << 0, PROP_ACCELEROMETER_ORIENTATION = 1 << 1, @@ -233,11 +250,10 @@ any_sensors_left (SensorData *data) return exists; } -static gboolean +static void client_release (SensorData *data, const char *sender, - DriverType driver_type, - GDBusMethodInvocation *invocation) + DriverType driver_type) { GHashTable *ht; guint watch_id; @@ -245,24 +261,13 @@ client_release (SensorData *data, 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; - } + if (watch_id == 0) + return; - 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 @@ -288,7 +293,7 @@ client_vanished_cb (GDBusConnection *connection, watch_id = GPOINTER_TO_UINT (g_hash_table_lookup (ht, sender)); if (watch_id > 0) - client_release (data, sender, i, NULL); + client_release (data, sender, i); } g_free (sender); @@ -323,15 +328,6 @@ handle_method_call (GDBusConnection *connection, 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_type_to_str (driver_type)); - return; - } - ht = data->clients[driver_type]; if (g_str_has_prefix (method_name, "Claim")) { @@ -346,7 +342,8 @@ handle_method_call (GDBusConnection *connection, } /* No other clients for this sensor? Start it */ - if (g_hash_table_size (ht) == 0) + if (driver_type_exists (data, driver_type) && + 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, @@ -360,8 +357,8 @@ handle_method_call (GDBusConnection *connection, g_dbus_method_invocation_return_value (invocation, NULL); } else if (g_str_has_prefix (method_name, "Release")) { - if (client_release (data, sender, driver_type, invocation)) - g_dbus_method_invocation_return_value (invocation, NULL); + client_release (data, sender, driver_type); + g_dbus_method_invocation_return_value (invocation, NULL); } } @@ -576,8 +573,13 @@ sensor_changes (GUdevClient *client, 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; + + g_clear_pointer (&data->clients[i], g_hash_table_unref); + data->clients[i] = create_clients_hash_table (); + send_driver_changed_dbus_event (data, i); } } @@ -598,9 +600,16 @@ sensor_changes (GUdevClient *client, if (driver_open (driver, device, driver_type_to_callback_func (driver->type), data)) { + GHashTable *ht; + DEVICE_FOR_TYPE(driver->type) = g_object_ref (device); DRIVER_FOR_TYPE(driver->type) = (SensorDriver *) driver; send_driver_changed_dbus_event (data, driver->type); + + ht = data->clients[driver->type]; + + if (g_hash_table_size (ht) > 0) + driver_set_polling (DRIVER_FOR_TYPE(driver->type), TRUE); } break; } @@ -634,10 +643,7 @@ int main (int argc, char **argv) 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); + data->clients[i] = create_clients_hash_table (); if (!driver_type_exists (data, i)) continue; diff --git a/src/monitor-sensor.c b/src/monitor-sensor.c index 1fbdb1e..955c657 100644 --- a/src/monitor-sensor.c +++ b/src/monitor-sensor.c @@ -58,10 +58,6 @@ appeared_cb (GDBusConnection *connection, gpointer user_data) { GError *error = NULL; - gboolean has_accel, has_als; - GVariant *v; - - has_accel = has_als = FALSE; iio_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, G_DBUS_PROXY_FLAGS_NONE, @@ -75,38 +71,22 @@ appeared_cb (GDBusConnection *connection, G_CALLBACK (properties_changed), NULL); /* Accelerometer */ - v = g_dbus_proxy_get_cached_property (iio_proxy, "HasAccelerometer"); - if (v) { - has_accel = g_variant_get_boolean (v); - g_variant_unref (v); - } - if (has_accel && !accel_claimed) { - g_dbus_proxy_call_sync (iio_proxy, - "ClaimAccelerometer", - NULL, - G_DBUS_CALL_FLAGS_NONE, - -1, - NULL, &error); - g_assert_no_error (error); - accel_claimed = TRUE; - } + g_dbus_proxy_call_sync (iio_proxy, + "ClaimAccelerometer", + NULL, + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, &error); + g_assert_no_error (error); /* ALS */ - v = g_dbus_proxy_get_cached_property (iio_proxy, "HasAmbientLight"); - if (v) { - has_als = g_variant_get_boolean (v); - g_variant_unref (v); - } - if (has_als && !als_claimed) { - g_dbus_proxy_call_sync (iio_proxy, - "ClaimLight", - NULL, - G_DBUS_CALL_FLAGS_NONE, - -1, - NULL, &error); - g_assert_no_error (error); - als_claimed = TRUE; - } + g_dbus_proxy_call_sync (iio_proxy, + "ClaimLight", + NULL, + G_DBUS_CALL_FLAGS_NONE, + -1, + NULL, &error); + g_assert_no_error (error); } static void diff --git a/src/net.hadess.SensorProxy.xml b/src/net.hadess.SensorProxy.xml index 5f034f3..34bfa68 100644 --- a/src/net.hadess.SensorProxy.xml +++ b/src/net.hadess.SensorProxy.xml @@ -66,7 +66,9 @@ ClaimAccelerometer: To start receiving accelerometer reading updates from the proxy, the application - must call the net.hadess.SensorProxy.ClaimAccelerometer() method. + must call the net.hadess.SensorProxy.ClaimAccelerometer() method. It can do so + whether an accelerometer is available or not, updates would then be sent when an + accelerometer appears. Applications should call net.hadess.SensorProxy.ReleaseAccelerometer() when readings are not required anymore. For example, an application that monitors @@ -83,7 +85,7 @@ This should be called as soon as readings are not required anymore. Note that resources are freed up if a monitoring application exits without - calling net.hadess.SensorProxy.Release(), or crashes. + calling net.hadess.SensorProxy.Release(), crashes or the sensor disappears. --> @@ -91,7 +93,9 @@ ClaimLight: To start receiving ambient light sensor reading updates from the proxy, the - application must call the net.hadess.SensorProxy.ClaimLight() method. + application must call the net.hadess.SensorProxy.ClaimLight() method. It can do so + whether an ambient light sensor is available or not, updates would then be sent + when such a sensor appears. Applications should call net.hadess.SensorProxy.ReleaseLight() when readings are not required anymore. For example, an application that monitors the ambient light @@ -108,7 +112,7 @@ This should be called as soon as readings are not required anymore. Note that resources are freed up if a monitoring application exits without - calling net.hadess.SensorProxy.Release(), or crashes. + calling net.hadess.SensorProxy.Release(), crashes or the sensor disappears. -->