Commit e63c733d authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid

Pull HID fixes from Jiri Kosina:

 - fixes for pen pen proximity / touch events in wacom driver, from Ping
   Cheng and Benjamin Tissoires

 - two new device-specific quirks from Oliver Neukum and Forest
   Wilkinson

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid:
  HID: wacom: check for wacom->shared before following the pointer
  HID: tivo: enable all buttons on the TiVo Slide Pro remote
  HID: add ALWAYS_POLL quirk for a Logitech 0xc007
  HID: wacom: rely on actual touch down count to decide touch_down
  HID: wacom: do not send pen events before touch is up/forced out
parents c5861658 e2c7d887
...@@ -1959,6 +1959,7 @@ static const struct hid_device_id hid_have_special_driver[] = { ...@@ -1959,6 +1959,7 @@ static const struct hid_device_id hid_have_special_driver[] = {
{ HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb65a) }, { HID_USB_DEVICE(USB_VENDOR_ID_THRUSTMASTER, 0xb65a) },
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_TIVO, USB_DEVICE_ID_TIVO_SLIDE_BT) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_TIVO, USB_DEVICE_ID_TIVO_SLIDE_BT) },
{ HID_USB_DEVICE(USB_VENDOR_ID_TIVO, USB_DEVICE_ID_TIVO_SLIDE) }, { HID_USB_DEVICE(USB_VENDOR_ID_TIVO, USB_DEVICE_ID_TIVO_SLIDE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_TIVO, USB_DEVICE_ID_TIVO_SLIDE_PRO) },
{ HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED, USB_DEVICE_ID_TOPSEED_CYBERLINK) }, { HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED, USB_DEVICE_ID_TOPSEED_CYBERLINK) },
{ HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED2, USB_DEVICE_ID_TOPSEED2_RF_COMBO) }, { HID_USB_DEVICE(USB_VENDOR_ID_TOPSEED2, USB_DEVICE_ID_TOPSEED2_RF_COMBO) },
{ HID_USB_DEVICE(USB_VENDOR_ID_TWINHAN, USB_DEVICE_ID_TWINHAN_IR_REMOTE) }, { HID_USB_DEVICE(USB_VENDOR_ID_TWINHAN, USB_DEVICE_ID_TWINHAN_IR_REMOTE) },
......
...@@ -586,6 +586,7 @@ ...@@ -586,6 +586,7 @@
#define USB_VENDOR_ID_LOGITECH 0x046d #define USB_VENDOR_ID_LOGITECH 0x046d
#define USB_DEVICE_ID_LOGITECH_AUDIOHUB 0x0a0e #define USB_DEVICE_ID_LOGITECH_AUDIOHUB 0x0a0e
#define USB_DEVICE_ID_LOGITECH_T651 0xb00c #define USB_DEVICE_ID_LOGITECH_T651 0xb00c
#define USB_DEVICE_ID_LOGITECH_C077 0xc007
#define USB_DEVICE_ID_LOGITECH_RECEIVER 0xc101 #define USB_DEVICE_ID_LOGITECH_RECEIVER 0xc101
#define USB_DEVICE_ID_LOGITECH_HARMONY_FIRST 0xc110 #define USB_DEVICE_ID_LOGITECH_HARMONY_FIRST 0xc110
#define USB_DEVICE_ID_LOGITECH_HARMONY_LAST 0xc14f #define USB_DEVICE_ID_LOGITECH_HARMONY_LAST 0xc14f
...@@ -898,6 +899,7 @@ ...@@ -898,6 +899,7 @@
#define USB_VENDOR_ID_TIVO 0x150a #define USB_VENDOR_ID_TIVO 0x150a
#define USB_DEVICE_ID_TIVO_SLIDE_BT 0x1200 #define USB_DEVICE_ID_TIVO_SLIDE_BT 0x1200
#define USB_DEVICE_ID_TIVO_SLIDE 0x1201 #define USB_DEVICE_ID_TIVO_SLIDE 0x1201
#define USB_DEVICE_ID_TIVO_SLIDE_PRO 0x1203
#define USB_VENDOR_ID_TOPSEED 0x0766 #define USB_VENDOR_ID_TOPSEED 0x0766
#define USB_DEVICE_ID_TOPSEED_CYBERLINK 0x0204 #define USB_DEVICE_ID_TOPSEED_CYBERLINK 0x0204
......
...@@ -64,6 +64,7 @@ static const struct hid_device_id tivo_devices[] = { ...@@ -64,6 +64,7 @@ static const struct hid_device_id tivo_devices[] = {
/* TiVo Slide Bluetooth remote, pairs with a Broadcom dongle */ /* TiVo Slide Bluetooth remote, pairs with a Broadcom dongle */
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_TIVO, USB_DEVICE_ID_TIVO_SLIDE_BT) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_TIVO, USB_DEVICE_ID_TIVO_SLIDE_BT) },
{ HID_USB_DEVICE(USB_VENDOR_ID_TIVO, USB_DEVICE_ID_TIVO_SLIDE) }, { HID_USB_DEVICE(USB_VENDOR_ID_TIVO, USB_DEVICE_ID_TIVO_SLIDE) },
{ HID_USB_DEVICE(USB_VENDOR_ID_TIVO, USB_DEVICE_ID_TIVO_SLIDE_PRO) },
{ } { }
}; };
MODULE_DEVICE_TABLE(hid, tivo_devices); MODULE_DEVICE_TABLE(hid, tivo_devices);
......
...@@ -78,6 +78,7 @@ static const struct hid_blacklist { ...@@ -78,6 +78,7 @@ static const struct hid_blacklist {
{ USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2700, HID_QUIRK_NOGET }, { USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2700, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_FORMOSA, USB_DEVICE_ID_FORMOSA_IR_RECEIVER, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_FORMOSA, USB_DEVICE_ID_FORMOSA_IR_RECEIVER, HID_QUIRK_NO_INIT_REPORTS },
{ USB_VENDOR_ID_FREESCALE, USB_DEVICE_ID_FREESCALE_MX28, HID_QUIRK_NOGET }, { USB_VENDOR_ID_FREESCALE, USB_DEVICE_ID_FREESCALE_MX28, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_C077, HID_QUIRK_ALWAYS_POLL },
{ USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_NOGET }, { USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_NOGET },
{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_3, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_3, HID_QUIRK_NO_INIT_REPORTS },
{ USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_3_JP, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_3_JP, HID_QUIRK_NO_INIT_REPORTS },
......
...@@ -551,9 +551,13 @@ static int wacom_intuos_inout(struct wacom_wac *wacom) ...@@ -551,9 +551,13 @@ static int wacom_intuos_inout(struct wacom_wac *wacom)
(features->type == CINTIQ && !(data[1] & 0x40))) (features->type == CINTIQ && !(data[1] & 0x40)))
return 1; return 1;
if (features->quirks & WACOM_QUIRK_MULTI_INPUT) if (wacom->shared) {
wacom->shared->stylus_in_proximity = true; wacom->shared->stylus_in_proximity = true;
if (wacom->shared->touch_down)
return 1;
}
/* in Range while exiting */ /* in Range while exiting */
if (((data[1] & 0xfe) == 0x20) && wacom->reporting_data) { if (((data[1] & 0xfe) == 0x20) && wacom->reporting_data) {
input_report_key(input, BTN_TOUCH, 0); input_report_key(input, BTN_TOUCH, 0);
...@@ -1043,27 +1047,28 @@ static int wacom_24hdt_irq(struct wacom_wac *wacom) ...@@ -1043,27 +1047,28 @@ static int wacom_24hdt_irq(struct wacom_wac *wacom)
struct input_dev *input = wacom->input; struct input_dev *input = wacom->input;
unsigned char *data = wacom->data; unsigned char *data = wacom->data;
int i; int i;
int current_num_contacts = 0; int current_num_contacts = data[61];
int contacts_to_send = 0; int contacts_to_send = 0;
int num_contacts_left = 4; /* maximum contacts per packet */ int num_contacts_left = 4; /* maximum contacts per packet */
int byte_per_packet = WACOM_BYTES_PER_24HDT_PACKET; int byte_per_packet = WACOM_BYTES_PER_24HDT_PACKET;
int y_offset = 2; int y_offset = 2;
static int contact_with_no_pen_down_count = 0;
if (wacom->features.type == WACOM_27QHDT) { if (wacom->features.type == WACOM_27QHDT) {
current_num_contacts = data[63]; current_num_contacts = data[63];
num_contacts_left = 10; num_contacts_left = 10;
byte_per_packet = WACOM_BYTES_PER_QHDTHID_PACKET; byte_per_packet = WACOM_BYTES_PER_QHDTHID_PACKET;
y_offset = 0; y_offset = 0;
} else {
current_num_contacts = data[61];
} }
/* /*
* First packet resets the counter since only the first * First packet resets the counter since only the first
* packet in series will have non-zero current_num_contacts. * packet in series will have non-zero current_num_contacts.
*/ */
if (current_num_contacts) if (current_num_contacts) {
wacom->num_contacts_left = current_num_contacts; wacom->num_contacts_left = current_num_contacts;
contact_with_no_pen_down_count = 0;
}
contacts_to_send = min(num_contacts_left, wacom->num_contacts_left); contacts_to_send = min(num_contacts_left, wacom->num_contacts_left);
...@@ -1096,15 +1101,16 @@ static int wacom_24hdt_irq(struct wacom_wac *wacom) ...@@ -1096,15 +1101,16 @@ static int wacom_24hdt_irq(struct wacom_wac *wacom)
input_report_abs(input, ABS_MT_WIDTH_MINOR, min(w, h)); input_report_abs(input, ABS_MT_WIDTH_MINOR, min(w, h));
input_report_abs(input, ABS_MT_ORIENTATION, w > h); input_report_abs(input, ABS_MT_ORIENTATION, w > h);
} }
contact_with_no_pen_down_count++;
} }
} }
input_mt_report_pointer_emulation(input, true); input_mt_report_pointer_emulation(input, true);
wacom->num_contacts_left -= contacts_to_send; wacom->num_contacts_left -= contacts_to_send;
if (wacom->num_contacts_left <= 0) if (wacom->num_contacts_left <= 0) {
wacom->num_contacts_left = 0; wacom->num_contacts_left = 0;
wacom->shared->touch_down = (contact_with_no_pen_down_count > 0);
wacom->shared->touch_down = (wacom->num_contacts_left > 0); }
return 1; return 1;
} }
...@@ -1116,6 +1122,7 @@ static int wacom_mt_touch(struct wacom_wac *wacom) ...@@ -1116,6 +1122,7 @@ static int wacom_mt_touch(struct wacom_wac *wacom)
int current_num_contacts = data[2]; int current_num_contacts = data[2];
int contacts_to_send = 0; int contacts_to_send = 0;
int x_offset = 0; int x_offset = 0;
static int contact_with_no_pen_down_count = 0;
/* MTTPC does not support Height and Width */ /* MTTPC does not support Height and Width */
if (wacom->features.type == MTTPC || wacom->features.type == MTTPC_B) if (wacom->features.type == MTTPC || wacom->features.type == MTTPC_B)
...@@ -1125,8 +1132,10 @@ static int wacom_mt_touch(struct wacom_wac *wacom) ...@@ -1125,8 +1132,10 @@ static int wacom_mt_touch(struct wacom_wac *wacom)
* First packet resets the counter since only the first * First packet resets the counter since only the first
* packet in series will have non-zero current_num_contacts. * packet in series will have non-zero current_num_contacts.
*/ */
if (current_num_contacts) if (current_num_contacts) {
wacom->num_contacts_left = current_num_contacts; wacom->num_contacts_left = current_num_contacts;
contact_with_no_pen_down_count = 0;
}
/* There are at most 5 contacts per packet */ /* There are at most 5 contacts per packet */
contacts_to_send = min(5, wacom->num_contacts_left); contacts_to_send = min(5, wacom->num_contacts_left);
...@@ -1147,15 +1156,16 @@ static int wacom_mt_touch(struct wacom_wac *wacom) ...@@ -1147,15 +1156,16 @@ static int wacom_mt_touch(struct wacom_wac *wacom)
int y = get_unaligned_le16(&data[offset + x_offset + 9]); int y = get_unaligned_le16(&data[offset + x_offset + 9]);
input_report_abs(input, ABS_MT_POSITION_X, x); input_report_abs(input, ABS_MT_POSITION_X, x);
input_report_abs(input, ABS_MT_POSITION_Y, y); input_report_abs(input, ABS_MT_POSITION_Y, y);
contact_with_no_pen_down_count++;
} }
} }
input_mt_report_pointer_emulation(input, true); input_mt_report_pointer_emulation(input, true);
wacom->num_contacts_left -= contacts_to_send; wacom->num_contacts_left -= contacts_to_send;
if (wacom->num_contacts_left < 0) if (wacom->num_contacts_left <= 0) {
wacom->num_contacts_left = 0; wacom->num_contacts_left = 0;
wacom->shared->touch_down = (contact_with_no_pen_down_count > 0);
wacom->shared->touch_down = (wacom->num_contacts_left > 0); }
return 1; return 1;
} }
...@@ -1193,29 +1203,25 @@ static int wacom_tpc_single_touch(struct wacom_wac *wacom, size_t len) ...@@ -1193,29 +1203,25 @@ static int wacom_tpc_single_touch(struct wacom_wac *wacom, size_t len)
{ {
unsigned char *data = wacom->data; unsigned char *data = wacom->data;
struct input_dev *input = wacom->input; struct input_dev *input = wacom->input;
bool prox; bool prox = !wacom->shared->stylus_in_proximity;
int x = 0, y = 0; int x = 0, y = 0;
if (wacom->features.touch_max > 1 || len > WACOM_PKGLEN_TPC2FG) if (wacom->features.touch_max > 1 || len > WACOM_PKGLEN_TPC2FG)
return 0; return 0;
if (!wacom->shared->stylus_in_proximity) {
if (len == WACOM_PKGLEN_TPC1FG) { if (len == WACOM_PKGLEN_TPC1FG) {
prox = data[0] & 0x01; prox = prox && (data[0] & 0x01);
x = get_unaligned_le16(&data[1]); x = get_unaligned_le16(&data[1]);
y = get_unaligned_le16(&data[3]); y = get_unaligned_le16(&data[3]);
} else if (len == WACOM_PKGLEN_TPC1FG_B) { } else if (len == WACOM_PKGLEN_TPC1FG_B) {
prox = data[2] & 0x01; prox = prox && (data[2] & 0x01);
x = get_unaligned_le16(&data[3]); x = get_unaligned_le16(&data[3]);
y = get_unaligned_le16(&data[5]); y = get_unaligned_le16(&data[5]);
} else { } else {
prox = data[1] & 0x01; prox = prox && (data[1] & 0x01);
x = le16_to_cpup((__le16 *)&data[2]); x = le16_to_cpup((__le16 *)&data[2]);
y = le16_to_cpup((__le16 *)&data[4]); y = le16_to_cpup((__le16 *)&data[4]);
} }
} else
/* force touch out when pen is in prox */
prox = 0;
if (prox) { if (prox) {
input_report_abs(input, ABS_X, x); input_report_abs(input, ABS_X, x);
...@@ -1613,6 +1619,7 @@ static int wacom_bpt_touch(struct wacom_wac *wacom) ...@@ -1613,6 +1619,7 @@ static int wacom_bpt_touch(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 i; int i;
int contact_with_no_pen_down_count = 0;
if (data[0] != 0x02) if (data[0] != 0x02)
return 0; return 0;
...@@ -1640,6 +1647,7 @@ static int wacom_bpt_touch(struct wacom_wac *wacom) ...@@ -1640,6 +1647,7 @@ static int wacom_bpt_touch(struct wacom_wac *wacom)
} }
input_report_abs(input, ABS_MT_POSITION_X, x); input_report_abs(input, ABS_MT_POSITION_X, x);
input_report_abs(input, ABS_MT_POSITION_Y, y); input_report_abs(input, ABS_MT_POSITION_Y, y);
contact_with_no_pen_down_count++;
} }
} }
...@@ -1649,11 +1657,12 @@ static int wacom_bpt_touch(struct wacom_wac *wacom) ...@@ -1649,11 +1657,12 @@ static int wacom_bpt_touch(struct wacom_wac *wacom)
input_report_key(pad_input, BTN_FORWARD, (data[1] & 0x04) != 0); input_report_key(pad_input, BTN_FORWARD, (data[1] & 0x04) != 0);
input_report_key(pad_input, BTN_BACK, (data[1] & 0x02) != 0); input_report_key(pad_input, BTN_BACK, (data[1] & 0x02) != 0);
input_report_key(pad_input, BTN_RIGHT, (data[1] & 0x01) != 0); input_report_key(pad_input, BTN_RIGHT, (data[1] & 0x01) != 0);
wacom->shared->touch_down = (contact_with_no_pen_down_count > 0);
return 1; return 1;
} }
static void wacom_bpt3_touch_msg(struct wacom_wac *wacom, unsigned char *data) static int wacom_bpt3_touch_msg(struct wacom_wac *wacom, unsigned char *data, int last_touch_count)
{ {
struct wacom_features *features = &wacom->features; struct wacom_features *features = &wacom->features;
struct input_dev *input = wacom->input; struct input_dev *input = wacom->input;
...@@ -1661,7 +1670,7 @@ static void wacom_bpt3_touch_msg(struct wacom_wac *wacom, unsigned char *data) ...@@ -1661,7 +1670,7 @@ static void wacom_bpt3_touch_msg(struct wacom_wac *wacom, unsigned char *data)
int slot = input_mt_get_slot_by_key(input, data[0]); int slot = input_mt_get_slot_by_key(input, data[0]);
if (slot < 0) if (slot < 0)
return; return 0;
touch = touch && !wacom->shared->stylus_in_proximity; touch = touch && !wacom->shared->stylus_in_proximity;
...@@ -1693,7 +1702,9 @@ static void wacom_bpt3_touch_msg(struct wacom_wac *wacom, unsigned char *data) ...@@ -1693,7 +1702,9 @@ static void wacom_bpt3_touch_msg(struct wacom_wac *wacom, unsigned char *data)
input_report_abs(input, ABS_MT_POSITION_Y, y); input_report_abs(input, ABS_MT_POSITION_Y, y);
input_report_abs(input, ABS_MT_TOUCH_MAJOR, width); input_report_abs(input, ABS_MT_TOUCH_MAJOR, width);
input_report_abs(input, ABS_MT_TOUCH_MINOR, height); input_report_abs(input, ABS_MT_TOUCH_MINOR, height);
last_touch_count++;
} }
return last_touch_count;
} }
static void wacom_bpt3_button_msg(struct wacom_wac *wacom, unsigned char *data) static void wacom_bpt3_button_msg(struct wacom_wac *wacom, unsigned char *data)
...@@ -1718,6 +1729,7 @@ static int wacom_bpt3_touch(struct wacom_wac *wacom) ...@@ -1718,6 +1729,7 @@ static int wacom_bpt3_touch(struct wacom_wac *wacom)
unsigned char *data = wacom->data; unsigned char *data = wacom->data;
int count = data[1] & 0x07; int count = data[1] & 0x07;
int i; int i;
int contact_with_no_pen_down_count = 0;
if (data[0] != 0x02) if (data[0] != 0x02)
return 0; return 0;
...@@ -1728,12 +1740,15 @@ static int wacom_bpt3_touch(struct wacom_wac *wacom) ...@@ -1728,12 +1740,15 @@ static int wacom_bpt3_touch(struct wacom_wac *wacom)
int msg_id = data[offset]; int msg_id = data[offset];
if (msg_id >= 2 && msg_id <= 17) if (msg_id >= 2 && msg_id <= 17)
wacom_bpt3_touch_msg(wacom, data + offset); contact_with_no_pen_down_count =
wacom_bpt3_touch_msg(wacom, data + offset,
contact_with_no_pen_down_count);
else if (msg_id == 128) else if (msg_id == 128)
wacom_bpt3_button_msg(wacom, data + offset); wacom_bpt3_button_msg(wacom, data + offset);
} }
input_mt_report_pointer_emulation(input, true); input_mt_report_pointer_emulation(input, true);
wacom->shared->touch_down = (contact_with_no_pen_down_count > 0);
return 1; return 1;
} }
...@@ -1759,6 +1774,9 @@ static int wacom_bpt_pen(struct wacom_wac *wacom) ...@@ -1759,6 +1774,9 @@ static int wacom_bpt_pen(struct wacom_wac *wacom)
return 0; return 0;
} }
if (wacom->shared->touch_down)
return 0;
prox = (data[1] & 0x20) == 0x20; prox = (data[1] & 0x20) == 0x20;
/* /*
......
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