more input layer tweaks

git-svn-id: file:///home/notaz/opt/svn/PicoDrive/platform@627 be3aeb3a-fb24-0410-a615-afba39da0efa
This commit is contained in:
notaz 2009-01-02 19:43:27 +00:00
parent da767bd51b
commit 906bdc9fb5
4 changed files with 165 additions and 59 deletions

View file

@ -9,8 +9,9 @@ typedef struct
{ {
int drv_id; int drv_id;
void *drv_data; void *drv_data;
int *binds;
char *name; char *name;
int *binds;
int prev_result;
int probed:1; int probed:1;
} in_dev_t; } in_dev_t;
@ -154,11 +155,19 @@ int in_update(void)
int i, result = 0; int i, result = 0;
for (i = 0; i < in_dev_count; i++) { for (i = 0; i < in_dev_count; i++) {
if (in_devices[i].probed && in_devices[i].binds != NULL) { in_dev_t *dev = &in_devices[i];
switch (in_devices[i].drv_id) { int ret;
if (dev->probed && dev->binds != NULL) {
switch (dev->drv_id) {
#ifdef IN_EVDEV #ifdef IN_EVDEV
case IN_DRVID_EVDEV: case IN_DRVID_EVDEV:
result |= in_evdev_update(in_devices[i].drv_data, in_devices[i].binds); ret = in_evdev_update(dev->drv_data, dev->binds);
if (ret == -1) /* no change */
result |= dev->prev_result;
else {
dev->prev_result = ret;
result |= ret;
}
break; break;
#endif #endif
} }
@ -181,6 +190,8 @@ static void **in_collect_drvdata(int drv_id, int *count)
return data; return data;
} }
static int menu_key_state = 0;
void in_set_blocking(int is_blocking) void in_set_blocking(int is_blocking)
{ {
int i; int i;
@ -188,16 +199,21 @@ void in_set_blocking(int is_blocking)
for (i = 0; i < in_dev_count; i++) { for (i = 0; i < in_dev_count; i++) {
if (in_devices[i].probed) if (in_devices[i].probed)
DRV(in_devices[i].drv_id).set_blocking(in_devices[i].drv_data, is_blocking); DRV(in_devices[i].drv_id).set_blocking(in_devices[i].drv_data, is_blocking);
in_devices[i].prev_result = 0;
} }
menu_key_state = 0;
/* flush events */
in_update_keycode(NULL, NULL, 1);
} }
/* /*
* update with wait for a press, return keycode * update with wait for a press, return keycode
* only can use 1 drv here.. * only can use 1 drv here..
*/ */
int in_update_keycode(int *dev_id, int *is_down) int in_update_keycode(int *dev_id_out, int *is_down_out, int timeout_ms)
{ {
int result = 0; int result = 0, dev_id, is_down, result_menu;
#ifdef IN_EVDEV #ifdef IN_EVDEV
void **data; void **data;
int i, id = 0, count = 0; int i, id = 0, count = 0;
@ -209,48 +225,58 @@ int in_update_keycode(int *dev_id, int *is_down)
exit(1); exit(1);
} }
result = in_evdev_update_keycode(data, count, &id, is_down); result = in_evdev_update_keycode(data, count, &id, &is_down, timeout_ms);
if (dev_id != NULL) { for (i = id; i < in_dev_count; i++) {
for (i = id; i < in_dev_count; i++) { if (in_devices[i].drv_data == data[id]) {
if (in_devices[i].drv_data == data[id]) { dev_id = i;
*dev_id = i; break;
break;
}
} }
} }
#else #else
#error no menu read handlers #error no menu read handlers
#endif #endif
/* keep track of menu key state, to allow mixing
* in_update_keycode() and in_update_menu() calls */
result_menu = DRV(in_devices[dev_id].drv_id).menu_translate(result);
if (result_menu != 0) {
if (is_down)
menu_key_state |= result_menu;
else
menu_key_state &= ~result_menu;
}
if (dev_id_out != NULL)
*dev_id_out = dev_id;
if (is_down_out != NULL)
*is_down_out = is_down;
return result; return result;
} }
/* /*
* same as above, only return bitfield of BTN_* * same as above, only return bitfield of BTN_*
*/ */
int in_update_menu(void) int in_update_menu(int timeout_ms)
{ {
static int keys_active = 0; int keys_old = menu_key_state;
int keys_old = keys_active;
while (1) while (1)
{ {
int code, is_down = 0, dev_id = 0; int code, is_down = 0, dev_id = 0;
code = in_update_keycode(&dev_id, &is_down);
code = in_update_keycode(&dev_id, &is_down, timeout_ms);
code = DRV(in_devices[dev_id].drv_id).menu_translate(code); code = DRV(in_devices[dev_id].drv_id).menu_translate(code);
if (code == 0) continue;
if (is_down) if (timeout_ms != 0)
keys_active |= code; break;
else if (code == 0)
keys_active &= ~code; continue;
if (keys_old != menu_key_state)
if (keys_old != keys_active)
break; break;
} }
return keys_active; return menu_key_state;
} }
const int *in_get_dev_binds(int dev_id) const int *in_get_dev_binds(int dev_id)
@ -288,12 +314,61 @@ const char *in_get_dev_name(int dev_id)
return in_devices[dev_id].name; return in_devices[dev_id].name;
} }
/* never returns NULL */
const char *in_get_key_name(int dev_id, int keycode) const char *in_get_key_name(int dev_id, int keycode)
{ {
static char xname[16];
const char *name;
if (dev_id < 0 || dev_id >= IN_MAX_DEVS) if (dev_id < 0 || dev_id >= IN_MAX_DEVS)
return "Unkn0"; return "Unkn0";
return DRV(in_devices[dev_id].drv_id).get_key_name(keycode); name = DRV(in_devices[dev_id].drv_id).get_key_name(keycode);
if (name != NULL)
return name;
/* assume scancode */
if ((keycode >= '0' && keycode <= '9') || (keycode >= 'a' && keycode <= 'z')
|| (keycode >= 'A' && keycode <= 'Z'))
sprintf(xname, "%c", keycode);
else
sprintf(xname, "\\x%02X", keycode);
return xname;
}
int in_bind_key(int dev_id, int keycode, int mask, int force_unbind)
{
int ret, count;
in_dev_t *dev;
if (dev_id < 0 || dev_id >= IN_MAX_DEVS)
return -1;
dev = &in_devices[dev_id];
if (dev->binds == NULL) {
if (force_unbind)
return 0;
dev->binds = in_alloc_binds(dev->drv_id);
if (dev->binds == NULL)
return -1;
}
count = in_bind_count(dev->drv_id);
if (keycode < 0 || keycode >= count)
return -1;
if (force_unbind)
dev->binds[keycode] &= ~mask;
else
dev->binds[keycode] ^= mask;
ret = DRV(dev->drv_id).clean_binds(dev->drv_data, dev->binds);
if (ret == 0) {
free(dev->binds);
dev->binds = NULL;
}
return 0;
} }
/* returns device id, or -1 on error */ /* returns device id, or -1 on error */
@ -354,11 +429,11 @@ void in_config_start(void)
for (i = 0; i < IN_MAX_DEVS; i++) { for (i = 0; i < IN_MAX_DEVS; i++) {
int n, count, *binds, *def_binds; int n, count, *binds, *def_binds;
if (in_devices[i].binds == NULL) binds = in_devices[i].binds;
if (binds == NULL)
continue; continue;
count = in_bind_count(in_devices[i].drv_id); count = in_bind_count(in_devices[i].drv_id);
binds = in_devices[i].binds;
def_binds = binds + count; def_binds = binds + count;
for (n = 0; n < count; n++) for (n = 0; n < count; n++)
@ -369,27 +444,46 @@ void in_config_start(void)
int in_config_bind_key(int dev_id, const char *key, int binds) int in_config_bind_key(int dev_id, const char *key, int binds)
{ {
int kc; int count, kc;
in_dev_t *dev;
if (dev_id < 0 || dev_id >= IN_MAX_DEVS) if (dev_id < 0 || dev_id >= IN_MAX_DEVS)
return -1; return -1;
dev = &in_devices[dev_id];
if (in_devices[dev_id].binds == NULL) { count = in_bind_count(dev->drv_id);
in_devices[dev_id].binds = in_alloc_binds(in_devices[dev_id].drv_id);
if (in_devices[dev_id].binds == NULL) /* maybe a raw code? */
return -1; if (key[0] == '\\' && key[1] == 'x') {
in_config_start(); char *p = NULL;
kc = (int)strtoul(key + 2, &p, 16);
if (p == NULL || *p != 0)
kc = -1;
}
else {
/* device specific key name */
if (dev->binds == NULL) {
dev->binds = in_alloc_binds(dev->drv_id);
if (dev->binds == NULL)
return -1;
in_config_start();
}
kc = DRV(dev->drv_id).get_key_code(key);
if (kc < 0 && strlen(key) == 1) {
/* assume scancode */
kc = key[0];
}
} }
kc = DRV(in_devices[dev_id].drv_id).get_key_code(key); if (kc < 0 || kc >= count) {
if (kc < 0) {
printf("input: bad key: %s\n", key); printf("input: bad key: %s\n", key);
return -1; return -1;
} }
if (in_devices[dev_id].binds[kc] == -1) if (dev->binds[kc] == -1)
in_devices[dev_id].binds[kc] = 0; dev->binds[kc] = 0;
in_devices[dev_id].binds[kc] |= binds; dev->binds[kc] |= binds;
return 0; return 0;
} }
@ -400,26 +494,27 @@ void in_config_end(void)
for (i = 0; i < IN_MAX_DEVS; i++) { for (i = 0; i < IN_MAX_DEVS; i++) {
int n, ret, count, *binds, *def_binds; int n, ret, count, *binds, *def_binds;
in_dev_t *dev = &in_devices[i];
if (in_devices[i].binds == NULL) if (dev->binds == NULL)
continue; continue;
count = in_bind_count(in_devices[i].drv_id); count = in_bind_count(dev->drv_id);
binds = in_devices[i].binds; binds = dev->binds;
def_binds = binds + count; def_binds = binds + count;
for (n = 0; n < count; n++) for (n = 0; n < count; n++)
if (binds[n] == -1) if (binds[n] == -1)
binds[n] = def_binds[n]; binds[n] = def_binds[n];
if (in_devices[i].drv_data == NULL) if (dev->drv_data == NULL)
continue; continue;
ret = DRV(in_devices[i].drv_id).clean_binds(in_devices[i].drv_data, binds); ret = DRV(dev->drv_id).clean_binds(dev->drv_data, binds);
if (ret == 0) { if (ret == 0) {
/* no useable binds */ /* no useable binds */
free(binds); free(dev->binds);
in_devices[i].binds = NULL; dev->binds = NULL;
} }
} }
} }

View file

@ -27,14 +27,14 @@ void in_init(void);
void in_probe(void); void in_probe(void);
int in_update(void); int in_update(void);
void in_set_blocking(int is_blocking); void in_set_blocking(int is_blocking);
int in_update_keycode(int *dev_id, int *is_down); int in_update_keycode(int *dev_id, int *is_down, int timeout_ms);
int in_update_menu(void); int in_update_menu(int timeout_ms);
int in_get_dev_bind_count(int dev_id); int in_get_dev_bind_count(int dev_id);
void in_config_start(void); void in_config_start(void);
int in_config_parse_dev(const char *dev_name); int in_config_parse_dev(const char *dev_name);
int in_config_bind_key(int dev_id, const char *key, int mask); int in_config_bind_key(int dev_id, const char *key, int mask);
void in_config_end(void); void in_config_end(void);
int in_bind_key(int dev_id, int keycode, int mask); int in_bind_key(int dev_id, int keycode, int mask, int force_unbind);
void in_debug_dump(void); void in_debug_dump(void);
const int *in_get_dev_binds(int dev_id); const int *in_get_dev_binds(int dev_id);

View file

@ -165,6 +165,8 @@ static int in_evdev_get_bind_count(void)
return KEY_MAX + 1; return KEY_MAX + 1;
} }
/* returns bitfield of active binds or -1 if nothing
* changed from previous time */
int in_evdev_update(void *drv_data, int *binds) int in_evdev_update(void *drv_data, int *binds)
{ {
struct input_event ev[16]; struct input_event ev[16];
@ -184,24 +186,20 @@ int in_evdev_update(void *drv_data, int *binds)
changed = 1; changed = 1;
} }
/*
if (!changed) if (!changed)
return 0; return -1;
*/
ret = ioctl(fd, EVIOCGKEY(sizeof(keybits)), keybits); ret = ioctl(fd, EVIOCGKEY(sizeof(keybits)), keybits);
if (ret == -1) { if (ret == -1) {
perror("in_evdev: ioctl failed"); perror("in_evdev: ioctl failed");
return 0; return 0;
} }
printf("#%d: ", fd);
for (u = 0; u < KEY_MAX + 1; u++) { for (u = 0; u < KEY_MAX + 1; u++) {
if (KEYBITS_BIT(u)) { if (KEYBITS_BIT(u)) {
printf(" %d", u);
result |= binds[u]; result |= binds[u];
} }
} }
printf("\n");
return result; return result;
} }
@ -225,11 +223,21 @@ static void in_evdev_set_blocking(void *data, int y)
perror("in_evdev: F_SETFL fcntl failed"); perror("in_evdev: F_SETFL fcntl failed");
} }
int in_evdev_update_keycode(void **data, int dcount, int *which, int *is_down) int in_evdev_update_keycode(void **data, int dcount, int *which, int *is_down, int timeout_ms)
{ {
const int *fds = (const int *)data; const int *fds = (const int *)data;
struct timeval tv, *timeout = NULL;
int i, fdmax = -1; int i, fdmax = -1;
if (timeout_ms > 0) {
tv.tv_sec = timeout_ms / 1000;
tv.tv_usec = (timeout_ms % 1000) * 1000;
timeout = &tv;
}
if (is_down != NULL)
*is_down = 0;
for (i = 0; i < dcount; i++) for (i = 0; i < dcount; i++)
if (fds[i] > fdmax) fdmax = fds[i]; if (fds[i] > fdmax) fdmax = fds[i];
@ -243,7 +251,7 @@ int in_evdev_update_keycode(void **data, int dcount, int *which, int *is_down)
for (i = 0; i < dcount; i++) for (i = 0; i < dcount; i++)
FD_SET(fds[i], &fdset); FD_SET(fds[i], &fdset);
ret = select(fdmax + 1, &fdset, NULL, NULL, NULL); ret = select(fdmax + 1, &fdset, NULL, NULL, timeout);
if (ret == -1) if (ret == -1)
{ {
perror("in_evdev: select failed"); perror("in_evdev: select failed");
@ -251,6 +259,9 @@ int in_evdev_update_keycode(void **data, int dcount, int *which, int *is_down)
return 0; return 0;
} }
if (ret == 0)
return 0; /* timeout */
for (i = 0; i < dcount; i++) for (i = 0; i < dcount; i++)
if (FD_ISSET(fds[i], &fdset)) if (FD_ISSET(fds[i], &fdset))
*which = i, fd = fds[i]; *which = i, fd = fds[i];
@ -267,7 +278,7 @@ int in_evdev_update_keycode(void **data, int dcount, int *which, int *is_down)
if (ev[i].type != EV_KEY || ev[i].value < 0 || ev[i].value > 1) if (ev[i].type != EV_KEY || ev[i].value < 0 || ev[i].value > 1)
continue; continue;
if (is_down) if (is_down != NULL)
*is_down = ev[i].value; *is_down = ev[i].value;
return ev[i].code; return ev[i].code;
} }

View file

@ -1,5 +1,5 @@
int in_evdev_update(void *drv_data, int *binds); int in_evdev_update(void *drv_data, int *binds);
int in_evdev_update_keycode(void **data, int count, int *which, int *is_down); int in_evdev_update_keycode(void **data, int count, int *which, int *is_down, int timeout_ms);
void in_evdev_init(void *vdrv); void in_evdev_init(void *vdrv);