diff --git a/.depend b/.depend index 760ed524..996f8366 100644 --- a/.depend +++ b/.depend @@ -41,6 +41,7 @@ builtin-gconf.pic.o:\ datapipe.o:\ datapipe.c\ datapipe.h\ + evdev.h\ mce-lib.h\ mce-log.h\ mce.h\ @@ -48,6 +49,7 @@ datapipe.o:\ datapipe.pic.o:\ datapipe.c\ datapipe.h\ + evdev.h\ mce-lib.h\ mce-log.h\ mce.h\ @@ -142,6 +144,7 @@ mce-common.o:\ datapipe.h\ mce-common.h\ mce-dbus.h\ + mce-lib.h\ mce-log.h\ mce.h\ @@ -151,6 +154,7 @@ mce-common.pic.o:\ datapipe.h\ mce-common.h\ mce-dbus.h\ + mce-lib.h\ mce-log.h\ mce.h\ @@ -928,6 +932,7 @@ modules/proximity.o:\ modules/proximity.c\ builtin-gconf.h\ datapipe.h\ + mce-lib.h\ mce-log.h\ mce-sensorfw.h\ mce-setting.h\ @@ -938,6 +943,7 @@ modules/proximity.pic.o:\ modules/proximity.c\ builtin-gconf.h\ datapipe.h\ + mce-lib.h\ mce-log.h\ mce-sensorfw.h\ mce-setting.h\ diff --git a/builtin-gconf.c b/builtin-gconf.c index 52f5d0f0..1a2d7087 100644 --- a/builtin-gconf.c +++ b/builtin-gconf.c @@ -1,8 +1,23 @@ -/* ------------------------------------------------------------------------- * - * Copyright (C) 2012-2014 Jolla Ltd. - * Contact: Simo Piiroinen - * License: LGPLv2 - * ------------------------------------------------------------------------- */ +/** + * @file builtin-gconf.c + * GConf compatibility module - for dynamic mce settings + *

+ * Copyright (C) 2012-2019 Jolla Ltd. + *

+ * @author Simo Piiroinen + * + * mce is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License + * version 2.1 as published by the Free Software Foundation. + * + * mce is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with mce. If not, see . + */ /* ------------------------------------------------------------------------- * * NOTE: This module implements just enough of the GConf API to allow us @@ -1592,6 +1607,11 @@ static const setting_t gconf_defaults[] = .type = "b", .def = G_STRINGIFY(MCE_DEFAULT_PROXIMITY_PS_ENABLED), }, + { + .key = MCE_SETTING_PROXIMITY_ON_DEMAND, + .type = "b", + .def = G_STRINGIFY(MCE_DEFAULT_PROXIMITY_ON_DEMAND), + }, { .key = MCE_SETTING_PROXIMITY_PS_ACTS_AS_LID, .type = "b", diff --git a/datapipe.c b/datapipe.c index 0d11ef83..236374f8 100644 --- a/datapipe.c +++ b/datapipe.c @@ -4,7 +4,7 @@ * this can be used to filter data and to setup data triggers *

* Copyright © 2007-2008 Nokia Corporation and/or its subsidiary(-ies). - * Copyright (C) 2014-2017 Jolla Ltd. + * Copyright (C) 2014-2019 Jolla Ltd. *

* @author David Weinehall * @author Simo Piiroinen @@ -630,6 +630,31 @@ datapipe_t lens_cover_state_pipe = DATAPIPE_INIT(lens_cover_state /** Proximity sensor; read only */ datapipe_t proximity_sensor_actual_pipe = DATAPIPE_INIT(proximity_sensor_actual, cover_state, COVER_OPEN, 0, DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_DEFAULT); +/** Proximity sensor; read only */ +datapipe_t proximity_sensor_effective_pipe = DATAPIPE_INIT(proximity_sensor_effective, cover_state, COVER_UNDEF, 0, DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_DEFAULT); + +/** Proximity sensor on-demand control; write only + * + * The data fed into proximity_sensor_required_pipe needs to + * be a statically allocated const string with format like: + * + * "" + * + * Where is one of: + * + * - PROXIMITY_SENSOR_REQUIRED_ADD: is added to the + * list of resons to keep on-demand proximity sensor mode + * active. + * + * - PROXIMITY_SENSOR_REQUIRED_REM: is from the the + * list of resons to keep on-demand proximity sensor mode + * active. + */ +datapipe_t proximity_sensor_required_pipe = DATAPIPE_INIT(proximity_sensor_required, string, 0, 0, DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_NOTHING); + +/** proximity blanking; read only */ +datapipe_t proximity_blanked_pipe = DATAPIPE_INIT(proximity_blanked, boolean, false, 0, DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_DEFAULT); + /** Ambient light sensor; read only */ datapipe_t light_sensor_actual_pipe = DATAPIPE_INIT(light_sensor_actual, int, 400, 0, DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_DEFAULT); @@ -766,9 +791,6 @@ datapipe_t keypad_grab_active_pipe = DATAPIPE_INIT(keypad_grab_acti /** music playback active; read only */ datapipe_t music_playback_ongoing_pipe = DATAPIPE_INIT(music_playback_ongoing, boolean, false, 0, DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_DEFAULT); -/** proximity blanking; read only */ -datapipe_t proximity_blanked_pipe = DATAPIPE_INIT(proximity_blanked, boolean, false, 0, DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_DEFAULT); - /** fingerprint daemon availability; read only */ datapipe_t fpd_service_state_pipe = DATAPIPE_INIT(fpd_service_state, service_state, SERVICE_STATE_UNDEF, 0, DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_DEFAULT); @@ -1265,6 +1287,9 @@ void mce_datapipe_quit(void) datapipe_free(&interaction_expected_pipe); datapipe_free(&tklock_request_pipe); datapipe_free(&proximity_sensor_actual_pipe); + datapipe_free(&proximity_sensor_effective_pipe); + datapipe_free(&proximity_sensor_required_pipe); + datapipe_free(&proximity_blanked_pipe); datapipe_free(&light_sensor_actual_pipe); datapipe_free(&light_sensor_filtered_pipe); datapipe_free(&light_sensor_poll_request_pipe); @@ -1320,7 +1345,6 @@ void mce_datapipe_quit(void) datapipe_free(&keypad_grab_active_pipe); datapipe_free(&keypad_grab_wanted_pipe); datapipe_free(&music_playback_ongoing_pipe); - datapipe_free(&proximity_blanked_pipe); datapipe_free(&fpd_service_state_pipe); datapipe_free(&fpstate_pipe); datapipe_free(&enroll_in_progress_pipe); diff --git a/datapipe.h b/datapipe.h index 9dbe3c83..5d8a48fb 100644 --- a/datapipe.h +++ b/datapipe.h @@ -3,8 +3,10 @@ * Headers for the simple filter framework *

* Copyright © 2007 Nokia Corporation and/or its subsidiary(-ies). + * Copyright (C) 2014-2019 Jolla Ltd. *

* @author David Weinehall + * @author: Simo Piiroinen * * mce is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License @@ -193,6 +195,18 @@ void mce_datapipe_generate_inactivity (void); GINT_TO_POINTER(tklock_request));\ }while(0) +/** Add reason -prefix for executing proximity_sensor_required_pipe request + * + * See #proximity_sensor_required_pipe for details. + */ +#define PROXIMITY_SENSOR_REQUIRED_ADD "+" + +/** Remove reason -prefix for executing proximity_sensor_required_pipe request + * + * See #proximity_sensor_required_pipe for details. + */ +#define PROXIMITY_SENSOR_REQUIRED_REM "-" + /* ========================================================================= * * Datapipes * ========================================================================= */ @@ -223,6 +237,9 @@ extern datapipe_t lid_sensor_actual_pipe; extern datapipe_t lid_sensor_filtered_pipe; extern datapipe_t lens_cover_state_pipe; extern datapipe_t proximity_sensor_actual_pipe; +extern datapipe_t proximity_sensor_effective_pipe; +extern datapipe_t proximity_sensor_required_pipe; +extern datapipe_t proximity_blanked_pipe; extern datapipe_t light_sensor_actual_pipe; extern datapipe_t light_sensor_filtered_pipe; extern datapipe_t light_sensor_poll_request_pipe; @@ -267,7 +284,6 @@ extern datapipe_t touch_grab_active_pipe; extern datapipe_t keypad_grab_wanted_pipe; extern datapipe_t keypad_grab_active_pipe; extern datapipe_t music_playback_ongoing_pipe; -extern datapipe_t proximity_blanked_pipe; extern datapipe_t fpd_service_state_pipe; extern datapipe_t fpstate_pipe; extern datapipe_t enroll_in_progress_pipe; diff --git a/mce-common.c b/mce-common.c index 6d1dc4d8..c2cd0ad4 100644 --- a/mce-common.c +++ b/mce-common.c @@ -2,7 +2,7 @@ * @file mce-common.c * Common state logic for Mode Control Entity *

- * Copyright (C) 2017 Jolla Ltd. + * Copyright (C) 2017-2019 Jolla Ltd. *

* @author Simo Piiroinen * @@ -22,6 +22,7 @@ #include "mce.h" #include "mce-dbus.h" +#include "mce-lib.h" #include "mce-log.h" #include @@ -29,11 +30,52 @@ #include #include +/* ========================================================================= * + * TYPES + * ========================================================================= */ + +/** Bookkeeping data for on-condition callback function */ +typedef struct +{ + /** Source identification, for mass cancelation */ + gchar *srce; + + /** Function to call */ + GDestroyNotify func; + + /** Parameter to give to the function */ + gpointer aptr; +} on_condition_t; + /* ========================================================================= * * PROTOTYPES * ========================================================================= */ -// DBUS_FUNCTIONS +/* ------------------------------------------------------------------------- * + * ON_CONDITION + * ------------------------------------------------------------------------- */ + +static bool on_condition_matches (on_condition_t *self, const char *srce, GDestroyNotify func, gpointer aptr); +static on_condition_t *on_condition_create (const char *srce, GDestroyNotify func, gpointer aptr); +static void on_condition_delete (on_condition_t *self); +static void on_condition_exec (on_condition_t *self); +static void on_condition_exec_and_delete_cb(gpointer self); +static void on_condition_delete_cb (gpointer self); + +/* ------------------------------------------------------------------------- * + * COMMON_ON_PROXIMITY + * ------------------------------------------------------------------------- */ + +static gboolean common_on_proximity_exec_cb (gpointer aptr); +static void common_on_proximity_exec (void); +void common_on_proximity_schedule(const char *srce, GDestroyNotify func, gpointer aptr); +void common_on_proximity_cancel (const char *srce, GDestroyNotify func, gpointer aptr); +static void common_on_proximity_quit (void); + +/* ------------------------------------------------------------------------- * + * COMMON_DBUS + * ------------------------------------------------------------------------- */ + static void common_dbus_send_usb_cable_state (DBusMessage *const req); static gboolean common_dbus_get_usb_cable_state_cb(DBusMessage *const req); static void common_dbus_send_charger_state (DBusMessage *const req); @@ -42,18 +84,26 @@ static void common_dbus_send_battery_status (DBusMessage *const req); static gboolean common_dbus_get_battery_status_cb (DBusMessage *const req); static void common_dbus_send_battery_level (DBusMessage *const req); static gboolean common_dbus_get_battery_level_cb (DBusMessage *const req); +static gboolean common_dbus_initial_cb (gpointer aptr); static void common_dbus_init (void); static void common_dbus_quit (void); -// DATAPIPE_FUNCTIONS -static void common_datapipe_usb_cable_state_cb(gconstpointer data); -static void common_datapipe_charger_state_cb (gconstpointer data); -static void common_datapipe_battery_status_cb (gconstpointer data); -static void common_datapipe_battery_level_cb (gconstpointer data); -static void common_datapipe_init (void); -static void common_datapipe_quit (void); +/* ------------------------------------------------------------------------- * + * COMMON_DATAPIPE + * ------------------------------------------------------------------------- */ + +static void common_datapipe_usb_cable_state_cb (gconstpointer data); +static void common_datapipe_charger_state_cb (gconstpointer data); +static void common_datapipe_battery_status_cb (gconstpointer data); +static void common_datapipe_battery_level_cb (gconstpointer data); +static void common_datapipe_proximity_sensor_actual_cb(gconstpointer data); +static void common_datapipe_init (void); +static void common_datapipe_quit (void); + +/* ------------------------------------------------------------------------- * + * MCE_COMMON + * ------------------------------------------------------------------------- */ -// MODULE_INIT_QUIT bool mce_common_init(void); void mce_common_quit(void); @@ -73,6 +123,210 @@ static battery_status_t battery_status = BATTERY_STATUS_UNDEF; /** Battery charge level: assume 100% */ static gint battery_level = BATTERY_LEVEL_INITIAL; +/** Cached (raw) proximity sensor state */ +static cover_state_t proximity_sensor_actual = COVER_UNDEF; + +/* ========================================================================= * + * ON_CONDITION + * ========================================================================= */ + +static bool +on_condition_matches(on_condition_t *self, + const char *srce, GDestroyNotify func, gpointer aptr) +{ + bool matches = false; + + if( !srce || !self || !self->srce ) + goto EXIT; + + if( strcmp(self->srce, srce) ) + goto EXIT; + + if( self->func == func && self->aptr == aptr ) + matches = true; + else + matches = !func && !srce; + +EXIT: + return matches; +} + +static on_condition_t * +on_condition_create(const char *srce, GDestroyNotify func, gpointer aptr) +{ + on_condition_t *self = g_slice_alloc0(sizeof *self); + self->srce = g_strdup(srce); + self->func = func; + self->aptr = aptr; + return self; +} + +static void +on_condition_delete(on_condition_t *self) +{ + if( self ) { + g_free(self->srce); + g_slice_free1(sizeof *self, self); + } +} + +static void +on_condition_exec(on_condition_t *self) +{ + if( self ) + self->func(self->aptr); +} + +static void +on_condition_exec_and_delete_cb(gpointer self) +{ + on_condition_exec(self); + on_condition_delete(self); +} + +static void +on_condition_delete_cb(gpointer self) +{ + on_condition_delete(self); +} + +/* ========================================================================= * + * COMMON_ON_PROXIMITY + * ========================================================================= */ + +#define COMMON_ON_DEMAND_TAG "common_on_proximity" + +static GSList *common_on_proximity_actions = 0; +static guint common_on_proximity_exec_id = 0; + +static gboolean +common_on_proximity_exec_cb(gpointer aptr) +{ + (void)aptr; + + gboolean result = G_SOURCE_REMOVE; + + GSList *todo; + + /* Execute queued actions */ + if( (todo = common_on_proximity_actions) ) { + common_on_proximity_actions = 0; + todo = g_slist_reverse(todo); + g_slist_free_full(todo, on_condition_exec_and_delete_cb); + } + + /* Check if executed actions queued more actions */ + if( common_on_proximity_actions ) { + /* Repeat to handle freshly added actions */ + result = G_SOURCE_CONTINUE; + } + else { + /* Queue exchausted - sensor no longer needed */ + datapipe_exec_full(&proximity_sensor_required_pipe, + PROXIMITY_SENSOR_REQUIRED_REM + COMMON_ON_DEMAND_TAG); + } + +EXIT: + if( result == G_SOURCE_REMOVE ) + common_on_proximity_exec_id = 0; + + return result; +} + +static void +common_on_proximity_exec(void) +{ + /* Execute via idle to make sure all proximity + * datapipe listeners have had a chance to + * register sensor state before callbacks + * get triggered. */ + if( !common_on_proximity_exec_id ) { + common_on_proximity_exec_id = + mce_wakelocked_idle_add(common_on_proximity_exec_cb, + 0); + } +} + +/** Execute callback function when actual proximity sensor state is available + * + * @param srce Call site identification + * @param func Callback function pointer + * @param aptr Parameter for the callback function + */ +void +common_on_proximity_schedule(const char *srce, GDestroyNotify func, gpointer aptr) +{ + /* In order to execute actions in the requested order, + * immediate execution can be allowed only when proximity + * sensor state is known and the already queued actions + * have been executed. + */ + if( proximity_sensor_actual == COVER_UNDEF || + common_on_proximity_actions || + common_on_proximity_exec_id ) { + // TODO: all failures to communicate sensor power up with + // sensorfwd should lead to mce-sensorfw module + // declaring proximity=not-covered, but having an + // explicit timeout here would not hurt ... + if( !common_on_proximity_actions ) + datapipe_exec_full(&proximity_sensor_required_pipe, + PROXIMITY_SENSOR_REQUIRED_ADD + COMMON_ON_DEMAND_TAG); + + common_on_proximity_actions = + g_slist_prepend(common_on_proximity_actions, + on_condition_create(srce, func, aptr)); + } + else { + func(aptr); + } +} + +/** Cancel pending on-proximity callback + * + * @param srce Call site identification + * @param func Callback function pointer, or NULL for all + * @param aptr Parameter for the callback function, or NULL for all + */ +void +common_on_proximity_cancel(const char *srce, GDestroyNotify func, gpointer aptr) +{ + for( GSList *iter = common_on_proximity_actions; iter; iter = iter->next ) { + on_condition_t *item = iter->data; + + if( !item ) + continue; + + if( !on_condition_matches(item, srce, func, aptr) ) + continue; + + /* Detach from list and delete. + * + * Note that the list itself is not garbage collected in order not + * to disturb possibly pending execute etc logic -> all iterators + * must be prepared to bump into empty links. + */ + iter->data = 0; + on_condition_delete(item); + } +} + +static void +common_on_proximity_quit(void) +{ + /* Cancel pending "on_condition" actions */ + g_slist_free_full(common_on_proximity_actions, + on_condition_delete_cb), + common_on_proximity_actions = 0; + + /* Do not leave active timers behind */ + if( common_on_proximity_exec_id ) { + g_source_remove(common_on_proximity_exec_id), + common_on_proximity_exec_id = 0; + } +} + /* ========================================================================= * * DBUS_FUNCTIONS * ========================================================================= */ @@ -578,6 +832,31 @@ static void common_datapipe_battery_level_cb(gconstpointer data) return; } +/* ------------------------------------------------------------------------- * + * proximity_sensor + * ------------------------------------------------------------------------- */ + +/** Change notifications for proximity_sensor_actual + */ +static void common_datapipe_proximity_sensor_actual_cb(gconstpointer data) +{ + cover_state_t prev = proximity_sensor_actual; + proximity_sensor_actual = GPOINTER_TO_INT(data); + + if( proximity_sensor_actual == prev ) + goto EXIT; + + mce_log(LL_DEBUG, "proximity_sensor_actual = %s -> %s", + proximity_state_repr(prev), + proximity_state_repr(proximity_sensor_actual)); + + if( proximity_sensor_actual != COVER_UNDEF ) + common_on_proximity_exec(); + +EXIT: + return; +} + /* ------------------------------------------------------------------------- * * init/quit * ------------------------------------------------------------------------- */ @@ -602,6 +881,10 @@ static datapipe_handler_t common_datapipe_handlers[] = .datapipe = &battery_level_pipe, .output_cb = common_datapipe_battery_level_cb, }, + { + .datapipe = &proximity_sensor_actual_pipe, + .output_cb = common_datapipe_proximity_sensor_actual_cb, + }, // sentinel { .datapipe = 0, @@ -654,4 +937,5 @@ mce_common_quit(void) /* remove all handlers */ common_dbus_quit(); common_datapipe_quit(); + common_on_proximity_quit(); } diff --git a/mce-common.h b/mce-common.h index 94b9ffef..553976d2 100644 --- a/mce-common.h +++ b/mce-common.h @@ -2,7 +2,7 @@ * @file mce-common.h * Header for common state logic for Mode Control Entity *

- * Copyright (C) 2017 Jolla Ltd. + * Copyright (C) 2017-2019 Jolla Ltd. *

* @author Simo Piiroinen * @@ -23,8 +23,12 @@ # define MCE_COMMON_H_ # include +# include bool mce_common_init(void); void mce_common_quit(void); +void common_on_proximity_schedule(const char *srce, GDestroyNotify func, gpointer aptr); +void common_on_proximity_cancel (const char *srce, GDestroyNotify func, gpointer aptr); + #endif /* MCE_COMMON_H_ */ diff --git a/modules/proximity.c b/modules/proximity.c index 61d070d3..0b2c7d1c 100644 --- a/modules/proximity.c +++ b/modules/proximity.c @@ -27,6 +27,7 @@ #include "proximity.h" #include "../mce.h" +#include "../mce-lib.h" #include "../mce-log.h" #include "../mce-setting.h" #include "../mce-sensorfw.h" @@ -44,21 +45,19 @@ * Protos * ========================================================================= */ -/* ------------------------------------------------------------------------- * - * MP_REPORT - * ------------------------------------------------------------------------- */ - -static void mp_report_proximity_state(cover_state_t state); -static void mp_report_lid_state (cover_state_t state); - /* ------------------------------------------------------------------------- * * MP_MONITOR * ------------------------------------------------------------------------- */ -static void mp_monitor_update_state(bool covered); -static void mp_monitor_enable (void); -static void mp_monitor_disable (void); -static void mp_monitor_rethink (void); +static gboolean mp_monitor_linger_end_cb (gpointer aptr); +static void mp_monitor_cancel_linger (void); +static void mp_monitor_start_linger (void); +static gboolean mp_monitor_enable_delay_cb (gpointer aptr); +static void mp_monitor_report_state (void); +static void mp_monitor_update_state (bool covered); +static void mp_monitor_set_enabled (bool enable); +static bool mp_monitor_on_demand (void); +static void mp_monitor_rethink (void); /* ------------------------------------------------------------------------- * * MP_SETTING @@ -72,12 +71,17 @@ static void mp_setting_quit(void); * MP_DATAPIPE * ------------------------------------------------------------------------- */ -static void mp_datapipe_call_state_cb (gconstpointer const data); -static void mp_datapipe_alarm_ui_state_cb (gconstpointer const data); -static void mp_datapipe_display_state_curr_cb(gconstpointer data); -static void mp_datapipe_submode_cb (gconstpointer data); -static void mp_datapipe_init (void); -static void mp_datapipe_quit (void); +static void mp_datapipe_set_proximity_sensor_actual (cover_state_t state); +static void mp_datapipe_set_lid_sensor_actual (cover_state_t state); +static void mp_datapipe_call_state_cb (gconstpointer const data); +static void mp_datapipe_alarm_ui_state_cb (gconstpointer const data); +static void mp_datapipe_display_state_next_cb (gconstpointer data); +static void mp_datapipe_display_state_curr_cb (gconstpointer data); +static void mp_datapipe_submode_cb (gconstpointer data); +static void mp_datapipe_uiexception_type_cb (gconstpointer data); +static void mp_datapipe_proximity_sensor_required_cb(gconstpointer data); +static void mp_datapipe_init (void); +static void mp_datapipe_quit (void); /* ------------------------------------------------------------------------- * * G_MODULE @@ -103,82 +107,129 @@ G_MODULE_EXPORT module_info_struct module_info = { .priority = 100 }; -/** Cached call state */ +/** State of proximity sensor monitoring */ +static bool mp_monitor_enabled = FALSE; + +/** Linger time for disabling sensor in on-demand mode [ms] */ +static gint mp_monitor_linger_end_ms = 5000; + +/** Timer id for disabling sensor in on-demand mode */ +static guint mp_monitor_linger_end_id = 0; + +/** Time reserved for sensor power up to reach stable state [ms] */ +static gint mp_monitor_enable_delay_ms = 500; + +/** Timer id for ending sensor power up delay */ +static guint mp_monitor_enable_delay_id = 0; + +/** Currently active on-demand reasons */ +static GHashTable *mp_datapipe_proximity_sensor_required_lut = 0; + +/* ------------------------------------------------------------------------- * + * datapipes + * ------------------------------------------------------------------------- */ + +/** Cached proximity_sensor_required_pipe state */ +static bool proximity_sensor_required = false; + +/** Cached call_state_pipe state */ static call_state_t call_state = CALL_STATE_INVALID; -/** Cached alarm UI state */ +/** Cached alarm_ui_state_pipe state */ static alarm_ui_state_t alarm_ui_state = MCE_ALARM_UI_INVALID_INT32; -/** Cached display state */ +/** Cached display_state_next_pipe state */ +static display_state_t display_state_next = MCE_DISPLAY_UNDEF; + +/** Cached display_state_curr_pipe state */ static display_state_t display_state_curr = MCE_DISPLAY_UNDEF; -/** Cached submode state */ +/** Cached submode_pipe state */ static submode_t submode = MCE_SUBMODE_NORMAL; -/** State of proximity sensor monitoring */ -static gboolean mp_monitor_enabled = FALSE; +/** Cached uiexception_type_pipe state */ +static uiexception_type_t uiexception_type = UIEXCEPTION_TYPE_NONE; + +/* ------------------------------------------------------------------------- * + * settings + * ------------------------------------------------------------------------- */ /** Configuration value for use proximity sensor */ -static gboolean use_ps = MCE_DEFAULT_PROXIMITY_PS_ENABLED; +static gboolean setting_use_ps = MCE_DEFAULT_PROXIMITY_PS_ENABLED; +static guint setting_use_ps_conf_id = 0; -/** Configuration change id for use_ps */ -static guint use_ps_conf_id = 0; +/** Configuration value for on-demand proximity sensor use */ +static gboolean setting_on_demand_ps = MCE_DEFAULT_PROXIMITY_ON_DEMAND; +static guint setting_on_demand_ps_conf_id = 0; /** Configuration value for ps acts as lid sensor */ -static gboolean ps_acts_as_lid = MCE_DEFAULT_PROXIMITY_PS_ACTS_AS_LID; - -/** Configuration change id for ps_acts_as_lid */ -static guint ps_acts_as_lid_conf_id = 0; +static gboolean setting_ps_acts_as_lid = MCE_DEFAULT_PROXIMITY_PS_ACTS_AS_LID; +static guint setting_ps_acts_as_lid_conf_id = 0; /* ========================================================================= * - * MP_REPORT + * MP_MONITOR * ========================================================================= */ -/** Broadcast proximity sensor state within MCE - * - * @param state COVER_CLOSED or COVER_OPEN - */ -static void -mp_report_proximity_state(cover_state_t state) +static gboolean +mp_monitor_linger_end_cb(gpointer aptr) { - /* Get current proximity datapipe value */ - cover_state_t old_state = datapipe_get_gint(proximity_sensor_actual_pipe); - - /* Execute datapipe if state has changed */ + (void)aptr; + mce_log(LL_DEBUG, "PS monitoring: linger timeout"); + mp_monitor_linger_end_id = 0; + mp_monitor_set_enabled(false); + return G_SOURCE_REMOVE; +} - if( old_state != state ) { - mce_log(LL_CRUCIAL, "state: %s -> %s", - cover_state_repr(old_state), - cover_state_repr(state)); +static void +mp_monitor_cancel_linger(void) +{ + if( mp_monitor_linger_end_id ) { + mce_log(LL_DEBUG, "PS monitoring: linger stopped"); + g_source_remove(mp_monitor_linger_end_id), + mp_monitor_linger_end_id = 0; + } +} - datapipe_exec_full(&proximity_sensor_actual_pipe, - GINT_TO_POINTER(state)); +static void +mp_monitor_start_linger(void) +{ + if( !mp_monitor_linger_end_id ) { + mce_log(LL_DEBUG, "PS monitoring: linger started"); + mp_monitor_linger_end_id = + mce_wakelocked_timeout_add(mp_monitor_linger_end_ms, + mp_monitor_linger_end_cb, + 0); } } -/** Broadcast faked lid sensor state within mce - * - * @param state COVER_CLOSED, COVER_OPEN or COVER_UNDEF - */ +static gboolean mp_monitor_enable_delay_cb(gpointer aptr) +{ + (void)aptr; + mce_log(LL_DEBUG, "PS monitoring: sensor power up finished"); + mp_monitor_enable_delay_id = 0; + mp_monitor_report_state(); + return G_SOURCE_REMOVE; +} + +static cover_state_t proximity_sensor_actual = COVER_UNDEF; + static void -mp_report_lid_state(cover_state_t state) +mp_monitor_report_state(void) { - cover_state_t old_state = datapipe_get_gint(lid_sensor_actual_pipe); + /* Skip if the sensor is not fully powered up yet */ + if( !mp_monitor_enabled || mp_monitor_enable_delay_id ) + goto EXIT; - if( state != old_state ) { - mce_log(LL_CRUCIAL, "state: %s -> %s", - cover_state_repr(old_state), - cover_state_repr(state)); + cover_state_t state = proximity_sensor_actual; + if( setting_ps_acts_as_lid ) + mp_datapipe_set_lid_sensor_actual(state); + else + mp_datapipe_set_proximity_sensor_actual(state); - datapipe_exec_full(&lid_sensor_actual_pipe, - GINT_TO_POINTER(state)); - } +EXIT: + return; } -/* ========================================================================= * - * MP_MONITOR - * ========================================================================= */ - /** Callback for handling proximity sensor state changes * * @param covered proximity sensor covered @@ -186,62 +237,118 @@ mp_report_lid_state(cover_state_t state) static void mp_monitor_update_state(bool covered) { - cover_state_t proximity_sensor_actual = COVER_UNDEF; + mce_log(LL_DEBUG, "PS monitoring: %s from sensorfwd", + covered ? "COVERED" : "NOT-COVERED"); if( covered ) proximity_sensor_actual = COVER_CLOSED; else proximity_sensor_actual = COVER_OPEN; - if( ps_acts_as_lid ) - mp_report_lid_state(proximity_sensor_actual); - else - mp_report_proximity_state(proximity_sensor_actual); - - return; + mp_monitor_report_state(); } -/** Enable proximity monitoring +/** Enable / disable proximity monitoring */ + static void -mp_monitor_enable(void) +mp_monitor_set_enabled(bool enable) { - /* Already enabled? */ - if( mp_monitor_enabled ) + mp_monitor_cancel_linger(); + + if( mp_monitor_enabled == enable ) goto EXIT; - mce_log(LL_DEBUG, "enable PS monitoring"); - mp_monitor_enabled = TRUE; + if( mp_monitor_enable_delay_id ) { + g_source_remove(mp_monitor_enable_delay_id), + mp_monitor_enable_delay_id = 0; + } - /* install input processing hooks, update current state */ - mce_sensorfw_ps_set_notify(mp_monitor_update_state); - mce_sensorfw_ps_enable(); + if( (mp_monitor_enabled = enable) ) { + mce_log(LL_DEBUG, "PS monitoring: start sensor power up"); + /* Start sensor power up hold-out timer */ + mp_monitor_enable_delay_id = + mce_wakelocked_timeout_add(mp_monitor_enable_delay_ms, + mp_monitor_enable_delay_cb, + 0); + /* Install input processing hooks, update current state */ + mce_sensorfw_ps_set_notify(mp_monitor_update_state); + mce_sensorfw_ps_enable(); + } + else { + mce_log(LL_DEBUG, "PS monitoring: sensor power down"); + /* disable input */ + mce_sensorfw_ps_disable(); + /* remove input processing hooks */ + mce_sensorfw_ps_set_notify(0); + /* Artificially flip to unknown state */ + if( setting_ps_acts_as_lid ) + mp_datapipe_set_lid_sensor_actual(COVER_UNDEF); + else + mp_datapipe_set_proximity_sensor_actual(COVER_UNDEF); + } EXIT: return; - } -/** Disable proximity monitoring +/** Evaluate whether there is demand for proximity sensor */ -static void -mp_monitor_disable(void) +static bool +mp_monitor_on_demand(void) { - /* Already disabled? */ - if( !mp_monitor_enabled ) - goto EXIT; + /* Assume proximity state is not needed */ + bool enable = false; + + /* LPM states are controlled by proximity sensor */ + switch( display_state_next ) { + case MCE_DISPLAY_LPM_ON: + case MCE_DISPLAY_LPM_OFF: + enable = true; + break; + default: + break; + } + switch( display_state_curr ) { + case MCE_DISPLAY_LPM_ON: + case MCE_DISPLAY_LPM_OFF: + enable = true; + break; + default: + break; + } - mce_log(LL_DEBUG, "disable PS monitoring"); - mp_monitor_enabled = FALSE; + /* Unblank on ringing / in-call blank/unblank */ + switch( call_state ) { + case CALL_STATE_RINGING: + case CALL_STATE_ACTIVE: + enable = true; + break; + default: + break; + } - /* disable input */ - mce_sensorfw_ps_disable(); + /* Unblank on alarm */ + switch( alarm_ui_state ) { + case MCE_ALARM_UI_RINGING_INT32: + case MCE_ALARM_UI_VISIBLE_INT32: + enable = true; + break; + default: + break; + } - /* remove input processing hooks */ - mce_sensorfw_ps_set_notify(0); + /* All exceptional display on conditions require + * proximity information. */ + if( uiexception_type != UIEXCEPTION_TYPE_NONE ) + enable = true; -EXIT: - return; + /* Need for proximity sensor, as signaled via + * proximity_sensor_required_pipe */ + if( proximity_sensor_required ) + enable = true; + + return enable; } /** Re-evaluate need for proximity monitoring @@ -249,30 +356,40 @@ mp_monitor_disable(void) static void mp_monitor_rethink(void) { - static gboolean old_enable = FALSE; - - /* Default to keeping the proximity sensor always enabled. */ - gboolean enable = TRUE; + mce_log(LL_DEBUG, "setting_use_ps=%d setting_on_demand_ps=%d", + setting_use_ps, setting_on_demand_ps); - if( !use_ps ) { - enable = FALSE; + if( !setting_use_ps ) { + /* Disable without delay */ + mp_monitor_set_enabled(false); - if( ps_acts_as_lid ) - mp_report_lid_state(COVER_UNDEF); + /* As there will be no updates, feign value + * appropriate for target datapipe. */ + if( setting_ps_acts_as_lid ) + mp_datapipe_set_lid_sensor_actual(COVER_UNDEF); else - mp_report_proximity_state(COVER_OPEN); + mp_datapipe_set_proximity_sensor_actual(COVER_OPEN); } + else if( !setting_on_demand_ps ) { + /* Enable without delay and wait for sensor data */ + mp_monitor_set_enabled(true); + } + else { + /* Act on demand */ + bool enable = mp_monitor_on_demand(); - if( old_enable == enable ) - goto EXIT; + mce_log(LL_DEBUG, "enable=%d enabled=%d", + enable, mp_monitor_enabled); - if( (old_enable = enable) ) - mp_monitor_enable(); - else - mp_monitor_disable(); - -EXIT: - return; + if( enable ) { + /* Enable without delay, wait for data */ + mp_monitor_set_enabled(true); + } + else if( mp_monitor_enabled ) { + /* Disable after delay, then switch to COVER_UNDEF */ + mp_monitor_start_linger(); + } + } } /* ========================================================================= * @@ -299,36 +416,53 @@ mp_setting_cb(GConfClient *const gcc, const guint id, goto EXIT; } - if( id == use_ps_conf_id ) { - gboolean old = use_ps; - use_ps = gconf_value_get_bool(gcv); - - if( use_ps == old ) - goto EXIT; - + if( id == setting_use_ps_conf_id ) { + gboolean prev = setting_use_ps; + setting_use_ps = gconf_value_get_bool(gcv); + + if( prev != setting_use_ps ) { + /* If sensor was disabled, we need to clear feigned + * targer datapipe values. */ + if( setting_use_ps ) { + if( setting_ps_acts_as_lid ) + mp_datapipe_set_lid_sensor_actual(COVER_UNDEF); + else + mp_datapipe_set_proximity_sensor_actual(COVER_UNDEF); + } + mp_monitor_rethink(); + } } - else if( id == ps_acts_as_lid_conf_id ) { - gboolean old = ps_acts_as_lid; - ps_acts_as_lid = gconf_value_get_bool(gcv); - - if( ps_acts_as_lid == old ) - goto EXIT; + else if( id == setting_on_demand_ps_conf_id ) { + gboolean prev = setting_on_demand_ps; + setting_on_demand_ps = gconf_value_get_bool(gcv); - if( ps_acts_as_lid ) { - // ps is lid now -> set ps to open state - mp_report_proximity_state(COVER_OPEN); - } - else { - // ps is ps again -> invalidate lid state - mp_report_lid_state(COVER_UNDEF); + if( prev != setting_on_demand_ps ) + mp_monitor_rethink(); + } + else if( id == setting_ps_acts_as_lid_conf_id ) { + gboolean prev = setting_ps_acts_as_lid; + setting_ps_acts_as_lid = gconf_value_get_bool(gcv); + + if( prev != setting_ps_acts_as_lid ) { + /* Transfer exposed value to current target datapipe + * and clear the previous target datapipe. */ + if( setting_ps_acts_as_lid ) { + /* ps is lid now */ + cover_state_t curr = datapipe_get_gint(proximity_sensor_actual_pipe); + mp_datapipe_set_proximity_sensor_actual(COVER_OPEN); + mp_datapipe_set_lid_sensor_actual(curr); + } + else { + /* ps is ps again */ + cover_state_t curr = datapipe_get_gint(lid_sensor_actual_pipe); + mp_datapipe_set_lid_sensor_actual(COVER_UNDEF); + mp_datapipe_set_proximity_sensor_actual(curr); + } } } else { mce_log(LL_WARN, "Spurious GConf value received; confused!"); - goto EXIT; } - - mp_monitor_rethink(); EXIT: return; } @@ -340,17 +474,24 @@ mp_setting_init(void) { /* PS enabled setting */ mce_setting_track_bool(MCE_SETTING_PROXIMITY_PS_ENABLED, - &use_ps, + &setting_use_ps, MCE_DEFAULT_PROXIMITY_PS_ENABLED, mp_setting_cb, - &use_ps_conf_id); + &setting_use_ps_conf_id); + + /* on-demand setting */ + mce_setting_track_bool(MCE_SETTING_PROXIMITY_ON_DEMAND, + &setting_on_demand_ps, + MCE_DEFAULT_PROXIMITY_ON_DEMAND, + mp_setting_cb, + &setting_on_demand_ps_conf_id); /* PS acts as LID sensor */ mce_setting_track_bool(MCE_SETTING_PROXIMITY_PS_ACTS_AS_LID, - &ps_acts_as_lid, + &setting_ps_acts_as_lid, MCE_DEFAULT_PROXIMITY_PS_ACTS_AS_LID, mp_setting_cb, - &ps_acts_as_lid_conf_id); + &setting_ps_acts_as_lid_conf_id); } /** Stop tracking dynamic settings @@ -358,17 +499,61 @@ mp_setting_init(void) static void mp_setting_quit(void) { - mce_setting_notifier_remove(use_ps_conf_id), - use_ps_conf_id = 0; + mce_setting_notifier_remove(setting_use_ps_conf_id), + setting_use_ps_conf_id = 0; - mce_setting_notifier_remove(ps_acts_as_lid_conf_id), - ps_acts_as_lid_conf_id = 0; + mce_setting_notifier_remove(setting_use_ps_conf_id), + setting_on_demand_ps_conf_id = 0; + + mce_setting_notifier_remove(setting_ps_acts_as_lid_conf_id), + setting_ps_acts_as_lid_conf_id = 0; } /* ========================================================================= * * MP_DATAPIPE * ========================================================================= */ +/** Broadcast proximity sensor state within MCE + * + * @param state COVER_CLOSED or COVER_OPEN + */ +static void +mp_datapipe_set_proximity_sensor_actual(cover_state_t state) +{ + /* Get current proximity datapipe value */ + cover_state_t curr = datapipe_get_gint(proximity_sensor_actual_pipe); + + /* Execute datapipe if state has changed */ + + if( curr != state ) { + mce_log(LL_CRUCIAL, "state: %s -> %s", + cover_state_repr(curr), + cover_state_repr(state)); + + datapipe_exec_full(&proximity_sensor_actual_pipe, + GINT_TO_POINTER(state)); + } +} + +/** Broadcast faked lid sensor state within mce + * + * @param state COVER_CLOSED, COVER_OPEN or COVER_UNDEF + */ +static void +mp_datapipe_set_lid_sensor_actual(cover_state_t state) +{ + cover_state_t curr = datapipe_get_gint(lid_sensor_actual_pipe); + + if( state != curr ) { + mce_log(LL_CRUCIAL, "state: %s -> %s", + cover_state_repr(curr), + cover_state_repr(state)); + + datapipe_exec_full(&lid_sensor_actual_pipe, + GINT_TO_POINTER(state)); + } +} + /** Handle call state change * * @param data The call state stored in a pointer @@ -376,9 +561,20 @@ mp_setting_quit(void) static void mp_datapipe_call_state_cb(gconstpointer const data) { + call_state_t prev = call_state; call_state = GPOINTER_TO_INT(data); + if( prev == call_state ) + goto EXIT; + + mce_log(LL_DEBUG, "call_state: %s -> %s", + call_state_repr(prev), + call_state_repr(call_state)); + mp_monitor_rethink(); + +EXIT: + return; } /** Handle alarm ui state change @@ -388,9 +584,43 @@ mp_datapipe_call_state_cb(gconstpointer const data) static void mp_datapipe_alarm_ui_state_cb(gconstpointer const data) { + alarm_ui_state_t prev = alarm_ui_state; alarm_ui_state = GPOINTER_TO_INT(data); + if( prev == alarm_ui_state ) + goto EXIT; + + mce_log(LL_DEBUG, "alarm_ui_state: %s -> %s", + alarm_state_repr(prev), + alarm_state_repr(alarm_ui_state)); + mp_monitor_rethink(); + +EXIT: + return; +} + +/** Handle display state change + * + * @param data The display state stored in a pointer + */ +static void +mp_datapipe_display_state_next_cb(gconstpointer data) +{ + display_state_t prev = display_state_next; + display_state_next = GPOINTER_TO_INT(data); + + if( prev == display_state_next ) + goto EXIT; + + mce_log(LL_DEBUG, "display_state_next: %s -> %s", + display_state_repr(prev), + display_state_repr(display_state_next)); + + mp_monitor_rethink(); + +EXIT: + return; } /** Handle display state change @@ -400,9 +630,20 @@ mp_datapipe_alarm_ui_state_cb(gconstpointer const data) static void mp_datapipe_display_state_curr_cb(gconstpointer data) { + display_state_t prev = display_state_curr; display_state_curr = GPOINTER_TO_INT(data); + if( prev == display_state_curr ) + goto EXIT; + + mce_log(LL_DEBUG, "display_state_curr: %s -> %s", + display_state_repr(prev), + display_state_repr(display_state_curr)); + mp_monitor_rethink(); + +EXIT: + return; } /** Handle submode change @@ -412,14 +653,91 @@ mp_datapipe_display_state_curr_cb(gconstpointer data) static void mp_datapipe_submode_cb(gconstpointer data) { + submode_t prev = submode; submode = GPOINTER_TO_INT(data); + if( prev == submode ) + goto EXIT; + + mce_log(LL_DEBUG, "submode: %s", + submode_change_repr(prev, submode)); + +EXIT: + return; +} + +/** Change notifications for uiexception_type + */ +static void mp_datapipe_uiexception_type_cb(gconstpointer data) +{ + uiexception_type_t prev = uiexception_type; + uiexception_type = GPOINTER_TO_INT(data); + + if( uiexception_type == prev ) + goto EXIT; + + mce_log(LL_DEBUG, "uiexception_type = %s -> %s", + uiexception_type_repr(prev), + uiexception_type_repr(uiexception_type)); + + mp_monitor_rethink(); + +EXIT: + return; +} + +/** Input notifications for proximity_sensor_required_pipe + */ +static void mp_datapipe_proximity_sensor_required_cb(gconstpointer data) +{ + /* Assumption: The tags are statically allocated const strings */ + const char *tag = data; + + if( !tag ) + goto EXIT; + + mce_log(LL_DEBUG, "proximity_sensor_required: %s", tag); + + if( !mp_datapipe_proximity_sensor_required_lut ) + goto EXIT; + + switch( *tag++ ){ + case '+': + g_hash_table_add(mp_datapipe_proximity_sensor_required_lut, + (gpointer)tag); + break; + case '-': + g_hash_table_remove(mp_datapipe_proximity_sensor_required_lut, + (gpointer)tag); + break; + default: + goto EXIT; + } + + bool prev = proximity_sensor_required; + proximity_sensor_required = + g_hash_table_size(mp_datapipe_proximity_sensor_required_lut) != 0; + + if( prev == proximity_sensor_required ) + goto EXIT; + + mce_log(LL_DEBUG, "proximity_sensor_required: %d -> %d", + prev, proximity_sensor_required); + mp_monitor_rethink(); + +EXIT: + return; } /** Array of datapipe handlers */ static datapipe_handler_t mp_datapipe_handlers[] = { + // input triggers + { + .datapipe = &proximity_sensor_required_pipe, + .input_cb = mp_datapipe_proximity_sensor_required_cb, + }, // output triggers { .datapipe = &call_state_pipe, @@ -429,6 +747,10 @@ static datapipe_handler_t mp_datapipe_handlers[] = .datapipe = &alarm_ui_state_pipe, .output_cb = mp_datapipe_alarm_ui_state_cb, }, + { + .datapipe = &display_state_next_pipe, + .output_cb = mp_datapipe_display_state_next_cb, + }, { .datapipe = &display_state_curr_pipe, .output_cb = mp_datapipe_display_state_curr_cb, @@ -437,6 +759,10 @@ static datapipe_handler_t mp_datapipe_handlers[] = .datapipe = &submode_pipe, .output_cb = mp_datapipe_submode_cb, }, + { + .datapipe = &uiexception_type_pipe, + .output_cb = mp_datapipe_uiexception_type_cb, + }, // sentinel { .datapipe = 0, @@ -454,6 +780,12 @@ static datapipe_bindings_t mp_datapipe_bindings = static void mp_datapipe_init(void) { + if( !mp_datapipe_proximity_sensor_required_lut ) { + /* Assumption: Set of statically allocated const strings */ + mp_datapipe_proximity_sensor_required_lut = + g_hash_table_new(g_str_hash, g_str_equal); + } + mce_datapipe_init_bindings(&mp_datapipe_bindings); } @@ -462,6 +794,11 @@ mp_datapipe_init(void) static void mp_datapipe_quit(void) { + if( mp_datapipe_proximity_sensor_required_lut ) { + g_hash_table_unref(mp_datapipe_proximity_sensor_required_lut), + mp_datapipe_proximity_sensor_required_lut = 0; + } + mce_datapipe_quit_bindings(&mp_datapipe_bindings); } @@ -488,9 +825,9 @@ g_module_check_init(GModule *module) /* If the proximity sensor input is used for toggling * lid state, we must take care not to leave proximity - * tracking to covered state. */ - if( ps_acts_as_lid ) - mp_report_proximity_state(COVER_OPEN); + * tracking to covered/unknown state. */ + if( setting_ps_acts_as_lid ) + mp_datapipe_set_proximity_sensor_actual(COVER_OPEN); /* enable/disable sensor based on initial conditions */ mp_monitor_rethink(); @@ -515,6 +852,6 @@ g_module_unload(GModule *module) /* Disable proximity monitoring to remove callbacks * to unloaded module */ - mp_monitor_disable(); + mp_monitor_set_enabled(false); return; } diff --git a/modules/proximity.h b/modules/proximity.h index 0b83210a..40517ce7 100644 --- a/modules/proximity.h +++ b/modules/proximity.h @@ -3,9 +3,13 @@ * Headers for the proximity sensor module *

* Copyright © 2010-2011 Nokia Corporation and/or its subsidiary(-ies). + * Copyright (C) 2013-2019 Jolla Ltd. *

* @author David Weinehall * @author Tuomo Tanskanen + * @author Tapio Rantala + * @author Santtu Lakkala + * @author Simo Piiroinen * * mce is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License @@ -29,6 +33,10 @@ # define MCE_SETTING_PROXIMITY_PS_ENABLED MCE_SETTING_PROXIMITY_PATH "/ps_enabled" # define MCE_DEFAULT_PROXIMITY_PS_ENABLED true +/** Whether proximity sensor should be used on-demand*/ +# define MCE_SETTING_PROXIMITY_ON_DEMAND MCE_SETTING_PROXIMITY_PATH "/on_demand" +# define MCE_DEFAULT_PROXIMITY_ON_DEMAND false + /** Whether proximity sensor should be treated as cover closed sensor */ # define MCE_SETTING_PROXIMITY_PS_ACTS_AS_LID MCE_SETTING_PROXIMITY_PATH "/ps_acts_as_lid" # define MCE_DEFAULT_PROXIMITY_PS_ACTS_AS_LID false diff --git a/tklock.c b/tklock.c index 91ab0b28..cc7ee1d6 100644 --- a/tklock.c +++ b/tklock.c @@ -4,9 +4,19 @@ * of the Mode Control Entity *

* Copyright © 2004-2011 Nokia Corporation and/or its subsidiary(-ies). + * Copyright (C) 2012-2019 Jolla Ltd. *

* @author David Weinehall + * @author Tapio Rantala + * @author Santtu Lakkala + * @author Jukka Turunen + * @author Irina Bezruk + * @author Kalle Jokiniemi + * @author Mika Laitio + * @author Markus Lehtonen * @author Simo Piiroinen + * @author Vesa Halttunen + * @author Andrew den Exter * * mce is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License @@ -1083,6 +1093,9 @@ static void tklock_datapipe_proximity_update(void) proximity_sensor_effective = proximity_sensor_actual; + datapipe_exec_full(&proximity_sensor_effective_pipe, + GINT_TO_POINTER(proximity_sensor_effective)); + tklock_datapipe_proximity_eval_led(); tklock_uiexception_rethink(); tklock_proxlock_rethink(); diff --git a/tools/mcetool.c b/tools/mcetool.c index c823119a..76b90ad2 100644 --- a/tools/mcetool.c +++ b/tools/mcetool.c @@ -2,8 +2,15 @@ * Tool to test and remote control the Mode Control Entity *

* Copyright © 2005-2011 Nokia Corporation and/or its subsidiary(-ies). + * Copyright (C) 2012-2019 Jolla Ltd. *

* @author David Weinehall + * @author Santtu Lakkala + * @author Victor Portnov + * @author Philippe De Swert + * @author Simo Piiroinen + * @author Vesa Halttunen + * @author Kimmo Lindholm * * mce is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License @@ -225,6 +232,8 @@ static bool xmce_set_flipover_gesture_detection (const ch static void xmce_get_flipover_gesture_detection (void); static bool xmce_set_ps_mode (const char *args); static void xmce_get_ps_mode (void); +static bool xmce_set_ps_on_demand (const char *args); +static void xmce_get_ps_on_demand (void); static bool xmce_set_ps_blocks_touch (const char *args); static void xmce_get_ps_blocks_touch (void); static bool xmce_set_ps_acts_as_lid (const char *args); @@ -4082,6 +4091,30 @@ static void xmce_get_ps_mode(void) printf("%-"PAD1"s %s\n", "Use ps mode:", txt); } +/* Set ps use mode + * + * @param args string suitable for interpreting as enabled/disabled + */ +static bool xmce_set_ps_on_demand(const char *args) +{ + debugf("%s(%s)\n", __FUNCTION__, args); + gboolean val = xmce_parse_enabled(args); + xmce_setting_set_bool(MCE_SETTING_PROXIMITY_ON_DEMAND, val); + return true; +} + +/** Get current ps mode from mce and print it out + */ +static void xmce_get_ps_on_demand(void) +{ + gboolean val = 0; + char txt[32] = "unknown"; + + if( xmce_setting_get_bool(MCE_SETTING_PROXIMITY_ON_DEMAND, &val) ) + snprintf(txt, sizeof txt, "%s", val ? "enabled" : "disabled"); + printf("%-"PAD1"s %s\n", "Use ps on-demand:", txt); +} + /** Set ps can block touch input mode * * @param args string suitable for interpreting as enabled/disabled @@ -6362,6 +6395,7 @@ static bool xmce_get_status(const char *args) xmce_get_orientation_change_is_activity(); xmce_get_flipover_gesture_detection(); xmce_get_ps_mode(); + xmce_get_ps_on_demand(); xmce_get_ps_uncover_delay(); xmce_get_ps_blocks_touch(); xmce_get_ps_acts_as_lid(); @@ -7219,7 +7253,17 @@ static const mce_opt_t options[] = .with_arg = xmce_set_ps_mode, .values = "enabled|disabled", "set the ps mode; valid modes are:\n" - "'enabled' and 'disabled'\n" + "'enabled' sensor is disabled/enabled based on policy\n" + " and other settings\n" + "'disabled' sensor is never powered on by mce\n" + }, + { + .name = "set-ps-on-demand", + .with_arg = xmce_set_ps_on_demand, + .values = "enabled|disabled", + "set the ps on-demand mode; valid modes are:\n" + "'enabled' sensor is powered up only when needed\n" + "'disabled' sensor is always kept powered on\n" }, { .name = "set-default-ps-uncover-delay",