+ dev = &in_devices[dev_id];
+ if (keycode < 0) /* want name for menu key? */
+ keycode = DRV(dev->drv_id).menu_translate(dev->drv_data, keycode);
+
+ if (dev->key_names != NULL && 0 <= keycode && keycode < dev->key_count)
+ name = dev->key_names[keycode];
+ if (name != NULL)
+ return name;
+
+ name = DRV(dev->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_get_key_code(int dev_id, const char *key_name)
+{
+ in_dev_t *dev;
+ int i;
+
+ if (dev_id < 0) /* want last used dev? */
+ dev_id = menu_last_used_dev;
+
+ if (dev_id < 0 || dev_id >= IN_MAX_DEVS)
+ return -1;
+
+ dev = &in_devices[dev_id];
+ if (dev->key_names == NULL)
+ return -1;
+
+ for (i = 0; i < dev->key_count; i++)
+ if (dev->key_names[i] && strcasecmp(dev->key_names[i], key_name) == 0)
+ return i;
+
+ return -1;
+}
+
+int in_bind_key(int dev_id, int keycode, int mask, int bind_type, int force_unbind)
+{
+ int ret, count;
+ in_dev_t *dev;
+
+ if (dev_id < 0 || dev_id >= IN_MAX_DEVS || bind_type >= IN_BINDTYPE_COUNT)
+ return -1;
+
+ dev = &in_devices[dev_id];
+ count = dev->key_count;
+
+ if (dev->binds == NULL) {
+ if (force_unbind)
+ return 0;
+ dev->binds = in_alloc_binds(dev->drv_id, count);
+ if (dev->binds == NULL)
+ return -1;
+ }
+
+ if (keycode < 0 || keycode >= count)
+ return -1;
+
+ if (force_unbind)
+ dev->binds[IN_BIND_OFFS(keycode, bind_type)] &= ~mask;
+ else
+ dev->binds[IN_BIND_OFFS(keycode, bind_type)] ^= mask;
+
+ ret = DRV(dev->drv_id).clean_binds(dev->drv_data, dev->binds,
+ dev->binds + count * IN_BINDTYPE_COUNT);
+ if (ret == 0) {
+ free(dev->binds);
+ dev->binds = NULL;
+ }
+
+ return 0;
+}
+
+/*
+ * Unbind act_mask on binds with type bind_type
+ * - if dev_id_ < 0, affects all devices
+ * else only affects dev_id_
+ * - if act_mask == -1, unbind all keys
+ * else only actions in mask
+ */
+void in_unbind_all(int dev_id_, int act_mask, int bind_type)
+{
+ int dev_id = 0, dev_last = IN_MAX_DEVS - 1;
+ int i, count;
+ in_dev_t *dev;
+
+ if (dev_id_ >= 0)
+ dev_id = dev_last = dev_id_;
+
+ if (bind_type >= IN_BINDTYPE_COUNT)
+ return;
+
+ for (; dev_id <= dev_last; dev_id++) {
+ dev = &in_devices[dev_id];
+ count = dev->key_count;
+
+ if (dev->binds == NULL)
+ continue;
+
+ if (act_mask != -1) {
+ for (i = 0; i < count; i++)
+ dev->binds[IN_BIND_OFFS(i, bind_type)] &= ~act_mask;
+ }
+ else
+ memset(dev->binds, 0, sizeof(dev->binds[0]) * count * IN_BINDTYPE_COUNT);
+ }