aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hid
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/hid')
-rw-r--r--drivers/hid/hid-input.c103
1 files changed, 70 insertions, 33 deletions
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
index 6c03dcc5760a..b12c07e64fbd 100644
--- a/drivers/hid/hid-input.c
+++ b/drivers/hid/hid-input.c
@@ -68,39 +68,49 @@ static const struct {
68#define map_key_clear(c) hid_map_usage_clear(hidinput, usage, &bit, \ 68#define map_key_clear(c) hid_map_usage_clear(hidinput, usage, &bit, \
69 &max, EV_KEY, (c)) 69 &max, EV_KEY, (c))
70 70
71static inline int match_scancode(unsigned int code, unsigned int scancode) 71static bool match_scancode(struct hid_usage *usage,
72 unsigned int cur_idx, unsigned int scancode)
72{ 73{
73 if (scancode == 0) 74 return (usage->hid & (HID_USAGE_PAGE | HID_USAGE)) == scancode;
74 return 1;
75
76 return (code & (HID_USAGE_PAGE | HID_USAGE)) == scancode;
77} 75}
78 76
79static inline int match_keycode(unsigned int code, unsigned int keycode) 77static bool match_keycode(struct hid_usage *usage,
78 unsigned int cur_idx, unsigned int keycode)
80{ 79{
81 if (keycode == 0) 80 return usage->code == keycode;
82 return 1; 81}
83 82
84 return code == keycode; 83static bool match_index(struct hid_usage *usage,
84 unsigned int cur_idx, unsigned int idx)
85{
86 return cur_idx == idx;
85} 87}
86 88
89typedef bool (*hid_usage_cmp_t)(struct hid_usage *usage,
90 unsigned int cur_idx, unsigned int val);
91
87static struct hid_usage *hidinput_find_key(struct hid_device *hid, 92static struct hid_usage *hidinput_find_key(struct hid_device *hid,
88 unsigned int scancode, 93 hid_usage_cmp_t match,
89 unsigned int keycode) 94 unsigned int value,
95 unsigned int *usage_idx)
90{ 96{
91 int i, j, k; 97 unsigned int i, j, k, cur_idx = 0;
92 struct hid_report *report; 98 struct hid_report *report;
93 struct hid_usage *usage; 99 struct hid_usage *usage;
94 100
95 for (k = HID_INPUT_REPORT; k <= HID_OUTPUT_REPORT; k++) { 101 for (k = HID_INPUT_REPORT; k <= HID_OUTPUT_REPORT; k++) {
96 list_for_each_entry(report, &hid->report_enum[k].report_list, list) { 102 list_for_each_entry(report, &hid->report_enum[k].report_list, list) {
97 for (i = 0; i < report->maxfield; i++) { 103 for (i = 0; i < report->maxfield; i++) {
98 for ( j = 0; j < report->field[i]->maxusage; j++) { 104 for (j = 0; j < report->field[i]->maxusage; j++) {
99 usage = report->field[i]->usage + j; 105 usage = report->field[i]->usage + j;
100 if (usage->type == EV_KEY && 106 if (usage->type == EV_KEY) {
101 match_scancode(usage->hid, scancode) && 107 if (match(usage, cur_idx, value)) {
102 match_keycode(usage->code, keycode)) 108 if (usage_idx)
103 return usage; 109 *usage_idx = cur_idx;
110 return usage;
111 }
112 cur_idx++;
113 }
104 } 114 }
105 } 115 }
106 } 116 }
@@ -108,39 +118,66 @@ static struct hid_usage *hidinput_find_key(struct hid_device *hid,
108 return NULL; 118 return NULL;
109} 119}
110 120
121static struct hid_usage *hidinput_locate_usage(struct hid_device *hid,
122 const struct input_keymap_entry *ke,
123 unsigned int *index)
124{
125 struct hid_usage *usage;
126 unsigned int scancode;
127
128 if (ke->flags & INPUT_KEYMAP_BY_INDEX)
129 usage = hidinput_find_key(hid, match_index, ke->index, index);
130 else if (input_scancode_to_scalar(ke, &scancode) == 0)
131 usage = hidinput_find_key(hid, match_scancode, scancode, index);
132 else
133 usage = NULL;
134
135 return usage;
136}
137
111static int hidinput_getkeycode(struct input_dev *dev, 138static int hidinput_getkeycode(struct input_dev *dev,
112 unsigned int scancode, unsigned int *keycode) 139 struct input_keymap_entry *ke)
113{ 140{
114 struct hid_device *hid = input_get_drvdata(dev); 141 struct hid_device *hid = input_get_drvdata(dev);
115 struct hid_usage *usage; 142 struct hid_usage *usage;
143 unsigned int scancode, index;
116 144
117 usage = hidinput_find_key(hid, scancode, 0); 145 usage = hidinput_locate_usage(hid, ke, &index);
118 if (usage) { 146 if (usage) {
119 *keycode = usage->code; 147 ke->keycode = usage->code;
148 ke->index = index;
149 scancode = usage->hid & (HID_USAGE_PAGE | HID_USAGE);
150 ke->len = sizeof(scancode);
151 memcpy(ke->scancode, &scancode, sizeof(scancode));
120 return 0; 152 return 0;
121 } 153 }
154
122 return -EINVAL; 155 return -EINVAL;
123} 156}
124 157
125static int hidinput_setkeycode(struct input_dev *dev, 158static int hidinput_setkeycode(struct input_dev *dev,
126 unsigned int scancode, unsigned int keycode) 159 const struct input_keymap_entry *ke,
160 unsigned int *old_keycode)
127{ 161{
128 struct hid_device *hid = input_get_drvdata(dev); 162 struct hid_device *hid = input_get_drvdata(dev);
129 struct hid_usage *usage; 163 struct hid_usage *usage;
130 int old_keycode;
131 164
132 usage = hidinput_find_key(hid, scancode, 0); 165 usage = hidinput_locate_usage(hid, ke, NULL);
133 if (usage) { 166 if (usage) {
134 old_keycode = usage->code; 167 *old_keycode = usage->code;
135 usage->code = keycode; 168 usage->code = ke->keycode;
136 169
137 clear_bit(old_keycode, dev->keybit); 170 clear_bit(*old_keycode, dev->keybit);
138 set_bit(usage->code, dev->keybit); 171 set_bit(usage->code, dev->keybit);
139 dbg_hid(KERN_DEBUG "Assigned keycode %d to HID usage code %x\n", keycode, scancode); 172 dbg_hid(KERN_DEBUG "Assigned keycode %d to HID usage code %x\n",
140 /* Set the keybit for the old keycode if the old keycode is used 173 usage->code, usage->hid);
141 * by another key */ 174
142 if (hidinput_find_key (hid, 0, old_keycode)) 175 /*
143 set_bit(old_keycode, dev->keybit); 176 * Set the keybit for the old keycode if the old keycode is used
177 * by another key
178 */
179 if (hidinput_find_key(hid, match_keycode, *old_keycode, NULL))
180 set_bit(*old_keycode, dev->keybit);
144 181
145 return 0; 182 return 0;
146 } 183 }
@@ -748,8 +785,8 @@ int hidinput_connect(struct hid_device *hid, unsigned int force)
748 hid->ll_driver->hidinput_input_event; 785 hid->ll_driver->hidinput_input_event;
749 input_dev->open = hidinput_open; 786 input_dev->open = hidinput_open;
750 input_dev->close = hidinput_close; 787 input_dev->close = hidinput_close;
751 input_dev->setkeycode = hidinput_setkeycode; 788 input_dev->setkeycode_new = hidinput_setkeycode;
752 input_dev->getkeycode = hidinput_getkeycode; 789 input_dev->getkeycode_new = hidinput_getkeycode;
753 790
754 input_dev->name = hid->name; 791 input_dev->name = hid->name;
755 input_dev->phys = hid->phys; 792 input_dev->phys = hid->phys;