Support proximity polling sensors
This commit is contained in:

committed by
Bastien Nocera

parent
9e22ff5d9d
commit
7024b9c45a
@@ -17,6 +17,7 @@ iio_sensor_proxy_SOURCES = \
|
|||||||
orientation.h \
|
orientation.h \
|
||||||
drv-iio-buffer-accel.c \
|
drv-iio-buffer-accel.c \
|
||||||
drv-iio-poll-accel.c \
|
drv-iio-poll-accel.c \
|
||||||
|
drv-iio-poll-proximity.c \
|
||||||
drv-input-accel.c \
|
drv-input-accel.c \
|
||||||
drv-fake-compass.c \
|
drv-fake-compass.c \
|
||||||
drv-fake-light.c \
|
drv-fake-light.c \
|
||||||
|
@@ -15,6 +15,7 @@ typedef enum {
|
|||||||
DRIVER_TYPE_ACCEL,
|
DRIVER_TYPE_ACCEL,
|
||||||
DRIVER_TYPE_LIGHT,
|
DRIVER_TYPE_LIGHT,
|
||||||
DRIVER_TYPE_COMPASS,
|
DRIVER_TYPE_COMPASS,
|
||||||
|
DRIVER_TYPE_PROXIMITY,
|
||||||
} DriverType;
|
} DriverType;
|
||||||
|
|
||||||
/* Driver types */
|
/* Driver types */
|
||||||
@@ -36,6 +37,16 @@ typedef enum {
|
|||||||
DRIVER_TYPE_COMPASS_FAKE
|
DRIVER_TYPE_COMPASS_FAKE
|
||||||
} DriverTypeCompass;
|
} DriverTypeCompass;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
DRIVER_TYPE_PROXIMITY_IIO,
|
||||||
|
} DriverTypeProximity;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
PROXIMITY_NEAR_ERROR = -1,
|
||||||
|
PROXIMITY_NEAR_FALSE = 0,
|
||||||
|
PROXIMITY_NEAR_TRUE = 1,
|
||||||
|
} ProximityNear;
|
||||||
|
|
||||||
typedef struct SensorDriver SensorDriver;
|
typedef struct SensorDriver SensorDriver;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@@ -54,6 +65,10 @@ typedef struct {
|
|||||||
gdouble heading;
|
gdouble heading;
|
||||||
} CompassReadings;
|
} CompassReadings;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
ProximityNear is_near;
|
||||||
|
} ProximityReadings;
|
||||||
|
|
||||||
typedef void (*ReadingsUpdateFunc) (SensorDriver *driver,
|
typedef void (*ReadingsUpdateFunc) (SensorDriver *driver,
|
||||||
gpointer readings,
|
gpointer readings,
|
||||||
gpointer user_data);
|
gpointer user_data);
|
||||||
@@ -132,3 +147,4 @@ extern SensorDriver iio_poll_light;
|
|||||||
extern SensorDriver hwmon_light;
|
extern SensorDriver hwmon_light;
|
||||||
extern SensorDriver iio_buffer_light;
|
extern SensorDriver iio_buffer_light;
|
||||||
extern SensorDriver iio_buffer_compass;
|
extern SensorDriver iio_buffer_compass;
|
||||||
|
extern SensorDriver iio_poll_proximity;
|
||||||
|
127
src/drv-iio-poll-proximity.c
Normal file
127
src/drv-iio-poll-proximity.c
Normal file
@@ -0,0 +1,127 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2019 Purism SPC
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 3 as published by
|
||||||
|
* the Free Software Foundation.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "drivers.h"
|
||||||
|
#include "iio-buffer-utils.h"
|
||||||
|
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
/* FIXME: This needs to come from udev since it's device dependent */
|
||||||
|
#define NEAR_LEVEL 200
|
||||||
|
|
||||||
|
typedef struct DrvData {
|
||||||
|
guint timeout_id;
|
||||||
|
ReadingsUpdateFunc callback_func;
|
||||||
|
gpointer user_data;
|
||||||
|
GUdevDevice *dev;
|
||||||
|
const char *name;
|
||||||
|
} DrvData;
|
||||||
|
|
||||||
|
static DrvData *drv_data = NULL;
|
||||||
|
|
||||||
|
static int
|
||||||
|
sysfs_get_int (GUdevDevice *dev,
|
||||||
|
const char *attribute)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
char *contents;
|
||||||
|
char *filename;
|
||||||
|
|
||||||
|
result = 0;
|
||||||
|
filename = g_build_filename (g_udev_device_get_sysfs_path (dev), attribute, NULL);
|
||||||
|
if (g_file_get_contents (filename, &contents, NULL, NULL)) {
|
||||||
|
result = atoi (contents);
|
||||||
|
g_free (contents);
|
||||||
|
}
|
||||||
|
g_free (filename);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
poll_proximity (gpointer user_data)
|
||||||
|
{
|
||||||
|
DrvData *data = user_data;
|
||||||
|
ProximityReadings readings;
|
||||||
|
gint prox;
|
||||||
|
|
||||||
|
/* g_udev_device_get_sysfs_attr_as_int does not update when there's no event */
|
||||||
|
prox = sysfs_get_int (data->dev, "in_proximity_raw");
|
||||||
|
readings.is_near = (prox > NEAR_LEVEL) ? TRUE : FALSE;
|
||||||
|
g_debug ("Proximity read from IIO on '%s': %d, near: %d", data->name, prox, readings.is_near);
|
||||||
|
|
||||||
|
drv_data->callback_func (&iio_poll_proximity, (gpointer) &readings, drv_data->user_data);
|
||||||
|
|
||||||
|
return G_SOURCE_CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
iio_poll_proximity_discover (GUdevDevice *device)
|
||||||
|
{
|
||||||
|
/* We also handle devices with trigger buffers, but there's no trigger available on the system */
|
||||||
|
if (g_strcmp0 (g_udev_device_get_property (device, "IIO_SENSOR_PROXY_TYPE"), "iio-poll-proximity") != 0)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
g_debug ("Found IIO poll proximity sensor at %s", g_udev_device_get_sysfs_path (device));
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
iio_poll_proximity_set_polling (gboolean state)
|
||||||
|
{
|
||||||
|
if (drv_data->timeout_id > 0 && state)
|
||||||
|
return;
|
||||||
|
if (drv_data->timeout_id == 0 && !state)
|
||||||
|
return;
|
||||||
|
|
||||||
|
g_clear_handle_id (&drv_data->timeout_id, g_source_remove);
|
||||||
|
if (state) {
|
||||||
|
drv_data->timeout_id = g_timeout_add (700, poll_proximity, drv_data);
|
||||||
|
g_source_set_name_by_id (drv_data->timeout_id, "[iio_poll_proximity_set_polling] poll_proximity");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
iio_poll_proximity_open (GUdevDevice *device,
|
||||||
|
ReadingsUpdateFunc callback_func,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
iio_fixup_sampling_frequency (device);
|
||||||
|
|
||||||
|
drv_data = g_new0 (DrvData, 1);
|
||||||
|
drv_data->dev = g_object_ref (device);
|
||||||
|
drv_data->name = g_udev_device_get_sysfs_attr (device, "name");
|
||||||
|
drv_data->callback_func = callback_func;
|
||||||
|
drv_data->user_data = user_data;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
iio_poll_proximity_close (void)
|
||||||
|
{
|
||||||
|
iio_poll_proximity_set_polling (FALSE);
|
||||||
|
g_clear_object (&drv_data->dev);
|
||||||
|
g_clear_pointer (&drv_data, g_free);
|
||||||
|
}
|
||||||
|
|
||||||
|
SensorDriver iio_poll_proximity = {
|
||||||
|
.name = "IIO Poll proximity sensor",
|
||||||
|
.type = DRIVER_TYPE_PROXIMITY,
|
||||||
|
.specific_type = DRIVER_TYPE_PROXIMITY_IIO,
|
||||||
|
|
||||||
|
.discover = iio_poll_proximity_discover,
|
||||||
|
.open = iio_poll_proximity_open,
|
||||||
|
.set_polling = iio_poll_proximity_set_polling,
|
||||||
|
.close = iio_poll_proximity_close,
|
||||||
|
};
|
@@ -29,7 +29,7 @@
|
|||||||
#define SENSOR_PROXY_IFACE_NAME SENSOR_PROXY_DBUS_NAME
|
#define SENSOR_PROXY_IFACE_NAME SENSOR_PROXY_DBUS_NAME
|
||||||
#define SENSOR_PROXY_COMPASS_IFACE_NAME SENSOR_PROXY_DBUS_NAME ".Compass"
|
#define SENSOR_PROXY_COMPASS_IFACE_NAME SENSOR_PROXY_DBUS_NAME ".Compass"
|
||||||
|
|
||||||
#define NUM_SENSOR_TYPES DRIVER_TYPE_COMPASS + 1
|
#define NUM_SENSOR_TYPES DRIVER_TYPE_PROXIMITY + 1
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
GMainLoop *loop;
|
GMainLoop *loop;
|
||||||
@@ -52,6 +52,9 @@ typedef struct {
|
|||||||
|
|
||||||
/* Compass */
|
/* Compass */
|
||||||
gdouble previous_heading;
|
gdouble previous_heading;
|
||||||
|
|
||||||
|
/* Proximity */
|
||||||
|
gboolean previous_prox_near;
|
||||||
} SensorData;
|
} SensorData;
|
||||||
|
|
||||||
static const SensorDriver * const drivers[] = {
|
static const SensorDriver * const drivers[] = {
|
||||||
@@ -63,7 +66,8 @@ static const SensorDriver * const drivers[] = {
|
|||||||
&hwmon_light,
|
&hwmon_light,
|
||||||
&fake_compass,
|
&fake_compass,
|
||||||
&fake_light,
|
&fake_light,
|
||||||
&iio_buffer_compass
|
&iio_buffer_compass,
|
||||||
|
&iio_poll_proximity,
|
||||||
};
|
};
|
||||||
|
|
||||||
static ReadingsUpdateFunc driver_type_to_callback_func (DriverType type);
|
static ReadingsUpdateFunc driver_type_to_callback_func (DriverType type);
|
||||||
@@ -78,6 +82,8 @@ driver_type_to_str (DriverType type)
|
|||||||
return "ambient light sensor";
|
return "ambient light sensor";
|
||||||
case DRIVER_TYPE_COMPASS:
|
case DRIVER_TYPE_COMPASS:
|
||||||
return "compass";
|
return "compass";
|
||||||
|
case DRIVER_TYPE_PROXIMITY:
|
||||||
|
return "proximity";
|
||||||
default:
|
default:
|
||||||
g_assert_not_reached ();
|
g_assert_not_reached ();
|
||||||
}
|
}
|
||||||
@@ -133,6 +139,7 @@ find_sensors (GUdevClient *client,
|
|||||||
|
|
||||||
if (driver_type_exists (data, DRIVER_TYPE_ACCEL) &&
|
if (driver_type_exists (data, DRIVER_TYPE_ACCEL) &&
|
||||||
driver_type_exists (data, DRIVER_TYPE_LIGHT) &&
|
driver_type_exists (data, DRIVER_TYPE_LIGHT) &&
|
||||||
|
driver_type_exists (data, DRIVER_TYPE_PROXIMITY) &&
|
||||||
driver_type_exists (data, DRIVER_TYPE_COMPASS))
|
driver_type_exists (data, DRIVER_TYPE_COMPASS))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -164,13 +171,17 @@ typedef enum {
|
|||||||
PROP_HAS_AMBIENT_LIGHT = 1 << 2,
|
PROP_HAS_AMBIENT_LIGHT = 1 << 2,
|
||||||
PROP_LIGHT_LEVEL = 1 << 3,
|
PROP_LIGHT_LEVEL = 1 << 3,
|
||||||
PROP_HAS_COMPASS = 1 << 4,
|
PROP_HAS_COMPASS = 1 << 4,
|
||||||
PROP_COMPASS_HEADING = 1 << 5
|
PROP_COMPASS_HEADING = 1 << 5,
|
||||||
|
PROP_HAS_PROXIMITY = 1 << 6,
|
||||||
|
PROP_PROXIMITY_NEAR = 1 << 7,
|
||||||
} PropertiesMask;
|
} PropertiesMask;
|
||||||
|
|
||||||
#define PROP_ALL (PROP_HAS_ACCELEROMETER | \
|
#define PROP_ALL (PROP_HAS_ACCELEROMETER | \
|
||||||
PROP_ACCELEROMETER_ORIENTATION | \
|
PROP_ACCELEROMETER_ORIENTATION | \
|
||||||
PROP_HAS_AMBIENT_LIGHT | \
|
PROP_HAS_AMBIENT_LIGHT | \
|
||||||
PROP_LIGHT_LEVEL)
|
PROP_LIGHT_LEVEL | \
|
||||||
|
PROP_HAS_PROXIMITY | \
|
||||||
|
PROP_PROXIMITY_NEAR)
|
||||||
#define PROP_ALL_COMPASS (PROP_HAS_COMPASS | \
|
#define PROP_ALL_COMPASS (PROP_HAS_COMPASS | \
|
||||||
PROP_COMPASS_HEADING)
|
PROP_COMPASS_HEADING)
|
||||||
|
|
||||||
@@ -245,6 +256,23 @@ send_dbus_event (SensorData *data,
|
|||||||
g_variant_new_double (data->previous_heading));
|
g_variant_new_double (data->previous_heading));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mask & PROP_HAS_PROXIMITY) {
|
||||||
|
gboolean has_proximity;
|
||||||
|
|
||||||
|
has_proximity = driver_type_exists (data, DRIVER_TYPE_PROXIMITY);
|
||||||
|
g_variant_builder_add (&props_builder, "{sv}", "HasProximity",
|
||||||
|
g_variant_new_boolean (has_proximity));
|
||||||
|
|
||||||
|
/* Send proximity information when the device appears */
|
||||||
|
if (has_proximity)
|
||||||
|
mask |= PROP_PROXIMITY_NEAR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mask & PROP_PROXIMITY_NEAR) {
|
||||||
|
g_variant_builder_add (&props_builder, "{sv}", "ProximityNear",
|
||||||
|
g_variant_new_boolean (data->previous_prox_near));
|
||||||
|
}
|
||||||
|
|
||||||
props_changed = g_variant_new ("(s@a{sv}@as)", (mask & PROP_ALL) ? SENSOR_PROXY_IFACE_NAME : SENSOR_PROXY_COMPASS_IFACE_NAME,
|
props_changed = g_variant_new ("(s@a{sv}@as)", (mask & PROP_ALL) ? SENSOR_PROXY_IFACE_NAME : SENSOR_PROXY_COMPASS_IFACE_NAME,
|
||||||
g_variant_builder_end (&props_builder),
|
g_variant_builder_end (&props_builder),
|
||||||
g_variant_new_strv (NULL, 0));
|
g_variant_new_strv (NULL, 0));
|
||||||
@@ -265,6 +293,8 @@ send_driver_changed_dbus_event (SensorData *data,
|
|||||||
send_dbus_event (data, PROP_HAS_ACCELEROMETER);
|
send_dbus_event (data, PROP_HAS_ACCELEROMETER);
|
||||||
else if (driver_type == DRIVER_TYPE_LIGHT)
|
else if (driver_type == DRIVER_TYPE_LIGHT)
|
||||||
send_dbus_event (data, PROP_HAS_AMBIENT_LIGHT);
|
send_dbus_event (data, PROP_HAS_AMBIENT_LIGHT);
|
||||||
|
else if (driver_type == DRIVER_TYPE_PROXIMITY)
|
||||||
|
send_dbus_event (data, PROP_HAS_PROXIMITY);
|
||||||
else if (driver_type == DRIVER_TYPE_COMPASS)
|
else if (driver_type == DRIVER_TYPE_COMPASS)
|
||||||
send_dbus_event (data, PROP_HAS_COMPASS);
|
send_dbus_event (data, PROP_HAS_COMPASS);
|
||||||
else
|
else
|
||||||
@@ -402,6 +432,9 @@ handle_method_call (GDBusConnection *connection,
|
|||||||
else if (g_strcmp0 (method_name, "ClaimLight") == 0 ||
|
else if (g_strcmp0 (method_name, "ClaimLight") == 0 ||
|
||||||
g_strcmp0 (method_name, "ReleaseLight") == 0)
|
g_strcmp0 (method_name, "ReleaseLight") == 0)
|
||||||
driver_type = DRIVER_TYPE_LIGHT;
|
driver_type = DRIVER_TYPE_LIGHT;
|
||||||
|
else if (g_strcmp0 (method_name, "ClaimProximity") == 0 ||
|
||||||
|
g_strcmp0 (method_name, "ReleaseProximity") == 0)
|
||||||
|
driver_type = DRIVER_TYPE_PROXIMITY;
|
||||||
else {
|
else {
|
||||||
g_dbus_method_invocation_return_error (invocation,
|
g_dbus_method_invocation_return_error (invocation,
|
||||||
G_DBUS_ERROR,
|
G_DBUS_ERROR,
|
||||||
@@ -439,6 +472,10 @@ handle_get_property (GDBusConnection *connection,
|
|||||||
return g_variant_new_string (data->uses_lux ? "lux" : "vendor");
|
return g_variant_new_string (data->uses_lux ? "lux" : "vendor");
|
||||||
if (g_strcmp0 (property_name, "LightLevel") == 0)
|
if (g_strcmp0 (property_name, "LightLevel") == 0)
|
||||||
return g_variant_new_double (data->previous_level);
|
return g_variant_new_double (data->previous_level);
|
||||||
|
if (g_strcmp0 (property_name, "HasProximity") == 0)
|
||||||
|
return g_variant_new_boolean (driver_type_exists (data, DRIVER_TYPE_PROXIMITY));
|
||||||
|
if (g_strcmp0 (property_name, "ProximityNear") == 0)
|
||||||
|
return g_variant_new_boolean (data->previous_prox_near);
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -684,6 +721,32 @@ compass_changed_func (SensorDriver *driver,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
proximity_changed_func (SensorDriver *driver,
|
||||||
|
gpointer readings_data,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
SensorData *data = user_data;
|
||||||
|
ProximityReadings *readings = (ProximityReadings *) readings_data;
|
||||||
|
gboolean near;
|
||||||
|
|
||||||
|
//FIXME handle errors
|
||||||
|
g_debug ("Proximity sent by driver: %d",
|
||||||
|
readings->is_near);
|
||||||
|
|
||||||
|
near = readings->is_near > 0;
|
||||||
|
if (data->previous_prox_near != near) {
|
||||||
|
ProximityNear tmp;
|
||||||
|
|
||||||
|
tmp = data->previous_prox_near;
|
||||||
|
data->previous_prox_near = near;
|
||||||
|
|
||||||
|
send_dbus_event (data, PROP_PROXIMITY_NEAR);
|
||||||
|
g_debug ("Emitted proximity changed: from %d to %d",
|
||||||
|
tmp, near);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static ReadingsUpdateFunc
|
static ReadingsUpdateFunc
|
||||||
driver_type_to_callback_func (DriverType type)
|
driver_type_to_callback_func (DriverType type)
|
||||||
{
|
{
|
||||||
@@ -694,6 +757,8 @@ driver_type_to_callback_func (DriverType type)
|
|||||||
return light_changed_func;
|
return light_changed_func;
|
||||||
case DRIVER_TYPE_COMPASS:
|
case DRIVER_TYPE_COMPASS:
|
||||||
return compass_changed_func;
|
return compass_changed_func;
|
||||||
|
case DRIVER_TYPE_PROXIMITY:
|
||||||
|
return proximity_changed_func;
|
||||||
default:
|
default:
|
||||||
g_assert_not_reached ();
|
g_assert_not_reached ();
|
||||||
}
|
}
|
||||||
|
@@ -64,6 +64,20 @@
|
|||||||
-->
|
-->
|
||||||
<property name="LightLevel" type="d" access="read"/>
|
<property name="LightLevel" type="d" access="read"/>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
HasProximity:
|
||||||
|
|
||||||
|
Whether a supported proximity sensor is present on the system.
|
||||||
|
-->
|
||||||
|
<property name="HasProximity" type="b" access="read"/>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
ProximityNear:
|
||||||
|
|
||||||
|
Whether an object is near to the proximity sensor.
|
||||||
|
-->
|
||||||
|
<property name='ProximityNear' type='b' access='read'/>
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
ClaimAccelerometer:
|
ClaimAccelerometer:
|
||||||
|
|
||||||
@@ -117,6 +131,30 @@
|
|||||||
calling net.hadess.SensorProxy.ReleaseLight(), crashes or the sensor disappears.
|
calling net.hadess.SensorProxy.ReleaseLight(), crashes or the sensor disappears.
|
||||||
-->
|
-->
|
||||||
<method name="ReleaseLight"/>
|
<method name="ReleaseLight"/>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
ClaimProximity:
|
||||||
|
|
||||||
|
To start receiving proximity updates from the proxy, the
|
||||||
|
application must call the net.hadess.SensorProxy.ClaimProximity() method. It can do so
|
||||||
|
whether a proximity is available or not, updates would then be sent
|
||||||
|
when such a sensor appears.
|
||||||
|
|
||||||
|
Applications should call net.hadess.SensorProxy.ReleaseProximity() when readings are
|
||||||
|
not required anymore. This prevents the sensor proxy from polling the device, thus
|
||||||
|
increasing wake-ups and reducing battery life.
|
||||||
|
-->
|
||||||
|
<method name="ClaimProximity"/>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
ReleaseProximity:
|
||||||
|
|
||||||
|
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.ReleaseProximity(), crashes or the sensor disappears.
|
||||||
|
-->
|
||||||
|
<method name="ReleaseProximity"/>
|
||||||
|
|
||||||
</interface>
|
</interface>
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
|
Reference in New Issue
Block a user