diff options
Diffstat (limited to 'drivers/hid/hid-input.c')
-rw-r--r-- | drivers/hid/hid-input.c | 101 |
1 files changed, 96 insertions, 5 deletions
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index a19b65ed311..7f817897b17 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c @@ -240,11 +240,94 @@ static inline void hidinput_pb_setup(struct input_dev *input) } #endif +static inline int match_scancode(int code, int scancode) +{ + if (scancode == 0) + return 1; + return ((code & (HID_USAGE_PAGE | HID_USAGE)) == scancode); +} + +static inline int match_keycode(int code, int keycode) +{ + if (keycode == 0) + return 1; + return (code == keycode); +} + +static struct hid_usage *hidinput_find_key(struct hid_device *hid, + int scancode, int keycode) +{ + int i, j, k; + struct hid_report *report; + struct hid_usage *usage; + + for (k = HID_INPUT_REPORT; k <= HID_OUTPUT_REPORT; k++) { + list_for_each_entry(report, &hid->report_enum[k].report_list, list) { + for (i = 0; i < report->maxfield; i++) { + for ( j = 0; j < report->field[i]->maxusage; j++) { + usage = report->field[i]->usage + j; + if (usage->type == EV_KEY && + match_scancode(usage->hid, scancode) && + match_keycode(usage->code, keycode)) + return usage; + } + } + } + } + return NULL; +} + +static int hidinput_getkeycode(struct input_dev *dev, int scancode, + int *keycode) +{ + struct hid_device *hid = dev->private; + struct hid_usage *usage; + + usage = hidinput_find_key(hid, scancode, 0); + if (usage) { + *keycode = usage->code; + return 0; + } + return -EINVAL; +} + +static int hidinput_setkeycode(struct input_dev *dev, int scancode, + int keycode) +{ + struct hid_device *hid = dev->private; + struct hid_usage *usage; + int old_keycode; + + if (keycode < 0 || keycode > KEY_MAX) + return -EINVAL; + + usage = hidinput_find_key(hid, scancode, 0); + if (usage) { + old_keycode = usage->code; + usage->code = keycode; + + clear_bit(old_keycode, dev->keybit); + set_bit(usage->code, dev->keybit); +#ifdef CONFIG_HID_DEBUG + printk (KERN_DEBUG "Assigned keycode %d to HID usage code %x\n", keycode, scancode); +#endif + /* Set the keybit for the old keycode if the old keycode is used + * by another key */ + if (hidinput_find_key (hid, 0, old_keycode)) + set_bit(old_keycode, dev->keybit); + + return 0; + } + + return -EINVAL; +} + + static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_field *field, struct hid_usage *usage) { struct input_dev *input = hidinput->input; - struct hid_device *device = input->private; + struct hid_device *device = input_get_drvdata(input); int max = 0, code; unsigned long *bit = NULL; @@ -553,6 +636,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel case 0x1015: map_key_clear(KEY_RECORD); break; case 0x1016: map_key_clear(KEY_PLAYER); break; case 0x1017: map_key_clear(KEY_EJECTCD); break; + case 0x1018: map_key_clear(KEY_MEDIA); break; case 0x1019: map_key_clear(KEY_PROG1); break; case 0x101a: map_key_clear(KEY_PROG2); break; case 0x101b: map_key_clear(KEY_PROG3); break; @@ -560,9 +644,12 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel case 0x1020: map_key_clear(KEY_ZOOMOUT); break; case 0x1021: map_key_clear(KEY_ZOOMRESET); break; case 0x1023: map_key_clear(KEY_CLOSE); break; + case 0x1027: map_key_clear(KEY_MENU); break; /* this one is marked as 'Rotate' */ case 0x1028: map_key_clear(KEY_ANGLE); break; case 0x1029: map_key_clear(KEY_SHUFFLE); break; + case 0x102a: map_key_clear(KEY_BACK); break; + case 0x102b: map_key_clear(KEY_CYCLEWINDOWS); break; case 0x1041: map_key_clear(KEY_BATTERY); break; case 0x1042: map_key_clear(KEY_WORDPROCESSOR); break; case 0x1043: map_key_clear(KEY_SPREADSHEET); break; @@ -855,13 +942,15 @@ EXPORT_SYMBOL_GPL(hidinput_find_field); static int hidinput_open(struct input_dev *dev) { - struct hid_device *hid = dev->private; + struct hid_device *hid = input_get_drvdata(dev); + return hid->hid_open(hid); } static void hidinput_close(struct input_dev *dev) { - struct hid_device *hid = dev->private; + struct hid_device *hid = input_get_drvdata(dev); + hid->hid_close(hid); } @@ -909,10 +998,12 @@ int hidinput_connect(struct hid_device *hid) return -1; } - input_dev->private = hid; + input_set_drvdata(input_dev, hid); input_dev->event = hid->hidinput_input_event; input_dev->open = hidinput_open; input_dev->close = hidinput_close; + input_dev->setkeycode = hidinput_setkeycode; + input_dev->getkeycode = hidinput_getkeycode; input_dev->name = hid->name; input_dev->phys = hid->phys; @@ -921,7 +1012,7 @@ int hidinput_connect(struct hid_device *hid) input_dev->id.vendor = hid->vendor; input_dev->id.product = hid->product; input_dev->id.version = hid->version; - input_dev->cdev.dev = hid->dev; + input_dev->dev.parent = hid->dev; hidinput->input = input_dev; list_add_tail(&hidinput->list, &hid->inputs); } |