From 3d61510f4ecacfe47c75c0eb51c0659dfa77fb1b Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Fri, 2 Apr 2010 13:21:58 -0400 Subject: HID: usbhid: enable remote wakeup for keyboards This patch (as1365) enables remote wakeup by default for USB keyboard devices. Keyboards in general are supposed to be wakeup devices, but the correct place to enable it depends on the device's bus; no single approach will work for all keyboard devices. In particular, this covers only USB keyboards (and then only those supporting the boot protocol). Signed-off-by: Alan Stern Signed-off-by: Jiri Kosina --- drivers/hid/usbhid/hid-core.c | 7 +++++-- drivers/hid/usbhid/usbkbd.c | 1 + 2 files changed, 6 insertions(+), 2 deletions(-) (limited to 'drivers/hid/usbhid') diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index 56d06cd8075..9cd61a52e9e 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c @@ -1026,12 +1026,15 @@ static int usbhid_start(struct hid_device *hid) /* Some keyboards don't work until their LEDs have been set. * Since BIOSes do set the LEDs, it must be safe for any device * that supports the keyboard boot protocol. + * In addition, enable remote wakeup by default for all keyboard + * devices supporting the boot protocol. */ if (interface->desc.bInterfaceSubClass == USB_INTERFACE_SUBCLASS_BOOT && interface->desc.bInterfaceProtocol == - USB_INTERFACE_PROTOCOL_KEYBOARD) + USB_INTERFACE_PROTOCOL_KEYBOARD) { usbhid_set_leds(hid); - + device_set_wakeup_enable(&dev->dev, 1); + } return 0; fail: diff --git a/drivers/hid/usbhid/usbkbd.c b/drivers/hid/usbhid/usbkbd.c index f843443ba5c..b2fd0b00de9 100644 --- a/drivers/hid/usbhid/usbkbd.c +++ b/drivers/hid/usbhid/usbkbd.c @@ -313,6 +313,7 @@ static int usb_kbd_probe(struct usb_interface *iface, goto fail2; usb_set_intfdata(iface, kbd); + device_set_wakeup_enable(&dev->dev, 1); return 0; fail2: -- cgit v1.2.3-70-g09d2 From b5e5a37e36cd4d355b875665312d7aaae4e5833c Mon Sep 17 00:00:00 2001 From: Bastien Nocera Date: Fri, 16 Apr 2010 17:19:50 +0100 Subject: HID: add HID_QUIRK_HIDDEV_FORCE and HID_QUIRK_NO_IGNORE Add two quirks to make it possible for usbhid module options to override whether a device is ignored (HID_QUIRK_NO_IGNORE) and whether to connect a hiddev device (HID_QUIRK_HIDDEV_FORCE). Passing HID_QUIRK_NO_IGNORE for your device means that it will not be ignored by the HID layer, even if present in a blacklist. HID_QUIRK_HIDDEV_FORCE will force the creation of a hiddev for that device, making it accessible from user-space. Tested with an Apple IR Receiver, switching it from using appleir to using lirc's macmini driver. Signed-off-by: Bastien Nocera Signed-off-by: Jiri Kosina --- drivers/hid/hid-core.c | 4 +++- drivers/hid/usbhid/hid-core.c | 1 + include/linux/hid.h | 2 ++ 3 files changed, 6 insertions(+), 1 deletion(-) (limited to 'drivers/hid/usbhid') diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 8617aa97a9c..468c6c2d4ad 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c @@ -1168,6 +1168,8 @@ int hid_connect(struct hid_device *hdev, unsigned int connect_mask) unsigned int i; int len; + if (hdev->quirks & HID_QUIRK_HIDDEV_FORCE) + connect_mask |= (HID_CONNECT_HIDDEV_FORCE | HID_CONNECT_HIDDEV); if (hdev->bus != BUS_USB) connect_mask &= ~HID_CONNECT_HIDDEV; if (hid_hiddev(hdev)) @@ -1757,7 +1759,7 @@ int hid_add_device(struct hid_device *hdev) /* we need to kill them here, otherwise they will stay allocated to * wait for coming driver */ - if (hid_ignore(hdev)) + if (!(hdev->quirks & HID_QUIRK_NO_IGNORE) && hid_ignore(hdev)) return -ENODEV; /* XXX hack, any other cleaner solution after the driver core diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index 9cd61a52e9e..245aef0de8f 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c @@ -1143,6 +1143,7 @@ static int usbhid_probe(struct usb_interface *intf, const struct usb_device_id * hid->vendor = le16_to_cpu(dev->descriptor.idVendor); hid->product = le16_to_cpu(dev->descriptor.idProduct); hid->name[0] = 0; + hid->quirks = usbhid_lookup_quirk(hid->vendor, hid->product); if (intf->cur_altsetting->desc.bInterfaceProtocol == USB_INTERFACE_PROTOCOL_MOUSE) hid->type = HID_TYPE_USBMOUSE; diff --git a/include/linux/hid.h b/include/linux/hid.h index b1344ec4b7f..f1f2b6f0d1c 100644 --- a/include/linux/hid.h +++ b/include/linux/hid.h @@ -308,11 +308,13 @@ struct hid_item { #define HID_QUIRK_NOTOUCH 0x00000002 #define HID_QUIRK_IGNORE 0x00000004 #define HID_QUIRK_NOGET 0x00000008 +#define HID_QUIRK_HIDDEV_FORCE 0x00000010 #define HID_QUIRK_BADPAD 0x00000020 #define HID_QUIRK_MULTI_INPUT 0x00000040 #define HID_QUIRK_SKIP_OUTPUT_REPORTS 0x00010000 #define HID_QUIRK_FULLSPEED_INTERVAL 0x10000000 #define HID_QUIRK_NO_INIT_REPORTS 0x20000000 +#define HID_QUIRK_NO_IGNORE 0x40000000 /* * This is the global environment of the parser. This information is -- cgit v1.2.3-70-g09d2 From fe6065dc30c8cdd4beaffd6d3fa110222ad08795 Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Tue, 2 Feb 2010 13:40:40 +1000 Subject: HID: add multi-input quirk for eGalax Touchcontroller I've got one of these devices on my desk and it seems that it suffers from the ABS_Z/ABS_RX issue that we've seen in other devices before. This patch uses the same reasoning as 9db630b48 ("HID: add multi-input quirk for NextWindow Touchscreen"). Signed-off-by: Peter Hutterer Signed-off-by: Jiri Kosina --- drivers/hid/hid-ids.h | 3 +++ drivers/hid/usbhid/hid-quirks.c | 1 + 2 files changed, 4 insertions(+) (limited to 'drivers/hid/usbhid') diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 9791d0a8d16..513e75e0f65 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -174,6 +174,9 @@ #define USB_VENDOR_ID_DRAGONRISE 0x0079 +#define USB_VENDOR_ID_EGALAX 0x0EEF +#define USB_DEVICE_ID_EGALAX_TOUCHCONTROLLER 0x0001 + #define USB_VENDOR_ID_ELO 0x04E7 #define USB_DEVICE_ID_ELO_TS2700 0x0020 diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index 7844280897d..8ea185246a7 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c @@ -32,6 +32,7 @@ static const struct hid_blacklist { { USB_VENDOR_ID_AASHIMA, USB_DEVICE_ID_AASHIMA_PREDATOR, HID_QUIRK_BADPAD }, { USB_VENDOR_ID_ALPS, USB_DEVICE_ID_IBM_GAMEPAD, HID_QUIRK_BADPAD }, { USB_VENDOR_ID_CHIC, USB_DEVICE_ID_CHIC_GAMEPAD, HID_QUIRK_BADPAD }, + { USB_VENDOR_ID_EGALAX, USB_DEVICE_ID_EGALAX_TOUCHCONTROLLER, HID_QUIRK_MULTI_INPUT }, { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_DRIVING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FLYING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, { USB_VENDOR_ID_HAPP, USB_DEVICE_ID_UGCI_FIGHTING, HID_QUIRK_BADPAD | HID_QUIRK_MULTI_INPUT }, -- cgit v1.2.3-70-g09d2 From a8ab5d58b0238b8199cc699b8dff7c5e1da24138 Mon Sep 17 00:00:00 2001 From: Alan Ott Date: Sun, 16 May 2010 18:07:09 -0400 Subject: HID: hidraw: Use Interrupt Endpoint for OUT Transfers if Available This patch makes the hidraw driver use the first Interrupt OUT endpoint for HID transfers to the device if such an endpoint exists. This is consistent with the behavior of the hiddev driver, and the logic is similar. From the USB HID specification: The Interrupt Out pipe is optional. If a device declares an Interrupt Out endpoint then Output reports are transmitted by the host to the device through the Interrupt Out endpoint. If no Interrupt Out endpoint is declared then Output reports are transmitted to a device through the Control endpoint, using Set_Report(Output) requests. Signed-off-by: Alan Ott Signed-off-by: Jiri Kosina --- drivers/hid/usbhid/hid-core.c | 40 ++++++++++++++++++++++++++++++---------- 1 file changed, 30 insertions(+), 10 deletions(-) (limited to 'drivers/hid/usbhid') diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index 245aef0de8f..f9640a362ca 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c @@ -807,16 +807,36 @@ static int usbhid_output_raw_report(struct hid_device *hid, __u8 *buf, size_t co struct usb_host_interface *interface = intf->cur_altsetting; int ret; - ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), - HID_REQ_SET_REPORT, - USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, - ((report_type + 1) << 8) | *buf, - interface->desc.bInterfaceNumber, buf + 1, count - 1, - USB_CTRL_SET_TIMEOUT); - - /* count also the report id */ - if (ret > 0) - ret++; + if (usbhid->urbout) { + int actual_length; + int skipped_report_id = 0; + if (buf[0] == 0x0) { + /* Don't send the Report ID */ + buf++; + count--; + skipped_report_id = 1; + } + ret = usb_interrupt_msg(dev, usbhid->urbout->pipe, + buf, count, &actual_length, + USB_CTRL_SET_TIMEOUT); + /* return the number of bytes transferred */ + if (ret == 0) { + ret = actual_length; + /* count also the report id */ + if (skipped_report_id) + ret++; + } + } else { + ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), + HID_REQ_SET_REPORT, + USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE, + ((report_type + 1) << 8) | *buf, + interface->desc.bInterfaceNumber, buf + 1, count - 1, + USB_CTRL_SET_TIMEOUT); + /* count also the report id */ + if (ret > 0) + ret++; + } return ret; } -- cgit v1.2.3-70-g09d2