+static const struct {
+ short code;
+ short bit;
+} in_evdev_def_binds[] =
+{
+ /* MXYZ SACB RLDU */
+ { KEY_UP, 0 },
+ { KEY_DOWN, 1 },
+ { KEY_LEFT, 2 },
+ { KEY_RIGHT, 3 },
+ { KEY_S, 4 }, /* B */
+ { BTN_B, 4 },
+ { KEY_D, 5 }, /* C */
+ { BTN_A, 5 },
+ { KEY_A, 6 }, /* A */
+ { BTN_Y, 6 },
+ { KEY_ENTER, 7 },
+ { BTN_START, 7 },
+ { BTN_TL, PEVB_STATE_LOAD },
+ { BTN_TR, PEVB_STATE_SAVE },
+};
+
+#define DEF_BIND_COUNT (sizeof(in_evdev_def_binds) / sizeof(in_evdev_def_binds[0]))
+
+static void in_evdev_get_def_binds(int *binds)
+{
+ int i;
+
+ for (i = 0; i < DEF_BIND_COUNT; i++)
+ binds[in_evdev_def_binds[i].code] = 1 << in_evdev_def_binds[i].bit;
+}
+
+/* remove binds of missing keys, count remaining ones */
+static int in_evdev_clean_binds(void *drv_data, int *binds)
+{
+ int keybits[(KEY_MAX+1)/sizeof(int)];
+ in_evdev_t *dev = drv_data;
+ int i, ret, count = 0;
+
+ ret = ioctl(dev->fd, EVIOCGBIT(EV_KEY, sizeof(keybits)), keybits);
+ if (ret == -1) {
+ perror("in_evdev: ioctl failed");
+ memset(keybits, 0xff, sizeof(keybits)); /* mark all as good */
+ }
+
+ if (dev->abs_lzone != 0) {
+ KEYBITS_BIT_SET(KEY_LEFT);
+ KEYBITS_BIT_SET(KEY_RIGHT);
+ }
+ if (dev->abs_tzone != 0) {
+ KEYBITS_BIT_SET(KEY_UP);
+ KEYBITS_BIT_SET(KEY_DOWN);
+ }
+
+ for (i = 0; i < KEY_MAX + 1; i++) {
+ if (!KEYBITS_BIT(i))
+ binds[i] = binds[i + KEY_MAX + 1] = 0;
+ if (binds[i])
+ count++;
+ }
+
+ return count;
+}
+
+void in_evdev_init(void *vdrv)
+{
+ in_drv_t *drv = 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_def_binds = in_evdev_get_def_binds;
+ drv->clean_binds = in_evdev_clean_binds;
+ drv->set_blocking = in_evdev_set_blocking;
+ drv->update_keycode = in_evdev_update_keycode;
+ drv->menu_translate = in_evdev_menu_translate;
+ drv->get_key_code = in_evdev_get_key_code;
+ drv->get_key_name = in_evdev_get_key_name;
+}
+