Skip to content

Commit

Permalink
Assume lid sensor is broken until it has been switch to open position
Browse files Browse the repository at this point in the history
Broken sensor hw / kernel drivers can make available lid sensors that
are permanently locked to closed position.

Ignore lid closed events until the sensor has been observed to flip
into open position.

Add lid_sensor_is_working_pipe datapipe for tracking this state and
use a flag file to keep the status over mce / device restarts.

Initialize lid sensor & policy datapipes to undefined state instead
of open state, but logically treat undefined and open as equals.

Replace old code that unconditionally forced lid sensor state to open
position with evdev check that retrieves actual sensor state if it is
available.

[mce] Assume lid sensor is broken until it has been switch to open position. Contributes to JB#29011
  • Loading branch information
spiiroin committed Jun 11, 2015
1 parent 9c86840 commit 4b8d964
Show file tree
Hide file tree
Showing 6 changed files with 138 additions and 40 deletions.
10 changes: 8 additions & 2 deletions datapipe.c
Expand Up @@ -88,6 +88,9 @@ datapipe_struct keyboard_slide_pipe;
/** Keyboard available; read only */
datapipe_struct keyboard_available_pipe;

/** Lid sensor is working state; read/write */
datapipe_struct lid_sensor_is_working_pipe;

/** Lid cover sensor open/closed; read only */
datapipe_struct lid_cover_sensor_pipe;

Expand Down Expand Up @@ -846,10 +849,12 @@ void mce_datapipe_init(void)
0, GINT_TO_POINTER(COVER_CLOSED));
setup_datapipe(&keyboard_available_pipe, READ_ONLY, DONT_FREE_CACHE,
0, GINT_TO_POINTER(COVER_CLOSED));
setup_datapipe(&lid_sensor_is_working_pipe, READ_WRITE,
DONT_FREE_CACHE, 0, GINT_TO_POINTER(FALSE));
setup_datapipe(&lid_cover_sensor_pipe, READ_ONLY, DONT_FREE_CACHE,
0, GINT_TO_POINTER(COVER_OPEN));
0, GINT_TO_POINTER(COVER_UNDEF));
setup_datapipe(&lid_cover_policy_pipe, READ_ONLY, DONT_FREE_CACHE,
0, GINT_TO_POINTER(COVER_OPEN));
0, GINT_TO_POINTER(COVER_UNDEF));
setup_datapipe(&lens_cover_pipe, READ_ONLY, DONT_FREE_CACHE,
0, GINT_TO_POINTER(0));
setup_datapipe(&proximity_sensor_pipe, READ_ONLY, DONT_FREE_CACHE,
Expand Down Expand Up @@ -937,6 +942,7 @@ void mce_datapipe_quit(void)
free_datapipe(&ambient_light_level_pipe);
free_datapipe(&orientation_sensor_pipe);
free_datapipe(&lens_cover_pipe);
free_datapipe(&lid_sensor_is_working_pipe);
free_datapipe(&lid_cover_sensor_pipe);
free_datapipe(&lid_cover_policy_pipe);
free_datapipe(&keyboard_slide_pipe);
Expand Down
1 change: 1 addition & 0 deletions datapipe.h
Expand Up @@ -108,6 +108,7 @@ extern datapipe_struct touchscreen_pipe;
extern datapipe_struct lockkey_pipe;
extern datapipe_struct keyboard_slide_pipe;
extern datapipe_struct keyboard_available_pipe;
extern datapipe_struct lid_sensor_is_working_pipe;
extern datapipe_struct lid_cover_sensor_pipe;
extern datapipe_struct lid_cover_policy_pipe;
extern datapipe_struct lens_cover_pipe;
Expand Down
8 changes: 8 additions & 0 deletions event-input.c
Expand Up @@ -2388,6 +2388,14 @@ evin_iomon_switch_states_update_iter_cb(gpointer io_monitor, gpointer user_data)
USE_INDATA, CACHE_INDATA);
}

/* Check initial lid sensor state */
ecode = evin_event_mapper_rlookup_switch(SW_LID);
if( test_bit(ecode, featurelist) ) {
state = test_bit(ecode, statelist) ? COVER_CLOSED : COVER_OPEN;
execute_datapipe(&lid_cover_sensor_pipe, GINT_TO_POINTER(state),
USE_INDATA, CACHE_INDATA);
}

/* Need to consider more than one switch state when setting the
* initial value of the jack_sense_pipe */

Expand Down
5 changes: 0 additions & 5 deletions event-switches.c
Expand Up @@ -474,11 +474,6 @@ gboolean mce_switches_init(void)
append_output_trigger_to_datapipe(&submode_pipe,
submode_trigger);

/* Set default values, in case these are not available */
(void)execute_datapipe(&lid_cover_sensor_pipe,
GINT_TO_POINTER(COVER_OPEN),
USE_INDATA, CACHE_INDATA);

/* Register I/O monitors */
lockkey_iomon_id =
mce_switches_add_iomon(MCE_FLICKER_KEY_STATE_PATH,
Expand Down
9 changes: 3 additions & 6 deletions modules/display.c
Expand Up @@ -1135,9 +1135,9 @@ static void mdy_datapipe_submode_cb(gconstpointer data)
return;
}

/** Cache Lid cover policy state; assume open
/** Cache Lid cover policy state; assume unknown
*/
static cover_state_t lid_cover_policy_state = COVER_OPEN;
static cover_state_t lid_cover_policy_state = COVER_UNDEF;

/** Change notifications from lid_cover_policy_pipe
*/
Expand All @@ -1146,9 +1146,6 @@ static void tklock_datapipe_mdy_datapipe_lid_cover_policy_cb(gconstpointer data)
cover_state_t prev = lid_cover_policy_state;
lid_cover_policy_state = GPOINTER_TO_INT(data);

if( lid_cover_policy_state == COVER_UNDEF )
lid_cover_policy_state = COVER_OPEN;

if( lid_cover_policy_state == prev )
goto EXIT;

Expand Down Expand Up @@ -4021,7 +4018,7 @@ static void mdy_blanking_rethink_proximity(void)

case MCE_DISPLAY_LPM_OFF:
if( proximity_state == COVER_OPEN &&
lid_cover_policy_state == COVER_OPEN )
lid_cover_policy_state != COVER_CLOSED )
execute_datapipe(&display_state_req_pipe,
GINT_TO_POINTER(MCE_DISPLAY_LPM_ON),
USE_INDATA, CACHE_INDATA);
Expand Down
145 changes: 118 additions & 27 deletions tklock.c
Expand Up @@ -43,8 +43,13 @@

#include <linux/input.h>

#include <sys/types.h>
#include <sys/stat.h>

#include <unistd.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>

#include <mce/dbus-names.h>
#include <mce/mode-names.h>
Expand Down Expand Up @@ -171,6 +176,7 @@ static void tklock_datapipe_keyboard_slide_input_cb(gconstpointer const data
static void tklock_datapipe_keyboard_slide_output_cb(gconstpointer const data);
static void tklock_datapipe_keyboard_available_cb(gconstpointer const data);
static void tklock_datapipe_ambient_light_sensor_cb(gconstpointer data);
static void tklock_datapipe_lid_sensor_is_working_cb(gconstpointer data);
static void tklock_datapipe_lid_cover_sensor_cb(gconstpointer data);
static void tklock_datapipe_lid_cover_policy_cb(gconstpointer data);
static void tklock_datapipe_lens_cover_cb(gconstpointer data);
Expand All @@ -184,6 +190,7 @@ static void tklock_datapipe_quit(void);

// lid cover state machine

static void tklock_lid_sensor_init(void);
static void tklock_lid_sensor_rethink(void);

// keyboard slide state machine
Expand Down Expand Up @@ -818,8 +825,20 @@ static cover_state_t proximity_state_actual = COVER_OPEN;
/** Effective proximity state; assume not covered */
static cover_state_t proximity_state_effective = COVER_OPEN;

/** Lid cover policy state; assume open */
static cover_state_t lid_cover_policy_state = COVER_OPEN;
/** Lid cover sensor state; assume unkown
*
* When in covered state, it is assumed that it is not physically
* possible to see/interact with the display and thus it should
* stay powered off.
*
* Originally was used to track Nokia N770 slidable cover. Now
* it is used also for things like the hammerhead magnetic lid
* sensor.
*/
static cover_state_t lid_cover_sensor_state = COVER_UNDEF;

/** Lid cover policy state; assume unknown */
static cover_state_t lid_cover_policy_state = COVER_UNDEF;

/** Timer id for delayed proximity uncovering */
static guint tklock_datapipe_proximity_uncover_id = 0;
Expand Down Expand Up @@ -1659,18 +1678,6 @@ static void tklock_datapipe_ambient_light_sensor_cb(gconstpointer data)
return;
}

/** Lid cover sensor state; assume open
*
* When in covered state, it is assumed that it is not physically
* possible to see/interact with the display and thus it should
* stay powered off.
*
* Originally was used to track Nokia N770 slidable cover. Now
* it is used also for things like the hammerhead magnetic lid
* sensor.
*/
static cover_state_t lid_cover_sensor_state = COVER_OPEN;

/** ALS lux limit for allowing lid close actions [lux] */
static gint lid_cover_close_als_limit = 1;

Expand All @@ -1683,19 +1690,69 @@ static gint lid_cover_close_hi_als_delay = 2500;
/** Timeout for waiting for ALS level drop [ms, CLOCK_BOOTTIME base] */
static int64_t lid_cover_close_timeout = 0;

/** Assume lid sensor is broken until we have seen lid=open event */
static bool tklock_lid_sensor_is_working = false;

/** Path to the flag file for persistent tklock_lid_sensor_is_working */
#define LID_SENSOR_IS_WORKING_FLAG_FILE "/var/lib/mce/lid_sensor_is_working"

/** Keep flag file in sync with lid_sensor_is_working_pipe status
*/
static void tklock_datapipe_lid_sensor_is_working_cb(gconstpointer data)
{
bool prev = tklock_lid_sensor_is_working;
tklock_lid_sensor_is_working = GPOINTER_TO_INT(data);

if( tklock_lid_sensor_is_working == prev )
goto EXIT;

mce_log(LL_DEVEL, "lid_sensor_is_working = %s -> %s",
prev ? "true" : "false",
tklock_lid_sensor_is_working ? "true" : "false");

if( tklock_lid_sensor_is_working ) {
/* Create flag file */
int fd = open(LID_SENSOR_IS_WORKING_FLAG_FILE, O_WRONLY|O_CREAT, 0644);
if( fd == -1 )
mce_log(LL_WARN, "%s: could not create flag file: %m",
LID_SENSOR_IS_WORKING_FLAG_FILE);
else
close(fd);
}
else {
/* Remove flag file */
if( unlink(LID_SENSOR_IS_WORKING_FLAG_FILE) == -1 && errno != ENOENT )
mce_log(LL_WARN, "%s: could not remove flag file: %m",
LID_SENSOR_IS_WORKING_FLAG_FILE);

/* Invalidate sensor data */
execute_datapipe(&lid_cover_sensor_pipe,
GINT_TO_POINTER(COVER_UNDEF),
USE_INDATA, CACHE_INDATA);
}

EXIT:
return;
}

/** Change notifications from lid_cover_sensor_pipe
*/
static void tklock_datapipe_lid_cover_sensor_cb(gconstpointer data)
{
cover_state_t prev = lid_cover_sensor_state;
lid_cover_sensor_state = GPOINTER_TO_INT(data);

if( lid_cover_sensor_state == COVER_UNDEF )
lid_cover_sensor_state = COVER_OPEN;

if( lid_cover_sensor_state == prev )
goto EXIT;

if( lid_cover_sensor_state == COVER_OPEN ) {
/* We have seen the sensor flip to open position, so we can
* stop assuming it stays forever in the closed position */
execute_datapipe(&lid_sensor_is_working_pipe,
GINT_TO_POINTER(true),
USE_INDATA, CACHE_INDATA);
}

mce_log(LL_DEBUG, "lid_cover_sensor_state = %s -> %s",
cover_state_repr(prev),
cover_state_repr(lid_cover_sensor_state));
Expand All @@ -1719,9 +1776,6 @@ static void tklock_datapipe_lid_cover_policy_cb(gconstpointer data)
cover_state_t prev = lid_cover_policy_state;
lid_cover_policy_state = GPOINTER_TO_INT(data);

if( lid_cover_policy_state == COVER_UNDEF )
lid_cover_policy_state = COVER_OPEN;

if( lid_cover_policy_state == prev )
goto EXIT;

Expand Down Expand Up @@ -1970,6 +2024,10 @@ static datapipe_handler_t tklock_datapipe_handlers[] =
.datapipe = &ambient_light_sensor_pipe,
.output_cb = tklock_datapipe_ambient_light_sensor_cb,
},
{
.datapipe = &lid_sensor_is_working_pipe,
.output_cb = tklock_datapipe_lid_sensor_is_working_cb,
},
{
.datapipe = &lid_cover_sensor_pipe,
.output_cb = tklock_datapipe_lid_cover_sensor_cb,
Expand Down Expand Up @@ -2182,6 +2240,21 @@ static void tklock_autolock_on_devlock_trigger(void)
*
* ========================================================================= */

static void tklock_lid_sensor_init(void)
{
/* Initialize state based on flag file presense */
tklock_lid_sensor_is_working =
(access(LID_SENSOR_IS_WORKING_FLAG_FILE, F_OK) == 0);

mce_log(LL_DEVEL, "lid_sensor_is_working = %s",
tklock_lid_sensor_is_working ? "true" : "false");

/* Broadcast initial state */
execute_datapipe(&lid_sensor_is_working_pipe,
GINT_TO_POINTER(tklock_lid_sensor_is_working),
USE_INDATA, CACHE_INDATA);
}

static void tklock_lid_sensor_rethink(void)
{
static int64_t nonzero_lux_seen_at = 0;
Expand Down Expand Up @@ -2224,7 +2297,12 @@ static void tklock_lid_sensor_rethink(void)
* that might trigger the sensor from below the device when
* the cover is folded all the way underneath the device. */
if( action_curr == COVER_CLOSED ) {
if( display_state_next == MCE_DISPLAY_OFF ) {
if( !tklock_lid_sensor_is_working ) {
/* No blanking based on lid sensor that might not work */
mce_log(LL_DEVEL, "ignoring lid cover; not validated");
action_curr = COVER_UNDEF;
}
else if( display_state_next == MCE_DISPLAY_OFF ) {
/* Allow close while already blanked without
* paying attention to als level */
}
Expand All @@ -2249,8 +2327,6 @@ static void tklock_lid_sensor_rethink(void)
if( action_prev == action_curr )
goto EXIT;

action_prev = action_curr;

/* First make the policy decision known */
execute_datapipe(&lid_cover_policy_pipe,
GINT_TO_POINTER(action_curr),
Expand All @@ -2272,6 +2348,12 @@ static void tklock_lid_sensor_rethink(void)
break;

case COVER_OPEN:
/* No action on initial undef -> open */
if( action_prev == COVER_UNDEF ) {
mce_log(LL_DEVEL, "lid open - initial state ignored");
break;
}

mce_log(LL_DEVEL, "lid open - unblank");
/* unblank display */
execute_datapipe(&display_state_req_pipe,
Expand All @@ -2285,6 +2367,8 @@ static void tklock_lid_sensor_rethink(void)
break;
}

action_prev = action_curr;

EXIT:
return;
}
Expand All @@ -2309,7 +2393,7 @@ static void tklock_keyboard_slide_rethink(void)

if( !display_on &&
proximity_state_actual == COVER_OPEN &&
lid_cover_policy_state == COVER_OPEN ) {
lid_cover_policy_state != COVER_CLOSED ) {
mce_log(LL_DEBUG, "autorelock primed: on kbd slide close");
autorelock_trigger = AUTORELOCK_KBD_SLIDE;

Expand Down Expand Up @@ -2973,7 +3057,7 @@ static void tklock_uiexcept_finish(void)
* proximity_state_effective that is normally used
* with unblanking policies. */
if( proximity_state_actual != COVER_OPEN ||
lid_cover_policy_state != COVER_OPEN )
lid_cover_policy_state == COVER_CLOSED )
break;

execute_datapipe(&display_state_req_pipe,
Expand Down Expand Up @@ -3301,7 +3385,7 @@ static void tklock_lpmui_rethink(void)
goto EXIT;

/* when lid is closed */
if( lid_cover_policy_state != COVER_OPEN )
if( lid_cover_policy_state == COVER_CLOSED )
goto EXIT;

/* or when proximity is covered */
Expand Down Expand Up @@ -3689,7 +3773,7 @@ static void tklock_evctrl_rethink(void)
if( grab_ts ||
( (proximity_state_effective == COVER_OPEN ||
!proximity_blocks_touch) &&
(lid_cover_policy_state == COVER_OPEN) ) ) {
(lid_cover_policy_state != COVER_CLOSED) ) ) {
execute_datapipe(&touch_grab_wanted_pipe,
GINT_TO_POINTER(grab_ts),
USE_INDATA, CACHE_INDATA);
Expand Down Expand Up @@ -5647,6 +5731,10 @@ gboolean mce_tklock_init(void)

tklock_autolock_init();

/* Set initial lid_sensor_is_working_pipe value
* before installing datapipe handlers */
tklock_lid_sensor_init();

/* attach to internal state variables */
tklock_datapipe_init();

Expand All @@ -5656,6 +5744,9 @@ gboolean mce_tklock_init(void)
/* Make sure lpm state gets initialized & broadcast */
tklock_lpmui_set_state(false);

/* Evaluate initial lid sensor state */
tklock_lid_sensor_rethink();

status = TRUE;

return status;
Expand Down

0 comments on commit 4b8d964

Please sign in to comment.