From 7f77897ef2b6a5ee4eb8bc24fe8b1f3eab254328 Mon Sep 17 00:00:00 2001 From: Jiri Kosina Date: Tue, 24 May 2011 11:43:18 +0200 Subject: HID: hiddev: fix potential use-after-free Commit 6cb4b040795 ("HID: hiddev: fix race between hiddev_disconnect and hiddev_release") made it possible to access hiddev (for unlocking the existance mutex) once hiddev has been kfreed. Change the order so that this can not happen (always unlock the mutex first, it is needed only to protect access to ->exist and ->open). Signed-off-by: Jiri Kosina --- drivers/hid/usbhid/hiddev.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'drivers/hid') diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c index ff3c644..4985f485 100644 --- a/drivers/hid/usbhid/hiddev.c +++ b/drivers/hid/usbhid/hiddev.c @@ -923,10 +923,11 @@ void hiddev_disconnect(struct hid_device *hid) usb_deregister_dev(usbhid->intf, &hiddev_class); if (hiddev->open) { + mutex_unlock(&hiddev->existancelock); usbhid_close(hiddev->hid); wake_up_interruptible(&hiddev->wait); } else { + mutex_unlock(&hiddev->existancelock); kfree(hiddev); } - mutex_unlock(&hiddev->existancelock); } -- cgit v1.1 From e23be0a27dcc9297ff0495360d89bc5b0bf12383 Mon Sep 17 00:00:00 2001 From: Jimmy Hon Date: Fri, 20 May 2011 17:59:19 -0400 Subject: HID: add quirk for HyperPen 10000U Add 5543:0064 UC-Logic Technology Corp. Aiptek HyperPen 10000U to quirks with HID_QUIRK_MULTI_INPUT. Originally the device is reporting the x,y coordinates on Z and RX. By adding this quirk, there will be two kernel devices. The first one is muted and the second device will report coordinates on X and Y. Signed-off-by: Jimmy Hon Signed-off-by: Jiri Kosina --- drivers/hid/hid-ids.h | 1 + drivers/hid/usbhid/hid-quirks.c | 1 + 2 files changed, 2 insertions(+) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 0b374a6..2bbaad7 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -622,6 +622,7 @@ #define USB_VENDOR_ID_UCLOGIC 0x5543 #define USB_DEVICE_ID_UCLOGIC_TABLET_PF1209 0x0042 #define USB_DEVICE_ID_UCLOGIC_TABLET_KNA5 0x6001 +#define USB_DEVICE_ID_UCLOGIC_TABLET_TWA60 0x0064 #define USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U 0x0003 #define USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U 0x0004 #define USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U 0x0005 diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index 0e30b14..621959d 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c @@ -74,6 +74,7 @@ static const struct hid_blacklist { { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_PF1209, HID_QUIRK_MULTI_INPUT }, { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U, HID_QUIRK_MULTI_INPUT }, { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_KNA5, HID_QUIRK_MULTI_INPUT }, + { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_TWA60, HID_QUIRK_MULTI_INPUT }, { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U, HID_QUIRK_MULTI_INPUT }, { USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U, HID_QUIRK_MULTI_INPUT }, { USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_10_6_INCH, HID_QUIRK_MULTI_INPUT }, -- cgit v1.1 From 5c699d7d3f94ee1dd934edea889b32f8279a4e65 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Thu, 26 May 2011 11:49:16 +0300 Subject: HID: hiddev: fix use after free in hiddev_release There are a couple use after free bugs here. Signed-off-by: Dan Carpenter [jkosina@suse.cz: removed already fixed hunk] Signed-off-by: Jiri Kosina --- drivers/hid/usbhid/hiddev.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'drivers/hid') diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c index 4985f485..7c1188b 100644 --- a/drivers/hid/usbhid/hiddev.c +++ b/drivers/hid/usbhid/hiddev.c @@ -248,12 +248,15 @@ static int hiddev_release(struct inode * inode, struct file * file) usbhid_close(list->hiddev->hid); usbhid_put_power(list->hiddev->hid); } else { + mutex_unlock(&list->hiddev->existancelock); kfree(list->hiddev); + kfree(list); + return 0; } } - kfree(list); mutex_unlock(&list->hiddev->existancelock); + kfree(list); return 0; } -- cgit v1.1 From 6dc1418e13144162e8bc4858789010d8f0e1e65c Mon Sep 17 00:00:00 2001 From: Tomoki Sekiyama Date: Mon, 23 May 2011 15:45:44 -0700 Subject: HID: yurex: recognize GeneralKeys wireless presenter as generic HID Unfortunately, the device seems to have the same Vendor ID and Product ID as YUREX leg-shakes sensors, and the commit 6bc235a2e2 ("USB: add driver for Meywa-Denki & Kayac YUREX") added the ID to hid_ignore_list. I believe that we can distinguish YUREX and the Wireless Presenter by device type. The patch below makes the driver ignore only YUREX (bInterfaceProtocol==0), and recognize Wireless Presenter (bInterfaceProtocol is keyboard or mouse) as generic HID. (I don't have the Wireless Presenter, so not yet ested.) ** YUREX lsusb information: Bus 002 Device 007: ID 0c45:1010 Microdia Device Descriptor: bLength 18 bDescriptorType 1 bcdUSB 1.10 bDeviceClass 0 (Defined at Interface level) bDeviceSubClass 0 bDeviceProtocol 0 bMaxPacketSize0 8 idVendor 0x0c45 Microdia idProduct 0x1010 bcdDevice 0.03 iManufacturer 1 JESS iProduct 2 YUREX iSerial 3 10000269 bNumConfigurations 1 Configuration Descriptor: bLength 9 bDescriptorType 2 wTotalLength 34 bNumInterfaces 1 bConfigurationValue 1 iConfiguration 0 bmAttributes 0xa0 (Bus Powered) Remote Wakeup MaxPower 100mA Interface Descriptor: bLength 9 bDescriptorType 4 bInterfaceNumber 0 bAlternateSetting 0 bNumEndpoints 1 bInterfaceClass 3 Human Interface Device bInterfaceSubClass 1 Boot Interface Subclass bInterfaceProtocol 0 None iInterface 0 HID Device Descriptor: bLength 9 bDescriptorType 33 bcdHID 1.10 bCountryCode 0 Not supported bNumDescriptors 1 bDescriptorType 34 Report wDescriptorLength 31 Report Descriptors: ** UNAVAILABLE ** Endpoint Descriptor: bLength 7 bDescriptorType 5 bEndpointAddress 0x81 EP 1 IN bmAttributes 3 Transfer Type Interrupt Synch Type None Usage Type Data wMaxPacketSize 0x0008 1x 8 bytes bInterval 10 Device Status: 0x0002 (Bus Powered) Remote Wakeup Enabled Addresses https://bugzilla.kernel.org/show_bug.cgi?id=26922 Signed-off-by: Tomoki Sekiyama Cc: Greg KH Cc: "Rafael J. Wysocki" Cc: Maciej Rutecki Reported-by: Thomas B?chler Tested-by: Thomas B?chler Signed-off-by: Andrew Morton Signed-off-by: Jiri Kosina --- drivers/hid/hid-core.c | 6 +++++- drivers/hid/usbhid/hid-core.c | 2 ++ 2 files changed, 7 insertions(+), 1 deletion(-) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index c957c4b..9d6495d 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1769,7 +1769,6 @@ static const struct hid_device_id hid_ignore_list[] = { { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1006) }, { HID_USB_DEVICE(USB_VENDOR_ID_GTCO, USB_DEVICE_ID_GTCO_1007) }, { HID_USB_DEVICE(USB_VENDOR_ID_IMATION, USB_DEVICE_ID_DISC_STAKKA) }, - { HID_USB_DEVICE(USB_VENDOR_ID_JESS, USB_DEVICE_ID_JESS_YUREX) }, { HID_USB_DEVICE(USB_VENDOR_ID_KBGEAR, USB_DEVICE_ID_KBGEAR_JAMSTUDIO) }, { HID_USB_DEVICE(USB_VENDOR_ID_KWORLD, USB_DEVICE_ID_KWORLD_RADIO_FM700) }, { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_GPEN_560) }, @@ -1910,6 +1909,11 @@ static bool hid_ignore(struct hid_device *hdev) hdev->product <= USB_DEVICE_ID_HANWANG_TABLET_LAST) return true; break; + case USB_VENDOR_ID_JESS: + if (hdev->product == USB_DEVICE_ID_JESS_YUREX && + hdev->type == HID_TYPE_USBNONE) + return true; + break; } if (hdev->type == HID_TYPE_USBMOUSE && diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index 38c261a..ad978f5 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c @@ -1191,6 +1191,8 @@ static int usbhid_probe(struct usb_interface *intf, const struct usb_device_id * if (intf->cur_altsetting->desc.bInterfaceProtocol == USB_INTERFACE_PROTOCOL_MOUSE) hid->type = HID_TYPE_USBMOUSE; + else if (intf->cur_altsetting->desc.bInterfaceProtocol == 0) + hid->type = HID_TYPE_USBNONE; if (dev->manufacturer) strlcpy(hid->name, dev->manufacturer, sizeof(hid->name)); -- cgit v1.1 From 942fd4225f72826b31d893582b6ae7e172bb3202 Mon Sep 17 00:00:00 2001 From: Austin Zhang Date: Sat, 28 May 2011 02:03:47 +0800 Subject: HID: hid-multitouch: add support for Chunghwa multi-touch panel Added Chunghwa hid multitouch panel support into hid-multitouch. Signed-off-by: Austin Zhang Reviewed-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/Kconfig | 1 + drivers/hid/hid-core.c | 1 + drivers/hid/hid-ids.h | 3 +++ drivers/hid/hid-multitouch.c | 5 +++++ 4 files changed, 10 insertions(+) (limited to 'drivers/hid') diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index 67d2a75..36ca465 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig @@ -305,6 +305,7 @@ config HID_MULTITOUCH - 3M PCT touch screens - ActionStar dual touch panels - Cando dual touch panels + - Chunghwa panels - CVTouch panels - Cypress TrueTouch panels - Elo TouchSystems IntelliTouch Plus panels diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index c957c4b..f7440e8 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1359,6 +1359,7 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION_SOLAR) }, { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_TACTICAL_PAD) }, { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_WIRELESS) }, + { HID_USB_DEVICE(USB_VENDOR_ID_CHUNGHWAT, USB_DEVICE_ID_CHUNGHWAT_MULTITOUCH) }, { HID_USB_DEVICE(USB_VENDOR_ID_CREATIVELABS, USB_DEVICE_ID_PRODIKEYS_PCMIDI) }, { HID_USB_DEVICE(USB_VENDOR_ID_CVTOUCH, USB_DEVICE_ID_CVTOUCH_SCREEN) }, { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1) }, diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 2bbaad7..aecb5a4 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -173,6 +173,9 @@ #define USB_DEVICE_ID_CHICONY_MULTI_TOUCH 0xb19d #define USB_DEVICE_ID_CHICONY_WIRELESS 0x0618 +#define USB_VENDOR_ID_CHUNGHWAT 0x2247 +#define USB_DEVICE_ID_CHUNGHWAT_MULTITOUCH 0x0001 + #define USB_VENDOR_ID_CIDC 0x1677 #define USB_VENDOR_ID_CMEDIA 0x0d8c diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index ecd4d2d..8bc32a0 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c @@ -593,6 +593,11 @@ static const struct hid_device_id mt_devices[] = { HID_USB_DEVICE(USB_VENDOR_ID_CANDO, USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6) }, + /* Chunghwa Telecom touch panels */ + { .driver_data = MT_CLS_DEFAULT, + HID_USB_DEVICE(USB_VENDOR_ID_CHUNGHWAT, + USB_DEVICE_ID_CHUNGHWAT_MULTITOUCH) }, + /* CVTouch panels */ { .driver_data = MT_CLS_DEFAULT, HID_USB_DEVICE(USB_VENDOR_ID_CVTOUCH, -- cgit v1.1 From dc0a4f0ce2b1a9ef5947cdb6d62f60008a7e42bf Mon Sep 17 00:00:00 2001 From: Michael Bauer Date: Thu, 2 Jun 2011 15:40:14 -0700 Subject: HID: Fix Logitech Driving Force Pro wheel - Add the quirk "NOGET" to make the wheel work at all in native mode. - Replace the somehow broken report descriptor with a custom one to have separate throttle and brake axes. As there are significant differences in the descriptor (original descriptor "hides" the separate axes in a 24 bit FF00 usagepage, new descripter replaces that with two individual 8 bit desktop.y and desktop.rz usages) I provided a complete replacement descriptor instead trying to patch the original one. Patching the descriptor seems not feasible as the new one is much larger. Note: To actually test this you have to use the tool "ltwheelconf" to put the DFP into it's native mode - See below for more info. Background: Most Logitech wheels are initially reporting themselves with a "fallback" deviceID (USB_DEVICE_ID_LOGITECH_WHEEL - 0xc294), in order to make sure they are working even without having the proper driver installed. If the Logitech driver is installed it sends a special command to the wheel which sets the wheel to "native mode", enabling enhance features like: - Clutch pedal - extended wheel rotation range (up to 900 degrees) - H-gate shifter - separate axis for throttle / brake - all buttons When the wheel is set to native mode it basically disconnects and reconnects with a different deviceID (USB_DEVICE_ID_LOGITECH_DFP_WHEEL - 0xc298 in this case). I am working on a userspace tool [1] which does the switching from fallback to native mode. During development I found out that the Driving Force Pro wheel is not supported in native mode - quierk NOGET is missing and the throttle and brake axes are reported in a combined way only. Signed-off-by: Michael Bauer Signed-off-by: Simon Wood [1] https://github.com/TripleSpeeder/LTWheelConf Signed-off-by: Jiri Kosina --- drivers/hid/hid-lg.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 73 insertions(+), 1 deletion(-) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-lg.c b/drivers/hid/hid-lg.c index 21f205f..a7f916e 100644 --- a/drivers/hid/hid-lg.c +++ b/drivers/hid/hid-lg.c @@ -41,6 +41,66 @@ #define LG_FF3 0x1000 #define LG_FF4 0x2000 +/* Size of the original descriptor of the Driving Force Pro wheel */ +#define DFP_RDESC_ORIG_SIZE 97 + +/* Fixed report descriptor for Logitech Driving Force Pro wheel controller + * + * The original descriptor hides the separate throttle and brake axes in + * a custom vendor usage page, providing only a combined value as + * GenericDesktop.Y. + * This descriptor removes the combined Y axis and instead reports + * separate throttle (Y) and brake (RZ). + */ +static __u8 dfp_rdesc_fixed[] = { +0x05, 0x01, /* Usage Page (Desktop), */ +0x09, 0x04, /* Usage (Joystik), */ +0xA1, 0x01, /* Collection (Application), */ +0xA1, 0x02, /* Collection (Logical), */ +0x95, 0x01, /* Report Count (1), */ +0x75, 0x0E, /* Report Size (14), */ +0x14, /* Logical Minimum (0), */ +0x26, 0xFF, 0x3F, /* Logical Maximum (16383), */ +0x34, /* Physical Minimum (0), */ +0x46, 0xFF, 0x3F, /* Physical Maximum (16383), */ +0x09, 0x30, /* Usage (X), */ +0x81, 0x02, /* Input (Variable), */ +0x95, 0x0E, /* Report Count (14), */ +0x75, 0x01, /* Report Size (1), */ +0x25, 0x01, /* Logical Maximum (1), */ +0x45, 0x01, /* Physical Maximum (1), */ +0x05, 0x09, /* Usage Page (Button), */ +0x19, 0x01, /* Usage Minimum (01h), */ +0x29, 0x0E, /* Usage Maximum (0Eh), */ +0x81, 0x02, /* Input (Variable), */ +0x05, 0x01, /* Usage Page (Desktop), */ +0x95, 0x01, /* Report Count (1), */ +0x75, 0x04, /* Report Size (4), */ +0x25, 0x07, /* Logical Maximum (7), */ +0x46, 0x3B, 0x01, /* Physical Maximum (315), */ +0x65, 0x14, /* Unit (Degrees), */ +0x09, 0x39, /* Usage (Hat Switch), */ +0x81, 0x42, /* Input (Variable, Nullstate), */ +0x65, 0x00, /* Unit, */ +0x26, 0xFF, 0x00, /* Logical Maximum (255), */ +0x46, 0xFF, 0x00, /* Physical Maximum (255), */ +0x75, 0x08, /* Report Size (8), */ +0x81, 0x01, /* Input (Constant), */ +0x09, 0x31, /* Usage (Y), */ +0x81, 0x02, /* Input (Variable), */ +0x09, 0x35, /* Usage (Rz), */ +0x81, 0x02, /* Input (Variable), */ +0x81, 0x01, /* Input (Constant), */ +0xC0, /* End Collection, */ +0xA1, 0x02, /* Collection (Logical), */ +0x09, 0x02, /* Usage (02h), */ +0x95, 0x07, /* Report Count (7), */ +0x91, 0x02, /* Output (Variable), */ +0xC0, /* End Collection, */ +0xC0 /* End Collection */ +}; + + /* * Certain Logitech keyboards send in report #3 keys which are far * above the logical maximum described in descriptor. This extends @@ -74,6 +134,18 @@ static __u8 *lg_report_fixup(struct hid_device *hdev, __u8 *rdesc, rdesc[47] = 0x95; rdesc[48] = 0x0B; } + + switch (hdev->product) { + case USB_DEVICE_ID_LOGITECH_DFP_WHEEL: + if (*rsize == DFP_RDESC_ORIG_SIZE) { + hid_info(hdev, + "fixing up Logitech Driving Force Pro report descriptor\n"); + rdesc = dfp_rdesc_fixed; + *rsize = sizeof(dfp_rdesc_fixed); + } + break; + } + return rdesc; } @@ -380,7 +452,7 @@ static const struct hid_device_id lg_devices[] = { { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G27_WHEEL), .driver_data = LG_FF }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_DFP_WHEEL), - .driver_data = LG_FF }, + .driver_data = LG_NOGET | LG_FF }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WII_WHEEL), .driver_data = LG_FF4 }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_FFG ), -- cgit v1.1 From 74bc6953135ae1478acc18046321bfca05b0e823 Mon Sep 17 00:00:00 2001 From: Stefan Kriwanek Date: Fri, 27 May 2011 18:40:29 +0200 Subject: HID: Add driver to fix Speedlink VAD Cezanne support Speedlink VAD Cezanne have a hardware bug that makes the cursor "jump" from one place to another every now and then. The issue are relative motion events erroneously reported by the device, each having a distance value of +256. This 256 can in fact never occur due to real motion, therefore those events can safely be ignored. The driver also drops useless EV_REL events with a value of 0, that the device sends every time it sends an "real" EV_REL or EV_KEY event. Signed-off-by: Stefan Kriwanek Signed-off-by: Jiri Kosina --- drivers/hid/Kconfig | 6 +++ drivers/hid/Makefile | 1 + drivers/hid/hid-core.c | 1 + drivers/hid/hid-ids.h | 3 ++ drivers/hid/hid-speedlink.c | 89 +++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 100 insertions(+) create mode 100644 drivers/hid/hid-speedlink.c (limited to 'drivers/hid') diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index 67d2a75..860b1db 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig @@ -494,6 +494,12 @@ config HID_SONY ---help--- Support for Sony PS3 controller. +config HID_SPEEDLINK + tristate "Speedlink VAD Cezanne mouse support" + depends on USB_HID + ---help--- + Support for Speedlink Vicious and Divine Cezanne mouse. + config HID_SUNPLUS tristate "Sunplus wireless desktop" depends on USB_HID diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile index f8cc4ea..f977180 100644 --- a/drivers/hid/Makefile +++ b/drivers/hid/Makefile @@ -63,6 +63,7 @@ obj-$(CONFIG_HID_ROCCAT_PYRA) += hid-roccat-pyra.o obj-$(CONFIG_HID_SAMSUNG) += hid-samsung.o obj-$(CONFIG_HID_SMARTJOYPLUS) += hid-sjoy.o obj-$(CONFIG_HID_SONY) += hid-sony.o +obj-$(CONFIG_HID_SPEEDLINK) += hid-speedlink.o obj-$(CONFIG_HID_SUNPLUS) += hid-sunplus.o obj-$(CONFIG_HID_GREENASIA) += hid-gaff.o obj-$(CONFIG_HID_THRUSTMASTER) += hid-tmff.o diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 9d6495d..d93d8c0 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1497,6 +1497,7 @@ static const struct hid_device_id hid_have_special_driver[] = { { 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_MEDIA_TABLET_10_6_INCH) }, { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_14_1_INCH) }, + { HID_USB_DEVICE(USB_VENDOR_ID_X_TENSIONS, USB_DEVICE_ID_SPEEDLINK_VAD_CEZANNE) }, { HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0005) }, { HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0030) }, { HID_USB_DEVICE(USB_VENDOR_ID_ZYDACRON, USB_DEVICE_ID_ZYDACRON_REMOTE_CONTROL) }, diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 0b374a6..cc298cb 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -658,6 +658,9 @@ #define USB_VENDOR_ID_WISEGROUP_LTD2 0x6677 #define USB_DEVICE_ID_SMARTJOY_DUAL_PLUS 0x8802 +#define USB_VENDOR_ID_X_TENSIONS 0x1ae7 +#define USB_DEVICE_ID_SPEEDLINK_VAD_CEZANNE 0x9001 + #define USB_VENDOR_ID_YEALINK 0x6993 #define USB_DEVICE_ID_YEALINK_P1K_P4K_B2K 0xb001 diff --git a/drivers/hid/hid-speedlink.c b/drivers/hid/hid-speedlink.c new file mode 100644 index 0000000..6020137 --- /dev/null +++ b/drivers/hid/hid-speedlink.c @@ -0,0 +1,89 @@ +/* + * HID driver for Speedlink Vicious and Divine Cezanne (USB mouse). + * Fixes "jumpy" cursor and removes nonexistent keyboard LEDS from + * the HID descriptor. + * + * Copyright (c) 2011 Stefan Kriwanek + */ + +/* + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + */ + +#include +#include +#include +#include + +#include "hid-ids.h" +#include "usbhid/usbhid.h" + +static const struct hid_device_id speedlink_devices[] = { + { HID_USB_DEVICE(USB_VENDOR_ID_X_TENSIONS, USB_DEVICE_ID_SPEEDLINK_VAD_CEZANNE)}, + { } +}; + +static int speedlink_input_mapping(struct hid_device *hdev, + struct hid_input *hi, + struct hid_field *field, struct hid_usage *usage, + unsigned long **bit, int *max) +{ + /* + * The Cezanne mouse has a second "keyboard" USB endpoint for it is + * able to map keyboard events to the button presses. + * It sends a standard keyboard report descriptor, though, whose + * LEDs we ignore. + */ + switch (usage->hid & HID_USAGE_PAGE) { + case HID_UP_LED: + return -1; + } + return 0; +} + +static int speedlink_event(struct hid_device *hdev, struct hid_field *field, + struct hid_usage *usage, __s32 value) +{ + /* No other conditions due to usage_table. */ + /* Fix "jumpy" cursor (invalid events sent by device). */ + if (value == 256) + return 1; + /* Drop useless distance 0 events (on button clicks etc.) as well */ + if (value == 0) + return 1; + + return 0; +} + +MODULE_DEVICE_TABLE(hid, speedlink_devices); + +static const struct hid_usage_id speedlink_grabbed_usages[] = { + { HID_GD_X, EV_REL, 0 }, + { HID_GD_Y, EV_REL, 1 }, + { HID_ANY_ID - 1, HID_ANY_ID - 1, HID_ANY_ID - 1} +}; + +static struct hid_driver speedlink_driver = { + .name = "speedlink", + .id_table = speedlink_devices, + .usage_table = speedlink_grabbed_usages, + .input_mapping = speedlink_input_mapping, + .event = speedlink_event, +}; + +static int __init speedlink_init(void) +{ + return hid_register_driver(&speedlink_driver); +} + +static void __exit speedlink_exit(void) +{ + hid_unregister_driver(&speedlink_driver); +} + +module_init(speedlink_init); +module_exit(speedlink_exit); +MODULE_LICENSE("GPL"); -- cgit v1.1 From b84bd27fe70206f9253c395958134e4e4b7e55f0 Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Sun, 12 Jun 2011 08:22:08 +0200 Subject: HID: hid-multitouch: fix broken eGalax Since the inclusion of eGalax devices in 2.6.39, I've got some bug reports for 480d and other devices. The problem lies in the reports descriptors: eGalax supports both pen and fingers, and so the reports descriptors contained both. But hid-multitouch relies on them to detect the last item in each field to send the multitouch events. In 480d, the last item is not Y as it should but Pressure. That means that the fields are not aligned and X,Y are at 0,0 (the other touch coordinates of the report). With this patch, the detection is made only when the field ContactID has been detected inside the collection. There is still a problem with the detections of the range as stylus and fingers may not have the same min/max, but it's a start. Signed-off-by: Benjamin Tissoires Reviewed-by: Henrik Rydberg Signed-off-by: Jiri Kosina --- drivers/hid/hid-multitouch.c | 57 ++++++++++++++++++++++++++++++-------------- 1 file changed, 39 insertions(+), 18 deletions(-) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index 8bc32a0..0b2dcd0 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c @@ -64,6 +64,7 @@ struct mt_device { struct mt_class *mtclass; /* our mt device class */ unsigned last_field_index; /* last field index of the report */ unsigned last_slot_field; /* the last field of a slot */ + int last_mt_collection; /* last known mt-related collection */ __s8 inputmode; /* InputMode HID feature, -1 if non-existent */ __u8 num_received; /* how many contacts we received */ __u8 num_expected; /* expected last contact index */ @@ -225,8 +226,10 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, cls->sn_move); /* touchscreen emulation */ set_abs(hi->input, ABS_X, field, cls->sn_move); - td->last_slot_field = usage->hid; - td->last_field_index = field->index; + if (td->last_mt_collection == usage->collection_index) { + td->last_slot_field = usage->hid; + td->last_field_index = field->index; + } return 1; case HID_GD_Y: if (quirks & MT_QUIRK_EGALAX_XYZ_FIXUP) @@ -237,8 +240,10 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, cls->sn_move); /* touchscreen emulation */ set_abs(hi->input, ABS_Y, field, cls->sn_move); - td->last_slot_field = usage->hid; - td->last_field_index = field->index; + if (td->last_mt_collection == usage->collection_index) { + td->last_slot_field = usage->hid; + td->last_field_index = field->index; + } return 1; } return 0; @@ -246,31 +251,40 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, case HID_UP_DIGITIZER: switch (usage->hid) { case HID_DG_INRANGE: - td->last_slot_field = usage->hid; - td->last_field_index = field->index; + if (td->last_mt_collection == usage->collection_index) { + td->last_slot_field = usage->hid; + td->last_field_index = field->index; + } return 1; case HID_DG_CONFIDENCE: - td->last_slot_field = usage->hid; - td->last_field_index = field->index; + if (td->last_mt_collection == usage->collection_index) { + td->last_slot_field = usage->hid; + td->last_field_index = field->index; + } return 1; case HID_DG_TIPSWITCH: hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH); input_set_capability(hi->input, EV_KEY, BTN_TOUCH); - td->last_slot_field = usage->hid; - td->last_field_index = field->index; + if (td->last_mt_collection == usage->collection_index) { + td->last_slot_field = usage->hid; + td->last_field_index = field->index; + } return 1; case HID_DG_CONTACTID: input_mt_init_slots(hi->input, td->maxcontacts); td->last_slot_field = usage->hid; td->last_field_index = field->index; + td->last_mt_collection = usage->collection_index; return 1; case HID_DG_WIDTH: hid_map_usage(hi, usage, bit, max, EV_ABS, ABS_MT_TOUCH_MAJOR); set_abs(hi->input, ABS_MT_TOUCH_MAJOR, field, cls->sn_width); - td->last_slot_field = usage->hid; - td->last_field_index = field->index; + if (td->last_mt_collection == usage->collection_index) { + td->last_slot_field = usage->hid; + td->last_field_index = field->index; + } return 1; case HID_DG_HEIGHT: hid_map_usage(hi, usage, bit, max, @@ -279,8 +293,10 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, cls->sn_height); input_set_abs_params(hi->input, ABS_MT_ORIENTATION, 0, 1, 0, 0); - td->last_slot_field = usage->hid; - td->last_field_index = field->index; + if (td->last_mt_collection == usage->collection_index) { + td->last_slot_field = usage->hid; + td->last_field_index = field->index; + } return 1; case HID_DG_TIPPRESSURE: if (quirks & MT_QUIRK_EGALAX_XYZ_FIXUP) @@ -292,16 +308,20 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, /* touchscreen emulation */ set_abs(hi->input, ABS_PRESSURE, field, cls->sn_pressure); - td->last_slot_field = usage->hid; - td->last_field_index = field->index; + if (td->last_mt_collection == usage->collection_index) { + td->last_slot_field = usage->hid; + td->last_field_index = field->index; + } return 1; case HID_DG_CONTACTCOUNT: - td->last_field_index = field->index; + if (td->last_mt_collection == usage->collection_index) + td->last_field_index = field->index; return 1; case HID_DG_CONTACTMAX: /* we don't set td->last_slot_field as contactcount and * contact max are global to the report */ - td->last_field_index = field->index; + if (td->last_mt_collection == usage->collection_index) + td->last_field_index = field->index; return -1; } /* let hid-input decide for the others */ @@ -516,6 +536,7 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) } td->mtclass = mtclass; td->inputmode = -1; + td->last_mt_collection = -1; hid_set_drvdata(hdev, td); ret = hid_parse(hdev); -- cgit v1.1 From 61ab44bebdefab296487e7cd723a634849278827 Mon Sep 17 00:00:00 2001 From: Simon Wood Date: Fri, 10 Jun 2011 12:00:26 +0200 Subject: HID: hid-sony: amend Sixaxis descriptor to enable accelerometers Modify the HID descriptor of the Sixaxis controller to allow the reporting of the accelerometers and gyro via a joystick axis. Rewrite section from offset 83: -- 0x75, 0x08, /* Report Size (8), */ /* all the other data lumped together */ 0x95, 0x27, /* Report Count (39), */ 0x09, 0x01, /* Usage (Pointer), */ 0x81, 0x02, /* Input (Variable), */ 0x75, 0x08, /* Report Size (8), */ 0x95, 0x30, /* Report Count (48), */ 0x09, 0x01, /* Usage (Pointer), */ /* Note Output */ 0x91, 0x02, /* Output (Variable), */ 0x75, 0x08, /* Report Size (8), */ 0x95, 0x30, /* Report Count (48), */ 0x09, 0x01, /* Usage (Pointer), */ /* Note Feature */ 0xB1, 0x02, /* Feature (Variable), */ -- with -- /* last 2 not used... */ 0x95, 0x13, /* Report Count (19), */ 0x09, 0x01, /* Usage (Pointer), */ 0x81, 0x02, /* Input (Variable), */ /* Padding */ 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), */ -- Signed-off-by: Simon Wood Signed-off-by: Antonio Ospite Signed-off-by: Jiri Kosina --- drivers/hid/hid-sony.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index 936c911..5398507 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c @@ -28,6 +28,12 @@ #define SIXAXIS_CONTROLLER_USB (1 << 1) #define SIXAXIS_CONTROLLER_BT (1 << 2) +static const u8 sixaxis_rdesc_fixup[] = { + 0x95, 0x13, 0x09, 0x01, 0x81, 0x02, 0x95, 0x0C, + 0x81, 0x01, 0x75, 0x10, 0x95, 0x04, 0x26, 0xFF, + 0x03, 0x46, 0xFF, 0x03, 0x09, 0x01, 0x81, 0x02 +}; + struct sony_sc { unsigned long quirks; }; @@ -43,6 +49,15 @@ static __u8 *sony_report_fixup(struct hid_device *hdev, __u8 *rdesc, hid_info(hdev, "Fixing up Sony Vaio VGX report descriptor\n"); rdesc[55] = 0x06; } + + /* The HID descriptor exposed over BT has a trailing zero byte */ + if ((((sc->quirks & SIXAXIS_CONTROLLER_USB) && *rsize == 148) || + ((sc->quirks & SIXAXIS_CONTROLLER_BT) && *rsize == 149)) && + rdesc[83] == 0x75) { + hid_info(hdev, "Fixing up Sony Sixaxis report descriptor\n"); + memcpy((void *)&rdesc[83], (void *)&sixaxis_rdesc_fixup, + sizeof(sixaxis_rdesc_fixup)); + } return rdesc; } -- cgit v1.1 From c9e4d87758e95ef9d78a7767e2405ebaf54adcd8 Mon Sep 17 00:00:00 2001 From: Simon Wood Date: Fri, 10 Jun 2011 12:00:27 +0200 Subject: HID: hid-sony: fix endiannes of Sixaxis accel/gyro values The accelerometers/gyro on the Sixaxis are reported in the wrong endianness (ie. not compatible with HID), so this patch intercepts the report and swaps the appropriate bytes over. Accelerometers are scaled with a nominal value of +/-4000 = 1G, maximum value would be around +/-32768 = 8G. Gyro on my device always reports -32768, might need some calibration set within the controller. Fix extracted from previous patch submission: https://patchwork.kernel.org/patch/95212/ Signed-off-by: Marcin Tolysz Signed-off-by: Simon Wood Signed-off-by: Antonio Ospite Signed-off-by: Jiri Kosina --- drivers/hid/hid-sony.c | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index 5398507..5cd25bd 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c @@ -61,6 +61,25 @@ static __u8 *sony_report_fixup(struct hid_device *hdev, __u8 *rdesc, return rdesc; } +static int sony_raw_event(struct hid_device *hdev, struct hid_report *report, + __u8 *rd, int size) +{ + struct sony_sc *sc = hid_get_drvdata(hdev); + + /* Sixaxis HID report has acclerometers/gyro with MSByte first, this + * has to be BYTE_SWAPPED before passing up to joystick interface + */ + if ((sc->quirks & (SIXAXIS_CONTROLLER_USB | SIXAXIS_CONTROLLER_BT)) && + rd[0] == 0x01 && size == 49) { + swap(rd[41], rd[42]); + swap(rd[43], rd[44]); + swap(rd[45], rd[46]); + swap(rd[47], rd[48]); + } + + return 0; +} + /* * The Sony Sixaxis does not handle HID Output Reports on the Interrupt EP * like it should according to usbhid/hid-core.c::usbhid_output_raw_report() @@ -209,6 +228,7 @@ static struct hid_driver sony_driver = { .probe = sony_probe, .remove = sony_remove, .report_fixup = sony_report_fixup, + .raw_event = sony_raw_event }; static int __init sony_init(void) -- cgit v1.1 From f3b83d71a1b1a1569dba774c3a4f6e2a3b9fef99 Mon Sep 17 00:00:00 2001 From: Jiri Kosina Date: Mon, 13 Jun 2011 23:08:18 +0300 Subject: HID: add support for MS Digital Media 3000 The Digital Media 3000 keyboard (USB id: 0x0730) features the same 1-5 Application Launch keys that the Natural Ergonomic 4000 has. Add its usb id to the list of quirks. Reported-by: Khelben Blackstaff Signed-off-by: Jiri Kosina --- drivers/hid/hid-core.c | 1 + drivers/hid/hid-ids.h | 1 + drivers/hid/hid-microsoft.c | 2 ++ 3 files changed, 4 insertions(+) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index d93d8c0..3b6af7c 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1428,6 +1428,7 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_NE4K) }, { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_LK6K) }, { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_USB) }, + { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_DIGITAL_MEDIA_3K) }, { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0) }, { HID_USB_DEVICE(USB_VENDOR_ID_MONTEREY, USB_DEVICE_ID_GENIUS_KB29E) }, { HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN) }, diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index cc298cb..e8faee4 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -468,6 +468,7 @@ #define USB_DEVICE_ID_MS_LK6K 0x00f9 #define USB_DEVICE_ID_MS_PRESENTER_8K_BT 0x0701 #define USB_DEVICE_ID_MS_PRESENTER_8K_USB 0x0713 +#define USB_DEVICE_ID_MS_DIGITAL_MEDIA_3K 0x0730 #define USB_VENDOR_ID_MOJO 0x8282 #define USB_DEVICE_ID_RETRO_ADAPTER 0x3201 diff --git a/drivers/hid/hid-microsoft.c b/drivers/hid/hid-microsoft.c index 0f6fc54..df91791f 100644 --- a/drivers/hid/hid-microsoft.c +++ b/drivers/hid/hid-microsoft.c @@ -179,6 +179,8 @@ static const struct hid_device_id ms_devices[] = { .driver_data = MS_ERGONOMY | MS_RDESC }, { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_USB), .driver_data = MS_PRESENTER }, + { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_DIGITAL_MEDIA_3K), + .driver_data = MS_ERGONOMY }, { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0), .driver_data = MS_NOGET }, -- cgit v1.1 From c3a4924565e2eecf2539871abd123d35be6d76d5 Mon Sep 17 00:00:00 2001 From: Jiri Kosina Date: Thu, 16 Jun 2011 12:21:34 +0200 Subject: Revert "HID: magicmouse: ignore 'ivalid report id' while switching modes" This reverts commit 23746a66d7d9e73402c68ef00d708796b97ebd72. It turned out that the actual reason for failure is not the device firmware, but bug in Bluetooth stack, which will be fixed by patch by Ville Tervo which corrects the mask handling for CSR 1.1 Dongles. Reported-and-tested-by: Ed Tomlinson Reported-and-tested-by: Chase Douglas Signed-off-by: Jiri Kosina --- drivers/hid/hid-magicmouse.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-magicmouse.c b/drivers/hid/hid-magicmouse.c index a5eda4c..0ec91c1 100644 --- a/drivers/hid/hid-magicmouse.c +++ b/drivers/hid/hid-magicmouse.c @@ -501,17 +501,9 @@ static int magicmouse_probe(struct hid_device *hdev, } report->size = 6; - /* - * The device reponds with 'invalid report id' when feature - * report switching it into multitouch mode is sent to it. - * - * This results in -EIO from the _raw low-level transport callback, - * but there seems to be no other way of switching the mode. - * Thus the super-ugly hacky success check below. - */ ret = hdev->hid_output_raw_report(hdev, feature, sizeof(feature), HID_FEATURE_REPORT); - if (ret != -EIO) { + if (ret != sizeof(feature)) { hid_err(hdev, "unable to request touch data (%d)\n", ret); goto err_stop_hw; } -- cgit v1.1 From 50bc03ab5c7529fdfe4e01621efca7d26439ea00 Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Tue, 21 Jun 2011 15:01:53 +0200 Subject: HID: hid-multitouch: ensure slots are initialized In case a device does not provide the feature "Maximum Contact Count", or set it at 0, the maxcontacts field may be at 0 while calling input_mt_init_slots. This patch ensures that hid-multitouch will allways report ABS_MT_SLOT and ABS_MT_TRACKING_ID to the user space. This corrects a bug found with some Ilitek devices that has been integrated in 3.0-rc0. Signed-off-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/hid-multitouch.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index 0b2dcd0..3867656 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c @@ -271,6 +271,8 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi, } return 1; case HID_DG_CONTACTID: + if (!td->maxcontacts) + td->maxcontacts = MT_DEFAULT_MAXCONTACT; input_mt_init_slots(hi->input, td->maxcontacts); td->last_slot_field = usage->hid; td->last_field_index = field->index; @@ -547,9 +549,6 @@ static int mt_probe(struct hid_device *hdev, const struct hid_device_id *id) if (ret) goto fail; - if (!td->maxcontacts) - td->maxcontacts = MT_DEFAULT_MAXCONTACT; - td->slots = kzalloc(td->maxcontacts * sizeof(struct mt_slot), GFP_KERNEL); if (!td->slots) { -- cgit v1.1 From 85a600825b425d52e466c6093dcdfeba85eb0044 Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Tue, 21 Jun 2011 15:01:54 +0200 Subject: HID: hid-multitouch: correct VID for Stantum panels while merging hid-stantum into hid-multitouch, I did not correctly copy/paste the VIDs for those devices. This patch fixes it. Signed-off-by: Benjamin Tissoires Signed-off-by: Jiri Kosina --- drivers/hid/hid-multitouch.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index 3867656..467b518 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c @@ -706,10 +706,10 @@ static const struct hid_device_id mt_devices[] = { HID_USB_DEVICE(USB_VENDOR_ID_STANTUM, USB_DEVICE_ID_MTP)}, { .driver_data = MT_CLS_CONFIDENCE, - HID_USB_DEVICE(USB_VENDOR_ID_STANTUM, + HID_USB_DEVICE(USB_VENDOR_ID_STANTUM_STM, USB_DEVICE_ID_MTP_STM)}, { .driver_data = MT_CLS_CONFIDENCE, - HID_USB_DEVICE(USB_VENDOR_ID_STANTUM, + HID_USB_DEVICE(USB_VENDOR_ID_STANTUM_SITRONIX, USB_DEVICE_ID_MTP_SITRONIX)}, /* Touch International panels */ -- cgit v1.1 From c3ead6de4f6bd1c08a81f84e629e3dbf4a9078f0 Mon Sep 17 00:00:00 2001 From: Benjamin Tissoires Date: Tue, 21 Jun 2011 15:01:55 +0200 Subject: HID: hid-multitouch: add support for a new Lumio dual-touch panel 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-multitouch.c | 3 +++ 3 files changed, 5 insertions(+) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index f7440e8..6f3289a 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1423,6 +1423,7 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_SPACETRAVELLER) }, { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_SPACENAVIGATOR) }, { HID_USB_DEVICE(USB_VENDOR_ID_LUMIO, USB_DEVICE_ID_CRYSTALTOUCH) }, + { HID_USB_DEVICE(USB_VENDOR_ID_LUMIO, USB_DEVICE_ID_CRYSTALTOUCH_DUAL) }, { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICOLCD) }, { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICOLCD_BOOTLOADER) }, { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_SIDEWINDER_GV) }, diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index aecb5a4..a756ee6 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -449,6 +449,7 @@ #define USB_VENDOR_ID_LUMIO 0x202e #define USB_DEVICE_ID_CRYSTALTOUCH 0x0006 +#define USB_DEVICE_ID_CRYSTALTOUCH_DUAL 0x0007 #define USB_VENDOR_ID_MCC 0x09db #define USB_DEVICE_ID_MCC_PMD1024LS 0x0076 diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index 467b518..62cac4d 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c @@ -676,6 +676,9 @@ static const struct hid_device_id mt_devices[] = { { .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE, HID_USB_DEVICE(USB_VENDOR_ID_LUMIO, USB_DEVICE_ID_CRYSTALTOUCH) }, + { .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE, + HID_USB_DEVICE(USB_VENDOR_ID_LUMIO, + USB_DEVICE_ID_CRYSTALTOUCH_DUAL) }, /* MosArt panels */ { .driver_data = MT_CLS_CONFIDENCE_MINUS_ONE, -- cgit v1.1 From d946e65e2ab885c05b8cacf292be65fa292d08f6 Mon Sep 17 00:00:00 2001 From: Anssi Hannula Date: Mon, 27 Jun 2011 00:07:31 +0300 Subject: HID: add FF support for Holtek On Line Grip based gamepads Add force feedback support for Holtek On Line Grip based HID devices. The protocol is more complex than that of most other rumblepads, but the device still needs to be handled as a memoryless one. Tested by Cleber de Mattos Casali with a 1241:5015 "Clone Joypad Super Power Fire" gamepad, with help from Hendrik Iben . Signed-off-by: Anssi Hannula Tested-by: Cleber de Mattos Casali Signed-off-by: Jiri Kosina --- drivers/hid/Kconfig | 14 +++ drivers/hid/Makefile | 1 + drivers/hid/hid-core.c | 1 + drivers/hid/hid-holtekff.c | 240 +++++++++++++++++++++++++++++++++++++++++++++ drivers/hid/hid-ids.h | 3 + 5 files changed, 259 insertions(+) create mode 100644 drivers/hid/hid-holtekff.c (limited to 'drivers/hid') diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index 860b1db..acc39e8 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig @@ -172,6 +172,20 @@ config HID_EZKEY ---help--- Support for Ezkey BTC 8193 keyboard. +config HID_HOLTEK + tristate "Holtek On Line Grip based game controller support" + depends on USB_HID + ---help--- + Say Y here if you have a Holtek On Line Grip based game controller. + +config HOLTEK_FF + bool "Holtek On Line Grip force feedback support" + depends on HID_HOLTEK + select INPUT_FF_MEMLESS + ---help--- + Say Y here if you have a Holtek On Line Grip based game controller + and want to have force feedback support for it. + config HID_KEYTOUCH tristate "Keytouch HID devices" depends on USB_HID diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile index f977180..21dea54 100644 --- a/drivers/hid/Makefile +++ b/drivers/hid/Makefile @@ -37,6 +37,7 @@ obj-$(CONFIG_HID_EMS_FF) += hid-emsff.o obj-$(CONFIG_HID_ELECOM) += hid-elecom.o obj-$(CONFIG_HID_EZKEY) += hid-ezkey.o obj-$(CONFIG_HID_GYRATION) += hid-gyration.o +obj-$(CONFIG_HID_HOLTEK) += hid-holtekff.o obj-$(CONFIG_HID_KENSINGTON) += hid-kensington.o obj-$(CONFIG_HID_KEYTOUCH) += hid-keytouch.o obj-$(CONFIG_HID_KYE) += hid-kye.o diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 3b6af7c..e5ab72a 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1387,6 +1387,7 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_2) }, { HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_3) }, { HID_USB_DEVICE(USB_VENDOR_ID_HANVON, USB_DEVICE_ID_HANVON_MULTITOUCH) }, + { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK, USB_DEVICE_ID_HOLTEK_ON_LINE_GRIP) }, { HID_USB_DEVICE(USB_VENDOR_ID_ILITEK, USB_DEVICE_ID_ILITEK_MULTITOUCH) }, { HID_USB_DEVICE(USB_VENDOR_ID_IRTOUCHSYSTEMS, USB_DEVICE_ID_IRTOUCH_INFRARED_USB) }, { HID_USB_DEVICE(USB_VENDOR_ID_KENSINGTON, USB_DEVICE_ID_KS_SLIMBLADE) }, diff --git a/drivers/hid/hid-holtekff.c b/drivers/hid/hid-holtekff.c new file mode 100644 index 0000000..91e3a03 --- /dev/null +++ b/drivers/hid/hid-holtekff.c @@ -0,0 +1,240 @@ +/* + * Force feedback support for Holtek On Line Grip based gamepads + * + * These include at least a Brazilian "Clone Joypad Super Power Fire" + * which uses vendor ID 0x1241 and identifies as "HOLTEK On Line Grip". + * + * Copyright (c) 2011 Anssi Hannula + */ + +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include + +#include "hid-ids.h" + +#ifdef CONFIG_HOLTEK_FF +#include "usbhid/usbhid.h" + +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Anssi Hannula "); +MODULE_DESCRIPTION("Force feedback support for Holtek On Line Grip based devices"); + +/* + * These commands and parameters are currently known: + * + * byte 0: command id: + * 01 set effect parameters + * 02 play specified effect + * 03 stop specified effect + * 04 stop all effects + * 06 stop all effects + * (the difference between 04 and 06 isn't known; win driver + * sends 06,04 on application init, and 06 otherwise) + * + * Commands 01 and 02 need to be sent as pairs, i.e. you need to send 01 + * before each 02. + * + * The rest of the bytes are parameters. Command 01 takes all of them, and + * commands 02,03 take only the effect id. + * + * byte 1: + * bits 0-3: effect id: + * 1: very strong rumble + * 2: periodic rumble, short intervals + * 3: very strong rumble + * 4: periodic rumble, long intervals + * 5: weak periodic rumble, long intervals + * 6: weak periodic rumble, short intervals + * 7: periodic rumble, short intervals + * 8: strong periodic rumble, short intervals + * 9: very strong rumble + * a: causes an error + * b: very strong periodic rumble, very short intervals + * c-f: nothing + * bit 6: right (weak) motor enabled + * bit 7: left (strong) motor enabled + * + * bytes 2-3: time in milliseconds, big-endian + * bytes 5-6: unknown (win driver seems to use at least 10e0 with effect 1 + * and 0014 with effect 6) + * byte 7: + * bits 0-3: effect magnitude + */ + +#define HOLTEKFF_MSG_LENGTH 7 + +static const u8 start_effect_1[] = { 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 }; +static const u8 stop_all4[] = { 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +static const u8 stop_all6[] = { 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + +struct holtekff_device { + struct hid_field *field; +}; + +static void holtekff_send(struct holtekff_device *holtekff, + struct hid_device *hid, + const u8 data[HOLTEKFF_MSG_LENGTH]) +{ + int i; + + for (i = 0; i < HOLTEKFF_MSG_LENGTH; i++) { + holtekff->field->value[i] = data[i]; + } + + dbg_hid("sending %02x %02x %02x %02x %02x %02x %02x\n", data[0], + data[1], data[2], data[3], data[4], data[5], data[6]); + + usbhid_submit_report(hid, holtekff->field->report, USB_DIR_OUT); +} + +static int holtekff_play(struct input_dev *dev, void *data, + struct ff_effect *effect) +{ + struct hid_device *hid = input_get_drvdata(dev); + struct holtekff_device *holtekff = data; + int left, right; + /* effect type 1, length 65535 msec */ + u8 buf[HOLTEKFF_MSG_LENGTH] = + { 0x01, 0x01, 0xff, 0xff, 0x10, 0xe0, 0x00 }; + + left = effect->u.rumble.strong_magnitude; + right = effect->u.rumble.weak_magnitude; + dbg_hid("called with 0x%04x 0x%04x\n", left, right); + + if (!left && !right) { + holtekff_send(holtekff, hid, stop_all6); + return 0; + } + + if (left) + buf[1] |= 0x80; + if (right) + buf[1] |= 0x40; + + /* The device takes a single magnitude, so we just sum them up. */ + buf[6] = min(0xf, (left >> 12) + (right >> 12)); + + holtekff_send(holtekff, hid, buf); + holtekff_send(holtekff, hid, start_effect_1); + + return 0; +} + +static int holtekff_init(struct hid_device *hid) +{ + struct holtekff_device *holtekff; + struct hid_report *report; + struct hid_input *hidinput = list_entry(hid->inputs.next, + struct hid_input, list); + struct list_head *report_list = + &hid->report_enum[HID_OUTPUT_REPORT].report_list; + struct input_dev *dev = hidinput->input; + int error; + + if (list_empty(report_list)) { + hid_err(hid, "no output report found\n"); + return -ENODEV; + } + + report = list_entry(report_list->next, struct hid_report, list); + + if (report->maxfield < 1 || report->field[0]->report_count != 7) { + hid_err(hid, "unexpected output report layout\n"); + return -ENODEV; + } + + holtekff = kzalloc(sizeof(*holtekff), GFP_KERNEL); + if (!holtekff) + return -ENOMEM; + + set_bit(FF_RUMBLE, dev->ffbit); + + holtekff->field = report->field[0]; + + /* initialize the same way as win driver does */ + holtekff_send(holtekff, hid, stop_all4); + holtekff_send(holtekff, hid, stop_all6); + + error = input_ff_create_memless(dev, holtekff, holtekff_play); + if (error) { + kfree(holtekff); + return error; + } + + hid_info(hid, "Force feedback for Holtek On Line Grip based devices by Anssi Hannula \n"); + + return 0; +} +#else +static inline int holtekff_init(struct hid_device *hid) +{ + return 0; +} +#endif + +static int holtek_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; + } + + ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF); + if (ret) { + hid_err(hdev, "hw start failed\n"); + goto err; + } + + holtekff_init(hdev); + + return 0; +err: + return ret; +} + +static const struct hid_device_id holtek_devices[] = { + { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK, USB_DEVICE_ID_HOLTEK_ON_LINE_GRIP) }, + { } +}; +MODULE_DEVICE_TABLE(hid, holtek_devices); + +static struct hid_driver holtek_driver = { + .name = "holtek", + .id_table = holtek_devices, + .probe = holtek_probe, +}; + +static int __init holtek_init(void) +{ + return hid_register_driver(&holtek_driver); +} + +static void __exit holtek_exit(void) +{ + hid_unregister_driver(&holtek_driver); +} + +module_init(holtek_init); +module_exit(holtek_exit); + diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index e8faee4..0c1cafa 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -347,6 +347,9 @@ #define USB_VENDOR_ID_ILITEK 0x222a #define USB_DEVICE_ID_ILITEK_MULTITOUCH 0x0001 +#define USB_VENDOR_ID_HOLTEK 0x1241 +#define USB_DEVICE_ID_HOLTEK_ON_LINE_GRIP 0x5015 + #define USB_VENDOR_ID_IMATION 0x0718 #define USB_DEVICE_ID_DISC_STAKKA 0xd000 -- cgit v1.1 From fb51b44385a0ded0d629d5cf4a2095f80fb01b56 Mon Sep 17 00:00:00 2001 From: David Herrmann Date: Tue, 5 Jul 2011 13:45:08 +0200 Subject: HID: wiimote: Add Nintendo Wii Remote driver stub Add stub driver for the Nintendo Wii Remote. The wii remote uses the HID protocol to communicate with the host over bluetooth. Hence, add dependency for HIDP and place driver in hid subsystem. Signed-off-by: David Herrmann Signed-off-by: Jiri Kosina --- drivers/hid/Kconfig | 6 ++++++ drivers/hid/Makefile | 1 + drivers/hid/hid-wiimote.c | 32 ++++++++++++++++++++++++++++++++ 3 files changed, 39 insertions(+) create mode 100644 drivers/hid/hid-wiimote.c (limited to 'drivers/hid') diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index 36ca465..df50c25 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig @@ -568,6 +568,12 @@ config HID_WACOM_POWER_SUPPLY Say Y here if you want to enable power supply status monitoring for Wacom Bluetooth devices. +config HID_WIIMOTE + tristate "Nintendo Wii Remote support" + depends on BT_HIDP + ---help--- + Support for the Nintendo Wii Remote bluetooth device. + config HID_ZEROPLUS tristate "Zeroplus based game controller support" depends on USB_HID diff --git a/drivers/hid/Makefile b/drivers/hid/Makefile index f8cc4ea..4ed9bed 100644 --- a/drivers/hid/Makefile +++ b/drivers/hid/Makefile @@ -73,6 +73,7 @@ obj-$(CONFIG_HID_ZEROPLUS) += hid-zpff.o obj-$(CONFIG_HID_ZYDACRON) += hid-zydacron.o obj-$(CONFIG_HID_WACOM) += hid-wacom.o obj-$(CONFIG_HID_WALTOP) += hid-waltop.o +obj-$(CONFIG_HID_WIIMOTE) += hid-wiimote.o obj-$(CONFIG_USB_HID) += usbhid/ obj-$(CONFIG_USB_MOUSE) += usbhid/ diff --git a/drivers/hid/hid-wiimote.c b/drivers/hid/hid-wiimote.c new file mode 100644 index 0000000..8a770e6 --- /dev/null +++ b/drivers/hid/hid-wiimote.c @@ -0,0 +1,32 @@ +/* + * HID driver for Nintendo Wiimote devices + * Copyright (c) 2011 David Herrmann + */ + +/* + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + */ + +#include + +#define WIIMOTE_VERSION "0.1" +#define WIIMOTE_NAME "Nintendo Wii Remote" + +static int __init wiimote_init(void) +{ + return 0; +} + +static void __exit wiimote_exit(void) +{ +} + +module_init(wiimote_init); +module_exit(wiimote_exit); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("David Herrmann "); +MODULE_DESCRIPTION(WIIMOTE_NAME " Device Driver"); +MODULE_VERSION(WIIMOTE_VERSION); -- cgit v1.1 From 02fb72a06ae1ed55b4373a4c678f25d70fd65902 Mon Sep 17 00:00:00 2001 From: David Herrmann Date: Tue, 5 Jul 2011 13:45:09 +0200 Subject: HID: wiimote: Register wiimote hid driver stub The wiimote uses a fake HID protocol. Hence, we need to prevent HIDINPUT and HIDDEV from parsing wiimote data and instead parse raw hid events. Add VID/PID to hid-core so the special driver is loaded on new wiimotes. Signed-off-by: David Herrmann Signed-off-by: Jiri Kosina --- drivers/hid/hid-core.c | 1 + drivers/hid/hid-ids.h | 3 +++ drivers/hid/hid-wiimote.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 65 insertions(+), 1 deletion(-) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 6f3289a..eccaf8a 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1504,6 +1504,7 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_ZYDACRON, USB_DEVICE_ID_ZYDACRON_REMOTE_CONTROL) }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_BT) }, + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_NINTENDO, USB_DEVICE_ID_NINTENDO_WIIMOTE) }, { } }; diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index a756ee6..dfe2528 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -495,6 +495,9 @@ #define USB_VENDOR_ID_NEXTWINDOW 0x1926 #define USB_DEVICE_ID_NEXTWINDOW_TOUCHSCREEN 0x0003 +#define USB_VENDOR_ID_NINTENDO 0x057e +#define USB_DEVICE_ID_NINTENDO_WIIMOTE 0x0306 + #define USB_VENDOR_ID_NTRIG 0x1b96 #define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN 0x0001 #define USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_1 0x0003 diff --git a/drivers/hid/hid-wiimote.c b/drivers/hid/hid-wiimote.c index 8a770e6..ed4fe18 100644 --- a/drivers/hid/hid-wiimote.c +++ b/drivers/hid/hid-wiimote.c @@ -10,18 +10,78 @@ * any later version. */ +#include #include +#include "hid-ids.h" #define WIIMOTE_VERSION "0.1" #define WIIMOTE_NAME "Nintendo Wii Remote" -static int __init wiimote_init(void) +static int wiimote_hid_event(struct hid_device *hdev, struct hid_report *report, + u8 *raw_data, int size) +{ + if (size < 1) + return -EINVAL; + + return 0; +} + +static int wiimote_hid_probe(struct hid_device *hdev, + const struct hid_device_id *id) { + int ret; + + ret = hid_parse(hdev); + if (ret) { + hid_err(hdev, "HID parse failed\n"); + return ret; + } + + ret = hid_hw_start(hdev, HID_CONNECT_HIDRAW); + if (ret) { + hid_err(hdev, "HW start failed\n"); + return ret; + } + + hid_info(hdev, "New device registered\n"); return 0; } +static void wiimote_hid_remove(struct hid_device *hdev) +{ + hid_info(hdev, "Device removed\n"); + hid_hw_stop(hdev); +} + +static const struct hid_device_id wiimote_hid_devices[] = { + { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_NINTENDO, + USB_DEVICE_ID_NINTENDO_WIIMOTE) }, + { } +}; +MODULE_DEVICE_TABLE(hid, wiimote_hid_devices); + +static struct hid_driver wiimote_hid_driver = { + .name = "wiimote", + .id_table = wiimote_hid_devices, + .probe = wiimote_hid_probe, + .remove = wiimote_hid_remove, + .raw_event = wiimote_hid_event, +}; + +static int __init wiimote_init(void) +{ + int ret; + + ret = hid_register_driver(&wiimote_hid_driver); + if (ret) + pr_err("Can't register wiimote hid driver\n"); + + return ret; +} + static void __exit wiimote_exit(void) { + hid_unregister_driver(&wiimote_hid_driver); } module_init(wiimote_init); -- cgit v1.1 From e894d0e3e06650510c70e50b317dfaba5295f4db Mon Sep 17 00:00:00 2001 From: David Herrmann Date: Tue, 5 Jul 2011 13:45:10 +0200 Subject: HID: wiimote: Add wiimote device structure Allocate wiimote device structure with all wiimote related data when registering new wiimote devices. Signed-off-by: David Herrmann Signed-off-by: Jiri Kosina --- drivers/hid/hid-wiimote.c | 41 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-wiimote.c b/drivers/hid/hid-wiimote.c index ed4fe18..ff7cf12 100644 --- a/drivers/hid/hid-wiimote.c +++ b/drivers/hid/hid-wiimote.c @@ -17,6 +17,10 @@ #define WIIMOTE_VERSION "0.1" #define WIIMOTE_NAME "Nintendo Wii Remote" +struct wiimote_data { + struct hid_device *hdev; +}; + static int wiimote_hid_event(struct hid_device *hdev, struct hid_report *report, u8 *raw_data, int size) { @@ -26,31 +30,64 @@ static int wiimote_hid_event(struct hid_device *hdev, struct hid_report *report, return 0; } +static struct wiimote_data *wiimote_create(struct hid_device *hdev) +{ + struct wiimote_data *wdata; + + wdata = kzalloc(sizeof(*wdata), GFP_KERNEL); + if (!wdata) + return NULL; + + wdata->hdev = hdev; + hid_set_drvdata(hdev, wdata); + + return wdata; +} + +static void wiimote_destroy(struct wiimote_data *wdata) +{ + kfree(wdata); +} + static int wiimote_hid_probe(struct hid_device *hdev, const struct hid_device_id *id) { + struct wiimote_data *wdata; int ret; + wdata = wiimote_create(hdev); + if (!wdata) { + hid_err(hdev, "Can't alloc device\n"); + return -ENOMEM; + } + ret = hid_parse(hdev); if (ret) { hid_err(hdev, "HID parse failed\n"); - return ret; + goto err; } ret = hid_hw_start(hdev, HID_CONNECT_HIDRAW); if (ret) { hid_err(hdev, "HW start failed\n"); - return ret; + goto err; } hid_info(hdev, "New device registered\n"); return 0; + +err: + wiimote_destroy(wdata); + return ret; } static void wiimote_hid_remove(struct hid_device *hdev) { + struct wiimote_data *wdata = hid_get_drvdata(hdev); + hid_info(hdev, "Device removed\n"); hid_hw_stop(hdev); + wiimote_destroy(wdata); } static const struct hid_device_id wiimote_hid_devices[] = { -- cgit v1.1 From 672bc4e090c9a2c655c28f8295e981609a1b84ba Mon Sep 17 00:00:00 2001 From: David Herrmann Date: Tue, 5 Jul 2011 13:45:11 +0200 Subject: HID: wiimote: Register input device in wiimote hid driver Register input device so the wiimote can report input events on it. We do not use HIDINPUT because the wiimote does not provide any descriptor table which might be used by HIDINPUT. So we avoid having HIDINPUT parse the wiimote descriptor and create unrelated or unknown event flags. Instead we register our own input device that we have full control of. Signed-off-by: David Herrmann Signed-off-by: Jiri Kosina --- drivers/hid/hid-wiimote.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-wiimote.c b/drivers/hid/hid-wiimote.c index ff7cf12..deaf232 100644 --- a/drivers/hid/hid-wiimote.c +++ b/drivers/hid/hid-wiimote.c @@ -10,7 +10,9 @@ * any later version. */ +#include #include +#include #include #include "hid-ids.h" @@ -19,8 +21,15 @@ struct wiimote_data { struct hid_device *hdev; + struct input_dev *input; }; +static int wiimote_input_event(struct input_dev *dev, unsigned int type, + unsigned int code, int value) +{ + return 0; +} + static int wiimote_hid_event(struct hid_device *hdev, struct hid_report *report, u8 *raw_data, int size) { @@ -38,9 +47,24 @@ static struct wiimote_data *wiimote_create(struct hid_device *hdev) if (!wdata) return NULL; + wdata->input = input_allocate_device(); + if (!wdata->input) { + kfree(wdata); + return NULL; + } + wdata->hdev = hdev; hid_set_drvdata(hdev, wdata); + input_set_drvdata(wdata->input, wdata); + wdata->input->event = wiimote_input_event; + wdata->input->dev.parent = &wdata->hdev->dev; + wdata->input->id.bustype = wdata->hdev->bus; + wdata->input->id.vendor = wdata->hdev->vendor; + wdata->input->id.product = wdata->hdev->product; + wdata->input->id.version = wdata->hdev->version; + wdata->input->name = WIIMOTE_NAME; + return wdata; } @@ -73,10 +97,19 @@ static int wiimote_hid_probe(struct hid_device *hdev, goto err; } + ret = input_register_device(wdata->input); + if (ret) { + hid_err(hdev, "Cannot register input device\n"); + goto err_stop; + } + hid_info(hdev, "New device registered\n"); return 0; +err_stop: + hid_hw_stop(hdev); err: + input_free_device(wdata->input); wiimote_destroy(wdata); return ret; } @@ -87,6 +120,7 @@ static void wiimote_hid_remove(struct hid_device *hdev) hid_info(hdev, "Device removed\n"); hid_hw_stop(hdev); + input_unregister_device(wdata->input); wiimote_destroy(wdata); } -- cgit v1.1 From 4d36e9754f6b71870a476e84f418a864c2ddf77c Mon Sep 17 00:00:00 2001 From: David Herrmann Date: Tue, 5 Jul 2011 13:45:12 +0200 Subject: HID: wiimote: Synchronize wiimote input and hid event handling The wiimote first starts HID hardware and then registers the input device. We need to synchronize the startup so no event handler will start parsing events when the wiimote device is not ready, yet. Signed-off-by: David Herrmann Signed-off-by: Jiri Kosina --- drivers/hid/hid-wiimote.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-wiimote.c b/drivers/hid/hid-wiimote.c index deaf232..3416f69 100644 --- a/drivers/hid/hid-wiimote.c +++ b/drivers/hid/hid-wiimote.c @@ -10,6 +10,7 @@ * any later version. */ +#include #include #include #include @@ -20,6 +21,7 @@ #define WIIMOTE_NAME "Nintendo Wii Remote" struct wiimote_data { + atomic_t ready; struct hid_device *hdev; struct input_dev *input; }; @@ -27,12 +29,26 @@ struct wiimote_data { static int wiimote_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) { + struct wiimote_data *wdata = input_get_drvdata(dev); + + if (!atomic_read(&wdata->ready)) + return -EBUSY; + /* smp_rmb: Make sure wdata->xy is available when wdata->ready is 1 */ + smp_rmb(); + return 0; } static int wiimote_hid_event(struct hid_device *hdev, struct hid_report *report, u8 *raw_data, int size) { + struct wiimote_data *wdata = hid_get_drvdata(hdev); + + if (!atomic_read(&wdata->ready)) + return -EBUSY; + /* smp_rmb: Make sure wdata->xy is available when wdata->ready is 1 */ + smp_rmb(); + if (size < 1) return -EINVAL; @@ -103,6 +119,9 @@ static int wiimote_hid_probe(struct hid_device *hdev, goto err_stop; } + /* smp_wmb: Write wdata->xy first before wdata->ready is set to 1 */ + smp_wmb(); + atomic_set(&wdata->ready, 1); hid_info(hdev, "New device registered\n"); return 0; -- cgit v1.1 From 0c218f14487fd67e60059458c48b43cc3d36b96e Mon Sep 17 00:00:00 2001 From: David Herrmann Date: Tue, 5 Jul 2011 13:45:13 +0200 Subject: HID: wiimote: Add wiimote send function The wiimote driver needs to send raw output reports to the wiimote device. Otherwise we could not manage the peripherals of the wiimote or perform memory operations on the wiimote. We cannot use hidinput_input_event of the lowlevel hid driver, since this does not accept raw input. Therefore, we need to use the same function that hidraw uses to send output. Side effect is, the raw output function is not buffered and can sleep. Signed-off-by: David Herrmann Signed-off-by: Jiri Kosina --- drivers/hid/hid-wiimote.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-wiimote.c b/drivers/hid/hid-wiimote.c index 3416f69..811ed89 100644 --- a/drivers/hid/hid-wiimote.c +++ b/drivers/hid/hid-wiimote.c @@ -26,6 +26,25 @@ struct wiimote_data { struct input_dev *input; }; +static ssize_t wiimote_hid_send(struct hid_device *hdev, __u8 *buffer, + size_t count) +{ + __u8 *buf; + ssize_t ret; + + if (!hdev->hid_output_raw_report) + return -ENODEV; + + buf = kmemdup(buffer, count, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + ret = hdev->hid_output_raw_report(hdev, buf, count, HID_OUTPUT_REPORT); + + kfree(buf); + return ret; +} + static int wiimote_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) { -- cgit v1.1 From 23c063cb02b69244bbc215cb81c2cad0208fbecf Mon Sep 17 00:00:00 2001 From: David Herrmann Date: Tue, 5 Jul 2011 13:45:14 +0200 Subject: HID: wiimote: Add output queue for wiimote driver The raw hid output function that is supported by bluetooth low-level hid driver does not provide an output queue and also may sleep. The wiimote driver, though, may need to send data in atomic context so this patch adds a buffered output queue for the wiimote driver. We use the shared workqueue to send our buffer to the hid device. There is always only one active worker which flushes the whole output queue to the device. If our queue is full, every further output is discarded. Special care is needed in the deinitialization routine. When wiimote_hid_remove is called, HID input is already disabled, but HID output may still be used from our worker and is then discarded by the lower HID layers. Therefore, we can safely disable the input layer since it is the only layer that still sends input events. Future sysfs attributes must be freed before unregistering input to avoid the sysfs handlers to send input events to a non-existing input layer. Signed-off-by: David Herrmann Signed-off-by: Jiri Kosina --- drivers/hid/hid-wiimote.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 78 insertions(+) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-wiimote.c b/drivers/hid/hid-wiimote.c index 811ed89..bfc5049 100644 --- a/drivers/hid/hid-wiimote.c +++ b/drivers/hid/hid-wiimote.c @@ -15,15 +15,28 @@ #include #include #include +#include #include "hid-ids.h" #define WIIMOTE_VERSION "0.1" #define WIIMOTE_NAME "Nintendo Wii Remote" +#define WIIMOTE_BUFSIZE 32 + +struct wiimote_buf { + __u8 data[HID_MAX_BUFFER_SIZE]; + size_t size; +}; struct wiimote_data { atomic_t ready; struct hid_device *hdev; struct input_dev *input; + + spinlock_t qlock; + __u8 head; + __u8 tail; + struct wiimote_buf outq[WIIMOTE_BUFSIZE]; + struct work_struct worker; }; static ssize_t wiimote_hid_send(struct hid_device *hdev, __u8 *buffer, @@ -45,6 +58,65 @@ static ssize_t wiimote_hid_send(struct hid_device *hdev, __u8 *buffer, return ret; } +static void wiimote_worker(struct work_struct *work) +{ + struct wiimote_data *wdata = container_of(work, struct wiimote_data, + worker); + unsigned long flags; + + spin_lock_irqsave(&wdata->qlock, flags); + + while (wdata->head != wdata->tail) { + spin_unlock_irqrestore(&wdata->qlock, flags); + wiimote_hid_send(wdata->hdev, wdata->outq[wdata->tail].data, + wdata->outq[wdata->tail].size); + spin_lock_irqsave(&wdata->qlock, flags); + + wdata->tail = (wdata->tail + 1) % WIIMOTE_BUFSIZE; + } + + spin_unlock_irqrestore(&wdata->qlock, flags); +} + +static void wiimote_queue(struct wiimote_data *wdata, const __u8 *buffer, + size_t count) +{ + unsigned long flags; + __u8 newhead; + + if (count > HID_MAX_BUFFER_SIZE) { + hid_warn(wdata->hdev, "Sending too large output report\n"); + return; + } + + /* + * Copy new request into our output queue and check whether the + * queue is full. If it is full, discard this request. + * If it is empty we need to start a new worker that will + * send out the buffer to the hid device. + * If the queue is not empty, then there must be a worker + * that is currently sending out our buffer and this worker + * will reschedule itself until the queue is empty. + */ + + spin_lock_irqsave(&wdata->qlock, flags); + + memcpy(wdata->outq[wdata->head].data, buffer, count); + wdata->outq[wdata->head].size = count; + newhead = (wdata->head + 1) % WIIMOTE_BUFSIZE; + + if (wdata->head == wdata->tail) { + wdata->head = newhead; + schedule_work(&wdata->worker); + } else if (newhead != wdata->tail) { + wdata->head = newhead; + } else { + hid_warn(wdata->hdev, "Output queue is full"); + } + + spin_unlock_irqrestore(&wdata->qlock, flags); +} + static int wiimote_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) { @@ -100,6 +172,9 @@ static struct wiimote_data *wiimote_create(struct hid_device *hdev) wdata->input->id.version = wdata->hdev->version; wdata->input->name = WIIMOTE_NAME; + spin_lock_init(&wdata->qlock); + INIT_WORK(&wdata->worker, wiimote_worker); + return wdata; } @@ -157,8 +232,11 @@ static void wiimote_hid_remove(struct hid_device *hdev) struct wiimote_data *wdata = hid_get_drvdata(hdev); hid_info(hdev, "Device removed\n"); + hid_hw_stop(hdev); input_unregister_device(wdata->input); + + cancel_work_sync(&wdata->worker); wiimote_destroy(wdata); } -- cgit v1.1 From a4d19197627e2a8645cccd9039edf513c6384297 Mon Sep 17 00:00:00 2001 From: David Herrmann Date: Tue, 5 Jul 2011 13:45:15 +0200 Subject: HID: wiimote: Add wiimote event handler Create array of all event handlers and call each handler when we receive the related event. Signed-off-by: David Herrmann Signed-off-by: Jiri Kosina --- drivers/hid/hid-wiimote.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-wiimote.c b/drivers/hid/hid-wiimote.c index bfc5049..c86ae92 100644 --- a/drivers/hid/hid-wiimote.c +++ b/drivers/hid/hid-wiimote.c @@ -130,10 +130,22 @@ static int wiimote_input_event(struct input_dev *dev, unsigned int type, return 0; } +struct wiiproto_handler { + __u8 id; + size_t size; + void (*func)(struct wiimote_data *wdata, const __u8 *payload); +}; + +static struct wiiproto_handler handlers[] = { + { .id = 0 } +}; + static int wiimote_hid_event(struct hid_device *hdev, struct hid_report *report, u8 *raw_data, int size) { struct wiimote_data *wdata = hid_get_drvdata(hdev); + struct wiiproto_handler *h; + int i; if (!atomic_read(&wdata->ready)) return -EBUSY; @@ -143,6 +155,12 @@ static int wiimote_hid_event(struct hid_device *hdev, struct hid_report *report, if (size < 1) return -EINVAL; + for (i = 0; handlers[i].id; ++i) { + h = &handlers[i]; + if (h->id == raw_data[0] && h->size < size) + h->func(wdata, &raw_data[1]); + } + return 0; } -- cgit v1.1 From 1abb9ad389f037612b6ba6b0dede2095c59cd2fa Mon Sep 17 00:00:00 2001 From: David Herrmann Date: Tue, 5 Jul 2011 13:45:16 +0200 Subject: HID: wiimote: Add wiimote input button parser Parse input report 0x30 from the wiimote as button input. We need to send events for all buttons on every input report because the wiimote does not send events for single buttons but always for all buttons to us. The input layer, however, filters redundant events. Signed-off-by: David Herrmann Signed-off-by: Jiri Kosina --- drivers/hid/hid-wiimote.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-wiimote.c b/drivers/hid/hid-wiimote.c index c86ae92..efdf62b 100644 --- a/drivers/hid/hid-wiimote.c +++ b/drivers/hid/hid-wiimote.c @@ -39,6 +39,39 @@ struct wiimote_data { struct work_struct worker; }; +enum wiiproto_reqs { + WIIPROTO_REQ_DRM_K = 0x30, +}; + +enum wiiproto_keys { + WIIPROTO_KEY_LEFT, + WIIPROTO_KEY_RIGHT, + WIIPROTO_KEY_UP, + WIIPROTO_KEY_DOWN, + WIIPROTO_KEY_PLUS, + WIIPROTO_KEY_MINUS, + WIIPROTO_KEY_ONE, + WIIPROTO_KEY_TWO, + WIIPROTO_KEY_A, + WIIPROTO_KEY_B, + WIIPROTO_KEY_HOME, + WIIPROTO_KEY_COUNT +}; + +static __u16 wiiproto_keymap[] = { + KEY_LEFT, /* WIIPROTO_KEY_LEFT */ + KEY_RIGHT, /* WIIPROTO_KEY_RIGHT */ + KEY_UP, /* WIIPROTO_KEY_UP */ + KEY_DOWN, /* WIIPROTO_KEY_DOWN */ + KEY_NEXT, /* WIIPROTO_KEY_PLUS */ + KEY_PREVIOUS, /* WIIPROTO_KEY_MINUS */ + BTN_1, /* WIIPROTO_KEY_ONE */ + BTN_2, /* WIIPROTO_KEY_TWO */ + BTN_A, /* WIIPROTO_KEY_A */ + BTN_B, /* WIIPROTO_KEY_B */ + BTN_MODE, /* WIIPROTO_KEY_HOME */ +}; + static ssize_t wiimote_hid_send(struct hid_device *hdev, __u8 *buffer, size_t count) { @@ -130,6 +163,33 @@ static int wiimote_input_event(struct input_dev *dev, unsigned int type, return 0; } +static void handler_keys(struct wiimote_data *wdata, const __u8 *payload) +{ + input_report_key(wdata->input, wiiproto_keymap[WIIPROTO_KEY_LEFT], + !!(payload[0] & 0x01)); + input_report_key(wdata->input, wiiproto_keymap[WIIPROTO_KEY_RIGHT], + !!(payload[0] & 0x02)); + input_report_key(wdata->input, wiiproto_keymap[WIIPROTO_KEY_DOWN], + !!(payload[0] & 0x04)); + input_report_key(wdata->input, wiiproto_keymap[WIIPROTO_KEY_UP], + !!(payload[0] & 0x08)); + input_report_key(wdata->input, wiiproto_keymap[WIIPROTO_KEY_PLUS], + !!(payload[0] & 0x10)); + input_report_key(wdata->input, wiiproto_keymap[WIIPROTO_KEY_TWO], + !!(payload[1] & 0x01)); + input_report_key(wdata->input, wiiproto_keymap[WIIPROTO_KEY_ONE], + !!(payload[1] & 0x02)); + input_report_key(wdata->input, wiiproto_keymap[WIIPROTO_KEY_B], + !!(payload[1] & 0x04)); + input_report_key(wdata->input, wiiproto_keymap[WIIPROTO_KEY_A], + !!(payload[1] & 0x08)); + input_report_key(wdata->input, wiiproto_keymap[WIIPROTO_KEY_MINUS], + !!(payload[1] & 0x10)); + input_report_key(wdata->input, wiiproto_keymap[WIIPROTO_KEY_HOME], + !!(payload[1] & 0x80)); + input_sync(wdata->input); +} + struct wiiproto_handler { __u8 id; size_t size; @@ -137,6 +197,7 @@ struct wiiproto_handler { }; static struct wiiproto_handler handlers[] = { + { .id = WIIPROTO_REQ_DRM_K, .size = 2, .func = handler_keys }, { .id = 0 } }; @@ -167,6 +228,7 @@ static int wiimote_hid_event(struct hid_device *hdev, struct hid_report *report, static struct wiimote_data *wiimote_create(struct hid_device *hdev) { struct wiimote_data *wdata; + int i; wdata = kzalloc(sizeof(*wdata), GFP_KERNEL); if (!wdata) @@ -190,6 +252,10 @@ static struct wiimote_data *wiimote_create(struct hid_device *hdev) wdata->input->id.version = wdata->hdev->version; wdata->input->name = WIIMOTE_NAME; + set_bit(EV_KEY, wdata->input->evbit); + for (i = 0; i < WIIPROTO_KEY_COUNT; ++i) + set_bit(wiiproto_keymap[i], wdata->input->keybit); + spin_lock_init(&wdata->qlock); INIT_WORK(&wdata->worker, wiimote_worker); -- cgit v1.1 From db3083467f1527816fca95ae2d8bfe5d81503a8e Mon Sep 17 00:00:00 2001 From: David Herrmann Date: Tue, 5 Jul 2011 13:45:17 +0200 Subject: HID: wiimote: Add wiimote led request Add new request that sets the leds on the target device. Also, per default, set led1 after initializing a device. Signed-off-by: David Herrmann Signed-off-by: Jiri Kosina --- drivers/hid/hid-wiimote.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-wiimote.c b/drivers/hid/hid-wiimote.c index efdf62b..3fb18fb 100644 --- a/drivers/hid/hid-wiimote.c +++ b/drivers/hid/hid-wiimote.c @@ -39,7 +39,13 @@ struct wiimote_data { struct work_struct worker; }; +#define WIIPROTO_FLAG_LED1 0x01 +#define WIIPROTO_FLAG_LED2 0x02 +#define WIIPROTO_FLAG_LED3 0x04 +#define WIIPROTO_FLAG_LED4 0x08 + enum wiiproto_reqs { + WIIPROTO_REQ_LED = 0x11, WIIPROTO_REQ_DRM_K = 0x30, }; @@ -150,6 +156,25 @@ static void wiimote_queue(struct wiimote_data *wdata, const __u8 *buffer, spin_unlock_irqrestore(&wdata->qlock, flags); } +static void wiiproto_req_leds(struct wiimote_data *wdata, int leds) +{ + __u8 cmd[2]; + + cmd[0] = WIIPROTO_REQ_LED; + cmd[1] = 0; + + if (leds & WIIPROTO_FLAG_LED1) + cmd[1] |= 0x10; + if (leds & WIIPROTO_FLAG_LED2) + cmd[1] |= 0x20; + if (leds & WIIPROTO_FLAG_LED3) + cmd[1] |= 0x40; + if (leds & WIIPROTO_FLAG_LED4) + cmd[1] |= 0x80; + + wiimote_queue(wdata, cmd, sizeof(cmd)); +} + static int wiimote_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) { @@ -301,6 +326,7 @@ static int wiimote_hid_probe(struct hid_device *hdev, smp_wmb(); atomic_set(&wdata->ready, 1); hid_info(hdev, "New device registered\n"); + wiiproto_req_leds(wdata, WIIPROTO_FLAG_LED1); return 0; err_stop: -- cgit v1.1 From 32a0d9a522b577d0efa6ce793a6ac0516c5e3627 Mon Sep 17 00:00:00 2001 From: David Herrmann Date: Tue, 5 Jul 2011 13:45:18 +0200 Subject: HID: wiimote: Cache wiimote led state Save the current state of the leds in the wiimote data structure. This allows us to discard new led requests that wouldn't change anything. Protect the whole state structure by a spinlock. Every wiiproto_* function expects this spinlock to be held when called. Signed-off-by: David Herrmann Signed-off-by: Jiri Kosina --- drivers/hid/hid-wiimote.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-wiimote.c b/drivers/hid/hid-wiimote.c index 3fb18fb..f9a3bcb 100644 --- a/drivers/hid/hid-wiimote.c +++ b/drivers/hid/hid-wiimote.c @@ -27,6 +27,11 @@ struct wiimote_buf { size_t size; }; +struct wiimote_state { + spinlock_t lock; + __u8 flags; +}; + struct wiimote_data { atomic_t ready; struct hid_device *hdev; @@ -37,12 +42,16 @@ struct wiimote_data { __u8 tail; struct wiimote_buf outq[WIIMOTE_BUFSIZE]; struct work_struct worker; + + struct wiimote_state state; }; #define WIIPROTO_FLAG_LED1 0x01 #define WIIPROTO_FLAG_LED2 0x02 #define WIIPROTO_FLAG_LED3 0x04 #define WIIPROTO_FLAG_LED4 0x08 +#define WIIPROTO_FLAGS_LEDS (WIIPROTO_FLAG_LED1 | WIIPROTO_FLAG_LED2 | \ + WIIPROTO_FLAG_LED3 | WIIPROTO_FLAG_LED4) enum wiiproto_reqs { WIIPROTO_REQ_LED = 0x11, @@ -160,6 +169,11 @@ static void wiiproto_req_leds(struct wiimote_data *wdata, int leds) { __u8 cmd[2]; + leds &= WIIPROTO_FLAGS_LEDS; + if ((wdata->state.flags & WIIPROTO_FLAGS_LEDS) == leds) + return; + wdata->state.flags = (wdata->state.flags & ~WIIPROTO_FLAGS_LEDS) | leds; + cmd[0] = WIIPROTO_REQ_LED; cmd[1] = 0; @@ -232,6 +246,7 @@ static int wiimote_hid_event(struct hid_device *hdev, struct hid_report *report, struct wiimote_data *wdata = hid_get_drvdata(hdev); struct wiiproto_handler *h; int i; + unsigned long flags; if (!atomic_read(&wdata->ready)) return -EBUSY; @@ -241,12 +256,16 @@ static int wiimote_hid_event(struct hid_device *hdev, struct hid_report *report, if (size < 1) return -EINVAL; + spin_lock_irqsave(&wdata->state.lock, flags); + for (i = 0; handlers[i].id; ++i) { h = &handlers[i]; if (h->id == raw_data[0] && h->size < size) h->func(wdata, &raw_data[1]); } + spin_unlock_irqrestore(&wdata->state.lock, flags); + return 0; } @@ -284,6 +303,8 @@ static struct wiimote_data *wiimote_create(struct hid_device *hdev) spin_lock_init(&wdata->qlock); INIT_WORK(&wdata->worker, wiimote_worker); + spin_lock_init(&wdata->state.lock); + return wdata; } @@ -326,7 +347,12 @@ static int wiimote_hid_probe(struct hid_device *hdev, smp_wmb(); atomic_set(&wdata->ready, 1); hid_info(hdev, "New device registered\n"); + + /* by default set led1 after device initialization */ + spin_lock_irq(&wdata->state.lock); wiiproto_req_leds(wdata, WIIPROTO_FLAG_LED1); + spin_unlock_irq(&wdata->state.lock); + return 0; err_stop: -- cgit v1.1 From 3c1c2fce64fdfa2f0c0ff4fffb3bb171ea6361ca Mon Sep 17 00:00:00 2001 From: David Herrmann Date: Tue, 5 Jul 2011 13:45:19 +0200 Subject: HID: wiimote: Add sysfs support to wiimote driver Add sysfs files for each led of the wiimote. Writing 1 to the file enables the led and 0 disables the led. We do not need memory barriers when checking wdata->ready since we use a spinlock directly after it. Signed-off-by: David Herrmann Signed-off-by: Jiri Kosina --- drivers/hid/hid-wiimote.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-wiimote.c b/drivers/hid/hid-wiimote.c index f9a3bcb..a594383 100644 --- a/drivers/hid/hid-wiimote.c +++ b/drivers/hid/hid-wiimote.c @@ -87,6 +87,9 @@ static __u16 wiiproto_keymap[] = { BTN_MODE, /* WIIPROTO_KEY_HOME */ }; +#define dev_to_wii(pdev) hid_get_drvdata(container_of(pdev, struct hid_device, \ + dev)) + static ssize_t wiimote_hid_send(struct hid_device *hdev, __u8 *buffer, size_t count) { @@ -189,6 +192,55 @@ static void wiiproto_req_leds(struct wiimote_data *wdata, int leds) wiimote_queue(wdata, cmd, sizeof(cmd)); } +#define wiifs_led_show_set(num) \ +static ssize_t wiifs_led_show_##num(struct device *dev, \ + struct device_attribute *attr, char *buf) \ +{ \ + struct wiimote_data *wdata = dev_to_wii(dev); \ + unsigned long flags; \ + int state; \ + \ + if (!atomic_read(&wdata->ready)) \ + return -EBUSY; \ + \ + spin_lock_irqsave(&wdata->state.lock, flags); \ + state = !!(wdata->state.flags & WIIPROTO_FLAG_LED##num); \ + spin_unlock_irqrestore(&wdata->state.lock, flags); \ + \ + return sprintf(buf, "%d\n", state); \ +} \ +static ssize_t wiifs_led_set_##num(struct device *dev, \ + struct device_attribute *attr, const char *buf, size_t count) \ +{ \ + struct wiimote_data *wdata = dev_to_wii(dev); \ + int tmp = simple_strtoul(buf, NULL, 10); \ + unsigned long flags; \ + __u8 state; \ + \ + if (!atomic_read(&wdata->ready)) \ + return -EBUSY; \ + \ + spin_lock_irqsave(&wdata->state.lock, flags); \ + \ + state = wdata->state.flags; \ + \ + if (tmp) \ + wiiproto_req_leds(wdata, state | WIIPROTO_FLAG_LED##num);\ + else \ + wiiproto_req_leds(wdata, state & ~WIIPROTO_FLAG_LED##num);\ + \ + spin_unlock_irqrestore(&wdata->state.lock, flags); \ + \ + return count; \ +} \ +static DEVICE_ATTR(led##num, S_IRUGO | S_IWUSR, wiifs_led_show_##num, \ + wiifs_led_set_##num) + +wiifs_led_show_set(1); +wiifs_led_show_set(2); +wiifs_led_show_set(3); +wiifs_led_show_set(4); + static int wiimote_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) { @@ -325,6 +377,19 @@ static int wiimote_hid_probe(struct hid_device *hdev, return -ENOMEM; } + ret = device_create_file(&hdev->dev, &dev_attr_led1); + if (ret) + goto err; + ret = device_create_file(&hdev->dev, &dev_attr_led2); + if (ret) + goto err; + ret = device_create_file(&hdev->dev, &dev_attr_led3); + if (ret) + goto err; + ret = device_create_file(&hdev->dev, &dev_attr_led4); + if (ret) + goto err; + ret = hid_parse(hdev); if (ret) { hid_err(hdev, "HID parse failed\n"); @@ -359,6 +424,10 @@ err_stop: hid_hw_stop(hdev); err: input_free_device(wdata->input); + device_remove_file(&hdev->dev, &dev_attr_led1); + device_remove_file(&hdev->dev, &dev_attr_led2); + device_remove_file(&hdev->dev, &dev_attr_led3); + device_remove_file(&hdev->dev, &dev_attr_led4); wiimote_destroy(wdata); return ret; } @@ -369,6 +438,11 @@ static void wiimote_hid_remove(struct hid_device *hdev) hid_info(hdev, "Device removed\n"); + device_remove_file(&hdev->dev, &dev_attr_led1); + device_remove_file(&hdev->dev, &dev_attr_led2); + device_remove_file(&hdev->dev, &dev_attr_led3); + device_remove_file(&hdev->dev, &dev_attr_led4); + hid_hw_stop(hdev); input_unregister_device(wdata->input); -- cgit v1.1 From 6be914f11db8e88d11b08d6c496624dbbd642d80 Mon Sep 17 00:00:00 2001 From: Nikolai Kondrashov Date: Wed, 6 Jul 2011 09:23:41 +0300 Subject: HID: uclogic: Add support for UC-Logic WP1062 Add support for UC-Logic Tablet WP1062 by fixing its report descriptor. This tablet is sold as Monoprice 10X6.25 Inches Graphic Drawing Tablet. Signed-off-by: Nikolai Kondrashov Signed-off-by: Jiri Kosina --- drivers/hid/hid-core.c | 1 + drivers/hid/hid-ids.h | 1 + drivers/hid/hid-uclogic.c | 195 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 197 insertions(+) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index e5ab72a..2a268fc 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1491,6 +1491,7 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U) }, { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U) }, { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U) }, + { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP1062) }, { HID_USB_DEVICE(USB_VENDOR_ID_UNITEC, USB_DEVICE_ID_UNITEC_USB_TOUCH_0709) }, { HID_USB_DEVICE(USB_VENDOR_ID_UNITEC, USB_DEVICE_ID_UNITEC_USB_TOUCH_0A19) }, { HID_USB_DEVICE(USB_VENDOR_ID_WISEGROUP, USB_DEVICE_ID_SMARTJOY_PLUS) }, diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 0c1cafa..8c00e4a 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -629,6 +629,7 @@ #define USB_DEVICE_ID_UCLOGIC_TABLET_WP4030U 0x0003 #define USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U 0x0004 #define USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U 0x0005 +#define USB_DEVICE_ID_UCLOGIC_TABLET_WP1062 0x0064 #define USB_VENDOR_ID_UNITEC 0x227d #define USB_DEVICE_ID_UNITEC_USB_TOUCH_0709 0x0709 diff --git a/drivers/hid/hid-uclogic.c b/drivers/hid/hid-uclogic.c index 05fdc85a..e15732f 100644 --- a/drivers/hid/hid-uclogic.c +++ b/drivers/hid/hid-uclogic.c @@ -343,6 +343,193 @@ static __u8 wp8060u_rdesc_fixed[] = { }; /* + * Original WP1062 report descriptor. + * + * Only report ID 9 is actually used. + * + * Usage Page (Digitizer), ; Digitizer (0Dh) + * Usage (Pen), ; Pen (02h, application collection) + * Collection (Application), + * Report ID (7), + * Usage (Stylus), ; Stylus (20h, logical collection) + * Collection (Physical), + * Usage (Tip Switch), ; Tip switch (42h, momentary control) + * Usage (Barrel Switch), ; Barrel switch (44h, momentary control) + * Usage (Eraser), ; Eraser (45h, momentary control) + * Logical Minimum (0), + * Logical Maximum (1), + * Report Size (1), + * Report Count (3), + * Input (Variable), + * Report Count (3), + * Input (Constant, Variable), + * Usage (In Range), ; In range (32h, momentary control) + * Report Count (1), + * Input (Variable), + * Report Count (1), + * Input (Constant, Variable), + * Usage Page (Desktop), ; Generic desktop controls (01h) + * Usage (X), ; X (30h, dynamic value) + * Report Size (16), + * Report Count (1), + * Push, + * Unit Exponent (13), + * Unit (Inch), + * Physical Minimum (0), + * Physical Maximum (10000), + * Logical Maximum (20000), + * Input (Variable), + * Usage (Y), ; Y (31h, dynamic value) + * Physical Maximum (6583), + * Logical Maximum (13166), + * Input (Variable), + * Pop, + * Usage Page (Digitizer), ; Digitizer (0Dh) + * Usage (Tip Pressure), ; Tip pressure (30h, dynamic value) + * Logical Maximum (1023), + * Input (Variable), + * Report Size (16), + * End Collection, + * End Collection, + * Usage Page (Desktop), ; Generic desktop controls (01h) + * Usage (Mouse), ; Mouse (02h, application collection) + * Collection (Application), + * Report ID (8), + * Usage (Pointer), ; Pointer (01h, physical collection) + * Collection (Physical), + * Usage Page (Button), ; Button (09h) + * Usage Minimum (01h), + * Usage Maximum (03h), + * Logical Minimum (0), + * Logical Maximum (1), + * Report Count (3), + * Report Size (1), + * Input (Variable), + * Report Count (5), + * Input (Constant), + * Usage Page (Desktop), ; Generic desktop controls (01h) + * Usage (X), ; X (30h, dynamic value) + * Usage (Y), ; Y (31h, dynamic value) + * Usage (Wheel), ; Wheel (38h, dynamic value) + * Usage (00h), + * Logical Minimum (-127), + * Logical Maximum (127), + * Report Size (8), + * Report Count (4), + * Input (Variable, Relative), + * End Collection, + * End Collection, + * Usage Page (Desktop), ; Generic desktop controls (01h) + * Usage (Mouse), ; Mouse (02h, application collection) + * Collection (Application), + * Report ID (9), + * Usage (Pointer), ; Pointer (01h, physical collection) + * Collection (Physical), + * Usage Page (Button), ; Button (09h) + * Usage Minimum (01h), + * Usage Maximum (03h), + * Logical Minimum (0), + * Logical Maximum (1), + * Report Count (3), + * Report Size (1), + * Input (Variable), + * Report Count (4), + * Input (Constant), + * Usage Page (Digitizer), ; Digitizer (0Dh) + * Usage (In Range), ; In range (32h, momentary control) + * Report Count (1), + * Input (Variable), + * Usage Page (Desktop), ; Generic desktop controls (01h) + * Usage (X), ; X (30h, dynamic value) + * Report Size (16), + * Report Count (1), + * Push, + * Unit Exponent (13), + * Unit (Inch), + * Physical Minimum (0), + * Physical Maximum (10000), + * Logical Maximum (20000), + * Input (Variable), + * Usage (Y), ; Y (31h, dynamic value) + * Physical Maximum (6583), + * Logical Maximum (13166), + * Input (Variable), + * Pop, + * Usage Page (Digitizer), ; Digitizer (0Dh) + * Usage (Tip Pressure), ; Tip pressure (30h, dynamic value) + * Logical Maximum (1023), + * Report Count (1), + * Report Size (16), + * Input (Variable), + * End Collection, + * End Collection, + * Usage Page (Desktop), ; Generic desktop controls (01h) + * Usage (00h), + * Collection (Application), + * Report ID (4), + * Logical Minimum (0), + * Logical Maximum (255), + * Usage (00h), + * Report Size (8), + * Report Count (3), + * Feature (Variable), + * End Collection + */ + +/* Size of the original descriptor of WP1062 tablet */ +#define WP1062_RDESC_ORIG_SIZE 254 + +/* + * Fixed WP1062 report descriptor. + * + * Removed unused reports, corrected second barrel button usage code, physical + * units. + */ +static __u8 wp1062_rdesc_fixed[] = { + 0x05, 0x0D, /* Usage Page (Digitizer), */ + 0x09, 0x02, /* Usage (Pen), */ + 0xA1, 0x01, /* Collection (Application), */ + 0x85, 0x09, /* Report ID (9), */ + 0x09, 0x20, /* Usage (Stylus), */ + 0xA0, /* Collection (Physical), */ + 0x75, 0x01, /* Report Size (1), */ + 0x09, 0x42, /* Usage (Tip Switch), */ + 0x09, 0x44, /* Usage (Barrel Switch), */ + 0x09, 0x46, /* Usage (Tablet Pick), */ + 0x14, /* Logical Minimum (0), */ + 0x25, 0x01, /* Logical Maximum (1), */ + 0x95, 0x03, /* Report Count (3), */ + 0x81, 0x02, /* Input (Variable), */ + 0x95, 0x04, /* Report Count (4), */ + 0x81, 0x01, /* Input (Constant), */ + 0x09, 0x32, /* Usage (In Range), */ + 0x95, 0x01, /* Report Count (1), */ + 0x81, 0x02, /* Input (Variable), */ + 0x75, 0x10, /* Report Size (16), */ + 0x95, 0x01, /* Report Count (1), */ + 0x14, /* Logical Minimum (0), */ + 0xA4, /* Push, */ + 0x05, 0x01, /* Usage Page (Desktop), */ + 0x55, 0xFD, /* Unit Exponent (-3), */ + 0x65, 0x13, /* Unit (Inch), */ + 0x34, /* Physical Minimum (0), */ + 0x09, 0x30, /* Usage (X), */ + 0x46, 0x10, 0x27, /* Physical Maximum (10000), */ + 0x26, 0x20, 0x4E, /* Logical Maximum (20000), */ + 0x81, 0x02, /* Input (Variable), */ + 0x09, 0x31, /* Usage (Y), */ + 0x46, 0xB7, 0x19, /* Physical Maximum (6583), */ + 0x26, 0x6E, 0x33, /* Logical Maximum (13166), */ + 0x81, 0x02, /* Input (Variable), */ + 0xB4, /* Pop, */ + 0x09, 0x30, /* Usage (Tip Pressure), */ + 0x26, 0xFF, 0x03, /* Logical Maximum (1023), */ + 0x81, 0x02, /* Input (Variable), */ + 0xC0, /* End Collection, */ + 0xC0 /* End Collection */ +}; + +/* * Original PF1209 report descriptor. * * The descriptor is similar to WPXXXXU descriptors, with an addition of a @@ -584,6 +771,12 @@ static __u8 *uclogic_report_fixup(struct hid_device *hdev, __u8 *rdesc, *rsize = sizeof(wp8060u_rdesc_fixed); } break; + case USB_DEVICE_ID_UCLOGIC_TABLET_WP1062: + if (*rsize == WP1062_RDESC_ORIG_SIZE) { + rdesc = wp1062_rdesc_fixed; + *rsize = sizeof(wp1062_rdesc_fixed); + } + break; } return rdesc; @@ -598,6 +791,8 @@ static const struct hid_device_id uclogic_devices[] = { USB_DEVICE_ID_UCLOGIC_TABLET_WP5540U) }, { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, USB_DEVICE_ID_UCLOGIC_TABLET_WP8060U) }, + { HID_USB_DEVICE(USB_VENDOR_ID_UCLOGIC, + USB_DEVICE_ID_UCLOGIC_TABLET_WP1062) }, { } }; MODULE_DEVICE_TABLE(hid, uclogic_devices); -- cgit v1.1 From 23c10becdbc712de3fb35d0c7ec105a81d21f4c7 Mon Sep 17 00:00:00 2001 From: Ari Savolainen Date: Mon, 11 Jul 2011 21:42:52 +0300 Subject: HID: fix horizontal wheel for ms comfort mouse 4500 Microsoft comfort mouse 4500 report descriptor contains duplicate usages for horizontal wheel. This patch fixes the wrong mapping caused by that. Signed-off-by: Ari Savolainen Signed-off-by: Jiri Kosina --- drivers/hid/hid-ids.h | 1 + drivers/hid/hid-microsoft.c | 26 +++++++++++++++++++++----- 2 files changed, 22 insertions(+), 5 deletions(-) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 8c00e4a..2c85947 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -472,6 +472,7 @@ #define USB_DEVICE_ID_MS_PRESENTER_8K_BT 0x0701 #define USB_DEVICE_ID_MS_PRESENTER_8K_USB 0x0713 #define USB_DEVICE_ID_MS_DIGITAL_MEDIA_3K 0x0730 +#define USB_DEVICE_ID_MS_COMFORT_MOUSE_4500 0x076c #define USB_VENDOR_ID_MOJO 0x8282 #define USB_DEVICE_ID_RETRO_ADAPTER 0x3201 diff --git a/drivers/hid/hid-microsoft.c b/drivers/hid/hid-microsoft.c index df91791f..e5c699b 100644 --- a/drivers/hid/hid-microsoft.c +++ b/drivers/hid/hid-microsoft.c @@ -23,11 +23,12 @@ #include "hid-ids.h" -#define MS_HIDINPUT 0x01 -#define MS_ERGONOMY 0x02 -#define MS_PRESENTER 0x04 -#define MS_RDESC 0x08 -#define MS_NOGET 0x10 +#define MS_HIDINPUT 0x01 +#define MS_ERGONOMY 0x02 +#define MS_PRESENTER 0x04 +#define MS_RDESC 0x08 +#define MS_NOGET 0x10 +#define MS_DUPLICATE_USAGES 0x20 /* * Microsoft Wireless Desktop Receiver (Model 1028) has @@ -109,6 +110,18 @@ static int ms_input_mapping(struct hid_device *hdev, struct hid_input *hi, return 0; } +static int ms_input_mapped(struct hid_device *hdev, struct hid_input *hi, + struct hid_field *field, struct hid_usage *usage, + unsigned long **bit, int *max) +{ + unsigned long quirks = (unsigned long)hid_get_drvdata(hdev); + + if (quirks & MS_DUPLICATE_USAGES) + clear_bit(usage->code, *bit); + + return 0; +} + static int ms_event(struct hid_device *hdev, struct hid_field *field, struct hid_usage *usage, __s32 value) { @@ -183,6 +196,8 @@ static const struct hid_device_id ms_devices[] = { .driver_data = MS_ERGONOMY }, { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0), .driver_data = MS_NOGET }, + { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_COMFORT_MOUSE_4500), + .driver_data = MS_DUPLICATE_USAGES }, { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_PRESENTER_8K_BT), .driver_data = MS_PRESENTER }, @@ -195,6 +210,7 @@ static struct hid_driver ms_driver = { .id_table = ms_devices, .report_fixup = ms_report_fixup, .input_mapping = ms_input_mapping, + .input_mapped = ms_input_mapped, .event = ms_event, .probe = ms_probe, }; -- cgit v1.1 From b30d89d1055f9acd14b5eaf82d8f6a4763e91d85 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 14 Jul 2011 13:07:51 +0800 Subject: HID: ACRUX - add missing hid_hw_stop() in ax_probe() error path hid_hw_stop() must be called in ax_probe() error path if hid_hw_start() was successful. Signed-off-by: Axel Lin Signed-off-by: Jiri Kosina --- drivers/hid/hid-axff.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-axff.c b/drivers/hid/hid-axff.c index b455428..1215141 100644 --- a/drivers/hid/hid-axff.c +++ b/drivers/hid/hid-axff.c @@ -154,6 +154,7 @@ static int ax_probe(struct hid_device *hdev, const struct hid_device_id *id) error = hid_hw_open(hdev); if (error) { dev_err(&hdev->dev, "hw open failed\n"); + hid_hw_stop(hdev); return error; } -- cgit v1.1 From 2dcd9543a28da523a179a13b1eefa5f9b8e05d72 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Tue, 19 Jul 2011 16:14:04 +0800 Subject: HID: emsff: properly handle emsff_init failure emsff_init() may fail, let's properly handle the failure. Signed-off-by: Axel Lin Signed-off-by: Jiri Kosina --- drivers/hid/hid-emsff.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-emsff.c b/drivers/hid/hid-emsff.c index 81877c6..a5dc13f 100644 --- a/drivers/hid/hid-emsff.c +++ b/drivers/hid/hid-emsff.c @@ -126,7 +126,12 @@ static int ems_probe(struct hid_device *hdev, const struct hid_device_id *id) goto err; } - emsff_init(hdev); + ret = emsff_init(hdev); + if (ret) { + dev_err(&hdev->dev, "force feedback init failed\n"); + hid_hw_stop(hdev); + goto err; + } return 0; err: -- cgit v1.1 From f4c79818ac6e36e304a01ea2fb6be6e14a545bcf Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 21 Jul 2011 15:21:33 +0800 Subject: HID: prodikeys: make needlessly global symbols static The following symbols are not referenced outside this file so there's no need for it to be in the global name space. pcmidi_sustained_note_release init_sustain_timers stop_sustain_timers pcmidi_handle_report pcmidi_setup_extra_keys pcmidi_snd_initialise pcmidi_snd_terminate Make them static. Signed-off-by: Axel Lin Signed-off-by: Jiri Kosina --- drivers/hid/hid-prodikeys.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-prodikeys.c b/drivers/hid/hid-prodikeys.c index ab19f29..7563229 100644 --- a/drivers/hid/hid-prodikeys.c +++ b/drivers/hid/hid-prodikeys.c @@ -242,7 +242,7 @@ drop_note: return; } -void pcmidi_sustained_note_release(unsigned long data) +static void pcmidi_sustained_note_release(unsigned long data) { struct pcmidi_sustain *pms = (struct pcmidi_sustain *)data; @@ -250,7 +250,7 @@ void pcmidi_sustained_note_release(unsigned long data) pms->in_use = 0; } -void init_sustain_timers(struct pcmidi_snd *pm) +static void init_sustain_timers(struct pcmidi_snd *pm) { struct pcmidi_sustain *pms; unsigned i; @@ -264,7 +264,7 @@ void init_sustain_timers(struct pcmidi_snd *pm) } } -void stop_sustain_timers(struct pcmidi_snd *pm) +static void stop_sustain_timers(struct pcmidi_snd *pm) { struct pcmidi_sustain *pms; unsigned i; @@ -499,7 +499,7 @@ static int pcmidi_handle_report4(struct pcmidi_snd *pm, u8 *data) return 1; } -int pcmidi_handle_report( +static int pcmidi_handle_report( struct pcmidi_snd *pm, unsigned report_id, u8 *data, int size) { int ret = 0; @@ -518,7 +518,8 @@ int pcmidi_handle_report( return ret; } -void pcmidi_setup_extra_keys(struct pcmidi_snd *pm, struct input_dev *input) +static void pcmidi_setup_extra_keys( + struct pcmidi_snd *pm, struct input_dev *input) { /* reassigned functionality for N/A keys MY PICTURES => KEY_WORDPROCESSOR @@ -602,7 +603,7 @@ static struct snd_rawmidi_ops pcmidi_in_ops = { .trigger = pcmidi_in_trigger }; -int pcmidi_snd_initialise(struct pcmidi_snd *pm) +static int pcmidi_snd_initialise(struct pcmidi_snd *pm) { static int dev; struct snd_card *card; @@ -720,7 +721,7 @@ fail: return err; } -int pcmidi_snd_terminate(struct pcmidi_snd *pm) +static int pcmidi_snd_terminate(struct pcmidi_snd *pm) { if (pm->card) { stop_sustain_timers(pm); -- cgit v1.1 From d6b8f5819f56ab79741871a4bd8a6e9f9d127bd6 Mon Sep 17 00:00:00 2001 From: Axel Lin Date: Thu, 21 Jul 2011 15:47:28 +0800 Subject: HID: prodikeys: remove a redundant forward declaration of struct pcmidi_snd Signed-off-by: Axel Lin Signed-off-by: Jiri Kosina --- drivers/hid/hid-prodikeys.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-prodikeys.c b/drivers/hid/hid-prodikeys.c index 7563229..158b389 100644 --- a/drivers/hid/hid-prodikeys.c +++ b/drivers/hid/hid-prodikeys.c @@ -44,8 +44,6 @@ struct pk_device { struct pcmidi_snd *pm; /* pcmidi device context */ }; -struct pcmidi_snd; - struct pcmidi_sustain { unsigned long in_use; struct pcmidi_snd *pm; -- cgit v1.1 From bc8a2a9b4e5c418bebaa6bb812982b7ecd298821 Mon Sep 17 00:00:00 2001 From: ice chien Date: Fri, 15 Jul 2011 16:58:06 +0800 Subject: HID: hid-multitouch: add one new multitouch device's VID/PID This patch adds support for the CSR panel built by XAT. Signed-off-by: Ice Chien Signed-off-by: Jiri Kosina --- drivers/hid/Kconfig | 1 + drivers/hid/hid-core.c | 1 + drivers/hid/hid-ids.h | 3 +++ drivers/hid/hid-multitouch.c | 4 ++++ 4 files changed, 9 insertions(+) (limited to 'drivers/hid') diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index acc39e8..6008e63 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig @@ -335,6 +335,7 @@ config HID_MULTITOUCH - Stantum multitouch panels - Touch International Panels - Unitec Panels + - XAT optical touch panels If unsure, say N. diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 2a268fc..1ae647e 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1500,6 +1500,7 @@ static const struct hid_device_id hid_have_special_driver[] = { { 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_MEDIA_TABLET_10_6_INCH) }, { HID_USB_DEVICE(USB_VENDOR_ID_WALTOP, USB_DEVICE_ID_WALTOP_MEDIA_TABLET_14_1_INCH) }, + { HID_USB_DEVICE(USB_VENDOR_ID_XAT, USB_DEVICE_ID_XAT_CSR) }, { HID_USB_DEVICE(USB_VENDOR_ID_X_TENSIONS, USB_DEVICE_ID_SPEEDLINK_VAD_CEZANNE) }, { HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0005) }, { HID_USB_DEVICE(USB_VENDOR_ID_ZEROPLUS, 0x0030) }, diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 2c85947..f9717e2 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -667,6 +667,9 @@ #define USB_VENDOR_ID_X_TENSIONS 0x1ae7 #define USB_DEVICE_ID_SPEEDLINK_VAD_CEZANNE 0x9001 +#define USB_VENDOR_ID_XAT 0x2505 +#define USB_DEVICE_ID_XAT_CSR 0x0220 + #define USB_VENDOR_ID_YEALINK 0x6993 #define USB_DEVICE_ID_YEALINK_P1K_P4K_B2K 0xb001 diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index ecd4d2d..c0d1b15 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c @@ -699,6 +699,10 @@ static const struct hid_device_id mt_devices[] = { { .driver_data = MT_CLS_DEFAULT, HID_USB_DEVICE(USB_VENDOR_ID_UNITEC, USB_DEVICE_ID_UNITEC_USB_TOUCH_0A19) }, + /* XAT */ + { .driver_data = MT_CLS_DEFAULT, + HID_USB_DEVICE(USB_VENDOR_ID_XAT, + USB_DEVICE_ID_XAT_CSR) }, { } }; -- cgit v1.1 From b580169affd7ccc9347cbf4d5f4db1480ee7ee06 Mon Sep 17 00:00:00 2001 From: Jiri Kosina Date: Fri, 22 Jul 2011 12:11:15 +0200 Subject: HID: fix support for Microsoft comfort mouse 4500 Add forgotten entry into the global blacklist. Signed-off-by: Jiri Kosina --- drivers/hid/hid-core.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/hid') diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 1ae647e..9657007 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1425,6 +1425,7 @@ static const struct hid_device_id hid_have_special_driver[] = { { HID_USB_DEVICE(USB_VENDOR_ID_LUMIO, USB_DEVICE_ID_CRYSTALTOUCH) }, { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICOLCD) }, { HID_USB_DEVICE(USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICOLCD_BOOTLOADER) }, + { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_COMFORT_MOUSE_4500) }, { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_SIDEWINDER_GV) }, { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_NE4K) }, { HID_USB_DEVICE(USB_VENDOR_ID_MICROSOFT, USB_DEVICE_ID_MS_LK6K) }, -- cgit v1.1