Skip to content

Commit

Permalink
Merge pull request #4 from spiiroin/jb55731_mouse_availability
Browse files Browse the repository at this point in the history
Mouse availability signaling and YubiKey configuration
  • Loading branch information
spiiroin authored Oct 25, 2021
2 parents d32103d + 7df8a02 commit d7a5172
Show file tree
Hide file tree
Showing 12 changed files with 524 additions and 25 deletions.
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -491,6 +491,7 @@ install:: build
$(INSTALL_DTA) inifiles/hybris-features.ini $(DESTDIR)$(CONFDIR)/20hybris-features.ini
$(INSTALL_DTA) inifiles/debug-led.ini $(DESTDIR)$(CONFDIR)/20debug-led.ini
$(INSTALL_DTA) inifiles/als-defaults.ini $(DESTDIR)$(CONFDIR)/20als-defaults.ini
$(INSTALL_DTA) inifiles/evdev-types.ini $(DESTDIR)$(CONFDIR)/20evdev-types.ini
$(INSTALL_DTA) inifiles/legacy.ini $(DESTDIR)$(CONFDIR)/11legacy.ini

ifeq ($(ENABLE_SYSTEMD_SUPPORT),y)
Expand Down
4 changes: 4 additions & 0 deletions datapipe.c
Original file line number Diff line number Diff line change
Expand Up @@ -657,6 +657,9 @@ datapipe_t keyboard_slide_state_pipe = DATAPIPE_INIT(keyboard_slide_s
/** Keyboard available; read only */
datapipe_t keyboard_available_state_pipe = DATAPIPE_INIT(keyboard_available_state, cover_state, COVER_CLOSED, 0, DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_DEFAULT);

/** Mouse available; read only */
datapipe_t mouse_available_state_pipe = DATAPIPE_INIT(mouse_available_state, cover_state, COVER_UNDEF, 0, DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_DEFAULT);

/** Lid sensor is working state; read/write */
datapipe_t lid_sensor_is_working_pipe = DATAPIPE_INIT(lid_sensor_is_working, boolean, false, 0, DATAPIPE_FILTERING_DENIED, DATAPIPE_CACHE_DEFAULT);

Expand Down Expand Up @@ -1353,6 +1356,7 @@ void mce_datapipe_quit(void)
datapipe_free(&lid_sensor_filtered_pipe);
datapipe_free(&keyboard_slide_state_pipe);
datapipe_free(&keyboard_available_state_pipe);
datapipe_free(&mouse_available_state_pipe);
datapipe_free(&lockkey_state_pipe);
datapipe_free(&init_done_pipe);
datapipe_free(&device_inactive_pipe);
Expand Down
6 changes: 4 additions & 2 deletions datapipe.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
# define _DATAPIPE_H_

# include <stdbool.h>
# include <stdint.h>
# include <glib.h>

/* ========================================================================= *
Expand Down Expand Up @@ -149,10 +150,10 @@ void mce_datapipe_generate_inactivity (void);
* ========================================================================= */

/** Retrieve a gint from a datapipe */
# define datapipe_get_gint(_datapipe) ((gint)(void*)datapipe_value(&(_datapipe)))
# define datapipe_get_gint(_datapipe) ((gint)(intptr_t)(void*)datapipe_value(&(_datapipe)))

/** Retrieve a guint from a datapipe */
# define datapipe_get_guint(_datapipe) ((guint)(void*)datapipe_value(&(_datapipe)))
# define datapipe_get_guint(_datapipe) ((guint)(uintptr_t)(void*)datapipe_value(&(_datapipe)))

/* Helper for making display state requests
*
Expand Down Expand Up @@ -233,6 +234,7 @@ extern datapipe_t lockkey_state_pipe;
extern datapipe_t init_done_pipe;
extern datapipe_t keyboard_slide_state_pipe;
extern datapipe_t keyboard_available_state_pipe;
extern datapipe_t mouse_available_state_pipe;
extern datapipe_t lid_sensor_is_working_pipe;
extern datapipe_t lid_sensor_actual_pipe;
extern datapipe_t lid_sensor_filtered_pipe;
Expand Down
155 changes: 138 additions & 17 deletions event-input.c
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,9 @@ typedef enum {
/** Touch screen to be tracked and processed */
EVDEV_TOUCH,

/** Mouse to be tracked and processed */
EVDEV_MOUSE,

/** Keys etc that mce needs to track and process */
EVDEV_INPUT,

Expand Down Expand Up @@ -319,6 +322,9 @@ static void evin_iomon_switch_states_update (void);
static void evin_iomon_keyboard_state_update_iter_cb (gpointer io_monitor, gpointer user_data);
static void evin_iomon_keyboard_state_update (void);

static void evin_iomon_mouse_state_update_iter_cb (gpointer io_monitor, gpointer user_data);
static void evin_iomon_mouse_state_update (void);

// start/stop io monitoring

static bool evin_iomon_init (void);
Expand Down Expand Up @@ -1392,6 +1398,7 @@ evin_evdevtype_repr(evin_evdevtype_t type)
{
[EVDEV_REJECT] = "REJECT",
[EVDEV_TOUCH] = "TOUCHSCREEN",
[EVDEV_MOUSE] = "MOUSE",
[EVDEV_INPUT] = "KEY, BUTTON or SWITCH",
[EVDEV_ACTIVITY] = "USER ACTIVITY ONLY",
[EVDEV_IGNORE] = "IGNORE",
Expand Down Expand Up @@ -1423,6 +1430,7 @@ evin_evdevtype_parse(const char *name)
{
{ "REJECT", EVDEV_REJECT, },
{ "TOUCH", EVDEV_TOUCH, },
{ "MOUSE", EVDEV_MOUSE, },
{ "INPUT", EVDEV_INPUT, },
{ "ACTIVITY", EVDEV_ACTIVITY, },
{ "IGNORE", EVDEV_IGNORE, },
Expand Down Expand Up @@ -1580,7 +1588,7 @@ evin_evdevtype_from_info(evin_evdevinfo_t *info)
evin_evdevinfo_has_code(info, EV_REL, REL_X) &&
evin_evdevinfo_has_code(info, EV_REL, REL_Y) ) {
// mouse
res = EVDEV_TOUCH;
res = EVDEV_MOUSE;
goto cleanup;
}

Expand Down Expand Up @@ -1828,9 +1836,11 @@ evin_iomon_extra_delete_cb(void *aptr)
static evin_iomon_extra_t *
evin_iomon_extra_create(int fd, const char *name)
{
evin_iomon_extra_t *self = calloc(1, sizeof *self);
gchar *type = 0;
char *key = 0;
evin_iomon_extra_t *self = calloc(1, sizeof *self);
gchar *config = 0;
char *key = 0;
char *id = 0;
struct input_id info = {};

/* Initialize extra info to sane defaults */
self->ex_name = strdup(name);
Expand All @@ -1841,33 +1851,87 @@ evin_iomon_extra_create(int fd, const char *name)

evin_evdevinfo_probe(self->ex_info, fd);

/* Check if evdev device type has been set in the configuration */
key = evio_sanitize_key_name(name);
type = mce_conf_get_string(MCE_CONF_EVDEV_TYPE_GROUP, key, 0);
if( type ) {
self->ex_type = evin_evdevtype_parse(type);
if( self->ex_type == EVDEV_UNKNOWN )
mce_log(LL_WARN, "unknown evdev device type '%s'", type);
/* Check if evdev device type has been set in the configuration
*
* First lookup using bus-vendor-product based name,
* then as a fallback lookup using sanitized device name.
*/
if( ioctl(fd, EVIOCGID, &info) < 0 ) {
mce_log(LL_WARN, "EVIOCGID: N/A (%m)");
}
else {
id = g_strdup_printf("b%04xv%04xp%04x",
info.bustype,
info.vendor,
info.product);
}

if( id ) {
config = mce_conf_get_string(MCE_CONF_EVDEV_TYPE_GROUP, id, 0);
}

/* In case of missing / faulty configuration, use heuristics
* to determine the device type */
if( self->ex_type == EVDEV_UNKNOWN )
self->ex_type = evin_evdevtype_from_info(self->ex_info);
if( !config ) {
key = evio_sanitize_key_name(name);
config = mce_conf_get_string(MCE_CONF_EVDEV_TYPE_GROUP, key, 0);
}

/* Heuristics based type detection */
evin_evdevtype_t probed = evin_evdevtype_from_info(self->ex_info);

/* Override based on configuration */
if( config ) {
/* RULE := <TYPE_TO_USE>[':'<ON_PROBED_TYPE>[':'<RESERVED>]]
* RULES := <RULE>[';'<RULE>]...
*/
char *rules = config;
for( char *rule; *(rule = mce_slice_token(rules, &rules, ";")); ) {
const char *arg1 = mce_slice_token(rule, &rule, ":");
const char *arg2 = mce_slice_token(rule, &rule, ":");

evin_evdevtype_t configured = EVDEV_UNKNOWN;
evin_evdevtype_t replaces = EVDEV_UNKNOWN;

if( *arg1 ) {
if( (configured = evin_evdevtype_parse(arg1)) == EVDEV_UNKNOWN )
mce_log(LL_WARN, "unknown evdev device type '%s'", arg1);
}

if( *arg2 ) {
if( (replaces = evin_evdevtype_parse(arg2)) == EVDEV_UNKNOWN )
mce_log(LL_WARN, "unknown evdev device type '%s'", arg2);
}

if( replaces == EVDEV_UNKNOWN || replaces == probed ) {
/* Unconditional / condition matched
* -> use configured / keep probed type
*/
if( configured != EVDEV_UNKNOWN )
probed = configured;
break;
}
}
}

self->ex_type = probed;

/* Initialize type specific tracking data */

if( self->ex_type == EVDEV_KEYBOARD ) {
self->ex_sw_keypad_slide = mce_conf_get_string("SW_KEYPAD_SLIDE",
self->ex_name, 0);
}

if( self->ex_type == EVDEV_TOUCH ) {
if( self->ex_type == EVDEV_TOUCH ||
self->ex_type == EVDEV_MOUSE ||
self->ex_type == EVDEV_DBLTAP ) {
bool protocol_b = evin_evdevinfo_has_code(self->ex_info,
EV_ABS, ABS_MT_SLOT);
self->ex_mt_state = mt_state_create(protocol_b);
}

g_free(type);
g_free(config);
free(key);
g_free(id);

return self;
}
Expand Down Expand Up @@ -2449,6 +2513,7 @@ evin_iomon_device_add(const gchar *path)
/* Choose notification callback function based on device type */
switch( extra->ex_type ) {
case EVDEV_TOUCH:
case EVDEV_MOUSE:
notify = evin_iomon_touchscreen_cb;
break;

Expand Down Expand Up @@ -2544,6 +2609,7 @@ evin_iomon_device_update(const gchar *path, gboolean add)

evin_iomon_switch_states_update();
evin_iomon_keyboard_state_update();
evin_iomon_mouse_state_update();
}

/** Check whether the fd in question supports the switches
Expand Down Expand Up @@ -2755,6 +2821,52 @@ evin_iomon_keyboard_state_update(void)
GINT_TO_POINTER(state));
}

/** Iterator callback for evaluation availability of mouse input devices
*
* Note: The iteration is peforming a logical OR operation, so the
* result variable must be modified only to set it true.
*
* @param io_monitor io monitor as void pointer
* @param user_data pointer to bool available flag
*/
static void
evin_iomon_mouse_state_update_iter_cb(gpointer io_monitor, gpointer user_data)
{
(void)io_monitor;
bool *available = user_data;

/* As long as we are iterating devices of EVDEV_MOUSE
* type, it is enough that we got here */
*available = true;
return;
}

/** Check if at least one mouse device in usable state exists
*
* Iterate over monitored input devices to find mouses.
*
* Update mouse availablity state based on the scanning result.
*
* This function should be called when new devices are detected,
* or old ones disappear.
*/
static void
evin_iomon_mouse_state_update(void)
{
bool available = false;

evin_iomon_device_iterate(EVDEV_MOUSE,
evin_iomon_mouse_state_update_iter_cb,
&available);

mce_log(LL_DEBUG, "available = %s", available ? "true" : "false");

cover_state_t state = available ? COVER_OPEN : COVER_CLOSED;

datapipe_exec_full(&mouse_available_state_pipe,
GINT_TO_POINTER(state));
}

/** Scan /dev/input for input event devices
*
* @return TRUE on success, FALSE on failure
Expand Down Expand Up @@ -2979,6 +3091,10 @@ evin_touchstate_update_cb(gpointer aptr)
evin_touchstate_iomon_iter_cb,
&touching);

evin_iomon_device_iterate(EVDEV_MOUSE,
evin_touchstate_iomon_iter_cb,
&touching);

if( touching == touch_detected )
goto EXIT;

Expand Down Expand Up @@ -3361,6 +3477,10 @@ evin_ts_grab_set_active(gboolean grab)
evin_input_grab_iomon_cb,
GINT_TO_POINTER(grab));

evin_iomon_device_iterate(EVDEV_MOUSE,
evin_input_grab_iomon_cb,
GINT_TO_POINTER(grab));

// STATE MACHINE -> OUTPUT DATAPIPE
datapipe_exec_full(&touch_grab_active_pipe,
GINT_TO_POINTER(grab));
Expand Down Expand Up @@ -4212,6 +4332,7 @@ mce_input_init(void)

evin_iomon_switch_states_update();
evin_iomon_keyboard_state_update();
evin_iomon_mouse_state_update();

status = TRUE;
EXIT:
Expand Down
Loading

0 comments on commit d7a5172

Please sign in to comment.