Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid
Pull HID fixes from Jiri Kosina: - data sanitization and validtion fixes for report descriptor parser from Marc Zyngier - memory leak fix for hid-elan driver from Dinghao Liu - two device-specific quirks * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid: HID: core: Sanitize event code and type when mapping input HID: core: Correctly handle ReportSize being zero HID: elan: Fix memleak in elan_input_configured HID: microsoft: Add rumble support for the 8bitdo SN30 Pro+ controller HID: quirks: Set INCREMENT_USAGE_ON_DUPLICATE for all Saitek X52 devices
This commit is contained in:
commit
fc3abb5325
@ -1597,6 +1597,17 @@ static void hid_output_field(const struct hid_device *hid,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Compute the size of a report.
|
||||||
|
*/
|
||||||
|
static size_t hid_compute_report_size(struct hid_report *report)
|
||||||
|
{
|
||||||
|
if (report->size)
|
||||||
|
return ((report->size - 1) >> 3) + 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Create a report. 'data' has to be allocated using
|
* Create a report. 'data' has to be allocated using
|
||||||
* hid_alloc_report_buf() so that it has proper size.
|
* hid_alloc_report_buf() so that it has proper size.
|
||||||
@ -1609,7 +1620,7 @@ void hid_output_report(struct hid_report *report, __u8 *data)
|
|||||||
if (report->id > 0)
|
if (report->id > 0)
|
||||||
*data++ = report->id;
|
*data++ = report->id;
|
||||||
|
|
||||||
memset(data, 0, ((report->size - 1) >> 3) + 1);
|
memset(data, 0, hid_compute_report_size(report));
|
||||||
for (n = 0; n < report->maxfield; n++)
|
for (n = 0; n < report->maxfield; n++)
|
||||||
hid_output_field(report->device, report->field[n], data);
|
hid_output_field(report->device, report->field[n], data);
|
||||||
}
|
}
|
||||||
@ -1739,7 +1750,7 @@ int hid_report_raw_event(struct hid_device *hid, int type, u8 *data, u32 size,
|
|||||||
csize--;
|
csize--;
|
||||||
}
|
}
|
||||||
|
|
||||||
rsize = ((report->size - 1) >> 3) + 1;
|
rsize = hid_compute_report_size(report);
|
||||||
|
|
||||||
if (report_enum->numbered && rsize >= HID_MAX_BUFFER_SIZE)
|
if (report_enum->numbered && rsize >= HID_MAX_BUFFER_SIZE)
|
||||||
rsize = HID_MAX_BUFFER_SIZE - 1;
|
rsize = HID_MAX_BUFFER_SIZE - 1;
|
||||||
|
@ -188,6 +188,7 @@ static int elan_input_configured(struct hid_device *hdev, struct hid_input *hi)
|
|||||||
ret = input_mt_init_slots(input, ELAN_MAX_FINGERS, INPUT_MT_POINTER);
|
ret = input_mt_init_slots(input, ELAN_MAX_FINGERS, INPUT_MT_POINTER);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
hid_err(hdev, "Failed to init elan MT slots: %d\n", ret);
|
hid_err(hdev, "Failed to init elan MT slots: %d\n", ret);
|
||||||
|
input_free_device(input);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -198,6 +199,7 @@ static int elan_input_configured(struct hid_device *hdev, struct hid_input *hi)
|
|||||||
if (ret) {
|
if (ret) {
|
||||||
hid_err(hdev, "Failed to register elan input device: %d\n",
|
hid_err(hdev, "Failed to register elan input device: %d\n",
|
||||||
ret);
|
ret);
|
||||||
|
input_mt_destroy_slots(input);
|
||||||
input_free_device(input);
|
input_free_device(input);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -850,6 +850,7 @@
|
|||||||
#define USB_DEVICE_ID_MS_POWER_COVER 0x07da
|
#define USB_DEVICE_ID_MS_POWER_COVER 0x07da
|
||||||
#define USB_DEVICE_ID_MS_XBOX_ONE_S_CONTROLLER 0x02fd
|
#define USB_DEVICE_ID_MS_XBOX_ONE_S_CONTROLLER 0x02fd
|
||||||
#define USB_DEVICE_ID_MS_PIXART_MOUSE 0x00cb
|
#define USB_DEVICE_ID_MS_PIXART_MOUSE 0x00cb
|
||||||
|
#define USB_DEVICE_ID_8BITDO_SN30_PRO_PLUS 0x02e0
|
||||||
|
|
||||||
#define USB_VENDOR_ID_MOJO 0x8282
|
#define USB_VENDOR_ID_MOJO 0x8282
|
||||||
#define USB_DEVICE_ID_RETRO_ADAPTER 0x3201
|
#define USB_DEVICE_ID_RETRO_ADAPTER 0x3201
|
||||||
@ -1015,6 +1016,8 @@
|
|||||||
#define USB_DEVICE_ID_SAITEK_RAT9 0x0cfa
|
#define USB_DEVICE_ID_SAITEK_RAT9 0x0cfa
|
||||||
#define USB_DEVICE_ID_SAITEK_MMO7 0x0cd0
|
#define USB_DEVICE_ID_SAITEK_MMO7 0x0cd0
|
||||||
#define USB_DEVICE_ID_SAITEK_X52 0x075c
|
#define USB_DEVICE_ID_SAITEK_X52 0x075c
|
||||||
|
#define USB_DEVICE_ID_SAITEK_X52_2 0x0255
|
||||||
|
#define USB_DEVICE_ID_SAITEK_X52_PRO 0x0762
|
||||||
|
|
||||||
#define USB_VENDOR_ID_SAMSUNG 0x0419
|
#define USB_VENDOR_ID_SAMSUNG 0x0419
|
||||||
#define USB_DEVICE_ID_SAMSUNG_IR_REMOTE 0x0001
|
#define USB_DEVICE_ID_SAMSUNG_IR_REMOTE 0x0001
|
||||||
|
@ -1132,6 +1132,10 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel
|
|||||||
}
|
}
|
||||||
|
|
||||||
mapped:
|
mapped:
|
||||||
|
/* Mapping failed, bail out */
|
||||||
|
if (!bit)
|
||||||
|
return;
|
||||||
|
|
||||||
if (device->driver->input_mapped &&
|
if (device->driver->input_mapped &&
|
||||||
device->driver->input_mapped(device, hidinput, field, usage,
|
device->driver->input_mapped(device, hidinput, field, usage,
|
||||||
&bit, &max) < 0) {
|
&bit, &max) < 0) {
|
||||||
|
@ -448,6 +448,8 @@ static const struct hid_device_id ms_devices[] = {
|
|||||||
.driver_data = MS_SURFACE_DIAL },
|
.driver_data = MS_SURFACE_DIAL },
|
||||||
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_XBOX_ONE_S_CONTROLLER),
|
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_XBOX_ONE_S_CONTROLLER),
|
||||||
.driver_data = MS_QUIRK_FF },
|
.driver_data = MS_QUIRK_FF },
|
||||||
|
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_8BITDO_SN30_PRO_PLUS),
|
||||||
|
.driver_data = MS_QUIRK_FF },
|
||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(hid, ms_devices);
|
MODULE_DEVICE_TABLE(hid, ms_devices);
|
||||||
|
@ -856,6 +856,8 @@ static int mt_touch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
|
|||||||
code = BTN_0 + ((usage->hid - 1) & HID_USAGE);
|
code = BTN_0 + ((usage->hid - 1) & HID_USAGE);
|
||||||
|
|
||||||
hid_map_usage(hi, usage, bit, max, EV_KEY, code);
|
hid_map_usage(hi, usage, bit, max, EV_KEY, code);
|
||||||
|
if (!*bit)
|
||||||
|
return -1;
|
||||||
input_set_capability(hi->input, EV_KEY, code);
|
input_set_capability(hi->input, EV_KEY, code);
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
|
@ -150,6 +150,8 @@ static const struct hid_device_id hid_quirks[] = {
|
|||||||
{ HID_USB_DEVICE(USB_VENDOR_ID_RETROUSB, USB_DEVICE_ID_RETROUSB_SNES_RETROPORT), HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE },
|
{ HID_USB_DEVICE(USB_VENDOR_ID_RETROUSB, USB_DEVICE_ID_RETROUSB_SNES_RETROPORT), HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE },
|
||||||
{ HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RUMBLEPAD), HID_QUIRK_BADPAD },
|
{ HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RUMBLEPAD), HID_QUIRK_BADPAD },
|
||||||
{ HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_X52), HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE },
|
{ HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_X52), HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE },
|
||||||
|
{ HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_X52_2), HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE },
|
||||||
|
{ HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_X52_PRO), HID_QUIRK_INCREMENT_USAGE_ON_DUPLICATE },
|
||||||
{ HID_USB_DEVICE(USB_VENDOR_ID_SEMICO, USB_DEVICE_ID_SEMICO_USB_KEYKOARD2), HID_QUIRK_NO_INIT_REPORTS },
|
{ HID_USB_DEVICE(USB_VENDOR_ID_SEMICO, USB_DEVICE_ID_SEMICO_USB_KEYKOARD2), HID_QUIRK_NO_INIT_REPORTS },
|
||||||
{ HID_USB_DEVICE(USB_VENDOR_ID_SEMICO, USB_DEVICE_ID_SEMICO_USB_KEYKOARD), HID_QUIRK_NO_INIT_REPORTS },
|
{ HID_USB_DEVICE(USB_VENDOR_ID_SEMICO, USB_DEVICE_ID_SEMICO_USB_KEYKOARD), HID_QUIRK_NO_INIT_REPORTS },
|
||||||
{ HID_USB_DEVICE(USB_VENDOR_ID_SENNHEISER, USB_DEVICE_ID_SENNHEISER_BTD500USB), HID_QUIRK_NOGET },
|
{ HID_USB_DEVICE(USB_VENDOR_ID_SENNHEISER, USB_DEVICE_ID_SENNHEISER_BTD500USB), HID_QUIRK_NOGET },
|
||||||
|
@ -959,34 +959,49 @@ static inline void hid_device_io_stop(struct hid_device *hid) {
|
|||||||
* @max: maximal valid usage->code to consider later (out parameter)
|
* @max: maximal valid usage->code to consider later (out parameter)
|
||||||
* @type: input event type (EV_KEY, EV_REL, ...)
|
* @type: input event type (EV_KEY, EV_REL, ...)
|
||||||
* @c: code which corresponds to this usage and type
|
* @c: code which corresponds to this usage and type
|
||||||
|
*
|
||||||
|
* The value pointed to by @bit will be set to NULL if either @type is
|
||||||
|
* an unhandled event type, or if @c is out of range for @type. This
|
||||||
|
* can be used as an error condition.
|
||||||
*/
|
*/
|
||||||
static inline void hid_map_usage(struct hid_input *hidinput,
|
static inline void hid_map_usage(struct hid_input *hidinput,
|
||||||
struct hid_usage *usage, unsigned long **bit, int *max,
|
struct hid_usage *usage, unsigned long **bit, int *max,
|
||||||
__u8 type, __u16 c)
|
__u8 type, unsigned int c)
|
||||||
{
|
{
|
||||||
struct input_dev *input = hidinput->input;
|
struct input_dev *input = hidinput->input;
|
||||||
|
unsigned long *bmap = NULL;
|
||||||
usage->type = type;
|
unsigned int limit = 0;
|
||||||
usage->code = c;
|
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case EV_ABS:
|
case EV_ABS:
|
||||||
*bit = input->absbit;
|
bmap = input->absbit;
|
||||||
*max = ABS_MAX;
|
limit = ABS_MAX;
|
||||||
break;
|
break;
|
||||||
case EV_REL:
|
case EV_REL:
|
||||||
*bit = input->relbit;
|
bmap = input->relbit;
|
||||||
*max = REL_MAX;
|
limit = REL_MAX;
|
||||||
break;
|
break;
|
||||||
case EV_KEY:
|
case EV_KEY:
|
||||||
*bit = input->keybit;
|
bmap = input->keybit;
|
||||||
*max = KEY_MAX;
|
limit = KEY_MAX;
|
||||||
break;
|
break;
|
||||||
case EV_LED:
|
case EV_LED:
|
||||||
*bit = input->ledbit;
|
bmap = input->ledbit;
|
||||||
*max = LED_MAX;
|
limit = LED_MAX;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (unlikely(c > limit || !bmap)) {
|
||||||
|
pr_warn_ratelimited("%s: Invalid code %d type %d\n",
|
||||||
|
input->name, c, type);
|
||||||
|
*bit = NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
usage->type = type;
|
||||||
|
usage->code = c;
|
||||||
|
*max = limit;
|
||||||
|
*bit = bmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1000,7 +1015,8 @@ static inline void hid_map_usage_clear(struct hid_input *hidinput,
|
|||||||
__u8 type, __u16 c)
|
__u8 type, __u16 c)
|
||||||
{
|
{
|
||||||
hid_map_usage(hidinput, usage, bit, max, type, c);
|
hid_map_usage(hidinput, usage, bit, max, type, c);
|
||||||
clear_bit(c, *bit);
|
if (*bit)
|
||||||
|
clear_bit(usage->code, *bit);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user