diff options
Diffstat (limited to 'drivers/hid')
-rw-r--r-- | drivers/hid/Kconfig | 10 | ||||
-rw-r--r-- | drivers/hid/Makefile | 1 | ||||
-rw-r--r-- | drivers/hid/hid-core.c | 16 | ||||
-rw-r--r-- | drivers/hid/hid-cp2112.c | 6 | ||||
-rw-r--r-- | drivers/hid/hid-debug.c | 6 | ||||
-rw-r--r-- | drivers/hid/hid-ids.h | 14 | ||||
-rw-r--r-- | drivers/hid/hid-input.c | 14 | ||||
-rw-r--r-- | drivers/hid/hid-lenovo.c | 13 | ||||
-rw-r--r-- | drivers/hid/hid-microsoft.c | 2 | ||||
-rw-r--r-- | drivers/hid/hid-multitouch.c | 27 | ||||
-rw-r--r-- | drivers/hid/hid-plantronics.c | 55 | ||||
-rw-r--r-- | drivers/hid/hid-rmi.c | 83 | ||||
-rw-r--r-- | drivers/hid/hid-roccat-kone.c | 9 | ||||
-rw-r--r-- | drivers/hid/hid-saitek.c | 4 | ||||
-rw-r--r-- | drivers/hid/hid-sony.c | 150 | ||||
-rw-r--r-- | drivers/hid/i2c-hid/i2c-hid.c | 16 | ||||
-rw-r--r-- | drivers/hid/usbhid/hid-core.c | 39 | ||||
-rw-r--r-- | drivers/hid/usbhid/hid-quirks.c | 5 | ||||
-rw-r--r-- | drivers/hid/usbhid/usbhid.h | 1 | ||||
-rw-r--r-- | drivers/hid/wacom.h | 2 | ||||
-rw-r--r-- | drivers/hid/wacom_sys.c | 68 | ||||
-rw-r--r-- | drivers/hid/wacom_wac.c | 216 | ||||
-rw-r--r-- | drivers/hid/wacom_wac.h | 3 |
23 files changed, 559 insertions, 201 deletions
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index dd49a9b14b9c..230b6f887cd8 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig @@ -625,6 +625,13 @@ config HID_PICOLCD_CIR ---help--- Provide access to PicoLCD's CIR interface via remote control (LIRC). +config HID_PLANTRONICS + tristate "Plantronics USB HID Driver" + default !EXPERT + depends on HID + ---help--- + Provides HID support for Plantronics telephony devices. + config HID_PRIMAX tristate "Primax non-fully HID-compliant devices" depends on HID @@ -641,7 +648,7 @@ config HID_ROCCAT support for its special functionalities. config HID_SAITEK - tristate "Saitek non-fully HID-compliant devices" + tristate "Saitek (Mad Catz) non-fully HID-compliant devices" depends on HID ---help--- Support for Saitek devices that are not fully compliant with the @@ -649,6 +656,7 @@ config HID_SAITEK Supported devices: - PS1000 Dual Analog Pad + - R.A.T.9 Gaming Mouse - R.A.T.7 Gaming Mouse - M.M.O.7 Gaming Mouse diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile index b102774b4e16..debd15b44b59 100644 --- a/drivers/hid/Makefile +++ b/drivers/hid/Makefile @@ -95,6 +95,7 @@ ifdef CONFIG_DEBUG_FS hid-picolcd-y += hid-picolcd_debugfs.o endif +obj-$(CONFIG_HID_PLANTRONICS) += hid-plantronics.o obj-$(CONFIG_HID_PRIMAX) += hid-primax.o obj-$(CONFIG_HID_ROCCAT) += hid-roccat.o hid-roccat-common.o \ hid-roccat-arvo.o hid-roccat-isku.o hid-roccat-kone.o \ diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 395549fea44c..c3d0ac1a0988 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -702,6 +702,11 @@ static void hid_scan_collection(struct hid_parser *parser, unsigned type) if (((parser->global.usage_page << 16) == HID_UP_SENSOR) && type == HID_COLLECTION_PHYSICAL) hid->group = HID_GROUP_SENSOR_HUB; + + if (hid->vendor == USB_VENDOR_ID_MICROSOFT && + hid->product == USB_DEVICE_ID_MS_TYPE_COVER_3 && + hid->group == HID_GROUP_MULTITOUCH) + hid->group = HID_GROUP_GENERIC; } static int hid_scan_main(struct hid_parser *parser, struct hid_item *item) @@ -1277,12 +1282,6 @@ void hid_output_report(struct hid_report *report, __u8 *data) } EXPORT_SYMBOL_GPL(hid_output_report); -static int hid_report_len(struct hid_report *report) -{ - /* equivalent to DIV_ROUND_UP(report->size, 8) + !!(report->id > 0) */ - return ((report->size - 1) >> 3) + 1 + (report->id > 0); -} - /* * Allocator for buffer that is going to be passed to hid_output_report() */ @@ -1656,6 +1655,7 @@ void hid_disconnect(struct hid_device *hdev) hdev->hiddev_disconnect(hdev); if (hdev->claimed & HID_CLAIMED_HIDRAW) hidraw_disconnect(hdev); + hdev->claimed = 0; } EXPORT_SYMBOL_GPL(hid_disconnect); @@ -1859,6 +1859,7 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_DIGITAL_MEDIA_3K) }, { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0) }, { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_OFFICE_KB) }, + { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_3) }, { HID_USB_DEVICE(USB_VENDOR_ID_MONTEREY, USB_DEVICE_ID_GENIUS_KB29E) }, { HID_USB_DEVICE(USB_VENDOR_ID_MSI, USB_DEVICE_ID_MSI_GT683R_LED_PANEL) }, { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN) }, @@ -1884,6 +1885,7 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_WKB2000) }, { HID_USB_DEVICE(USB_VENDOR_ID_PENMOUNT, USB_DEVICE_ID_PENMOUNT_6000) }, { HID_USB_DEVICE(USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE) }, + { HID_USB_DEVICE(USB_VENDOR_ID_PLANTRONICS, HID_ANY_ID) }, { HID_USB_DEVICE(USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_KEYBOARD) }, #if IS_ENABLED(CONFIG_HID_ROCCAT) { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ARVO) }, @@ -1907,10 +1909,12 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_PS1000) }, { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RAT7) }, { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_MMO7) }, + { HID_USB_DEVICE(USB_VENDOR_ID_MADCATZ, USB_DEVICE_ID_MADCATZ_RAT9) }, #endif { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) }, { HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE) }, { HID_USB_DEVICE(USB_VENDOR_ID_SKYCABLE, USB_DEVICE_ID_SKYCABLE_WIRELESS_PRESENTER) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SMK, USB_DEVICE_ID_SMK_PS3_BDREMOTE) }, { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_BUZZ_CONTROLLER) }, { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_WIRELESS_BUZZ_CONTROLLER) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_BDREMOTE) }, diff --git a/drivers/hid/hid-cp2112.c b/drivers/hid/hid-cp2112.c index a822db5a8338..3318de690e00 100644 --- a/drivers/hid/hid-cp2112.c +++ b/drivers/hid/hid-cp2112.c @@ -1069,8 +1069,7 @@ static int cp2112_probe(struct hid_device *hdev, const struct hid_device_id *id) return ret; err_gpiochip_remove: - if (gpiochip_remove(&dev->gc) < 0) - hid_err(hdev, "error removing gpio chip\n"); + gpiochip_remove(&dev->gc); err_free_i2c: i2c_del_adapter(&dev->adap); err_free_dev: @@ -1089,8 +1088,7 @@ static void cp2112_remove(struct hid_device *hdev) struct cp2112_device *dev = hid_get_drvdata(hdev); sysfs_remove_group(&hdev->dev.kobj, &cp2112_attr_group); - if (gpiochip_remove(&dev->gc)) - hid_err(hdev, "unable to remove gpio chip\n"); + gpiochip_remove(&dev->gc); i2c_del_adapter(&dev->adap); /* i2c_del_adapter has finished removing all i2c devices from our * adapter. Well behaved devices should no longer call our cp2112_xfer diff --git a/drivers/hid/hid-debug.c b/drivers/hid/hid-debug.c index 84c3cb15ccdd..8bf61d295ffd 100644 --- a/drivers/hid/hid-debug.c +++ b/drivers/hid/hid-debug.c @@ -946,6 +946,12 @@ static const char *keys[KEY_MAX + 1] = { [KEY_BRIGHTNESS_MIN] = "BrightnessMin", [KEY_BRIGHTNESS_MAX] = "BrightnessMax", [KEY_BRIGHTNESS_AUTO] = "BrightnessAuto", + [KEY_KBDINPUTASSIST_PREV] = "KbdInputAssistPrev", + [KEY_KBDINPUTASSIST_NEXT] = "KbdInputAssistNext", + [KEY_KBDINPUTASSIST_PREVGROUP] = "KbdInputAssistPrevGroup", + [KEY_KBDINPUTASSIST_NEXTGROUP] = "KbdInputAssistNextGroup", + [KEY_KBDINPUTASSIST_ACCEPT] = "KbdInputAssistAccept", + [KEY_KBDINPUTASSIST_CANCEL] = "KbdInputAssistCancel", }; static const char *relatives[REL_MAX + 1] = { diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 2aa5091ecc08..7460f3402298 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -298,6 +298,10 @@ #define USB_VENDOR_ID_ELAN 0x04f3 #define USB_DEVICE_ID_ELAN_TOUCHSCREEN 0x0089 +#define USB_DEVICE_ID_ELAN_TOUCHSCREEN_009B 0x009b +#define USB_DEVICE_ID_ELAN_TOUCHSCREEN_0103 0x0103 +#define USB_DEVICE_ID_ELAN_TOUCHSCREEN_010c 0x010c +#define USB_DEVICE_ID_ELAN_TOUCHSCREEN_016F 0x016f #define USB_VENDOR_ID_ELECOM 0x056e #define USB_DEVICE_ID_ELECOM_BM084 0x0061 @@ -618,6 +622,7 @@ #define USB_VENDOR_ID_MADCATZ 0x0738 #define USB_DEVICE_ID_MADCATZ_BEATPAD 0x4540 +#define USB_DEVICE_ID_MADCATZ_RAT9 0x1709 #define USB_VENDOR_ID_MCC 0x09db #define USB_DEVICE_ID_MCC_PMD1024LS 0x0076 @@ -647,6 +652,7 @@ #define USB_DEVICE_ID_MS_SURFACE_PRO_2 0x0799 #define USB_DEVICE_ID_MS_TOUCH_COVER_2 0x07a7 #define USB_DEVICE_ID_MS_TYPE_COVER_2 0x07a9 +#define USB_DEVICE_ID_MS_TYPE_COVER_3 0x07dc #define USB_VENDOR_ID_MOJO 0x8282 #define USB_DEVICE_ID_RETRO_ADAPTER 0x3201 @@ -714,6 +720,8 @@ #define USB_DEVICE_ID_ORTEK_PKB1700 0x1700 #define USB_DEVICE_ID_ORTEK_WKB2000 0x2000 +#define USB_VENDOR_ID_PLANTRONICS 0x047f + #define USB_VENDOR_ID_PANASONIC 0x04da #define USB_DEVICE_ID_PANABOARD_UBT780 0x1044 #define USB_DEVICE_ID_PANABOARD_UBT880 0x104d @@ -811,6 +819,9 @@ #define USB_VENDOR_ID_SKYCABLE 0x1223 #define USB_DEVICE_ID_SKYCABLE_WIRELESS_PRESENTER 0x3F07 +#define USB_VENDOR_ID_SMK 0x0609 +#define USB_DEVICE_ID_SMK_PS3_BDREMOTE 0x0306 + #define USB_VENDOR_ID_SONY 0x054c #define USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE 0x024b #define USB_DEVICE_ID_SONY_VAIO_VGP_MOUSE 0x0374 @@ -929,6 +940,9 @@ #define USB_DEVICE_ID_VERNIER_CYCLOPS 0x0004 #define USB_DEVICE_ID_VERNIER_LCSPEC 0x0006 +#define USB_VENDOR_ID_VTL 0x0306 +#define USB_DEVICE_ID_VTL_MULTITOUCH_FF3F 0xff3f + #define USB_VENDOR_ID_WACOM 0x056a #define USB_DEVICE_ID_WACOM_GRAPHIRE_BLUETOOTH 0x81 #define USB_DEVICE_ID_WACOM_INTUOS4_BLUETOOTH 0x00BD diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c index 7ea582be9c9a..e0a0f06ac5ef 100644 --- a/drivers/hid/hid-input.c +++ b/drivers/hid/hid-input.c @@ -695,7 +695,10 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel break; case 0x5b: /* TransducerSerialNumber */ - set_bit(MSC_SERIAL, input->mscbit); + usage->type = EV_MSC; + usage->code = MSC_SERIAL; + bit = input->mscbit; + max = MSC_MAX; break; default: goto unknown; @@ -862,6 +865,13 @@ static void hidinput_configure_usage(struct hid_input *hidinput, struct hid_fiel case 0x28b: map_key_clear(KEY_FORWARDMAIL); break; case 0x28c: map_key_clear(KEY_SEND); break; + case 0x2c7: map_key_clear(KEY_KBDINPUTASSIST_PREV); break; + case 0x2c8: map_key_clear(KEY_KBDINPUTASSIST_NEXT); break; + case 0x2c9: map_key_clear(KEY_KBDINPUTASSIST_PREVGROUP); break; + case 0x2ca: map_key_clear(KEY_KBDINPUTASSIST_NEXTGROUP); break; + case 0x2cb: map_key_clear(KEY_KBDINPUTASSIST_ACCEPT); break; + case 0x2cc: map_key_clear(KEY_KBDINPUTASSIST_CANCEL); break; + default: map_key_clear(KEY_UNKNOWN); } break; @@ -1205,7 +1215,7 @@ static void hidinput_led_worker(struct work_struct *work) return hid->ll_driver->request(hid, report, HID_REQ_SET_REPORT); /* fall back to generic raw-output-report */ - len = ((report->size - 1) >> 3) + 1 + (report->id > 0); + len = hid_report_len(report); buf = hid_alloc_report_buf(report, GFP_KERNEL); if (!buf) return; diff --git a/drivers/hid/hid-lenovo.c b/drivers/hid/hid-lenovo.c index bf227f7679af..4c55f4d95798 100644 --- a/drivers/hid/hid-lenovo.c +++ b/drivers/hid/hid-lenovo.c @@ -62,7 +62,6 @@ static int lenovo_input_mapping_cptkbd(struct hid_device *hdev, /* HID_UP_LNVENDOR = USB, HID_UP_MSVENDOR = BT */ if ((usage->hid & HID_USAGE_PAGE) == HID_UP_MSVENDOR || (usage->hid & HID_USAGE_PAGE) == HID_UP_LNVENDOR) { - set_bit(EV_REP, hi->input->evbit); switch (usage->hid & HID_USAGE) { case 0x00f1: /* Fn-F4: Mic mute */ map_key_clear(KEY_MICMUTE); @@ -85,13 +84,13 @@ static int lenovo_input_mapping_cptkbd(struct hid_device *hdev, case 0x00f8: /* Fn-F11: View open applications (3 boxes) */ map_key_clear(KEY_SCALE); return 1; - case 0x00fa: /* Fn-Esc: Fn-lock toggle */ - map_key_clear(KEY_FN_ESC); - return 1; - case 0x00fb: /* Fn-F12: Open My computer (6 boxes) USB-only */ + case 0x00f9: /* Fn-F12: Open My computer (6 boxes) USB-only */ /* NB: This mapping is invented in raw_event below */ map_key_clear(KEY_FILE); return 1; + case 0x00fa: /* Fn-Esc: Fn-lock toggle */ + map_key_clear(KEY_FN_ESC); + return 1; } } @@ -207,8 +206,8 @@ static int lenovo_raw_event(struct hid_device *hdev, && data[0] == 0x15 && data[1] == 0x94 && data[2] == 0x01)) { - data[1] = 0x0; - data[2] = 0x4; + data[1] = 0x00; + data[2] = 0x01; } return 0; diff --git a/drivers/hid/hid-microsoft.c b/drivers/hid/hid-microsoft.c index 8ba17a946f2a..cacda43f6a6f 100644 --- a/drivers/hid/hid-microsoft.c +++ b/drivers/hid/hid-microsoft.c @@ -274,6 +274,8 @@ static const struct hid_device_id ms_devices[] = { .driver_data = MS_NOGET }, { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_COMFORT_MOUSE_4500), .driver_data = MS_DUPLICATE_USAGES }, + { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_TYPE_COVER_3), + .driver_data = MS_HIDINPUT }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_BT), .driver_data = MS_PRESENTER }, diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index 51e25b9407f2..f65e78b46999 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c @@ -67,6 +67,7 @@ MODULE_LICENSE("GPL"); #define MT_QUIRK_IGNORE_DUPLICATES (1 << 10) #define MT_QUIRK_HOVERING (1 << 11) #define MT_QUIRK_CONTACT_CNT_ACCURATE (1 << 12) +#define MT_QUIRK_FORCE_GET_FEATURE (1 << 13) #define MT_INPUTMODE_TOUCHSCREEN 0x02 #define MT_INPUTMODE_TOUCHPAD 0x03 @@ -150,6 +151,7 @@ static void mt_post_parse(struct mt_device *td); #define MT_CLS_FLATFROG 0x0107 #define MT_CLS_GENERALTOUCH_TWOFINGERS 0x0108 #define MT_CLS_GENERALTOUCH_PWT_TENFINGERS 0x0109 +#define MT_CLS_VTL 0x0110 #define MT_DEFAULT_MAXCONTACT 10 #define MT_MAX_MAXCONTACT 250 @@ -255,6 +257,11 @@ static struct mt_class mt_classes[] = { .sn_move = 2048, .maxcontacts = 40, }, + { .name = MT_CLS_VTL, + .quirks = MT_QUIRK_ALWAYS_VALID | + MT_QUIRK_CONTACT_CNT_ACCURATE | + MT_QUIRK_FORCE_GET_FEATURE, + }, { } }; @@ -809,6 +816,9 @@ static void mt_set_input_mode(struct hid_device *hdev) struct mt_device *td = hid_get_drvdata(hdev); struct hid_report *r; struct hid_report_enum *re; + struct mt_class *cls = &td->mtclass; + char *buf; + int report_len; if (td->inputmode < 0) return; @@ -816,6 +826,18 @@ static void mt_set_input_mode(struct hid_device *hdev) re = &(hdev->report_enum[HID_FEATURE_REPORT]); r = re->report_id_hash[td->inputmode]; if (r) { + if (cls->quirks & MT_QUIRK_FORCE_GET_FEATURE) { + report_len = hid_report_len(r); + buf = hid_alloc_report_buf(r, GFP_KERNEL); + if (!buf) { + hid_err(hdev, "failed to allocate buffer for report\n"); + return; + } + hid_hw_raw_request(hdev, r->id, buf, report_len, + HID_FEATURE_REPORT, + HID_REQ_GET_REPORT); + kfree(buf); + } r->field[0]->value[td->inputmode_index] = td->inputmode_value; hid_hw_request(hdev, r, HID_REQ_SET_REPORT); } @@ -1281,6 +1303,11 @@ static const struct hid_device_id mt_devices[] = { MT_USB_DEVICE(USB_VENDOR_ID_UNITEC, USB_DEVICE_ID_UNITEC_USB_TOUCH_0A19) }, + /* VTL panels */ + { .driver_data = MT_CLS_VTL, + MT_USB_DEVICE(USB_VENDOR_ID_VTL, + USB_DEVICE_ID_VTL_MULTITOUCH_FF3F) }, + /* Wistron panels */ { .driver_data = MT_CLS_NSMU, MT_USB_DEVICE(USB_VENDOR_ID_WISTRON, diff --git a/drivers/hid/hid-plantronics.c b/drivers/hid/hid-plantronics.c new file mode 100644 index 000000000000..2180e0789b76 --- /dev/null +++ b/drivers/hid/hid-plantronics.c @@ -0,0 +1,55 @@ +/* + * Plantronics USB HID Driver + * + * Copyright (c) 2014 JD Cole <jd.cole@plantronics.com> + * Copyright (c) 2014 Terry Junge <terry.junge@plantronics.com> + */ + +/* + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + */ + +#include "hid-ids.h" + +#include <linux/hid.h> +#include <linux/module.h> + +static int plantronics_input_mapping(struct hid_device *hdev, + struct hid_input *hi, + struct hid_field *field, + struct hid_usage *usage, + unsigned long **bit, int *max) +{ + if (field->application == HID_CP_CONSUMERCONTROL + && (usage->hid & HID_USAGE_PAGE) == HID_UP_CONSUMER) { + hid_dbg(hdev, "usage: %08x (appl: %08x) - defaulted\n", + usage->hid, field->application); + return 0; + } + + hid_dbg(hdev, "usage: %08x (appl: %08x) - ignored\n", + usage->hid, field->application); + + return -1; +} + +static const struct hid_device_id plantronics_devices[] = { + { HID_USB_DEVICE(USB_VENDOR_ID_PLANTRONICS, HID_ANY_ID) }, + { } +}; +MODULE_DEVICE_TABLE(hid, plantronics_devices); + +static struct hid_driver plantronics_driver = { + .name = "plantronics", + .id_table = plantronics_devices, + .input_mapping = plantronics_input_mapping, +}; +module_hid_driver(plantronics_driver); + +MODULE_AUTHOR("JD Cole <jd.cole@plantronics.com>"); +MODULE_AUTHOR("Terry Junge <terry.junge@plantronics.com>"); +MODULE_DESCRIPTION("Plantronics USB HID Driver"); +MODULE_LICENSE("GPL"); diff --git a/drivers/hid/hid-rmi.c b/drivers/hid/hid-rmi.c index 3cccff73b9b9..b51200fe2f33 100644 --- a/drivers/hid/hid-rmi.c +++ b/drivers/hid/hid-rmi.c @@ -584,11 +584,15 @@ static int rmi_populate_f11(struct hid_device *hdev) bool has_query10 = false; bool has_query11; bool has_query12; + bool has_query27; + bool has_query28; + bool has_query36 = false; bool has_physical_props; bool has_gestures; bool has_rel; + bool has_data40 = false; unsigned x_size, y_size; - u16 query12_offset; + u16 query_offset; if (!data->f11.query_base_addr) { hid_err(hdev, "No 2D sensor found, giving up.\n"); @@ -604,6 +608,8 @@ static int rmi_populate_f11(struct hid_device *hdev) has_query9 = !!(buf[0] & BIT(3)); has_query11 = !!(buf[0] & BIT(4)); has_query12 = !!(buf[0] & BIT(5)); + has_query27 = !!(buf[0] & BIT(6)); + has_query28 = !!(buf[0] & BIT(7)); /* query 1 to get the max number of fingers */ ret = rmi_read(hdev, data->f11.query_base_addr + 1, buf); @@ -626,43 +632,43 @@ static int rmi_populate_f11(struct hid_device *hdev) has_rel = !!(buf[0] & BIT(3)); has_gestures = !!(buf[0] & BIT(5)); + /* + * At least 4 queries are guaranteed to be present in F11 + * +1 for query 5 which is present since absolute events are + * reported and +1 for query 12. + */ + query_offset = 6; + + if (has_rel) + ++query_offset; /* query 6 is present */ + if (has_gestures) { /* query 8 to find out if query 10 exists */ - ret = rmi_read(hdev, data->f11.query_base_addr + 8, buf); + ret = rmi_read(hdev, + data->f11.query_base_addr + query_offset + 1, buf); if (ret) { hid_err(hdev, "can not read gesture information: %d.\n", ret); return ret; } has_query10 = !!(buf[0] & BIT(2)); - } - /* - * At least 4 queries are guaranteed to be present in F11 - * +1 for query 5 which is present since absolute events are - * reported and +1 for query 12. - */ - query12_offset = 6; - - if (has_rel) - ++query12_offset; /* query 6 is present */ - - if (has_gestures) - query12_offset += 2; /* query 7 and 8 are present */ + query_offset += 2; /* query 7 and 8 are present */ + } if (has_query9) - ++query12_offset; + ++query_offset; if (has_query10) - ++query12_offset; + ++query_offset; if (has_query11) - ++query12_offset; + ++query_offset; /* query 12 to know if the physical properties are reported */ if (has_query12) { ret = rmi_read(hdev, data->f11.query_base_addr - + query12_offset, buf); + + query_offset, buf); if (ret) { hid_err(hdev, "can not get query 12: %d.\n", ret); return ret; @@ -670,9 +676,10 @@ static int rmi_populate_f11(struct hid_device *hdev) has_physical_props = !!(buf[0] & BIT(5)); if (has_physical_props) { + query_offset += 1; ret = rmi_read_block(hdev, data->f11.query_base_addr - + query12_offset + 1, buf, 4); + + query_offset, buf, 4); if (ret) { hid_err(hdev, "can not read query 15-18: %d.\n", ret); @@ -687,9 +694,45 @@ static int rmi_populate_f11(struct hid_device *hdev) hid_info(hdev, "%s: size in mm: %d x %d\n", __func__, data->x_size_mm, data->y_size_mm); + + /* + * query 15 - 18 contain the size of the sensor + * and query 19 - 26 contain bezel dimensions + */ + query_offset += 12; + } + } + + if (has_query27) + ++query_offset; + + if (has_query28) { + ret = rmi_read(hdev, data->f11.query_base_addr + + query_offset, buf); + if (ret) { + hid_err(hdev, "can not get query 28: %d.\n", ret); + return ret; + } + + has_query36 = !!(buf[0] & BIT(6)); + } + + if (has_query36) { + query_offset += 2; + ret = rmi_read(hdev, data->f11.query_base_addr + + query_offset, buf); + if (ret) { + hid_err(hdev, "can not get query 36: %d.\n", ret); + return ret; } + + has_data40 = !!(buf[0] & BIT(5)); } + + if (has_data40) + data->f11.report_size += data->max_fingers * 2; + /* * retrieve the ctrl registers * the ctrl register has a size of 20 but a fw bug split it into 16 + 4, diff --git a/drivers/hid/hid-roccat-kone.c b/drivers/hid/hid-roccat-kone.c index 6101816a7ddd..c29265055ac1 100644 --- a/drivers/hid/hid-roccat-kone.c +++ b/drivers/hid/hid-roccat-kone.c @@ -46,6 +46,7 @@ static void kone_profile_activated(struct kone_device *kone, uint new_profile) static void kone_profile_report(struct kone_device *kone, uint new_profile) { struct kone_roccat_report roccat_report; + roccat_report.event = kone_mouse_event_switch_profile; roccat_report.value = new_profile; roccat_report.key = 0; @@ -163,6 +164,7 @@ static int kone_set_settings(struct usb_device *usb_dev, struct kone_settings const *settings) { int retval; + retval = kone_send(usb_dev, kone_command_settings, settings, sizeof(struct kone_settings)); if (retval) @@ -387,7 +389,7 @@ static struct bin_attribute bin_attr_profile##number = { \ .read = kone_sysfs_read_profilex, \ .write = kone_sysfs_write_profilex, \ .private = &profile_numbers[number-1], \ -}; +} PROFILE_ATTR(1); PROFILE_ATTR(2); PROFILE_ATTR(3); @@ -456,6 +458,7 @@ static ssize_t kone_sysfs_show_tcu(struct device *dev, static int kone_tcu_command(struct usb_device *usb_dev, int number) { unsigned char value; + value = number; return kone_send(usb_dev, kone_command_calibrate, &value, 1); } @@ -697,10 +700,8 @@ static int kone_init_specials(struct hid_device *hdev) == USB_INTERFACE_PROTOCOL_MOUSE) { kone = kzalloc(sizeof(*kone), GFP_KERNEL); - if (!kone) { - hid_err(hdev, "can't alloc device descriptor\n"); + if (!kone) return -ENOMEM; - } hid_set_drvdata(hdev, kone); retval = kone_init_kone_device_struct(usb_dev, kone); diff --git a/drivers/hid/hid-saitek.c b/drivers/hid/hid-saitek.c index 69cca1476a0c..5632c54eadf0 100644 --- a/drivers/hid/hid-saitek.c +++ b/drivers/hid/hid-saitek.c @@ -7,7 +7,7 @@ * (This module is based on "hid-ortek".) * Copyright (c) 2012 Andreas Hübner * - * R.A.T.7, M.M.O.7 (USB gaming mice): + * R.A.T.7, R.A.T.9, M.M.O.7 (USB gaming mice): * Fixes the mode button which cycles through three constantly pressed * buttons. All three press events are mapped to one button and the * missing release event is generated immediately. @@ -179,6 +179,8 @@ static const struct hid_device_id saitek_devices[] = { .driver_data = SAITEK_FIX_PS1000 }, { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_RAT7), .driver_data = SAITEK_RELEASE_MODE_RAT7 }, + { HID_USB_DEVICE(USB_VENDOR_ID_MADCATZ, USB_DEVICE_ID_MADCATZ_RAT9), + .driver_data = SAITEK_RELEASE_MODE_RAT7 }, { HID_USB_DEVICE(USB_VENDOR_ID_SAITEK, USB_DEVICE_ID_SAITEK_MMO7), .driver_data = SAITEK_RELEASE_MODE_MMO7 }, { } diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index bc4269e559f1..31e9d2561106 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c @@ -798,6 +798,12 @@ union sixaxis_output_report_01 { __u8 buf[36]; }; +#define DS4_REPORT_0x02_SIZE 37 +#define DS4_REPORT_0x05_SIZE 32 +#define DS4_REPORT_0x11_SIZE 78 +#define DS4_REPORT_0x81_SIZE 7 +#define SIXAXIS_REPORT_0xF2_SIZE 18 + static spinlock_t sony_dev_list_lock; static LIST_HEAD(sony_device_list); static DEFINE_IDA(sony_device_id_allocator); @@ -811,6 +817,7 @@ struct sony_sc { struct work_struct state_worker; struct power_supply battery; int device_id; + __u8 *output_report_dmabuf; #ifdef CONFIG_SONY_FF __u8 left; @@ -1142,9 +1149,20 @@ static int sixaxis_set_operational_usb(struct hid_device *hdev) static int sixaxis_set_operational_bt(struct hid_device *hdev) { - unsigned char buf[] = { 0xf4, 0x42, 0x03, 0x00, 0x00 }; - return hid_hw_raw_request(hdev, buf[0], buf, sizeof(buf), + static const __u8 report[] = { 0xf4, 0x42, 0x03, 0x00, 0x00 }; + __u8 *buf; + int ret; + + buf = kmemdup(report, sizeof(report), GFP_KERNEL); + if (!buf) + return -ENOMEM; + + ret = hid_hw_raw_request(hdev, buf[0], buf, sizeof(report), HID_FEATURE_REPORT, HID_REQ_SET_REPORT); + + kfree(buf); + + return ret; } /* @@ -1153,10 +1171,19 @@ static int sixaxis_set_operational_bt(struct hid_device *hdev) */ static int dualshock4_set_operational_bt(struct hid_device *hdev) { - __u8 buf[37] = { 0 }; + __u8 *buf; + int ret; + + buf = kmalloc(DS4_REPORT_0x02_SIZE, GFP_KERNEL); + if (!buf) + return -ENOMEM; - return hid_hw_raw_request(hdev, 0x02, buf, sizeof(buf), + ret = hid_hw_raw_request(hdev, 0x02, buf, DS4_REPORT_0x02_SIZE, HID_FEATURE_REPORT, HID_REQ_GET_REPORT); + + kfree(buf); + + return ret; } static void sixaxis_set_leds_from_id(int id, __u8 values[MAX_LEDS]) @@ -1471,9 +1498,7 @@ error_leds: static void sixaxis_state_worker(struct work_struct *work) { - struct sony_sc *sc = container_of(work, struct sony_sc, state_worker); - int n; - union sixaxis_output_report_01 report = { + static const union sixaxis_output_report_01 default_report = { .buf = { 0x01, 0x00, 0xff, 0x00, 0xff, 0x00, @@ -1485,20 +1510,27 @@ static void sixaxis_state_worker(struct work_struct *work) 0x00, 0x00, 0x00, 0x00, 0x00 } }; + struct sony_sc *sc = container_of(work, struct sony_sc, state_worker); + struct sixaxis_output_report *report = + (struct sixaxis_output_report *)sc->output_report_dmabuf; + int n; + + /* Initialize the report with default values */ + memcpy(report, &default_report, sizeof(struct sixaxis_output_report)); #ifdef CONFIG_SONY_FF - report.data.rumble.right_motor_on = sc->right ? 1 : 0; - report.data.rumble.left_motor_force = sc->left; + report->rumble.right_motor_on = sc->right ? 1 : 0; + report->rumble.left_motor_force = sc->left; #endif - report.data.leds_bitmap |= sc->led_state[0] << 1; - report.data.leds_bitmap |= sc->led_state[1] << 2; - report.data.leds_bitmap |= sc->led_state[2] << 3; - report.data.leds_bitmap |= sc->led_state[3] << 4; + report->leds_bitmap |= sc->led_state[0] << 1; + report->leds_bitmap |= sc->led_state[1] << 2; + report->leds_bitmap |= sc->led_state[2] << 3; + report->leds_bitmap |= sc->led_state[3] << 4; /* Set flag for all leds off, required for 3rd party INTEC controller */ - if ((report.data.leds_bitmap & 0x1E) == 0) - report.data.leds_bitmap |= 0x20; + if ((report->leds_bitmap & 0x1E) == 0) + report->leds_bitmap |= 0x20; /* * The LEDs in the report are indexed in reverse order to their @@ -1511,28 +1543,30 @@ static void sixaxis_state_worker(struct work_struct *work) */ for (n = 0; n < 4; n++) { if (sc->led_delay_on[n] || sc->led_delay_off[n]) { - report.data.led[3 - n].duty_off = sc->led_delay_off[n]; - report.data.led[3 - n].duty_on = sc->led_delay_on[n]; + report->led[3 - n].duty_off = sc->led_delay_off[n]; + report->led[3 - n].duty_on = sc->led_delay_on[n]; } } - hid_hw_raw_request(sc->hdev, report.data.report_id, report.buf, - sizeof(report), HID_OUTPUT_REPORT, HID_REQ_SET_REPORT); + hid_hw_raw_request(sc->hdev, report->report_id, (__u8 *)report, + sizeof(struct sixaxis_output_report), + HID_OUTPUT_REPORT, HID_REQ_SET_REPORT); } static void dualshock4_state_worker(struct work_struct *work) { struct sony_sc *sc = container_of(work, struct sony_sc, state_worker); struct hid_device *hdev = sc->hdev; + __u8 *buf = sc->output_report_dmabuf; int offset; - __u8 buf[78] = { 0 }; - if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) { + memset(buf, 0, DS4_REPORT_0x05_SIZE); buf[0] = 0x05; buf[1] = 0xFF; offset = 4; } else { + memset(buf, 0, DS4_REPORT_0x11_SIZE); buf[0] = 0x11; buf[1] = 0xB0; buf[3] = 0x0F; @@ -1560,12 +1594,33 @@ static void dualshock4_state_worker(struct work_struct *work) buf[offset++] = sc->led_delay_off[3]; if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) - hid_hw_output_report(hdev, buf, 32); + hid_hw_output_report(hdev, buf, DS4_REPORT_0x05_SIZE); else - hid_hw_raw_request(hdev, 0x11, buf, 78, + hid_hw_raw_request(hdev, 0x11, buf, DS4_REPORT_0x11_SIZE, HID_OUTPUT_REPORT, HID_REQ_SET_REPORT); } +static int sony_allocate_output_report(struct sony_sc *sc) +{ + if (sc->quirks & SIXAXIS_CONTROLLER) + sc->output_report_dmabuf = + kmalloc(sizeof(union sixaxis_output_report_01), + GFP_KERNEL); + else if (sc->quirks & DUALSHOCK4_CONTROLLER_BT) + sc->output_report_dmabuf = kmalloc(DS4_REPORT_0x11_SIZE, + GFP_KERNEL); + else if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) + sc->output_report_dmabuf = kmalloc(DS4_REPORT_0x05_SIZE, + GFP_KERNEL); + else + return 0; + + if (!sc->output_report_dmabuf) + return -ENOMEM; + + return 0; +} + #ifdef CONFIG_SONY_FF static int sony_play_effect(struct input_dev *dev, void *data, struct ff_effect *effect) @@ -1754,6 +1809,7 @@ static int sony_get_bt_devaddr(struct sony_sc *sc) static int sony_check_add(struct sony_sc *sc) { + __u8 *buf = NULL; int n, ret; if ((sc->quirks & DUALSHOCK4_CONTROLLER_BT) || @@ -1769,36 +1825,44 @@ static int sony_check_add(struct sony_sc *sc) return 0; } } else if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) { - __u8 buf[7]; + buf = kmalloc(DS4_REPORT_0x81_SIZE, GFP_KERNEL); + if (!buf) + return -ENOMEM; /* * The MAC address of a DS4 controller connected via USB can be * retrieved with feature report 0x81. The address begins at * offset 1. */ - ret = hid_hw_raw_request(sc->hdev, 0x81, buf, sizeof(buf), - HID_FEATURE_REPORT, HID_REQ_GET_REPORT); + ret = hid_hw_raw_request(sc->hdev, 0x81, buf, + DS4_REPORT_0x81_SIZE, HID_FEATURE_REPORT, + HID_REQ_GET_REPORT); - if (ret != 7) { + if (ret != DS4_REPORT_0x81_SIZE) { hid_err(sc->hdev, "failed to retrieve feature report 0x81 with the DualShock 4 MAC address\n"); - return ret < 0 ? ret : -EINVAL; + ret = ret < 0 ? ret : -EINVAL; + goto out_free; } memcpy(sc->mac_address, &buf[1], sizeof(sc->mac_address)); } else if (sc->quirks & SIXAXIS_CONTROLLER_USB) { - __u8 buf[18]; + buf = kmalloc(SIXAXIS_REPORT_0xF2_SIZE, GFP_KERNEL); + if (!buf) + return -ENOMEM; /* * The MAC address of a Sixaxis controller connected via USB can * be retrieved with feature report 0xf2. The address begins at * offset 4. */ - ret = hid_hw_raw_request(sc->hdev, 0xf2, buf, sizeof(buf), - HID_FEATURE_REPORT, HID_REQ_GET_REPORT); + ret = hid_hw_raw_request(sc->hdev, 0xf2, buf, + SIXAXIS_REPORT_0xF2_SIZE, HID_FEATURE_REPORT, + HID_REQ_GET_REPORT); - if (ret != 18) { + if (ret != SIXAXIS_REPORT_0xF2_SIZE) { hid_err(sc->hdev, "failed to retrieve feature report 0xf2 with the Sixaxis MAC address\n"); - return ret < 0 ? ret : -EINVAL; + ret = ret < 0 ? ret : -EINVAL; + goto out_free; } /* @@ -1811,7 +1875,13 @@ static int sony_check_add(struct sony_sc *sc) return 0; } - return sony_check_add_dev_list(sc); + ret = sony_check_add_dev_list(sc); + +out_free: + + kfree(buf); + + return ret; } static int sony_set_device_id(struct sony_sc *sc) @@ -1895,6 +1965,12 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) return ret; } + ret = sony_allocate_output_report(sc); + if (ret < 0) { + hid_err(hdev, "failed to allocate the output report buffer\n"); + goto err_stop; + } + ret = sony_set_device_id(sc); if (ret < 0) { hid_err(hdev, "failed to allocate the device id\n"); @@ -1984,6 +2060,7 @@ err_stop: if (sc->quirks & SONY_BATTERY_SUPPORT) sony_battery_remove(sc); sony_cancel_work_sync(sc); + kfree(sc->output_report_dmabuf); sony_remove_dev_list(sc); sony_release_device_id(sc); hid_hw_stop(hdev); @@ -2004,6 +2081,8 @@ static void sony_remove(struct hid_device *hdev) sony_cancel_work_sync(sc); + kfree(sc->output_report_dmabuf); + sony_remove_dev_list(sc); sony_release_device_id(sc); @@ -2034,6 +2113,9 @@ static const struct hid_device_id sony_devices[] = { /* Logitech Harmony Adapter for PS3 */ { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_HARMONY_PS3), .driver_data = PS3REMOTE }, + /* SMK-Link PS3 BD Remote Control */ + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SMK, USB_DEVICE_ID_SMK_PS3_BDREMOTE), + .driver_data = PS3REMOTE }, /* Sony Dualshock 4 controllers for PS4 */ { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER), .driver_data = DUALSHOCK4_CONTROLLER_USB }, diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid.c index 747d54421e73..fbd07812f2d9 100644 --- a/drivers/hid/i2c-hid/i2c-hid.c +++ b/drivers/hid/i2c-hid/i2c-hid.c @@ -137,6 +137,7 @@ struct i2c_hid { * descriptor. */ unsigned int bufsize; /* i2c buffer size */ char *inbuf; /* Input buffer */ + char *rawbuf; /* Raw Input buffer */ char *cmdbuf; /* Command buffer */ char *argsbuf; /* Command arguments buffer */ @@ -369,7 +370,7 @@ static int i2c_hid_hwreset(struct i2c_client *client) static void i2c_hid_get_input(struct i2c_hid *ihid) { int ret, ret_size; - int size = le16_to_cpu(ihid->hdesc.wMaxInputLength); + int size = ihid->bufsize; ret = i2c_master_recv(ihid->client, ihid->inbuf, size); if (ret != size) { @@ -437,7 +438,7 @@ static void i2c_hid_init_report(struct hid_report *report, u8 *buffer, report->id, buffer, size)) return; - i2c_hid_dbg(ihid, "report (len=%d): %*ph\n", size, size, ihid->inbuf); + i2c_hid_dbg(ihid, "report (len=%d): %*ph\n", size, size, buffer); ret_size = buffer[0] | (buffer[1] << 8); @@ -504,9 +505,11 @@ static void i2c_hid_find_max_report(struct hid_device *hid, unsigned int type, static void i2c_hid_free_buffers(struct i2c_hid *ihid) { kfree(ihid->inbuf); + kfree(ihid->rawbuf); kfree(ihid->argsbuf); kfree(ihid->cmdbuf); ihid->inbuf = NULL; + ihid->rawbuf = NULL; ihid->cmdbuf = NULL; ihid->argsbuf = NULL; ihid->bufsize = 0; @@ -522,10 +525,11 @@ static int i2c_hid_alloc_buffers(struct i2c_hid *ihid, size_t report_size) report_size; /* report */ ihid->inbuf = kzalloc(report_size, GFP_KERNEL); + ihid->rawbuf = kzalloc(report_size, GFP_KERNEL); ihid->argsbuf = kzalloc(args_len, GFP_KERNEL); ihid->cmdbuf = kzalloc(sizeof(union command) + args_len, GFP_KERNEL); - if (!ihid->inbuf || !ihid->argsbuf || !ihid->cmdbuf) { + if (!ihid->inbuf || !ihid->rawbuf || !ihid->argsbuf || !ihid->cmdbuf) { i2c_hid_free_buffers(ihid); return -ENOMEM; } @@ -552,12 +556,12 @@ static int i2c_hid_get_raw_report(struct hid_device *hid, ret = i2c_hid_get_report(client, report_type == HID_FEATURE_REPORT ? 0x03 : 0x01, - report_number, ihid->inbuf, ask_count); + report_number, ihid->rawbuf, ask_count); if (ret < 0) return ret; - ret_count = ihid->inbuf[0] | (ihid->inbuf[1] << 8); + ret_count = ihid->rawbuf[0] | (ihid->rawbuf[1] << 8); if (ret_count <= 2) return 0; @@ -566,7 +570,7 @@ static int i2c_hid_get_raw_report(struct hid_device *hid, /* The query buffer contains the size, dropping it in the reply */ count = min(count, ret_count - 2); - memcpy(buf, ihid->inbuf + 2, count); + memcpy(buf, ihid->rawbuf + 2, count); return count; } diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index ca6849a0121e..bfbe1bedda7f 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c @@ -278,18 +278,20 @@ static void hid_irq_in(struct urb *urb) usbhid->retry_delay = 0; if ((hid->quirks & HID_QUIRK_ALWAYS_POLL) && !hid->open) break; - hid_input_report(urb->context, HID_INPUT_REPORT, - urb->transfer_buffer, - urb->actual_length, 1); - /* - * autosuspend refused while keys are pressed - * because most keyboards don't wake up when - * a key is released - */ - if (hid_check_keys_pressed(hid)) - set_bit(HID_KEYS_PRESSED, &usbhid->iofl); - else - clear_bit(HID_KEYS_PRESSED, &usbhid->iofl); + if (!test_bit(HID_RESUME_RUNNING, &usbhid->iofl)) { + hid_input_report(urb->context, HID_INPUT_REPORT, + urb->transfer_buffer, + urb->actual_length, 1); + /* + * autosuspend refused while keys are pressed + * because most keyboards don't wake up when + * a key is released + */ + if (hid_check_keys_pressed(hid)) + set_bit(HID_KEYS_PRESSED, &usbhid->iofl); + else + clear_bit(HID_KEYS_PRESSED, &usbhid->iofl); + } break; case -EPIPE: /* stall */ usbhid_mark_busy(usbhid); @@ -338,8 +340,7 @@ static int hid_submit_out(struct hid_device *hid) report = usbhid->out[usbhid->outtail].report; raw_report = usbhid->out[usbhid->outtail].raw_report; - usbhid->urbout->transfer_buffer_length = ((report->size - 1) >> 3) + - 1 + (report->id > 0); + usbhid->urbout->transfer_buffer_length = hid_report_len(report); usbhid->urbout->dev = hid_to_usb_dev(hid); if (raw_report) { memcpy(usbhid->outbuf, raw_report, @@ -688,6 +689,7 @@ int usbhid_open(struct hid_device *hid) goto done; } usbhid->intf->needs_remote_wakeup = 1; + set_bit(HID_RESUME_RUNNING, &usbhid->iofl); res = hid_start_in(hid); if (res) { if (res != -ENOSPC) { @@ -701,6 +703,15 @@ int usbhid_open(struct hid_device *hid) } } usb_autopm_put_interface(usbhid->intf); + + /* + * In case events are generated while nobody was listening, + * some are released when the device is re-opened. + * Wait 50 msec for the queue to empty before allowing events + * to go through hid. + */ + msleep(50); + clear_bit(HID_RESUME_RUNNING, &usbhid->iofl); } done: mutex_unlock(&hid_open_mut); diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index f3cb5b0a4345..dc89be90b35e 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c @@ -71,10 +71,15 @@ static const struct hid_blacklist { { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_AXIS_295, HID_QUIRK_NOGET }, { USB_VENDOR_ID_DMI, USB_DEVICE_ID_DMI_ENC, HID_QUIRK_NOGET }, { USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ELAN_TOUCHSCREEN, HID_QUIRK_ALWAYS_POLL }, + { USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ELAN_TOUCHSCREEN_009B, HID_QUIRK_ALWAYS_POLL }, + { USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ELAN_TOUCHSCREEN_0103, HID_QUIRK_ALWAYS_POLL }, + { USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ELAN_TOUCHSCREEN_010c, HID_QUIRK_ALWAYS_POLL }, + { USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ELAN_TOUCHSCREEN_016F, HID_QUIRK_ALWAYS_POLL }, { 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_FREESCALE, USB_DEVICE_ID_FREESCALE_MX28, 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_MSI, USB_DEVICE_ID_MSI_GT683R_LED_PANEL, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_NEXIO, USB_DEVICE_ID_NEXIO_MULTITOUCH_PTI0750, HID_QUIRK_NO_INIT_REPORTS }, { USB_VENDOR_ID_NOVATEK, USB_DEVICE_ID_NOVATEK_MOUSE, HID_QUIRK_NO_INIT_REPORTS }, diff --git a/drivers/hid/usbhid/usbhid.h b/drivers/hid/usbhid/usbhid.h index f633c24ce28b..807922b49aa4 100644 --- a/drivers/hid/usbhid/usbhid.h +++ b/drivers/hid/usbhid/usbhid.h @@ -52,6 +52,7 @@ struct usb_interface *usbhid_find_interface(int minor); #define HID_STARTED 8 #define HID_KEYS_PRESSED 10 #define HID_NO_BANDWIDTH 11 +#define HID_RESUME_RUNNING 12 /* * USB-specific HID struct, to be pointed to diff --git a/drivers/hid/wacom.h b/drivers/hid/wacom.h index 0cc53440543a..7db432809e9e 100644 --- a/drivers/hid/wacom.h +++ b/drivers/hid/wacom.h @@ -140,7 +140,7 @@ extern const struct hid_device_id wacom_ids[]; void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len); void wacom_setup_device_quirks(struct wacom_features *features); -int wacom_setup_input_capabilities(struct input_dev *input_dev, +int wacom_setup_pentouch_input_capabilities(struct input_dev *input_dev, struct wacom_wac *wacom_wac); int wacom_setup_pad_input_capabilities(struct input_dev *input_dev, struct wacom_wac *wacom_wac); diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c index 8593047bb726..654202941d30 100644 --- a/drivers/hid/wacom_sys.c +++ b/drivers/hid/wacom_sys.c @@ -13,6 +13,7 @@ #include "wacom_wac.h" #include "wacom.h" +#include <linux/input/mt.h> #define WAC_MSG_RETRIES 5 @@ -70,22 +71,15 @@ static int wacom_raw_event(struct hid_device *hdev, struct hid_report *report, static int wacom_open(struct input_dev *dev) { struct wacom *wacom = input_get_drvdata(dev); - int retval; - - mutex_lock(&wacom->lock); - retval = hid_hw_open(wacom->hdev); - mutex_unlock(&wacom->lock); - return retval; + return hid_hw_open(wacom->hdev); } static void wacom_close(struct input_dev *dev) { struct wacom *wacom = input_get_drvdata(dev); - mutex_lock(&wacom->lock); hid_hw_close(wacom->hdev); - mutex_unlock(&wacom->lock); } /* @@ -192,9 +186,15 @@ static void wacom_usage_mapping(struct hid_device *hdev, if (!pen && !finger) return; - if (finger && !features->touch_max) - /* touch device at least supports one touch point */ - features->touch_max = 1; + /* + * Bamboo models do not support HID_DG_CONTACTMAX. + * And, Bamboo Pen only descriptor contains touch. + */ + if (features->type != BAMBOO_PT) { + /* ISDv4 touch devices at least supports one touch point */ + if (finger && !features->touch_max) + features->touch_max = 1; + } switch (usage->hid) { case HID_GD_X: @@ -230,6 +230,21 @@ static void wacom_usage_mapping(struct hid_device *hdev, wacom_wac_usage_mapping(hdev, field, usage); } +static void wacom_post_parse_hid(struct hid_device *hdev, + struct wacom_features *features) +{ + struct wacom *wacom = hid_get_drvdata(hdev); + struct wacom_wac *wacom_wac = &wacom->wacom_wac; + + if (features->type == HID_GENERIC) { + /* Any last-minute generic device setup */ + if (features->touch_max > 1) { + input_mt_init_slots(wacom_wac->input, wacom_wac->features.touch_max, + INPUT_MT_DIRECT); + } + } +} + static void wacom_parse_hid(struct hid_device *hdev, struct wacom_features *features) { @@ -264,6 +279,8 @@ static void wacom_parse_hid(struct hid_device *hdev, wacom_usage_mapping(hdev, hreport->field[i], hreport->field[i]->usage + j); } + + wacom_post_parse_hid(hdev, features); } static int wacom_hid_set_device_mode(struct hid_device *hdev) @@ -1129,7 +1146,7 @@ static void wacom_clean_inputs(struct wacom *wacom) input_free_device(wacom->wacom_wac.input); } if (wacom->wacom_wac.pad_input) { - if (wacom->wacom_wac.input_registered) + if (wacom->wacom_wac.pad_registered) input_unregister_device(wacom->wacom_wac.pad_input); else input_free_device(wacom->wacom_wac.pad_input); @@ -1151,13 +1168,13 @@ static int wacom_register_inputs(struct wacom *wacom) if (!input_dev || !pad_input_dev) return -EINVAL; - error = wacom_setup_input_capabilities(input_dev, wacom_wac); - if (error) - return error; - - error = input_register_device(input_dev); - if (error) - return error; + error = wacom_setup_pentouch_input_capabilities(input_dev, wacom_wac); + if (!error) { + error = input_register_device(input_dev); + if (error) + return error; + wacom_wac->input_registered = true; + } error = wacom_setup_pad_input_capabilities(pad_input_dev, wacom_wac); if (error) { @@ -1169,22 +1186,23 @@ static int wacom_register_inputs(struct wacom *wacom) error = input_register_device(pad_input_dev); if (error) goto fail_register_pad_input; + wacom_wac->pad_registered = true; error = wacom_initialize_leds(wacom); if (error) goto fail_leds; } - wacom_wac->input_registered = true; - return 0; fail_leds: input_unregister_device(pad_input_dev); pad_input_dev = NULL; + wacom_wac->pad_registered = false; fail_register_pad_input: input_unregister_device(input_dev); wacom_wac->input = NULL; + wacom_wac->input_registered = false; return error; } @@ -1321,12 +1339,6 @@ static void wacom_calculate_res(struct wacom_features *features) features->unitExpo); } -static int wacom_hid_report_len(struct hid_report *report) -{ - /* equivalent to DIV_ROUND_UP(report->size, 8) + !!(report->id > 0) */ - return ((report->size - 1) >> 3) + 1 + (report->id > 0); -} - static size_t wacom_compute_pktlen(struct hid_device *hdev) { struct hid_report_enum *report_enum; @@ -1336,7 +1348,7 @@ static size_t wacom_compute_pktlen(struct hid_device *hdev) report_enum = hdev->report_enum + HID_INPUT_REPORT; list_for_each_entry(report, &report_enum->report_list, list) { - size_t report_size = wacom_hid_report_len(report); + size_t report_size = hid_report_len(report); if (report_size > size) size = report_size; } diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index 586b2405b0d4..ac7447c7b82e 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -25,6 +25,10 @@ #define WACOM_INTUOS_RES 100 #define WACOM_INTUOS3_RES 200 +/* Newer Cintiq and DTU have an offset between tablet and screen areas */ +#define WACOM_DTU_OFFSET 200 +#define WACOM_CINTIQ_OFFSET 400 + /* * Scale factor relating reported contact size to logical contact area. * 2^14/pi is a good approximation on Intuos5 and 3rd-gen Bamboo @@ -600,8 +604,8 @@ static void wacom_intuos_general(struct wacom_wac *wacom) } input_report_abs(input, ABS_PRESSURE, t); input_report_abs(input, ABS_TILT_X, - ((data[7] << 1) & 0x7e) | (data[8] >> 7)); - input_report_abs(input, ABS_TILT_Y, data[8] & 0x7f); + (((data[7] << 1) & 0x7e) | (data[8] >> 7)) - 64); + input_report_abs(input, ABS_TILT_Y, (data[8] & 0x7f) - 64); input_report_key(input, BTN_STYLUS, data[1] & 2); input_report_key(input, BTN_STYLUS2, data[1] & 4); input_report_key(input, BTN_TOUCH, t > 10); @@ -612,8 +616,8 @@ static void wacom_intuos_general(struct wacom_wac *wacom) input_report_abs(input, ABS_WHEEL, (data[6] << 2) | ((data[7] >> 6) & 3)); input_report_abs(input, ABS_TILT_X, - ((data[7] << 1) & 0x7e) | (data[8] >> 7)); - input_report_abs(input, ABS_TILT_Y, data[8] & 0x7f); + (((data[7] << 1) & 0x7e) | (data[8] >> 7)) - 64); + input_report_abs(input, ABS_TILT_Y, (data[8] & 0x7f) - 64); } } @@ -915,8 +919,8 @@ static int wacom_intuos_irq(struct wacom_wac *wacom) input_report_key(input, BTN_EXTRA, data[6] & 0x10); input_report_abs(input, ABS_TILT_X, - ((data[7] << 1) & 0x7e) | (data[8] >> 7)); - input_report_abs(input, ABS_TILT_Y, data[8] & 0x7f); + (((data[7] << 1) & 0x7e) | (data[8] >> 7)) - 64); + input_report_abs(input, ABS_TILT_Y, (data[8] & 0x7f) - 64); } else { /* 2D mouse packet */ input_report_key(input, BTN_LEFT, data[8] & 0x04); @@ -1377,11 +1381,12 @@ static void wacom_wac_finger_usage_mapping(struct hid_device *hdev, { struct wacom *wacom = hid_get_drvdata(hdev); struct wacom_wac *wacom_wac = &wacom->wacom_wac; - struct input_dev *input = wacom_wac->input; + struct wacom_features *features = &wacom_wac->features; unsigned touch_max = wacom_wac->features.touch_max; switch (usage->hid) { case HID_GD_X: + features->last_slot_field = usage->hid; if (touch_max == 1) wacom_map_usage(wacom, usage, field, EV_ABS, ABS_X, 4); else @@ -1389,6 +1394,7 @@ static void wacom_wac_finger_usage_mapping(struct hid_device *hdev, ABS_MT_POSITION_X, 4); break; case HID_GD_Y: + features->last_slot_field = usage->hid; if (touch_max == 1) wacom_map_usage(wacom, usage, field, EV_ABS, ABS_Y, 4); else @@ -1396,19 +1402,48 @@ static void wacom_wac_finger_usage_mapping(struct hid_device *hdev, ABS_MT_POSITION_Y, 4); break; case HID_DG_CONTACTID: - input_mt_init_slots(input, wacom_wac->features.touch_max, - INPUT_MT_DIRECT); + features->last_slot_field = usage->hid; break; case HID_DG_INRANGE: + features->last_slot_field = usage->hid; break; case HID_DG_INVERT: + features->last_slot_field = usage->hid; break; case HID_DG_TIPSWITCH: + features->last_slot_field = usage->hid; wacom_map_usage(wacom, usage, field, EV_KEY, BTN_TOUCH, 0); break; } } +static void wacom_wac_finger_slot(struct wacom_wac *wacom_wac, + struct input_dev *input) +{ + struct hid_data *hid_data = &wacom_wac->hid_data; + bool mt = wacom_wac->features.touch_max > 1; + bool prox = hid_data->tipswitch && + !wacom_wac->shared->stylus_in_proximity; + + if (mt) { + int slot; + + slot = input_mt_get_slot_by_key(input, hid_data->id); + input_mt_slot(input, slot); + input_mt_report_slot_state(input, MT_TOOL_FINGER, prox); + } + else { + input_report_key(input, BTN_TOUCH, prox); + } + + if (prox) { + input_report_abs(input, mt ? ABS_MT_POSITION_X : ABS_X, + hid_data->x); + input_report_abs(input, mt ? ABS_MT_POSITION_Y : ABS_Y, + hid_data->y); + } +} + static int wacom_wac_finger_event(struct hid_device *hdev, struct hid_field *field, struct hid_usage *usage, __s32 value) { @@ -1431,36 +1466,35 @@ static int wacom_wac_finger_event(struct hid_device *hdev, } + if (usage->usage_index + 1 == field->report_count) { + if (usage->hid == wacom_wac->features.last_slot_field) + wacom_wac_finger_slot(wacom_wac, wacom_wac->input); + } + return 0; } -static void wacom_wac_finger_mt_report(struct wacom_wac *wacom_wac, - struct input_dev *input, bool touch) +static int wacom_wac_finger_count_touches(struct hid_device *hdev) { - int slot; - struct hid_data *hid_data = &wacom_wac->hid_data; + struct wacom *wacom = hid_get_drvdata(hdev); + struct wacom_wac *wacom_wac = &wacom->wacom_wac; + struct input_dev *input = wacom_wac->input; + unsigned touch_max = wacom_wac->features.touch_max; + int count = 0; + int i; - slot = input_mt_get_slot_by_key(input, hid_data->id); + if (touch_max == 1) + return wacom_wac->hid_data.tipswitch && + !wacom_wac->shared->stylus_in_proximity; - input_mt_slot(input, slot); - input_mt_report_slot_state(input, MT_TOOL_FINGER, touch); - if (touch) { - input_report_abs(input, ABS_MT_POSITION_X, hid_data->x); - input_report_abs(input, ABS_MT_POSITION_Y, hid_data->y); + for (i = 0; i < input->mt->num_slots; i++) { + struct input_mt_slot *ps = &input->mt->slots[i]; + int id = input_mt_get_value(ps, ABS_MT_TRACKING_ID); + if (id >= 0) + count++; } - input_mt_sync_frame(input); -} -static void wacom_wac_finger_single_touch_report(struct wacom_wac *wacom_wac, - struct input_dev *input, bool touch) -{ - struct hid_data *hid_data = &wacom_wac->hid_data; - - if (touch) { - input_report_abs(input, ABS_X, hid_data->x); - input_report_abs(input, ABS_Y, hid_data->y); - } - input_report_key(input, BTN_TOUCH, touch); + return count; } static void wacom_wac_finger_report(struct hid_device *hdev, @@ -1469,24 +1503,23 @@ static void wacom_wac_finger_report(struct hid_device *hdev, struct wacom *wacom = hid_get_drvdata(hdev); struct wacom_wac *wacom_wac = &wacom->wacom_wac; struct input_dev *input = wacom_wac->input; - bool touch = wacom_wac->hid_data.tipswitch && - !wacom_wac->shared->stylus_in_proximity; unsigned touch_max = wacom_wac->features.touch_max; if (touch_max > 1) - wacom_wac_finger_mt_report(wacom_wac, input, touch); - else - wacom_wac_finger_single_touch_report(wacom_wac, input, touch); + input_mt_sync_frame(input); + input_sync(input); /* keep touch state for pen event */ - wacom_wac->shared->touch_down = touch; + wacom_wac->shared->touch_down = wacom_wac_finger_count_touches(hdev); } #define WACOM_PEN_FIELD(f) (((f)->logical == HID_DG_STYLUS) || \ - ((f)->physical == HID_DG_STYLUS)) + ((f)->physical == HID_DG_STYLUS) || \ + ((f)->application == HID_DG_PEN)) #define WACOM_FINGER_FIELD(f) (((f)->logical == HID_DG_FINGER) || \ - ((f)->physical == HID_DG_FINGER)) + ((f)->physical == HID_DG_FINGER) || \ + ((f)->application == HID_DG_TOUCHSCREEN)) void wacom_wac_usage_mapping(struct hid_device *hdev, struct hid_field *field, struct hid_usage *usage) @@ -1681,7 +1714,9 @@ static int wacom_bpt_pen(struct wacom_wac *wacom) return 0; if (data[0] == WACOM_REPORT_USB) { - if (features->type == INTUOSHT && features->touch_max) { + if (features->type == INTUOSHT && + wacom->shared->touch_input && + features->touch_max) { input_report_switch(wacom->shared->touch_input, SW_MUTE_DEVICE, data[8] & 0x40); input_sync(wacom->shared->touch_input); @@ -1774,7 +1809,8 @@ static int wacom_wireless_irq(struct wacom_wac *wacom, size_t len) int pid, battery, ps_connected; if ((wacom->shared->type == INTUOSHT) && - wacom->shared->touch_max) { + wacom->shared->touch_input && + wacom->shared->touch_max) { input_report_switch(wacom->shared->touch_input, SW_MUTE_DEVICE, data[5] & 0x40); input_sync(wacom->shared->touch_input); @@ -1838,6 +1874,7 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len) break; case DTUS: + case DTUSX: sync = wacom_dtus_irq(wacom_wac); break; @@ -1926,8 +1963,10 @@ static void wacom_setup_cintiq(struct wacom_wac *wacom_wac) input_set_abs_params(input_dev, ABS_DISTANCE, 0, wacom_wac->features.distance_max, 0, 0); input_set_abs_params(input_dev, ABS_WHEEL, 0, 1023, 0, 0); - input_set_abs_params(input_dev, ABS_TILT_X, 0, 127, 0, 0); - input_set_abs_params(input_dev, ABS_TILT_Y, 0, 127, 0, 0); + input_set_abs_params(input_dev, ABS_TILT_X, -64, 63, 0, 0); + input_abs_set_res(input_dev, ABS_TILT_X, 57); + input_set_abs_params(input_dev, ABS_TILT_Y, -64, 63, 0, 0); + input_abs_set_res(input_dev, ABS_TILT_Y, 57); } static void wacom_setup_intuos(struct wacom_wac *wacom_wac) @@ -1947,6 +1986,7 @@ static void wacom_setup_intuos(struct wacom_wac *wacom_wac) __set_bit(BTN_TOOL_LENS, input_dev->keybit); input_set_abs_params(input_dev, ABS_RZ, -900, 899, 0, 0); + input_abs_set_res(input_dev, ABS_RZ, 287); input_set_abs_params(input_dev, ABS_THROTTLE, -1023, 1023, 0, 0); } @@ -2029,7 +2069,7 @@ static void wacom_abs_set_axis(struct input_dev *input_dev, } } -int wacom_setup_input_capabilities(struct input_dev *input_dev, +int wacom_setup_pentouch_input_capabilities(struct input_dev *input_dev, struct wacom_wac *wacom_wac) { struct wacom_features *features = &wacom_wac->features; @@ -2047,9 +2087,6 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev, switch (features->type) { case WACOM_MO: - input_set_abs_params(input_dev, ABS_WHEEL, 0, 71, 0, 0); - /* fall through */ - case WACOM_G4: /* fall through */ @@ -2092,6 +2129,7 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev, case WACOM_24HD: input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0); + input_abs_set_res(input_dev, ABS_Z, 287); input_set_abs_params(input_dev, ABS_THROTTLE, 0, 71, 0, 0); /* fall through */ @@ -2106,6 +2144,7 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev, case WACOM_BEE: case CINTIQ: input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0); + input_abs_set_res(input_dev, ABS_Z, 287); __set_bit(INPUT_PROP_DIRECT, input_dev->propbit); @@ -2114,6 +2153,7 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev, case WACOM_13HD: input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0); + input_abs_set_res(input_dev, ABS_Z, 287); __set_bit(INPUT_PROP_DIRECT, input_dev->propbit); wacom_setup_cintiq(wacom_wac); break; @@ -2122,6 +2162,7 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev, case INTUOS3L: case INTUOS3S: input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0); + input_abs_set_res(input_dev, ABS_Z, 287); /* fall through */ case INTUOS: @@ -2144,6 +2185,7 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev, 0, 0); input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0); + input_abs_set_res(input_dev, ABS_Z, 287); wacom_setup_intuos(wacom_wac); } else if (features->device_type == BTN_TOOL_FINGER) { @@ -2162,6 +2204,7 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev, case INTUOS4L: case INTUOS4S: input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0); + input_abs_set_res(input_dev, ABS_Z, 287); wacom_setup_intuos(wacom_wac); __set_bit(INPUT_PROP_POINTER, input_dev->propbit); @@ -2196,6 +2239,7 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev, /* fall through */ case DTUS: + case DTUSX: case PL: case DTU: __set_bit(BTN_TOOL_PEN, input_dev->keybit); @@ -2246,6 +2290,9 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev, __clear_bit(ABS_X, input_dev->absbit); __clear_bit(ABS_Y, input_dev->absbit); __clear_bit(BTN_TOUCH, input_dev->keybit); + + /* PAD is setup by wacom_setup_pad_input_capabilities later */ + return 1; } } else if (features->device_type == BTN_TOOL_PEN) { __set_bit(INPUT_PROP_POINTER, input_dev->propbit); @@ -2261,6 +2308,7 @@ int wacom_setup_input_capabilities(struct input_dev *input_dev, case CINTIQ_HYBRID: input_set_abs_params(input_dev, ABS_Z, -900, 899, 0, 0); + input_abs_set_res(input_dev, ABS_Z, 287); __set_bit(INPUT_PROP_DIRECT, input_dev->propbit); wacom_setup_cintiq(wacom_wac); @@ -2303,9 +2351,7 @@ int wacom_setup_pad_input_capabilities(struct input_dev *input_dev, case WACOM_G4: __set_bit(BTN_BACK, input_dev->keybit); - __set_bit(BTN_LEFT, input_dev->keybit); __set_bit(BTN_FORWARD, input_dev->keybit); - __set_bit(BTN_RIGHT, input_dev->keybit); input_set_capability(input_dev, EV_REL, REL_WHEEL); break; @@ -2402,7 +2448,7 @@ int wacom_setup_pad_input_capabilities(struct input_dev *input_dev, case INTUOSPS: /* touch interface does not have the pad device */ if (features->device_type != BTN_TOOL_PEN) - return 1; + return -ENODEV; for (i = 0; i < 7; i++) __set_bit(BTN_0 + i, input_dev->keybit); @@ -2446,8 +2492,10 @@ int wacom_setup_pad_input_capabilities(struct input_dev *input_dev, case INTUOSHT: case BAMBOO_PT: /* pad device is on the touch interface */ - if (features->device_type != BTN_TOOL_FINGER) - return 1; + if ((features->device_type != BTN_TOOL_FINGER) || + /* Bamboo Pen only tablet does not have pad */ + ((features->type == BAMBOO_PT) && !features->touch_max)) + return -ENODEV; __clear_bit(ABS_MISC, input_dev->absbit); @@ -2460,7 +2508,7 @@ int wacom_setup_pad_input_capabilities(struct input_dev *input_dev, default: /* no pad supported */ - return 1; + return -ENODEV; } return 0; } @@ -2664,11 +2712,13 @@ static const struct wacom_features wacom_features_0x317 = INTUOSPL, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, .touch_max = 16, .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE }; static const struct wacom_features wacom_features_0xF4 = - { "Wacom Cintiq 24HD", 104280, 65400, 2047, 63, - WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 200, 200 }; + { "Wacom Cintiq 24HD", 104080, 65200, 2047, 63, + WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, + WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET }; static const struct wacom_features wacom_features_0xF8 = - { "Wacom Cintiq 24HD touch", 104280, 65400, 2047, 63, /* Pen */ - WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 200, 200, + { "Wacom Cintiq 24HD touch", 104080, 65200, 2047, 63, /* Pen */ + WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, + WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, .oVid = USB_VENDOR_ID_WACOM, .oPid = 0xf6 }; static const struct wacom_features wacom_features_0xF6 = { "Wacom Cintiq 24HD touch", .type = WACOM_24HDT, /* Touch */ @@ -2684,8 +2734,9 @@ static const struct wacom_features wacom_features_0xC6 = { "Wacom Cintiq 12WX", 53020, 33440, 1023, 63, WACOM_BEE, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES }; static const struct wacom_features wacom_features_0x304 = - { "Wacom Cintiq 13HD", 59352, 33648, 1023, 63, - WACOM_13HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 200, 200 }; + { "Wacom Cintiq 13HD", 59152, 33448, 1023, 63, + WACOM_13HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, + WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET }; static const struct wacom_features wacom_features_0xC7 = { "Wacom DTU1931", 37832, 30305, 511, 0, PL, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; @@ -2697,28 +2748,38 @@ static const struct wacom_features wacom_features_0xF0 = { "Wacom DTU1631", 34623, 19553, 511, 0, DTU, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0xFB = - { "Wacom DTU1031", 22096, 13960, 511, 0, - DTUS, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; + { "Wacom DTU1031", 21896, 13760, 511, 0, + DTUS, WACOM_INTUOS_RES, WACOM_INTUOS_RES, + WACOM_DTU_OFFSET, WACOM_DTU_OFFSET }; +static const struct wacom_features wacom_features_0x32F = + { "Wacom DTU1031X", 22472, 12728, 511, 0, + DTUSX, WACOM_INTUOS_RES, WACOM_INTUOS_RES, + WACOM_DTU_OFFSET, WACOM_DTU_OFFSET }; static const struct wacom_features wacom_features_0x57 = { "Wacom DTK2241", 95640, 54060, 2047, 63, - DTK, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 200, 200 }; + DTK, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, + WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET }; static const struct wacom_features wacom_features_0x59 = /* Pen */ { "Wacom DTH2242", 95640, 54060, 2047, 63, - DTK, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 200, 200, + DTK, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, + WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x5D }; static const struct wacom_features wacom_features_0x5D = /* Touch */ { "Wacom DTH2242", .type = WACOM_24HDT, .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x59, .touch_max = 10, .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE }; static const struct wacom_features wacom_features_0xCC = - { "Wacom Cintiq 21UX2", 87000, 65400, 2047, 63, - WACOM_21UX2, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 200, 200 }; + { "Wacom Cintiq 21UX2", 86800, 65200, 2047, 63, + WACOM_21UX2, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, + WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET }; static const struct wacom_features wacom_features_0xFA = - { "Wacom Cintiq 22HD", 95640, 54060, 2047, 63, - WACOM_22HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 200, 200 }; + { "Wacom Cintiq 22HD", 95440, 53860, 2047, 63, + WACOM_22HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, + WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET }; static const struct wacom_features wacom_features_0x5B = - { "Wacom Cintiq 22HDT", 95640, 54060, 2047, 63, - WACOM_22HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 200, 200, + { "Wacom Cintiq 22HDT", 95440, 53860, 2047, 63, + WACOM_22HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, + WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x5e }; static const struct wacom_features wacom_features_0x5E = { "Wacom Cintiq 22HDT", .type = WACOM_24HDT, @@ -2863,21 +2924,27 @@ static const struct wacom_features wacom_features_0x6004 = { "ISD-V4", 12800, 8000, 255, 0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0x307 = - { "Wacom ISDv5 307", 59352, 33648, 2047, 63, - CINTIQ_HYBRID, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 200, 200, + { "Wacom ISDv5 307", 59152, 33448, 2047, 63, + CINTIQ_HYBRID, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, + WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x309 }; static const struct wacom_features wacom_features_0x309 = { "Wacom ISDv5 309", .type = WACOM_24HDT, /* Touch */ .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x0307, .touch_max = 10, .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE }; static const struct wacom_features wacom_features_0x30A = - { "Wacom ISDv5 30A", 59352, 33648, 2047, 63, - CINTIQ_HYBRID, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, 200, 200, + { "Wacom ISDv5 30A", 59152, 33448, 2047, 63, + CINTIQ_HYBRID, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, + WACOM_CINTIQ_OFFSET, WACOM_CINTIQ_OFFSET, .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x30C }; static const struct wacom_features wacom_features_0x30C = { "Wacom ISDv5 30C", .type = WACOM_24HDT, /* Touch */ .oVid = USB_VENDOR_ID_WACOM, .oPid = 0x30A, .touch_max = 10, .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE }; +static const struct wacom_features wacom_features_0x323 = + { "Wacom Intuos P M", 21600, 13500, 1023, 31, + INTUOSHT, WACOM_INTUOS_RES, WACOM_INTUOS_RES, + .check_for_hid_type = true, .hid_type = HID_TYPE_USBNONE }; static const struct wacom_features wacom_features_HID_ANY_ID = { "Wacom HID", .type = HID_GENERIC }; @@ -3022,10 +3089,13 @@ const struct hid_device_id wacom_ids[] = { { USB_DEVICE_WACOM(0x314) }, { USB_DEVICE_WACOM(0x315) }, { USB_DEVICE_WACOM(0x317) }, + { USB_DEVICE_WACOM(0x323) }, + { USB_DEVICE_WACOM(0x32F) }, { USB_DEVICE_WACOM(0x4001) }, { USB_DEVICE_WACOM(0x4004) }, { USB_DEVICE_WACOM(0x5000) }, { USB_DEVICE_WACOM(0x5002) }, + { USB_DEVICE_LENOVO(0x6004) }, { USB_DEVICE_WACOM(HID_ANY_ID) }, { } diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h index 0f0b85ec1322..bfad815cda8a 100644 --- a/drivers/hid/wacom_wac.h +++ b/drivers/hid/wacom_wac.h @@ -80,6 +80,7 @@ enum { PL, DTU, DTUS, + DTUSX, INTUOS, INTUOS3S, INTUOS3, @@ -144,6 +145,7 @@ struct wacom_features { int pktlen; bool check_for_hid_type; int hid_type; + int last_slot_field; }; struct wacom_shared { @@ -183,6 +185,7 @@ struct wacom_wac { struct input_dev *input; struct input_dev *pad_input; bool input_registered; + bool pad_registered; int pid; int battery_capacity; int num_contacts_left; |