HID: add hooks for getkeycode() and setkeycode() methods

Provide hooks for getkeycode() and setkeycode() methods to
input_dev.

Signed-off-by: Marvin Raaijmakers <marvin.raaijmakers@gmail.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index a87b059..7f81789 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -240,6 +240,89 @@
 }
 #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)
 {
@@ -919,6 +1002,8 @@
 				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;