From e92865edebe90cde1eef968cf85acb6613e5695f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Br=C3=BCns?= Date: Thu, 5 Mar 2015 23:25:51 -0800 Subject: Input: use more descriptive KEY_ROTATE_DISPLAY instead of KEY_DIRECTION MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Stefan BrĂ¼ns Acked-by: Jiri Kosina Signed-off-by: Dmitry Torokhov --- drivers/hid/hid-debug.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-debug.c b/drivers/hid/hid-debug.c index 8bf61d2..1086800 100644 --- a/drivers/hid/hid-debug.c +++ b/drivers/hid/hid-debug.c @@ -814,7 +814,7 @@ static const char *keys[KEY_MAX + 1] = { [KEY_DELETEFILE] = "DeleteFile", [KEY_XFER] = "X-fer", [KEY_PROG1] = "Prog1", [KEY_PROG2] = "Prog2", [KEY_WWW] = "WWW", [KEY_MSDOS] = "MSDOS", - [KEY_COFFEE] = "Coffee", [KEY_DIRECTION] = "Direction", + [KEY_COFFEE] = "Coffee", [KEY_ROTATE_DISPLAY] = "RotateDisplay", [KEY_CYCLEWINDOWS] = "CycleWindows", [KEY_MAIL] = "Mail", [KEY_BOOKMARKS] = "Bookmarks", [KEY_COMPUTER] = "Computer", [KEY_BACK] = "Back", [KEY_FORWARD] = "Forward", -- cgit v1.1 From 42f4f272746f9e4e3fecb4440dc2429822b6950b Mon Sep 17 00:00:00 2001 From: Ping Cheng Date: Wed, 15 Apr 2015 16:53:54 -0700 Subject: HID: wacom: move all quirks to wacom_setup_device_quirks It makes probe routine easy to follow. Signed-off-by: Ping Cheng Reviewed-by: Jason Gerecke Signed-off-by: Jiri Kosina --- drivers/hid/wacom.h | 2 +- drivers/hid/wacom_sys.c | 39 +-------------------------------------- drivers/hid/wacom_wac.c | 30 +++++++++++++++++++++++++++++- 3 files changed, 31 insertions(+), 40 deletions(-) (limited to 'drivers/hid') diff --git a/drivers/hid/wacom.h b/drivers/hid/wacom.h index 024f4d89..c76e21f 100644 --- a/drivers/hid/wacom.h +++ b/drivers/hid/wacom.h @@ -134,7 +134,7 @@ static inline void wacom_schedule_work(struct wacom_wac *wacom_wac) 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); +void wacom_setup_device_quirks(struct wacom *wacom); 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, diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c index e8607d0..13d8c8f 100644 --- a/drivers/hid/wacom_sys.c +++ b/drivers/hid/wacom_sys.c @@ -1475,44 +1475,7 @@ static int wacom_probe(struct hid_device *hdev, /* Retrieve the physical and logical size for touch devices */ wacom_retrieve_hid_descriptor(hdev, features); - /* - * Intuos5 has no useful data about its touch interface in its - * HID descriptor. If this is the touch interface (PacketSize - * of WACOM_PKGLEN_BBTOUCH3), override the table values. - */ - if (features->type >= INTUOS5S && features->type <= INTUOSHT) { - if (features->pktlen == WACOM_PKGLEN_BBTOUCH3) { - features->device_type = BTN_TOOL_FINGER; - - features->x_max = 4096; - features->y_max = 4096; - } else { - features->device_type = BTN_TOOL_PEN; - } - } - - /* - * Same thing for Bamboo 3rd gen. - */ - if ((features->type == BAMBOO_PT) && - (features->pktlen == WACOM_PKGLEN_BBTOUCH3) && - (features->device_type == BTN_TOOL_PEN)) { - features->device_type = BTN_TOOL_FINGER; - - features->x_max = 4096; - features->y_max = 4096; - } - - /* - * Same thing for Bamboo PAD - */ - if (features->type == BAMBOO_PAD) - features->device_type = BTN_TOOL_FINGER; - - if (hdev->bus == BUS_BLUETOOTH) - features->quirks |= WACOM_QUIRK_BATTERY; - - wacom_setup_device_quirks(features); + wacom_setup_device_quirks(wacom); /* set unit to "100th of a mm" for devices not reported by HID */ if (!features->unit) { diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index fa54d32..3609cbe 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -2164,8 +2164,9 @@ static void wacom_setup_intuos(struct wacom_wac *wacom_wac) input_set_abs_params(input_dev, ABS_THROTTLE, -1023, 1023, 0, 0); } -void wacom_setup_device_quirks(struct wacom_features *features) +void wacom_setup_device_quirks(struct wacom *wacom) { + struct wacom_features *features = &wacom->wacom_wac.features; /* touch device found but size is not defined. use default */ if (features->device_type == BTN_TOOL_FINGER && !features->x_max) { @@ -2173,6 +2174,33 @@ void wacom_setup_device_quirks(struct wacom_features *features) features->y_max = 1023; } + /* + * Intuos5/Pro and Bamboo 3rd gen have no useful data about its + * touch interface in its HID descriptor. If this is the touch + * interface (PacketSize of WACOM_PKGLEN_BBTOUCH3), override the + * tablet values. + */ + if ((features->type >= INTUOS5S && features->type <= INTUOSHT) || + (features->type == BAMBOO_PT)) { + if (features->pktlen == WACOM_PKGLEN_BBTOUCH3) { + features->device_type = BTN_TOOL_FINGER; + + features->x_max = 4096; + features->y_max = 4096; + } else { + features->device_type = BTN_TOOL_PEN; + } + } + + /* + * Same thing for Bamboo PAD + */ + if (features->type == BAMBOO_PAD) + features->device_type = BTN_TOOL_FINGER; + + if (wacom->hdev->bus == BUS_BLUETOOTH) + features->quirks |= WACOM_QUIRK_BATTERY; + /* quirk for bamboo touch with 2 low res touches */ if (features->type == BAMBOO_PT && features->pktlen == WACOM_PKGLEN_BBTOUCH) { -- cgit v1.1 From 3d64f54dd0de57bdbcde4b91495fb8e02c620762 Mon Sep 17 00:00:00 2001 From: Ping Cheng Date: Wed, 15 Apr 2015 16:54:14 -0700 Subject: HID: wacom: move unit and unitExpo initialization to wacom_calculate_res That is where they belong... Signed-off-by: Ping Cheng Reviewed-by: Jason Gerecke Signed-off-by: Jiri Kosina --- drivers/hid/wacom_sys.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'drivers/hid') diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c index 13d8c8f..b3c6f11 100644 --- a/drivers/hid/wacom_sys.c +++ b/drivers/hid/wacom_sys.c @@ -1369,6 +1369,12 @@ static void wacom_set_default_phy(struct wacom_features *features) static void wacom_calculate_res(struct wacom_features *features) { + /* set unit to "100th of a mm" for devices not reported by HID */ + if (!features->unit) { + features->unit = 0x11; + features->unitExpo = -3; + } + features->x_resolution = wacom_calc_hid_res(features->x_max, features->x_phy, features->unit, @@ -1476,12 +1482,6 @@ static int wacom_probe(struct hid_device *hdev, wacom_retrieve_hid_descriptor(hdev, features); wacom_setup_device_quirks(wacom); - - /* set unit to "100th of a mm" for devices not reported by HID */ - if (!features->unit) { - features->unit = 0x11; - features->unitExpo = -3; - } wacom_calculate_res(features); strlcpy(wacom_wac->name, features->name, sizeof(wacom_wac->name)); -- cgit v1.1 From e48151a3a456b38b1029a8a7380246b53c768400 Mon Sep 17 00:00:00 2001 From: Ping Cheng Date: Wed, 15 Apr 2015 16:54:58 -0700 Subject: HID: wacom: remove unused packet lengths We use generic hid_report_len() to get individual packet length now. Signed-off-by: Ping Cheng Reviewed-by: Jason Gerecke Signed-off-by: Jiri Kosina --- drivers/hid/wacom_wac.h | 6 ------ 1 file changed, 6 deletions(-) (limited to 'drivers/hid') diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h index 4700ac9..f5a5f68 100644 --- a/drivers/hid/wacom_wac.h +++ b/drivers/hid/wacom_wac.h @@ -18,10 +18,7 @@ #define WACOM_NAME_MAX 64 /* packet length for individual models */ -#define WACOM_PKGLEN_PENPRTN 7 -#define WACOM_PKGLEN_GRAPHIRE 8 #define WACOM_PKGLEN_BBFUN 9 -#define WACOM_PKGLEN_INTUOS 10 #define WACOM_PKGLEN_TPC1FG 5 #define WACOM_PKGLEN_TPC1FG_B 10 #define WACOM_PKGLEN_TPC2FG 14 @@ -29,9 +26,6 @@ #define WACOM_PKGLEN_BBTOUCH3 64 #define WACOM_PKGLEN_BBPEN 10 #define WACOM_PKGLEN_WIRELESS 32 -#define WACOM_PKGLEN_MTOUCH 62 -#define WACOM_PKGLEN_MTTPC 40 -#define WACOM_PKGLEN_DTUS 68 #define WACOM_PKGLEN_PENABLED 8 #define WACOM_PKGLEN_BPAD_TOUCH 32 #define WACOM_PKGLEN_BPAD_TOUCH_USB 64 -- cgit v1.1 From 71b5c4766c1ca4c646a90f64552b140b1368f2f1 Mon Sep 17 00:00:00 2001 From: Jason Gerecke Date: Wed, 15 Apr 2015 17:22:32 -0700 Subject: HID: wacom: Simplify check for presence of single-finger touch To determine if a touch is present in the single-touch case, we can simply check if the BTN_TOUCH key is active or not. This will work for both HID_GENERIC and other device types. Signed-off-by: Jason Gerecke Signed-off-by: Jiri Kosina --- drivers/hid/wacom_wac.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers/hid') diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index 3609cbe..091bab4 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -1072,9 +1072,8 @@ static int wacom_wac_finger_count_touches(struct wacom_wac *wacom) int count = 0; int i; - /* non-HID_GENERIC single touch input doesn't call this routine */ - if ((touch_max == 1) && (wacom->features.type == HID_GENERIC)) - return wacom->hid_data.tipswitch && + if (touch_max == 1) + return test_bit(BTN_TOUCH, input->key) && !wacom->shared->stylus_in_proximity; for (i = 0; i < input->mt->num_slots; i++) { -- cgit v1.1 From 007760cf082392b65a05c40eb615c5f8294b441a Mon Sep 17 00:00:00 2001 From: Aaron Skomra Date: Thu, 16 Apr 2015 15:01:14 -0700 Subject: HID: wacom: Add support for DTU-1141 Signed-off-by: Aaron Skomra Signed-off-by: Jiri Kosina --- drivers/hid/wacom_wac.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'drivers/hid') diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index 091bab4..dff99ff 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -2946,6 +2946,9 @@ 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_0x336 = + { "Wacom DTU1141", 23472, 13203, 1023, 0, + DTUS, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; static const struct wacom_features wacom_features_0x57 = { "Wacom DTK2241", 95640, 54060, 2047, 63, DTK, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES, @@ -3299,6 +3302,7 @@ const struct hid_device_id wacom_ids[] = { { USB_DEVICE_WACOM(0x32F) }, { USB_DEVICE_WACOM(0x333) }, { USB_DEVICE_WACOM(0x335) }, + { USB_DEVICE_WACOM(0x336) }, { USB_DEVICE_WACOM(0x4001) }, { USB_DEVICE_WACOM(0x4004) }, { USB_DEVICE_WACOM(0x5000) }, -- cgit v1.1 From d92189ebbdcd0eb180317d8cd6d46c57ac9a3dc0 Mon Sep 17 00:00:00 2001 From: Andreas Fleig Date: Thu, 23 Apr 2015 10:25:58 +0200 Subject: HID: lenovo: set INPUT_PROP_POINTING_STICK Set flags INPUT_PROP_POINTER and INPUT_PROP_POINTING_STICK for the trackpoint integrated in Lenovo USB and Bluetooth keyboards. Libinput checks these flags to enable features such as middle-button-scrolling by default. Signed-off-by: Andreas Fleig Reviewed-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/hid-lenovo.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-lenovo.c b/drivers/hid/hid-lenovo.c index c4c3f09..78608d6 100644 --- a/drivers/hid/hid-lenovo.c +++ b/drivers/hid/hid-lenovo.c @@ -762,6 +762,24 @@ static void lenovo_remove(struct hid_device *hdev) hid_hw_stop(hdev); } +static void lenovo_input_configured(struct hid_device *hdev, + struct hid_input *hi) +{ + switch (hdev->product) { + case USB_DEVICE_ID_LENOVO_TPKBD: + case USB_DEVICE_ID_LENOVO_CUSBKBD: + case USB_DEVICE_ID_LENOVO_CBTKBD: + if (test_bit(EV_REL, hi->input->evbit)) { + /* set only for trackpoint device */ + __set_bit(INPUT_PROP_POINTER, hi->input->propbit); + __set_bit(INPUT_PROP_POINTING_STICK, + hi->input->propbit); + } + break; + } +} + + static const struct hid_device_id lenovo_devices[] = { { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_TPKBD) }, { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_CUSBKBD) }, @@ -774,6 +792,7 @@ MODULE_DEVICE_TABLE(hid, lenovo_devices); static struct hid_driver lenovo_driver = { .name = "lenovo", .id_table = lenovo_devices, + .input_configured = lenovo_input_configured, .input_mapping = lenovo_input_mapping, .probe = lenovo_probe, .remove = lenovo_remove, -- cgit v1.1 From c24eab4e0e449845ba98e649b0605ab0450193db Mon Sep 17 00:00:00 2001 From: Ping Cheng Date: Fri, 24 Apr 2015 15:32:51 -0700 Subject: HID: wacom: retrieve name from HID descriptor for generic devices HID generic devices share the same default name, "Wacom HID". This causes userland programs to show same device names for different devices, which would confuse end users with same device names for different devices too. This patch uses name retrieved from HID descriptor, if a meaningful name is reported. Otherwise, affix its product ID to "Wacom HID". Names from descriptor may contain extra whitespaces. To comfort readers' eyes, we removed those extra whitespaces too. Signed-off-by: Ping Cheng Reviewed-by: Jason Gerecke Signed-off-by: Jiri Kosina --- drivers/hid/wacom_sys.c | 58 +++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 47 insertions(+), 11 deletions(-) (limited to 'drivers/hid') diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c index b3c6f11..9c57ac0 100644 --- a/drivers/hid/wacom_sys.c +++ b/drivers/hid/wacom_sys.c @@ -1402,6 +1402,52 @@ static size_t wacom_compute_pktlen(struct hid_device *hdev) return size; } +static void wacom_update_name(struct wacom *wacom) +{ + struct wacom_wac *wacom_wac = &wacom->wacom_wac; + struct wacom_features *features = &wacom_wac->features; + + /* Generic devices name unspecified */ + if ((features->type == HID_GENERIC) && !strcmp("Wacom HID", features->name)) { + if (strstr(wacom->hdev->name, "Wacom") || + strstr(wacom->hdev->name, "wacom") || + strstr(wacom->hdev->name, "WACOM")) { + /* name is in HID descriptor, use it */ + strlcpy(wacom_wac->name, wacom->hdev->name, + sizeof(wacom_wac->name)); + + /* strip out excess whitespaces */ + while (1) { + char *gap = strstr(wacom_wac->name, " "); + if (gap == NULL) + break; + /* shift everything including the terminator */ + memmove(gap, gap+1, strlen(gap)); + } + /* get rid of trailing whitespace */ + if (wacom_wac->name[strlen(wacom_wac->name)-1] == ' ') + wacom_wac->name[strlen(wacom_wac->name)-1] = '\0'; + } else { + /* no meaningful name retrieved. use product ID */ + snprintf(wacom_wac->name, sizeof(wacom_wac->name), + "%s %X", features->name, wacom->hdev->product); + } + } else { + strlcpy(wacom_wac->name, features->name, sizeof(wacom_wac->name)); + } + + /* Append the device type to the name */ + snprintf(wacom_wac->pad_name, sizeof(wacom_wac->pad_name), + "%s Pad", wacom_wac->name); + + if (features->device_type != BTN_TOOL_FINGER) + strlcat(wacom_wac->name, " Pen", WACOM_NAME_MAX); + else if (features->touch_max) + strlcat(wacom_wac->name, " Finger", WACOM_NAME_MAX); + else + strlcat(wacom_wac->name, " Pad", WACOM_NAME_MAX); +} + static int wacom_probe(struct hid_device *hdev, const struct hid_device_id *id) { @@ -1484,17 +1530,7 @@ static int wacom_probe(struct hid_device *hdev, wacom_setup_device_quirks(wacom); wacom_calculate_res(features); - strlcpy(wacom_wac->name, features->name, sizeof(wacom_wac->name)); - snprintf(wacom_wac->pad_name, sizeof(wacom_wac->pad_name), - "%s Pad", features->name); - - /* Append the device type to the name */ - if (features->device_type != BTN_TOOL_FINGER) - strlcat(wacom_wac->name, " Pen", WACOM_NAME_MAX); - else if (features->touch_max) - strlcat(wacom_wac->name, " Finger", WACOM_NAME_MAX); - else - strlcat(wacom_wac->name, " Pad", WACOM_NAME_MAX); + wacom_update_name(wacom); error = wacom_add_shared_data(hdev); if (error) -- cgit v1.1 From 8d80f790ecbcd0c3d55be51d867cbe4db1debd89 Mon Sep 17 00:00:00 2001 From: Jason Gerecke Date: Thu, 30 Apr 2015 17:51:53 -0700 Subject: HID: wacom: Do not add suffix to name of devices with an unknown type The naming logic currently assumes that all devices will be a pen, finger, or pad. Though this has historically been the case, the new HID_GENERIC catch-all may cause us to probe devices with Wacom's 056A VID which aren't any of these types (e.g. the "Cintiq 24HDT Monitor Control"). This patch updates the logic so that no suffix will be added to the device name if the device type is unknown. Signed-off-by: Jason Gerecke Reviewed-by: Ping Cheng Reviewed-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/wacom_sys.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'drivers/hid') diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c index 9c57ac0..222baf5 100644 --- a/drivers/hid/wacom_sys.c +++ b/drivers/hid/wacom_sys.c @@ -1440,12 +1440,15 @@ static void wacom_update_name(struct wacom *wacom) snprintf(wacom_wac->pad_name, sizeof(wacom_wac->pad_name), "%s Pad", wacom_wac->name); - if (features->device_type != BTN_TOOL_FINGER) + if (features->device_type == BTN_TOOL_PEN) { strlcat(wacom_wac->name, " Pen", WACOM_NAME_MAX); - else if (features->touch_max) - strlcat(wacom_wac->name, " Finger", WACOM_NAME_MAX); - else - strlcat(wacom_wac->name, " Pad", WACOM_NAME_MAX); + } + else if (features->device_type == BTN_TOOL_FINGER) { + if (features->touch_max) + strlcat(wacom_wac->name, " Finger", WACOM_NAME_MAX); + else + strlcat(wacom_wac->name, " Pad", WACOM_NAME_MAX); + } } static int wacom_probe(struct hid_device *hdev, -- cgit v1.1 From 042628abd59c9a034797bd3083f806fa17cda62d Mon Sep 17 00:00:00 2001 From: Jason Gerecke Date: Thu, 30 Apr 2015 17:51:54 -0700 Subject: HID: wacom: Discover device_type from HID descriptor for all devices Currently, we assume a device_type of BTN_TOOL_PEN before scanning the HID descriptor and then change the device_type if what we discover proves that assumption wrong. This way of doing things makes it more difficult to figure out if a device (particularly a HID_GENERIC device) actually does tablet/touch input or is something completley different. This patch leaves device_type at its initial value of 0 and then calls 'wacom_parse_hid' for every device (not just those that have touch). As we map the usages, we can set the device_type as before. After we're finished, we can then check if the value is still zero and do whatever is most appropriate. Detecting the pen can be a little tricky on most Wacom devices because the descriptors describe opaque blobs. Fortunately, older Wacom tablets have the HID_DG_DIGITIZER usage on the pen's application collection and newer tablets seem to have a similar vendor-defined usage that we can trigger on. Signed-off-by: Jason Gerecke Reviewed-by: Ping Cheng Reviewed-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/wacom_sys.c | 23 +++++++++++++---------- drivers/hid/wacom_wac.c | 8 +++++--- drivers/hid/wacom_wac.h | 6 +++++- 3 files changed, 23 insertions(+), 14 deletions(-) (limited to 'drivers/hid') diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c index 222baf5..157aa7a 100644 --- a/drivers/hid/wacom_sys.c +++ b/drivers/hid/wacom_sys.c @@ -181,7 +181,11 @@ static void wacom_usage_mapping(struct hid_device *hdev, * X/Y values and some cases of invalid Digitizer X/Y * values commonly reported. */ - if (!pen && !finger) + if (pen) + features->device_type = BTN_TOOL_PEN; + else if (finger) + features->device_type = BTN_TOOL_FINGER; + else return; /* @@ -198,14 +202,11 @@ static void wacom_usage_mapping(struct hid_device *hdev, case HID_GD_X: features->x_max = field->logical_maximum; if (finger) { - features->device_type = BTN_TOOL_FINGER; features->x_phy = field->physical_maximum; if (features->type != BAMBOO_PT) { features->unit = field->unit; features->unitExpo = field->unit_exponent; } - } else { - features->device_type = BTN_TOOL_PEN; } break; case HID_GD_Y: @@ -425,7 +426,6 @@ static void wacom_retrieve_hid_descriptor(struct hid_device *hdev, struct usb_interface *intf = wacom->intf; /* default features */ - features->device_type = BTN_TOOL_PEN; features->x_fuzz = 4; features->y_fuzz = 4; features->pressure_fuzz = 0; @@ -446,10 +446,6 @@ static void wacom_retrieve_hid_descriptor(struct hid_device *hdev, } } - /* only devices that support touch need to retrieve the info */ - if (features->type < BAMBOO_PT) - return; - wacom_parse_hid(hdev, features); } @@ -1529,8 +1525,15 @@ static int wacom_probe(struct hid_device *hdev, /* Retrieve the physical and logical size for touch devices */ wacom_retrieve_hid_descriptor(hdev, features); - wacom_setup_device_quirks(wacom); + + if (!features->device_type && features->type != WIRELESS) { + dev_warn(&hdev->dev, "Unknown device_type for '%s'. %s.", + hdev->name, "Assuming pen"); + + features->device_type = BTN_TOOL_PEN; + } + wacom_calculate_res(features); wacom_update_name(wacom); diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index dff99ff..a52fc25 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -2186,13 +2186,15 @@ void wacom_setup_device_quirks(struct wacom *wacom) features->x_max = 4096; features->y_max = 4096; - } else { - features->device_type = BTN_TOOL_PEN; } } /* - * Same thing for Bamboo PAD + * Raw Wacom-mode pen and touch events both come from interface + * 0, whose HID descriptor has an application usage of 0xFF0D + * (i.e., WACOM_VENDORDEFINED_PEN). We route pen packets back + * out through the HID_GENERIC device created for interface 1, + * so rewrite this one to be of type BTN_TOOL_FINGER. */ if (features->type == BAMBOO_PAD) features->device_type = BTN_TOOL_FINGER; diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h index f5a5f68..9a5ee62 100644 --- a/drivers/hid/wacom_wac.h +++ b/drivers/hid/wacom_wac.h @@ -72,10 +72,14 @@ #define WACOM_QUIRK_MONITOR 0x0004 #define WACOM_QUIRK_BATTERY 0x0008 +#define WACOM_VENDORDEFINED_PEN 0xff0d0001 + #define WACOM_PEN_FIELD(f) (((f)->logical == HID_DG_STYLUS) || \ ((f)->physical == HID_DG_STYLUS) || \ ((f)->physical == HID_DG_PEN) || \ - ((f)->application == HID_DG_PEN)) + ((f)->application == HID_DG_PEN) || \ + ((f)->application == HID_DG_DIGITIZER) || \ + ((f)->application == WACOM_VENDORDEFINED_PEN)) #define WACOM_FINGER_FIELD(f) (((f)->logical == HID_DG_FINGER) || \ ((f)->physical == HID_DG_FINGER) || \ ((f)->application == HID_DG_TOUCHSCREEN)) -- cgit v1.1 From 8e116d3169cc2b93b7eb2f44dc021a93cd3d5308 Mon Sep 17 00:00:00 2001 From: Jason Gerecke Date: Thu, 30 Apr 2015 17:51:55 -0700 Subject: HID: wacom: Fail probe if HID_GENERIC device has unknown device_type The last patch was careful to maintain backwards-compatible behavior by forcing device_type to BTN_TOOL_PEN (and printing a warning) if it were still uninitialized after scanning the HID descriptor and applying quirks. We should be more strict with HID_GENERIC devices, however, since there is no a priori guarantee that it is a tablet or touchpad. If the device_type is still uninitialized for a HID_GENERIC device then we assume that it isn't something the driver can work with and so fail the probe. Signed-off-by: Jason Gerecke Reviewed-by: Ping Cheng Reviewed-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/wacom_sys.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers/hid') diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c index 157aa7a..7abf52c 100644 --- a/drivers/hid/wacom_sys.c +++ b/drivers/hid/wacom_sys.c @@ -1528,8 +1528,14 @@ static int wacom_probe(struct hid_device *hdev, wacom_setup_device_quirks(wacom); if (!features->device_type && features->type != WIRELESS) { + error = features->type == HID_GENERIC ? -ENODEV : 0; + dev_warn(&hdev->dev, "Unknown device_type for '%s'. %s.", - hdev->name, "Assuming pen"); + hdev->name, + error ? "Ignoring" : "Assuming pen"); + + if (error) + goto fail_shared_data; features->device_type = BTN_TOOL_PEN; } -- cgit v1.1 From 181a8b911dd26cd44dc7283d7953a2e138842767 Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Fri, 1 May 2015 16:22:45 -0400 Subject: HID: lenovo: add support for Lenovo ThinkPad Keyboard Pro unit This dock is used with the Thinkpad Helix 2 but suffers from an error in the report descriptor where an usage max is 65535. Add a report fixup for it and make the keyboard working. Tested-by: Jonathan Oppenheim Tested-by: John Reid Signed-off-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/hid-core.c | 1 + drivers/hid/hid-ids.h | 1 + drivers/hid/hid-lenovo.c | 31 +++++++++++++++++++++++++++++++ 3 files changed, 33 insertions(+) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 722a925..c2baf8c 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1851,6 +1851,7 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_TPKBD) }, { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_CUSBKBD) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_CBTKBD) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_TPPRODOCK) }, #endif { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER) }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER) }, diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 41f167e..1649436 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -585,6 +585,7 @@ #define USB_DEVICE_ID_LENOVO_TPKBD 0x6009 #define USB_DEVICE_ID_LENOVO_CUSBKBD 0x6047 #define USB_DEVICE_ID_LENOVO_CBTKBD 0x6048 +#define USB_DEVICE_ID_LENOVO_TPPRODOCK 0x6067 #define USB_VENDOR_ID_LG 0x1fd2 #define USB_DEVICE_ID_LG_MULTITOUCH 0x0064 diff --git a/drivers/hid/hid-lenovo.c b/drivers/hid/hid-lenovo.c index 78608d6..4e291d5 100644 --- a/drivers/hid/hid-lenovo.c +++ b/drivers/hid/hid-lenovo.c @@ -43,6 +43,35 @@ struct lenovo_drvdata_cptkbd { #define map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, EV_KEY, (c)) +static const __u8 lenovo_pro_dock_need_fixup_collection[] = { + 0x05, 0x88, /* Usage Page (Vendor Usage Page 0x88) */ + 0x09, 0x01, /* Usage (Vendor Usage 0x01) */ + 0xa1, 0x01, /* Collection (Application) */ + 0x85, 0x04, /* Report ID (4) */ + 0x19, 0x00, /* Usage Minimum (0) */ + 0x2a, 0xff, 0xff, /* Usage Maximum (65535) */ +}; + +static __u8 *lenovo_report_fixup(struct hid_device *hdev, __u8 *rdesc, + unsigned int *rsize) +{ + switch (hdev->product) { + case USB_DEVICE_ID_LENOVO_TPPRODOCK: + /* the fixups that need to be done: + * - get a reasonable usage max for the vendor collection + * 0x8801 from the report ID 4 + */ + if (*rsize >= 153 && + memcmp(&rdesc[140], lenovo_pro_dock_need_fixup_collection, + sizeof(lenovo_pro_dock_need_fixup_collection)) == 0) { + rdesc[151] = 0x01; + rdesc[152] = 0x00; + } + break; + } + return rdesc; +} + static int lenovo_input_mapping_tpkbd(struct hid_device *hdev, struct hid_input *hi, struct hid_field *field, struct hid_usage *usage, unsigned long **bit, int *max) @@ -784,6 +813,7 @@ static const struct hid_device_id lenovo_devices[] = { { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_TPKBD) }, { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_CUSBKBD) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_CBTKBD) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_TPPRODOCK) }, { } }; @@ -797,6 +827,7 @@ static struct hid_driver lenovo_driver = { .probe = lenovo_probe, .remove = lenovo_remove, .raw_event = lenovo_raw_event, + .report_fixup = lenovo_report_fixup, }; module_hid_driver(lenovo_driver); -- cgit v1.1 From 131a8a9a56f16d8d237b39a8677ccee44a355392 Mon Sep 17 00:00:00 2001 From: Frank Praznik Date: Tue, 5 May 2015 20:47:28 -0400 Subject: HID: sony: Prevent the freeing of an unitialized ida value sony_allocate_output_report() was being called before sony_set_device_id() which meant that an unallocated ida value was was freed if the output report allocation failed and the probe function jumped to err_stop. Do the device ID allocation before the output report allocation to avoid freeing an unallocated value in case of a failure. Signed-off-by: Frank Praznik Acked-by: Pavel Machek Signed-off-by: Jiri Kosina --- drivers/hid/hid-sony.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index 6ca96ce..4c521b2 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c @@ -1993,15 +1993,15 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) return ret; } - ret = sony_allocate_output_report(sc); + ret = sony_set_device_id(sc); if (ret < 0) { - hid_err(hdev, "failed to allocate the output report buffer\n"); + hid_err(hdev, "failed to allocate the device id\n"); goto err_stop; } - ret = sony_set_device_id(sc); + ret = sony_allocate_output_report(sc); if (ret < 0) { - hid_err(hdev, "failed to allocate the device id\n"); + hid_err(hdev, "failed to allocate the output report buffer\n"); goto err_stop; } -- cgit v1.1 From 7c886d098d6128438e706ca4c068b8920fdac42d Mon Sep 17 00:00:00 2001 From: Frank Praznik Date: Tue, 5 May 2015 20:47:29 -0400 Subject: HID: sony: Add the product ID for the Sony Motion Controller Adds the PID for the Sony motion controller to the hardware ID list. Signed-off-by: Pavel Machek Signed-off-by: Frank Praznik Acked-by: Pavel Machek Signed-off-by: Jiri Kosina --- drivers/hid/hid-core.c | 1 + drivers/hid/hid-ids.h | 1 + 2 files changed, 2 insertions(+) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 722a925..2cb9ac7 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1961,6 +1961,7 @@ static const struct hid_device_id hid_have_special_driver[] = { { 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) }, { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) }, + { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_MOTION_CONTROLLER) }, { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) }, { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER) }, diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 41f167e..14fcb11 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -851,6 +851,7 @@ #define USB_DEVICE_ID_SONY_PS3_BDREMOTE 0x0306 #define USB_DEVICE_ID_SONY_PS3_CONTROLLER 0x0268 #define USB_DEVICE_ID_SONY_PS4_CONTROLLER 0x05c4 +#define USB_DEVICE_ID_SONY_MOTION_CONTROLLER 0x03d5 #define USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER 0x042f #define USB_DEVICE_ID_SONY_BUZZ_CONTROLLER 0x0002 #define USB_DEVICE_ID_SONY_WIRELESS_BUZZ_CONTROLLER 0x1000 -- cgit v1.1 From c5e0c1c4950f9126f7eb2fb1d3f8aa4080f05538 Mon Sep 17 00:00:00 2001 From: Frank Praznik Date: Tue, 5 May 2015 20:47:30 -0400 Subject: HID: sony: Add support for the Sony Motion Controller Add a fixed-up HID descriptor for the Sony motion controller and enable controls for the LED light as well as force-feedback. The LED is multi-colored (red, green, blue). The motion controller has a single rumble motor so the higher of the left and right values is used to set the speed. Signed-off-by: Pavel Machek Signed-off-by: Frank Praznik Acked-by: Pavel Machek Signed-off-by: Jiri Kosina --- drivers/hid/hid-sony.c | 138 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 136 insertions(+), 2 deletions(-) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index 4c521b2..d0b18a5 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c @@ -46,14 +46,16 @@ #define PS3REMOTE BIT(4) #define DUALSHOCK4_CONTROLLER_USB BIT(5) #define DUALSHOCK4_CONTROLLER_BT BIT(6) +#define MOTION_CONTROLLER BIT(7) #define SIXAXIS_CONTROLLER (SIXAXIS_CONTROLLER_USB | SIXAXIS_CONTROLLER_BT) #define DUALSHOCK4_CONTROLLER (DUALSHOCK4_CONTROLLER_USB |\ DUALSHOCK4_CONTROLLER_BT) #define SONY_LED_SUPPORT (SIXAXIS_CONTROLLER | BUZZ_CONTROLLER |\ - DUALSHOCK4_CONTROLLER) + DUALSHOCK4_CONTROLLER | MOTION_CONTROLLER) #define SONY_BATTERY_SUPPORT (SIXAXIS_CONTROLLER | DUALSHOCK4_CONTROLLER) -#define SONY_FF_SUPPORT (SIXAXIS_CONTROLLER | DUALSHOCK4_CONTROLLER) +#define SONY_FF_SUPPORT (SIXAXIS_CONTROLLER | DUALSHOCK4_CONTROLLER |\ + MOTION_CONTROLLER) #define MAX_LEDS 4 @@ -134,6 +136,85 @@ static __u8 sixaxis_rdesc[] = { 0xC0 /* End Collection */ }; +/* PS/3 Motion controller */ +static __u8 motion_rdesc[] = { + 0x05, 0x01, /* Usage Page (Desktop), */ + 0x09, 0x04, /* Usage (Joystick), */ + 0xA1, 0x01, /* Collection (Application), */ + 0xA1, 0x02, /* Collection (Logical), */ + 0x85, 0x01, /* Report ID (1), */ + 0x75, 0x08, /* Report Size (8), */ + 0x95, 0x01, /* Report Count (1), */ + 0x15, 0x00, /* Logical Minimum (0), */ + 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ + 0x81, 0x03, /* Input (Constant, Variable), */ + 0x75, 0x01, /* Report Size (1), */ + 0x95, 0x13, /* Report Count (19), */ + 0x15, 0x00, /* Logical Minimum (0), */ + 0x25, 0x01, /* Logical Maximum (1), */ + 0x35, 0x00, /* Physical Minimum (0), */ + 0x45, 0x01, /* Physical Maximum (1), */ + 0x05, 0x09, /* Usage Page (Button), */ + 0x19, 0x01, /* Usage Minimum (01h), */ + 0x29, 0x13, /* Usage Maximum (13h), */ + 0x81, 0x02, /* Input (Variable), */ + 0x75, 0x01, /* Report Size (1), */ + 0x95, 0x0D, /* Report Count (13), */ + 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ + 0x81, 0x03, /* Input (Constant, Variable), */ + 0x15, 0x00, /* Logical Minimum (0), */ + 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ + 0x05, 0x01, /* Usage Page (Desktop), */ + 0x09, 0x01, /* Usage (Pointer), */ + 0xA1, 0x00, /* Collection (Physical), */ + 0x75, 0x08, /* Report Size (8), */ + 0x95, 0x04, /* Report Count (4), */ + 0x35, 0x00, /* Physical Minimum (0), */ + 0x46, 0xFF, 0x00, /* Physical Maximum (255), */ + 0x09, 0x30, /* Usage (X), */ + 0x09, 0x31, /* Usage (Y), */ + 0x09, 0x32, /* Usage (Z), */ + 0x09, 0x35, /* Usage (Rz), */ + 0x81, 0x02, /* Input (Variable), */ + 0xC0, /* End Collection, */ + 0x05, 0x01, /* Usage Page (Desktop), */ + 0x95, 0x13, /* Report Count (19), */ + 0x09, 0x01, /* Usage (Pointer), */ + 0x81, 0x02, /* Input (Variable), */ + 0x95, 0x0C, /* Report Count (12), */ + 0x81, 0x01, /* Input (Constant), */ + 0x75, 0x10, /* Report Size (16), */ + 0x95, 0x04, /* Report Count (4), */ + 0x26, 0xFF, 0x03, /* Logical Maximum (1023), */ + 0x46, 0xFF, 0x03, /* Physical Maximum (1023), */ + 0x09, 0x01, /* Usage (Pointer), */ + 0x81, 0x02, /* Input (Variable), */ + 0xC0, /* End Collection, */ + 0xA1, 0x02, /* Collection (Logical), */ + 0x85, 0x02, /* Report ID (2), */ + 0x75, 0x08, /* Report Size (8), */ + 0x95, 0x30, /* Report Count (48), */ + 0x09, 0x01, /* Usage (Pointer), */ + 0xB1, 0x02, /* Feature (Variable), */ + 0xC0, /* End Collection, */ + 0xA1, 0x02, /* Collection (Logical), */ + 0x85, 0xEE, /* Report ID (238), */ + 0x75, 0x08, /* Report Size (8), */ + 0x95, 0x30, /* Report Count (48), */ + 0x09, 0x01, /* Usage (Pointer), */ + 0xB1, 0x02, /* Feature (Variable), */ + 0xC0, /* End Collection, */ + 0xA1, 0x02, /* Collection (Logical), */ + 0x85, 0xEF, /* Report ID (239), */ + 0x75, 0x08, /* Report Size (8), */ + 0x95, 0x30, /* Report Count (48), */ + 0x09, 0x01, /* Usage (Pointer), */ + 0xB1, 0x02, /* Feature (Variable), */ + 0xC0, /* End Collection, */ + 0xC0 /* End Collection */ +}; + + /* * The default descriptor doesn't provide mapping for the accelerometers * or orientation sensors. This fixed descriptor maps the accelerometers @@ -798,6 +879,13 @@ union sixaxis_output_report_01 { __u8 buf[36]; }; +struct motion_output_report_02 { + u8 type, zero; + u8 r, g, b; + u8 zero2; + u8 rumble; +}; + #define DS4_REPORT_0x02_SIZE 37 #define DS4_REPORT_0x05_SIZE 32 #define DS4_REPORT_0x11_SIZE 78 @@ -844,6 +932,13 @@ static __u8 *sixaxis_fixup(struct hid_device *hdev, __u8 *rdesc, return sixaxis_rdesc; } +static u8 *motion_fixup(struct hid_device *hdev, u8 *rdesc, + unsigned int *rsize) +{ + *rsize = sizeof(motion_rdesc); + return motion_rdesc; +} + static __u8 *ps3remote_fixup(struct hid_device *hdev, __u8 *rdesc, unsigned int *rsize) { @@ -924,6 +1019,9 @@ static __u8 *sony_report_fixup(struct hid_device *hdev, __u8 *rdesc, if (sc->quirks & SIXAXIS_CONTROLLER) return sixaxis_fixup(hdev, rdesc, rsize); + if (sc->quirks & MOTION_CONTROLLER) + return motion_fixup(hdev, rdesc, rsize); + if (sc->quirks & PS3REMOTE) return ps3remote_fixup(hdev, rdesc, rsize); @@ -1454,6 +1552,12 @@ static int sony_leds_init(struct sony_sc *sc) use_ds4_names = 1; name_len = 0; name_fmt = "%s:%s"; + } else if (sc->quirks & MOTION_CONTROLLER) { + sc->led_count = 3; + memset(max_brightness, 255, 3); + use_ds4_names = 1; + name_len = 0; + name_fmt = "%s:%s"; } else { sixaxis_set_leds_from_id(sc->device_id, initial_values); sc->led_count = 4; @@ -1622,6 +1726,28 @@ static void dualshock4_state_worker(struct work_struct *work) HID_OUTPUT_REPORT, HID_REQ_SET_REPORT); } +static void motion_state_worker(struct work_struct *work) +{ + struct sony_sc *sc = container_of(work, struct sony_sc, state_worker); + struct hid_device *hdev = sc->hdev; + struct motion_output_report_02 *report = + (struct motion_output_report_02 *)sc->output_report_dmabuf; + + memset(report, 0, sizeof(struct motion_output_report_02)); + + report->type = 0x02; /* set leds */ + report->r = sc->led_state[0]; + report->g = sc->led_state[1]; + report->b = sc->led_state[2]; + +#ifdef CONFIG_SONY_FF + report->rumble = max(sc->right, sc->left); +#endif + + hid_hw_output_report(hdev, (__u8 *)report, + sizeof(struct motion_output_report_02)); +} + static int sony_allocate_output_report(struct sony_sc *sc) { if (sc->quirks & SIXAXIS_CONTROLLER) @@ -1634,6 +1760,10 @@ static int sony_allocate_output_report(struct sony_sc *sc) else if (sc->quirks & DUALSHOCK4_CONTROLLER_USB) sc->output_report_dmabuf = kmalloc(DS4_REPORT_0x05_SIZE, GFP_KERNEL); + else if (sc->quirks & MOTION_CONTROLLER) + sc->output_report_dmabuf = + kmalloc(sizeof(struct motion_output_report_02), + GFP_KERNEL); else return 0; @@ -2043,6 +2173,8 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) } sony_init_work(sc, dualshock4_state_worker); + } else if (sc->quirks & MOTION_CONTROLLER) { + sony_init_work(sc, motion_state_worker); } else { ret = 0; } @@ -2123,6 +2255,8 @@ static const struct hid_device_id sony_devices[] = { .driver_data = SIXAXIS_CONTROLLER_USB }, { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER), .driver_data = SIXAXIS_CONTROLLER_USB }, + { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_MOTION_CONTROLLER), + .driver_data = MOTION_CONTROLLER }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER), .driver_data = SIXAXIS_CONTROLLER_BT }, { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE), -- cgit v1.1 From 8f069fdf5bbc6b300f9c88801d0d858d2a4d46e6 Mon Sep 17 00:00:00 2001 From: Frank Praznik Date: Tue, 5 May 2015 20:47:31 -0400 Subject: HID: sony: Correct Sony device ordering Rearrange Sony controller devices into alphabetical order in the hardware device list. Signed-off-by: Frank Praznik Acked-by: Pavel Machek Signed-off-by: Jiri Kosina --- drivers/hid/hid-core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 2cb9ac7..aefb248 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1959,10 +1959,10 @@ static const struct hid_device_id hid_have_special_driver[] = { { 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) }, - { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) }, { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_MOTION_CONTROLLER) }, { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_BDREMOTE) }, + { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) }, { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS4_CONTROLLER) }, -- cgit v1.1 From 221399b36535752351d4631606b427daca3dc35c Mon Sep 17 00:00:00 2001 From: Frank Praznik Date: Tue, 5 May 2015 20:47:32 -0400 Subject: HID: sony: Simplify LED initialization and eliminate redundant copies when updating LED states Directly set the initial LED states in the device state struct instead of copying them from a temporary array. This allows for the removal of a redundant "x = x" copy loop in sony_set_leds() that was taking place any time an LED was updated. It also allows for the simplifying of the parameters in functions dealing with LED initialization and updates since only a pointer to the sony_sc struct is needed now. Signed-off-by: Frank Praznik Acked-by: Pavel Machek Signed-off-by: Jiri Kosina --- drivers/hid/hid-sony.c | 58 ++++++++++++++++++++++++-------------------------- 1 file changed, 28 insertions(+), 30 deletions(-) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index d0b18a5..9370509 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c @@ -1306,7 +1306,7 @@ static int dualshock4_set_operational_bt(struct hid_device *hdev) return ret; } -static void sixaxis_set_leds_from_id(int id, __u8 values[MAX_LEDS]) +static void sixaxis_set_leds_from_id(struct sony_sc *sc) { static const __u8 sixaxis_leds[10][4] = { { 0x01, 0x00, 0x00, 0x00 }, @@ -1321,16 +1321,18 @@ static void sixaxis_set_leds_from_id(int id, __u8 values[MAX_LEDS]) { 0x01, 0x01, 0x01, 0x01 } }; - BUG_ON(MAX_LEDS < ARRAY_SIZE(sixaxis_leds[0])); + int id = sc->device_id; + + BUILD_BUG_ON(MAX_LEDS < ARRAY_SIZE(sixaxis_leds[0])); if (id < 0) return; id %= 10; - memcpy(values, sixaxis_leds[id], sizeof(sixaxis_leds[id])); + memcpy(sc->led_state, sixaxis_leds[id], sizeof(sixaxis_leds[id])); } -static void dualshock4_set_leds_from_id(int id, __u8 values[MAX_LEDS]) +static void dualshock4_set_leds_from_id(struct sony_sc *sc) { /* The first 4 color/index entries match what the PS4 assigns */ static const __u8 color_code[7][3] = { @@ -1343,46 +1345,44 @@ static void dualshock4_set_leds_from_id(int id, __u8 values[MAX_LEDS]) /* White */ { 0x01, 0x01, 0x01 } }; - BUG_ON(MAX_LEDS < ARRAY_SIZE(color_code[0])); + int id = sc->device_id; + + BUILD_BUG_ON(MAX_LEDS < ARRAY_SIZE(color_code[0])); if (id < 0) return; id %= 7; - memcpy(values, color_code[id], sizeof(color_code[id])); + memcpy(sc->led_state, color_code[id], sizeof(color_code[id])); } -static void buzz_set_leds(struct hid_device *hdev, const __u8 *leds) +static void buzz_set_leds(struct sony_sc *sc) { + struct hid_device *hdev = sc->hdev; struct list_head *report_list = &hdev->report_enum[HID_OUTPUT_REPORT].report_list; struct hid_report *report = list_entry(report_list->next, struct hid_report, list); __s32 *value = report->field[0]->value; + BUILD_BUG_ON(MAX_LEDS < 4); + value[0] = 0x00; - value[1] = leds[0] ? 0xff : 0x00; - value[2] = leds[1] ? 0xff : 0x00; - value[3] = leds[2] ? 0xff : 0x00; - value[4] = leds[3] ? 0xff : 0x00; + value[1] = sc->led_state[0] ? 0xff : 0x00; + value[2] = sc->led_state[1] ? 0xff : 0x00; + value[3] = sc->led_state[2] ? 0xff : 0x00; + value[4] = sc->led_state[3] ? 0xff : 0x00; value[5] = 0x00; value[6] = 0x00; hid_hw_request(hdev, report, HID_REQ_SET_REPORT); } -static void sony_set_leds(struct sony_sc *sc, const __u8 *leds, int count) +static void sony_set_leds(struct sony_sc *sc) { - int n; - - BUG_ON(count > MAX_LEDS); - - if (sc->quirks & BUZZ_CONTROLLER && count == 4) { - buzz_set_leds(sc->hdev, leds); - } else { - for (n = 0; n < count; n++) - sc->led_state[n] = leds[n]; + if (!(sc->quirks & BUZZ_CONTROLLER)) schedule_work(&sc->state_worker); - } + else + buzz_set_leds(sc); } static void sony_led_set_brightness(struct led_classdev *led, @@ -1422,8 +1422,7 @@ static void sony_led_set_brightness(struct led_classdev *led, drv_data->led_delay_on[n] = 0; drv_data->led_delay_off[n] = 0; - sony_set_leds(drv_data, drv_data->led_state, - drv_data->led_count); + sony_set_leds(drv_data); break; } } @@ -1529,7 +1528,6 @@ static int sony_leds_init(struct sony_sc *sc) const char *name_fmt; static const char * const ds4_name_str[] = { "red", "green", "blue", "global" }; - __u8 initial_values[MAX_LEDS] = { 0 }; __u8 max_brightness[MAX_LEDS] = { [0 ... (MAX_LEDS - 1)] = 1 }; __u8 use_hw_blink[MAX_LEDS] = { 0 }; @@ -1544,8 +1542,8 @@ static int sony_leds_init(struct sony_sc *sc) if (!hid_validate_values(hdev, HID_OUTPUT_REPORT, 0, 0, 7)) return -ENODEV; } else if (sc->quirks & DUALSHOCK4_CONTROLLER) { - dualshock4_set_leds_from_id(sc->device_id, initial_values); - initial_values[3] = 1; + dualshock4_set_leds_from_id(sc); + sc->led_state[3] = 1; sc->led_count = 4; memset(max_brightness, 255, 3); use_hw_blink[3] = 1; @@ -1559,7 +1557,7 @@ static int sony_leds_init(struct sony_sc *sc) name_len = 0; name_fmt = "%s:%s"; } else { - sixaxis_set_leds_from_id(sc->device_id, initial_values); + sixaxis_set_leds_from_id(sc); sc->led_count = 4; memset(use_hw_blink, 1, 4); use_ds4_names = 0; @@ -1572,7 +1570,7 @@ static int sony_leds_init(struct sony_sc *sc) * only relevant if the driver is loaded after somebody actively set the * LEDs to on */ - sony_set_leds(sc, initial_values, sc->led_count); + sony_set_leds(sc); name_sz = strlen(dev_name(&hdev->dev)) + name_len + 1; @@ -1595,7 +1593,7 @@ static int sony_leds_init(struct sony_sc *sc) else snprintf(name, name_sz, name_fmt, dev_name(&hdev->dev), n + 1); led->name = name; - led->brightness = initial_values[n]; + led->brightness = sc->led_state[n]; led->max_brightness = max_brightness[n]; led->brightness_get = sony_led_get_brightness; led->brightness_set = sony_led_set_brightness; -- cgit v1.1 From 4c3e829849cc05f82c11fe9a3c662c7e1323d6cf Mon Sep 17 00:00:00 2001 From: Frank Praznik Date: Tue, 5 May 2015 20:47:33 -0400 Subject: HID: sony: Correct a typo in a HID descriptor comment and explain the odd Sixaxis axis mapping Correct a spelling mistake in the Sixaxis HID descriptor comment. Add an explanation as to why the Sixaxis has so many analog axes and why some of them are seen as multi-touch axes. Signed-off-by: Frank Praznik Acked-by: Pavel Machek Signed-off-by: Jiri Kosina --- drivers/hid/hid-sony.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index 9370509..aeb8b41 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c @@ -59,9 +59,16 @@ #define MAX_LEDS 4 +/* + * The Sixaxis reports both digital and analog values for each button on the + * controller except for Start, Select and the PS button. The controller ends + * up reporting 27 axes which causes them to spill over into the multi-touch + * axis values. Additionally, the controller only has 20 actual, physical axes + * so there are several unused axes in between the used ones. + */ static __u8 sixaxis_rdesc[] = { 0x05, 0x01, /* Usage Page (Desktop), */ - 0x09, 0x04, /* Usage (Joystik), */ + 0x09, 0x04, /* Usage (Joystick), */ 0xA1, 0x01, /* Collection (Application), */ 0xA1, 0x02, /* Collection (Logical), */ 0x85, 0x01, /* Report ID (1), */ -- cgit v1.1 From 6e5e9a06a206010eabd19b523fd0833c51afc0b0 Mon Sep 17 00:00:00 2001 From: Sean Young Date: Wed, 6 May 2015 21:38:42 +0100 Subject: HID: sjoy: support Super Joy Box 4 This device supports force feedback and has two ports. Signed-off-by: Sean Young Signed-off-by: Jiri Kosina --- drivers/hid/hid-core.c | 1 + drivers/hid/hid-sjoy.c | 3 +++ drivers/hid/usbhid/hid-quirks.c | 1 - 3 files changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 722a925..1ec1e4d 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1997,6 +1997,7 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_JOY_BOX_3_PRO) }, { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_DUAL_BOX_PRO) }, { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SUPER_JOY_BOX_5_PRO) }, + { HID_USB_DEVICE(USB_VENDOR_ID_PLAYDOTCOM, USB_DEVICE_ID_PLAYDOTCOM_EMS_USBII) }, { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SLIM_TABLET_5_8_INCH) }, { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_SLIM_TABLET_12_1_INCH) }, { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_Q_PAD) }, diff --git a/drivers/hid/hid-sjoy.c b/drivers/hid/hid-sjoy.c index 37845ec..36b6470 100644 --- a/drivers/hid/hid-sjoy.c +++ b/drivers/hid/hid-sjoy.c @@ -166,6 +166,9 @@ static const struct hid_device_id sjoy_devices[] = { { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_DUAL_USB_JOYPAD), .driver_data = HID_QUIRK_MULTI_INPUT | HID_QUIRK_SKIP_OUTPUT_REPORTS }, + { HID_USB_DEVICE(USB_VENDOR_ID_PLAYDOTCOM, USB_DEVICE_ID_PLAYDOTCOM_EMS_USBII), + .driver_data = HID_QUIRK_MULTI_INPUT | + HID_QUIRK_SKIP_OUTPUT_REPORTS }, { } }; MODULE_DEVICE_TABLE(hid, sjoy_devices); diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index a775143..ac12a36 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c @@ -52,7 +52,6 @@ static const struct hid_blacklist { { USB_VENDOR_ID_ETURBOTOUCH, USB_DEVICE_ID_ETURBOTOUCH_2968, HID_QUIRK_MULTI_INPUT }, { USB_VENDOR_ID_GREENASIA, USB_DEVICE_ID_GREENASIA_DUAL_USB_JOYPAD, HID_QUIRK_MULTI_INPUT }, { USB_VENDOR_ID_PANTHERLORD, USB_DEVICE_ID_PANTHERLORD_TWIN_USB_JOYSTICK, HID_QUIRK_MULTI_INPUT | HID_QUIRK_SKIP_OUTPUT_REPORTS }, - { USB_VENDOR_ID_PLAYDOTCOM, USB_DEVICE_ID_PLAYDOTCOM_EMS_USBII, HID_QUIRK_MULTI_INPUT }, { USB_VENDOR_ID_TOUCHPACK, USB_DEVICE_ID_TOUCHPACK_RTS, HID_QUIRK_MULTI_INPUT }, { USB_VENDOR_ID_AIREN, USB_DEVICE_ID_AIREN_SLIMPLUS, HID_QUIRK_NOGET }, -- cgit v1.1 From aef3156d7294ac878c10ca8f02539b49adee9624 Mon Sep 17 00:00:00 2001 From: Jason Gerecke Date: Thu, 21 May 2015 10:44:31 -0700 Subject: HID: wacom: Have wacom_{get,set}_report retry on -EAGAIN, not -EPIPE Retrying on -EPIPE makes very little sense since this typically indicates a problem that will not just disappear on its own. For instance, the USB documentation states that it will be sent if the endpoint is stalled or the device has disconnected. Instead, we should retry if -EAGAIN is received since this indicates a temporary error condition such as a busy bus. In addition to adjusting the conditions we retry under, we also log an error on failure so that we can be aware of what's going on. Signed-off-by: Jason Gerecke Reviewed-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/wacom_sys.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) (limited to 'drivers/hid') diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c index 7abf52c..109312f 100644 --- a/drivers/hid/wacom_sys.c +++ b/drivers/hid/wacom_sys.c @@ -35,7 +35,11 @@ static int wacom_get_report(struct hid_device *hdev, u8 type, u8 *buf, do { retval = hid_hw_raw_request(hdev, buf[0], buf, size, type, HID_REQ_GET_REPORT); - } while ((retval == -ETIMEDOUT || retval == -EPIPE) && --retries); + } while ((retval == -ETIMEDOUT || retval == -EAGAIN) && --retries); + + if (retval < 0) + hid_err(hdev, "wacom_get_report: ran out of retries " + "(last error = %d)\n", retval); return retval; } @@ -48,7 +52,11 @@ static int wacom_set_report(struct hid_device *hdev, u8 type, u8 *buf, do { retval = hid_hw_raw_request(hdev, buf[0], buf, size, type, HID_REQ_SET_REPORT); - } while ((retval == -ETIMEDOUT || retval == -EPIPE) && --retries); + } while ((retval == -ETIMEDOUT || retval == -EAGAIN) && --retries); + + if (retval < 0) + hid_err(hdev, "wacom_set_report: ran out of retries " + "(last error = %d)\n", retval); return retval; } -- cgit v1.1 From 05e8fd9202247ac6cdc26f6bafb5453120065490 Mon Sep 17 00:00:00 2001 From: Jason Gerecke Date: Thu, 21 May 2015 10:44:32 -0700 Subject: HID: wacom: Handle failing HID_DG_CONTACTMAX requests Hardware may not respond to a request for the HID_DG_CONTACTMAX feature and we should be tolerant of such a failure. This is especially true when using hid-replay where the hardware doesn't exist, but also for devices attached to a flaky bus. This patch increases the number of allowable retries to match other calls to 'wacom_get_report' and also provides a fallback which forces 'touch_max = 16' (enough for any Wacom device seen so far). Signed-off-by: Jason Gerecke Reviewed-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/wacom_sys.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'drivers/hid') diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c index 109312f..eea18a6 100644 --- a/drivers/hid/wacom_sys.c +++ b/drivers/hid/wacom_sys.c @@ -125,9 +125,16 @@ static void wacom_feature_mapping(struct hid_device *hdev, break; data[0] = field->report->id; ret = wacom_get_report(hdev, HID_FEATURE_REPORT, - data, 2, 0); - if (ret == 2) + data, 2, WAC_CMD_RETRIES); + if (ret == 2) { features->touch_max = data[1]; + } else { + features->touch_max = 16; + hid_warn(hdev, "wacom_feature_mapping: " + "could not get HID_DG_CONTACTMAX, " + "defaulting to %d\n", + features->touch_max); + } kfree(data); } break; -- cgit v1.1 From 3e48138c2c66d8ff7d96c87a0535cd50078c742f Mon Sep 17 00:00:00 2001 From: Andrew Duggan Date: Tue, 2 Jun 2015 14:46:20 -0700 Subject: HID: i2c-hid: Do not set the ACPI companion field in the HID device The HID device does not need to know about the ACPI device associated with the underlying i2c device. Setting the ACPI companion field in the HID device also has the side effect of causing HID to be set as wake capable, since acpi_bind_one uses's the companion ACPI device's wakeup flags to set the device as wake capable. Which results in power/wakeup files in sysfs for the HID device which do not do anything. Signed-off-by: Andrew Duggan Reviewed-by: Benson Leung Tested-by: Benson Leung Acked-by: Mika Westerberg Signed-off-by: Jiri Kosina --- drivers/hid/i2c-hid/i2c-hid.c | 1 - 1 file changed, 1 deletion(-) (limited to 'drivers/hid') diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid.c index 92d6cdf..0dfb5d1 100644 --- a/drivers/hid/i2c-hid/i2c-hid.c +++ b/drivers/hid/i2c-hid/i2c-hid.c @@ -1019,7 +1019,6 @@ static int i2c_hid_probe(struct i2c_client *client, hid->driver_data = client; hid->ll_driver = &i2c_hid_ll_driver; hid->dev.parent = &client->dev; - ACPI_COMPANION_SET(&hid->dev, ACPI_COMPANION(&client->dev)); hid->bus = BUS_I2C; hid->version = le16_to_cpu(ihid->hdesc.bcdVersion); hid->vendor = le16_to_cpu(ihid->hdesc.wVendorID); -- cgit v1.1 From a4afa8544d49237a7d9e492ead047501de69aa25 Mon Sep 17 00:00:00 2001 From: Simon Wood Date: Wed, 3 Jun 2015 09:45:19 -0600 Subject: HID: sony: Support PS3 Move Controller when connected via Bluetooth Signed-off-by: Simon Wood Signed-off-by: Jiri Kosina --- drivers/hid/hid-core.c | 1 + drivers/hid/hid-sony.c | 2 ++ 2 files changed, 3 insertions(+) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index aefb248..044e96a 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1960,6 +1960,7 @@ static const struct hid_device_id hid_have_special_driver[] = { { 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_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_MOTION_CONTROLLER) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_MOTION_CONTROLLER) }, { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_BDREMOTE) }, { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) }, diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index aeb8b41..6fcc2b4 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c @@ -2262,6 +2262,8 @@ static const struct hid_device_id sony_devices[] = { .driver_data = SIXAXIS_CONTROLLER_USB }, { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_MOTION_CONTROLLER), .driver_data = MOTION_CONTROLLER }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_MOTION_CONTROLLER), + .driver_data = MOTION_CONTROLLER }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER), .driver_data = SIXAXIS_CONTROLLER_BT }, { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE), -- cgit v1.1 From b3bca326fa813e4770f74f9ceffe97b72e281475 Mon Sep 17 00:00:00 2001 From: Simon Wood Date: Tue, 9 Jun 2015 21:27:04 -0600 Subject: HID: sony: Add quirk for MOTION_CONTROLLER_BT Split quirk for PS Move Controller as it has to be treated differently when connected via BT. Signed-off-by: Simon Wood Signed-off-by: Jiri Kosina --- drivers/hid/hid-sony.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index 6fcc2b4..28dba6c 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c @@ -46,9 +46,11 @@ #define PS3REMOTE BIT(4) #define DUALSHOCK4_CONTROLLER_USB BIT(5) #define DUALSHOCK4_CONTROLLER_BT BIT(6) -#define MOTION_CONTROLLER BIT(7) +#define MOTION_CONTROLLER_USB BIT(7) +#define MOTION_CONTROLLER_BT BIT(8) #define SIXAXIS_CONTROLLER (SIXAXIS_CONTROLLER_USB | SIXAXIS_CONTROLLER_BT) +#define MOTION_CONTROLLER (MOTION_CONTROLLER_USB | MOTION_CONTROLLER_BT) #define DUALSHOCK4_CONTROLLER (DUALSHOCK4_CONTROLLER_USB |\ DUALSHOCK4_CONTROLLER_BT) #define SONY_LED_SUPPORT (SIXAXIS_CONTROLLER | BUZZ_CONTROLLER |\ @@ -2261,9 +2263,9 @@ static const struct hid_device_id sony_devices[] = { { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER), .driver_data = SIXAXIS_CONTROLLER_USB }, { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_MOTION_CONTROLLER), - .driver_data = MOTION_CONTROLLER }, + .driver_data = MOTION_CONTROLLER_USB }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_MOTION_CONTROLLER), - .driver_data = MOTION_CONTROLLER }, + .driver_data = MOTION_CONTROLLER_BT }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER), .driver_data = SIXAXIS_CONTROLLER_BT }, { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE), -- cgit v1.1 From 12e9a6d72b3ac33e542b6001ccd891d7b41fff10 Mon Sep 17 00:00:00 2001 From: Simon Wood Date: Tue, 9 Jun 2015 21:27:05 -0600 Subject: HID: sony: Add support PS3 Move Battery via BT Add support for the battery charge level and state to be read via BT. This is not support via USB as there is no know way to get the device sending 'input' reports over USB. Signed-off-by: Simon Wood Signed-off-by: Jiri Kosina --- drivers/hid/hid-sony.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index 28dba6c..d9fa804 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c @@ -55,7 +55,8 @@ DUALSHOCK4_CONTROLLER_BT) #define SONY_LED_SUPPORT (SIXAXIS_CONTROLLER | BUZZ_CONTROLLER |\ DUALSHOCK4_CONTROLLER | MOTION_CONTROLLER) -#define SONY_BATTERY_SUPPORT (SIXAXIS_CONTROLLER | DUALSHOCK4_CONTROLLER) +#define SONY_BATTERY_SUPPORT (SIXAXIS_CONTROLLER | DUALSHOCK4_CONTROLLER |\ + MOTION_CONTROLLER_BT) #define SONY_FF_SUPPORT (SIXAXIS_CONTROLLER | DUALSHOCK4_CONTROLLER |\ MOTION_CONTROLLER) @@ -1041,6 +1042,7 @@ static void sixaxis_parse_report(struct sony_sc *sc, __u8 *rd, int size) { static const __u8 sixaxis_battery_capacity[] = { 0, 1, 25, 50, 75, 100 }; unsigned long flags; + int offset; __u8 cable_state, battery_capacity, battery_charging; /* @@ -1049,12 +1051,14 @@ static void sixaxis_parse_report(struct sony_sc *sc, __u8 *rd, int size) * It does not report the actual level while charging so it * is set to 100% while charging is in progress. */ - if (rd[30] >= 0xee) { + offset = (sc->quirks & MOTION_CONTROLLER) ? 12 : 30; + + if (rd[offset] >= 0xee) { battery_capacity = 100; - battery_charging = !(rd[30] & 0x01); + battery_charging = !(rd[offset] & 0x01); cable_state = 1; } else { - __u8 index = rd[30] <= 5 ? rd[30] : 5; + __u8 index = rd[offset] <= 5 ? rd[offset] : 5; battery_capacity = sixaxis_battery_capacity[index]; battery_charging = 0; cable_state = 0; @@ -1155,6 +1159,8 @@ static int sony_raw_event(struct hid_device *hdev, struct hid_report *report, swap(rd[47], rd[48]); sixaxis_parse_report(sc, rd, size); + } else if ((sc->quirks & MOTION_CONTROLLER_BT) && rd[0] == 0x01 && size == 49) { + sixaxis_parse_report(sc, rd, size); } else if (((sc->quirks & DUALSHOCK4_CONTROLLER_USB) && rd[0] == 0x01 && size == 64) || ((sc->quirks & DUALSHOCK4_CONTROLLER_BT) && rd[0] == 0x11 && size == 78)) { @@ -1976,6 +1982,7 @@ static int sony_check_add(struct sony_sc *sc) int n, ret; if ((sc->quirks & DUALSHOCK4_CONTROLLER_BT) || + (sc->quirks & MOTION_CONTROLLER_BT) || (sc->quirks & SIXAXIS_CONTROLLER_BT)) { /* * sony_get_bt_devaddr() attempts to parse the Bluetooth MAC -- cgit v1.1 From 41d2d42534e79561930aa831870352a80cd2e72c Mon Sep 17 00:00:00 2001 From: Simon Wood Date: Tue, 9 Jun 2015 21:27:06 -0600 Subject: HID: sony: PS3 Move enable LEDs and Rumble via BT The LED and Rumble control only function via BT if the full output report is sent. The large report still functions via USB. Signed-off-by: Simon Wood Signed-off-by: Jiri Kosina --- drivers/hid/hid-sony.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index d9fa804..51cb1ac 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c @@ -902,6 +902,7 @@ struct motion_output_report_02 { #define DS4_REPORT_0x81_SIZE 7 #define SIXAXIS_REPORT_0xF2_SIZE 17 #define SIXAXIS_REPORT_0xF5_SIZE 8 +#define MOTION_REPORT_0x02_SIZE 49 static DEFINE_SPINLOCK(sony_dev_list_lock); static LIST_HEAD(sony_device_list); @@ -1746,7 +1747,7 @@ static void motion_state_worker(struct work_struct *work) struct motion_output_report_02 *report = (struct motion_output_report_02 *)sc->output_report_dmabuf; - memset(report, 0, sizeof(struct motion_output_report_02)); + memset(report, 0, MOTION_REPORT_0x02_SIZE); report->type = 0x02; /* set leds */ report->r = sc->led_state[0]; @@ -1757,8 +1758,7 @@ static void motion_state_worker(struct work_struct *work) report->rumble = max(sc->right, sc->left); #endif - hid_hw_output_report(hdev, (__u8 *)report, - sizeof(struct motion_output_report_02)); + hid_hw_output_report(hdev, (__u8 *)report, MOTION_REPORT_0x02_SIZE); } static int sony_allocate_output_report(struct sony_sc *sc) @@ -1774,9 +1774,8 @@ static int sony_allocate_output_report(struct sony_sc *sc) sc->output_report_dmabuf = kmalloc(DS4_REPORT_0x05_SIZE, GFP_KERNEL); else if (sc->quirks & MOTION_CONTROLLER) - sc->output_report_dmabuf = - kmalloc(sizeof(struct motion_output_report_02), - GFP_KERNEL); + sc->output_report_dmabuf = kmalloc(MOTION_REPORT_0x02_SIZE, + GFP_KERNEL); else return 0; -- cgit v1.1 From 8b2513c313612541085a19551139e68ccab13b3f Mon Sep 17 00:00:00 2001 From: Simon Wood Date: Tue, 9 Jun 2015 21:27:07 -0600 Subject: HID: sony: PS Move fix report descriptor Fix the report descriptor so that the buttons and trigger are correctly reported. The format of the input report is described here: https://github.com/nitsch/moveonpc/wiki/Input-report The Accelerometers and Gyros (1st frame only) are also reported as axis, but the Magnetometers are NOT as 'fixing' their byte order would break user-space drivers such as PSMoveAPI. It is hoped to resolve this at a future time. Signed-off-by: Simon Wood Signed-off-by: Jiri Kosina --- drivers/hid/hid-sony.c | 69 ++++++++++++++++++++++++++++++++------------------ 1 file changed, 44 insertions(+), 25 deletions(-) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index 51cb1ac..2ce0295 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c @@ -153,52 +153,71 @@ static __u8 motion_rdesc[] = { 0xA1, 0x01, /* Collection (Application), */ 0xA1, 0x02, /* Collection (Logical), */ 0x85, 0x01, /* Report ID (1), */ - 0x75, 0x08, /* Report Size (8), */ - 0x95, 0x01, /* Report Count (1), */ - 0x15, 0x00, /* Logical Minimum (0), */ - 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ - 0x81, 0x03, /* Input (Constant, Variable), */ 0x75, 0x01, /* Report Size (1), */ - 0x95, 0x13, /* Report Count (19), */ + 0x95, 0x15, /* Report Count (21), */ 0x15, 0x00, /* Logical Minimum (0), */ 0x25, 0x01, /* Logical Maximum (1), */ 0x35, 0x00, /* Physical Minimum (0), */ 0x45, 0x01, /* Physical Maximum (1), */ 0x05, 0x09, /* Usage Page (Button), */ 0x19, 0x01, /* Usage Minimum (01h), */ - 0x29, 0x13, /* Usage Maximum (13h), */ - 0x81, 0x02, /* Input (Variable), */ - 0x75, 0x01, /* Report Size (1), */ - 0x95, 0x0D, /* Report Count (13), */ + 0x29, 0x15, /* Usage Maximum (15h), */ + 0x81, 0x02, /* Input (Variable), * Buttons */ + 0x95, 0x0B, /* Report Count (11), */ 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ - 0x81, 0x03, /* Input (Constant, Variable), */ + 0x81, 0x03, /* Input (Constant, Variable), * Padding */ 0x15, 0x00, /* Logical Minimum (0), */ 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ 0x05, 0x01, /* Usage Page (Desktop), */ - 0x09, 0x01, /* Usage (Pointer), */ 0xA1, 0x00, /* Collection (Physical), */ 0x75, 0x08, /* Report Size (8), */ - 0x95, 0x04, /* Report Count (4), */ + 0x95, 0x01, /* Report Count (1), */ 0x35, 0x00, /* Physical Minimum (0), */ 0x46, 0xFF, 0x00, /* Physical Maximum (255), */ 0x09, 0x30, /* Usage (X), */ - 0x09, 0x31, /* Usage (Y), */ - 0x09, 0x32, /* Usage (Z), */ - 0x09, 0x35, /* Usage (Rz), */ - 0x81, 0x02, /* Input (Variable), */ + 0x81, 0x02, /* Input (Variable), * Trigger */ 0xC0, /* End Collection, */ - 0x05, 0x01, /* Usage Page (Desktop), */ - 0x95, 0x13, /* Report Count (19), */ - 0x09, 0x01, /* Usage (Pointer), */ + 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ + 0x75, 0x08, /* Report Size (8), */ + 0x95, 0x07, /* Report Count (7), * skip 7 bytes */ 0x81, 0x02, /* Input (Variable), */ - 0x95, 0x0C, /* Report Count (12), */ - 0x81, 0x01, /* Input (Constant), */ + 0x05, 0x01, /* Usage Page (Desktop), */ 0x75, 0x10, /* Report Size (16), */ - 0x95, 0x04, /* Report Count (4), */ - 0x26, 0xFF, 0x03, /* Logical Maximum (1023), */ - 0x46, 0xFF, 0x03, /* Physical Maximum (1023), */ + 0x46, 0xFF, 0xFF, /* Physical Maximum (65535), */ + 0x27, 0xFF, 0xFF, 0x00, 0x00, /* Logical Maximum (65535), */ + 0x95, 0x03, /* Report Count (3), * 3x Accels */ + 0x09, 0x33, /* Usage (rX), */ + 0x09, 0x34, /* Usage (rY), */ + 0x09, 0x35, /* Usage (rZ), */ + 0x81, 0x02, /* Input (Variable), */ + 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ + 0x95, 0x03, /* Report Count (3), * Skip Accels 2nd frame */ + 0x81, 0x02, /* Input (Variable), */ + 0x05, 0x01, /* Usage Page (Desktop), */ 0x09, 0x01, /* Usage (Pointer), */ + 0x95, 0x03, /* Report Count (3), * 3x Gyros */ + 0x81, 0x02, /* Input (Variable), */ + 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ + 0x95, 0x03, /* Report Count (3), * Skip Gyros 2nd frame */ 0x81, 0x02, /* Input (Variable), */ + 0x75, 0x0C, /* Report Size (12), */ + 0x46, 0xFF, 0x0F, /* Physical Maximum (4095), */ + 0x26, 0xFF, 0x0F, /* Logical Maximum (4095), */ + 0x95, 0x04, /* Report Count (4), * Skip Temp and Magnetometers */ + 0x81, 0x02, /* Input (Variable), */ + 0x75, 0x08, /* Report Size (8), */ + 0x46, 0xFF, 0x00, /* Physical Maximum (255), */ + 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ + 0x95, 0x06, /* Report Count (6), * Skip Timestamp and Extension Bytes */ + 0x81, 0x02, /* Input (Variable), */ + 0x75, 0x08, /* Report Size (8), */ + 0x95, 0x30, /* Report Count (48), */ + 0x09, 0x01, /* Usage (Pointer), */ + 0x91, 0x02, /* Output (Variable), */ + 0x75, 0x08, /* Report Size (8), */ + 0x95, 0x30, /* Report Count (48), */ + 0x09, 0x01, /* Usage (Pointer), */ + 0xB1, 0x02, /* Feature (Variable), */ 0xC0, /* End Collection, */ 0xA1, 0x02, /* Collection (Logical), */ 0x85, 0x02, /* Report ID (2), */ -- cgit v1.1 From 81bb773faed7f5f0e82f14cdfcfe4e89fbea0e19 Mon Sep 17 00:00:00 2001 From: Terry Junge Date: Mon, 8 Jun 2015 14:27:57 -0700 Subject: HID: plantronics: Update to map volume up/down controls Update Kconfig with enhanced help text for hid-plantronics driver. Update hid-plantronics.c to identify device type and correctly map either the vendor unique or consumer control volume up/down usages to KEY_VOLUMEUP and KEY_VOLUMEDOWN events. Unmapped usages are ignored to prevent core mapping of unknown usages to random mouse events. Tested on ChromeBox/ChromeBook with various Plantronics devices. Signed-off-by: Terry Junge Signed-off-by: Jiri Kosina --- drivers/hid/Kconfig | 7 ++- drivers/hid/hid-plantronics.c | 132 +++++++++++++++++++++++++++++++++++++++--- 2 files changed, 130 insertions(+), 9 deletions(-) (limited to 'drivers/hid') diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index 15338af..cc4c664 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig @@ -634,7 +634,12 @@ config HID_PLANTRONICS tristate "Plantronics USB HID Driver" depends on HID ---help--- - Provides HID support for Plantronics telephony devices. + Provides HID support for Plantronics USB audio devices. + Correctly maps vendor unique volume up/down HID usages to + KEY_VOLUMEUP and KEY_VOLUMEDOWN events and prevents core mapping + of other vendor unique HID usages to random mouse events. + + Say M here if you may ever plug in a Plantronics USB audio device. config HID_PRIMAX tristate "Primax non-fully HID-compliant devices" diff --git a/drivers/hid/hid-plantronics.c b/drivers/hid/hid-plantronics.c index 2180e07..febb21e 100644 --- a/drivers/hid/hid-plantronics.c +++ b/drivers/hid/hid-plantronics.c @@ -2,7 +2,7 @@ * Plantronics USB HID Driver * * Copyright (c) 2014 JD Cole - * Copyright (c) 2014 Terry Junge + * Copyright (c) 2015 Terry Junge */ /* @@ -17,23 +17,138 @@ #include #include +#define PLT_HID_1_0_PAGE 0xffa00000 +#define PLT_HID_2_0_PAGE 0xffa20000 + +#define PLT_BASIC_TELEPHONY 0x0003 +#define PLT_BASIC_EXCEPTION 0x0005 + +#define PLT_VOL_UP 0x00b1 +#define PLT_VOL_DOWN 0x00b2 + +#define PLT1_VOL_UP (PLT_HID_1_0_PAGE | PLT_VOL_UP) +#define PLT1_VOL_DOWN (PLT_HID_1_0_PAGE | PLT_VOL_DOWN) +#define PLT2_VOL_UP (PLT_HID_2_0_PAGE | PLT_VOL_UP) +#define PLT2_VOL_DOWN (PLT_HID_2_0_PAGE | PLT_VOL_DOWN) + +#define PLT_DA60 0xda60 +#define PLT_BT300_MIN 0x0413 +#define PLT_BT300_MAX 0x0418 + + +#define PLT_ALLOW_CONSUMER (field->application == HID_CP_CONSUMERCONTROL && \ + (usage->hid & HID_USAGE_PAGE) == HID_UP_CONSUMER) + 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; + unsigned short mapped_key; + unsigned long plt_type = (unsigned long)hid_get_drvdata(hdev); + + /* handle volume up/down mapping */ + /* non-standard types or multi-HID interfaces - plt_type is PID */ + if (!(plt_type & HID_USAGE_PAGE)) { + switch (plt_type) { + case PLT_DA60: + if (PLT_ALLOW_CONSUMER) + goto defaulted; + goto ignored; + default: + if (PLT_ALLOW_CONSUMER) + goto defaulted; + } + } + /* handle standard types - plt_type is 0xffa0uuuu or 0xffa2uuuu */ + /* 'basic telephony compliant' - allow default consumer page map */ + else if ((plt_type & HID_USAGE) >= PLT_BASIC_TELEPHONY && + (plt_type & HID_USAGE) != PLT_BASIC_EXCEPTION) { + if (PLT_ALLOW_CONSUMER) + goto defaulted; + } + /* not 'basic telephony' - apply legacy mapping */ + /* only map if the field is in the device's primary vendor page */ + else if (!((field->application ^ plt_type) & HID_USAGE_PAGE)) { + switch (usage->hid) { + case PLT1_VOL_UP: + case PLT2_VOL_UP: + mapped_key = KEY_VOLUMEUP; + goto mapped; + case PLT1_VOL_DOWN: + case PLT2_VOL_DOWN: + mapped_key = KEY_VOLUMEDOWN; + goto mapped; + } } - hid_dbg(hdev, "usage: %08x (appl: %08x) - ignored\n", - usage->hid, field->application); +/* + * Future mapping of call control or other usages, + * if and when keys are defined would go here + * otherwise, ignore everything else that was not mapped + */ +ignored: return -1; + +defaulted: + hid_dbg(hdev, "usage: %08x (appl: %08x) - defaulted\n", + usage->hid, field->application); + return 0; + +mapped: + hid_map_usage_clear(hi, usage, bit, max, EV_KEY, mapped_key); + hid_dbg(hdev, "usage: %08x (appl: %08x) - mapped to key %d\n", + usage->hid, field->application, mapped_key); + return 1; +} + +static unsigned long plantronics_device_type(struct hid_device *hdev) +{ + unsigned i, col_page; + unsigned long plt_type = hdev->product; + + /* multi-HID interfaces? - plt_type is PID */ + if (plt_type >= PLT_BT300_MIN && plt_type <= PLT_BT300_MAX) + goto exit; + + /* determine primary vendor page */ + for (i = 0; i < hdev->maxcollection; i++) { + col_page = hdev->collection[i].usage & HID_USAGE_PAGE; + if (col_page == PLT_HID_2_0_PAGE) { + plt_type = hdev->collection[i].usage; + break; + } + if (col_page == PLT_HID_1_0_PAGE) + plt_type = hdev->collection[i].usage; + } + +exit: + hid_dbg(hdev, "plt_type decoded as: %08lx\n", plt_type); + return plt_type; +} + +static int plantronics_probe(struct hid_device *hdev, + const struct hid_device_id *id) +{ + int ret; + + ret = hid_parse(hdev); + if (ret) { + hid_err(hdev, "parse failed\n"); + goto err; + } + + hid_set_drvdata(hdev, (void *)plantronics_device_type(hdev)); + + ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT | + HID_CONNECT_HIDINPUT_FORCE | HID_CONNECT_HIDDEV_FORCE); + if (ret) + hid_err(hdev, "hw start failed\n"); + +err: + return ret; } static const struct hid_device_id plantronics_devices[] = { @@ -46,6 +161,7 @@ static struct hid_driver plantronics_driver = { .name = "plantronics", .id_table = plantronics_devices, .input_mapping = plantronics_input_mapping, + .probe = plantronics_probe, }; module_hid_driver(plantronics_driver); -- cgit v1.1 From 10e87dc42a086c256b25334b6c1c89214feba9a7 Mon Sep 17 00:00:00 2001 From: Andrew Duggan Date: Tue, 16 Jun 2015 14:08:41 -0700 Subject: HID: rmi: Disable populating F30 when the touchpad has physical buttons Physical buttons do not use F30 to report their state and in some cases the data reported in F30 is incorrect and inconsistent with what is reported by the HID descriptor. When physical buttons are present, ignore F30 and let hid-input report buttons based on what is defined in the HID descriptor. Signed-off-by: Andrew Duggan Reviewed-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/hid-rmi.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-rmi.c b/drivers/hid/hid-rmi.c index 368ffdf..721f7f9 100644 --- a/drivers/hid/hid-rmi.c +++ b/drivers/hid/hid-rmi.c @@ -1013,6 +1013,7 @@ static int rmi_populate_f30(struct hid_device *hdev) static int rmi_populate(struct hid_device *hdev) { + struct rmi_data *data = hid_get_drvdata(hdev); int ret; ret = rmi_scan_pdt(hdev); @@ -1033,9 +1034,11 @@ static int rmi_populate(struct hid_device *hdev) return ret; } - ret = rmi_populate_f30(hdev); - if (ret) - hid_warn(hdev, "Error while initializing F30 (%d).\n", ret); + if (!(data->device_flags & RMI_DEVICE_HAS_PHYS_BUTTONS)) { + ret = rmi_populate_f30(hdev); + if (ret) + hid_warn(hdev, "Error while initializing F30 (%d).\n", ret); + } return 0; } -- cgit v1.1 From 44b5250b97a0e5c3a257430ea28b10cf73899bd4 Mon Sep 17 00:00:00 2001 From: Jason Gerecke Date: Mon, 15 Jun 2015 18:01:41 -0700 Subject: HID: wacom: Simplify 'wacom_update_name' A little bit of cleanup work for 'wacom_update_name' to make it easier on the eyes. Creates a temporary 'name' variable on which we'll perform our edits. Once the name is in its final form, it will be copied (with appropriate suffix) to 'wacom_wac->name' and 'wacom_wac->pad_name'. Signed-off-by: Jason Gerecke Signed-off-by: Jiri Kosina --- drivers/hid/wacom_sys.c | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) (limited to 'drivers/hid') diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c index eea18a6..bdf31c9 100644 --- a/drivers/hid/wacom_sys.c +++ b/drivers/hid/wacom_sys.c @@ -1417,6 +1417,7 @@ static void wacom_update_name(struct wacom *wacom) { struct wacom_wac *wacom_wac = &wacom->wacom_wac; struct wacom_features *features = &wacom_wac->features; + char name[WACOM_NAME_MAX]; /* Generic devices name unspecified */ if ((features->type == HID_GENERIC) && !strcmp("Wacom HID", features->name)) { @@ -1424,41 +1425,43 @@ static void wacom_update_name(struct wacom *wacom) strstr(wacom->hdev->name, "wacom") || strstr(wacom->hdev->name, "WACOM")) { /* name is in HID descriptor, use it */ - strlcpy(wacom_wac->name, wacom->hdev->name, - sizeof(wacom_wac->name)); + strlcpy(name, wacom->hdev->name, sizeof(name)); /* strip out excess whitespaces */ while (1) { - char *gap = strstr(wacom_wac->name, " "); + char *gap = strstr(name, " "); if (gap == NULL) break; /* shift everything including the terminator */ memmove(gap, gap+1, strlen(gap)); } /* get rid of trailing whitespace */ - if (wacom_wac->name[strlen(wacom_wac->name)-1] == ' ') - wacom_wac->name[strlen(wacom_wac->name)-1] = '\0'; + if (name[strlen(name)-1] == ' ') + name[strlen(name)-1] = '\0'; } else { /* no meaningful name retrieved. use product ID */ - snprintf(wacom_wac->name, sizeof(wacom_wac->name), + snprintf(name, sizeof(name), "%s %X", features->name, wacom->hdev->product); } } else { - strlcpy(wacom_wac->name, features->name, sizeof(wacom_wac->name)); + strlcpy(name, features->name, sizeof(name)); } /* Append the device type to the name */ snprintf(wacom_wac->pad_name, sizeof(wacom_wac->pad_name), - "%s Pad", wacom_wac->name); + "%s Pad", name); if (features->device_type == BTN_TOOL_PEN) { - strlcat(wacom_wac->name, " Pen", WACOM_NAME_MAX); + snprintf(wacom_wac->name, sizeof(wacom_wac->name), + "%s Pen", name); } else if (features->device_type == BTN_TOOL_FINGER) { if (features->touch_max) - strlcat(wacom_wac->name, " Finger", WACOM_NAME_MAX); + snprintf(wacom_wac->name, sizeof(wacom_wac->name), + "%s Finger", name); else - strlcat(wacom_wac->name, " Pad", WACOM_NAME_MAX); + snprintf(wacom_wac->name, sizeof(wacom_wac->name), + "%s Pad", name); } } -- cgit v1.1 From aa86b18cc9cd147b40412a2d57b383a5e16fe3b5 Mon Sep 17 00:00:00 2001 From: Jason Gerecke Date: Mon, 15 Jun 2015 18:01:42 -0700 Subject: HID: wacom: Treat features->device_type values as flags The USB devices that this driver has historically supported segregate the pen and touch portions of the tablet. Oftentimes the segregation would be done at the interface level, though on occasion (e.g. Cintiq 24HDT) the tablet would combine two totally independent USB devices behind an internal USB hub. Because pen and touch never shared the same interface, it made sense for the 'device_type' to store a single value: "pen" or "touch". Recently, however, some I2C devices have been created which combine the two. A first step to accomodating this is to expand 'device_type' so that it can represent two (or potentially more) types simultaneously. To do this, we treat it as a bitfield and set/check individual bits rather than using the '=' and '==' operators. This should not result in any functional change since no supported devices (that I'm aware of, at least) have HID descriptors that indicate both pen and touch reports on a single interface. Signed-off-by: Jason Gerecke Signed-off-by: Jiri Kosina --- drivers/hid/wacom_sys.c | 35 ++++++++++++++++++----------------- drivers/hid/wacom_wac.c | 30 +++++++++++++++--------------- drivers/hid/wacom_wac.h | 5 +++++ 3 files changed, 38 insertions(+), 32 deletions(-) (limited to 'drivers/hid') diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c index bdf31c9..2b4cbd8 100644 --- a/drivers/hid/wacom_sys.c +++ b/drivers/hid/wacom_sys.c @@ -197,9 +197,9 @@ static void wacom_usage_mapping(struct hid_device *hdev, * values commonly reported. */ if (pen) - features->device_type = BTN_TOOL_PEN; + features->device_type |= WACOM_DEVICETYPE_PEN; else if (finger) - features->device_type = BTN_TOOL_FINGER; + features->device_type |= WACOM_DEVICETYPE_TOUCH; else return; @@ -411,7 +411,7 @@ static int wacom_query_tablet_data(struct hid_device *hdev, if (features->type == HID_GENERIC) return wacom_hid_set_device_mode(hdev); - if (features->device_type == BTN_TOOL_FINGER) { + if (features->device_type & WACOM_DEVICETYPE_TOUCH) { if (features->type > TABLETPC) { /* MT Tablet PC touch */ return wacom_set_device_mode(hdev, 3, 4, 4); @@ -425,7 +425,7 @@ static int wacom_query_tablet_data(struct hid_device *hdev, else if (features->type == BAMBOO_PAD) { return wacom_set_device_mode(hdev, 2, 2, 2); } - } else if (features->device_type == BTN_TOOL_PEN) { + } else if (features->device_type & WACOM_DEVICETYPE_PEN) { if (features->type <= BAMBOO_PT && features->type != WIRELESS) { return wacom_set_device_mode(hdev, 2, 2, 2); } @@ -454,9 +454,9 @@ static void wacom_retrieve_hid_descriptor(struct hid_device *hdev, */ if (features->type == WIRELESS) { if (intf->cur_altsetting->desc.bInterfaceNumber == 0) { - features->device_type = 0; + features->device_type = WACOM_DEVICETYPE_NONE; } else if (intf->cur_altsetting->desc.bInterfaceNumber == 2) { - features->device_type = BTN_TOOL_FINGER; + features->device_type |= WACOM_DEVICETYPE_TOUCH; features->pktlen = WACOM_PKGLEN_BBTOUCH3; } } @@ -538,9 +538,9 @@ static int wacom_add_shared_data(struct hid_device *hdev) wacom_wac->shared = &data->shared; - if (wacom_wac->features.device_type == BTN_TOOL_FINGER) + if (wacom_wac->features.device_type & WACOM_DEVICETYPE_TOUCH) wacom_wac->shared->touch = hdev; - else if (wacom_wac->features.device_type == BTN_TOOL_PEN) + else if (wacom_wac->features.device_type & WACOM_DEVICETYPE_PEN) wacom_wac->shared->pen = hdev; out: @@ -892,7 +892,7 @@ static int wacom_initialize_leds(struct wacom *wacom) case INTUOSPS: case INTUOSPM: case INTUOSPL: - if (wacom->wacom_wac.features.device_type == BTN_TOOL_PEN) { + if (wacom->wacom_wac.features.device_type & WACOM_DEVICETYPE_PEN) { wacom->led.select[0] = 0; wacom->led.select[1] = 0; wacom->led.llv = 32; @@ -948,7 +948,7 @@ static void wacom_destroy_leds(struct wacom *wacom) case INTUOSPS: case INTUOSPM: case INTUOSPL: - if (wacom->wacom_wac.features.device_type == BTN_TOOL_PEN) + if (wacom->wacom_wac.features.device_type & WACOM_DEVICETYPE_PEN) sysfs_remove_group(&wacom->hdev->dev.kobj, &intuos5_led_attr_group); break; @@ -1296,7 +1296,7 @@ static void wacom_wireless_work(struct work_struct *work) /* Stylus interface */ wacom_wac1->features = *((struct wacom_features *)id->driver_data); - wacom_wac1->features.device_type = BTN_TOOL_PEN; + wacom_wac1->features.device_type |= WACOM_DEVICETYPE_PEN; snprintf(wacom_wac1->name, WACOM_NAME_MAX, "%s (WL) Pen", wacom_wac1->features.name); snprintf(wacom_wac1->pad_name, WACOM_NAME_MAX, "%s (WL) Pad", @@ -1315,7 +1315,7 @@ static void wacom_wireless_work(struct work_struct *work) wacom_wac2->features = *((struct wacom_features *)id->driver_data); wacom_wac2->features.pktlen = WACOM_PKGLEN_BBTOUCH3; - wacom_wac2->features.device_type = BTN_TOOL_FINGER; + wacom_wac2->features.device_type |= WACOM_DEVICETYPE_TOUCH; wacom_wac2->features.x_max = wacom_wac2->features.y_max = 4096; if (wacom_wac2->features.touch_max) snprintf(wacom_wac2->name, WACOM_NAME_MAX, @@ -1451,11 +1451,11 @@ static void wacom_update_name(struct wacom *wacom) snprintf(wacom_wac->pad_name, sizeof(wacom_wac->pad_name), "%s Pad", name); - if (features->device_type == BTN_TOOL_PEN) { + if (features->device_type & WACOM_DEVICETYPE_PEN) { snprintf(wacom_wac->name, sizeof(wacom_wac->name), "%s Pen", name); } - else if (features->device_type == BTN_TOOL_FINGER) { + else if (features->device_type & WACOM_DEVICETYPE_TOUCH) { if (features->touch_max) snprintf(wacom_wac->name, sizeof(wacom_wac->name), "%s Finger", name); @@ -1545,7 +1545,8 @@ static int wacom_probe(struct hid_device *hdev, wacom_retrieve_hid_descriptor(hdev, features); wacom_setup_device_quirks(wacom); - if (!features->device_type && features->type != WIRELESS) { + if (features->device_type == WACOM_DEVICETYPE_NONE && + features->type != WIRELESS) { error = features->type == HID_GENERIC ? -ENODEV : 0; dev_warn(&hdev->dev, "Unknown device_type for '%s'. %s.", @@ -1555,7 +1556,7 @@ static int wacom_probe(struct hid_device *hdev, if (error) goto fail_shared_data; - features->device_type = BTN_TOOL_PEN; + features->device_type |= WACOM_DEVICETYPE_PEN; } wacom_calculate_res(features); @@ -1604,7 +1605,7 @@ static int wacom_probe(struct hid_device *hdev, error = hid_hw_open(hdev); if (wacom_wac->features.type == INTUOSHT && wacom_wac->features.touch_max) { - if (wacom_wac->features.device_type == BTN_TOOL_FINGER) + if (wacom_wac->features.device_type & WACOM_DEVICETYPE_TOUCH) wacom_wac->shared->touch_input = wacom_wac->input; } diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index a52fc25..5e7710d 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -2168,7 +2168,7 @@ void wacom_setup_device_quirks(struct wacom *wacom) struct wacom_features *features = &wacom->wacom_wac.features; /* touch device found but size is not defined. use default */ - if (features->device_type == BTN_TOOL_FINGER && !features->x_max) { + if (features->device_type & WACOM_DEVICETYPE_TOUCH && !features->x_max) { features->x_max = 1023; features->y_max = 1023; } @@ -2182,7 +2182,7 @@ void wacom_setup_device_quirks(struct wacom *wacom) if ((features->type >= INTUOS5S && features->type <= INTUOSHT) || (features->type == BAMBOO_PT)) { if (features->pktlen == WACOM_PKGLEN_BBTOUCH3) { - features->device_type = BTN_TOOL_FINGER; + features->device_type |= WACOM_DEVICETYPE_TOUCH; features->x_max = 4096; features->y_max = 4096; @@ -2197,7 +2197,7 @@ void wacom_setup_device_quirks(struct wacom *wacom) * so rewrite this one to be of type BTN_TOOL_FINGER. */ if (features->type == BAMBOO_PAD) - features->device_type = BTN_TOOL_FINGER; + features->device_type |= WACOM_DEVICETYPE_TOUCH; if (wacom->hdev->bus == BUS_BLUETOOTH) features->quirks |= WACOM_QUIRK_BATTERY; @@ -2218,7 +2218,7 @@ void wacom_setup_device_quirks(struct wacom *wacom) features->quirks |= WACOM_QUIRK_NO_INPUT; /* must be monitor interface if no device_type set */ - if (!features->device_type) { + if (features->device_type == WACOM_DEVICETYPE_NONE) { features->quirks |= WACOM_QUIRK_MONITOR; features->quirks |= WACOM_QUIRK_BATTERY; } @@ -2230,7 +2230,7 @@ static void wacom_abs_set_axis(struct input_dev *input_dev, { struct wacom_features *features = &wacom_wac->features; - if (features->device_type == BTN_TOOL_PEN) { + if (features->device_type & WACOM_DEVICETYPE_PEN) { input_set_abs_params(input_dev, ABS_X, features->x_min, features->x_max, features->x_fuzz, 0); input_set_abs_params(input_dev, ABS_Y, features->y_min, @@ -2349,7 +2349,7 @@ int wacom_setup_pentouch_input_capabilities(struct input_dev *input_dev, case INTUOSPS: __set_bit(INPUT_PROP_POINTER, input_dev->propbit); - if (features->device_type == BTN_TOOL_PEN) { + if (features->device_type & WACOM_DEVICETYPE_PEN) { input_set_abs_params(input_dev, ABS_DISTANCE, 0, features->distance_max, 0, 0); @@ -2358,7 +2358,7 @@ int wacom_setup_pentouch_input_capabilities(struct input_dev *input_dev, input_abs_set_res(input_dev, ABS_Z, 287); wacom_setup_intuos(wacom_wac); - } else if (features->device_type == BTN_TOOL_FINGER) { + } else if (features->device_type & WACOM_DEVICETYPE_TOUCH) { __clear_bit(ABS_MISC, input_dev->absbit); input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, @@ -2370,7 +2370,7 @@ int wacom_setup_pentouch_input_capabilities(struct input_dev *input_dev, break; case WACOM_24HDT: - if (features->device_type == BTN_TOOL_FINGER) { + if (features->device_type & WACOM_DEVICETYPE_TOUCH) { input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, features->x_max, 0, 0); input_set_abs_params(input_dev, ABS_MT_WIDTH_MAJOR, 0, features->x_max, 0, 0); input_set_abs_params(input_dev, ABS_MT_WIDTH_MINOR, 0, features->y_max, 0, 0); @@ -2383,7 +2383,7 @@ int wacom_setup_pentouch_input_capabilities(struct input_dev *input_dev, case MTTPC: case MTTPC_B: case TABLETPC2FG: - if (features->device_type == BTN_TOOL_FINGER && features->touch_max > 1) + if (features->device_type & WACOM_DEVICETYPE_TOUCH && features->touch_max > 1) input_mt_init_slots(input_dev, features->touch_max, INPUT_MT_DIRECT); /* fall through */ @@ -2393,7 +2393,7 @@ int wacom_setup_pentouch_input_capabilities(struct input_dev *input_dev, __set_bit(INPUT_PROP_DIRECT, input_dev->propbit); - if (features->device_type != BTN_TOOL_PEN) + if (!(features->device_type & WACOM_DEVICETYPE_PEN)) break; /* no need to process stylus stuff */ /* fall through */ @@ -2424,7 +2424,7 @@ int wacom_setup_pentouch_input_capabilities(struct input_dev *input_dev, case INTUOSHT: if (features->touch_max && - features->device_type == BTN_TOOL_FINGER) { + features->device_type & WACOM_DEVICETYPE_TOUCH) { input_dev->evbit[0] |= BIT_MASK(EV_SW); __set_bit(SW_MUTE_DEVICE, input_dev->swbit); } @@ -2433,7 +2433,7 @@ int wacom_setup_pentouch_input_capabilities(struct input_dev *input_dev, case BAMBOO_PT: __clear_bit(ABS_MISC, input_dev->absbit); - if (features->device_type == BTN_TOOL_FINGER) { + if (features->device_type & WACOM_DEVICETYPE_TOUCH) { if (features->touch_max) { if (features->pktlen == WACOM_PKGLEN_BBTOUCH3) { @@ -2454,7 +2454,7 @@ int wacom_setup_pentouch_input_capabilities(struct input_dev *input_dev, /* PAD is setup by wacom_setup_pad_input_capabilities later */ return 1; } - } else if (features->device_type == BTN_TOOL_PEN) { + } else if (features->device_type & WACOM_DEVICETYPE_PEN) { __set_bit(INPUT_PROP_POINTER, input_dev->propbit); __set_bit(BTN_TOOL_RUBBER, input_dev->keybit); __set_bit(BTN_TOOL_PEN, input_dev->keybit); @@ -2619,7 +2619,7 @@ int wacom_setup_pad_input_capabilities(struct input_dev *input_dev, case INTUOS5S: case INTUOSPS: /* touch interface does not have the pad device */ - if (features->device_type != BTN_TOOL_PEN) + if (!(features->device_type & WACOM_DEVICETYPE_PEN)) return -ENODEV; for (i = 0; i < 7; i++) @@ -2664,7 +2664,7 @@ 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) || + if (!(features->device_type & WACOM_DEVICETYPE_TOUCH) || /* Bamboo Pen only tablet does not have pad */ ((features->type == BAMBOO_PT) && !features->touch_max)) return -ENODEV; diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h index 9a5ee62..da2b309 100644 --- a/drivers/hid/wacom_wac.h +++ b/drivers/hid/wacom_wac.h @@ -72,6 +72,11 @@ #define WACOM_QUIRK_MONITOR 0x0004 #define WACOM_QUIRK_BATTERY 0x0008 +/* device types */ +#define WACOM_DEVICETYPE_NONE 0x0000 +#define WACOM_DEVICETYPE_PEN 0x0001 +#define WACOM_DEVICETYPE_TOUCH 0x0002 + #define WACOM_VENDORDEFINED_PEN 0xff0d0001 #define WACOM_PEN_FIELD(f) (((f)->logical == HID_DG_STYLUS) || \ -- cgit v1.1 From 862cf5535c0cf4b39ce71a3b7e9a1c22ae4f70ae Mon Sep 17 00:00:00 2001 From: Jason Gerecke Date: Mon, 15 Jun 2015 18:01:43 -0700 Subject: HID: wacom: Introduce a new WACOM_DEVICETYPE_PAD device_type Historically, both the touch and pad tools would have shared the 'BTN_TOOL_FINGER' type. Any time you needed to distinguish the two, you had to use some other bit of knowledge (e.g. that the pad was on the same interface as the pen, and thus 'touch_max' would be zero). To make these checks more readable, we introduce WACOM_DEVICETYPE_PAD. Although we still have to rely on other bits of knowledge to set this bit on the right interface (since it cannot be detected from the HID descriptor), it can be done just once inside 'wacom_setup_device_quirks'. This patch introduces no functional changes. Signed-off-by: Jason Gerecke Signed-off-by: Jiri Kosina --- drivers/hid/wacom_sys.c | 65 +++++++++++++++++++++++--------------------- drivers/hid/wacom_wac.c | 71 ++++++++++++++++++++++++++----------------------- drivers/hid/wacom_wac.h | 1 + 3 files changed, 73 insertions(+), 64 deletions(-) (limited to 'drivers/hid') diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c index 2b4cbd8..aaa9c84 100644 --- a/drivers/hid/wacom_sys.c +++ b/drivers/hid/wacom_sys.c @@ -859,6 +859,9 @@ static int wacom_initialize_leds(struct wacom *wacom) { int error; + if (!(wacom->wacom_wac.features.device_type & WACOM_DEVICETYPE_PAD)) + return 0; + /* Initialize default values */ switch (wacom->wacom_wac.features.type) { case INTUOS4S: @@ -892,17 +895,14 @@ static int wacom_initialize_leds(struct wacom *wacom) case INTUOSPS: case INTUOSPM: case INTUOSPL: - if (wacom->wacom_wac.features.device_type & WACOM_DEVICETYPE_PEN) { - wacom->led.select[0] = 0; - wacom->led.select[1] = 0; - wacom->led.llv = 32; - wacom->led.hlv = 0; - wacom->led.img_lum = 0; - - error = sysfs_create_group(&wacom->hdev->dev.kobj, - &intuos5_led_attr_group); - } else - return 0; + wacom->led.select[0] = 0; + wacom->led.select[1] = 0; + wacom->led.llv = 32; + wacom->led.hlv = 0; + wacom->led.img_lum = 0; + + error = sysfs_create_group(&wacom->hdev->dev.kobj, + &intuos5_led_attr_group); break; default: @@ -925,6 +925,9 @@ static void wacom_destroy_leds(struct wacom *wacom) if (!wacom->led_initialized) return; + if (!(wacom->wacom_wac.features.device_type & WACOM_DEVICETYPE_PAD)) + return; + wacom->led_initialized = false; switch (wacom->wacom_wac.features.type) { @@ -948,9 +951,8 @@ static void wacom_destroy_leds(struct wacom *wacom) case INTUOSPS: case INTUOSPM: case INTUOSPL: - if (wacom->wacom_wac.features.device_type & WACOM_DEVICETYPE_PEN) - sysfs_remove_group(&wacom->hdev->dev.kobj, - &intuos5_led_attr_group); + sysfs_remove_group(&wacom->hdev->dev.kobj, + &intuos5_led_attr_group); break; } } @@ -1297,6 +1299,9 @@ static void wacom_wireless_work(struct work_struct *work) wacom_wac1->features = *((struct wacom_features *)id->driver_data); wacom_wac1->features.device_type |= WACOM_DEVICETYPE_PEN; + if (wacom_wac1->features.type != INTUOSHT && + wacom_wac1->features.type != BAMBOO_PT) + wacom_wac1->features.device_type |= WACOM_DEVICETYPE_PAD; snprintf(wacom_wac1->name, WACOM_NAME_MAX, "%s (WL) Pen", wacom_wac1->features.name); snprintf(wacom_wac1->pad_name, WACOM_NAME_MAX, "%s (WL) Pad", @@ -1315,16 +1320,16 @@ static void wacom_wireless_work(struct work_struct *work) wacom_wac2->features = *((struct wacom_features *)id->driver_data); wacom_wac2->features.pktlen = WACOM_PKGLEN_BBTOUCH3; - wacom_wac2->features.device_type |= WACOM_DEVICETYPE_TOUCH; wacom_wac2->features.x_max = wacom_wac2->features.y_max = 4096; - if (wacom_wac2->features.touch_max) - snprintf(wacom_wac2->name, WACOM_NAME_MAX, - "%s (WL) Finger",wacom_wac2->features.name); - else - snprintf(wacom_wac2->name, WACOM_NAME_MAX, - "%s (WL) Pad",wacom_wac2->features.name); + snprintf(wacom_wac2->name, WACOM_NAME_MAX, + "%s (WL) Finger",wacom_wac2->features.name); snprintf(wacom_wac2->pad_name, WACOM_NAME_MAX, - "%s (WL) Pad", wacom_wac2->features.name); + "%s (WL) Pad",wacom_wac2->features.name); + if (wacom_wac1->features.touch_max) + wacom_wac2->features.device_type |= WACOM_DEVICETYPE_TOUCH; + if (wacom_wac1->features.type == INTUOSHT || + wacom_wac1->features.type == BAMBOO_PT) + wacom_wac2->features.device_type |= WACOM_DEVICETYPE_PAD; wacom_wac2->pid = wacom_wac->pid; error = wacom_allocate_inputs(wacom2) || wacom_register_inputs(wacom2); @@ -1456,12 +1461,12 @@ static void wacom_update_name(struct wacom *wacom) "%s Pen", name); } else if (features->device_type & WACOM_DEVICETYPE_TOUCH) { - if (features->touch_max) - snprintf(wacom_wac->name, sizeof(wacom_wac->name), - "%s Finger", name); - else - snprintf(wacom_wac->name, sizeof(wacom_wac->name), - "%s Pad", name); + snprintf(wacom_wac->name, sizeof(wacom_wac->name), + "%s Finger", name); + } + else if (features->device_type & WACOM_DEVICETYPE_PAD) { + snprintf(wacom_wac->name, sizeof(wacom_wac->name), + "%s Pad", name); } } @@ -1604,8 +1609,8 @@ static int wacom_probe(struct hid_device *hdev, if (features->quirks & WACOM_QUIRK_MONITOR) error = hid_hw_open(hdev); - if (wacom_wac->features.type == INTUOSHT && wacom_wac->features.touch_max) { - if (wacom_wac->features.device_type & WACOM_DEVICETYPE_TOUCH) + if (wacom_wac->features.type == INTUOSHT && + wacom_wac->features.device_type & WACOM_DEVICETYPE_TOUCH) { wacom_wac->shared->touch_input = wacom_wac->input; } diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index 5e7710d..564a06d 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -2167,6 +2167,15 @@ void wacom_setup_device_quirks(struct wacom *wacom) { struct wacom_features *features = &wacom->wacom_wac.features; + /* The pen and pad share the same interface on most devices */ + if (features->type == GRAPHIRE_BT || features->type == WACOM_G4 || + features->type == DTUS || features->type == WACOM_MO || + (features->type >= INTUOS3S && features->type <= WACOM_13HD && + features->type != INTUOSHT)) { + if (features->device_type & WACOM_DEVICETYPE_PEN) + features->device_type |= WACOM_DEVICETYPE_PAD; + } + /* touch device found but size is not defined. use default */ if (features->device_type & WACOM_DEVICETYPE_TOUCH && !features->x_max) { features->x_max = 1023; @@ -2182,7 +2191,10 @@ void wacom_setup_device_quirks(struct wacom *wacom) if ((features->type >= INTUOS5S && features->type <= INTUOSHT) || (features->type == BAMBOO_PT)) { if (features->pktlen == WACOM_PKGLEN_BBTOUCH3) { - features->device_type |= WACOM_DEVICETYPE_TOUCH; + if (features->touch_max) + features->device_type |= WACOM_DEVICETYPE_TOUCH; + if (features->type == BAMBOO_PT || features->type == INTUOSHT) + features->device_type |= WACOM_DEVICETYPE_PAD; features->x_max = 4096; features->y_max = 4096; @@ -2241,7 +2253,7 @@ static void wacom_abs_set_axis(struct input_dev *input_dev, /* penabled devices have fixed resolution for each model */ input_abs_set_res(input_dev, ABS_X, features->x_resolution); input_abs_set_res(input_dev, ABS_Y, features->y_resolution); - } else { + } else if (features->device_type & WACOM_DEVICETYPE_TOUCH) { if (features->touch_max == 1) { input_set_abs_params(input_dev, ABS_X, 0, features->x_max, features->x_fuzz, 0); @@ -2423,8 +2435,7 @@ int wacom_setup_pentouch_input_capabilities(struct input_dev *input_dev, break; case INTUOSHT: - if (features->touch_max && - features->device_type & WACOM_DEVICETYPE_TOUCH) { + if (features->device_type & WACOM_DEVICETYPE_TOUCH) { input_dev->evbit[0] |= BIT_MASK(EV_SW); __set_bit(SW_MUTE_DEVICE, input_dev->swbit); } @@ -2434,27 +2445,26 @@ int wacom_setup_pentouch_input_capabilities(struct input_dev *input_dev, __clear_bit(ABS_MISC, input_dev->absbit); if (features->device_type & WACOM_DEVICETYPE_TOUCH) { - - if (features->touch_max) { - if (features->pktlen == WACOM_PKGLEN_BBTOUCH3) { - input_set_abs_params(input_dev, - ABS_MT_TOUCH_MAJOR, - 0, features->x_max, 0, 0); - input_set_abs_params(input_dev, - ABS_MT_TOUCH_MINOR, - 0, features->y_max, 0, 0); - } - input_mt_init_slots(input_dev, features->touch_max, INPUT_MT_POINTER); - } else { - /* buttons/keys only interface */ - __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; + if (features->pktlen == WACOM_PKGLEN_BBTOUCH3) { + input_set_abs_params(input_dev, + ABS_MT_TOUCH_MAJOR, + 0, features->x_max, 0, 0); + input_set_abs_params(input_dev, + ABS_MT_TOUCH_MINOR, + 0, features->y_max, 0, 0); } - } else if (features->device_type & WACOM_DEVICETYPE_PEN) { + input_mt_init_slots(input_dev, features->touch_max, INPUT_MT_POINTER); + } + if (features->device_type & WACOM_DEVICETYPE_PAD) { + /* buttons/keys only interface */ + __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; + } + if (features->device_type & WACOM_DEVICETYPE_PEN) { __set_bit(INPUT_PROP_POINTER, input_dev->propbit); __set_bit(BTN_TOOL_RUBBER, input_dev->keybit); __set_bit(BTN_TOOL_PEN, input_dev->keybit); @@ -2482,6 +2492,9 @@ int wacom_setup_pad_input_capabilities(struct input_dev *input_dev, struct wacom_features *features = &wacom_wac->features; int i; + if (!(features->device_type & WACOM_DEVICETYPE_PAD)) + return -ENODEV; + input_dev->evbit[0] |= BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); /* kept for making legacy xf86-input-wacom working with the wheels */ @@ -2618,10 +2631,6 @@ int wacom_setup_pad_input_capabilities(struct input_dev *input_dev, case INTUOS5S: case INTUOSPS: - /* touch interface does not have the pad device */ - if (!(features->device_type & WACOM_DEVICETYPE_PEN)) - return -ENODEV; - for (i = 0; i < 7; i++) __set_bit(BTN_0 + i, input_dev->keybit); @@ -2663,12 +2672,6 @@ 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 & WACOM_DEVICETYPE_TOUCH) || - /* Bamboo Pen only tablet does not have pad */ - ((features->type == BAMBOO_PT) && !features->touch_max)) - return -ENODEV; - __clear_bit(ABS_MISC, input_dev->absbit); __set_bit(BTN_LEFT, input_dev->keybit); diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h index da2b309..c873c9f 100644 --- a/drivers/hid/wacom_wac.h +++ b/drivers/hid/wacom_wac.h @@ -76,6 +76,7 @@ #define WACOM_DEVICETYPE_NONE 0x0000 #define WACOM_DEVICETYPE_PEN 0x0001 #define WACOM_DEVICETYPE_TOUCH 0x0002 +#define WACOM_DEVICETYPE_PAD 0x0004 #define WACOM_VENDORDEFINED_PEN 0xff0d0001 -- cgit v1.1 From 2636a3f2d1421e3e629dfc96489c23727bab17d7 Mon Sep 17 00:00:00 2001 From: Jason Gerecke Date: Mon, 15 Jun 2015 18:01:44 -0700 Subject: HID: wacom: Split apart 'wacom_setup_pentouch_input_capabilites' This splits the 'wacom_setup_pentouch_input_capabilites' function into pieces dedicated to doing setup for just the pen interface and just the touch interface. This makes it easier to focus on the relevant piece when making changes. This patch introduces no functional changes. Signed-off-by: Jason Gerecke Signed-off-by: Jiri Kosina --- drivers/hid/wacom.h | 4 +- drivers/hid/wacom_sys.c | 8 +- drivers/hid/wacom_wac.c | 234 +++++++++++++++++++++++++----------------------- 3 files changed, 131 insertions(+), 115 deletions(-) (limited to 'drivers/hid') diff --git a/drivers/hid/wacom.h b/drivers/hid/wacom.h index c76e21f..a533787 100644 --- a/drivers/hid/wacom.h +++ b/drivers/hid/wacom.h @@ -135,7 +135,9 @@ 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 *wacom); -int wacom_setup_pentouch_input_capabilities(struct input_dev *input_dev, +int wacom_setup_pen_input_capabilities(struct input_dev *input_dev, + struct wacom_wac *wacom_wac); +int wacom_setup_touch_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 aaa9c84..ca15c7f 100644 --- a/drivers/hid/wacom_sys.c +++ b/drivers/hid/wacom_sys.c @@ -1199,7 +1199,8 @@ static int wacom_register_inputs(struct wacom *wacom) { struct input_dev *input_dev, *pad_input_dev; struct wacom_wac *wacom_wac = &(wacom->wacom_wac); - int error; + struct wacom_features *features = &wacom_wac->features; + int error = 0; input_dev = wacom_wac->input; pad_input_dev = wacom_wac->pad_input; @@ -1207,7 +1208,10 @@ static int wacom_register_inputs(struct wacom *wacom) if (!input_dev || !pad_input_dev) return -EINVAL; - error = wacom_setup_pentouch_input_capabilities(input_dev, wacom_wac); + if (features->device_type & WACOM_DEVICETYPE_PEN) + error = wacom_setup_pen_input_capabilities(input_dev, wacom_wac); + if (!error && features->device_type & WACOM_DEVICETYPE_TOUCH) + error = wacom_setup_touch_input_capabilities(input_dev, wacom_wac); if (!error) { error = input_register_device(input_dev); if (error) diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index 564a06d..b80a67a 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -2237,54 +2237,16 @@ void wacom_setup_device_quirks(struct wacom *wacom) } } -static void wacom_abs_set_axis(struct input_dev *input_dev, - struct wacom_wac *wacom_wac) -{ - struct wacom_features *features = &wacom_wac->features; - - if (features->device_type & WACOM_DEVICETYPE_PEN) { - input_set_abs_params(input_dev, ABS_X, features->x_min, - features->x_max, features->x_fuzz, 0); - input_set_abs_params(input_dev, ABS_Y, features->y_min, - features->y_max, features->y_fuzz, 0); - input_set_abs_params(input_dev, ABS_PRESSURE, 0, - features->pressure_max, features->pressure_fuzz, 0); - - /* penabled devices have fixed resolution for each model */ - input_abs_set_res(input_dev, ABS_X, features->x_resolution); - input_abs_set_res(input_dev, ABS_Y, features->y_resolution); - } else if (features->device_type & WACOM_DEVICETYPE_TOUCH) { - if (features->touch_max == 1) { - input_set_abs_params(input_dev, ABS_X, 0, - features->x_max, features->x_fuzz, 0); - input_set_abs_params(input_dev, ABS_Y, 0, - features->y_max, features->y_fuzz, 0); - input_abs_set_res(input_dev, ABS_X, - features->x_resolution); - input_abs_set_res(input_dev, ABS_Y, - features->y_resolution); - } - - if (features->touch_max > 1) { - input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0, - features->x_max, features->x_fuzz, 0); - input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0, - features->y_max, features->y_fuzz, 0); - input_abs_set_res(input_dev, ABS_MT_POSITION_X, - features->x_resolution); - input_abs_set_res(input_dev, ABS_MT_POSITION_Y, - features->y_resolution); - } - } -} - -int wacom_setup_pentouch_input_capabilities(struct input_dev *input_dev, +int wacom_setup_pen_input_capabilities(struct input_dev *input_dev, struct wacom_wac *wacom_wac) { struct wacom_features *features = &wacom_wac->features; input_dev->evbit[0] |= BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); + if (!(features->device_type & WACOM_DEVICETYPE_PEN)) + return -ENODEV; + if (features->type == HID_GENERIC) /* setup has already been done */ return 0; @@ -2292,7 +2254,17 @@ int wacom_setup_pentouch_input_capabilities(struct input_dev *input_dev, __set_bit(BTN_TOUCH, input_dev->keybit); __set_bit(ABS_MISC, input_dev->absbit); - wacom_abs_set_axis(input_dev, wacom_wac); + input_set_abs_params(input_dev, ABS_X, features->x_min, + features->x_max, features->x_fuzz, 0); + input_set_abs_params(input_dev, ABS_Y, features->y_min, + features->y_max, features->y_fuzz, 0); + input_set_abs_params(input_dev, ABS_PRESSURE, 0, + features->pressure_max, features->pressure_fuzz, 0); + + /* penabled devices have fixed resolution for each model */ + input_abs_set_res(input_dev, ABS_X, features->x_resolution); + input_abs_set_res(input_dev, ABS_Y, features->y_resolution); + switch (features->type) { case GRAPHIRE_BT: @@ -2361,53 +2333,25 @@ int wacom_setup_pentouch_input_capabilities(struct input_dev *input_dev, case INTUOSPS: __set_bit(INPUT_PROP_POINTER, input_dev->propbit); - if (features->device_type & WACOM_DEVICETYPE_PEN) { - input_set_abs_params(input_dev, ABS_DISTANCE, 0, - features->distance_max, - 0, 0); - - 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_DISTANCE, 0, + features->distance_max, + 0, 0); - wacom_setup_intuos(wacom_wac); - } else if (features->device_type & WACOM_DEVICETYPE_TOUCH) { - __clear_bit(ABS_MISC, input_dev->absbit); + 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_MT_TOUCH_MAJOR, - 0, features->x_max, 0, 0); - input_set_abs_params(input_dev, ABS_MT_TOUCH_MINOR, - 0, features->y_max, 0, 0); - input_mt_init_slots(input_dev, features->touch_max, INPUT_MT_POINTER); - } + wacom_setup_intuos(wacom_wac); break; case WACOM_24HDT: - if (features->device_type & WACOM_DEVICETYPE_TOUCH) { - input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, features->x_max, 0, 0); - input_set_abs_params(input_dev, ABS_MT_WIDTH_MAJOR, 0, features->x_max, 0, 0); - input_set_abs_params(input_dev, ABS_MT_WIDTH_MINOR, 0, features->y_max, 0, 0); - input_set_abs_params(input_dev, ABS_MT_ORIENTATION, 0, 1, 0, 0); - } - /* fall through */ - case WACOM_27QHDT: case MTSCREEN: case MTTPC: case MTTPC_B: case TABLETPC2FG: - if (features->device_type & WACOM_DEVICETYPE_TOUCH && features->touch_max > 1) - input_mt_init_slots(input_dev, features->touch_max, INPUT_MT_DIRECT); - /* fall through */ - case TABLETPC: case TABLETPCE: __clear_bit(ABS_MISC, input_dev->absbit); - - __set_bit(INPUT_PROP_DIRECT, input_dev->propbit); - - if (!(features->device_type & WACOM_DEVICETYPE_PEN)) - break; /* no need to process stylus stuff */ - /* fall through */ case DTUS: @@ -2435,48 +2379,114 @@ int wacom_setup_pentouch_input_capabilities(struct input_dev *input_dev, break; case INTUOSHT: - if (features->device_type & WACOM_DEVICETYPE_TOUCH) { - input_dev->evbit[0] |= BIT_MASK(EV_SW); - __set_bit(SW_MUTE_DEVICE, input_dev->swbit); - } - /* fall through */ - case BAMBOO_PT: __clear_bit(ABS_MISC, input_dev->absbit); - if (features->device_type & WACOM_DEVICETYPE_TOUCH) { - if (features->pktlen == WACOM_PKGLEN_BBTOUCH3) { - input_set_abs_params(input_dev, - ABS_MT_TOUCH_MAJOR, - 0, features->x_max, 0, 0); - input_set_abs_params(input_dev, - ABS_MT_TOUCH_MINOR, - 0, features->y_max, 0, 0); - } - input_mt_init_slots(input_dev, features->touch_max, INPUT_MT_POINTER); - } - if (features->device_type & WACOM_DEVICETYPE_PAD) { - /* buttons/keys only interface */ - __clear_bit(ABS_X, input_dev->absbit); - __clear_bit(ABS_Y, input_dev->absbit); - __clear_bit(BTN_TOUCH, input_dev->keybit); + __set_bit(INPUT_PROP_POINTER, input_dev->propbit); + __set_bit(BTN_TOOL_RUBBER, input_dev->keybit); + __set_bit(BTN_TOOL_PEN, input_dev->keybit); + __set_bit(BTN_STYLUS, input_dev->keybit); + __set_bit(BTN_STYLUS2, input_dev->keybit); + input_set_abs_params(input_dev, ABS_DISTANCE, 0, + features->distance_max, + 0, 0); + break; + case BAMBOO_PAD: + __clear_bit(ABS_MISC, input_dev->absbit); + break; + } + return 0; +} - /* PAD is setup by wacom_setup_pad_input_capabilities later */ - return 1; - } - if (features->device_type & WACOM_DEVICETYPE_PEN) { - __set_bit(INPUT_PROP_POINTER, input_dev->propbit); - __set_bit(BTN_TOOL_RUBBER, input_dev->keybit); - __set_bit(BTN_TOOL_PEN, input_dev->keybit); - __set_bit(BTN_STYLUS, input_dev->keybit); - __set_bit(BTN_STYLUS2, input_dev->keybit); - input_set_abs_params(input_dev, ABS_DISTANCE, 0, - features->distance_max, - 0, 0); +int wacom_setup_touch_input_capabilities(struct input_dev *input_dev, + struct wacom_wac *wacom_wac) +{ + struct wacom_features *features = &wacom_wac->features; + + input_dev->evbit[0] |= BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); + + if (!(features->device_type & WACOM_DEVICETYPE_TOUCH)) + return -ENODEV; + + if (features->type == HID_GENERIC) + /* setup has already been done */ + return 0; + + __set_bit(BTN_TOUCH, input_dev->keybit); + + if (features->touch_max == 1) { + input_set_abs_params(input_dev, ABS_X, 0, + features->x_max, features->x_fuzz, 0); + input_set_abs_params(input_dev, ABS_Y, 0, + features->y_max, features->y_fuzz, 0); + input_abs_set_res(input_dev, ABS_X, + features->x_resolution); + input_abs_set_res(input_dev, ABS_Y, + features->y_resolution); + } + else if (features->touch_max > 1) { + input_set_abs_params(input_dev, ABS_MT_POSITION_X, 0, + features->x_max, features->x_fuzz, 0); + input_set_abs_params(input_dev, ABS_MT_POSITION_Y, 0, + features->y_max, features->y_fuzz, 0); + input_abs_set_res(input_dev, ABS_MT_POSITION_X, + features->x_resolution); + input_abs_set_res(input_dev, ABS_MT_POSITION_Y, + features->y_resolution); + } + + switch (features->type) { + case INTUOS5: + case INTUOS5L: + case INTUOSPM: + case INTUOSPL: + case INTUOS5S: + case INTUOSPS: + __set_bit(INPUT_PROP_POINTER, input_dev->propbit); + + input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, features->x_max, 0, 0); + input_set_abs_params(input_dev, ABS_MT_TOUCH_MINOR, 0, features->y_max, 0, 0); + input_mt_init_slots(input_dev, features->touch_max, INPUT_MT_POINTER); + break; + + case WACOM_24HDT: + input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR, 0, features->x_max, 0, 0); + input_set_abs_params(input_dev, ABS_MT_WIDTH_MAJOR, 0, features->x_max, 0, 0); + input_set_abs_params(input_dev, ABS_MT_WIDTH_MINOR, 0, features->y_max, 0, 0); + input_set_abs_params(input_dev, ABS_MT_ORIENTATION, 0, 1, 0, 0); + /* fall through */ + + case WACOM_27QHDT: + case MTSCREEN: + case MTTPC: + case MTTPC_B: + case TABLETPC2FG: + input_mt_init_slots(input_dev, features->touch_max, INPUT_MT_DIRECT); + /*fall through */ + + case TABLETPC: + case TABLETPCE: + __set_bit(INPUT_PROP_DIRECT, input_dev->propbit); + break; + + case INTUOSHT: + input_dev->evbit[0] |= BIT_MASK(EV_SW); + __set_bit(SW_MUTE_DEVICE, input_dev->swbit); + /* fall through */ + + case BAMBOO_PT: + if (features->pktlen == WACOM_PKGLEN_BBTOUCH3) { + input_set_abs_params(input_dev, + ABS_MT_TOUCH_MAJOR, + 0, features->x_max, 0, 0); + input_set_abs_params(input_dev, + ABS_MT_TOUCH_MINOR, + 0, features->y_max, 0, 0); } + input_mt_init_slots(input_dev, features->touch_max, INPUT_MT_POINTER); break; + case BAMBOO_PAD: - __clear_bit(ABS_MISC, input_dev->absbit); input_mt_init_slots(input_dev, features->touch_max, INPUT_MT_POINTER); __set_bit(BTN_LEFT, input_dev->keybit); -- cgit v1.1 From 2a6cdbdd4cc0da0b0190b9a43648dff7b44adc0a Mon Sep 17 00:00:00 2001 From: Jason Gerecke Date: Mon, 15 Jun 2015 18:01:45 -0700 Subject: HID: wacom: Introduce new 'touch_input' device Instead of having a single 'input_dev' device that will take either pen or touch data depending on the type of the device, create seperate devices devices for each. By splitting things like this, we can support devices (e.g. the I2C "AES" sensors in some newer tablet PCs) that send both pen and touch reports from a single endpoint. Signed-off-by: Jason Gerecke Signed-off-by: Jiri Kosina --- drivers/hid/wacom_sys.c | 116 +++++++++++++++++++++++++++++------------------- drivers/hid/wacom_wac.c | 115 +++++++++++++++++++++++++---------------------- drivers/hid/wacom_wac.h | 9 ++-- 3 files changed, 139 insertions(+), 101 deletions(-) (limited to 'drivers/hid') diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c index ca15c7f..4c0ffca 100644 --- a/drivers/hid/wacom_sys.c +++ b/drivers/hid/wacom_sys.c @@ -253,7 +253,7 @@ static void wacom_post_parse_hid(struct hid_device *hdev, 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_init_slots(wacom_wac->touch_input, wacom_wac->features.touch_max, INPUT_MT_DIRECT); } } @@ -1130,7 +1130,7 @@ static struct input_dev *wacom_allocate_input(struct wacom *wacom) if (!input_dev) return NULL; - input_dev->name = wacom_wac->name; + input_dev->name = wacom_wac->pen_name; input_dev->phys = hdev->phys; input_dev->dev.parent = &hdev->dev; input_dev->open = wacom_open; @@ -1149,27 +1149,33 @@ static void wacom_free_inputs(struct wacom *wacom) { struct wacom_wac *wacom_wac = &(wacom->wacom_wac); - if (wacom_wac->input) - input_free_device(wacom_wac->input); + if (wacom_wac->pen_input) + input_free_device(wacom_wac->pen_input); + if (wacom_wac->touch_input) + input_free_device(wacom_wac->touch_input); if (wacom_wac->pad_input) input_free_device(wacom_wac->pad_input); - wacom_wac->input = NULL; + wacom_wac->pen_input = NULL; + wacom_wac->touch_input = NULL; wacom_wac->pad_input = NULL; } static int wacom_allocate_inputs(struct wacom *wacom) { - struct input_dev *input_dev, *pad_input_dev; + struct input_dev *pen_input_dev, *touch_input_dev, *pad_input_dev; struct wacom_wac *wacom_wac = &(wacom->wacom_wac); - input_dev = wacom_allocate_input(wacom); + pen_input_dev = wacom_allocate_input(wacom); + touch_input_dev = wacom_allocate_input(wacom); pad_input_dev = wacom_allocate_input(wacom); - if (!input_dev || !pad_input_dev) { + if (!pen_input_dev || !touch_input_dev || !pad_input_dev) { wacom_free_inputs(wacom); return -ENOMEM; } - wacom_wac->input = input_dev; + wacom_wac->pen_input = pen_input_dev; + wacom_wac->touch_input = touch_input_dev; + wacom_wac->touch_input->name = wacom_wac->touch_name; wacom_wac->pad_input = pad_input_dev; wacom_wac->pad_input->name = wacom_wac->pad_name; @@ -1178,11 +1184,17 @@ static int wacom_allocate_inputs(struct wacom *wacom) static void wacom_clean_inputs(struct wacom *wacom) { - if (wacom->wacom_wac.input) { - if (wacom->wacom_wac.input_registered) - input_unregister_device(wacom->wacom_wac.input); + if (wacom->wacom_wac.pen_input) { + if (wacom->wacom_wac.pen_registered) + input_unregister_device(wacom->wacom_wac.pen_input); else - input_free_device(wacom->wacom_wac.input); + input_free_device(wacom->wacom_wac.pen_input); + } + if (wacom->wacom_wac.touch_input) { + if (wacom->wacom_wac.touch_registered) + input_unregister_device(wacom->wacom_wac.touch_input); + else + input_free_device(wacom->wacom_wac.touch_input); } if (wacom->wacom_wac.pad_input) { if (wacom->wacom_wac.pad_registered) @@ -1190,33 +1202,49 @@ static void wacom_clean_inputs(struct wacom *wacom) else input_free_device(wacom->wacom_wac.pad_input); } - wacom->wacom_wac.input = NULL; + wacom->wacom_wac.pen_input = NULL; + wacom->wacom_wac.touch_input = NULL; wacom->wacom_wac.pad_input = NULL; wacom_destroy_leds(wacom); } static int wacom_register_inputs(struct wacom *wacom) { - struct input_dev *input_dev, *pad_input_dev; + struct input_dev *pen_input_dev, *touch_input_dev, *pad_input_dev; struct wacom_wac *wacom_wac = &(wacom->wacom_wac); - struct wacom_features *features = &wacom_wac->features; int error = 0; - input_dev = wacom_wac->input; + pen_input_dev = wacom_wac->pen_input; + touch_input_dev = wacom_wac->touch_input; pad_input_dev = wacom_wac->pad_input; - if (!input_dev || !pad_input_dev) + if (!pen_input_dev || !touch_input_dev || !pad_input_dev) return -EINVAL; - if (features->device_type & WACOM_DEVICETYPE_PEN) - error = wacom_setup_pen_input_capabilities(input_dev, wacom_wac); - if (!error && features->device_type & WACOM_DEVICETYPE_TOUCH) - error = wacom_setup_touch_input_capabilities(input_dev, wacom_wac); - if (!error) { - error = input_register_device(input_dev); + error = wacom_setup_pen_input_capabilities(pen_input_dev, wacom_wac); + if (error) { + /* no pen in use on this interface */ + input_free_device(pen_input_dev); + wacom_wac->pen_input = NULL; + pen_input_dev = NULL; + } else { + error = input_register_device(pen_input_dev); + if (error) + goto fail_register_pen_input; + wacom_wac->pen_registered = true; + } + + error = wacom_setup_touch_input_capabilities(touch_input_dev, wacom_wac); + if (error) { + /* no touch in use on this interface */ + input_free_device(touch_input_dev); + wacom_wac->touch_input = NULL; + touch_input_dev = NULL; + } else { + error = input_register_device(touch_input_dev); if (error) - return error; - wacom_wac->input_registered = true; + goto fail_register_touch_input; + wacom_wac->touch_registered = true; } error = wacom_setup_pad_input_capabilities(pad_input_dev, wacom_wac); @@ -1243,9 +1271,14 @@ fail_leds: 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; + input_unregister_device(touch_input_dev); + wacom_wac->touch_input = NULL; + wacom_wac->touch_registered = false; +fail_register_touch_input: + input_unregister_device(pen_input_dev); + wacom_wac->pen_input = NULL; + wacom_wac->pen_registered = false; +fail_register_pen_input: return error; } @@ -1306,7 +1339,7 @@ static void wacom_wireless_work(struct work_struct *work) if (wacom_wac1->features.type != INTUOSHT && wacom_wac1->features.type != BAMBOO_PT) wacom_wac1->features.device_type |= WACOM_DEVICETYPE_PAD; - snprintf(wacom_wac1->name, WACOM_NAME_MAX, "%s (WL) Pen", + snprintf(wacom_wac1->pen_name, WACOM_NAME_MAX, "%s (WL) Pen", wacom_wac1->features.name); snprintf(wacom_wac1->pad_name, WACOM_NAME_MAX, "%s (WL) Pad", wacom_wac1->features.name); @@ -1325,7 +1358,7 @@ static void wacom_wireless_work(struct work_struct *work) *((struct wacom_features *)id->driver_data); wacom_wac2->features.pktlen = WACOM_PKGLEN_BBTOUCH3; wacom_wac2->features.x_max = wacom_wac2->features.y_max = 4096; - snprintf(wacom_wac2->name, WACOM_NAME_MAX, + snprintf(wacom_wac2->touch_name, WACOM_NAME_MAX, "%s (WL) Finger",wacom_wac2->features.name); snprintf(wacom_wac2->pad_name, WACOM_NAME_MAX, "%s (WL) Pad",wacom_wac2->features.name); @@ -1342,7 +1375,7 @@ static void wacom_wireless_work(struct work_struct *work) if (wacom_wac1->features.type == INTUOSHT && wacom_wac1->features.touch_max) - wacom_wac->shared->touch_input = wacom_wac2->input; + wacom_wac->shared->touch_input = wacom_wac2->touch_input; } error = wacom_initialize_battery(wacom); @@ -1457,21 +1490,12 @@ static void wacom_update_name(struct wacom *wacom) } /* Append the device type to the name */ + snprintf(wacom_wac->pen_name, sizeof(wacom_wac->pen_name), + "%s Pen", name); + snprintf(wacom_wac->touch_name, sizeof(wacom_wac->touch_name), + "%s Finger", name); snprintf(wacom_wac->pad_name, sizeof(wacom_wac->pad_name), "%s Pad", name); - - if (features->device_type & WACOM_DEVICETYPE_PEN) { - snprintf(wacom_wac->name, sizeof(wacom_wac->name), - "%s Pen", name); - } - else if (features->device_type & WACOM_DEVICETYPE_TOUCH) { - snprintf(wacom_wac->name, sizeof(wacom_wac->name), - "%s Finger", name); - } - else if (features->device_type & WACOM_DEVICETYPE_PAD) { - snprintf(wacom_wac->name, sizeof(wacom_wac->name), - "%s Pad", name); - } } static int wacom_probe(struct hid_device *hdev, @@ -1615,7 +1639,7 @@ static int wacom_probe(struct hid_device *hdev, if (wacom_wac->features.type == INTUOSHT && wacom_wac->features.device_type & WACOM_DEVICETYPE_TOUCH) { - wacom_wac->shared->touch_input = wacom_wac->input; + wacom_wac->shared->touch_input = wacom_wac->touch_input; } return 0; diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index b80a67a..d811e87 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -69,7 +69,7 @@ static void wacom_notify_battery(struct wacom_wac *wacom_wac, static int wacom_penpartner_irq(struct wacom_wac *wacom) { unsigned char *data = wacom->data; - struct input_dev *input = wacom->input; + struct input_dev *input = wacom->pen_input; switch (data[0]) { case 1: @@ -114,7 +114,7 @@ static int wacom_pl_irq(struct wacom_wac *wacom) { struct wacom_features *features = &wacom->features; unsigned char *data = wacom->data; - struct input_dev *input = wacom->input; + struct input_dev *input = wacom->pen_input; int prox, pressure; if (data[0] != WACOM_REPORT_PENABLED) { @@ -186,7 +186,7 @@ static int wacom_pl_irq(struct wacom_wac *wacom) static int wacom_ptu_irq(struct wacom_wac *wacom) { unsigned char *data = wacom->data; - struct input_dev *input = wacom->input; + struct input_dev *input = wacom->pen_input; if (data[0] != WACOM_REPORT_PENABLED) { dev_dbg(input->dev.parent, @@ -215,7 +215,7 @@ static int wacom_ptu_irq(struct wacom_wac *wacom) static int wacom_dtu_irq(struct wacom_wac *wacom) { unsigned char *data = wacom->data; - struct input_dev *input = wacom->input; + struct input_dev *input = wacom->pen_input; int prox = data[1] & 0x20; dev_dbg(input->dev.parent, @@ -245,7 +245,7 @@ static int wacom_dtu_irq(struct wacom_wac *wacom) static int wacom_dtus_irq(struct wacom_wac *wacom) { char *data = wacom->data; - struct input_dev *input = wacom->input; + struct input_dev *input = wacom->pen_input; unsigned short prox, pressure = 0; if (data[0] != WACOM_REPORT_DTUS && data[0] != WACOM_REPORT_DTUSPAD) { @@ -297,7 +297,7 @@ static int wacom_graphire_irq(struct wacom_wac *wacom) { struct wacom_features *features = &wacom->features; unsigned char *data = wacom->data; - struct input_dev *input = wacom->input; + struct input_dev *input = wacom->pen_input; struct input_dev *pad_input = wacom->pad_input; int battery_capacity, ps_connected; int prox; @@ -464,7 +464,7 @@ static int wacom_intuos_inout(struct wacom_wac *wacom) { struct wacom_features *features = &wacom->features; unsigned char *data = wacom->data; - struct input_dev *input = wacom->input; + struct input_dev *input = wacom->pen_input; int idx = 0; /* tool number */ @@ -649,7 +649,7 @@ static void wacom_intuos_general(struct wacom_wac *wacom) { struct wacom_features *features = &wacom->features; unsigned char *data = wacom->data; - struct input_dev *input = wacom->input; + struct input_dev *input = wacom->pen_input; unsigned int t; /* general pen packet */ @@ -681,7 +681,7 @@ static int wacom_intuos_irq(struct wacom_wac *wacom) { struct wacom_features *features = &wacom->features; unsigned char *data = wacom->data; - struct input_dev *input = wacom->input; + struct input_dev *input = wacom->pen_input; unsigned int t; int idx = 0, result; @@ -1025,7 +1025,7 @@ static void wacom_intuos_bt_process_data(struct wacom_wac *wacom, memcpy(wacom->data, data, 10); wacom_intuos_irq(wacom); - input_sync(wacom->input); + input_sync(wacom->pen_input); if (wacom->pad_input) input_sync(wacom->pad_input); } @@ -1057,7 +1057,7 @@ static int wacom_intuos_bt_irq(struct wacom_wac *wacom, size_t len) ps_connected); break; default: - dev_dbg(wacom->input->dev.parent, + dev_dbg(wacom->pen_input->dev.parent, "Unknown report: %d,%d size:%zu\n", data[0], data[1], len); return 0; @@ -1067,7 +1067,7 @@ static int wacom_intuos_bt_irq(struct wacom_wac *wacom, size_t len) static int wacom_wac_finger_count_touches(struct wacom_wac *wacom) { - struct input_dev *input = wacom->input; + struct input_dev *input = wacom->touch_input; unsigned touch_max = wacom->features.touch_max; int count = 0; int i; @@ -1088,7 +1088,7 @@ static int wacom_wac_finger_count_touches(struct wacom_wac *wacom) static int wacom_24hdt_irq(struct wacom_wac *wacom) { - struct input_dev *input = wacom->input; + struct input_dev *input = wacom->touch_input; unsigned char *data = wacom->data; int i; int current_num_contacts = data[61]; @@ -1156,7 +1156,7 @@ static int wacom_24hdt_irq(struct wacom_wac *wacom) static int wacom_mt_touch(struct wacom_wac *wacom) { - struct input_dev *input = wacom->input; + struct input_dev *input = wacom->touch_input; unsigned char *data = wacom->data; int i; int current_num_contacts = data[2]; @@ -1207,7 +1207,7 @@ static int wacom_mt_touch(struct wacom_wac *wacom) static int wacom_tpc_mt_touch(struct wacom_wac *wacom) { - struct input_dev *input = wacom->input; + struct input_dev *input = wacom->touch_input; unsigned char *data = wacom->data; int i; @@ -1236,7 +1236,7 @@ static int wacom_tpc_mt_touch(struct wacom_wac *wacom) static int wacom_tpc_single_touch(struct wacom_wac *wacom, size_t len) { unsigned char *data = wacom->data; - struct input_dev *input = wacom->input; + struct input_dev *input = wacom->touch_input; bool prox = !wacom->shared->stylus_in_proximity; int x = 0, y = 0; @@ -1272,7 +1272,7 @@ static int wacom_tpc_single_touch(struct wacom_wac *wacom, size_t len) static int wacom_tpc_pen(struct wacom_wac *wacom) { unsigned char *data = wacom->data; - struct input_dev *input = wacom->input; + struct input_dev *input = wacom->pen_input; bool prox = data[1] & 0x20; if (!wacom->shared->stylus_in_proximity) /* first in prox */ @@ -1301,8 +1301,12 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, size_t len) { unsigned char *data = wacom->data; - dev_dbg(wacom->input->dev.parent, - "%s: received report #%d\n", __func__, data[0]); + if (wacom->pen_input) + dev_dbg(wacom->pen_input->dev.parent, + "%s: received report #%d\n", __func__, data[0]); + else if (wacom->touch_input) + dev_dbg(wacom->touch_input->dev.parent, + "%s: received report #%d\n", __func__, data[0]); switch (len) { case WACOM_PKGLEN_TPC1FG: @@ -1334,11 +1338,9 @@ static int wacom_tpc_irq(struct wacom_wac *wacom, size_t len) return 0; } -static void wacom_map_usage(struct wacom *wacom, struct hid_usage *usage, +static void wacom_map_usage(struct input_dev *input, struct hid_usage *usage, struct hid_field *field, __u8 type, __u16 code, int fuzz) { - struct wacom_wac *wacom_wac = &wacom->wacom_wac; - struct input_dev *input = wacom_wac->input; int fmin = field->logical_minimum; int fmax = field->logical_maximum; @@ -1366,36 +1368,38 @@ static void wacom_wac_pen_usage_mapping(struct hid_device *hdev, struct hid_field *field, struct hid_usage *usage) { struct wacom *wacom = hid_get_drvdata(hdev); + struct wacom_wac *wacom_wac = &wacom->wacom_wac; + struct input_dev *input = wacom_wac->pen_input; switch (usage->hid) { case HID_GD_X: - wacom_map_usage(wacom, usage, field, EV_ABS, ABS_X, 4); + wacom_map_usage(input, usage, field, EV_ABS, ABS_X, 4); break; case HID_GD_Y: - wacom_map_usage(wacom, usage, field, EV_ABS, ABS_Y, 4); + wacom_map_usage(input, usage, field, EV_ABS, ABS_Y, 4); break; case HID_DG_TIPPRESSURE: - wacom_map_usage(wacom, usage, field, EV_ABS, ABS_PRESSURE, 0); + wacom_map_usage(input, usage, field, EV_ABS, ABS_PRESSURE, 0); break; case HID_DG_INRANGE: - wacom_map_usage(wacom, usage, field, EV_KEY, BTN_TOOL_PEN, 0); + wacom_map_usage(input, usage, field, EV_KEY, BTN_TOOL_PEN, 0); break; case HID_DG_INVERT: - wacom_map_usage(wacom, usage, field, EV_KEY, + wacom_map_usage(input, usage, field, EV_KEY, BTN_TOOL_RUBBER, 0); break; case HID_DG_ERASER: case HID_DG_TIPSWITCH: - wacom_map_usage(wacom, usage, field, EV_KEY, BTN_TOUCH, 0); + wacom_map_usage(input, usage, field, EV_KEY, BTN_TOUCH, 0); break; case HID_DG_BARRELSWITCH: - wacom_map_usage(wacom, usage, field, EV_KEY, BTN_STYLUS, 0); + wacom_map_usage(input, usage, field, EV_KEY, BTN_STYLUS, 0); break; case HID_DG_BARRELSWITCH2: - wacom_map_usage(wacom, usage, field, EV_KEY, BTN_STYLUS2, 0); + wacom_map_usage(input, usage, field, EV_KEY, BTN_STYLUS2, 0); break; case HID_DG_TOOLSERIALNUMBER: - wacom_map_usage(wacom, usage, field, EV_MSC, MSC_SERIAL, 0); + wacom_map_usage(input, usage, field, EV_MSC, MSC_SERIAL, 0); break; } } @@ -1405,7 +1409,7 @@ static int wacom_wac_pen_event(struct hid_device *hdev, struct hid_field *field, { struct wacom *wacom = hid_get_drvdata(hdev); struct wacom_wac *wacom_wac = &wacom->wacom_wac; - struct input_dev *input = wacom_wac->input; + struct input_dev *input = wacom_wac->pen_input; /* checking which Tool / tip switch to send */ switch (usage->hid) { @@ -1435,7 +1439,7 @@ static void wacom_wac_pen_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; + struct input_dev *input = wacom_wac->pen_input; bool prox = wacom_wac->hid_data.inrange_state; if (!wacom_wac->shared->stylus_in_proximity) /* first in prox */ @@ -1464,23 +1468,24 @@ 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 wacom_features *features = &wacom_wac->features; + struct input_dev *input = wacom_wac->touch_input; 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); + wacom_map_usage(input, usage, field, EV_ABS, ABS_X, 4); else - wacom_map_usage(wacom, usage, field, EV_ABS, + wacom_map_usage(input, usage, field, EV_ABS, 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); + wacom_map_usage(input, usage, field, EV_ABS, ABS_Y, 4); else - wacom_map_usage(wacom, usage, field, EV_ABS, + wacom_map_usage(input, usage, field, EV_ABS, ABS_MT_POSITION_Y, 4); break; case HID_DG_CONTACTID: @@ -1494,7 +1499,7 @@ static void wacom_wac_finger_usage_mapping(struct hid_device *hdev, break; case HID_DG_TIPSWITCH: features->last_slot_field = usage->hid; - wacom_map_usage(wacom, usage, field, EV_KEY, BTN_TOUCH, 0); + wacom_map_usage(input, usage, field, EV_KEY, BTN_TOUCH, 0); break; } } @@ -1550,7 +1555,7 @@ 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); + wacom_wac_finger_slot(wacom_wac, wacom_wac->touch_input); } return 0; @@ -1561,7 +1566,7 @@ 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; + struct input_dev *input = wacom_wac->touch_input; unsigned touch_max = wacom_wac->features.touch_max; if (touch_max > 1) @@ -1578,10 +1583,10 @@ void wacom_wac_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; /* currently, only direct devices have proper hid report descriptors */ - __set_bit(INPUT_PROP_DIRECT, input->propbit); + __set_bit(INPUT_PROP_DIRECT, wacom_wac->pen_input->propbit); + __set_bit(INPUT_PROP_DIRECT, wacom_wac->touch_input->propbit); if (WACOM_PEN_FIELD(field)) return wacom_wac_pen_usage_mapping(hdev, field, usage); @@ -1626,7 +1631,7 @@ void wacom_wac_report(struct hid_device *hdev, struct hid_report *report) static int wacom_bpt_touch(struct wacom_wac *wacom) { struct wacom_features *features = &wacom->features; - struct input_dev *input = wacom->input; + struct input_dev *input = wacom->touch_input; struct input_dev *pad_input = wacom->pad_input; unsigned char *data = wacom->data; int i; @@ -1674,7 +1679,7 @@ static int wacom_bpt_touch(struct wacom_wac *wacom) static void wacom_bpt3_touch_msg(struct wacom_wac *wacom, unsigned char *data) { struct wacom_features *features = &wacom->features; - struct input_dev *input = wacom->input; + struct input_dev *input = wacom->touch_input; bool touch = data[1] & 0x80; int slot = input_mt_get_slot_by_key(input, data[0]); @@ -1732,7 +1737,6 @@ static void wacom_bpt3_button_msg(struct wacom_wac *wacom, unsigned char *data) static int wacom_bpt3_touch(struct wacom_wac *wacom) { - struct input_dev *input = wacom->input; unsigned char *data = wacom->data; int count = data[1] & 0x07; int i; @@ -1751,8 +1755,12 @@ static int wacom_bpt3_touch(struct wacom_wac *wacom) wacom_bpt3_button_msg(wacom, data + offset); } - input_mt_sync_frame(input); - wacom->shared->touch_down = wacom_wac_finger_count_touches(wacom); + + /* only update the touch if we actually have a touchpad */ + if (wacom->touch_registered) { + input_mt_sync_frame(wacom->touch_input); + wacom->shared->touch_down = wacom_wac_finger_count_touches(wacom); + } return 1; } @@ -1760,7 +1768,7 @@ static int wacom_bpt3_touch(struct wacom_wac *wacom) static int wacom_bpt_pen(struct wacom_wac *wacom) { struct wacom_features *features = &wacom->features; - struct input_dev *input = wacom->input; + struct input_dev *input = wacom->pen_input; unsigned char *data = wacom->data; int prox = 0, x = 0, y = 0, p = 0, d = 0, pen = 0, btn1 = 0, btn2 = 0; @@ -1869,7 +1877,7 @@ static void wacom_bamboo_pad_pen_event(struct wacom_wac *wacom, static int wacom_bamboo_pad_touch_event(struct wacom_wac *wacom, unsigned char *data) { - struct input_dev *input = wacom->input; + struct input_dev *input = wacom->touch_input; unsigned char *finger_data, prefix; unsigned id; int x, y; @@ -2113,7 +2121,10 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len) } if (sync) { - input_sync(wacom_wac->input); + if (wacom_wac->pen_input) + input_sync(wacom_wac->pen_input); + if (wacom_wac->touch_input) + input_sync(wacom_wac->touch_input); if (wacom_wac->pad_input) input_sync(wacom_wac->pad_input); } @@ -2121,7 +2132,7 @@ void wacom_wac_irq(struct wacom_wac *wacom_wac, size_t len) static void wacom_setup_cintiq(struct wacom_wac *wacom_wac) { - struct input_dev *input_dev = wacom_wac->input; + struct input_dev *input_dev = wacom_wac->pen_input; input_set_capability(input_dev, EV_MSC, MSC_SERIAL); @@ -2144,7 +2155,7 @@ static void wacom_setup_cintiq(struct wacom_wac *wacom_wac) static void wacom_setup_intuos(struct wacom_wac *wacom_wac) { - struct input_dev *input_dev = wacom_wac->input; + struct input_dev *input_dev = wacom_wac->pen_input; input_set_capability(input_dev, EV_REL, REL_WHEEL); diff --git a/drivers/hid/wacom_wac.h b/drivers/hid/wacom_wac.h index c873c9f..2978c30 100644 --- a/drivers/hid/wacom_wac.h +++ b/drivers/hid/wacom_wac.h @@ -196,7 +196,8 @@ struct hid_data { }; struct wacom_wac { - char name[WACOM_NAME_MAX]; + char pen_name[WACOM_NAME_MAX]; + char touch_name[WACOM_NAME_MAX]; char pad_name[WACOM_NAME_MAX]; char bat_name[WACOM_NAME_MAX]; char ac_name[WACOM_NAME_MAX]; @@ -207,9 +208,11 @@ struct wacom_wac { bool reporting_data; struct wacom_features features; struct wacom_shared *shared; - struct input_dev *input; + struct input_dev *pen_input; + struct input_dev *touch_input; struct input_dev *pad_input; - bool input_registered; + bool pen_registered; + bool touch_registered; bool pad_registered; int pid; int battery_capacity; -- cgit v1.1 From 6eabaaa09128169f42d97d6a3502729f8ad27c4a Mon Sep 17 00:00:00 2001 From: Simon Wood Date: Wed, 17 Jun 2015 00:08:51 -0600 Subject: HID: hid-sony: Add BT support for Navigation Controller Signed-off-by: Simon Wood Signed-off-by: Jiri Kosina --- drivers/hid/hid-core.c | 1 + drivers/hid/hid-sony.c | 2 ++ 2 files changed, 3 insertions(+) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 044e96a..a64f862 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1962,6 +1962,7 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_MOTION_CONTROLLER) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_MOTION_CONTROLLER) }, { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_BDREMOTE) }, { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) }, diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index 2ce0295..3fba2dca 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c @@ -2287,6 +2287,8 @@ static const struct hid_device_id sony_devices[] = { .driver_data = SIXAXIS_CONTROLLER_USB }, { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER), .driver_data = SIXAXIS_CONTROLLER_USB }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER), + .driver_data = SIXAXIS_CONTROLLER_BT }, { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_MOTION_CONTROLLER), .driver_data = MOTION_CONTROLLER_USB }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_MOTION_CONTROLLER), -- cgit v1.1 From 4545ee0a70e49b7d355181540a77c0a1aa2a7fe4 Mon Sep 17 00:00:00 2001 From: Simon Wood Date: Wed, 17 Jun 2015 00:08:52 -0600 Subject: HID: hid-sony: Navigation controller only has 1 LED and no rumble Signed-off-by: Simon Wood Signed-off-by: Jiri Kosina --- drivers/hid/hid-sony.c | 41 +++++++++++++++++++++++++++++++++-------- 1 file changed, 33 insertions(+), 8 deletions(-) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index 3fba2dca..af02139 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c @@ -48,15 +48,20 @@ #define DUALSHOCK4_CONTROLLER_BT BIT(6) #define MOTION_CONTROLLER_USB BIT(7) #define MOTION_CONTROLLER_BT BIT(8) +#define NAVIGATION_CONTROLLER_USB BIT(9) +#define NAVIGATION_CONTROLLER_BT BIT(10) #define SIXAXIS_CONTROLLER (SIXAXIS_CONTROLLER_USB | SIXAXIS_CONTROLLER_BT) #define MOTION_CONTROLLER (MOTION_CONTROLLER_USB | MOTION_CONTROLLER_BT) +#define NAVIGATION_CONTROLLER (NAVIGATION_CONTROLLER_USB |\ + NAVIGATION_CONTROLLER_BT) #define DUALSHOCK4_CONTROLLER (DUALSHOCK4_CONTROLLER_USB |\ DUALSHOCK4_CONTROLLER_BT) #define SONY_LED_SUPPORT (SIXAXIS_CONTROLLER | BUZZ_CONTROLLER |\ - DUALSHOCK4_CONTROLLER | MOTION_CONTROLLER) + DUALSHOCK4_CONTROLLER | MOTION_CONTROLLER |\ + NAVIGATION_CONTROLLER) #define SONY_BATTERY_SUPPORT (SIXAXIS_CONTROLLER | DUALSHOCK4_CONTROLLER |\ - MOTION_CONTROLLER_BT) + MOTION_CONTROLLER_BT | NAVIGATION_CONTROLLER) #define SONY_FF_SUPPORT (SIXAXIS_CONTROLLER | DUALSHOCK4_CONTROLLER |\ MOTION_CONTROLLER) @@ -1052,6 +1057,9 @@ static __u8 *sony_report_fixup(struct hid_device *hdev, __u8 *rdesc, if (sc->quirks & MOTION_CONTROLLER) return motion_fixup(hdev, rdesc, rsize); + if (sc->quirks & NAVIGATION_CONTROLLER) + return sixaxis_fixup(hdev, rdesc, rsize); + if (sc->quirks & PS3REMOTE) return ps3remote_fixup(hdev, rdesc, rsize); @@ -1181,6 +1189,9 @@ static int sony_raw_event(struct hid_device *hdev, struct hid_report *report, sixaxis_parse_report(sc, rd, size); } else if ((sc->quirks & MOTION_CONTROLLER_BT) && rd[0] == 0x01 && size == 49) { sixaxis_parse_report(sc, rd, size); + } else if ((sc->quirks & NAVIGATION_CONTROLLER) && rd[0] == 0x01 && + size == 49) { + sixaxis_parse_report(sc, rd, size); } else if (((sc->quirks & DUALSHOCK4_CONTROLLER_USB) && rd[0] == 0x01 && size == 64) || ((sc->quirks & DUALSHOCK4_CONTROLLER_BT) && rd[0] == 0x11 && size == 78)) { @@ -1591,6 +1602,15 @@ static int sony_leds_init(struct sony_sc *sc) use_ds4_names = 1; name_len = 0; name_fmt = "%s:%s"; + } else if (sc->quirks & NAVIGATION_CONTROLLER) { + static const __u8 navigation_leds[4] = {0x01, 0x00, 0x00, 0x00}; + + memcpy(sc->led_state, navigation_leds, sizeof(navigation_leds)); + sc->led_count = 1; + memset(use_hw_blink, 1, 4); + use_ds4_names = 0; + name_len = strlen("::sony#"); + name_fmt = "%s::sony%d"; } else { sixaxis_set_leds_from_id(sc); sc->led_count = 4; @@ -1782,7 +1802,8 @@ static void motion_state_worker(struct work_struct *work) static int sony_allocate_output_report(struct sony_sc *sc) { - if (sc->quirks & SIXAXIS_CONTROLLER) + if ((sc->quirks & SIXAXIS_CONTROLLER) || + (sc->quirks & NAVIGATION_CONTROLLER)) sc->output_report_dmabuf = kmalloc(sizeof(union sixaxis_output_report_01), GFP_KERNEL); @@ -2001,6 +2022,7 @@ static int sony_check_add(struct sony_sc *sc) if ((sc->quirks & DUALSHOCK4_CONTROLLER_BT) || (sc->quirks & MOTION_CONTROLLER_BT) || + (sc->quirks & NAVIGATION_CONTROLLER_BT) || (sc->quirks & SIXAXIS_CONTROLLER_BT)) { /* * sony_get_bt_devaddr() attempts to parse the Bluetooth MAC @@ -2033,7 +2055,8 @@ static int sony_check_add(struct sony_sc *sc) } memcpy(sc->mac_address, &buf[1], sizeof(sc->mac_address)); - } else if (sc->quirks & SIXAXIS_CONTROLLER_USB) { + } else if ((sc->quirks & SIXAXIS_CONTROLLER_USB) || + (sc->quirks & NAVIGATION_CONTROLLER_USB)) { buf = kmalloc(SIXAXIS_REPORT_0xF2_SIZE, GFP_KERNEL); if (!buf) return -ENOMEM; @@ -2167,7 +2190,8 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) goto err_stop; } - if (sc->quirks & SIXAXIS_CONTROLLER_USB) { + if ((sc->quirks & SIXAXIS_CONTROLLER_USB) || + (sc->quirks & NAVIGATION_CONTROLLER_USB)) { /* * The Sony Sixaxis does not handle HID Output Reports on the * Interrupt EP like it could, so we need to force HID Output @@ -2182,7 +2206,8 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id) hdev->quirks |= HID_QUIRK_SKIP_OUTPUT_REPORT_ID; ret = sixaxis_set_operational_usb(hdev); sony_init_work(sc, sixaxis_state_worker); - } else if (sc->quirks & SIXAXIS_CONTROLLER_BT) { + } else if ((sc->quirks & SIXAXIS_CONTROLLER_BT) || + (sc->quirks & NAVIGATION_CONTROLLER_BT)) { /* * The Sixaxis wants output reports sent on the ctrl endpoint * when connected via Bluetooth. @@ -2286,9 +2311,9 @@ static const struct hid_device_id sony_devices[] = { { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER), .driver_data = SIXAXIS_CONTROLLER_USB }, { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER), - .driver_data = SIXAXIS_CONTROLLER_USB }, + .driver_data = NAVIGATION_CONTROLLER_USB }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_NAVIGATION_CONTROLLER), - .driver_data = SIXAXIS_CONTROLLER_BT }, + .driver_data = NAVIGATION_CONTROLLER_BT }, { HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_MOTION_CONTROLLER), .driver_data = MOTION_CONTROLLER_USB }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_MOTION_CONTROLLER), -- cgit v1.1 From b2723eb73c6dc014980beb0f3e5f47d6cac57939 Mon Sep 17 00:00:00 2001 From: Simon Wood Date: Wed, 17 Jun 2015 00:08:53 -0600 Subject: HID: hid-sony: Fix report descriptor for Navigation Controller Patch report descriptor to remove unused and ramdomly changing axis. Original report descriptor (via BT) was as follows: 00000000 05 01 09 04 a1 01 a1 02 85 01 75 08 95 01 15 00 |..........u.....| 00000010 26 ff 00 81 03 75 01 95 13 15 00 25 01 35 00 45 |&....u.....%.5.E| 00000020 01 05 09 19 01 29 13 81 02 75 01 95 0d 06 00 ff |.....)...u......| 00000030 81 03 15 00 26 ff 00 05 01 09 01 a1 00 75 08 95 |....&........u..| 00000040 04 35 00 46 ff 00 09 30 09 31 09 32 09 35 81 02 |.5.F...0.1.2.5..| 00000050 c0 05 01 75 08 95 27 09 01 81 02 75 08 95 30 09 |...u..'....u..0.| 00000060 01 91 02 75 08 95 30 09 01 b1 02 c0 a1 02 85 02 |...u..0.........| 00000070 75 08 95 30 09 01 b1 02 c0 a1 02 85 ee 75 08 95 |u..0.........u..| 00000080 30 09 01 b1 02 c0 a1 02 85 ef 75 08 95 30 09 01 |0.........u..0..| 00000090 b1 02 c0 c0 00 |.....| 00000095 Signed-off-by: Simon Wood Signed-off-by: Jiri Kosina --- drivers/hid/hid-sony.c | 91 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 90 insertions(+), 1 deletion(-) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index af02139..ed2f008 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c @@ -248,6 +248,88 @@ static __u8 motion_rdesc[] = { 0xC0 /* End Collection */ }; +/* PS/3 Navigation controller */ +static __u8 navigation_rdesc[] = { + 0x05, 0x01, /* Usage Page (Desktop), */ + 0x09, 0x04, /* Usage (Joystik), */ + 0xA1, 0x01, /* Collection (Application), */ + 0xA1, 0x02, /* Collection (Logical), */ + 0x85, 0x01, /* Report ID (1), */ + 0x75, 0x08, /* Report Size (8), */ + 0x95, 0x01, /* Report Count (1), */ + 0x15, 0x00, /* Logical Minimum (0), */ + 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ + 0x81, 0x03, /* Input (Constant, Variable), */ + 0x75, 0x01, /* Report Size (1), */ + 0x95, 0x13, /* Report Count (19), */ + 0x15, 0x00, /* Logical Minimum (0), */ + 0x25, 0x01, /* Logical Maximum (1), */ + 0x35, 0x00, /* Physical Minimum (0), */ + 0x45, 0x01, /* Physical Maximum (1), */ + 0x05, 0x09, /* Usage Page (Button), */ + 0x19, 0x01, /* Usage Minimum (01h), */ + 0x29, 0x13, /* Usage Maximum (13h), */ + 0x81, 0x02, /* Input (Variable), */ + 0x75, 0x01, /* Report Size (1), */ + 0x95, 0x0D, /* Report Count (13), */ + 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ + 0x81, 0x03, /* Input (Constant, Variable), */ + 0x15, 0x00, /* Logical Minimum (0), */ + 0x26, 0xFF, 0x00, /* Logical Maximum (255), */ + 0x05, 0x01, /* Usage Page (Desktop), */ + 0x09, 0x01, /* Usage (Pointer), */ + 0xA1, 0x00, /* Collection (Physical), */ + 0x75, 0x08, /* Report Size (8), */ + 0x95, 0x02, /* Report Count (2), */ + 0x35, 0x00, /* Physical Minimum (0), */ + 0x46, 0xFF, 0x00, /* Physical Maximum (255), */ + 0x09, 0x30, /* Usage (X), */ + 0x09, 0x31, /* Usage (Y), */ + 0x81, 0x02, /* Input (Variable), */ + 0xC0, /* End Collection, */ + 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ + 0x95, 0x06, /* Report Count (6), */ + 0x81, 0x03, /* Input (Constant, Variable), */ + 0x05, 0x01, /* Usage Page (Desktop), */ + 0x75, 0x08, /* Report Size (8), */ + 0x95, 0x05, /* Report Count (5), */ + 0x09, 0x01, /* Usage (Pointer), */ + 0x81, 0x02, /* Input (Variable), */ + 0x06, 0x00, 0xFF, /* Usage Page (FF00h), */ + 0x95, 0x20, /* Report Count (26), */ + 0x81, 0x02, /* Input (Variable), */ + 0x75, 0x08, /* Report Size (8), */ + 0x95, 0x30, /* Report Count (48), */ + 0x09, 0x01, /* Usage (Pointer), */ + 0x91, 0x02, /* Output (Variable), */ + 0x75, 0x08, /* Report Size (8), */ + 0x95, 0x30, /* Report Count (48), */ + 0x09, 0x01, /* Usage (Pointer), */ + 0xB1, 0x02, /* Feature (Variable), */ + 0xC0, /* End Collection, */ + 0xA1, 0x02, /* Collection (Logical), */ + 0x85, 0x02, /* Report ID (2), */ + 0x75, 0x08, /* Report Size (8), */ + 0x95, 0x30, /* Report Count (48), */ + 0x09, 0x01, /* Usage (Pointer), */ + 0xB1, 0x02, /* Feature (Variable), */ + 0xC0, /* End Collection, */ + 0xA1, 0x02, /* Collection (Logical), */ + 0x85, 0xEE, /* Report ID (238), */ + 0x75, 0x08, /* Report Size (8), */ + 0x95, 0x30, /* Report Count (48), */ + 0x09, 0x01, /* Usage (Pointer), */ + 0xB1, 0x02, /* Feature (Variable), */ + 0xC0, /* End Collection, */ + 0xA1, 0x02, /* Collection (Logical), */ + 0x85, 0xEF, /* Report ID (239), */ + 0x75, 0x08, /* Report Size (8), */ + 0x95, 0x30, /* Report Count (48), */ + 0x09, 0x01, /* Usage (Pointer), */ + 0xB1, 0x02, /* Feature (Variable), */ + 0xC0, /* End Collection, */ + 0xC0 /* End Collection */ +}; /* * The default descriptor doesn't provide mapping for the accelerometers @@ -974,6 +1056,13 @@ static u8 *motion_fixup(struct hid_device *hdev, u8 *rdesc, return motion_rdesc; } +static u8 *navigation_fixup(struct hid_device *hdev, u8 *rdesc, + unsigned int *rsize) +{ + *rsize = sizeof(navigation_rdesc); + return navigation_rdesc; +} + static __u8 *ps3remote_fixup(struct hid_device *hdev, __u8 *rdesc, unsigned int *rsize) { @@ -1058,7 +1147,7 @@ static __u8 *sony_report_fixup(struct hid_device *hdev, __u8 *rdesc, return motion_fixup(hdev, rdesc, rsize); if (sc->quirks & NAVIGATION_CONTROLLER) - return sixaxis_fixup(hdev, rdesc, rsize); + return navigation_fixup(hdev, rdesc, rsize); if (sc->quirks & PS3REMOTE) return ps3remote_fixup(hdev, rdesc, rsize); -- cgit v1.1