diff options
| author | Benjamin Tissoires <benjamin.tissoires@redhat.com> | 2013-08-22 08:51:08 -0400 |
|---|---|---|
| committer | Jiri Kosina <jkosina@suse.cz> | 2013-08-27 04:00:00 -0400 |
| commit | f961bd3516e4f699bbacff5d7f5247d6d87c59f0 (patch) | |
| tree | ecc8cb61c11e00419a8fed6f277517c4f8aed711 | |
| parent | 3dc8fc083dbfeede7b63a0c07581192e97711365 (diff) | |
HID: detect Win 8 multitouch devices in core
Detecting Win 8 multitouch devices in core allows us to set quirks
before the device is parsed through hid_hw_start().
It also simplifies the detection of those devices in hid-multitouch and
makes the handling of those devices cleaner.
As Win 8 multitouch panels are in the group multitouch and rely on a
special feature to be detected, this patch adds a bitfield in the parser.
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Reviewed-by: Henrik Rydberg <rydberg@euromail.se>
Tested-by: Srinivas Pandruvada<srinivas.pandruvada@linux.intel.com>
Signed-off-by: Jiri Kosina <jkosina@suse.cz>
| -rw-r--r-- | drivers/hid/hid-core.c | 16 | ||||
| -rw-r--r-- | drivers/hid/hid-multitouch.c | 24 | ||||
| -rw-r--r-- | include/linux/hid.h | 4 |
3 files changed, 31 insertions, 13 deletions
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index ddd95f3e33c0..660dce964162 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c | |||
| @@ -685,6 +685,13 @@ static void hid_scan_input_usage(struct hid_parser *parser, u32 usage) | |||
| 685 | hid->group = HID_GROUP_MULTITOUCH; | 685 | hid->group = HID_GROUP_MULTITOUCH; |
| 686 | } | 686 | } |
| 687 | 687 | ||
| 688 | static void hid_scan_feature_usage(struct hid_parser *parser, u32 usage) | ||
| 689 | { | ||
| 690 | if (usage == 0xff0000c5 && parser->global.report_count == 256 && | ||
| 691 | parser->global.report_size == 8) | ||
| 692 | parser->scan_flags |= HID_SCAN_FLAG_MT_WIN_8; | ||
| 693 | } | ||
| 694 | |||
| 688 | static void hid_scan_collection(struct hid_parser *parser, unsigned type) | 695 | static void hid_scan_collection(struct hid_parser *parser, unsigned type) |
| 689 | { | 696 | { |
| 690 | struct hid_device *hid = parser->device; | 697 | struct hid_device *hid = parser->device; |
| @@ -714,6 +721,8 @@ static int hid_scan_main(struct hid_parser *parser, struct hid_item *item) | |||
| 714 | case HID_MAIN_ITEM_TAG_OUTPUT: | 721 | case HID_MAIN_ITEM_TAG_OUTPUT: |
| 715 | break; | 722 | break; |
| 716 | case HID_MAIN_ITEM_TAG_FEATURE: | 723 | case HID_MAIN_ITEM_TAG_FEATURE: |
| 724 | for (i = 0; i < parser->local.usage_index; i++) | ||
| 725 | hid_scan_feature_usage(parser, parser->local.usage[i]); | ||
| 717 | break; | 726 | break; |
| 718 | } | 727 | } |
| 719 | 728 | ||
| @@ -757,6 +766,13 @@ static int hid_scan_report(struct hid_device *hid) | |||
| 757 | while ((start = fetch_item(start, end, &item)) != NULL) | 766 | while ((start = fetch_item(start, end, &item)) != NULL) |
| 758 | dispatch_type[item.type](parser, &item); | 767 | dispatch_type[item.type](parser, &item); |
| 759 | 768 | ||
| 769 | /* | ||
| 770 | * Handle special flags set during scanning. | ||
| 771 | */ | ||
| 772 | if ((parser->scan_flags & HID_SCAN_FLAG_MT_WIN_8) && | ||
| 773 | (hid->group == HID_GROUP_MULTITOUCH)) | ||
| 774 | hid->group = HID_GROUP_MULTITOUCH_WIN_8; | ||
| 775 | |||
| 760 | vfree(parser); | 776 | vfree(parser); |
| 761 | return 0; | 777 | return 0; |
| 762 | } | 778 | } |
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index 0fe00e2552f2..c28ef86c7c67 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c | |||
| @@ -133,6 +133,7 @@ static void mt_post_parse(struct mt_device *td); | |||
| 133 | #define MT_CLS_NSMU 0x000a | 133 | #define MT_CLS_NSMU 0x000a |
| 134 | #define MT_CLS_DUAL_CONTACT_NUMBER 0x0010 | 134 | #define MT_CLS_DUAL_CONTACT_NUMBER 0x0010 |
| 135 | #define MT_CLS_DUAL_CONTACT_ID 0x0011 | 135 | #define MT_CLS_DUAL_CONTACT_ID 0x0011 |
| 136 | #define MT_CLS_WIN_8 0x0012 | ||
| 136 | 137 | ||
| 137 | /* vendor specific classes */ | 138 | /* vendor specific classes */ |
| 138 | #define MT_CLS_3M 0x0101 | 139 | #define MT_CLS_3M 0x0101 |
| @@ -205,6 +206,11 @@ static struct mt_class mt_classes[] = { | |||
| 205 | MT_QUIRK_CONTACT_CNT_ACCURATE | | 206 | MT_QUIRK_CONTACT_CNT_ACCURATE | |
| 206 | MT_QUIRK_SLOT_IS_CONTACTID, | 207 | MT_QUIRK_SLOT_IS_CONTACTID, |
| 207 | .maxcontacts = 2 }, | 208 | .maxcontacts = 2 }, |
| 209 | { .name = MT_CLS_WIN_8, | ||
| 210 | .quirks = MT_QUIRK_ALWAYS_VALID | | ||
| 211 | MT_QUIRK_IGNORE_DUPLICATES | | ||
| 212 | MT_QUIRK_HOVERING | | ||
| 213 | MT_QUIRK_CONTACT_CNT_ACCURATE }, | ||
| 208 | 214 | ||
| 209 | /* | 215 | /* |
| 210 | * vendor specific classes | 216 | * vendor specific classes |
| @@ -332,19 +338,6 @@ static void mt_feature_mapping(struct hid_device *hdev, | |||
| 332 | td->maxcontacts = td->mtclass.maxcontacts; | 338 | td->maxcontacts = td->mtclass.maxcontacts; |
| 333 | 339 | ||
| 334 | break; | 340 | break; |
| 335 | case 0xff0000c5: | ||
| 336 | if (field->report_count == 256 && field->report_size == 8) { | ||
| 337 | /* Win 8 devices need special quirks */ | ||
| 338 | __s32 *quirks = &td->mtclass.quirks; | ||
| 339 | *quirks |= MT_QUIRK_ALWAYS_VALID; | ||
| 340 | *quirks |= MT_QUIRK_IGNORE_DUPLICATES; | ||
| 341 | *quirks |= MT_QUIRK_HOVERING; | ||
| 342 | *quirks |= MT_QUIRK_CONTACT_CNT_ACCURATE; | ||
| 343 | *quirks &= ~MT_QUIRK_NOT_SEEN_MEANS_UP; | ||
| 344 | *quirks &= ~MT_QUIRK_VALID_IS_INRANGE; | ||
| 345 | *quirks &= ~MT_QUIRK_VALID_IS_CONFIDENCE; | ||
| 346 | } | ||
| 347 | break; | ||
| 348 | } | 341 | } |
| 349 | } | 342 | } |
| 350 | 343 | ||
| @@ -1346,6 +1339,11 @@ static const struct hid_device_id mt_devices[] = { | |||
| 1346 | 1339 | ||
| 1347 | /* Generic MT device */ | 1340 | /* Generic MT device */ |
| 1348 | { HID_DEVICE(HID_BUS_ANY, HID_GROUP_MULTITOUCH, HID_ANY_ID, HID_ANY_ID) }, | 1341 | { HID_DEVICE(HID_BUS_ANY, HID_GROUP_MULTITOUCH, HID_ANY_ID, HID_ANY_ID) }, |
| 1342 | |||
| 1343 | /* Generic Win 8 certified MT device */ | ||
| 1344 | { .driver_data = MT_CLS_WIN_8, | ||
| 1345 | HID_DEVICE(HID_BUS_ANY, HID_GROUP_MULTITOUCH_WIN_8, | ||
| 1346 | HID_ANY_ID, HID_ANY_ID) }, | ||
| 1349 | { } | 1347 | { } |
| 1350 | }; | 1348 | }; |
| 1351 | MODULE_DEVICE_TABLE(hid, mt_devices); | 1349 | MODULE_DEVICE_TABLE(hid, mt_devices); |
diff --git a/include/linux/hid.h b/include/linux/hid.h index 0c48991b0402..cef1e9b86cc4 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h | |||
| @@ -295,6 +295,7 @@ struct hid_item { | |||
| 295 | #define HID_GROUP_GENERIC 0x0001 | 295 | #define HID_GROUP_GENERIC 0x0001 |
| 296 | #define HID_GROUP_MULTITOUCH 0x0002 | 296 | #define HID_GROUP_MULTITOUCH 0x0002 |
| 297 | #define HID_GROUP_SENSOR_HUB 0x0003 | 297 | #define HID_GROUP_SENSOR_HUB 0x0003 |
| 298 | #define HID_GROUP_MULTITOUCH_WIN_8 0x0004 | ||
| 298 | 299 | ||
| 299 | /* | 300 | /* |
| 300 | * This is the global environment of the parser. This information is | 301 | * This is the global environment of the parser. This information is |
| @@ -532,6 +533,8 @@ static inline void hid_set_drvdata(struct hid_device *hdev, void *data) | |||
| 532 | #define HID_GLOBAL_STACK_SIZE 4 | 533 | #define HID_GLOBAL_STACK_SIZE 4 |
| 533 | #define HID_COLLECTION_STACK_SIZE 4 | 534 | #define HID_COLLECTION_STACK_SIZE 4 |
| 534 | 535 | ||
| 536 | #define HID_SCAN_FLAG_MT_WIN_8 0x00000001 | ||
| 537 | |||
| 535 | struct hid_parser { | 538 | struct hid_parser { |
| 536 | struct hid_global global; | 539 | struct hid_global global; |
| 537 | struct hid_global global_stack[HID_GLOBAL_STACK_SIZE]; | 540 | struct hid_global global_stack[HID_GLOBAL_STACK_SIZE]; |
| @@ -540,6 +543,7 @@ struct hid_parser { | |||
| 540 | unsigned collection_stack[HID_COLLECTION_STACK_SIZE]; | 543 | unsigned collection_stack[HID_COLLECTION_STACK_SIZE]; |
| 541 | unsigned collection_stack_ptr; | 544 | unsigned collection_stack_ptr; |
| 542 | struct hid_device *device; | 545 | struct hid_device *device; |
| 546 | unsigned scan_flags; | ||
| 543 | }; | 547 | }; |
| 544 | 548 | ||
| 545 | struct hid_class_descriptor { | 549 | struct hid_class_descriptor { |
