diff options
Diffstat (limited to 'drivers/hid/hid-input.c')
-rw-r--r-- | drivers/hid/hid-input.c | 127 |
1 files changed, 86 insertions, 41 deletions
diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index a1a2206714fc..c0757821b1fc 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c | |||
@@ -68,39 +68,52 @@ 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 | ||
71 | static inline int match_scancode(unsigned int code, unsigned int scancode) | 71 | static 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 | ||
79 | static inline int match_keycode(unsigned int code, unsigned int keycode) | 77 | static bool match_keycode(struct hid_usage *usage, |
78 | unsigned int cur_idx, unsigned int keycode) | ||
80 | { | 79 | { |
81 | if (keycode == 0) | 80 | /* |
82 | return 1; | 81 | * We should exclude unmapped usages when doing lookup by keycode. |
82 | */ | ||
83 | return (usage->type == EV_KEY && usage->code == keycode); | ||
84 | } | ||
83 | 85 | ||
84 | return code == keycode; | 86 | static bool match_index(struct hid_usage *usage, |
87 | unsigned int cur_idx, unsigned int idx) | ||
88 | { | ||
89 | return cur_idx == idx; | ||
85 | } | 90 | } |
86 | 91 | ||
92 | typedef bool (*hid_usage_cmp_t)(struct hid_usage *usage, | ||
93 | unsigned int cur_idx, unsigned int val); | ||
94 | |||
87 | static struct hid_usage *hidinput_find_key(struct hid_device *hid, | 95 | static struct hid_usage *hidinput_find_key(struct hid_device *hid, |
88 | unsigned int scancode, | 96 | hid_usage_cmp_t match, |
89 | unsigned int keycode) | 97 | unsigned int value, |
98 | unsigned int *usage_idx) | ||
90 | { | 99 | { |
91 | int i, j, k; | 100 | unsigned int i, j, k, cur_idx = 0; |
92 | struct hid_report *report; | 101 | struct hid_report *report; |
93 | struct hid_usage *usage; | 102 | struct hid_usage *usage; |
94 | 103 | ||
95 | for (k = HID_INPUT_REPORT; k <= HID_OUTPUT_REPORT; k++) { | 104 | for (k = HID_INPUT_REPORT; k <= HID_OUTPUT_REPORT; k++) { |
96 | list_for_each_entry(report, &hid->report_enum[k].report_list, list) { | 105 | list_for_each_entry(report, &hid->report_enum[k].report_list, list) { |
97 | for (i = 0; i < report->maxfield; i++) { | 106 | for (i = 0; i < report->maxfield; i++) { |
98 | for ( j = 0; j < report->field[i]->maxusage; j++) { | 107 | for (j = 0; j < report->field[i]->maxusage; j++) { |
99 | usage = report->field[i]->usage + j; | 108 | usage = report->field[i]->usage + j; |
100 | if (usage->type == EV_KEY && | 109 | if (usage->type == EV_KEY || usage->type == 0) { |
101 | match_scancode(usage->hid, scancode) && | 110 | if (match(usage, cur_idx, value)) { |
102 | match_keycode(usage->code, keycode)) | 111 | if (usage_idx) |
103 | return usage; | 112 | *usage_idx = cur_idx; |
113 | return usage; | ||
114 | } | ||
115 | cur_idx++; | ||
116 | } | ||
104 | } | 117 | } |
105 | } | 118 | } |
106 | } | 119 | } |
@@ -108,39 +121,68 @@ static struct hid_usage *hidinput_find_key(struct hid_device *hid, | |||
108 | return NULL; | 121 | return NULL; |
109 | } | 122 | } |
110 | 123 | ||
124 | static struct hid_usage *hidinput_locate_usage(struct hid_device *hid, | ||
125 | const struct input_keymap_entry *ke, | ||
126 | unsigned int *index) | ||
127 | { | ||
128 | struct hid_usage *usage; | ||
129 | unsigned int scancode; | ||
130 | |||
131 | if (ke->flags & INPUT_KEYMAP_BY_INDEX) | ||
132 | usage = hidinput_find_key(hid, match_index, ke->index, index); | ||
133 | else if (input_scancode_to_scalar(ke, &scancode) == 0) | ||
134 | usage = hidinput_find_key(hid, match_scancode, scancode, index); | ||
135 | else | ||
136 | usage = NULL; | ||
137 | |||
138 | return usage; | ||
139 | } | ||
140 | |||
111 | static int hidinput_getkeycode(struct input_dev *dev, | 141 | static int hidinput_getkeycode(struct input_dev *dev, |
112 | unsigned int scancode, unsigned int *keycode) | 142 | struct input_keymap_entry *ke) |
113 | { | 143 | { |
114 | struct hid_device *hid = input_get_drvdata(dev); | 144 | struct hid_device *hid = input_get_drvdata(dev); |
115 | struct hid_usage *usage; | 145 | struct hid_usage *usage; |
146 | unsigned int scancode, index; | ||
116 | 147 | ||
117 | usage = hidinput_find_key(hid, scancode, 0); | 148 | usage = hidinput_locate_usage(hid, ke, &index); |
118 | if (usage) { | 149 | if (usage) { |
119 | *keycode = usage->code; | 150 | ke->keycode = usage->type == EV_KEY ? |
151 | usage->code : KEY_RESERVED; | ||
152 | ke->index = index; | ||
153 | scancode = usage->hid & (HID_USAGE_PAGE | HID_USAGE); | ||
154 | ke->len = sizeof(scancode); | ||
155 | memcpy(ke->scancode, &scancode, sizeof(scancode)); | ||
120 | return 0; | 156 | return 0; |
121 | } | 157 | } |
158 | |||
122 | return -EINVAL; | 159 | return -EINVAL; |
123 | } | 160 | } |
124 | 161 | ||
125 | static int hidinput_setkeycode(struct input_dev *dev, | 162 | static int hidinput_setkeycode(struct input_dev *dev, |
126 | unsigned int scancode, unsigned int keycode) | 163 | const struct input_keymap_entry *ke, |
164 | unsigned int *old_keycode) | ||
127 | { | 165 | { |
128 | struct hid_device *hid = input_get_drvdata(dev); | 166 | struct hid_device *hid = input_get_drvdata(dev); |
129 | struct hid_usage *usage; | 167 | struct hid_usage *usage; |
130 | int old_keycode; | ||
131 | 168 | ||
132 | usage = hidinput_find_key(hid, scancode, 0); | 169 | usage = hidinput_locate_usage(hid, ke, NULL); |
133 | if (usage) { | 170 | if (usage) { |
134 | old_keycode = usage->code; | 171 | *old_keycode = usage->type == EV_KEY ? |
135 | usage->code = keycode; | 172 | usage->code : KEY_RESERVED; |
173 | usage->code = ke->keycode; | ||
136 | 174 | ||
137 | clear_bit(old_keycode, dev->keybit); | 175 | clear_bit(*old_keycode, dev->keybit); |
138 | set_bit(usage->code, dev->keybit); | 176 | set_bit(usage->code, dev->keybit); |
139 | dbg_hid(KERN_DEBUG "Assigned keycode %d to HID usage code %x\n", keycode, scancode); | 177 | dbg_hid("Assigned keycode %d to HID usage code %x\n", |
140 | /* Set the keybit for the old keycode if the old keycode is used | 178 | usage->code, usage->hid); |
141 | * by another key */ | 179 | |
142 | if (hidinput_find_key (hid, 0, old_keycode)) | 180 | /* |
143 | set_bit(old_keycode, dev->keybit); | 181 | * Set the keybit for the old keycode if the old keycode is used |
182 | * by another key | ||
183 | */ | ||
184 | if (hidinput_find_key(hid, match_keycode, *old_keycode, NULL)) | ||
185 | set_bit(*old_keycode, dev->keybit); | ||
144 | 186 | ||
145 | return 0; | 187 | return 0; |
146 | } | 188 | } |
@@ -161,8 +203,8 @@ static int hidinput_setkeycode(struct input_dev *dev, | |||
161 | * | 203 | * |
162 | * as seen in the HID specification v1.11 6.2.2.7 Global Items. | 204 | * as seen in the HID specification v1.11 6.2.2.7 Global Items. |
163 | * | 205 | * |
164 | * Only exponent 1 length units are processed. Centimeters are converted to | 206 | * Only exponent 1 length units are processed. Centimeters and inches are |
165 | * inches. Degrees are converted to radians. | 207 | * converted to millimeters. Degrees are converted to radians. |
166 | */ | 208 | */ |
167 | static __s32 hidinput_calc_abs_res(const struct hid_field *field, __u16 code) | 209 | static __s32 hidinput_calc_abs_res(const struct hid_field *field, __u16 code) |
168 | { | 210 | { |
@@ -183,13 +225,16 @@ static __s32 hidinput_calc_abs_res(const struct hid_field *field, __u16 code) | |||
183 | */ | 225 | */ |
184 | if (code == ABS_X || code == ABS_Y || code == ABS_Z) { | 226 | if (code == ABS_X || code == ABS_Y || code == ABS_Z) { |
185 | if (field->unit == 0x11) { /* If centimeters */ | 227 | if (field->unit == 0x11) { /* If centimeters */ |
186 | /* Convert to inches */ | 228 | /* Convert to millimeters */ |
187 | prev = logical_extents; | 229 | unit_exponent += 1; |
188 | logical_extents *= 254; | 230 | } else if (field->unit == 0x13) { /* If inches */ |
189 | if (logical_extents < prev) | 231 | /* Convert to millimeters */ |
232 | prev = physical_extents; | ||
233 | physical_extents *= 254; | ||
234 | if (physical_extents < prev) | ||
190 | return 0; | 235 | return 0; |
191 | unit_exponent += 2; | 236 | unit_exponent -= 1; |
192 | } else if (field->unit != 0x13) { /* If not inches */ | 237 | } else { |
193 | return 0; | 238 | return 0; |
194 | } | 239 | } |
195 | } else if (code == ABS_RX || code == ABS_RY || code == ABS_RZ) { | 240 | } else if (code == ABS_RX || code == ABS_RY || code == ABS_RZ) { |
@@ -835,8 +880,8 @@ int hidinput_connect(struct hid_device *hid, unsigned int force) | |||
835 | hid->ll_driver->hidinput_input_event; | 880 | hid->ll_driver->hidinput_input_event; |
836 | input_dev->open = hidinput_open; | 881 | input_dev->open = hidinput_open; |
837 | input_dev->close = hidinput_close; | 882 | input_dev->close = hidinput_close; |
838 | input_dev->setkeycode = hidinput_setkeycode; | 883 | input_dev->setkeycode_new = hidinput_setkeycode; |
839 | input_dev->getkeycode = hidinput_getkeycode; | 884 | input_dev->getkeycode_new = hidinput_getkeycode; |
840 | 885 | ||
841 | input_dev->name = hid->name; | 886 | input_dev->name = hid->name; |
842 | input_dev->phys = hid->phys; | 887 | input_dev->phys = hid->phys; |