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
This commit is contained in:
@@ -132,6 +132,23 @@ find_sensors (GUdevClient *client,
|
|||||||
return found;
|
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 {
|
typedef enum {
|
||||||
PROP_HAS_ACCELEROMETER = 1 << 0,
|
PROP_HAS_ACCELEROMETER = 1 << 0,
|
||||||
PROP_ACCELEROMETER_ORIENTATION = 1 << 1,
|
PROP_ACCELEROMETER_ORIENTATION = 1 << 1,
|
||||||
@@ -233,11 +250,10 @@ any_sensors_left (SensorData *data)
|
|||||||
return exists;
|
return exists;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static void
|
||||||
client_release (SensorData *data,
|
client_release (SensorData *data,
|
||||||
const char *sender,
|
const char *sender,
|
||||||
DriverType driver_type,
|
DriverType driver_type)
|
||||||
GDBusMethodInvocation *invocation)
|
|
||||||
{
|
{
|
||||||
GHashTable *ht;
|
GHashTable *ht;
|
||||||
guint watch_id;
|
guint watch_id;
|
||||||
@@ -245,24 +261,13 @@ client_release (SensorData *data,
|
|||||||
ht = data->clients[driver_type];
|
ht = data->clients[driver_type];
|
||||||
|
|
||||||
watch_id = GPOINTER_TO_UINT (g_hash_table_lookup (ht, sender));
|
watch_id = GPOINTER_TO_UINT (g_hash_table_lookup (ht, sender));
|
||||||
if (watch_id == 0) {
|
if (watch_id == 0)
|
||||||
if (invocation) {
|
return;
|
||||||
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);
|
g_hash_table_remove (ht, sender);
|
||||||
|
|
||||||
if (g_hash_table_size (ht) == 0)
|
if (g_hash_table_size (ht) == 0)
|
||||||
driver_set_polling (DRIVER_FOR_TYPE(driver_type), FALSE);
|
driver_set_polling (DRIVER_FOR_TYPE(driver_type), FALSE);
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -288,7 +293,7 @@ client_vanished_cb (GDBusConnection *connection,
|
|||||||
|
|
||||||
watch_id = GPOINTER_TO_UINT (g_hash_table_lookup (ht, sender));
|
watch_id = GPOINTER_TO_UINT (g_hash_table_lookup (ht, sender));
|
||||||
if (watch_id > 0)
|
if (watch_id > 0)
|
||||||
client_release (data, sender, i, NULL);
|
client_release (data, sender, i);
|
||||||
}
|
}
|
||||||
|
|
||||||
g_free (sender);
|
g_free (sender);
|
||||||
@@ -323,15 +328,6 @@ handle_method_call (GDBusConnection *connection,
|
|||||||
return;
|
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];
|
ht = data->clients[driver_type];
|
||||||
|
|
||||||
if (g_str_has_prefix (method_name, "Claim")) {
|
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 */
|
/* 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);
|
driver_set_polling (DRIVER_FOR_TYPE(driver_type), TRUE);
|
||||||
|
|
||||||
watch_id = g_bus_watch_name_on_connection (data->connection,
|
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);
|
g_dbus_method_invocation_return_value (invocation, NULL);
|
||||||
} else if (g_str_has_prefix (method_name, "Release")) {
|
} else if (g_str_has_prefix (method_name, "Release")) {
|
||||||
if (client_release (data, sender, driver_type, invocation))
|
client_release (data, sender, driver_type);
|
||||||
g_dbus_method_invocation_return_value (invocation, NULL);
|
g_dbus_method_invocation_return_value (invocation, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -576,8 +573,13 @@ sensor_changes (GUdevClient *client,
|
|||||||
g_debug ("Sensor type %s got removed (%s)",
|
g_debug ("Sensor type %s got removed (%s)",
|
||||||
driver_type_to_str (i),
|
driver_type_to_str (i),
|
||||||
g_udev_device_get_sysfs_path (dev));
|
g_udev_device_get_sysfs_path (dev));
|
||||||
|
|
||||||
g_clear_object (&DEVICE_FOR_TYPE(i));
|
g_clear_object (&DEVICE_FOR_TYPE(i));
|
||||||
DRIVER_FOR_TYPE(i) = NULL;
|
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);
|
send_driver_changed_dbus_event (data, i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -598,9 +600,16 @@ sensor_changes (GUdevClient *client,
|
|||||||
|
|
||||||
if (driver_open (driver, device,
|
if (driver_open (driver, device,
|
||||||
driver_type_to_callback_func (driver->type), data)) {
|
driver_type_to_callback_func (driver->type), data)) {
|
||||||
|
GHashTable *ht;
|
||||||
|
|
||||||
DEVICE_FOR_TYPE(driver->type) = g_object_ref (device);
|
DEVICE_FOR_TYPE(driver->type) = g_object_ref (device);
|
||||||
DRIVER_FOR_TYPE(driver->type) = (SensorDriver *) driver;
|
DRIVER_FOR_TYPE(driver->type) = (SensorDriver *) driver;
|
||||||
send_driver_changed_dbus_event (data, driver->type);
|
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;
|
break;
|
||||||
}
|
}
|
||||||
@@ -634,10 +643,7 @@ int main (int argc, char **argv)
|
|||||||
G_CALLBACK (sensor_changes), data);
|
G_CALLBACK (sensor_changes), data);
|
||||||
|
|
||||||
for (i = 0; i < NUM_SENSOR_TYPES; i++) {
|
for (i = 0; i < NUM_SENSOR_TYPES; i++) {
|
||||||
data->clients[i] = g_hash_table_new_full (g_str_hash,
|
data->clients[i] = create_clients_hash_table ();
|
||||||
g_str_equal,
|
|
||||||
g_free,
|
|
||||||
NULL);
|
|
||||||
|
|
||||||
if (!driver_type_exists (data, i))
|
if (!driver_type_exists (data, i))
|
||||||
continue;
|
continue;
|
||||||
|
@@ -58,10 +58,6 @@ appeared_cb (GDBusConnection *connection,
|
|||||||
gpointer user_data)
|
gpointer user_data)
|
||||||
{
|
{
|
||||||
GError *error = NULL;
|
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,
|
iio_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
|
||||||
G_DBUS_PROXY_FLAGS_NONE,
|
G_DBUS_PROXY_FLAGS_NONE,
|
||||||
@@ -75,38 +71,22 @@ appeared_cb (GDBusConnection *connection,
|
|||||||
G_CALLBACK (properties_changed), NULL);
|
G_CALLBACK (properties_changed), NULL);
|
||||||
|
|
||||||
/* Accelerometer */
|
/* Accelerometer */
|
||||||
v = g_dbus_proxy_get_cached_property (iio_proxy, "HasAccelerometer");
|
g_dbus_proxy_call_sync (iio_proxy,
|
||||||
if (v) {
|
"ClaimAccelerometer",
|
||||||
has_accel = g_variant_get_boolean (v);
|
NULL,
|
||||||
g_variant_unref (v);
|
G_DBUS_CALL_FLAGS_NONE,
|
||||||
}
|
-1,
|
||||||
if (has_accel && !accel_claimed) {
|
NULL, &error);
|
||||||
g_dbus_proxy_call_sync (iio_proxy,
|
g_assert_no_error (error);
|
||||||
"ClaimAccelerometer",
|
|
||||||
NULL,
|
|
||||||
G_DBUS_CALL_FLAGS_NONE,
|
|
||||||
-1,
|
|
||||||
NULL, &error);
|
|
||||||
g_assert_no_error (error);
|
|
||||||
accel_claimed = TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ALS */
|
/* ALS */
|
||||||
v = g_dbus_proxy_get_cached_property (iio_proxy, "HasAmbientLight");
|
g_dbus_proxy_call_sync (iio_proxy,
|
||||||
if (v) {
|
"ClaimLight",
|
||||||
has_als = g_variant_get_boolean (v);
|
NULL,
|
||||||
g_variant_unref (v);
|
G_DBUS_CALL_FLAGS_NONE,
|
||||||
}
|
-1,
|
||||||
if (has_als && !als_claimed) {
|
NULL, &error);
|
||||||
g_dbus_proxy_call_sync (iio_proxy,
|
g_assert_no_error (error);
|
||||||
"ClaimLight",
|
|
||||||
NULL,
|
|
||||||
G_DBUS_CALL_FLAGS_NONE,
|
|
||||||
-1,
|
|
||||||
NULL, &error);
|
|
||||||
g_assert_no_error (error);
|
|
||||||
als_claimed = TRUE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@@ -66,7 +66,9 @@
|
|||||||
ClaimAccelerometer:
|
ClaimAccelerometer:
|
||||||
|
|
||||||
To start receiving accelerometer reading updates from the proxy, the application
|
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
|
Applications should call net.hadess.SensorProxy.ReleaseAccelerometer() when
|
||||||
readings are not required anymore. For example, an application that monitors
|
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
|
This should be called as soon as readings are not required anymore. Note
|
||||||
that resources are freed up if a monitoring application exits without
|
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.
|
||||||
-->
|
-->
|
||||||
<method name="ReleaseAccelerometer"/>
|
<method name="ReleaseAccelerometer"/>
|
||||||
|
|
||||||
@@ -91,7 +93,9 @@
|
|||||||
ClaimLight:
|
ClaimLight:
|
||||||
|
|
||||||
To start receiving ambient light sensor reading updates from the proxy, the
|
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
|
Applications should call net.hadess.SensorProxy.ReleaseLight() when readings are
|
||||||
not required anymore. For example, an application that monitors the ambient light
|
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
|
This should be called as soon as readings are not required anymore. Note
|
||||||
that resources are freed up if a monitoring application exits without
|
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.
|
||||||
-->
|
-->
|
||||||
<method name="ReleaseLight"/>
|
<method name="ReleaseLight"/>
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user