Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid
Pull HID fixes from Jiri Kosina: - Wacom driver functional and regression fixes from Jason Gerecke - race condition fix in usbhid, found by syzbot and fixed by Alan Stern - a few device-specific quirks and ID additions * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid: HID: quirks: Add HID_QUIRK_NO_INIT_REPORTS quirk for Dell K12A keyboard-dock HID: mcp2221: add gpiolib dependency HID: i2c-hid: reset Synaptics SYNA2393 on resume HID: wacom: Report 2nd-gen Intuos Pro S center button status over BT HID: usbhid: Fix race between usbhid_close() and usbhid_stop() Revert "HID: wacom: generic: read the number of expected touches on a per collection basis" HID: alps: ALPS_1657 is too specific; use U1_UNICORN_LEGACY instead HID: alps: Add AUI1657 device ID HID: logitech: Add support for Logitech G11 extra keys HID: multitouch: add eGalaxTouch P80H84 support HID: wacom: Read HID_DG_CONTACTMAX directly for non-generic devices
This commit is contained in:
Коммит
47cf1b422e
|
@ -1155,6 +1155,7 @@ config HID_ALPS
|
|||
config HID_MCP2221
|
||||
tristate "Microchip MCP2221 HID USB-to-I2C/SMbus host support"
|
||||
depends on USB_HID && I2C
|
||||
depends on GPIOLIB
|
||||
---help---
|
||||
Provides I2C and SMBUS host adapter functionality over USB-HID
|
||||
through MCP2221 device.
|
||||
|
|
|
@ -802,6 +802,7 @@ static int alps_probe(struct hid_device *hdev, const struct hid_device_id *id)
|
|||
break;
|
||||
case HID_DEVICE_ID_ALPS_U1_DUAL:
|
||||
case HID_DEVICE_ID_ALPS_U1:
|
||||
case HID_DEVICE_ID_ALPS_U1_UNICORN_LEGACY:
|
||||
data->dev_type = U1;
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -79,10 +79,10 @@
|
|||
#define HID_DEVICE_ID_ALPS_U1_DUAL_PTP 0x121F
|
||||
#define HID_DEVICE_ID_ALPS_U1_DUAL_3BTN_PTP 0x1220
|
||||
#define HID_DEVICE_ID_ALPS_U1 0x1215
|
||||
#define HID_DEVICE_ID_ALPS_U1_UNICORN_LEGACY 0x121E
|
||||
#define HID_DEVICE_ID_ALPS_T4_BTNLESS 0x120C
|
||||
#define HID_DEVICE_ID_ALPS_1222 0x1222
|
||||
|
||||
|
||||
#define USB_VENDOR_ID_AMI 0x046b
|
||||
#define USB_DEVICE_ID_AMI_VIRT_KEYBOARD_AND_MOUSE 0xff10
|
||||
|
||||
|
@ -385,6 +385,7 @@
|
|||
#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7349 0x7349
|
||||
#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_73F7 0x73f7
|
||||
#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_A001 0xa001
|
||||
#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_C002 0xc002
|
||||
|
||||
#define USB_VENDOR_ID_ELAN 0x04f3
|
||||
#define USB_DEVICE_ID_TOSHIBA_CLICK_L9W 0x0401
|
||||
|
@ -759,6 +760,7 @@
|
|||
#define USB_DEVICE_ID_LOGITECH_RUMBLEPAD2 0xc218
|
||||
#define USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_2 0xc219
|
||||
#define USB_DEVICE_ID_LOGITECH_G15_LCD 0xc222
|
||||
#define USB_DEVICE_ID_LOGITECH_G11 0xc225
|
||||
#define USB_DEVICE_ID_LOGITECH_G15_V2_LCD 0xc227
|
||||
#define USB_DEVICE_ID_LOGITECH_G510 0xc22d
|
||||
#define USB_DEVICE_ID_LOGITECH_G510_USB_AUDIO 0xc22e
|
||||
|
@ -1097,6 +1099,9 @@
|
|||
#define USB_DEVICE_ID_SYMBOL_SCANNER_2 0x1300
|
||||
#define USB_DEVICE_ID_SYMBOL_SCANNER_3 0x1200
|
||||
|
||||
#define I2C_VENDOR_ID_SYNAPTICS 0x06cb
|
||||
#define I2C_PRODUCT_ID_SYNAPTICS_SYNA2393 0x7a13
|
||||
|
||||
#define USB_VENDOR_ID_SYNAPTICS 0x06cb
|
||||
#define USB_DEVICE_ID_SYNAPTICS_TP 0x0001
|
||||
#define USB_DEVICE_ID_SYNAPTICS_INT_TP 0x0002
|
||||
|
@ -1111,6 +1116,7 @@
|
|||
#define USB_DEVICE_ID_SYNAPTICS_LTS2 0x1d10
|
||||
#define USB_DEVICE_ID_SYNAPTICS_HD 0x0ac3
|
||||
#define USB_DEVICE_ID_SYNAPTICS_QUAD_HD 0x1ac3
|
||||
#define USB_DEVICE_ID_SYNAPTICS_DELL_K12A 0x2819
|
||||
#define USB_DEVICE_ID_SYNAPTICS_ACER_SWITCH5_012 0x2968
|
||||
#define USB_DEVICE_ID_SYNAPTICS_TP_V103 0x5710
|
||||
#define USB_DEVICE_ID_SYNAPTICS_ACER_SWITCH5 0x81a7
|
||||
|
|
|
@ -872,6 +872,10 @@ error_hw_stop:
|
|||
}
|
||||
|
||||
static const struct hid_device_id lg_g15_devices[] = {
|
||||
/* The G11 is a G15 without the LCD, treat it as a G15 */
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
|
||||
USB_DEVICE_ID_LOGITECH_G11),
|
||||
.driver_data = LG_G15 },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
|
||||
USB_DEVICE_ID_LOGITECH_G15_LCD),
|
||||
.driver_data = LG_G15 },
|
||||
|
|
|
@ -1922,6 +1922,9 @@ static const struct hid_device_id mt_devices[] = {
|
|||
{ .driver_data = MT_CLS_EGALAX_SERIAL,
|
||||
MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
|
||||
USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_A001) },
|
||||
{ .driver_data = MT_CLS_EGALAX,
|
||||
MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
|
||||
USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_C002) },
|
||||
|
||||
/* Elitegroup panel */
|
||||
{ .driver_data = MT_CLS_SERIAL,
|
||||
|
|
|
@ -163,6 +163,7 @@ static const struct hid_device_id hid_quirks[] = {
|
|||
{ HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_LTS2), HID_QUIRK_NO_INIT_REPORTS },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_QUAD_HD), HID_QUIRK_NO_INIT_REPORTS },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_TP_V103), HID_QUIRK_NO_INIT_REPORTS },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_SYNAPTICS, USB_DEVICE_ID_SYNAPTICS_DELL_K12A), HID_QUIRK_NO_INIT_REPORTS },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_TOPMAX, USB_DEVICE_ID_TOPMAX_COBRAPAD), HID_QUIRK_BADPAD },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_TOUCHPACK, USB_DEVICE_ID_TOUCHPACK_RTS), HID_QUIRK_MULTI_INPUT },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_TPV, USB_DEVICE_ID_TPV_OPTICAL_TOUCHSCREEN_8882), HID_QUIRK_NOGET },
|
||||
|
|
|
@ -177,6 +177,8 @@ static const struct i2c_hid_quirks {
|
|||
I2C_HID_QUIRK_BOGUS_IRQ },
|
||||
{ USB_VENDOR_ID_ALPS_JP, HID_ANY_ID,
|
||||
I2C_HID_QUIRK_RESET_ON_RESUME },
|
||||
{ I2C_VENDOR_ID_SYNAPTICS, I2C_PRODUCT_ID_SYNAPTICS_SYNA2393,
|
||||
I2C_HID_QUIRK_RESET_ON_RESUME },
|
||||
{ USB_VENDOR_ID_ITE, I2C_DEVICE_ID_ITE_LENOVO_LEGION_Y720,
|
||||
I2C_HID_QUIRK_BAD_INPUT_SIZE },
|
||||
{ 0, 0 }
|
||||
|
|
|
@ -682,16 +682,21 @@ static int usbhid_open(struct hid_device *hid)
|
|||
struct usbhid_device *usbhid = hid->driver_data;
|
||||
int res;
|
||||
|
||||
mutex_lock(&usbhid->mutex);
|
||||
|
||||
set_bit(HID_OPENED, &usbhid->iofl);
|
||||
|
||||
if (hid->quirks & HID_QUIRK_ALWAYS_POLL)
|
||||
return 0;
|
||||
if (hid->quirks & HID_QUIRK_ALWAYS_POLL) {
|
||||
res = 0;
|
||||
goto Done;
|
||||
}
|
||||
|
||||
res = usb_autopm_get_interface(usbhid->intf);
|
||||
/* the device must be awake to reliably request remote wakeup */
|
||||
if (res < 0) {
|
||||
clear_bit(HID_OPENED, &usbhid->iofl);
|
||||
return -EIO;
|
||||
res = -EIO;
|
||||
goto Done;
|
||||
}
|
||||
|
||||
usbhid->intf->needs_remote_wakeup = 1;
|
||||
|
@ -725,6 +730,9 @@ static int usbhid_open(struct hid_device *hid)
|
|||
msleep(50);
|
||||
|
||||
clear_bit(HID_RESUME_RUNNING, &usbhid->iofl);
|
||||
|
||||
Done:
|
||||
mutex_unlock(&usbhid->mutex);
|
||||
return res;
|
||||
}
|
||||
|
||||
|
@ -732,6 +740,8 @@ static void usbhid_close(struct hid_device *hid)
|
|||
{
|
||||
struct usbhid_device *usbhid = hid->driver_data;
|
||||
|
||||
mutex_lock(&usbhid->mutex);
|
||||
|
||||
/*
|
||||
* Make sure we don't restart data acquisition due to
|
||||
* a resumption we no longer care about by avoiding racing
|
||||
|
@ -743,12 +753,13 @@ static void usbhid_close(struct hid_device *hid)
|
|||
clear_bit(HID_IN_POLLING, &usbhid->iofl);
|
||||
spin_unlock_irq(&usbhid->lock);
|
||||
|
||||
if (hid->quirks & HID_QUIRK_ALWAYS_POLL)
|
||||
return;
|
||||
if (!(hid->quirks & HID_QUIRK_ALWAYS_POLL)) {
|
||||
hid_cancel_delayed_stuff(usbhid);
|
||||
usb_kill_urb(usbhid->urbin);
|
||||
usbhid->intf->needs_remote_wakeup = 0;
|
||||
}
|
||||
|
||||
hid_cancel_delayed_stuff(usbhid);
|
||||
usb_kill_urb(usbhid->urbin);
|
||||
usbhid->intf->needs_remote_wakeup = 0;
|
||||
mutex_unlock(&usbhid->mutex);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1057,6 +1068,8 @@ static int usbhid_start(struct hid_device *hid)
|
|||
unsigned int n, insize = 0;
|
||||
int ret;
|
||||
|
||||
mutex_lock(&usbhid->mutex);
|
||||
|
||||
clear_bit(HID_DISCONNECTED, &usbhid->iofl);
|
||||
|
||||
usbhid->bufsize = HID_MIN_BUFFER_SIZE;
|
||||
|
@ -1177,6 +1190,8 @@ static int usbhid_start(struct hid_device *hid)
|
|||
usbhid_set_leds(hid);
|
||||
device_set_wakeup_enable(&dev->dev, 1);
|
||||
}
|
||||
|
||||
mutex_unlock(&usbhid->mutex);
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
|
@ -1187,6 +1202,7 @@ fail:
|
|||
usbhid->urbout = NULL;
|
||||
usbhid->urbctrl = NULL;
|
||||
hid_free_buffers(dev, hid);
|
||||
mutex_unlock(&usbhid->mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1202,6 +1218,8 @@ static void usbhid_stop(struct hid_device *hid)
|
|||
usbhid->intf->needs_remote_wakeup = 0;
|
||||
}
|
||||
|
||||
mutex_lock(&usbhid->mutex);
|
||||
|
||||
clear_bit(HID_STARTED, &usbhid->iofl);
|
||||
spin_lock_irq(&usbhid->lock); /* Sync with error and led handlers */
|
||||
set_bit(HID_DISCONNECTED, &usbhid->iofl);
|
||||
|
@ -1222,6 +1240,8 @@ static void usbhid_stop(struct hid_device *hid)
|
|||
usbhid->urbout = NULL;
|
||||
|
||||
hid_free_buffers(hid_to_usb_dev(hid), hid);
|
||||
|
||||
mutex_unlock(&usbhid->mutex);
|
||||
}
|
||||
|
||||
static int usbhid_power(struct hid_device *hid, int lvl)
|
||||
|
@ -1382,6 +1402,7 @@ static int usbhid_probe(struct usb_interface *intf, const struct usb_device_id *
|
|||
INIT_WORK(&usbhid->reset_work, hid_reset);
|
||||
timer_setup(&usbhid->io_retry, hid_retry_timeout, 0);
|
||||
spin_lock_init(&usbhid->lock);
|
||||
mutex_init(&usbhid->mutex);
|
||||
|
||||
ret = hid_add_device(hid);
|
||||
if (ret) {
|
||||
|
|
|
@ -80,6 +80,7 @@ struct usbhid_device {
|
|||
dma_addr_t outbuf_dma; /* Output buffer dma */
|
||||
unsigned long last_out; /* record of last output for timeouts */
|
||||
|
||||
struct mutex mutex; /* start/stop/open/close */
|
||||
spinlock_t lock; /* fifo spinlock */
|
||||
unsigned long iofl; /* I/O flags (CTRL_RUNNING, OUT_RUNNING) */
|
||||
struct timer_list io_retry; /* Retry timer */
|
||||
|
|
|
@ -319,9 +319,11 @@ static void wacom_feature_mapping(struct hid_device *hdev,
|
|||
data[0] = field->report->id;
|
||||
ret = wacom_get_report(hdev, HID_FEATURE_REPORT,
|
||||
data, n, WAC_CMD_RETRIES);
|
||||
if (ret == n) {
|
||||
if (ret == n && features->type == HID_GENERIC) {
|
||||
ret = hid_report_raw_event(hdev,
|
||||
HID_FEATURE_REPORT, data, n, 0);
|
||||
} else if (ret == 2 && features->type != HID_GENERIC) {
|
||||
features->touch_max = data[1];
|
||||
} else {
|
||||
features->touch_max = 16;
|
||||
hid_warn(hdev, "wacom_feature_mapping: "
|
||||
|
|
|
@ -1427,11 +1427,13 @@ static void wacom_intuos_pro2_bt_pad(struct wacom_wac *wacom)
|
|||
{
|
||||
struct input_dev *pad_input = wacom->pad_input;
|
||||
unsigned char *data = wacom->data;
|
||||
int nbuttons = wacom->features.numbered_buttons;
|
||||
|
||||
int buttons = data[282] | ((data[281] & 0x40) << 2);
|
||||
int expresskeys = data[282];
|
||||
int center = (data[281] & 0x40) >> 6;
|
||||
int ring = data[285] & 0x7F;
|
||||
bool ringstatus = data[285] & 0x80;
|
||||
bool prox = buttons || ringstatus;
|
||||
bool prox = expresskeys || center || ringstatus;
|
||||
|
||||
/* Fix touchring data: userspace expects 0 at left and increasing clockwise */
|
||||
ring = 71 - ring;
|
||||
|
@ -1439,7 +1441,8 @@ static void wacom_intuos_pro2_bt_pad(struct wacom_wac *wacom)
|
|||
if (ring > 71)
|
||||
ring -= 72;
|
||||
|
||||
wacom_report_numbered_buttons(pad_input, 9, buttons);
|
||||
wacom_report_numbered_buttons(pad_input, nbuttons,
|
||||
expresskeys | (center << (nbuttons - 1)));
|
||||
|
||||
input_report_abs(pad_input, ABS_WHEEL, ringstatus ? ring : 0);
|
||||
|
||||
|
@ -2637,9 +2640,25 @@ static void wacom_wac_finger_pre_report(struct hid_device *hdev,
|
|||
case HID_DG_TIPSWITCH:
|
||||
hid_data->last_slot_field = equivalent_usage;
|
||||
break;
|
||||
case HID_DG_CONTACTCOUNT:
|
||||
hid_data->cc_report = report->id;
|
||||
hid_data->cc_index = i;
|
||||
hid_data->cc_value_index = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (hid_data->cc_report != 0 &&
|
||||
hid_data->cc_index >= 0) {
|
||||
struct hid_field *field = report->field[hid_data->cc_index];
|
||||
int value = field->value[hid_data->cc_value_index];
|
||||
if (value)
|
||||
hid_data->num_expected = value;
|
||||
}
|
||||
else {
|
||||
hid_data->num_expected = wacom_wac->features.touch_max;
|
||||
}
|
||||
}
|
||||
|
||||
static void wacom_wac_finger_report(struct hid_device *hdev,
|
||||
|
@ -2649,7 +2668,6 @@ static void wacom_wac_finger_report(struct hid_device *hdev,
|
|||
struct wacom_wac *wacom_wac = &wacom->wacom_wac;
|
||||
struct input_dev *input = wacom_wac->touch_input;
|
||||
unsigned touch_max = wacom_wac->features.touch_max;
|
||||
struct hid_data *hid_data = &wacom_wac->hid_data;
|
||||
|
||||
/* If more packets of data are expected, give us a chance to
|
||||
* process them rather than immediately syncing a partial
|
||||
|
@ -2663,7 +2681,6 @@ static void wacom_wac_finger_report(struct hid_device *hdev,
|
|||
|
||||
input_sync(input);
|
||||
wacom_wac->hid_data.num_received = 0;
|
||||
hid_data->num_expected = 0;
|
||||
|
||||
/* keep touch state for pen event */
|
||||
wacom_wac->shared->touch_down = wacom_wac_finger_count_touches(wacom_wac);
|
||||
|
@ -2738,73 +2755,12 @@ static void wacom_report_events(struct hid_device *hdev,
|
|||
}
|
||||
}
|
||||
|
||||
static void wacom_set_num_expected(struct hid_device *hdev,
|
||||
struct hid_report *report,
|
||||
int collection_index,
|
||||
struct hid_field *field,
|
||||
int field_index)
|
||||
{
|
||||
struct wacom *wacom = hid_get_drvdata(hdev);
|
||||
struct wacom_wac *wacom_wac = &wacom->wacom_wac;
|
||||
struct hid_data *hid_data = &wacom_wac->hid_data;
|
||||
unsigned int original_collection_level =
|
||||
hdev->collection[collection_index].level;
|
||||
bool end_collection = false;
|
||||
int i;
|
||||
|
||||
if (hid_data->num_expected)
|
||||
return;
|
||||
|
||||
// find the contact count value for this segment
|
||||
for (i = field_index; i < report->maxfield && !end_collection; i++) {
|
||||
struct hid_field *field = report->field[i];
|
||||
unsigned int field_level =
|
||||
hdev->collection[field->usage[0].collection_index].level;
|
||||
unsigned int j;
|
||||
|
||||
if (field_level != original_collection_level)
|
||||
continue;
|
||||
|
||||
for (j = 0; j < field->maxusage; j++) {
|
||||
struct hid_usage *usage = &field->usage[j];
|
||||
|
||||
if (usage->collection_index != collection_index) {
|
||||
end_collection = true;
|
||||
break;
|
||||
}
|
||||
if (wacom_equivalent_usage(usage->hid) == HID_DG_CONTACTCOUNT) {
|
||||
hid_data->cc_report = report->id;
|
||||
hid_data->cc_index = i;
|
||||
hid_data->cc_value_index = j;
|
||||
|
||||
if (hid_data->cc_report != 0 &&
|
||||
hid_data->cc_index >= 0) {
|
||||
|
||||
struct hid_field *field =
|
||||
report->field[hid_data->cc_index];
|
||||
int value =
|
||||
field->value[hid_data->cc_value_index];
|
||||
|
||||
if (value)
|
||||
hid_data->num_expected = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (hid_data->cc_report == 0 || hid_data->cc_index < 0)
|
||||
hid_data->num_expected = wacom_wac->features.touch_max;
|
||||
}
|
||||
|
||||
static int wacom_wac_collection(struct hid_device *hdev, struct hid_report *report,
|
||||
int collection_index, struct hid_field *field,
|
||||
int field_index)
|
||||
{
|
||||
struct wacom *wacom = hid_get_drvdata(hdev);
|
||||
|
||||
if (WACOM_FINGER_FIELD(field))
|
||||
wacom_set_num_expected(hdev, report, collection_index, field,
|
||||
field_index);
|
||||
wacom_report_events(hdev, report, collection_index, field_index);
|
||||
|
||||
/*
|
||||
|
|
Загрузка…
Ссылка в новой задаче