summaryrefslogtreecommitdiff
path: root/usr/src/dkms_source_tree/hid-input.c
diff options
context:
space:
mode:
authorHenrik Rydberg <rydberg@euromail.se>2010-12-14 18:44:36 +0100
committerHenrik Rydberg <rydberg@euromail.se>2010-12-14 18:44:36 +0100
commit9305526d84391e7f3752119c9c9bbfa9433745a2 (patch)
tree4bd5fdc9142fb87c203d9fc1b388c1d9b572faed /usr/src/dkms_source_tree/hid-input.c
parent164aff3db49c55476492de9d9aa7fb9637868b98 (diff)
upgrade to natty (2.6.37-9)
Diffstat (limited to 'usr/src/dkms_source_tree/hid-input.c')
-rw-r--r--usr/src/dkms_source_tree/hid-input.c216
1 files changed, 174 insertions, 42 deletions
diff --git a/usr/src/dkms_source_tree/hid-input.c b/usr/src/dkms_source_tree/hid-input.c
index 9d97934..d8d372b 100644
--- a/usr/src/dkms_source_tree/hid-input.c
+++ b/usr/src/dkms_source_tree/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
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 /*
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; 86static 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
92typedef bool (*hid_usage_cmp_t)(struct hid_usage *usage,
93 unsigned int cur_idx, unsigned int val);
94
87static struct hid_usage *hidinput_find_key(struct hid_device *hid, 95static 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
124static 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
111static int hidinput_getkeycode(struct input_dev *dev, 141static 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
125static int hidinput_setkeycode(struct input_dev *dev, 162static 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 }
@@ -149,6 +191,86 @@ static int hidinput_setkeycode(struct input_dev *dev,
149} 191}
150 192
151 193
194/**
195 * hidinput_calc_abs_res - calculate an absolute axis resolution
196 * @field: the HID report field to calculate resolution for
197 * @code: axis code
198 *
199 * The formula is:
200 * (logical_maximum - logical_minimum)
201 * resolution = ----------------------------------------------------------
202 * (physical_maximum - physical_minimum) * 10 ^ unit_exponent
203 *
204 * as seen in the HID specification v1.11 6.2.2.7 Global Items.
205 *
206 * Only exponent 1 length units are processed. Centimeters and inches are
207 * converted to millimeters. Degrees are converted to radians.
208 */
209static __s32 hidinput_calc_abs_res(const struct hid_field *field, __u16 code)
210{
211 __s32 unit_exponent = field->unit_exponent;
212 __s32 logical_extents = field->logical_maximum -
213 field->logical_minimum;
214 __s32 physical_extents = field->physical_maximum -
215 field->physical_minimum;
216 __s32 prev;
217
218 /* Check if the extents are sane */
219 if (logical_extents <= 0 || physical_extents <= 0)
220 return 0;
221
222 /*
223 * Verify and convert units.
224 * See HID specification v1.11 6.2.2.7 Global Items for unit decoding
225 */
226 if (code == ABS_X || code == ABS_Y || code == ABS_Z) {
227 if (field->unit == 0x11) { /* If centimeters */
228 /* Convert to millimeters */
229 unit_exponent += 1;
230 } else if (field->unit == 0x13) { /* If inches */
231 /* Convert to millimeters */
232 prev = physical_extents;
233 physical_extents *= 254;
234 if (physical_extents < prev)
235 return 0;
236 unit_exponent -= 1;
237 } else {
238 return 0;
239 }
240 } else if (code == ABS_RX || code == ABS_RY || code == ABS_RZ) {
241 if (field->unit == 0x14) { /* If degrees */
242 /* Convert to radians */
243 prev = logical_extents;
244 logical_extents *= 573;
245 if (logical_extents < prev)
246 return 0;
247 unit_exponent += 1;
248 } else if (field->unit != 0x12) { /* If not radians */
249 return 0;
250 }
251 } else {
252 return 0;
253 }
254
255 /* Apply negative unit exponent */
256 for (; unit_exponent < 0; unit_exponent++) {
257 prev = logical_extents;
258 logical_extents *= 10;
259 if (logical_extents < prev)
260 return 0;
261 }
262 /* Apply positive unit exponent */
263 for (; unit_exponent > 0; unit_exponent--) {
264 prev = physical_extents;
265 physical_extents *= 10;
266 if (physical_extents < prev)
267 return 0;
268 }
269
270 /* Calculate resolution */
271 return logical_extents / physical_extents;
272}
273
152static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_field *field, 274static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_field *field,
153 struct hid_usage *usage) 275 struct hid_usage *usage)
154{ 276{
@@ -199,11 +321,11 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
199 case HID_GD_MOUSE: 321 case HID_GD_MOUSE:
200 case HID_GD_POINTER: code += 0x110; break; 322 case HID_GD_POINTER: code += 0x110; break;
201 case HID_GD_JOYSTICK: 323 case HID_GD_JOYSTICK:
202 if (code <= 0xf) 324 if (code <= 0xf)
203 code += BTN_JOYSTICK; 325 code += BTN_JOYSTICK;
204 else 326 else
205 code += BTN_TRIGGER_HAPPY; 327 code += BTN_TRIGGER_HAPPY;
206 break; 328 break;
207 case HID_GD_GAMEPAD: code += 0x130; break; 329 case HID_GD_GAMEPAD: code += 0x130; break;
208 default: 330 default:
209 switch (field->physical) { 331 switch (field->physical) {
@@ -301,6 +423,9 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
301 423
302 case HID_UP_DIGITIZER: 424 case HID_UP_DIGITIZER:
303 switch (usage->hid & 0xff) { 425 switch (usage->hid & 0xff) {
426 case 0x00: /* Undefined */
427 goto ignore;
428
304 case 0x30: /* TipPressure */ 429 case 0x30: /* TipPressure */
305 if (!test_bit(BTN_TOUCH, input->keybit)) { 430 if (!test_bit(BTN_TOUCH, input->keybit)) {
306 device->quirks |= HID_QUIRK_NOTOUCH; 431 device->quirks |= HID_QUIRK_NOTOUCH;
@@ -333,6 +458,10 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
333 map_key_clear(BTN_STYLUS); 458 map_key_clear(BTN_STYLUS);
334 break; 459 break;
335 460
461 case 0x46: /* TabletPick */
462 map_key_clear(BTN_STYLUS2);
463 break;
464
336 default: goto unknown; 465 default: goto unknown;
337 } 466 }
338 break; 467 break;
@@ -480,7 +609,7 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
480 609
481 case HID_UP_LOGIVENDOR: 610 case HID_UP_LOGIVENDOR:
482 goto ignore; 611 goto ignore;
483 612
484 case HID_UP_PID: 613 case HID_UP_PID:
485 switch (usage->hid & HID_USAGE) { 614 switch (usage->hid & HID_USAGE) {
486 case 0xa4: map_key_clear(BTN_DEAD); break; 615 case 0xa4: map_key_clear(BTN_DEAD); break;
@@ -534,6 +663,9 @@ mapped:
534 input_set_abs_params(input, usage->code, a, b, (b - a) >> 8, (b - a) >> 4); 663 input_set_abs_params(input, usage->code, a, b, (b - a) >> 8, (b - a) >> 4);
535 else input_set_abs_params(input, usage->code, a, b, 0, 0); 664 else input_set_abs_params(input, usage->code, a, b, 0, 0);
536 665
666 input_abs_set_res(input, usage->code,
667 hidinput_calc_abs_res(field, usage->code));
668
537 /* use a larger default input buffer for MT devices */ 669 /* use a larger default input buffer for MT devices */
538 if (usage->code == ABS_MT_POSITION_X && input->hint_events_per_packet == 0) 670 if (usage->code == ABS_MT_POSITION_X && input->hint_events_per_packet == 0)
539 input_set_events_per_packet(input, 60); 671 input_set_events_per_packet(input, 60);
@@ -589,9 +721,9 @@ void hidinput_hid_event(struct hid_device *hid, struct hid_field *field, struct
589 hat_dir = (value - usage->hat_min) * 8 / (usage->hat_max - usage->hat_min + 1) + 1; 721 hat_dir = (value - usage->hat_min) * 8 / (usage->hat_max - usage->hat_min + 1) + 1;
590 if (hat_dir < 0 || hat_dir > 8) hat_dir = 0; 722 if (hat_dir < 0 || hat_dir > 8) hat_dir = 0;
591 input_event(input, usage->type, usage->code , hid_hat_to_axis[hat_dir].x); 723 input_event(input, usage->type, usage->code , hid_hat_to_axis[hat_dir].x);
592 input_event(input, usage->type, usage->code + 1, hid_hat_to_axis[hat_dir].y); 724 input_event(input, usage->type, usage->code + 1, hid_hat_to_axis[hat_dir].y);
593 return; 725 return;
594 } 726 }
595 727
596 if (usage->hid == (HID_UP_DIGITIZER | 0x003c)) { /* Invert */ 728 if (usage->hid == (HID_UP_DIGITIZER | 0x003c)) { /* Invert */
597 *quirks = value ? (*quirks | HID_QUIRK_INVERT) : (*quirks & ~HID_QUIRK_INVERT); 729 *quirks = value ? (*quirks | HID_QUIRK_INVERT) : (*quirks & ~HID_QUIRK_INVERT);
@@ -748,8 +880,8 @@ int hidinput_connect(struct hid_device *hid, unsigned int force)
748 hid->ll_driver->hidinput_input_event; 880 hid->ll_driver->hidinput_input_event;
749 input_dev->open = hidinput_open; 881 input_dev->open = hidinput_open;
750 input_dev->close = hidinput_close; 882 input_dev->close = hidinput_close;
751 input_dev->setkeycode = hidinput_setkeycode; 883 input_dev->setkeycode_new = hidinput_setkeycode;
752 input_dev->getkeycode = hidinput_getkeycode; 884 input_dev->getkeycode_new = hidinput_getkeycode;
753 885
754 input_dev->name = hid->name; 886 input_dev->name = hid->name;
755 input_dev->phys = hid->phys; 887 input_dev->phys = hid->phys;