diff options
| author | Henrik Rydberg <rydberg@euromail.se> | 2010-12-14 18:44:36 +0100 |
|---|---|---|
| committer | Henrik Rydberg <rydberg@euromail.se> | 2010-12-14 18:44:36 +0100 |
| commit | 9305526d84391e7f3752119c9c9bbfa9433745a2 (patch) | |
| tree | 4bd5fdc9142fb87c203d9fc1b388c1d9b572faed /usr/src/dkms_source_tree/hid-input.c | |
| parent | 164aff3db49c55476492de9d9aa7fb9637868b98 (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.c | 216 |
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 | ||
| 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 | } |
| @@ -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 | */ | ||
| 209 | static __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 | |||
| 152 | static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_field *field, | 274 | static 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; |
