Loading Documentation/input/multi-touch-protocol.rst +6 −6 Original line number Original line Diff line number Diff line Loading @@ -310,12 +310,12 @@ ABS_MT_TOOL_Y ABS_MT_TOOL_TYPE ABS_MT_TOOL_TYPE The type of approaching tool. A lot of kernel drivers cannot distinguish The type of approaching tool. A lot of kernel drivers cannot distinguish between different tool types, such as a finger or a pen. In such cases, the between different tool types, such as a finger or a pen. In such cases, the event should be omitted. The protocol currently supports MT_TOOL_FINGER, event should be omitted. The protocol currently mainly supports MT_TOOL_PEN, and MT_TOOL_PALM [#f2]_. For type B devices, this event is MT_TOOL_FINGER, MT_TOOL_PEN, and MT_TOOL_PALM [#f2]_. handled by input core; drivers should instead use For type B devices, this event is handled by input core; drivers should input_mt_report_slot_state(). A contact's ABS_MT_TOOL_TYPE may change over instead use input_mt_report_slot_state(). A contact's ABS_MT_TOOL_TYPE may time while still touching the device, because the firmware may not be able change over time while still touching the device, because the firmware may to determine which tool is being used when it first appears. not be able to determine which tool is being used when it first appears. ABS_MT_BLOB_ID ABS_MT_BLOB_ID The BLOB_ID groups several packets together into one arbitrarily shaped The BLOB_ID groups several packets together into one arbitrarily shaped Loading drivers/hid/hid-core.c +14 −3 Original line number Original line Diff line number Diff line Loading @@ -128,9 +128,19 @@ static int open_collection(struct hid_parser *parser, unsigned type) usage = parser->local.usage[0]; usage = parser->local.usage[0]; if (parser->collection_stack_ptr == HID_COLLECTION_STACK_SIZE) { if (parser->collection_stack_ptr == parser->collection_stack_size) { hid_err(parser->device, "collection stack overflow\n"); unsigned int *collection_stack; return -EINVAL; unsigned int new_size = parser->collection_stack_size + HID_COLLECTION_STACK_SIZE; collection_stack = krealloc(parser->collection_stack, new_size * sizeof(unsigned int), GFP_KERNEL); if (!collection_stack) return -ENOMEM; parser->collection_stack = collection_stack; parser->collection_stack_size = new_size; } } if (parser->device->maxcollection == parser->device->collection_size) { if (parser->device->maxcollection == parser->device->collection_size) { Loading Loading @@ -840,6 +850,7 @@ static int hid_scan_report(struct hid_device *hid) break; break; } } kfree(parser->collection_stack); vfree(parser); vfree(parser); return 0; return 0; } } Loading drivers/hid/hid-input.c +3 −0 Original line number Original line Diff line number Diff line Loading @@ -1550,6 +1550,9 @@ static struct hid_input *hidinput_allocate(struct hid_device *hid, case HID_GD_WIRELESS_RADIO_CTLS: case HID_GD_WIRELESS_RADIO_CTLS: suffix = "Wireless Radio Control"; suffix = "Wireless Radio Control"; break; break; case HID_GD_SYSTEM_MULTIAXIS: suffix = "System Multi Axis"; break; default: default: break; break; } } Loading drivers/hid/hid-microsoft.c +43 −6 Original line number Original line Diff line number Diff line Loading @@ -22,12 +22,13 @@ #include "hid-ids.h" #include "hid-ids.h" #define MS_HIDINPUT 0x01 #define MS_HIDINPUT BIT(0) #define MS_ERGONOMY 0x02 #define MS_ERGONOMY BIT(1) #define MS_PRESENTER 0x04 #define MS_PRESENTER BIT(2) #define MS_RDESC 0x08 #define MS_RDESC BIT(3) #define MS_NOGET 0x10 #define MS_NOGET BIT(4) #define MS_DUPLICATE_USAGES 0x20 #define MS_DUPLICATE_USAGES BIT(5) #define MS_SURFACE_DIAL BIT(6) static __u8 *ms_report_fixup(struct hid_device *hdev, __u8 *rdesc, static __u8 *ms_report_fixup(struct hid_device *hdev, __u8 *rdesc, unsigned int *rsize) unsigned int *rsize) Loading Loading @@ -130,6 +131,30 @@ static int ms_presenter_8k_quirk(struct hid_input *hi, struct hid_usage *usage, return 1; return 1; } } static int ms_surface_dial_quirk(struct hid_input *hi, struct hid_field *field, struct hid_usage *usage, unsigned long **bit, int *max) { switch (usage->hid & HID_USAGE_PAGE) { case 0xff070000: /* fall-through */ case HID_UP_DIGITIZER: /* ignore those axis */ return -1; case HID_UP_GENDESK: switch (usage->hid) { case HID_GD_X: /* fall-through */ case HID_GD_Y: /* fall-through */ case HID_GD_RFKILL_BTN: /* ignore those axis */ return -1; } } return 0; } static int ms_input_mapping(struct hid_device *hdev, struct hid_input *hi, static int ms_input_mapping(struct hid_device *hdev, struct hid_input *hi, struct hid_field *field, struct hid_usage *usage, struct hid_field *field, struct hid_usage *usage, unsigned long **bit, int *max) unsigned long **bit, int *max) Loading @@ -146,6 +171,13 @@ static int ms_input_mapping(struct hid_device *hdev, struct hid_input *hi, ms_presenter_8k_quirk(hi, usage, bit, max)) ms_presenter_8k_quirk(hi, usage, bit, max)) return 1; return 1; if (quirks & MS_SURFACE_DIAL) { int ret = ms_surface_dial_quirk(hi, field, usage, bit, max); if (ret) return ret; } return 0; return 0; } } Loading Loading @@ -229,6 +261,9 @@ static int ms_probe(struct hid_device *hdev, const struct hid_device_id *id) if (quirks & MS_NOGET) if (quirks & MS_NOGET) hdev->quirks |= HID_QUIRK_NOGET; hdev->quirks |= HID_QUIRK_NOGET; if (quirks & MS_SURFACE_DIAL) hdev->quirks |= HID_QUIRK_INPUT_PER_APP; ret = hid_parse(hdev); ret = hid_parse(hdev); if (ret) { if (ret) { hid_err(hdev, "parse failed\n"); hid_err(hdev, "parse failed\n"); Loading Loading @@ -281,6 +316,8 @@ static const struct hid_device_id ms_devices[] = { { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_BT), { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_BT), .driver_data = MS_PRESENTER }, .driver_data = MS_PRESENTER }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, 0x091B), .driver_data = MS_SURFACE_DIAL }, { } { } }; }; MODULE_DEVICE_TABLE(hid, ms_devices); MODULE_DEVICE_TABLE(hid, ms_devices); Loading Loading
Documentation/input/multi-touch-protocol.rst +6 −6 Original line number Original line Diff line number Diff line Loading @@ -310,12 +310,12 @@ ABS_MT_TOOL_Y ABS_MT_TOOL_TYPE ABS_MT_TOOL_TYPE The type of approaching tool. A lot of kernel drivers cannot distinguish The type of approaching tool. A lot of kernel drivers cannot distinguish between different tool types, such as a finger or a pen. In such cases, the between different tool types, such as a finger or a pen. In such cases, the event should be omitted. The protocol currently supports MT_TOOL_FINGER, event should be omitted. The protocol currently mainly supports MT_TOOL_PEN, and MT_TOOL_PALM [#f2]_. For type B devices, this event is MT_TOOL_FINGER, MT_TOOL_PEN, and MT_TOOL_PALM [#f2]_. handled by input core; drivers should instead use For type B devices, this event is handled by input core; drivers should input_mt_report_slot_state(). A contact's ABS_MT_TOOL_TYPE may change over instead use input_mt_report_slot_state(). A contact's ABS_MT_TOOL_TYPE may time while still touching the device, because the firmware may not be able change over time while still touching the device, because the firmware may to determine which tool is being used when it first appears. not be able to determine which tool is being used when it first appears. ABS_MT_BLOB_ID ABS_MT_BLOB_ID The BLOB_ID groups several packets together into one arbitrarily shaped The BLOB_ID groups several packets together into one arbitrarily shaped Loading
drivers/hid/hid-core.c +14 −3 Original line number Original line Diff line number Diff line Loading @@ -128,9 +128,19 @@ static int open_collection(struct hid_parser *parser, unsigned type) usage = parser->local.usage[0]; usage = parser->local.usage[0]; if (parser->collection_stack_ptr == HID_COLLECTION_STACK_SIZE) { if (parser->collection_stack_ptr == parser->collection_stack_size) { hid_err(parser->device, "collection stack overflow\n"); unsigned int *collection_stack; return -EINVAL; unsigned int new_size = parser->collection_stack_size + HID_COLLECTION_STACK_SIZE; collection_stack = krealloc(parser->collection_stack, new_size * sizeof(unsigned int), GFP_KERNEL); if (!collection_stack) return -ENOMEM; parser->collection_stack = collection_stack; parser->collection_stack_size = new_size; } } if (parser->device->maxcollection == parser->device->collection_size) { if (parser->device->maxcollection == parser->device->collection_size) { Loading Loading @@ -840,6 +850,7 @@ static int hid_scan_report(struct hid_device *hid) break; break; } } kfree(parser->collection_stack); vfree(parser); vfree(parser); return 0; return 0; } } Loading
drivers/hid/hid-input.c +3 −0 Original line number Original line Diff line number Diff line Loading @@ -1550,6 +1550,9 @@ static struct hid_input *hidinput_allocate(struct hid_device *hid, case HID_GD_WIRELESS_RADIO_CTLS: case HID_GD_WIRELESS_RADIO_CTLS: suffix = "Wireless Radio Control"; suffix = "Wireless Radio Control"; break; break; case HID_GD_SYSTEM_MULTIAXIS: suffix = "System Multi Axis"; break; default: default: break; break; } } Loading
drivers/hid/hid-microsoft.c +43 −6 Original line number Original line Diff line number Diff line Loading @@ -22,12 +22,13 @@ #include "hid-ids.h" #include "hid-ids.h" #define MS_HIDINPUT 0x01 #define MS_HIDINPUT BIT(0) #define MS_ERGONOMY 0x02 #define MS_ERGONOMY BIT(1) #define MS_PRESENTER 0x04 #define MS_PRESENTER BIT(2) #define MS_RDESC 0x08 #define MS_RDESC BIT(3) #define MS_NOGET 0x10 #define MS_NOGET BIT(4) #define MS_DUPLICATE_USAGES 0x20 #define MS_DUPLICATE_USAGES BIT(5) #define MS_SURFACE_DIAL BIT(6) static __u8 *ms_report_fixup(struct hid_device *hdev, __u8 *rdesc, static __u8 *ms_report_fixup(struct hid_device *hdev, __u8 *rdesc, unsigned int *rsize) unsigned int *rsize) Loading Loading @@ -130,6 +131,30 @@ static int ms_presenter_8k_quirk(struct hid_input *hi, struct hid_usage *usage, return 1; return 1; } } static int ms_surface_dial_quirk(struct hid_input *hi, struct hid_field *field, struct hid_usage *usage, unsigned long **bit, int *max) { switch (usage->hid & HID_USAGE_PAGE) { case 0xff070000: /* fall-through */ case HID_UP_DIGITIZER: /* ignore those axis */ return -1; case HID_UP_GENDESK: switch (usage->hid) { case HID_GD_X: /* fall-through */ case HID_GD_Y: /* fall-through */ case HID_GD_RFKILL_BTN: /* ignore those axis */ return -1; } } return 0; } static int ms_input_mapping(struct hid_device *hdev, struct hid_input *hi, static int ms_input_mapping(struct hid_device *hdev, struct hid_input *hi, struct hid_field *field, struct hid_usage *usage, struct hid_field *field, struct hid_usage *usage, unsigned long **bit, int *max) unsigned long **bit, int *max) Loading @@ -146,6 +171,13 @@ static int ms_input_mapping(struct hid_device *hdev, struct hid_input *hi, ms_presenter_8k_quirk(hi, usage, bit, max)) ms_presenter_8k_quirk(hi, usage, bit, max)) return 1; return 1; if (quirks & MS_SURFACE_DIAL) { int ret = ms_surface_dial_quirk(hi, field, usage, bit, max); if (ret) return ret; } return 0; return 0; } } Loading Loading @@ -229,6 +261,9 @@ static int ms_probe(struct hid_device *hdev, const struct hid_device_id *id) if (quirks & MS_NOGET) if (quirks & MS_NOGET) hdev->quirks |= HID_QUIRK_NOGET; hdev->quirks |= HID_QUIRK_NOGET; if (quirks & MS_SURFACE_DIAL) hdev->quirks |= HID_QUIRK_INPUT_PER_APP; ret = hid_parse(hdev); ret = hid_parse(hdev); if (ret) { if (ret) { hid_err(hdev, "parse failed\n"); hid_err(hdev, "parse failed\n"); Loading Loading @@ -281,6 +316,8 @@ static const struct hid_device_id ms_devices[] = { { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_BT), { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_BT), .driver_data = MS_PRESENTER }, .driver_data = MS_PRESENTER }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, 0x091B), .driver_data = MS_SURFACE_DIAL }, { } { } }; }; MODULE_DEVICE_TABLE(hid, ms_devices); MODULE_DEVICE_TABLE(hid, ms_devices); Loading