From 17104348be2a7b6a882b340a2fd24ba9fd62b8a2 Mon Sep 17 00:00:00 2001 From: Simo Piiroinen Date: Fri, 25 May 2018 10:30:18 +0300 Subject: [PATCH] [mce-sensorfw] Refactor mce - sensorfwd IPC. JB#41369 So far MCE has utilized only three sensors - all of which report a single unsigned integer value. This has allowed code to organically grow in to a form that requires numerous glue functions for each sensor type and is ill-prepared for handling sensors that report vector form data. Reduce the amount of glue functions that needs to be implemented for each supported sensor type and stop assuming sensor data will be a single integer value. Handle situations where the standby-override attribute is not supported for an otherwise functioning sensor. Do not attempt to start mce-starting-up exceptional situation before the objects required by such operation have been created. Also fix spelling of some constants from SWF_xxx to SFW_xxx. Signed-off-by: Simo Piiroinen --- Makefile | 1 + mce-dbus.c | 8 +- mce-dbus.h | 2 + mce-sensorfw.c | 1231 ++++++++++++++++++++++++---------------------- mce-sensorfw.dot | 20 +- 5 files changed, 672 insertions(+), 590 deletions(-) diff --git a/Makefile b/Makefile index 49eee387..77c56383 100644 --- a/Makefile +++ b/Makefile @@ -258,6 +258,7 @@ CFLAGS += -Wmissing-format-attribute CFLAGS += -Wstack-protector #CFLAGS += -Werror (OBS build might have different compiler) CFLAGS += -Wno-declaration-after-statement +CFLAGS += -Wno-missing-field-initializers # Linker LDLIBS += -Wl,--as-needed diff --git a/mce-dbus.c b/mce-dbus.c index 5f3abbab..00e14e4e 100644 --- a/mce-dbus.c +++ b/mce-dbus.c @@ -402,8 +402,8 @@ static gboolean dbus_init_message_handler (void); const char *mce_dbus_type_repr (int type); bool mce_dbus_iter_at_end (DBusMessageIter *iter); -static bool mce_dbus_iter_req_type (DBusMessageIter *iter, int want); -static bool mce_dbus_iter_get_basic (DBusMessageIter *iter, void *pval, int type); +bool mce_dbus_iter_req_type (DBusMessageIter *iter, int want); +bool mce_dbus_iter_get_basic (DBusMessageIter *iter, void *pval, int type); bool mce_dbus_iter_get_object (DBusMessageIter *iter, const char **pval); bool mce_dbus_iter_get_string (DBusMessageIter *iter, const char **pval); bool mce_dbus_iter_get_bool (DBusMessageIter *iter, bool *pval); @@ -4475,7 +4475,7 @@ mce_dbus_iter_at_end(DBusMessageIter *iter) * * @return true if iterator points to expected type, false otherwise */ -static bool +bool mce_dbus_iter_req_type(DBusMessageIter *iter, int want) { int have = dbus_message_iter_get_arg_type(iter); @@ -4500,7 +4500,7 @@ mce_dbus_iter_req_type(DBusMessageIter *iter, int want) * * @return true if iterator points to expected type, false otherwise */ -static bool +bool mce_dbus_iter_get_basic(DBusMessageIter *iter, void *pval, int type) { if( !dbus_type_is_basic(type) ) { diff --git a/mce-dbus.h b/mce-dbus.h index bbb5e5a7..7fe6d3c9 100644 --- a/mce-dbus.h +++ b/mce-dbus.h @@ -196,6 +196,8 @@ char *mce_dbus_message_repr(DBusMessage *const msg); char *mce_dbus_message_iter_repr(DBusMessageIter *iter); bool mce_dbus_iter_at_end(DBusMessageIter *iter); +bool mce_dbus_iter_req_type(DBusMessageIter *iter, int want); +bool mce_dbus_iter_get_basic(DBusMessageIter *iter, void *pval, int type); bool mce_dbus_iter_get_object(DBusMessageIter *iter, const char **pval); bool mce_dbus_iter_get_string(DBusMessageIter *iter, const char **pval); bool mce_dbus_iter_get_bool(DBusMessageIter *iter, bool *pval); diff --git a/mce-sensorfw.c b/mce-sensorfw.c index 8d8bc24a..f92f5cc0 100644 --- a/mce-sensorfw.c +++ b/mce-sensorfw.c @@ -188,6 +188,17 @@ * * ========================================================================= */ +/** ID numbers for sensors supported by mce-sensorfwd module + */ +typedef enum +{ + SFW_SENSOR_ID_PS, + SFW_SENSOR_ID_ALS, + SFW_SENSOR_ID_ORIENT, + + SFW_SENSOR_ID_COUNT +} sensor_id_t; + /* ========================================================================= * * D-BUS CONSTANTS FOR D-BUS DAEMON * ========================================================================= */ @@ -223,40 +234,45 @@ // ---------------------------------------------------------------- -/* Note: Every sensor has unique object path & interface */ - -/** D-Bus interface used by proximity sensor plugin */ -#define SENSORFW_SENSOR_INTERFACE_PS "local.ProximitySensor" - -/** D-Bus interface used by ambient light sensor plugin */ -#define SENSORFW_SENSOR_INTERFACE_ALS "local.ALSSensor" - -/** D-Bus interface used by orientation sensor plugin */ -#define SENSORFW_SENSOR_INTERFACE_ORIENT "local.OrientationSensor" - -/* Common methods supported by all sensor interfaces */ - -/** D-Bus method for enabling sensor */ -#define SENSORFW_SENSOR_METHOD_START "start" +/* D-Bus interfaces for accessing sensor specific data + * + * Note: Sensorfwd uses separate interface for each sensor. */ -/** D-Bus method for disabling sensor */ -#define SENSORFW_SENSOR_METHOD_STOP "stop" +#define SFW_SENSOR_INTERFACE_PS "local.ProximitySensor" +#define SFW_SENSOR_INTERFACE_ALS "local.ALSSensor" +#define SFW_SENSOR_INTERFACE_ORIENT "local.OrientationSensor" -/** D-Bus method for changing sensor standby override */ -#define SENSORFW_SENSOR_METHOD_SET_OVERRIDE "setStandbyOverride" +/** D-Bus method for enabling sensor + * + * @Note All sensor specific interfaces have start method. + */ +#define SFW_SENSOR_METHOD_START "start" -/* Note: The sensor specific methods for reading current state - * differ only by method name, so common logic can stll be - * used for making the queries and processing the replies. */ +/** D-Bus method for disabling sensor + * + * @Note All sensor specific interfaces have stop method. + */ +#define SFW_SENSOR_METHOD_STOP "stop" -/** D-Bus method for reading intial proximity state */ -#define SENSORFW_SENSOR_METHOD_READ_PS "proximity" +/** D-Bus method for changing sensor standby override + * + * @Note All sensor specific interfaces have have this method, + * but unless it is actually explicitly implemented, a + * virtual dummy method call handler gets invoked and + * it will just return "false". + */ +#define SFW_SENSOR_METHOD_SET_OVERRIDE "setStandbyOverride" -/** D-Bus method for reading intial ambient light state */ -#define SENSORFW_SENSOR_METHOD_READ_ALS "lux" +/* D-Bus methods for getting current sensor value + * + * The method name and returned data varies from one sensor to + * another, and in some cases there is no "current state" to + * query (such as tap detection sensor which emits events). + */ -/** D-Bus method for reading intial orientation state */ -#define SENSORFW_SENSOR_METHOD_READ_ORIENT "orientation" +#define SFW_SENSOR_METHOD_READ_PS "proximity" +#define SFW_SENSOR_METHOD_READ_ALS "lux" +#define SFW_SENSOR_METHOD_READ_ORIENT "orientation" // ---------------------------------------------------------------- @@ -265,31 +281,85 @@ // ---------------------------------------------------------------- -/** Name of proximity sensor */ -#define SENSORFW_SENSOR_NAME_PS "proximitysensor" +/* Sensor names used by senseofwd */ -/** Name of ambient light sensor */ -#define SENSORFW_SENSOR_NAME_ALS "alssensor" +#define SFW_SENSOR_NAME_PS "proximitysensor" +#define SFW_SENSOR_NAME_ALS "alssensor" +#define SFW_SENSOR_NAME_ORIENT "orientationsensor" -/** Name of orientation sensor */ -#define SENSORFW_SENSOR_NAME_ORIENT "orientationsensor" +// ---------------------------------------------------------------- /* ========================================================================= * * FORWARD_DECLARATIONS * ========================================================================= */ -typedef struct sfw_service_t sfw_service_t; +typedef struct sfw_service_t sfw_service_t; -typedef struct sfw_plugin_t sfw_plugin_t; -typedef struct sfw_session_t sfw_session_t; -typedef struct sfw_connection_t sfw_connection_t; -typedef struct sfw_override_t sfw_override_t; -typedef struct sfw_reporting_t sfw_reporting_t; -typedef struct sfw_backend_t sfw_backend_t; +typedef struct sfw_plugin_t sfw_plugin_t; +typedef struct sfw_session_t sfw_session_t; +typedef struct sfw_connection_t sfw_connection_t; +typedef struct sfw_override_t sfw_override_t; +typedef struct sfw_reporting_t sfw_reporting_t; +typedef struct sfw_backend_t sfw_backend_t; -typedef struct sfw_sample_als_t sfw_sample_als_t; -typedef struct sfw_sample_ps_t sfw_sample_ps_t; -typedef struct sfw_sample_orient_t sfw_sample_orient_t; +typedef struct sfw_sample_als_t sfw_sample_als_t; +typedef struct sfw_sample_ps_t sfw_sample_ps_t; +typedef struct sfw_sample_orient_t sfw_sample_orient_t; + +/* ========================================================================= * + * SENSORFW_NOTIFY + * ========================================================================= */ + +/** Proximity state to use when sensor can't be enabled + * + * This must be "uncovered" so that absense of or failures within + * sensord do not make the device unusable due to proximity values + * blocking display power up and touch input. + */ +#define SFW_NOTIFY_DEFAULT_PS false + +/** Proximity state to use when waiting for sensord startup + * + * This must be "covered" so that we do not prematurely unblock + * touch input / allow display power up during bootup and during + * sensord restarts. + */ +#define SFW_NOTIFY_EXCEPTION_PS true + +/** Ambient light level [lux] to use when sensor can't be enabled */ +#define SFW_NOTIFY_DEFAULT_ALS 400 + +/** Orientation state to use when sensor can't be enabled */ +#define SFW_NOTIFY_DEFAULT_ORIENT MCE_ORIENTATION_UNDEFINED + +/** Dummy sensor value to use when re-sending cached state data */ +#define SFW_NOTIFY_DUMMY 0 + +typedef enum +{ + /** Cached sensor state should be reset to default value */ + NOTIFY_RESET, + + /** Cached sensor state should be restored from last-known value */ + NOTIFY_RESTORE, + + /** Cached sensor state should be sent again */ + NOTIFY_REPEAT, + + /** Sensor state was received from evdev source */ + NOTIFY_EVDEV, + + /** Sensor state was received from sensord */ + NOTIFY_SENSORD, + + /** Flush cached state */ + NOTIFY_FORGET, + + NOTIFY_NUMTYPES +} sfw_notify_t; + +static const char *sfw_notify_name (sfw_notify_t type); +static gboolean sfw_name_owner_changed_cb (DBusMessage *const msg); /* ========================================================================= * * SENSORD_DATA_TYPES @@ -305,6 +375,8 @@ struct sfw_sample_als_t uint32_t als_value; }; +static const char *sfw_sample_als_repr(const sfw_sample_als_t *self); + /** PS data block as sensord sends them */ struct sfw_sample_ps_t { @@ -322,6 +394,8 @@ struct sfw_sample_ps_t uint8_t ps_withinProximity; }; +static const char *sfw_sample_ps_repr(const sfw_sample_ps_t *self); + /** Orientation data block as sensord sends them */ struct sfw_sample_orient_t { @@ -332,18 +406,17 @@ struct sfw_sample_orient_t int32_t orient_state; }; +static const char *sfw_sample_orient_repr(const sfw_sample_orient_t *self); + /* ========================================================================= * * SENSORFW_BACKEND * ========================================================================= */ -/** Callback function type: initial value reporting */ -typedef void (*sfw_value_fn)(sfw_plugin_t *plugin, unsigned value); +/** Callback function type: parsing initial value reply */ +typedef bool (*sfw_value_fn)(sfw_plugin_t *plugin, DBusMessageIter *data); /** Callback function type: value change reporting */ -typedef void (*sfw_sample_fn)(sfw_plugin_t *plugin, const void *sample); - -/** Callback function type: value reset reporting */ -typedef void (*sfw_reset_fn)(sfw_plugin_t *plugin); +typedef void (*sfw_sample_fn)(sfw_plugin_t *plugin, sfw_notify_t type, const void *sample); /** Sensor specific data and callbacks */ struct sfw_backend_t @@ -360,24 +433,25 @@ struct sfw_backend_t /** Size of sensor data blobs sensord will be sending */ size_t be_sample_size; + /** Callback for handling initial value reply */ + sfw_value_fn be_value_cb; + /** Callback for handling sensor data blob */ sfw_sample_fn be_sample_cb; /** D-Bus method name for querying the initial sensor value */ const char *be_value_method; +}; - /** Callback for handling received initial sensor value */ - sfw_value_fn be_value_cb; +static bool sfw_backend_parse_data (DBusMessageIter *data, int arg_type, ...); - /** Callback for resetting sensor value back to default */ - sfw_reset_fn be_reset_cb; +static bool sfw_backend_als_value_cb (sfw_plugin_t *plugin, DBusMessageIter *data); +static bool sfw_backend_ps_value_cb (sfw_plugin_t *plugin, DBusMessageIter *data); +static bool sfw_backend_orient_value_cb (sfw_plugin_t *plugin, DBusMessageIter *data); - /** Callback for restoring sensor value back to last-known */ - sfw_reset_fn be_restore_cb; - - /** Callback for setting sensor value when stopped */ - sfw_reset_fn be_forget_cb; -}; +static void sfw_backend_als_sample_cb (sfw_plugin_t *plugin, sfw_notify_t type, const void *sample); +static void sfw_backend_ps_sample_cb (sfw_plugin_t *plugin, sfw_notify_t type, const void *sample); +static void sfw_backend_orient_sample_cb (sfw_plugin_t *plugin, sfw_notify_t type, const void *sample); /* ========================================================================= * * SENSORFW_HELPERS @@ -492,6 +566,9 @@ typedef enum { /** Something went wrong */ OVERRIDE_ERROR, + /** Not supported */ + OVERRIDE_NA, + OVERRIDE_NUMSTATES } sfw_override_state_t; @@ -560,6 +637,8 @@ typedef enum CONNECTION_NUMSTATES } sfw_connection_state_t; +static const char *sfw_connection_state_name (sfw_connection_state_t state); + /** State machine for handling sensor data connection */ struct sfw_connection_t { @@ -582,8 +661,6 @@ struct sfw_connection_t guint con_retry_id; }; -static const char *sfw_connection_state_name (sfw_connection_state_t state); - static sfw_connection_t *sfw_connection_create (sfw_plugin_t *plugin); static void sfw_connection_delete (sfw_connection_t *self); @@ -746,6 +823,7 @@ static const char *sfw_plugin_state_name (sfw_plugin_state_t stat static sfw_plugin_t *sfw_plugin_create (const sfw_backend_t *backend); static void sfw_plugin_delete (sfw_plugin_t *self); +static void sfw_plugin_enable_sensor (sfw_plugin_t *self, bool enable); static const char *sfw_plugin_get_sensor_name (const sfw_plugin_t *self); static const char *sfw_plugin_get_sensor_object (const sfw_plugin_t *self); static const char *sfw_plugin_get_sensor_interface(const sfw_plugin_t *self); @@ -753,8 +831,9 @@ static int sfw_plugin_get_session_id (const sfw_plugin_t *sel static const char *sfw_plugin_get_value_method (const sfw_plugin_t *self); static size_t sfw_plugin_get_sample_size (const sfw_plugin_t *self); static void sfw_plugin_handle_sample (sfw_plugin_t *self, const void *sample); -static void sfw_plugin_handle_value (sfw_plugin_t *self, unsigned value); +static bool sfw_plugin_handle_value (sfw_plugin_t *self, DBusMessageIter *data); static void sfw_plugin_reset_value (sfw_plugin_t *self); +static void sfw_plugin_repeat_value (sfw_plugin_t *self); static void sfw_plugin_restore_value (sfw_plugin_t *self); static void sfw_plugin_forget_value (sfw_plugin_t *self); @@ -811,15 +890,8 @@ struct sfw_service_t /** Pending name owner dbus method call */ DBusPendingCall *srv_query_pc; - /** State machine object for proximity sensor */ - sfw_plugin_t *srv_ps; - - /** State machine object for ambient light sensor */ - sfw_plugin_t *srv_als; - - /** State machine object for orientation sensor */ - sfw_plugin_t *srv_orient; - + /** State machine objects for sensors */ + sfw_plugin_t *srv_plugin[SFW_SENSOR_ID_COUNT]; }; static const char *sfw_service_state_name (sfw_service_state_t state); @@ -836,64 +908,8 @@ static void sfw_service_do_start (sfw_service_t *self); static void sfw_service_do_stop (sfw_service_t *self); static void sfw_service_do_query (sfw_service_t *self); -static void sfw_service_set_ps (sfw_service_t *self, bool enable); -static void sfw_service_set_als (sfw_service_t *self, bool enable); -static void sfw_service_set_orient (sfw_service_t *self, bool enable); - -/* ========================================================================= * - * SENSORFW_NOTIFY - * ========================================================================= */ - -/** Proximity state to use when sensor can't be enabled - * - * This must be "uncovered" so that absense of or failures within - * sensord do not make the device unusable due to proximity values - * blocking display power up and touch input. - */ -#define SWF_NOTIFY_DEFAULT_PS false - -/** Proximity state to use when waiting for sensord startup - * - * This must be "covered" so that we do not prematurely unblock - * touch input / allow display power up during bootup and during - * sensord restarts. - */ -#define SWF_NOTIFY_EXCEPTION_PS true - -/** Ambient light level [lux] to use when sensor can't be enabled */ -#define SWF_NOTIFY_DEFAULT_ALS 400 - -/** Orientation state to use when sensor can't be enabled */ -#define SWF_NOTIFY_DEFAULT_ORIENT MCE_ORIENTATION_UNDEFINED - -/** Dummy sensor value to use when re-sending cached state data */ -#define SWF_NOTIFY_DUMMY 0 - -typedef enum -{ - /** Cached sensor state should be reset to default value */ - NOTIFY_RESET, - - /** Cached sensor state should be restored from last-known value */ - NOTIFY_RESTORE, - - /** Cached sensor state should be sent again */ - NOTIFY_REPEAT, - - /** Sensor state was received from evdev source */ - NOTIFY_EVDEV, - - /** Sensor state was received from sensord */ - NOTIFY_SENSORD, - - NOTIFY_NUMTYPES -} sfw_notify_t; - -static gboolean sfw_name_owner_changed_cb (DBusMessage *const msg); - -static void sfw_notify_ps (sfw_notify_t type, bool covered); -static void sfw_notify_als (sfw_notify_t type, unsigned lux); -static void sfw_notify_orient (sfw_notify_t type, int state); +static sfw_plugin_t *sfw_service_plugin (const sfw_service_t *self, sensor_id_t id); +static void sfw_service_set_sensor (const sfw_service_t *self, sensor_id_t id, bool enable); /* ========================================================================= * * SENSORFW_EXCEPTION @@ -920,215 +936,403 @@ static bool sfw_exception_is_active (void); * SENSORFW_MODULE * ========================================================================= */ +/** Sensord availability tracking state machine object */ +static sfw_service_t *sfw_service = 0; + +/** Proximity change callback used for notifying upper level logic */ +static void (*sfw_notify_ps_cb)(bool covered) = 0; + +/** Ambient light change callback used for notifying upper level logic */ +static void (*sfw_notify_als_cb)(int lux) = 0; + +/** Orientation change callback used for notifying upper level logic */ +static void (*sfw_notify_orient_cb)(int state) = 0; + // (exported API defined in "mce-sensorfw.h") +static gboolean mce_sensorfw_evdev_cb (GIOChannel *chn, GIOCondition cnd, gpointer aptr); + +static void mce_sensorfw_als_detach (void); +static void mce_sensorfw_ps_detach (void); + +static bool als_from_evdev(void); +static bool ps_from_evdev(void); + /* ========================================================================= * - * SENSORFW_BACKEND + * SENSORD_DATA_TYPES * ========================================================================= */ -/** Callback for handling ambient light events from sensord */ -static void -sfw_backend_als_sample_cb(sfw_plugin_t *plugin, const void *sample) +static const char * +sfw_sample_als_repr(const sfw_sample_als_t *self) { - (void)plugin; - - const sfw_sample_als_t *self = sample; - - mce_log(LL_DEBUG, "ALS: time=%"PRIu64" light=%"PRIu32"", - self->als_timestamp, self->als_value); + static char buf[64]; + snprintf(buf, sizeof buf, + "time=%"PRIu64" lux=%"PRIu32, + self->als_timestamp, + self->als_value); + return buf; +} - sfw_notify_als(NOTIFY_SENSORD, self->als_value); +static const char * +sfw_sample_ps_repr(const sfw_sample_ps_t *self) +{ + static char buf[64]; + snprintf(buf, sizeof buf, + "time=%"PRIu64" distance=%"PRIu32" proximity=%s", + self->ps_timestamp, + self->ps_value, + self->ps_withinProximity ? "true" : "false"); + return buf; } -/** Callback for handling proximity events from sensord */ -static void -sfw_backend_ps_sample_cb(sfw_plugin_t *plugin, const void *sample) +static const char * +sfw_sample_orient_repr(const sfw_sample_orient_t *self) { - (void)plugin; + static char buf[64]; + snprintf(buf, sizeof buf, + "time=%"PRIu64" state=%s", + self->orient_timestamp, + orientation_state_repr(self->orient_state)); + return buf; +} - const sfw_sample_ps_t *self = sample; +/* ========================================================================= * + * SENSORFW_BACKEND + * ========================================================================= */ - mce_log(LL_DEBUG, "PS: time=%"PRIu64" distance=%"PRIu32" proximity=%s", - self->ps_timestamp, self->ps_value, - self->ps_withinProximity ? "true" : "false"); +/* ------------------------------------------------------------------------- * + * callbacks for interpreting sensor specific current value replies + * ------------------------------------------------------------------------- */ - sfw_notify_ps(NOTIFY_SENSORD, self->ps_withinProximity); +static bool +sfw_backend_parse_data(DBusMessageIter *data, int arg_type, ...) +{ + bool ack = false; + va_list va; + va_start(va, arg_type); + + while( !mce_dbus_iter_at_end(data) ) { + if( !mce_dbus_iter_get_basic(data, va_arg(va, void *), arg_type) ) + goto EXIT; + arg_type = va_arg(va, int); + } + + ack = true; +EXIT: + va_end(va); + return ack; } -/** Callback for handling orientation events from sensord */ -static void -sfw_backend_orient_sample_cb(sfw_plugin_t *plugin, const void *sample) +static bool +sfw_backend_als_value_cb(sfw_plugin_t *plugin, DBusMessageIter *data) { - (void)plugin; + bool ack = false; + dbus_uint64_t tck = 0; + dbus_uint32_t val = 0; - const sfw_sample_orient_t *self = sample; + if( !sfw_backend_parse_data(data, + DBUS_TYPE_UINT64, &tck, + DBUS_TYPE_UINT32, &val, + DBUS_TYPE_INVALID) ) + goto EXIT; - mce_log(LL_DEBUG, "ORIENT: time=%"PRIu64" state=%"PRId32"", - self->orient_timestamp, self->orient_state); + const sfw_sample_als_t sample = { + .als_timestamp = tck, + .als_value = val, + }; - sfw_notify_orient(NOTIFY_SENSORD, self->orient_state); -} + sfw_plugin_handle_sample(plugin, &sample); -// ---------------------------------------------------------------- + ack = true; +EXIT: + return ack; +} -/** Callback for handling reply to ambient light query from sensord */ -static void -sfw_backend_als_value_cb(sfw_plugin_t *plugin, unsigned value) +static bool +sfw_backend_ps_value_cb(sfw_plugin_t *plugin, DBusMessageIter *data) { - (void)plugin; + bool ack = false; + dbus_uint64_t tck = 0; + dbus_uint32_t val = 0; + + if( !sfw_backend_parse_data(data, + DBUS_TYPE_UINT64, &tck, + DBUS_TYPE_UINT32, &val, + DBUS_TYPE_INVALID) ) + goto EXIT; - mce_log(LL_DEBUG, "ALS: initial light=%u", value); + const sfw_sample_ps_t sample = { + .ps_timestamp = tck, + .ps_value = (val < 1) ? 0 : 10, + .ps_withinProximity = (val < 1) ? true : false, + }; + + sfw_plugin_handle_sample(plugin, &sample); - sfw_notify_als(NOTIFY_SENSORD, value); + ack = true; +EXIT: + return ack; } -/** Callback for handling reply to proximity query from sensord */ -static void -sfw_backend_ps_value_cb(sfw_plugin_t *plugin, unsigned value) +static bool +sfw_backend_orient_value_cb(sfw_plugin_t *plugin, DBusMessageIter *data) { - (void)plugin; + bool ack = false; + dbus_uint64_t tck = 0; + dbus_uint32_t val = 0; + + if( !sfw_backend_parse_data(data, + DBUS_TYPE_UINT64, &tck, + DBUS_TYPE_UINT32, &val, + DBUS_TYPE_INVALID) ) + goto EXIT; - bool covered = (value < 1); + const sfw_sample_orient_t sample = { + .orient_timestamp = tck, + .orient_state = val, + }; - mce_log(LL_DEBUG, "PS: initial distance=%u proximity=%s", - value, covered ? "true" : "false"); + sfw_plugin_handle_sample(plugin, &sample); - sfw_notify_ps(NOTIFY_SENSORD, covered); + ack = true; +EXIT: + return ack; } -/** Callback for handling reply to orientation query from sensord */ +/* ------------------------------------------------------------------------- * + * Callbacks for interpreting sensor specific change notifications + * ------------------------------------------------------------------------- */ + +/** Callback for handling ambient light events from sensord */ static void -sfw_backend_orient_value_cb(sfw_plugin_t *plugin, unsigned value) +sfw_backend_als_sample_cb(sfw_plugin_t *plugin, sfw_notify_t type, const void *sampledata) { (void)plugin; + const sfw_sample_als_t *sample = sampledata; - mce_log(LL_DEBUG, "ORIENT: initial state=%u", value); + static const sfw_sample_als_t default_value = { + .als_value = SFW_NOTIFY_DEFAULT_ALS, + }; - sfw_notify_orient(NOTIFY_SENSORD, value); -} + static sfw_sample_als_t cached_value = { + .als_value = SFW_NOTIFY_DEFAULT_ALS, + }; -// ---------------------------------------------------------------- + static bool tracking_active = false; -/** Callback for resetting ambient light state to default */ -static void -sfw_backend_als_reset_cb(sfw_plugin_t *plugin) -{ - (void)plugin; + if( sample ) { + mce_log(LL_DEBUG, "ALS: UPDATE %s %s", + sfw_notify_name(type), + sfw_sample_als_repr(sample)); + } + + switch( type ) { + default: + case NOTIFY_REPEAT: + break; - mce_log(LL_DEBUG, "ALS: light=reset-to-default"); + case NOTIFY_FORGET: + case NOTIFY_RESET: + tracking_active = false; + break; - sfw_notify_als(NOTIFY_RESET, SWF_NOTIFY_DUMMY); -} + case NOTIFY_RESTORE: + tracking_active = true; + break; -/** Callback for resetting proximity state to default */ -static void -sfw_backend_ps_reset_cb(sfw_plugin_t *plugin) -{ - (void)plugin; + case NOTIFY_EVDEV: + cached_value = *sample; + break; - mce_log(LL_DEBUG, "PS: covered=reset-to-default"); + case NOTIFY_SENSORD: + if( als_from_evdev() ) + mce_log(LL_DEBUG, "ignoring sensord input: %s", + sfw_sample_als_repr(sample)); + else + cached_value = *sample; + break; + } - sfw_notify_ps(NOTIFY_RESET, SWF_NOTIFY_DUMMY); + /* Default value is used unless we are in fully working state */ + sample = tracking_active ? &cached_value : &default_value ; + + if( sfw_notify_als_cb ) { + mce_log(LL_DEBUG, "ALS: NOTIFY %s %s", + sfw_notify_name(type), + sfw_sample_als_repr(sample)); + sfw_notify_als_cb(sample->als_value); + } + + return; } -/** Callback for resetting orientation state to default */ +/** Callback for handling proximity events from sensord */ static void -sfw_backend_orient_reset_cb(sfw_plugin_t *plugin) +sfw_backend_ps_sample_cb(sfw_plugin_t *plugin, sfw_notify_t type, const void *sampledata) { (void)plugin; + const sfw_sample_ps_t *sample = sampledata; - mce_log(LL_DEBUG, "ORIENT: state=reset-to-default"); + static const sfw_sample_ps_t exception_value = { + .ps_withinProximity = SFW_NOTIFY_EXCEPTION_PS, + }; - sfw_notify_orient(NOTIFY_RESET, SWF_NOTIFY_DUMMY); -} + static const sfw_sample_ps_t default_value = { + .ps_withinProximity = SFW_NOTIFY_DEFAULT_PS, + }; -/** Callback for restoring ambient light state to last-known */ -static void -sfw_backend_als_restore_cb(sfw_plugin_t *plugin) -{ - (void)plugin; + static sfw_sample_ps_t cached_value = { + .ps_value = 10, + .ps_withinProximity = SFW_NOTIFY_DEFAULT_PS, + }; - mce_log(LL_DEBUG, "ALS: light=restore-to-last-known"); + static bool tracking_active = false; - sfw_notify_als(NOTIFY_RESTORE, SWF_NOTIFY_DUMMY); -} + if( sample ) { + mce_log(LL_DEBUG, "PS: UPDATE %s %s", + sfw_notify_name(type), + sfw_sample_ps_repr(sample)); + } -/** Callback for restoring proximity state to last-known */ -static void -sfw_backend_ps_restore_cb(sfw_plugin_t *plugin) -{ - (void)plugin; + switch( type ) { + default: + case NOTIFY_FORGET: + case NOTIFY_REPEAT: + break; - mce_log(LL_DEBUG, "PS: covered=restore-to-last-known"); + case NOTIFY_RESET: + tracking_active = false; + break; - sfw_notify_ps(NOTIFY_RESTORE, SWF_NOTIFY_DUMMY); -} + case NOTIFY_RESTORE: + tracking_active = true; + break; -/** Callback for restoring orientation state to last-known */ -static void -sfw_backend_orient_restore_cb(sfw_plugin_t *plugin) -{ - (void)plugin; + case NOTIFY_EVDEV: + cached_value = *sample; + break; + + case NOTIFY_SENSORD: + if( ps_from_evdev() ) + mce_log(LL_DEBUG, "ignoring sensord input: %s", + sfw_sample_ps_repr(sample)); + else + cached_value = *sample; + break; + } - mce_log(LL_DEBUG, "ORIENT: state=restore-to-last-known"); + if( sfw_exception_is_active() ) { + // ps=covered while waiting for sensorfwd to show up + sample = &exception_value; + } + else if( !tracking_active ) { + // ps=not-covered while sensorfwd is not running + sample = &default_value; + } + else { + // ps=as-reported by sensorfwd or kernel + sample = &cached_value; + } - sfw_notify_orient(NOTIFY_RESTORE, SWF_NOTIFY_DUMMY); -} + if( sfw_notify_ps_cb ) { + mce_log(LL_DEBUG, "PS: NOTIFY %s %s", + sfw_notify_name(type), + sfw_sample_ps_repr(sample)); + sfw_notify_ps_cb(sample->ps_withinProximity); + } -// ---------------------------------------------------------------- + return; +} -/** Data and callbacks for proximity sensor */ -static const sfw_backend_t sfw_backend_ps = +/** Callback for handling orientation events from sensord */ +static void +sfw_backend_orient_sample_cb(sfw_plugin_t *plugin, sfw_notify_t type, const void *sampledata) { - .be_sensor_name = SENSORFW_SENSOR_NAME_PS, - .be_sensor_object = 0, - .be_sensor_interface = SENSORFW_SENSOR_INTERFACE_PS, + static const sfw_sample_orient_t default_value = { + .orient_state = SFW_NOTIFY_DEFAULT_ORIENT, + }; + + static sfw_sample_orient_t cached_value = { + .orient_state = SFW_NOTIFY_DEFAULT_ORIENT, + }; + + static bool tracking_active = false; - .be_sample_size = sizeof(sfw_sample_ps_t), - .be_sample_cb = sfw_backend_ps_sample_cb, + (void)plugin; + const sfw_sample_orient_t *sample = sampledata; - .be_value_method = SENSORFW_SENSOR_METHOD_READ_PS, - .be_value_cb = sfw_backend_ps_value_cb, + if( sample ) { + mce_log(LL_DEBUG, "ORIENT: UPDATE %s %s", + sfw_notify_name(type), + sfw_sample_orient_repr(sample)); + } - .be_reset_cb = sfw_backend_ps_reset_cb, - .be_restore_cb = sfw_backend_ps_restore_cb, - .be_forget_cb = 0, -}; + switch( type ) { + default: + case NOTIFY_REPEAT: + break; -/** Data and callbacks for ambient light sensor */ -static const sfw_backend_t sfw_backend_als = -{ - .be_sensor_name = SENSORFW_SENSOR_NAME_ALS, - .be_sensor_object = 0, - .be_sensor_interface = SENSORFW_SENSOR_INTERFACE_ALS, + case NOTIFY_FORGET: + case NOTIFY_RESET: + tracking_active = false; + cached_value = default_value; + break; - .be_sample_size = sizeof(sfw_sample_als_t), - .be_sample_cb = sfw_backend_als_sample_cb, + case NOTIFY_RESTORE: + tracking_active = true; + break; - .be_value_method = SENSORFW_SENSOR_METHOD_READ_ALS, - .be_value_cb = sfw_backend_als_value_cb, + case NOTIFY_EVDEV: + case NOTIFY_SENSORD: + cached_value = *sample; + break; + } - .be_reset_cb = sfw_backend_als_reset_cb, - .be_restore_cb = sfw_backend_als_restore_cb, - .be_forget_cb = 0, -}; + /* Default value is used unless we are in fully working state */ + sample = tracking_active ? &cached_value : &default_value ; -/** Data and callbacks for orientation sensor */ -static const sfw_backend_t sfw_backend_orient = -{ - .be_sensor_name = SENSORFW_SENSOR_NAME_ORIENT, - .be_sensor_object = 0, - .be_sensor_interface = SENSORFW_SENSOR_INTERFACE_ORIENT, + if( sfw_notify_orient_cb ) { + mce_log(LL_DEBUG, "ORIENT: NOTIFY %s %s", + sfw_notify_name(type), + sfw_sample_orient_repr(sample)); + sfw_notify_orient_cb(sample->orient_state); + } - .be_sample_size = sizeof(sfw_sample_orient_t), - .be_sample_cb = sfw_backend_orient_sample_cb, + return; +} - .be_value_method = SENSORFW_SENSOR_METHOD_READ_ORIENT, - .be_value_cb = sfw_backend_orient_value_cb, +// ---------------------------------------------------------------- - .be_reset_cb = sfw_backend_orient_reset_cb, - .be_restore_cb = sfw_backend_orient_restore_cb, - .be_forget_cb = sfw_backend_orient_reset_cb, +/** Data and callback functions for all sensors */ +static const sfw_backend_t sfw_backend_lut[SFW_SENSOR_ID_COUNT] = +{ + [SFW_SENSOR_ID_PS] = { + .be_sensor_name = SFW_SENSOR_NAME_PS, + .be_sensor_object = 0, + .be_sensor_interface = SFW_SENSOR_INTERFACE_PS, + .be_sample_size = sizeof(sfw_sample_ps_t), + .be_value_cb = sfw_backend_ps_value_cb, + .be_sample_cb = sfw_backend_ps_sample_cb, + .be_value_method = SFW_SENSOR_METHOD_READ_PS, + }, + [SFW_SENSOR_ID_ALS] = { + .be_sensor_name = SFW_SENSOR_NAME_ALS, + .be_sensor_object = 0, + .be_sensor_interface = SFW_SENSOR_INTERFACE_ALS, + .be_sample_size = sizeof(sfw_sample_als_t), + .be_value_cb = sfw_backend_als_value_cb, + .be_sample_cb = sfw_backend_als_sample_cb, + .be_value_method = SFW_SENSOR_METHOD_READ_ALS, + }, + [SFW_SENSOR_ID_ORIENT] = { + .be_sensor_name = SFW_SENSOR_NAME_ORIENT, + .be_sensor_object = 0, + .be_sensor_interface = SFW_SENSOR_INTERFACE_ORIENT, + .be_sample_size = sizeof(sfw_sample_orient_t), + .be_value_cb = sfw_backend_orient_value_cb, + .be_sample_cb = sfw_backend_orient_sample_cb, + .be_value_method = SFW_SENSOR_METHOD_READ_ORIENT, + }, }; /* ========================================================================= * @@ -1371,7 +1575,7 @@ sfw_reporting_trans(sfw_reporting_t *self, sfw_reporting_state_t state) dbus_send_ex(SENSORFW_SERVICE, sfw_plugin_get_sensor_object(self->rep_plugin), sfw_plugin_get_sensor_interface(self->rep_plugin), - SENSORFW_SENSOR_METHOD_START, + SFW_SENSOR_METHOD_START, sfw_reporting_change_cb, self, 0, &self->rep_change_pc, DBUS_TYPE_INT32, &sid, @@ -1385,7 +1589,7 @@ sfw_reporting_trans(sfw_reporting_t *self, sfw_reporting_state_t state) dbus_send_ex(SENSORFW_SERVICE, sfw_plugin_get_sensor_object(self->rep_plugin), sfw_plugin_get_sensor_interface(self->rep_plugin), - SENSORFW_SENSOR_METHOD_STOP, + SFW_SENSOR_METHOD_STOP, sfw_reporting_change_cb, self, 0, &self->rep_change_pc, DBUS_TYPE_INT32, &sid, @@ -1393,6 +1597,11 @@ sfw_reporting_trans(sfw_reporting_t *self, sfw_reporting_state_t state) break; case REPORTING_ENABLED: + if( !sfw_plugin_get_value_method(self->rep_plugin) ) { + mce_log(LL_DEBUG, "reporting(%s): skip state query", + sfw_plugin_get_sensor_name(self->rep_plugin)); + break; + } dbus_send_ex(SENSORFW_SERVICE, sfw_plugin_get_sensor_object(self->rep_plugin), sfw_plugin_get_sensor_interface(self->rep_plugin), @@ -1436,11 +1645,9 @@ sfw_reporting_value_cb(DBusPendingCall *pc, void *aptr) DBusMessage *rsp = 0; DBusError err = DBUS_ERROR_INIT; - dbus_uint32_t tck = 0; - dbus_uint32_t val = 0; bool ack = false; - if( !pc || !self || pc != self->rep_value_pc ) + if( pc != self->rep_value_pc ) goto EXIT; dbus_pending_call_unref(self->rep_value_pc), @@ -1459,30 +1666,20 @@ sfw_reporting_value_cb(DBusPendingCall *pc, void *aptr) goto EXIT; } + mce_log(LL_DEBUG, "reporting(%s): reply received", + sfw_plugin_get_sensor_name(self->rep_plugin)); + DBusMessageIter body, data; if( !dbus_message_iter_init(rsp, &body) ) goto PARSE_FAILED; - if( dbus_message_iter_get_arg_type(&body) != DBUS_TYPE_STRUCT ) - goto PARSE_FAILED; - - dbus_message_iter_recurse(&body, &data); - dbus_message_iter_next(&body); - - if( dbus_message_iter_get_arg_type(&data) != DBUS_TYPE_UINT64 ) + if( !mce_dbus_iter_get_struct(&body, &data) ) goto PARSE_FAILED; - dbus_message_iter_get_basic(&data, &tck); - dbus_message_iter_next(&data); - - if( dbus_message_iter_get_arg_type(&data) != DBUS_TYPE_UINT32 ) + if( !(ack = sfw_plugin_handle_value(self->rep_plugin, &data)) ) goto PARSE_FAILED; - dbus_message_iter_get_basic(&data, &val); - dbus_message_iter_next(&data); - - sfw_plugin_handle_value(self->rep_plugin, val); ack = true; goto EXIT; @@ -1511,7 +1708,7 @@ sfw_reporting_change_cb(DBusPendingCall *pc, void *aptr) DBusError err = DBUS_ERROR_INIT; dbus_bool_t ack = FALSE; - if( !pc || !self || pc != self->rep_change_pc ) + if( pc != self->rep_change_pc ) goto EXIT; dbus_pending_call_unref(self->rep_change_pc), @@ -1639,6 +1836,7 @@ sfw_override_state_name(sfw_override_state_t state) [OVERRIDE_DISABLING] = "DISABLING", [OVERRIDE_DISABLED] = "DISABLED", [OVERRIDE_ERROR] = "ERROR", + [OVERRIDE_NA] = "NA", }; return (state < OVERRIDE_NUMSTATES) ? lut[state] : 0; @@ -1742,7 +1940,7 @@ sfw_override_trans(sfw_override_t *self, sfw_override_state_t state) dbus_send_ex(SENSORFW_SERVICE, sfw_plugin_get_sensor_object(self->ovr_plugin), sfw_plugin_get_sensor_interface(self->ovr_plugin), - SENSORFW_SENSOR_METHOD_SET_OVERRIDE, + SFW_SENSOR_METHOD_SET_OVERRIDE, sfw_override_start_cb, self, 0, &self->ovr_start_pc, DBUS_TYPE_INT32, &sid, @@ -1762,6 +1960,7 @@ sfw_override_trans(sfw_override_t *self, sfw_override_state_t state) break; default: + case OVERRIDE_NA: case OVERRIDE_IDLE: case OVERRIDE_INITIAL: // NOP @@ -1784,8 +1983,9 @@ sfw_override_start_cb(DBusPendingCall *pc, void *aptr) DBusMessage *rsp = 0; DBusError err = DBUS_ERROR_INIT; dbus_bool_t ack = FALSE; + dbus_bool_t nak = FALSE; - if( !pc || !self || pc != self->ovr_start_pc ) + if( pc != self->ovr_start_pc ) goto EXIT; dbus_pending_call_unref(self->ovr_start_pc), @@ -1794,33 +1994,35 @@ sfw_override_start_cb(DBusPendingCall *pc, void *aptr) if( !(rsp = dbus_pending_call_steal_reply(pc)) ) { mce_log(LL_ERR, "override(%s): no reply", sfw_plugin_get_sensor_name(self->ovr_plugin)); - goto EXIT; } - - if( dbus_set_error_from_message(&err, rsp) ) { + else if( dbus_set_error_from_message(&err, rsp) ) { mce_log(LL_ERR, "override(%s): error reply: %s: %s", sfw_plugin_get_sensor_name(self->ovr_plugin), err.name, err.message); - goto EXIT; } - - if( !dbus_message_get_args(rsp, &err, + else if( !dbus_message_get_args(rsp, &err, DBUS_TYPE_BOOLEAN, &ack, DBUS_TYPE_INVALID) ) { mce_log(LL_ERR, "override(%s): parse error: %s: %s", sfw_plugin_get_sensor_name(self->ovr_plugin), err.name, err.message); - goto EXIT; } - -EXIT: - mce_log(LL_DEBUG, "override(%s): ack=%d", - sfw_plugin_get_sensor_name(self->ovr_plugin), ack); + else if( !ack ) { + mce_log(LL_ERR, "override(%s): failed", + sfw_plugin_get_sensor_name(self->ovr_plugin)); + nak = true; + } + else { + mce_log(LL_DEBUG, "override(%s): succeeded", + sfw_plugin_get_sensor_name(self->ovr_plugin)); + } if( self->ovr_state == OVERRIDE_ENABLING || self->ovr_state == OVERRIDE_DISABLING ) { - if( !ack ) + if( nak ) + sfw_override_trans(self, OVERRIDE_NA); + else if( !ack ) sfw_override_trans(self, OVERRIDE_ERROR); else if( self->ovr_state == OVERRIDE_ENABLING ) sfw_override_trans(self, OVERRIDE_ENABLED); @@ -1828,6 +2030,7 @@ sfw_override_start_cb(DBusPendingCall *pc, void *aptr) sfw_override_trans(self, OVERRIDE_DISABLED); } +EXIT: if( rsp ) dbus_message_unref(rsp); dbus_error_free(&err); @@ -2539,7 +2742,7 @@ sfw_session_start_cb(DBusPendingCall *pc, void *aptr) DBusError err = DBUS_ERROR_INIT; dbus_int32_t ses = SESSION_ID_UNKNOWN; - if( !pc || !self || pc != self->ses_start_pc ) + if( pc != self->ses_start_pc ) goto EXIT; dbus_pending_call_unref(self->ses_start_pc), @@ -2702,25 +2905,30 @@ sfw_plugin_get_session_id(const sfw_plugin_t *self) return self ? sfw_session_get_id(self->plg_session) : SESSION_ID_INVALID; } +static void +sfw_plugin_notify(sfw_plugin_t *self, sfw_notify_t type, const void *sample) +{ + if( self && self->plg_backend && self->plg_backend->be_sample_cb ) + self->plg_backend->be_sample_cb(self, type, sample); +} + /** Handle sensor specific change event received from data connection */ static void sfw_plugin_handle_sample(sfw_plugin_t *self, const void *sample) { - if( self->plg_backend->be_sample_cb ) - self->plg_backend->be_sample_cb(self, sample); + sfw_plugin_notify(self, NOTIFY_SENSORD, sample); } /** Handle sensor specific initial value received via dbus query */ -static void -sfw_plugin_handle_value(sfw_plugin_t *self, unsigned value) +static bool +sfw_plugin_handle_value(sfw_plugin_t *self, DBusMessageIter *data) { - mce_log(LL_DEBUG, "plugin(%s): initial=%u", - sfw_plugin_get_sensor_name(self), value); - + bool ack = false; if( self->plg_backend->be_value_cb ) - self->plg_backend->be_value_cb(self, value); + ack = self->plg_backend->be_value_cb(self, data); + return ack; } /** Reset sensor state to assumed default state @@ -2731,11 +2939,19 @@ sfw_plugin_handle_value(sfw_plugin_t *self, unsigned value) static void sfw_plugin_reset_value(sfw_plugin_t *self) { - mce_log(LL_DEBUG, "plugin(%s): reset", - sfw_plugin_get_sensor_name(self)); + mce_log(LL_DEBUG, "plugin(%s): reset", sfw_plugin_get_sensor_name(self)); + sfw_plugin_notify(self, NOTIFY_RESET, 0); +} - if( self->plg_backend->be_reset_cb ) - self->plg_backend->be_reset_cb(self); +/** Repeat sensor state notification + * + * Used when tracking callbacks are changed + */ +static void +sfw_plugin_repeat_value(sfw_plugin_t *self) +{ + mce_log(LL_DEBUG, "plugin(%s): repeat", sfw_plugin_get_sensor_name(self)); + sfw_plugin_notify(self, NOTIFY_REPEAT, 0); } /** Restore sensor state to last seen state @@ -2745,11 +2961,8 @@ sfw_plugin_reset_value(sfw_plugin_t *self) static void sfw_plugin_restore_value(sfw_plugin_t *self) { - mce_log(LL_DEBUG, "plugin(%s): restore", - sfw_plugin_get_sensor_name(self)); - - if( self->plg_backend->be_restore_cb ) - self->plg_backend->be_restore_cb(self); + mce_log(LL_DEBUG, "plugin(%s): restore", sfw_plugin_get_sensor_name(self)); + sfw_plugin_notify(self, NOTIFY_RESTORE, 0); } /** Set sensor state when stopped @@ -2759,11 +2972,8 @@ sfw_plugin_restore_value(sfw_plugin_t *self) static void sfw_plugin_forget_value(sfw_plugin_t *self) { - mce_log(LL_DEBUG, "plugin(%s): stopped", - sfw_plugin_get_sensor_name(self)); - - if( self->plg_backend->be_forget_cb ) - self->plg_backend->be_forget_cb(self); + mce_log(LL_DEBUG, "plugin(%s): forget", sfw_plugin_get_sensor_name(self)); + sfw_plugin_notify(self, NOTIFY_FORGET, 0); } /** Get size of sensor specific change event @@ -2810,6 +3020,9 @@ sfw_plugin_cancel_retry(sfw_plugin_t *self) static void sfw_plugin_trans(sfw_plugin_t *self, sfw_plugin_state_t state) { + if( !self ) + goto EXIT; + if( self->plg_state == state ) goto EXIT; @@ -2898,6 +3111,21 @@ sfw_plugin_create(const sfw_backend_t *backend) return self; } +/** Set sensor plugin target state + */ +static void +sfw_plugin_enable_sensor(sfw_plugin_t *self, bool enable) +{ + if( self ) { + mce_log(LL_DEBUG, "%s: %s", sfw_plugin_get_sensor_name(self), + enable ? "enable" : "disable"); + if( self->plg_override ) + sfw_override_set_target(self->plg_override, enable); + if( self->plg_reporting ) + sfw_reporting_set_target(self->plg_reporting, enable); + } +} + /** Delete sensor plugin load/unload state machine object */ static void @@ -2938,7 +3166,7 @@ sfw_plugin_load_cb(DBusPendingCall *pc, void *aptr) dbus_bool_t ack = FALSE; bool nak = true; - if( !pc || !self || pc != self->plg_load_pc ) + if( pc != self->plg_load_pc ) goto EXIT; dbus_pending_call_unref(self->plg_load_pc), @@ -3011,6 +3239,9 @@ sfw_plugin_retry_cb(gpointer aptr) static void sfw_plugin_do_load(sfw_plugin_t *self) { + if( !self ) + goto EXIT; + switch( self->plg_state ) { case PLUGIN_IDLE: case PLUGIN_INITIAL: @@ -3020,6 +3251,9 @@ sfw_plugin_do_load(sfw_plugin_t *self) // nop break; } + +EXIT: + return; } /** Unload plugin @@ -3145,11 +3379,12 @@ sfw_service_create(void) { sfw_service_t *self = calloc(1, sizeof *self); - self->srv_state = SERVICE_UNKNOWN; - self->srv_query_pc = 0; - self->srv_ps = sfw_plugin_create(&sfw_backend_ps); - self->srv_als = sfw_plugin_create(&sfw_backend_als); - self->srv_orient = sfw_plugin_create(&sfw_backend_orient); + self->srv_state = SERVICE_UNKNOWN; + self->srv_query_pc = 0; + + for( sensor_id_t id = 0; id < SFW_SENSOR_ID_COUNT; ++id ) { + self->srv_plugin[id] = sfw_plugin_create(sfw_backend_lut + id); + } return self; } @@ -3164,14 +3399,8 @@ sfw_service_delete(sfw_service_t *self) if( self ) { sfw_service_trans(self, SERVICE_UNKNOWN); - sfw_plugin_delete(self->srv_ps), - self->srv_ps = 0; - - sfw_plugin_delete(self->srv_als), - self->srv_als = 0; - - sfw_plugin_delete(self->srv_orient), - self->srv_orient = 0; + for( sensor_id_t id = 0; id < SFW_SENSOR_ID_COUNT; ++id ) + sfw_plugin_delete(self->srv_plugin[id]), self->srv_plugin[id] = 0; free(self); } @@ -3199,9 +3428,6 @@ sfw_service_query_cb(DBusPendingCall *pc, void *aptr) const char *owner = 0; DBusError err = DBUS_ERROR_INIT; - if( !pc || !self ) - goto EXIT; - if( pc != self->srv_query_pc ) goto EXIT; @@ -3267,17 +3493,15 @@ sfw_service_trans(sfw_service_t *self, sfw_service_state_t state) case SERVICE_RUNNING: sfw_exception_start(SFW_EXCEPTION_LENGTH_SENSORD_RUNNING); - sfw_plugin_do_load(self->srv_ps); - sfw_plugin_do_load(self->srv_als); - sfw_plugin_do_load(self->srv_orient); + for( sensor_id_t id = 0; id < SFW_SENSOR_ID_COUNT; ++id ) + sfw_plugin_do_load(self->srv_plugin[id]); break; case SERVICE_UNKNOWN: case SERVICE_STOPPED: sfw_exception_start(SFW_EXCEPTION_LENGTH_SENSORD_STOPPED); - sfw_plugin_do_reset(self->srv_ps); - sfw_plugin_do_reset(self->srv_als); - sfw_plugin_do_reset(self->srv_orient); + for( sensor_id_t id = 0; id < SFW_SENSOR_ID_COUNT; ++id ) + sfw_plugin_do_reset(self->srv_plugin[id]); break; default: @@ -3315,52 +3539,23 @@ sfw_service_do_query(sfw_service_t *self) sfw_service_trans(self, SERVICE_QUERYING); } -/** Perform actions needed when proximity sensor needed state changes - */ -static void -sfw_service_set_ps(sfw_service_t *self, bool enable) -{ - // using NULL self pointer explicitly allowed - - mce_log(LL_DEBUG, "%s", enable ? "enable" : "disable"); - if( self && self->srv_ps ) { - if( self->srv_ps->plg_override ) - sfw_override_set_target(self->srv_ps->plg_override, enable); - if( self->srv_ps->plg_reporting ) - sfw_reporting_set_target(self->srv_ps->plg_reporting, enable); - } -} - -/** Perform actions needed when ambient light sensor needed state changes - */ -static void -sfw_service_set_als(sfw_service_t *self, bool enable) +/** Lookup plugin by sensor id */ +static sfw_plugin_t * +sfw_service_plugin(const sfw_service_t *self, sensor_id_t id) { - // using NULL self pointer explicitly allowed - - mce_log(LL_DEBUG, "%s", enable ? "enable" : "disable"); - if( self && self->srv_als ) { - if( self->srv_als->plg_override ) - sfw_override_set_target(self->srv_als->plg_override, enable); - if( self->srv_als->plg_reporting ) - sfw_reporting_set_target(self->srv_als->plg_reporting, enable); + sfw_plugin_t *plugin = 0; + if( self ) { + plugin = self->srv_plugin[id]; } + return plugin; } -/** Perform actions needed when orientation sensor needed state changes - */ +/** Enable/disable sensor by id */ static void -sfw_service_set_orient(sfw_service_t *self, bool enable) +sfw_service_set_sensor(const sfw_service_t *self, sensor_id_t id, bool enable) { - // using NULL self pointer explicitly allowed - - mce_log(LL_DEBUG, "%s", enable ? "enable" : "disable"); - if( self && self->srv_orient ) { - if( self->srv_orient->plg_override ) - sfw_override_set_target(self->srv_orient->plg_override, enable); - if( self->srv_orient->plg_reporting ) - sfw_reporting_set_target(self->srv_orient->plg_reporting, enable); - } + sfw_plugin_t *plugin = sfw_service_plugin(self, id); + sfw_plugin_enable_sensor(plugin, enable); } /* ========================================================================= * @@ -3373,20 +3568,21 @@ sfw_service_set_orient(sfw_service_t *self, bool enable) */ static guint ps_evdev_id = 0; +static bool ps_from_evdev(void) +{ + return ps_evdev_id != 0; +} + /** io watch id for ALS evdev file descriptor * * If this is non-zero, ambient light data received from sensord is ignored. */ static guint als_evdev_id = 0; -/** Proximity change callback used for notifying upper level logic */ -static void (*sfw_notify_ps_cb)(bool covered) = 0; - -/** Ambient light change callback used for notifying upper level logic */ -static void (*sfw_notify_als_cb)(int lux) = 0; - -/** Orientation change callback used for notifying upper level logic */ -static void (*sfw_notify_orient_cb)(int state) = 0; +static bool als_from_evdev(void) +{ + return als_evdev_id != 0; +} /** Translate notification type to human readable form */ @@ -3400,170 +3596,12 @@ sfw_notify_name(sfw_notify_t type) [NOTIFY_REPEAT] = "REPEAT", [NOTIFY_EVDEV] = "EVDEV", [NOTIFY_SENSORD] = "SENSORD", + [NOTIFY_FORGET] = "FORGET", }; return (type < NOTIFY_NUMTYPES) ? lut[type] : 0; } -/** Notify proximity state via callback - */ -static void -sfw_notify_ps(sfw_notify_t type, bool input_value) -{ - static bool cached_value = SWF_NOTIFY_DEFAULT_PS; - const bool default_value = SWF_NOTIFY_DEFAULT_PS; - static bool tracking_active = false; - - /* Always update cached state data */ - switch( type ) { - default: - case NOTIFY_REPEAT: - break; - - case NOTIFY_RESET: - tracking_active = false; - break; - - case NOTIFY_RESTORE: - tracking_active = true; - break; - - case NOTIFY_EVDEV: - cached_value = input_value; - break; - - case NOTIFY_SENSORD: - if( ps_evdev_id ) - mce_log(LL_DEBUG, "ignoring PS=%d from sensord", input_value); - else - cached_value = input_value; - break; - } - - /* The rest can be skipped if callback function is unset */ - if( !sfw_notify_ps_cb ) - goto EXIT; - - /* Default value is used unless we are in fully working state */ - bool output_value = tracking_active ? cached_value : default_value ; - - /* Use separate value while expecting sensord startup */ - if( sfw_exception_is_active() && !output_value ) { - mce_log(LL_DEBUG, "waiting for sensord; using proximity=covered"); - output_value = SWF_NOTIFY_EXCEPTION_PS; - } - - mce_log(LL_DEBUG, "%s: input %s -> notify %s", - sfw_notify_name(type), - input_value ? "covered" : "uncovered", - output_value ? "covered" : "uncovered"); - - sfw_notify_ps_cb(output_value); - -EXIT: - return; -} - -/** Notify ambient light level via callback - */ -static void -sfw_notify_als(sfw_notify_t type, unsigned input_value) -{ - static unsigned cached_value = SWF_NOTIFY_DEFAULT_ALS; - const unsigned default_value = SWF_NOTIFY_DEFAULT_ALS; - static bool tracking_active = false; - - /* Always update cached state data */ - switch( type ) { - default: - case NOTIFY_REPEAT: - break; - - case NOTIFY_RESET: - tracking_active = false; - break; - - case NOTIFY_RESTORE: - tracking_active = true; - break; - - case NOTIFY_EVDEV: - cached_value = input_value; - break; - - case NOTIFY_SENSORD: - if( als_evdev_id ) - mce_log(LL_DEBUG, "ignoring ALS=%u from sensord", input_value); - else - cached_value = input_value; - break; - } - - /* The rest can be skipped if callback function is unset */ - if( !sfw_notify_als_cb ) - goto EXIT; - - /* Default value is used unless we are in fully working state */ - unsigned output_value = tracking_active ? cached_value : default_value ; - - mce_log(LL_DEBUG, "%s: input %u -> notify %u", - sfw_notify_name(type), - input_value, output_value); - - sfw_notify_als_cb(output_value); - -EXIT: - return; -} - -/** Notify orientation state via callback - */ -static void -sfw_notify_orient(sfw_notify_t type, int input_value) -{ - static unsigned cached_value = SWF_NOTIFY_DEFAULT_ORIENT; - const unsigned default_value = SWF_NOTIFY_DEFAULT_ORIENT; - static bool tracking_active = false; - - /* Always update cached state data */ - switch( type ) { - default: - case NOTIFY_REPEAT: - break; - - case NOTIFY_RESET: - tracking_active = false; - cached_value = default_value; - break; - - case NOTIFY_RESTORE: - tracking_active = true; - break; - - case NOTIFY_EVDEV: - case NOTIFY_SENSORD: - cached_value = input_value; - break; - } - - /* The rest can be skipped if callback function is unset */ - if( !sfw_notify_orient_cb ) - goto EXIT; - - /* Default value is used unless we are in fully working state */ - unsigned output_value = tracking_active ? cached_value : default_value ; - - mce_log(LL_DEBUG, "%s: input %s -> notify %s", - sfw_notify_name(type), - orientation_state_repr(input_value), - orientation_state_repr(output_value)); - - sfw_notify_orient_cb(output_value); - -EXIT: - return; -} - /* ========================================================================= * * SENSORFW_EXCEPTION * ========================================================================= */ @@ -3591,7 +3629,8 @@ static gboolean sfw_exception_timer_cb(gpointer aptr) mce_log(LL_DEBUG, "exceptional reporting ended"); - sfw_notify_ps(NOTIFY_REPEAT, SWF_NOTIFY_DUMMY); + sfw_plugin_t *plugin = sfw_service_plugin(sfw_service, SFW_SENSOR_ID_PS); + sfw_plugin_repeat_value(plugin); EXIT: return FALSE; @@ -3630,7 +3669,8 @@ static void sfw_exception_start(sfw_exception_delay_t delay_ms) 0); sfw_exception_inititial = false; - sfw_notify_ps(NOTIFY_REPEAT, SWF_NOTIFY_DUMMY); + sfw_plugin_t *plugin = sfw_service_plugin(sfw_service, SFW_SENSOR_ID_PS); + sfw_plugin_repeat_value(plugin); } /** Cancel exceptional value reporting period @@ -3648,9 +3688,6 @@ static void sfw_exception_cancel(void) * SENSORFW_MODULE * ========================================================================= */ -/** Sensord availability tracking state machine object */ -static sfw_service_t *sfw_service = 0; - // ---------------------------------------------------------------- /** Prepare sensors for suspending @@ -3678,8 +3715,11 @@ mce_sensorfw_resume(void) void mce_sensorfw_als_set_notify(void (*cb)(int lux)) { - if( (sfw_notify_als_cb = cb) ) - sfw_notify_als(NOTIFY_REPEAT, 0); + + if( (sfw_notify_als_cb = cb) ) { + sfw_plugin_t *plugin = sfw_service_plugin(sfw_service, SFW_SENSOR_ID_ALS); + sfw_plugin_repeat_value(plugin); + } } /** Try to enable ALS input @@ -3687,7 +3727,7 @@ mce_sensorfw_als_set_notify(void (*cb)(int lux)) void mce_sensorfw_als_enable(void) { - sfw_service_set_als(sfw_service, true); + sfw_service_set_sensor(sfw_service, SFW_SENSOR_ID_ALS, true); } /** Try to disable ALS input @@ -3695,7 +3735,7 @@ mce_sensorfw_als_enable(void) void mce_sensorfw_als_disable(void) { - sfw_service_set_als(sfw_service, false); + sfw_service_set_sensor(sfw_service, SFW_SENSOR_ID_ALS, false); } // ---------------------------------------------------------------- @@ -3707,8 +3747,10 @@ mce_sensorfw_als_disable(void) void mce_sensorfw_ps_set_notify(void (*cb)(bool covered)) { - if( (sfw_notify_ps_cb = cb) ) - sfw_notify_ps(NOTIFY_REPEAT, 0); + if( (sfw_notify_ps_cb = cb) ) { + sfw_plugin_t *plugin = sfw_service_plugin(sfw_service, SFW_SENSOR_ID_PS); + sfw_plugin_repeat_value(plugin); + } } /** Try to enable PS input @@ -3716,7 +3758,7 @@ mce_sensorfw_ps_set_notify(void (*cb)(bool covered)) void mce_sensorfw_ps_enable(void) { - sfw_service_set_ps(sfw_service, true); + sfw_service_set_sensor(sfw_service, SFW_SENSOR_ID_PS, true); } /** Try to disable PS input @@ -3724,7 +3766,7 @@ mce_sensorfw_ps_enable(void) void mce_sensorfw_ps_disable(void) { - sfw_service_set_ps(sfw_service, false); + sfw_service_set_sensor(sfw_service, SFW_SENSOR_ID_PS, false); } // ---------------------------------------------------------------- @@ -3736,8 +3778,10 @@ mce_sensorfw_ps_disable(void) void mce_sensorfw_orient_set_notify(void (*cb)(int state)) { - if( (sfw_notify_orient_cb = cb) ) - sfw_notify_orient(NOTIFY_REPEAT, 0); + if( (sfw_notify_orient_cb = cb) ) { + sfw_plugin_t *plugin = sfw_service_plugin(sfw_service, SFW_SENSOR_ID_ORIENT); + sfw_plugin_repeat_value(plugin); + } } /** Try to enable Orientation input @@ -3745,7 +3789,7 @@ mce_sensorfw_orient_set_notify(void (*cb)(int state)) void mce_sensorfw_orient_enable(void) { - sfw_service_set_orient(sfw_service, true); + sfw_service_set_sensor(sfw_service, SFW_SENSOR_ID_ORIENT, true); } /** Try to disable Orientation input @@ -3753,7 +3797,7 @@ mce_sensorfw_orient_enable(void) void mce_sensorfw_orient_disable(void) { - sfw_service_set_orient(sfw_service, false); + sfw_service_set_sensor(sfw_service, SFW_SENSOR_ID_ORIENT, false); } // ---------------------------------------------------------------- @@ -3819,11 +3863,26 @@ mce_sensorfw_evdev_cb(GIOChannel *chn, GIOCondition cnd, gpointer aptr) } } - if( als != -1 ) - sfw_notify_als(NOTIFY_EVDEV, als); + if( als != -1 ) { + sfw_sample_als_t sample = + { + .als_value = als, + }; + + sfw_plugin_t *plugin = sfw_service_plugin(sfw_service, SFW_SENSOR_ID_ALS); + sfw_plugin_notify(plugin, NOTIFY_EVDEV, &sample); + } + + if( ps != -1 ) { + sfw_sample_ps_t sample = + { + .ps_value = (ps < 1) ? 0 : 10, + .ps_withinProximity = (ps < 1) ? true : false, + }; - if( ps != -1 ) - sfw_notify_ps(NOTIFY_EVDEV, ps < 1); + sfw_plugin_t *plugin = sfw_service_plugin(sfw_service, SFW_SENSOR_ID_PS); + sfw_plugin_notify(plugin, NOTIFY_EVDEV, &sample); + } EXIT: if( !keep && *id ) { @@ -3886,7 +3945,13 @@ mce_sensorfw_als_attach(int fd) fd = -1; mce_log(LL_INFO, "ALS: %d (initial)", info.value); - sfw_notify_als(NOTIFY_EVDEV, info.value); + + sfw_sample_als_t sample = + { + .als_value = info.value, + }; + sfw_plugin_t *plugin = sfw_service_plugin(sfw_service, SFW_SENSOR_ID_ALS); + sfw_plugin_notify(plugin, NOTIFY_EVDEV, &sample); EXIT: if( fd != -1 ) @@ -3943,7 +4008,15 @@ mce_sensorfw_ps_attach(int fd) fd = -1; mce_log(LL_NOTICE, "PS: %d (initial)", info.value); - sfw_notify_ps(NOTIFY_EVDEV, info.value < 1); + + int ps = info.value; + sfw_sample_ps_t sample = + { + .ps_value = (ps < 1) ? 0 : 10, + .ps_withinProximity = (ps < 1) ? true : false, + }; + sfw_plugin_t *plugin = sfw_service_plugin(sfw_service, SFW_SENSOR_ID_PS); + sfw_plugin_notify(plugin, NOTIFY_EVDEV, &sample); EXIT: if( fd != -1 ) @@ -4017,8 +4090,6 @@ static mce_dbus_handler_t sfw_dbus_handlers[] = bool mce_sensorfw_init(void) { - sfw_exception_start(SFW_EXCEPTION_LENGTH_MCE_STARTING_UP); - /* Register D-Bus handlers */ mce_dbus_handler_register_array(sfw_dbus_handlers); @@ -4026,6 +4097,10 @@ mce_sensorfw_init(void) sfw_service = sfw_service_create(); sfw_service_do_query(sfw_service); + /* From proximity sensor reporting point of view MCE start up + * needs to be handled as a special case. */ + sfw_exception_start(SFW_EXCEPTION_LENGTH_MCE_STARTING_UP); + return true; } diff --git a/mce-sensorfw.dot b/mce-sensorfw.dot index 4dab5d62..a3e6daee 100644 --- a/mce-sensorfw.dot +++ b/mce-sensorfw.dot @@ -53,22 +53,26 @@ digraph mce_sensorfw OVERRIDE_DISABLING; OVERRIDE_DISABLED; OVERRIDE_ERROR; + OVERRIDE_NA; OVERRIDE_ANY [label="*"]; - OVERRIDE_ANY -> OVERRIDE_ERROR [label="failure"]; - OVERRIDE_ANY -> OVERRIDE_IDLE [label="reset()"]; + OVERRIDE_ANY -> OVERRIDE_ERROR [label="failure"]; + OVERRIDE_ANY -> OVERRIDE_IDLE [label="reset()"]; - OVERRIDE_IDLE -> OVERRIDE_RETHINK [label="connected"]; + OVERRIDE_IDLE -> OVERRIDE_RETHINK [label="connected"]; OVERRIDE_RETHINK -> OVERRIDE_ENABLING; OVERRIDE_RETHINK -> OVERRIDE_DISABLING; - OVERRIDE_ENABLING -> OVERRIDE_ENABLED; - OVERRIDE_ENABLED -> OVERRIDE_RETHINK [label="disable()"]; - OVERRIDE_DISABLING -> OVERRIDE_DISABLED; - OVERRIDE_DISABLED -> OVERRIDE_RETHINK [label="enable()"]; + OVERRIDE_ENABLING -> OVERRIDE_ENABLED [label="ack"]; + OVERRIDE_ENABLED -> OVERRIDE_RETHINK [label="disable()"]; + OVERRIDE_DISABLING -> OVERRIDE_DISABLED [label="ack"]; + OVERRIDE_DISABLED -> OVERRIDE_RETHINK [label="enable()"]; - OVERRIDE_ERROR -> OVERRIDE_RETHINK [label="retry"]; + OVERRIDE_ERROR -> OVERRIDE_RETHINK [label="retry"]; + + OVERRIDE_ENABLING -> OVERRIDE_NA [label="nak"]; + OVERRIDE_DISABLING -> OVERRIDE_NA [label="nak"]; } subgraph clusterCONNECTION {