From 605e6809b6e7f33153dedb3d6dfa7f7a9aa7c6a8 Mon Sep 17 00:00:00 2001
From: notaz <notasas@gmail.com>
Date: Mon, 21 Mar 2011 02:40:21 +0200
Subject: [PATCH] frontend: input: detect dead devices, always set keynames

---
 frontend/common/input.c   | 27 +++++++++++++++++++++------
 frontend/common/input.h   |  3 +++
 frontend/linux/in_evdev.c | 11 +++++++----
 3 files changed, 31 insertions(+), 10 deletions(-)

diff --git a/frontend/common/input.c b/frontend/common/input.c
index 75eba0ff..a91de8d3 100644
--- a/frontend/common/input.c
+++ b/frontend/common/input.c
@@ -41,7 +41,7 @@ typedef struct
 
 static in_drv_t in_drivers[IN_DRVID_COUNT];
 static in_dev_t in_devices[IN_MAX_DEVS];
-static int in_dev_count = 0;
+static int in_dev_count = 0;		/* probed + bind devices */
 static int in_have_async_devs = 0;
 static int menu_key_state = 0;
 static int menu_last_used_dev = 0;
@@ -64,12 +64,17 @@ static int *in_alloc_binds(int drv_id, int key_count)
 	return binds;
 }
 
-static void in_free(in_dev_t *dev)
+static void in_unprobe(in_dev_t *dev)
 {
 	if (dev->probed)
 		DRV(dev->drv_id).free(dev->drv_data);
 	dev->probed = 0;
 	dev->drv_data = NULL;
+}
+
+static void in_free(in_dev_t *dev)
+{
+	in_unprobe(dev);
 	free(dev->name);
 	dev->name = NULL;
 	free(dev->binds);
@@ -223,8 +228,11 @@ void in_probe(void)
 	int i;
 
 	in_have_async_devs = 0;
+	menu_key_state = 0;
+	menu_last_used_dev = 0;
+
 	for (i = 0; i < in_dev_count; i++)
-		in_devices[i].probed = 0;
+		in_unprobe(&in_devices[i]);
 
 	for (i = 1; i < IN_DRVID_COUNT; i++)
 		in_drivers[i].probe();
@@ -368,6 +376,12 @@ int in_update_keycode(int *dev_id_out, int *is_down_out, int timeout_ms)
 		if (result >= 0)
 			break;
 
+		if (result == -2) {
+			lprintf("input: \"%s\" errored out, removing.\n", in_devices[dev_id].name);
+			in_unprobe(&in_devices[dev_id]);
+			break;
+		}
+
 		if (timeout_ms >= 0) {
 			unsigned int ticks2 = plat_get_ticks_ms();
 			timeout_ms -= ticks2 - ticks;
@@ -755,7 +769,7 @@ int in_config_parse_dev(const char *name)
 	if (in_devices[i].name == NULL)
 		return -1;
 
-	in_devices[i].key_count = DRV(drv_id).get_bind_count();
+	in_devices[i].key_names = DRV(drv_id).get_key_names(&in_devices[i].key_count);
 	in_devices[i].drv_id = drv_id;
 
 	if (i + 1 > in_dev_count)
@@ -867,7 +881,8 @@ void in_debug_dump(void)
 
 static void in_def_probe(void) {}
 static void in_def_free(void *drv_data) {}
-static int  in_def_get_bind_count(void) { return 0; }
+static const char * const *
+            in_def_get_key_names(int *count) { return NULL; }
 static void in_def_get_def_binds(int *binds) {}
 static int  in_def_clean_binds(void *drv_data, int *b, int *db) { return 0; }
 static int  in_def_get_config(void *drv_data, int what, int *val) { return -1; }
@@ -889,7 +904,7 @@ void in_init(void)
 		in_drivers[i].prefix = "none:";
 		in_drivers[i].probe = in_def_probe;
 		in_drivers[i].free = in_def_free;
-		in_drivers[i].get_bind_count = in_def_get_bind_count;
+		in_drivers[i].get_key_names = in_def_get_key_names;
 		in_drivers[i].get_def_binds = in_def_get_def_binds;
 		in_drivers[i].clean_binds = in_def_clean_binds;
 		in_drivers[i].get_config = in_def_get_config;
diff --git a/frontend/common/input.h b/frontend/common/input.h
index bcafaa51..6ea14bd1 100644
--- a/frontend/common/input.h
+++ b/frontend/common/input.h
@@ -80,10 +80,13 @@ typedef struct {
 	void (*probe)(void);
 	void (*free)(void *drv_data);
 	int  (*get_bind_count)(void);
+	const char * const *
+	     (*get_key_names)(int *count);
 	void (*get_def_binds)(int *binds);
 	int  (*clean_binds)(void *drv_data, int *binds, int *def_finds);
 	int  (*get_config)(void *drv_data, int what, int *val);
 	int  (*set_config)(void *drv_data, int what, int val);
+	/* return -1 on no event, -2 on error */
 	int  (*update_keycode)(void *drv_data, int *is_down);
 	int  (*menu_translate)(void *drv_data, int keycode);
 	int  (*get_key_code)(const char *key_name);
diff --git a/frontend/linux/in_evdev.c b/frontend/linux/in_evdev.c
index d863c022..f11f3a41 100644
--- a/frontend/linux/in_evdev.c
+++ b/frontend/linux/in_evdev.c
@@ -261,9 +261,11 @@ static void in_evdev_free(void *drv_data)
 	free(dev);
 }
 
-static int in_evdev_get_bind_count(void)
+static const char * const *
+in_evdev_get_key_names(int *count)
 {
-	return KEY_CNT;
+	*count = KEY_CNT;
+	return in_evdev_keys;
 }
 
 static void or_binds(const int *binds, int key, int *result)
@@ -408,7 +410,8 @@ static int in_evdev_update_keycode(void *data, int *is_down)
 	if (rd < (int) sizeof(ev)) {
 		if (errno != EAGAIN) {
 			perror("in_evdev: error reading");
-			sleep(1);
+			//sleep(1);
+			ret_kc = -2;
 		}
 		goto out;
 	}
@@ -621,7 +624,7 @@ void in_evdev_init(void *vdrv)
 	drv->prefix = in_evdev_prefix;
 	drv->probe = in_evdev_probe;
 	drv->free = in_evdev_free;
-	drv->get_bind_count = in_evdev_get_bind_count;
+	drv->get_key_names = in_evdev_get_key_names;
 	drv->get_def_binds = in_evdev_get_def_binds;
 	drv->clean_binds = in_evdev_clean_binds;
 	drv->set_config = in_evdev_set_config;
-- 
2.39.5