#define DRIVER_DESC "USB HID core driver"
#define DRIVER_LICENSE "GPL"
-static char *hid_types[] = {"Device", "Pointer", "Mouse", "Device", "Joystick",
- "Gamepad", "Keyboard", "Keypad", "Multi-Axis Controller"};
/*
* Module parameters.
*/
" quirks=vendorID:productID:quirks"
" where vendorID, productID, and quirks are all in"
" 0x-prefixed hex");
-static char *rdesc_quirks_param[MAX_USBHID_BOOT_QUIRKS] = { [ 0 ... (MAX_USBHID_BOOT_QUIRKS - 1) ] = NULL };
-module_param_array_named(rdesc_quirks, rdesc_quirks_param, charp, NULL, 0444);
-MODULE_PARM_DESC(rdesc_quirks, "Add/modify report descriptor quirks by specifying "
- " rdesc_quirks=vendorID:productID:rdesc_quirks"
- " where vendorID, productID, and rdesc_quirks are all in"
- " 0x-prefixed hex");
/*
* Input submission and I/O error handler.
*/
int status;
switch (urb->status) {
- case 0: /* success */
- usbhid->retry_delay = 0;
- hid_input_report(urb->context, HID_INPUT_REPORT,
- urb->transfer_buffer,
- urb->actual_length, 1);
- break;
- case -EPIPE: /* stall */
- clear_bit(HID_IN_RUNNING, &usbhid->iofl);
- set_bit(HID_CLEAR_HALT, &usbhid->iofl);
- schedule_work(&usbhid->reset_work);
- return;
- case -ECONNRESET: /* unlink */
- case -ENOENT:
- case -ESHUTDOWN: /* unplug */
- clear_bit(HID_IN_RUNNING, &usbhid->iofl);
- return;
- case -EILSEQ: /* protocol error or unplug */
- case -EPROTO: /* protocol error or unplug */
- case -ETIME: /* protocol error or unplug */
- case -ETIMEDOUT: /* Should never happen, but... */
- clear_bit(HID_IN_RUNNING, &usbhid->iofl);
- hid_io_error(hid);
- return;
- default: /* error */
- warn("input irq status %d received", urb->status);
+ case 0: /* success */
+ usbhid->retry_delay = 0;
+ hid_input_report(urb->context, HID_INPUT_REPORT,
+ urb->transfer_buffer,
+ urb->actual_length, 1);
+ break;
+ case -EPIPE: /* stall */
+ clear_bit(HID_IN_RUNNING, &usbhid->iofl);
+ set_bit(HID_CLEAR_HALT, &usbhid->iofl);
+ schedule_work(&usbhid->reset_work);
+ return;
+ case -ECONNRESET: /* unlink */
+ case -ENOENT:
+ case -ESHUTDOWN: /* unplug */
+ clear_bit(HID_IN_RUNNING, &usbhid->iofl);
+ return;
+ case -EILSEQ: /* protocol error or unplug */
+ case -EPROTO: /* protocol error or unplug */
+ case -ETIME: /* protocol error or unplug */
+ case -ETIMEDOUT: /* Should never happen, but... */
+ clear_bit(HID_IN_RUNNING, &usbhid->iofl);
+ hid_io_error(hid);
+ return;
+ default: /* error */
+ warn("input irq status %d received", urb->status);
}
status = usb_submit_urb(urb, GFP_ATOMIC);
int unplug = 0;
switch (urb->status) {
- case 0: /* success */
- break;
- case -ESHUTDOWN: /* unplug */
- unplug = 1;
- case -EILSEQ: /* protocol error or unplug */
- case -EPROTO: /* protocol error or unplug */
- case -ECONNRESET: /* unlink */
- case -ENOENT:
- break;
- default: /* error */
- warn("output irq status %d received", urb->status);
+ case 0: /* success */
+ break;
+ case -ESHUTDOWN: /* unplug */
+ unplug = 1;
+ case -EILSEQ: /* protocol error or unplug */
+ case -EPROTO: /* protocol error or unplug */
+ case -ECONNRESET: /* unlink */
+ case -ENOENT:
+ break;
+ default: /* error */
+ warn("output irq status %d received", urb->status);
}
spin_lock_irqsave(&usbhid->outlock, flags);
spin_lock_irqsave(&usbhid->ctrllock, flags);
switch (urb->status) {
- case 0: /* success */
- if (usbhid->ctrl[usbhid->ctrltail].dir == USB_DIR_IN)
- hid_input_report(urb->context, usbhid->ctrl[usbhid->ctrltail].report->type,
- urb->transfer_buffer, urb->actual_length, 0);
- break;
- case -ESHUTDOWN: /* unplug */
- unplug = 1;
- case -EILSEQ: /* protocol error or unplug */
- case -EPROTO: /* protocol error or unplug */
- case -ECONNRESET: /* unlink */
- case -ENOENT:
- case -EPIPE: /* report not available */
- break;
- default: /* error */
- warn("ctrl urb status %d received", urb->status);
+ case 0: /* success */
+ if (usbhid->ctrl[usbhid->ctrltail].dir == USB_DIR_IN)
+ hid_input_report(urb->context,
+ usbhid->ctrl[usbhid->ctrltail].report->type,
+ urb->transfer_buffer, urb->actual_length, 0);
+ break;
+ case -ESHUTDOWN: /* unplug */
+ unplug = 1;
+ case -EILSEQ: /* protocol error or unplug */
+ case -EPROTO: /* protocol error or unplug */
+ case -ECONNRESET: /* unlink */
+ case -ENOENT:
+ case -EPIPE: /* report not available */
+ break;
+ default: /* error */
+ warn("ctrl urb status %d received", urb->status);
}
if (unplug)
spin_unlock_irqrestore(&usbhid->ctrllock, flags);
}
+EXPORT_SYMBOL_GPL(usbhid_submit_report);
static int usb_hidinput_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
{
return -1;
}
-static void usbhid_set_leds(struct hid_device *hid)
+void usbhid_set_leds(struct hid_device *hid)
{
struct hid_field *field;
int offset;
usbhid_submit_report(hid, field->report, USB_DIR_OUT);
}
}
+EXPORT_SYMBOL_GPL(usbhid_set_leds);
/*
* Traverse the supplied list of reports and find the longest
usb_buffer_free(dev, usbhid->bufsize, usbhid->ctrlbuf, usbhid->ctrlbuf_dma);
}
-/*
- * Sending HID_REQ_GET_REPORT changes the operation mode of the ps3 controller
- * to "operational". Without this, the ps3 controller will not report any
- * events.
- */
-static void hid_fixup_sony_ps3_controller(struct usb_device *dev, int ifnum)
-{
- int result;
- char *buf = kmalloc(18, GFP_KERNEL);
-
- if (!buf)
- return;
-
- result = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
- HID_REQ_GET_REPORT,
- USB_DIR_IN | USB_TYPE_CLASS |
- USB_RECIP_INTERFACE,
- (3 << 8) | 0xf2, ifnum, buf, 17,
- USB_CTRL_GET_TIMEOUT);
-
- if (result < 0)
- err_hid("%s failed: %d\n", __func__, result);
-
- kfree(buf);
-}
-
-static int usbhid_start_finish(struct hid_device *hid)
-{
- struct usb_interface *intf = to_usb_interface(hid->dev.parent);
- char path[64], *type;
- unsigned int i;
-
- usbhid_init_reports(hid);
- hid_dump_device(hid);
- if (hid->quirks & HID_QUIRK_RESET_LEDS)
- usbhid_set_leds(hid);
-
- if (!hidinput_connect(hid))
- hid->claimed |= HID_CLAIMED_INPUT;
- if (!hiddev_connect(hid))
- hid->claimed |= HID_CLAIMED_HIDDEV;
- if (!hidraw_connect(hid))
- hid->claimed |= HID_CLAIMED_HIDRAW;
-
- if (!hid->claimed) {
- printk(KERN_ERR "HID device claimed by neither input, hiddev "
- "nor hidraw\n");
- return -ENODEV;
- }
-
- if ((hid->claimed & HID_CLAIMED_INPUT))
- hid_ff_init(hid);
-
- if (hid->quirks & HID_QUIRK_SONY_PS3_CONTROLLER)
- hid_fixup_sony_ps3_controller(interface_to_usbdev(intf),
- intf->cur_altsetting->desc.bInterfaceNumber);
-
- printk(KERN_INFO);
-
- if (hid->claimed & HID_CLAIMED_INPUT)
- printk("input");
- if ((hid->claimed & HID_CLAIMED_INPUT) &&
- ((hid->claimed & HID_CLAIMED_HIDDEV) ||
- hid->claimed & HID_CLAIMED_HIDRAW))
- printk(",");
- if (hid->claimed & HID_CLAIMED_HIDDEV)
- printk("hiddev%d", hid->minor);
- if ((hid->claimed & HID_CLAIMED_INPUT) &&
- (hid->claimed & HID_CLAIMED_HIDDEV) &&
- (hid->claimed & HID_CLAIMED_HIDRAW))
- printk(",");
- if (hid->claimed & HID_CLAIMED_HIDRAW)
- printk("hidraw%d", ((struct hidraw *)hid->hidraw)->minor);
-
- type = "Device";
- for (i = 0; i < hid->maxcollection; i++) {
- if (hid->collection[i].type == HID_COLLECTION_APPLICATION &&
- (hid->collection[i].usage & HID_USAGE_PAGE) ==
- HID_UP_GENDESK &&
- (hid->collection[i].usage & 0xffff) <
- ARRAY_SIZE(hid_types)) {
- type = hid_types[hid->collection[i].usage & 0xffff];
- break;
- }
- }
-
- usb_make_path(interface_to_usbdev(intf), path, 63);
-
- printk(": USB HID v%x.%02x %s [%s] on %s\n",
- hid->version >> 8, hid->version & 0xff, type, hid->name, path);
-
- return 0;
-}
-
static int usbhid_parse(struct hid_device *hid)
{
struct usb_interface *intf = to_usb_interface(hid->dev.parent);
quirks |= HID_QUIRK_NOGET;
}
- if (quirks & HID_QUIRK_IGNORE)
- return -ENODEV;
-
- if ((quirks & HID_QUIRK_IGNORE_MOUSE) &&
- (interface->desc.bInterfaceProtocol == USB_INTERFACE_PROTOCOL_MOUSE))
- return -ENODEV;
-
if (usb_get_extra_descriptor(interface, HID_DT_HID, &hdesc) &&
(!interface->desc.bNumEndpoints ||
usb_get_extra_descriptor(&interface->endpoint[0], HID_DT_HID, &hdesc))) {
goto err;
}
- usbhid_fixup_report_descriptor(le16_to_cpu(dev->descriptor.idVendor),
- le16_to_cpu(dev->descriptor.idProduct), rdesc,
- rsize, rdesc_quirks_param);
-
dbg_hid("report descriptor (size %u, read %d) = ", rsize, n);
for (n = 0; n < rsize; n++)
dbg_hid_line(" %02x", (unsigned char) rdesc[n]);
usbhid->urbctrl->transfer_dma = usbhid->ctrlbuf_dma;
usbhid->urbctrl->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP);
- ret = usbhid_start_finish(hid);
- if (ret)
- goto fail;
+ usbhid_init_reports(hid);
+ hid_dump_device(hid);
return 0;
usb_set_intfdata(intf, hid);
hid->ll_driver = &usb_hid_driver;
hid->hid_output_raw_report = usbhid_output_raw_report;
+ hid->ff_init = hid_pidff_init;
#ifdef CONFIG_USB_HIDDEV
+ hid->hiddev_connect = hiddev_connect;
hid->hiddev_hid_event = hiddev_hid_event;
hid->hiddev_report_event = hiddev_report_event;
#endif
ret = hid_add_device(hid);
if (ret) {
- dev_err(&intf->dev, "can't add hid device: %d\n", ret);
+ if (ret != -ENODEV)
+ dev_err(&intf->dev, "can't add hid device: %d\n", ret);
goto err;
}