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 {