Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cdcba02a authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* '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
parents 53387b01 fa157bdf
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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) },
+1 −0
Original line number Diff line number Diff line
@@ -48,6 +48,7 @@ static int dell_probe(struct hid_device *hdev, const struct hid_device_id *id)
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);
+3 −0
Original line number Diff line number Diff line
@@ -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
+42 −18
Original line number Diff line number Diff line
@@ -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 @@ static int usbhid_start(struct hid_device *hid)
	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 @@ static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id)
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;
}
+2 −0
Original line number Diff line number Diff line
@@ -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 */
Loading