mirror of
https://github.com/torvalds/linux.git
synced 2024-11-26 14:12:06 +00:00
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid: HID: add quirk entry for no-name keyboard (0x13ba/0x0017) HID: fix hid_device_id for cross compiling HID: sync on deleted io_retry timer in usbhid driver HID: fix oops during suspend of unbound HID devices
This commit is contained in:
commit
cdcba02a5f
@ -1263,6 +1263,7 @@ static const struct hid_device_id hid_blacklist[] = {
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_W7658) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_SK8115) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_EZKEY, USB_DEVICE_ID_BTC_8193) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_GENERIC_13BA, USB_DEVICE_ID_GENERIC_13BA_KBD_MOUSE) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_2) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD) },
|
||||
|
@ -48,6 +48,7 @@ err_free:
|
||||
static const struct hid_device_id dell_devices[] = {
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_W7658) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_SK8115) },
|
||||
{ HID_USB_DEVICE(USB_VENDOR_ID_GENERIC_13BA, USB_DEVICE_ID_GENERIC_13BA_KBD_MOUSE) },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(hid, dell_devices);
|
||||
|
@ -163,6 +163,9 @@
|
||||
|
||||
#define USB_VENDOR_ID_GENERAL_TOUCH 0x0dfc
|
||||
|
||||
#define USB_VENDOR_ID_GENERIC_13BA 0x13ba
|
||||
#define USB_DEVICE_ID_GENERIC_13BA_KBD_MOUSE 0x0017
|
||||
|
||||
#define USB_VENDOR_ID_GLAB 0x06c2
|
||||
#define USB_DEVICE_ID_4_PHIDGETSERVO_30 0x0038
|
||||
#define USB_DEVICE_ID_1_PHIDGETSERVO_30 0x0039
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/mm.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/smp_lock.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <asm/unaligned.h>
|
||||
@ -776,21 +777,10 @@ static int usbhid_start(struct hid_device *hid)
|
||||
struct usb_interface *intf = to_usb_interface(hid->dev.parent);
|
||||
struct usb_host_interface *interface = intf->cur_altsetting;
|
||||
struct usb_device *dev = interface_to_usbdev(intf);
|
||||
struct usbhid_device *usbhid;
|
||||
struct usbhid_device *usbhid = hid->driver_data;
|
||||
unsigned int n, insize = 0;
|
||||
int ret;
|
||||
|
||||
WARN_ON(hid->driver_data);
|
||||
|
||||
usbhid = kzalloc(sizeof(struct usbhid_device), GFP_KERNEL);
|
||||
if (usbhid == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
hid->driver_data = usbhid;
|
||||
usbhid->hid = hid;
|
||||
|
||||
usbhid->bufsize = HID_MIN_BUFFER_SIZE;
|
||||
hid_find_max_report(hid, HID_INPUT_REPORT, &usbhid->bufsize);
|
||||
hid_find_max_report(hid, HID_OUTPUT_REPORT, &usbhid->bufsize);
|
||||
@ -804,6 +794,7 @@ static int usbhid_start(struct hid_device *hid)
|
||||
if (insize > HID_MAX_BUFFER_SIZE)
|
||||
insize = HID_MAX_BUFFER_SIZE;
|
||||
|
||||
mutex_lock(&usbhid->setup);
|
||||
if (hid_alloc_buffers(dev, hid)) {
|
||||
ret = -ENOMEM;
|
||||
goto fail;
|
||||
@ -888,6 +879,9 @@ static int usbhid_start(struct hid_device *hid)
|
||||
usbhid_init_reports(hid);
|
||||
hid_dump_device(hid);
|
||||
|
||||
set_bit(HID_STARTED, &usbhid->iofl);
|
||||
mutex_unlock(&usbhid->setup);
|
||||
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
@ -895,8 +889,7 @@ fail:
|
||||
usb_free_urb(usbhid->urbout);
|
||||
usb_free_urb(usbhid->urbctrl);
|
||||
hid_free_buffers(dev, hid);
|
||||
kfree(usbhid);
|
||||
err:
|
||||
mutex_unlock(&usbhid->setup);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -907,6 +900,8 @@ static void usbhid_stop(struct hid_device *hid)
|
||||
if (WARN_ON(!usbhid))
|
||||
return;
|
||||
|
||||
mutex_lock(&usbhid->setup);
|
||||
clear_bit(HID_STARTED, &usbhid->iofl);
|
||||
spin_lock_irq(&usbhid->inlock); /* Sync with error handler */
|
||||
set_bit(HID_DISCONNECTED, &usbhid->iofl);
|
||||
spin_unlock_irq(&usbhid->inlock);
|
||||
@ -931,8 +926,7 @@ static void usbhid_stop(struct hid_device *hid)
|
||||
usb_free_urb(usbhid->urbout);
|
||||
|
||||
hid_free_buffers(hid_to_usb_dev(hid), hid);
|
||||
kfree(usbhid);
|
||||
hid->driver_data = NULL;
|
||||
mutex_unlock(&usbhid->setup);
|
||||
}
|
||||
|
||||
static struct hid_ll_driver usb_hid_driver = {
|
||||
@ -947,6 +941,7 @@ static struct hid_ll_driver usb_hid_driver = {
|
||||
static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id)
|
||||
{
|
||||
struct usb_device *dev = interface_to_usbdev(intf);
|
||||
struct usbhid_device *usbhid;
|
||||
struct hid_device *hid;
|
||||
size_t len;
|
||||
int ret;
|
||||
@ -1000,14 +995,26 @@ static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id)
|
||||
if (usb_string(dev, dev->descriptor.iSerialNumber, hid->uniq, 64) <= 0)
|
||||
hid->uniq[0] = 0;
|
||||
|
||||
usbhid = kzalloc(sizeof(*usbhid), GFP_KERNEL);
|
||||
if (usbhid == NULL) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
hid->driver_data = usbhid;
|
||||
usbhid->hid = hid;
|
||||
mutex_init(&usbhid->setup); /* needed on suspend/resume */
|
||||
|
||||
ret = hid_add_device(hid);
|
||||
if (ret) {
|
||||
if (ret != -ENODEV)
|
||||
dev_err(&intf->dev, "can't add hid device: %d\n", ret);
|
||||
goto err;
|
||||
goto err_free;
|
||||
}
|
||||
|
||||
return 0;
|
||||
err_free:
|
||||
kfree(usbhid);
|
||||
err:
|
||||
hid_destroy_device(hid);
|
||||
return ret;
|
||||
@ -1016,11 +1023,14 @@ err:
|
||||
static void hid_disconnect(struct usb_interface *intf)
|
||||
{
|
||||
struct hid_device *hid = usb_get_intfdata(intf);
|
||||
struct usbhid_device *usbhid;
|
||||
|
||||
if (WARN_ON(!hid))
|
||||
return;
|
||||
|
||||
usbhid = hid->driver_data;
|
||||
hid_destroy_device(hid);
|
||||
kfree(usbhid);
|
||||
}
|
||||
|
||||
static int hid_suspend(struct usb_interface *intf, pm_message_t message)
|
||||
@ -1028,11 +1038,18 @@ static int hid_suspend(struct usb_interface *intf, pm_message_t message)
|
||||
struct hid_device *hid = usb_get_intfdata (intf);
|
||||
struct usbhid_device *usbhid = hid->driver_data;
|
||||
|
||||
mutex_lock(&usbhid->setup);
|
||||
if (!test_bit(HID_STARTED, &usbhid->iofl)) {
|
||||
mutex_unlock(&usbhid->setup);
|
||||
return 0;
|
||||
}
|
||||
|
||||
spin_lock_irq(&usbhid->inlock); /* Sync with error handler */
|
||||
set_bit(HID_SUSPENDED, &usbhid->iofl);
|
||||
spin_unlock_irq(&usbhid->inlock);
|
||||
del_timer(&usbhid->io_retry);
|
||||
del_timer_sync(&usbhid->io_retry);
|
||||
usb_kill_urb(usbhid->urbin);
|
||||
mutex_unlock(&usbhid->setup);
|
||||
dev_dbg(&intf->dev, "suspend\n");
|
||||
return 0;
|
||||
}
|
||||
@ -1043,9 +1060,16 @@ static int hid_resume(struct usb_interface *intf)
|
||||
struct usbhid_device *usbhid = hid->driver_data;
|
||||
int status;
|
||||
|
||||
mutex_lock(&usbhid->setup);
|
||||
if (!test_bit(HID_STARTED, &usbhid->iofl)) {
|
||||
mutex_unlock(&usbhid->setup);
|
||||
return 0;
|
||||
}
|
||||
|
||||
clear_bit(HID_SUSPENDED, &usbhid->iofl);
|
||||
usbhid->retry_delay = 0;
|
||||
status = hid_start_in(hid);
|
||||
mutex_unlock(&usbhid->setup);
|
||||
dev_dbg(&intf->dev, "resume status %d\n", status);
|
||||
return status;
|
||||
}
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include <linux/types.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/timer.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/workqueue.h>
|
||||
@ -73,6 +74,7 @@ struct usbhid_device {
|
||||
dma_addr_t outbuf_dma; /* Output buffer dma */
|
||||
spinlock_t outlock; /* Output fifo spinlock */
|
||||
|
||||
struct mutex setup;
|
||||
unsigned long iofl; /* I/O flags (CTRL_RUNNING, OUT_RUNNING) */
|
||||
struct timer_list io_retry; /* Retry timer */
|
||||
unsigned long stop_retry; /* Time to give up, in jiffies */
|
||||
|
@ -410,6 +410,7 @@ struct hid_output_fifo {
|
||||
#define HID_SUSPENDED 5
|
||||
#define HID_CLEAR_HALT 6
|
||||
#define HID_DISCONNECTED 7
|
||||
#define HID_STARTED 8
|
||||
|
||||
struct hid_input {
|
||||
struct list_head list;
|
||||
|
@ -135,6 +135,7 @@ struct usb_device_id {
|
||||
|
||||
struct hid_device_id {
|
||||
__u16 bus;
|
||||
__u16 pad1;
|
||||
__u32 vendor;
|
||||
__u32 product;
|
||||
kernel_ulong_t driver_data
|
||||
|
Loading…
Reference in New Issue
Block a user