From da54a0ced4502dc2a25df034f218463a2a50488d Mon Sep 17 00:00:00 2001 From: Jiri Kosina Date: Thu, 25 Mar 2010 15:34:34 +0100 Subject: HID: update BKL comment in hiddev Update comment explaining BKL usage in legacy hiddev driver. Signed-off-by: Jiri Kosina --- drivers/hid/usbhid/hiddev.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) (limited to 'drivers/hid/usbhid') diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c index 433602aed468..c24d2fa3e3b6 100644 --- a/drivers/hid/usbhid/hiddev.c +++ b/drivers/hid/usbhid/hiddev.c @@ -267,6 +267,7 @@ static int hiddev_open(struct inode *inode, struct file *file) struct hiddev_list *list; int res, i; + /* See comment in hiddev_connect() for BKL explanation */ lock_kernel(); i = iminor(inode) - HIDDEV_MINOR_BASE; @@ -894,8 +895,22 @@ int hiddev_connect(struct hid_device *hid, unsigned int force) hiddev->hid = hid; hiddev->exist = 1; - /* when lock_kernel() usage is fixed in usb_open(), - * we could also fix it here */ + /* + * BKL here is used to avoid race after usb_register_dev(). + * Once the device node has been created, open() could happen on it. + * The code below will then fail, as hiddev_table hasn't been + * updated. + * + * The obvious fix -- introducing mutex to guard hiddev_table[] + * doesn't work, as usb_open() and usb_register_dev() both take + * minor_rwsem, thus we'll have ABBA deadlock. + * + * Before BKL pushdown, usb_open() had been acquiring it in right + * order, so _open() was safe to use it to protect from this race. + * Now the order is different, but AB-BA deadlock still doesn't occur + * as BKL is dropped on schedule() (i.e. while sleeping on + * minor_rwsem). Fugly. + */ lock_kernel(); retval = usb_register_dev(usbhid->intf, &hiddev_class); if (retval) { -- cgit v1.2.1 From b8c21cf697d165999cc21a90e6caa73690ac6190 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bruno=20Pr=C3=A9mont?= Date: Tue, 30 Mar 2010 22:34:30 +0200 Subject: HID: add framebuffer support to PicoLCD device MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add framebuffer support to PicoLCD device with use of deferred-io. Only changed areas of framebuffer get sent to device in order to save USB bandwidth and especially resources on PicoLCD device or allow higher refresh rate for a small area. Changed tiles are determined while updating shadow framebuffer. Signed-off-by: Bruno Prémont Signed-off-by: Jiri Kosina --- drivers/hid/usbhid/hid-core.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/hid/usbhid') diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index 56d06cd8075b..3e7909b0f129 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c @@ -623,6 +623,7 @@ int usbhid_wait_io(struct hid_device *hid) return 0; } +EXPORT_SYMBOL_GPL(usbhid_wait_io); static int hid_set_idle(struct usb_device *dev, int ifnum, int report, int idle) { -- cgit v1.2.1 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 56d06cd8075b..9cd61a52e9e3 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 f843443ba5c3..b2fd0b00de92 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.1 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/usbhid/hid-core.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/hid/usbhid') diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index 9cd61a52e9e3..245aef0de8f2 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; -- cgit v1.2.1 From 6a740aa4f47b9f29bad5292cf51f008f3edad9b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bruno=20Pr=C3=A9mont?= Date: Sun, 25 Apr 2010 21:40:03 +0200 Subject: HID: add suspend/resume hooks for hid drivers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add suspend/resume hooks for HID drivers so these can do some additional state adjustment when device gets suspended/resumed. Signed-off-by: Bruno Prémont Signed-off-by: Jiri Kosina --- drivers/hid/usbhid/hid-core.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) (limited to 'drivers/hid/usbhid') diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index 56d06cd8075b..14a67fba590e 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c @@ -1290,6 +1290,11 @@ static int hid_suspend(struct usb_interface *intf, pm_message_t message) { set_bit(HID_REPORTED_IDLE, &usbhid->iofl); spin_unlock_irq(&usbhid->lock); + if (hid->driver && hid->driver->suspend) { + status = hid->driver->suspend(hid, message); + if (status < 0) + return status; + } } else { usbhid_mark_busy(usbhid); spin_unlock_irq(&usbhid->lock); @@ -1297,6 +1302,11 @@ static int hid_suspend(struct usb_interface *intf, pm_message_t message) } } else { + if (hid->driver && hid->driver->suspend) { + status = hid->driver->suspend(hid, message); + if (status < 0) + return status; + } spin_lock_irq(&usbhid->lock); set_bit(HID_REPORTED_IDLE, &usbhid->iofl); spin_unlock_irq(&usbhid->lock); @@ -1351,6 +1361,11 @@ static int hid_resume(struct usb_interface *intf) hid_io_error(hid); usbhid_restart_queues(usbhid); + if (status >= 0 && hid->driver && hid->driver->resume) { + int ret = hid->driver->resume(hid); + if (ret < 0) + status = ret; + } dev_dbg(&intf->dev, "resume status %d\n", status); return 0; } @@ -1359,9 +1374,16 @@ static int hid_reset_resume(struct usb_interface *intf) { struct hid_device *hid = usb_get_intfdata(intf); struct usbhid_device *usbhid = hid->driver_data; + int status; clear_bit(HID_REPORTED_IDLE, &usbhid->iofl); - return hid_post_reset(intf); + status = hid_post_reset(intf); + if (status >= 0 && hid->driver && hid->driver->reset_resume) { + int ret = hid->driver->reset_resume(hid); + if (ret < 0) + status = ret; + } + return status; } #endif /* CONFIG_PM */ -- cgit v1.2.1 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/usbhid/hid-quirks.c | 1 + 1 file changed, 1 insertion(+) (limited to 'drivers/hid/usbhid') diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index 7844280897d1..8ea185246a78 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.1 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 245aef0de8f2..f9640a362caa 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.1