Commit 47cf1b42 authored by Linus Torvalds's avatar Linus Torvalds

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
parents 9851a0de 1e189f26
...@@ -1155,6 +1155,7 @@ config HID_ALPS ...@@ -1155,6 +1155,7 @@ config HID_ALPS
config HID_MCP2221 config HID_MCP2221
tristate "Microchip MCP2221 HID USB-to-I2C/SMbus host support" tristate "Microchip MCP2221 HID USB-to-I2C/SMbus host support"
depends on USB_HID && I2C depends on USB_HID && I2C
depends on GPIOLIB
---help--- ---help---
Provides I2C and SMBUS host adapter functionality over USB-HID Provides I2C and SMBUS host adapter functionality over USB-HID
through MCP2221 device. through MCP2221 device.
......
...@@ -802,6 +802,7 @@ static int alps_probe(struct hid_device *hdev, const struct hid_device_id *id) ...@@ -802,6 +802,7 @@ static int alps_probe(struct hid_device *hdev, const struct hid_device_id *id)
break; break;
case HID_DEVICE_ID_ALPS_U1_DUAL: case HID_DEVICE_ID_ALPS_U1_DUAL:
case HID_DEVICE_ID_ALPS_U1: case HID_DEVICE_ID_ALPS_U1:
case HID_DEVICE_ID_ALPS_U1_UNICORN_LEGACY:
data->dev_type = U1; data->dev_type = U1;
break; break;
default: default:
......
...@@ -79,10 +79,10 @@ ...@@ -79,10 +79,10 @@
#define HID_DEVICE_ID_ALPS_U1_DUAL_PTP 0x121F #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_DUAL_3BTN_PTP 0x1220
#define HID_DEVICE_ID_ALPS_U1 0x1215 #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_T4_BTNLESS 0x120C
#define HID_DEVICE_ID_ALPS_1222 0x1222 #define HID_DEVICE_ID_ALPS_1222 0x1222
#define USB_VENDOR_ID_AMI 0x046b #define USB_VENDOR_ID_AMI 0x046b
#define USB_DEVICE_ID_AMI_VIRT_KEYBOARD_AND_MOUSE 0xff10 #define USB_DEVICE_ID_AMI_VIRT_KEYBOARD_AND_MOUSE 0xff10
...@@ -385,6 +385,7 @@ ...@@ -385,6 +385,7 @@
#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_7349 0x7349 #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_73F7 0x73f7
#define USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_A001 0xa001 #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_VENDOR_ID_ELAN 0x04f3
#define USB_DEVICE_ID_TOSHIBA_CLICK_L9W 0x0401 #define USB_DEVICE_ID_TOSHIBA_CLICK_L9W 0x0401
...@@ -759,6 +760,7 @@ ...@@ -759,6 +760,7 @@
#define USB_DEVICE_ID_LOGITECH_RUMBLEPAD2 0xc218 #define USB_DEVICE_ID_LOGITECH_RUMBLEPAD2 0xc218
#define USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_2 0xc219 #define USB_DEVICE_ID_LOGITECH_RUMBLEPAD2_2 0xc219
#define USB_DEVICE_ID_LOGITECH_G15_LCD 0xc222 #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_G15_V2_LCD 0xc227
#define USB_DEVICE_ID_LOGITECH_G510 0xc22d #define USB_DEVICE_ID_LOGITECH_G510 0xc22d
#define USB_DEVICE_ID_LOGITECH_G510_USB_AUDIO 0xc22e #define USB_DEVICE_ID_LOGITECH_G510_USB_AUDIO 0xc22e
...@@ -1097,6 +1099,9 @@ ...@@ -1097,6 +1099,9 @@
#define USB_DEVICE_ID_SYMBOL_SCANNER_2 0x1300 #define USB_DEVICE_ID_SYMBOL_SCANNER_2 0x1300
#define USB_DEVICE_ID_SYMBOL_SCANNER_3 0x1200 #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_VENDOR_ID_SYNAPTICS 0x06cb
#define USB_DEVICE_ID_SYNAPTICS_TP 0x0001 #define USB_DEVICE_ID_SYNAPTICS_TP 0x0001
#define USB_DEVICE_ID_SYNAPTICS_INT_TP 0x0002 #define USB_DEVICE_ID_SYNAPTICS_INT_TP 0x0002
...@@ -1111,6 +1116,7 @@ ...@@ -1111,6 +1116,7 @@
#define USB_DEVICE_ID_SYNAPTICS_LTS2 0x1d10 #define USB_DEVICE_ID_SYNAPTICS_LTS2 0x1d10
#define USB_DEVICE_ID_SYNAPTICS_HD 0x0ac3 #define USB_DEVICE_ID_SYNAPTICS_HD 0x0ac3
#define USB_DEVICE_ID_SYNAPTICS_QUAD_HD 0x1ac3 #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_ACER_SWITCH5_012 0x2968
#define USB_DEVICE_ID_SYNAPTICS_TP_V103 0x5710 #define USB_DEVICE_ID_SYNAPTICS_TP_V103 0x5710
#define USB_DEVICE_ID_SYNAPTICS_ACER_SWITCH5 0x81a7 #define USB_DEVICE_ID_SYNAPTICS_ACER_SWITCH5 0x81a7
......
...@@ -872,6 +872,10 @@ static int lg_g15_probe(struct hid_device *hdev, const struct hid_device_id *id) ...@@ -872,6 +872,10 @@ static int lg_g15_probe(struct hid_device *hdev, const struct hid_device_id *id)
} }
static const struct hid_device_id lg_g15_devices[] = { 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, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH,
USB_DEVICE_ID_LOGITECH_G15_LCD), USB_DEVICE_ID_LOGITECH_G15_LCD),
.driver_data = LG_G15 }, .driver_data = LG_G15 },
......
...@@ -1922,6 +1922,9 @@ static const struct hid_device_id mt_devices[] = { ...@@ -1922,6 +1922,9 @@ static const struct hid_device_id mt_devices[] = {
{ .driver_data = MT_CLS_EGALAX_SERIAL, { .driver_data = MT_CLS_EGALAX_SERIAL,
MT_USB_DEVICE(USB_VENDOR_ID_DWAV, MT_USB_DEVICE(USB_VENDOR_ID_DWAV,
USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH_A001) }, 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 */ /* Elitegroup panel */
{ .driver_data = MT_CLS_SERIAL, { .driver_data = MT_CLS_SERIAL,
......
...@@ -163,6 +163,7 @@ static const struct hid_device_id hid_quirks[] = { ...@@ -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_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_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_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_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_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 }, { 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 { ...@@ -177,6 +177,8 @@ static const struct i2c_hid_quirks {
I2C_HID_QUIRK_BOGUS_IRQ }, I2C_HID_QUIRK_BOGUS_IRQ },
{ USB_VENDOR_ID_ALPS_JP, HID_ANY_ID, { USB_VENDOR_ID_ALPS_JP, HID_ANY_ID,
I2C_HID_QUIRK_RESET_ON_RESUME }, 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, { USB_VENDOR_ID_ITE, I2C_DEVICE_ID_ITE_LENOVO_LEGION_Y720,
I2C_HID_QUIRK_BAD_INPUT_SIZE }, I2C_HID_QUIRK_BAD_INPUT_SIZE },
{ 0, 0 } { 0, 0 }
......
...@@ -682,16 +682,21 @@ static int usbhid_open(struct hid_device *hid) ...@@ -682,16 +682,21 @@ static int usbhid_open(struct hid_device *hid)
struct usbhid_device *usbhid = hid->driver_data; struct usbhid_device *usbhid = hid->driver_data;
int res; int res;
mutex_lock(&usbhid->mutex);
set_bit(HID_OPENED, &usbhid->iofl); set_bit(HID_OPENED, &usbhid->iofl);
if (hid->quirks & HID_QUIRK_ALWAYS_POLL) if (hid->quirks & HID_QUIRK_ALWAYS_POLL) {
return 0; res = 0;
goto Done;
}
res = usb_autopm_get_interface(usbhid->intf); res = usb_autopm_get_interface(usbhid->intf);
/* the device must be awake to reliably request remote wakeup */ /* the device must be awake to reliably request remote wakeup */
if (res < 0) { if (res < 0) {
clear_bit(HID_OPENED, &usbhid->iofl); clear_bit(HID_OPENED, &usbhid->iofl);
return -EIO; res = -EIO;
goto Done;
} }
usbhid->intf->needs_remote_wakeup = 1; usbhid->intf->needs_remote_wakeup = 1;
...@@ -725,6 +730,9 @@ static int usbhid_open(struct hid_device *hid) ...@@ -725,6 +730,9 @@ static int usbhid_open(struct hid_device *hid)
msleep(50); msleep(50);
clear_bit(HID_RESUME_RUNNING, &usbhid->iofl); clear_bit(HID_RESUME_RUNNING, &usbhid->iofl);
Done:
mutex_unlock(&usbhid->mutex);
return res; return res;
} }
...@@ -732,6 +740,8 @@ static void usbhid_close(struct hid_device *hid) ...@@ -732,6 +740,8 @@ static void usbhid_close(struct hid_device *hid)
{ {
struct usbhid_device *usbhid = hid->driver_data; struct usbhid_device *usbhid = hid->driver_data;
mutex_lock(&usbhid->mutex);
/* /*
* Make sure we don't restart data acquisition due to * Make sure we don't restart data acquisition due to
* a resumption we no longer care about by avoiding racing * a resumption we no longer care about by avoiding racing
...@@ -743,12 +753,13 @@ static void usbhid_close(struct hid_device *hid) ...@@ -743,12 +753,13 @@ static void usbhid_close(struct hid_device *hid)
clear_bit(HID_IN_POLLING, &usbhid->iofl); clear_bit(HID_IN_POLLING, &usbhid->iofl);
spin_unlock_irq(&usbhid->lock); spin_unlock_irq(&usbhid->lock);
if (hid->quirks & HID_QUIRK_ALWAYS_POLL) if (!(hid->quirks & HID_QUIRK_ALWAYS_POLL)) {
return; hid_cancel_delayed_stuff(usbhid);
usb_kill_urb(usbhid->urbin);
usbhid->intf->needs_remote_wakeup = 0;
}
hid_cancel_delayed_stuff(usbhid); mutex_unlock(&usbhid->mutex);
usb_kill_urb(usbhid->urbin);
usbhid->intf->needs_remote_wakeup = 0;
} }
/* /*
...@@ -1057,6 +1068,8 @@ static int usbhid_start(struct hid_device *hid) ...@@ -1057,6 +1068,8 @@ static int usbhid_start(struct hid_device *hid)
unsigned int n, insize = 0; unsigned int n, insize = 0;
int ret; int ret;
mutex_lock(&usbhid->mutex);
clear_bit(HID_DISCONNECTED, &usbhid->iofl); clear_bit(HID_DISCONNECTED, &usbhid->iofl);
usbhid->bufsize = HID_MIN_BUFFER_SIZE; usbhid->bufsize = HID_MIN_BUFFER_SIZE;
...@@ -1177,6 +1190,8 @@ static int usbhid_start(struct hid_device *hid) ...@@ -1177,6 +1190,8 @@ static int usbhid_start(struct hid_device *hid)
usbhid_set_leds(hid); usbhid_set_leds(hid);
device_set_wakeup_enable(&dev->dev, 1); device_set_wakeup_enable(&dev->dev, 1);
} }
mutex_unlock(&usbhid->mutex);
return 0; return 0;
fail: fail:
...@@ -1187,6 +1202,7 @@ static int usbhid_start(struct hid_device *hid) ...@@ -1187,6 +1202,7 @@ static int usbhid_start(struct hid_device *hid)
usbhid->urbout = NULL; usbhid->urbout = NULL;
usbhid->urbctrl = NULL; usbhid->urbctrl = NULL;
hid_free_buffers(dev, hid); hid_free_buffers(dev, hid);
mutex_unlock(&usbhid->mutex);
return ret; return ret;
} }
...@@ -1202,6 +1218,8 @@ static void usbhid_stop(struct hid_device *hid) ...@@ -1202,6 +1218,8 @@ static void usbhid_stop(struct hid_device *hid)
usbhid->intf->needs_remote_wakeup = 0; usbhid->intf->needs_remote_wakeup = 0;
} }
mutex_lock(&usbhid->mutex);
clear_bit(HID_STARTED, &usbhid->iofl); clear_bit(HID_STARTED, &usbhid->iofl);
spin_lock_irq(&usbhid->lock); /* Sync with error and led handlers */ spin_lock_irq(&usbhid->lock); /* Sync with error and led handlers */
set_bit(HID_DISCONNECTED, &usbhid->iofl); set_bit(HID_DISCONNECTED, &usbhid->iofl);
...@@ -1222,6 +1240,8 @@ static void usbhid_stop(struct hid_device *hid) ...@@ -1222,6 +1240,8 @@ static void usbhid_stop(struct hid_device *hid)
usbhid->urbout = NULL; usbhid->urbout = NULL;
hid_free_buffers(hid_to_usb_dev(hid), hid); hid_free_buffers(hid_to_usb_dev(hid), hid);
mutex_unlock(&usbhid->mutex);
} }
static int usbhid_power(struct hid_device *hid, int lvl) 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 * ...@@ -1382,6 +1402,7 @@ static int usbhid_probe(struct usb_interface *intf, const struct usb_device_id *
INIT_WORK(&usbhid->reset_work, hid_reset); INIT_WORK(&usbhid->reset_work, hid_reset);
timer_setup(&usbhid->io_retry, hid_retry_timeout, 0); timer_setup(&usbhid->io_retry, hid_retry_timeout, 0);
spin_lock_init(&usbhid->lock); spin_lock_init(&usbhid->lock);
mutex_init(&usbhid->mutex);
ret = hid_add_device(hid); ret = hid_add_device(hid);
if (ret) { if (ret) {
......
...@@ -80,6 +80,7 @@ struct usbhid_device { ...@@ -80,6 +80,7 @@ struct usbhid_device {
dma_addr_t outbuf_dma; /* Output buffer dma */ dma_addr_t outbuf_dma; /* Output buffer dma */
unsigned long last_out; /* record of last output for timeouts */ unsigned long last_out; /* record of last output for timeouts */
struct mutex mutex; /* start/stop/open/close */
spinlock_t lock; /* fifo spinlock */ spinlock_t lock; /* fifo spinlock */
unsigned long iofl; /* I/O flags (CTRL_RUNNING, OUT_RUNNING) */ unsigned long iofl; /* I/O flags (CTRL_RUNNING, OUT_RUNNING) */
struct timer_list io_retry; /* Retry timer */ struct timer_list io_retry; /* Retry timer */
......
...@@ -319,9 +319,11 @@ static void wacom_feature_mapping(struct hid_device *hdev, ...@@ -319,9 +319,11 @@ static void wacom_feature_mapping(struct hid_device *hdev,
data[0] = field->report->id; data[0] = field->report->id;
ret = wacom_get_report(hdev, HID_FEATURE_REPORT, ret = wacom_get_report(hdev, HID_FEATURE_REPORT,
data, n, WAC_CMD_RETRIES); data, n, WAC_CMD_RETRIES);
if (ret == n) { if (ret == n && features->type == HID_GENERIC) {
ret = hid_report_raw_event(hdev, ret = hid_report_raw_event(hdev,
HID_FEATURE_REPORT, data, n, 0); HID_FEATURE_REPORT, data, n, 0);
} else if (ret == 2 && features->type != HID_GENERIC) {
features->touch_max = data[1];
} else { } else {
features->touch_max = 16; features->touch_max = 16;
hid_warn(hdev, "wacom_feature_mapping: " hid_warn(hdev, "wacom_feature_mapping: "
......
...@@ -1427,11 +1427,13 @@ static void wacom_intuos_pro2_bt_pad(struct wacom_wac *wacom) ...@@ -1427,11 +1427,13 @@ static void wacom_intuos_pro2_bt_pad(struct wacom_wac *wacom)
{ {
struct input_dev *pad_input = wacom->pad_input; struct input_dev *pad_input = wacom->pad_input;
unsigned char *data = wacom->data; 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; int ring = data[285] & 0x7F;
bool ringstatus = data[285] & 0x80; 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 */ /* Fix touchring data: userspace expects 0 at left and increasing clockwise */
ring = 71 - ring; ring = 71 - ring;
...@@ -1439,7 +1441,8 @@ static void wacom_intuos_pro2_bt_pad(struct wacom_wac *wacom) ...@@ -1439,7 +1441,8 @@ static void wacom_intuos_pro2_bt_pad(struct wacom_wac *wacom)
if (ring > 71) if (ring > 71)
ring -= 72; 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); 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, ...@@ -2637,9 +2640,25 @@ static void wacom_wac_finger_pre_report(struct hid_device *hdev,
case HID_DG_TIPSWITCH: case HID_DG_TIPSWITCH:
hid_data->last_slot_field = equivalent_usage; hid_data->last_slot_field = equivalent_usage;
break; 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, static void wacom_wac_finger_report(struct hid_device *hdev,
...@@ -2649,7 +2668,6 @@ 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 wacom_wac *wacom_wac = &wacom->wacom_wac;
struct input_dev *input = wacom_wac->touch_input; struct input_dev *input = wacom_wac->touch_input;
unsigned touch_max = wacom_wac->features.touch_max; 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 /* If more packets of data are expected, give us a chance to
* process them rather than immediately syncing a partial * process them rather than immediately syncing a partial
...@@ -2663,7 +2681,6 @@ static void wacom_wac_finger_report(struct hid_device *hdev, ...@@ -2663,7 +2681,6 @@ static void wacom_wac_finger_report(struct hid_device *hdev,
input_sync(input); input_sync(input);
wacom_wac->hid_data.num_received = 0; wacom_wac->hid_data.num_received = 0;
hid_data->num_expected = 0;
/* keep touch state for pen event */ /* keep touch state for pen event */
wacom_wac->shared->touch_down = wacom_wac_finger_count_touches(wacom_wac); 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, ...@@ -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, static int wacom_wac_collection(struct hid_device *hdev, struct hid_report *report,
int collection_index, struct hid_field *field, int collection_index, struct hid_field *field,
int field_index) int field_index)
{ {
struct wacom *wacom = hid_get_drvdata(hdev); 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); wacom_report_events(hdev, report, collection_index, field_index);
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment