[PATCH] Generic HID layer - USB API
authorJiri Kosina <jkosina@suse.cz>
Fri, 8 Dec 2006 17:41:03 +0000 (18:41 +0100)
committerGreg Kroah-Hartman <gregkh@suse.de>
Fri, 8 Dec 2006 18:43:14 +0000 (10:43 -0800)
- 'dev' in struct hid_device changed from struct usb_device to
  struct device and fixed all the users
- renamed functions which are part of USB HID API from 'hid_*' to
  'usbhid_*'
- force feedback initialization moved from common part into USB-specific
  driver
- added usbhid.h header for USB HID API users
- removed USB-specific fields from struct hid_device and moved them
  to new usbhid_device, which is pointed to by hid_device->driver_data
- fixed all USB users to use this new structure

Signed-off-by: Jiri Kosina <jkosina@suse.cz>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/hid/hid-input.c
drivers/usb/input/hid-core.c
drivers/usb/input/hid-ff.c
drivers/usb/input/hid-lgff.c
drivers/usb/input/hid-pidff.c
drivers/usb/input/hid-tmff.c
drivers/usb/input/hid-zpff.c
drivers/usb/input/hiddev.c
drivers/usb/input/usbhid.h [new file with mode: 0644]
include/linux/hid.h

index 6d3d80b..e542ef9 100644 (file)
@@ -798,8 +798,7 @@ int hidinput_connect(struct hid_device *hid)
                                input_dev->id.vendor  = hid->vendor;
                                input_dev->id.product = hid->product;
                                input_dev->id.version = hid->version;
-                               input_dev->cdev.dev = &hid->intf->dev;
-
+                               input_dev->cdev.dev = hid->dev;
                                hidinput->input = input_dev;
                                list_add_tail(&hidinput->list, &hid->inputs);
                        }
@@ -821,13 +820,8 @@ int hidinput_connect(struct hid_device *hid)
                        }
                }
 
-       /* This only gets called when we are a single-input (most of the
-        * time). IOW, not a HID_QUIRK_MULTI_INPUT. The hid_ff_init() is
-        * only useful in this case, and not for multi-input quirks. */
-       if (hidinput) {
-               hid_ff_init(hid);
+       if (hidinput)
                input_register_device(hidinput->input);
-       }
 
        return 0;
 }
index 462947f..0991c4b 100644 (file)
@@ -35,6 +35,7 @@
 
 #include <linux/hid.h>
 #include <linux/hiddev.h>
+#include "usbhid.h"
 
 /*
  * Version Information
@@ -66,15 +67,16 @@ static int hid_start_in(struct hid_device *hid)
 {
        unsigned long flags;
        int rc = 0;
+       struct usbhid_device *usbhid = hid->driver_data;
 
-       spin_lock_irqsave(&hid->inlock, flags);
-       if (hid->open > 0 && !test_bit(HID_SUSPENDED, &hid->iofl) &&
-                       !test_and_set_bit(HID_IN_RUNNING, &hid->iofl)) {
-               rc = usb_submit_urb(hid->urbin, GFP_ATOMIC);
+       spin_lock_irqsave(&usbhid->inlock, flags);
+       if (hid->open > 0 && !test_bit(HID_SUSPENDED, &usbhid->iofl) &&
+                       !test_and_set_bit(HID_IN_RUNNING, &usbhid->iofl)) {
+               rc = usb_submit_urb(usbhid->urbin, GFP_ATOMIC);
                if (rc != 0)
-                       clear_bit(HID_IN_RUNNING, &hid->iofl);
+                       clear_bit(HID_IN_RUNNING, &usbhid->iofl);
        }
-       spin_unlock_irqrestore(&hid->inlock, flags);
+       spin_unlock_irqrestore(&usbhid->inlock, flags);
        return rc;
 }
 
@@ -82,8 +84,9 @@ static int hid_start_in(struct hid_device *hid)
 static void hid_retry_timeout(unsigned long _hid)
 {
        struct hid_device *hid = (struct hid_device *) _hid;
+       struct usbhid_device *usbhid = hid->driver_data;
 
-       dev_dbg(&hid->intf->dev, "retrying intr urb\n");
+       dev_dbg(&usbhid->intf->dev, "retrying intr urb\n");
        if (hid_start_in(hid))
                hid_io_error(hid);
 }
@@ -91,38 +94,39 @@ static void hid_retry_timeout(unsigned long _hid)
 /* Workqueue routine to reset the device or clear a halt */
 static void hid_reset(struct work_struct *work)
 {
-       struct hid_device *hid =
-               container_of(work, struct hid_device, reset_work);
+       struct usbhid_device *usbhid =
+               container_of(work, struct usbhid_device, reset_work);
+       struct hid_device *hid = usbhid->hid;
        int rc_lock, rc = 0;
 
-       if (test_bit(HID_CLEAR_HALT, &hid->iofl)) {
-               dev_dbg(&hid->intf->dev, "clear halt\n");
-               rc = usb_clear_halt(hid->dev, hid->urbin->pipe);
-               clear_bit(HID_CLEAR_HALT, &hid->iofl);
+       if (test_bit(HID_CLEAR_HALT, &usbhid->iofl)) {
+               dev_dbg(&usbhid->intf->dev, "clear halt\n");
+               rc = usb_clear_halt(to_usb_device(hid->dev), usbhid->urbin->pipe);
+               clear_bit(HID_CLEAR_HALT, &usbhid->iofl);
                hid_start_in(hid);
        }
 
-       else if (test_bit(HID_RESET_PENDING, &hid->iofl)) {
-               dev_dbg(&hid->intf->dev, "resetting device\n");
-               rc = rc_lock = usb_lock_device_for_reset(hid->dev, hid->intf);
+       else if (test_bit(HID_RESET_PENDING, &usbhid->iofl)) {
+               dev_dbg(&usbhid->intf->dev, "resetting device\n");
+               rc = rc_lock = usb_lock_device_for_reset(to_usb_device(hid->dev), usbhid->intf);
                if (rc_lock >= 0) {
-                       rc = usb_reset_composite_device(hid->dev, hid->intf);
+                       rc = usb_reset_composite_device(to_usb_device(hid->dev), usbhid->intf);
                        if (rc_lock)
-                               usb_unlock_device(hid->dev);
+                               usb_unlock_device(to_usb_device(hid->dev));
                }
-               clear_bit(HID_RESET_PENDING, &hid->iofl);
+               clear_bit(HID_RESET_PENDING, &usbhid->iofl);
        }
 
        switch (rc) {
        case 0:
-               if (!test_bit(HID_IN_RUNNING, &hid->iofl))
+               if (!test_bit(HID_IN_RUNNING, &usbhid->iofl))
                        hid_io_error(hid);
                break;
        default:
                err("can't reset device, %s-%s/input%d, status %d",
-                               hid->dev->bus->bus_name,
-                               hid->dev->devpath,
-                               hid->ifnum, rc);
+                               to_usb_device(hid->dev)->bus->bus_name,
+                               to_usb_device(hid->dev)->devpath,
+                               usbhid->ifnum, rc);
                /* FALLTHROUGH */
        case -EHOSTUNREACH:
        case -ENODEV:
@@ -135,33 +139,34 @@ static void hid_reset(struct work_struct *work)
 static void hid_io_error(struct hid_device *hid)
 {
        unsigned long flags;
+       struct usbhid_device *usbhid = hid->driver_data;
 
-       spin_lock_irqsave(&hid->inlock, flags);
+       spin_lock_irqsave(&usbhid->inlock, flags);
 
        /* Stop when disconnected */
-       if (usb_get_intfdata(hid->intf) == NULL)
+       if (usb_get_intfdata(usbhid->intf) == NULL)
                goto done;
 
        /* When an error occurs, retry at increasing intervals */
-       if (hid->retry_delay == 0) {
-               hid->retry_delay = 13;  /* Then 26, 52, 104, 104, ... */
-               hid->stop_retry = jiffies + msecs_to_jiffies(1000);
-       } else if (hid->retry_delay < 100)
-               hid->retry_delay *= 2;
+       if (usbhid->retry_delay == 0) {
+               usbhid->retry_delay = 13;       /* Then 26, 52, 104, 104, ... */
+               usbhid->stop_retry = jiffies + msecs_to_jiffies(1000);
+       } else if (usbhid->retry_delay < 100)
+               usbhid->retry_delay *= 2;
 
-       if (time_after(jiffies, hid->stop_retry)) {
+       if (time_after(jiffies, usbhid->stop_retry)) {
 
                /* Retries failed, so do a port reset */
-               if (!test_and_set_bit(HID_RESET_PENDING, &hid->iofl)) {
-                       schedule_work(&hid->reset_work);
+               if (!test_and_set_bit(HID_RESET_PENDING, &usbhid->iofl)) {
+                       schedule_work(&usbhid->reset_work);
                        goto done;
                }
        }
 
-       mod_timer(&hid->io_retry,
-                       jiffies + msecs_to_jiffies(hid->retry_delay));
+       mod_timer(&usbhid->io_retry,
+                       jiffies + msecs_to_jiffies(usbhid->retry_delay));
 done:
-       spin_unlock_irqrestore(&hid->inlock, flags);
+       spin_unlock_irqrestore(&usbhid->inlock, flags);
 }
 
 
@@ -230,28 +235,29 @@ static int hid_input_report(int type, struct urb *urb, int interrupt)
 static void hid_irq_in(struct urb *urb)
 {
        struct hid_device       *hid = urb->context;
+       struct usbhid_device    *usbhid = hid->driver_data;
        int                     status;
 
        switch (urb->status) {
                case 0:                 /* success */
-                       hid->retry_delay = 0;
+                       usbhid->retry_delay = 0;
                        hid_input_report(HID_INPUT_REPORT, urb, 1);
                        break;
                case -EPIPE:            /* stall */
-                       clear_bit(HID_IN_RUNNING, &hid->iofl);
-                       set_bit(HID_CLEAR_HALT, &hid->iofl);
-                       schedule_work(&hid->reset_work);
+                       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, &hid->iofl);
+                       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, &hid->iofl);
+                       clear_bit(HID_IN_RUNNING, &usbhid->iofl);
                        hid_io_error(hid);
                        return;
                default:                /* error */
@@ -260,12 +266,12 @@ static void hid_irq_in(struct urb *urb)
 
        status = usb_submit_urb(urb, GFP_ATOMIC);
        if (status) {
-               clear_bit(HID_IN_RUNNING, &hid->iofl);
+               clear_bit(HID_IN_RUNNING, &usbhid->iofl);
                if (status != -EPERM) {
                        err("can't resubmit intr, %s-%s/input%d, status %d",
-                                       hid->dev->bus->bus_name,
-                                       hid->dev->devpath,
-                                       hid->ifnum, status);
+                                       to_usb_device(hid->dev)->bus->bus_name,
+                                       to_usb_device(hid->dev)->devpath,
+                                       usbhid->ifnum, status);
                        hid_io_error(hid);
                }
        }
@@ -291,16 +297,17 @@ struct hid_field *hid_find_field_by_usage(struct hid_device *hid, __u32 wanted_u
 static int hid_submit_out(struct hid_device *hid)
 {
        struct hid_report *report;
+       struct usbhid_device *usbhid = hid->driver_data;
 
-       report = hid->out[hid->outtail];
+       report = usbhid->out[usbhid->outtail];
 
-       hid_output_report(report, hid->outbuf);
-       hid->urbout->transfer_buffer_length = ((report->size - 1) >> 3) + 1 + (report->id > 0);
-       hid->urbout->dev = hid->dev;
+       hid_output_report(report, usbhid->outbuf);
+       usbhid->urbout->transfer_buffer_length = ((report->size - 1) >> 3) + 1 + (report->id > 0);
+       usbhid->urbout->dev = to_usb_device(hid->dev);
 
        dbg("submitting out urb");
 
-       if (usb_submit_urb(hid->urbout, GFP_ATOMIC)) {
+       if (usb_submit_urb(usbhid->urbout, GFP_ATOMIC)) {
                err("usb_submit_urb(out) failed");
                return -1;
        }
@@ -313,42 +320,43 @@ static int hid_submit_ctrl(struct hid_device *hid)
        struct hid_report *report;
        unsigned char dir;
        int len;
+       struct usbhid_device *usbhid = hid->driver_data;
 
-       report = hid->ctrl[hid->ctrltail].report;
-       dir = hid->ctrl[hid->ctrltail].dir;
+       report = usbhid->ctrl[usbhid->ctrltail].report;
+       dir = usbhid->ctrl[usbhid->ctrltail].dir;
 
        len = ((report->size - 1) >> 3) + 1 + (report->id > 0);
        if (dir == USB_DIR_OUT) {
-               hid_output_report(report, hid->ctrlbuf);
-               hid->urbctrl->pipe = usb_sndctrlpipe(hid->dev, 0);
-               hid->urbctrl->transfer_buffer_length = len;
+               hid_output_report(report, usbhid->ctrlbuf);
+               usbhid->urbctrl->pipe = usb_sndctrlpipe(to_usb_device(hid->dev), 0);
+               usbhid->urbctrl->transfer_buffer_length = len;
        } else {
                int maxpacket, padlen;
 
-               hid->urbctrl->pipe = usb_rcvctrlpipe(hid->dev, 0);
-               maxpacket = usb_maxpacket(hid->dev, hid->urbctrl->pipe, 0);
+               usbhid->urbctrl->pipe = usb_rcvctrlpipe(to_usb_device(hid->dev), 0);
+               maxpacket = usb_maxpacket(to_usb_device(hid->dev), usbhid->urbctrl->pipe, 0);
                if (maxpacket > 0) {
                        padlen = (len + maxpacket - 1) / maxpacket;
                        padlen *= maxpacket;
-                       if (padlen > hid->bufsize)
-                               padlen = hid->bufsize;
+                       if (padlen > usbhid->bufsize)
+                               padlen = usbhid->bufsize;
                } else
                        padlen = 0;
-               hid->urbctrl->transfer_buffer_length = padlen;
+               usbhid->urbctrl->transfer_buffer_length = padlen;
        }
-       hid->urbctrl->dev = hid->dev;
+       usbhid->urbctrl->dev = to_usb_device(hid->dev);
 
-       hid->cr->bRequestType = USB_TYPE_CLASS | USB_RECIP_INTERFACE | dir;
-       hid->cr->bRequest = (dir == USB_DIR_OUT) ? HID_REQ_SET_REPORT : HID_REQ_GET_REPORT;
-       hid->cr->wValue = cpu_to_le16(((report->type + 1) << 8) | report->id);
-       hid->cr->wIndex = cpu_to_le16(hid->ifnum);
-       hid->cr->wLength = cpu_to_le16(len);
+       usbhid->cr->bRequestType = USB_TYPE_CLASS | USB_RECIP_INTERFACE | dir;
+       usbhid->cr->bRequest = (dir == USB_DIR_OUT) ? HID_REQ_SET_REPORT : HID_REQ_GET_REPORT;
+       usbhid->cr->wValue = cpu_to_le16(((report->type + 1) << 8) | report->id);
+       usbhid->cr->wIndex = cpu_to_le16(usbhid->ifnum);
+       usbhid->cr->wLength = cpu_to_le16(len);
 
        dbg("submitting ctrl urb: %s wValue=0x%04x wIndex=0x%04x wLength=%u",
-               hid->cr->bRequest == HID_REQ_SET_REPORT ? "Set_Report" : "Get_Report",
-               hid->cr->wValue, hid->cr->wIndex, hid->cr->wLength);
+               usbhid->cr->bRequest == HID_REQ_SET_REPORT ? "Set_Report" : "Get_Report",
+               usbhid->cr->wValue, usbhid->cr->wIndex, usbhid->cr->wLength);
 
-       if (usb_submit_urb(hid->urbctrl, GFP_ATOMIC)) {
+       if (usb_submit_urb(usbhid->urbctrl, GFP_ATOMIC)) {
                err("usb_submit_urb(ctrl) failed");
                return -1;
        }
@@ -363,6 +371,7 @@ static int hid_submit_ctrl(struct hid_device *hid)
 static void hid_irq_out(struct urb *urb)
 {
        struct hid_device *hid = urb->context;
+       struct usbhid_device *usbhid = hid->driver_data;
        unsigned long flags;
        int unplug = 0;
 
@@ -380,24 +389,24 @@ static void hid_irq_out(struct urb *urb)
                        warn("output irq status %d received", urb->status);
        }
 
-       spin_lock_irqsave(&hid->outlock, flags);
+       spin_lock_irqsave(&usbhid->outlock, flags);
 
        if (unplug)
-               hid->outtail = hid->outhead;
+               usbhid->outtail = usbhid->outhead;
        else
-               hid->outtail = (hid->outtail + 1) & (HID_OUTPUT_FIFO_SIZE - 1);
+               usbhid->outtail = (usbhid->outtail + 1) & (HID_OUTPUT_FIFO_SIZE - 1);
 
-       if (hid->outhead != hid->outtail) {
+       if (usbhid->outhead != usbhid->outtail) {
                if (hid_submit_out(hid)) {
-                       clear_bit(HID_OUT_RUNNING, &hid->iofl);
+                       clear_bit(HID_OUT_RUNNING, &usbhid->iofl);
                        wake_up(&hid->wait);
                }
-               spin_unlock_irqrestore(&hid->outlock, flags);
+               spin_unlock_irqrestore(&usbhid->outlock, flags);
                return;
        }
 
-       clear_bit(HID_OUT_RUNNING, &hid->iofl);
-       spin_unlock_irqrestore(&hid->outlock, flags);
+       clear_bit(HID_OUT_RUNNING, &usbhid->iofl);
+       spin_unlock_irqrestore(&usbhid->outlock, flags);
        wake_up(&hid->wait);
 }
 
@@ -408,15 +417,16 @@ static void hid_irq_out(struct urb *urb)
 static void hid_ctrl(struct urb *urb)
 {
        struct hid_device *hid = urb->context;
+       struct usbhid_device *usbhid = hid->driver_data;
        unsigned long flags;
        int unplug = 0;
 
-       spin_lock_irqsave(&hid->ctrllock, flags);
+       spin_lock_irqsave(&usbhid->ctrllock, flags);
 
        switch (urb->status) {
                case 0:                 /* success */
-                       if (hid->ctrl[hid->ctrltail].dir == USB_DIR_IN)
-                               hid_input_report(hid->ctrl[hid->ctrltail].report->type, urb, 0);
+                       if (usbhid->ctrl[usbhid->ctrltail].dir == USB_DIR_IN)
+                               hid_input_report(usbhid->ctrl[usbhid->ctrltail].report->type, urb, 0);
                        break;
                case -ESHUTDOWN:        /* unplug */
                        unplug = 1;
@@ -431,70 +441,71 @@ static void hid_ctrl(struct urb *urb)
        }
 
        if (unplug)
-               hid->ctrltail = hid->ctrlhead;
+               usbhid->ctrltail = usbhid->ctrlhead;
        else
-               hid->ctrltail = (hid->ctrltail + 1) & (HID_CONTROL_FIFO_SIZE - 1);
+               usbhid->ctrltail = (usbhid->ctrltail + 1) & (HID_CONTROL_FIFO_SIZE - 1);
 
-       if (hid->ctrlhead != hid->ctrltail) {
+       if (usbhid->ctrlhead != usbhid->ctrltail) {
                if (hid_submit_ctrl(hid)) {
-                       clear_bit(HID_CTRL_RUNNING, &hid->iofl);
+                       clear_bit(HID_CTRL_RUNNING, &usbhid->iofl);
                        wake_up(&hid->wait);
                }
-               spin_unlock_irqrestore(&hid->ctrllock, flags);
+               spin_unlock_irqrestore(&usbhid->ctrllock, flags);
                return;
        }
 
-       clear_bit(HID_CTRL_RUNNING, &hid->iofl);
-       spin_unlock_irqrestore(&hid->ctrllock, flags);
+       clear_bit(HID_CTRL_RUNNING, &usbhid->iofl);
+       spin_unlock_irqrestore(&usbhid->ctrllock, flags);
        wake_up(&hid->wait);
 }
 
-void hid_submit_report(struct hid_device *hid, struct hid_report *report, unsigned char dir)
+void usbhid_submit_report(struct hid_device *hid, struct hid_report *report, unsigned char dir)
 {
        int head;
        unsigned long flags;
+       struct usbhid_device *usbhid = hid->driver_data;
 
        if ((hid->quirks & HID_QUIRK_NOGET) && dir == USB_DIR_IN)
                return;
 
-       if (hid->urbout && dir == USB_DIR_OUT && report->type == HID_OUTPUT_REPORT) {
+       if (usbhid->urbout && dir == USB_DIR_OUT && report->type == HID_OUTPUT_REPORT) {
 
-               spin_lock_irqsave(&hid->outlock, flags);
+               spin_lock_irqsave(&usbhid->outlock, flags);
 
-               if ((head = (hid->outhead + 1) & (HID_OUTPUT_FIFO_SIZE - 1)) == hid->outtail) {
-                       spin_unlock_irqrestore(&hid->outlock, flags);
+               if ((head = (usbhid->outhead + 1) & (HID_OUTPUT_FIFO_SIZE - 1)) == usbhid->outtail) {
+                       spin_unlock_irqrestore(&usbhid->outlock, flags);
                        warn("output queue full");
                        return;
                }
 
-               hid->out[hid->outhead] = report;
-               hid->outhead = head;
+               usbhid->out[usbhid->outhead] = report;
+               usbhid->outhead = head;
 
-               if (!test_and_set_bit(HID_OUT_RUNNING, &hid->iofl))
+               if (!test_and_set_bit(HID_OUT_RUNNING, &usbhid->iofl))
                        if (hid_submit_out(hid))
-                               clear_bit(HID_OUT_RUNNING, &hid->iofl);
+                               clear_bit(HID_OUT_RUNNING, &usbhid->iofl);
 
-               spin_unlock_irqrestore(&hid->outlock, flags);
+               spin_unlock_irqrestore(&usbhid->outlock, flags);
                return;
        }
 
-       spin_lock_irqsave(&hid->ctrllock, flags);
+       spin_lock_irqsave(&usbhid->ctrllock, flags);
 
-       if ((head = (hid->ctrlhead + 1) & (HID_CONTROL_FIFO_SIZE - 1)) == hid->ctrltail) {
-               spin_unlock_irqrestore(&hid->ctrllock, flags);
+       if ((head = (usbhid->ctrlhead + 1) & (HID_CONTROL_FIFO_SIZE - 1)) == usbhid->ctrltail) {
+               spin_unlock_irqrestore(&usbhid->ctrllock, flags);
                warn("control queue full");
                return;
        }
 
-       hid->ctrl[hid->ctrlhead].report = report;
-       hid->ctrl[hid->ctrlhead].dir = dir;
-       hid->ctrlhead = head;
+       usbhid->ctrl[usbhid->ctrlhead].report = report;
+       usbhid->ctrl[usbhid->ctrlhead].dir = dir;
+       usbhid->ctrlhead = head;
 
-       if (!test_and_set_bit(HID_CTRL_RUNNING, &hid->iofl))
+       if (!test_and_set_bit(HID_CTRL_RUNNING, &usbhid->iofl))
                if (hid_submit_ctrl(hid))
-                       clear_bit(HID_CTRL_RUNNING, &hid->iofl);
+                       clear_bit(HID_CTRL_RUNNING, &usbhid->iofl);
 
-       spin_unlock_irqrestore(&hid->ctrllock, flags);
+       spin_unlock_irqrestore(&usbhid->ctrllock, flags);
 }
 
 static int usb_hidinput_input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value)
@@ -515,15 +526,17 @@ static int usb_hidinput_input_event(struct input_dev *dev, unsigned int type, un
        }
 
        hid_set_field(field, offset, value);
-       hid_submit_report(hid, field->report, USB_DIR_OUT);
+       usbhid_submit_report(hid, field->report, USB_DIR_OUT);
 
        return 0;
 }
 
-int hid_wait_io(struct hid_device *hid)
+int usbhid_wait_io(struct hid_device *hid)
 {
-       if (!wait_event_timeout(hid->wait, (!test_bit(HID_CTRL_RUNNING, &hid->iofl) &&
-                                       !test_bit(HID_OUT_RUNNING, &hid->iofl)),
+       struct usbhid_device *usbhid = hid->driver_data;
+
+       if (!wait_event_timeout(hid->wait, (!test_bit(HID_CTRL_RUNNING, &usbhid->iofl) &&
+                                       !test_bit(HID_OUT_RUNNING, &usbhid->iofl)),
                                        10*HZ)) {
                dbg("timeout waiting for ctrl or out queue to clear");
                return -1;
@@ -555,7 +568,7 @@ static int hid_get_class_descriptor(struct usb_device *dev, int ifnum,
        return result;
 }
 
-int hid_open(struct hid_device *hid)
+int usbhid_open(struct hid_device *hid)
 {
        ++hid->open;
        if (hid_start_in(hid))
@@ -563,22 +576,24 @@ int hid_open(struct hid_device *hid)
        return 0;
 }
 
-void hid_close(struct hid_device *hid)
+void usbhid_close(struct hid_device *hid)
 {
+       struct usbhid_device *usbhid = hid->driver_data;
+
        if (!--hid->open)
-               usb_kill_urb(hid->urbin);
+               usb_kill_urb(usbhid->urbin);
 }
 
 static int hidinput_open(struct input_dev *dev)
 {
        struct hid_device *hid = dev->private;
-       return hid_open(hid);
+       return usbhid_open(hid);
 }
 
 static void hidinput_close(struct input_dev *dev)
 {
        struct hid_device *hid = dev->private;
-       hid_close(hid);
+       usbhid_close(hid);
 }
 
 #define USB_VENDOR_ID_PANJIT           0x134c
@@ -590,26 +605,27 @@ static void hidinput_close(struct input_dev *dev)
  * Initialize all reports
  */
 
-void hid_init_reports(struct hid_device *hid)
+void usbhid_init_reports(struct hid_device *hid)
 {
        struct hid_report *report;
+       struct usbhid_device *usbhid = hid->driver_data;
        int err, ret;
 
        list_for_each_entry(report, &hid->report_enum[HID_INPUT_REPORT].report_list, list)
-               hid_submit_report(hid, report, USB_DIR_IN);
+               usbhid_submit_report(hid, report, USB_DIR_IN);
 
        list_for_each_entry(report, &hid->report_enum[HID_FEATURE_REPORT].report_list, list)
-               hid_submit_report(hid, report, USB_DIR_IN);
+               usbhid_submit_report(hid, report, USB_DIR_IN);
 
        err = 0;
-       ret = hid_wait_io(hid);
+       ret = usbhid_wait_io(hid);
        while (ret) {
                err |= ret;
-               if (test_bit(HID_CTRL_RUNNING, &hid->iofl))
-                       usb_kill_urb(hid->urbctrl);
-               if (test_bit(HID_OUT_RUNNING, &hid->iofl))
-                       usb_kill_urb(hid->urbout);
-               ret = hid_wait_io(hid);
+               if (test_bit(HID_CTRL_RUNNING, &usbhid->iofl))
+                       usb_kill_urb(usbhid->urbctrl);
+               if (test_bit(HID_OUT_RUNNING, &usbhid->iofl))
+                       usb_kill_urb(usbhid->urbout);
+               ret = usbhid_wait_io(hid);
        }
 
        if (err)
@@ -1022,13 +1038,15 @@ static void hid_find_max_report(struct hid_device *hid, unsigned int type, int *
 
 static int hid_alloc_buffers(struct usb_device *dev, struct hid_device *hid)
 {
-       if (!(hid->inbuf = usb_buffer_alloc(dev, hid->bufsize, GFP_ATOMIC, &hid->inbuf_dma)))
+       struct usbhid_device *usbhid = hid->driver_data;
+
+       if (!(usbhid->inbuf = usb_buffer_alloc(dev, usbhid->bufsize, GFP_ATOMIC, &usbhid->inbuf_dma)))
                return -1;
-       if (!(hid->outbuf = usb_buffer_alloc(dev, hid->bufsize, GFP_ATOMIC, &hid->outbuf_dma)))
+       if (!(usbhid->outbuf = usb_buffer_alloc(dev, usbhid->bufsize, GFP_ATOMIC, &usbhid->outbuf_dma)))
                return -1;
-       if (!(hid->cr = usb_buffer_alloc(dev, sizeof(*(hid->cr)), GFP_ATOMIC, &hid->cr_dma)))
+       if (!(usbhid->cr = usb_buffer_alloc(dev, sizeof(*(usbhid->cr)), GFP_ATOMIC, &usbhid->cr_dma)))
                return -1;
-       if (!(hid->ctrlbuf = usb_buffer_alloc(dev, hid->bufsize, GFP_ATOMIC, &hid->ctrlbuf_dma)))
+       if (!(usbhid->ctrlbuf = usb_buffer_alloc(dev, usbhid->bufsize, GFP_ATOMIC, &usbhid->ctrlbuf_dma)))
                return -1;
 
        return 0;
@@ -1036,14 +1054,16 @@ static int hid_alloc_buffers(struct usb_device *dev, struct hid_device *hid)
 
 static void hid_free_buffers(struct usb_device *dev, struct hid_device *hid)
 {
-       if (hid->inbuf)
-               usb_buffer_free(dev, hid->bufsize, hid->inbuf, hid->inbuf_dma);
-       if (hid->outbuf)
-               usb_buffer_free(dev, hid->bufsize, hid->outbuf, hid->outbuf_dma);
-       if (hid->cr)
-               usb_buffer_free(dev, sizeof(*(hid->cr)), hid->cr, hid->cr_dma);
-       if (hid->ctrlbuf)
-               usb_buffer_free(dev, hid->bufsize, hid->ctrlbuf, hid->ctrlbuf_dma);
+       struct usbhid_device *usbhid = hid->driver_data;
+
+       if (usbhid->inbuf)
+               usb_buffer_free(dev, usbhid->bufsize, usbhid->inbuf, usbhid->inbuf_dma);
+       if (usbhid->outbuf)
+               usb_buffer_free(dev, usbhid->bufsize, usbhid->outbuf, usbhid->outbuf_dma);
+       if (usbhid->cr)
+               usb_buffer_free(dev, sizeof(*(usbhid->cr)), usbhid->cr, usbhid->cr_dma);
+       if (usbhid->ctrlbuf)
+               usb_buffer_free(dev, usbhid->bufsize, usbhid->ctrlbuf, usbhid->ctrlbuf_dma);
 }
 
 /*
@@ -1069,6 +1089,7 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
        unsigned quirks = 0, rsize = 0;
        char *rdesc;
        int n, len, insize = 0;
+       struct usbhid_device *usbhid;
 
         /* Ignore all Wacom devices */
         if (le16_to_cpu(dev->descriptor.idVendor) == USB_VENDOR_ID_WACOM)
@@ -1138,13 +1159,19 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
        kfree(rdesc);
        hid->quirks = quirks;
 
-       hid->bufsize = HID_MIN_BUFFER_SIZE;
-       hid_find_max_report(hid, HID_INPUT_REPORT, &hid->bufsize);
-       hid_find_max_report(hid, HID_OUTPUT_REPORT, &hid->bufsize);
-       hid_find_max_report(hid, HID_FEATURE_REPORT, &hid->bufsize);
+       if (!(usbhid = kzalloc(sizeof(struct usbhid_device), GFP_KERNEL)))
+               goto fail;
+
+       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);
+       hid_find_max_report(hid, HID_FEATURE_REPORT, &usbhid->bufsize);
 
-       if (hid->bufsize > HID_MAX_BUFFER_SIZE)
-               hid->bufsize = HID_MAX_BUFFER_SIZE;
+       if (usbhid->bufsize > HID_MAX_BUFFER_SIZE)
+               usbhid->bufsize = HID_MAX_BUFFER_SIZE;
 
        hid_find_max_report(hid, HID_INPUT_REPORT, &insize);
 
@@ -1173,47 +1200,47 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
                        interval = hid_mousepoll_interval;
 
                if (usb_endpoint_dir_in(endpoint)) {
-                       if (hid->urbin)
+                       if (usbhid->urbin)
                                continue;
-                       if (!(hid->urbin = usb_alloc_urb(0, GFP_KERNEL)))
+                       if (!(usbhid->urbin = usb_alloc_urb(0, GFP_KERNEL)))
                                goto fail;
                        pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
-                       usb_fill_int_urb(hid->urbin, dev, pipe, hid->inbuf, insize,
+                       usb_fill_int_urb(usbhid->urbin, dev, pipe, usbhid->inbuf, insize,
                                         hid_irq_in, hid, interval);
-                       hid->urbin->transfer_dma = hid->inbuf_dma;
-                       hid->urbin->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+                       usbhid->urbin->transfer_dma = usbhid->inbuf_dma;
+                       usbhid->urbin->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
                } else {
-                       if (hid->urbout)
+                       if (usbhid->urbout)
                                continue;
-                       if (!(hid->urbout = usb_alloc_urb(0, GFP_KERNEL)))
+                       if (!(usbhid->urbout = usb_alloc_urb(0, GFP_KERNEL)))
                                goto fail;
                        pipe = usb_sndintpipe(dev, endpoint->bEndpointAddress);
-                       usb_fill_int_urb(hid->urbout, dev, pipe, hid->outbuf, 0,
+                       usb_fill_int_urb(usbhid->urbout, dev, pipe, usbhid->outbuf, 0,
                                         hid_irq_out, hid, interval);
-                       hid->urbout->transfer_dma = hid->outbuf_dma;
-                       hid->urbout->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+                       usbhid->urbout->transfer_dma = usbhid->outbuf_dma;
+                       usbhid->urbout->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
                }
        }
 
-       if (!hid->urbin) {
+       if (!usbhid->urbin) {
                err("couldn't find an input interrupt endpoint");
                goto fail;
        }
 
        init_waitqueue_head(&hid->wait);
 
-       INIT_WORK(&hid->reset_work, hid_reset);
-       setup_timer(&hid->io_retry, hid_retry_timeout, (unsigned long) hid);
+       INIT_WORK(&usbhid->reset_work, hid_reset);
+       setup_timer(&usbhid->io_retry, hid_retry_timeout, (unsigned long) hid);
 
-       spin_lock_init(&hid->inlock);
-       spin_lock_init(&hid->outlock);
-       spin_lock_init(&hid->ctrllock);
+       spin_lock_init(&usbhid->inlock);
+       spin_lock_init(&usbhid->outlock);
+       spin_lock_init(&usbhid->ctrllock);
 
        hid->version = le16_to_cpu(hdesc->bcdHID);
        hid->country = hdesc->bCountryCode;
-       hid->dev = dev;
-       hid->intf = intf;
-       hid->ifnum = interface->desc.bInterfaceNumber;
+       hid->dev = &dev->dev;
+       usbhid->intf = intf;
+       usbhid->ifnum = interface->desc.bInterfaceNumber;
 
        hid->name[0] = 0;
 
@@ -1245,15 +1272,15 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
        if (usb_string(dev, dev->descriptor.iSerialNumber, hid->uniq, 64) <= 0)
                hid->uniq[0] = 0;
 
-       hid->urbctrl = usb_alloc_urb(0, GFP_KERNEL);
-       if (!hid->urbctrl)
+       usbhid->urbctrl = usb_alloc_urb(0, GFP_KERNEL);
+       if (!usbhid->urbctrl)
                goto fail;
 
-       usb_fill_control_urb(hid->urbctrl, dev, 0, (void *) hid->cr,
-                            hid->ctrlbuf, 1, hid_ctrl, hid);
-       hid->urbctrl->setup_dma = hid->cr_dma;
-       hid->urbctrl->transfer_dma = hid->ctrlbuf_dma;
-       hid->urbctrl->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP);
+       usb_fill_control_urb(usbhid->urbctrl, dev, 0, (void *) usbhid->cr,
+                            usbhid->ctrlbuf, 1, hid_ctrl, hid);
+       usbhid->urbctrl->setup_dma = usbhid->cr_dma;
+       usbhid->urbctrl->transfer_dma = usbhid->ctrlbuf_dma;
+       usbhid->urbctrl->transfer_flags |= (URB_NO_TRANSFER_DMA_MAP | URB_NO_SETUP_DMA_MAP);
        hid->hidinput_input_event = usb_hidinput_input_event;
        hid->hidinput_open = hidinput_open;
        hid->hidinput_close = hidinput_close;
@@ -1261,9 +1288,9 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
        return hid;
 
 fail:
-       usb_free_urb(hid->urbin);
-       usb_free_urb(hid->urbout);
-       usb_free_urb(hid->urbctrl);
+       usb_free_urb(usbhid->urbin);
+       usb_free_urb(usbhid->urbout);
+       usb_free_urb(usbhid->urbctrl);
        hid_free_buffers(dev, hid);
        hid_free_device(hid);
 
@@ -1273,18 +1300,21 @@ fail:
 static void hid_disconnect(struct usb_interface *intf)
 {
        struct hid_device *hid = usb_get_intfdata (intf);
+       struct usbhid_device *usbhid;
 
        if (!hid)
                return;
 
-       spin_lock_irq(&hid->inlock);    /* Sync with error handler */
+       usbhid = hid->driver_data;
+
+       spin_lock_irq(&usbhid->inlock); /* Sync with error handler */
        usb_set_intfdata(intf, NULL);
-       spin_unlock_irq(&hid->inlock);
-       usb_kill_urb(hid->urbin);
-       usb_kill_urb(hid->urbout);
-       usb_kill_urb(hid->urbctrl);
+       spin_unlock_irq(&usbhid->inlock);
+       usb_kill_urb(usbhid->urbin);
+       usb_kill_urb(usbhid->urbout);
+       usb_kill_urb(usbhid->urbctrl);
 
-       del_timer_sync(&hid->io_retry);
+       del_timer_sync(&usbhid->io_retry);
        flush_scheduled_work();
 
        if (hid->claimed & HID_CLAIMED_INPUT)
@@ -1292,11 +1322,11 @@ static void hid_disconnect(struct usb_interface *intf)
        if (hid->claimed & HID_CLAIMED_HIDDEV)
                hiddev_disconnect(hid);
 
-       usb_free_urb(hid->urbin);
-       usb_free_urb(hid->urbctrl);
-       usb_free_urb(hid->urbout);
+       usb_free_urb(usbhid->urbin);
+       usb_free_urb(usbhid->urbctrl);
+       usb_free_urb(usbhid->urbout);
 
-       hid_free_buffers(hid->dev, hid);
+       hid_free_buffers(to_usb_device(hid->dev), hid);
        hid_free_device(hid);
 }
 
@@ -1313,7 +1343,7 @@ static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id)
        if (!(hid = usb_hid_configure(intf)))
                return -ENODEV;
 
-       hid_init_reports(hid);
+       usbhid_init_reports(hid);
        hid_dump_device(hid);
 
        if (!hidinput_connect(hid))
@@ -1329,6 +1359,13 @@ static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id)
                return -ENODEV;
        }
 
+       /* This only gets called when we are a single-input (most of the
+        * time). IOW, not a HID_QUIRK_MULTI_INPUT. The hid_ff_init() is
+        * only useful in this case, and not for multi-input quirks. */
+       if ((hid->claimed & HID_CLAIMED_INPUT) &&
+                       !(hid->quirks & HID_QUIRK_MULTI_INPUT))
+               hid_ff_init(hid);
+
        printk(KERN_INFO);
 
        if (hid->claimed & HID_CLAIMED_INPUT)
@@ -1359,12 +1396,13 @@ static int hid_probe(struct usb_interface *intf, const struct usb_device_id *id)
 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;
 
-       spin_lock_irq(&hid->inlock);    /* Sync with error handler */
-       set_bit(HID_SUSPENDED, &hid->iofl);
-       spin_unlock_irq(&hid->inlock);
-       del_timer(&hid->io_retry);
-       usb_kill_urb(hid->urbin);
+       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);
+       usb_kill_urb(usbhid->urbin);
        dev_dbg(&intf->dev, "suspend\n");
        return 0;
 }
@@ -1372,10 +1410,11 @@ static int hid_suspend(struct usb_interface *intf, pm_message_t message)
 static int hid_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_SUSPENDED, &hid->iofl);
-       hid->retry_delay = 0;
+       clear_bit(HID_SUSPENDED, &usbhid->iofl);
+       usbhid->retry_delay = 0;
        status = hid_start_in(hid);
        dev_dbg(&intf->dev, "resume status %d\n", status);
        return status;
index 7ecdafa..f8f660e 100644 (file)
@@ -70,8 +70,8 @@ static struct hid_ff_initializer inits[] = {
 int hid_ff_init(struct hid_device* hid)
 {
        struct hid_ff_initializer *init;
-       int vendor = le16_to_cpu(hid->dev->descriptor.idVendor);
-       int product = le16_to_cpu(hid->dev->descriptor.idProduct);
+       int vendor = le16_to_cpu(to_usb_device(hid->dev)->descriptor.idVendor);
+       int product = le16_to_cpu(to_usb_device(hid->dev)->descriptor.idProduct);
 
        for (init = inits; init->idVendor; init++)
                if (init->idVendor == vendor && init->idProduct == product)
index e977ba3..e474662 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/input.h>
 #include <linux/usb.h>
 #include <linux/hid.h>
+#include "usbhid.h"
 
 struct device_type {
        u16 idVendor;
@@ -75,7 +76,7 @@ static int hid_lgff_play(struct input_dev *dev, void *data, struct ff_effect *ef
                report->field[0]->value[2] = x;
                report->field[0]->value[3] = y;
                dbg("(x, y)=(%04x, %04x)", x, y);
-               hid_submit_report(hid, report, USB_DIR_OUT);
+               usbhid_submit_report(hid, report, USB_DIR_OUT);
                break;
 
        case FF_RUMBLE:
@@ -90,7 +91,7 @@ static int hid_lgff_play(struct input_dev *dev, void *data, struct ff_effect *ef
                report->field[0]->value[2] = left;
                report->field[0]->value[3] = right;
                dbg("(left, right)=(%04x, %04x)", left, right);
-               hid_submit_report(hid, report, USB_DIR_OUT);
+               usbhid_submit_report(hid, report, USB_DIR_OUT);
                break;
        }
        return 0;
index b4caea3..cbd2d53 100644 (file)
@@ -262,7 +262,7 @@ static void pidff_set_envelope_report(struct pidff_device *pidff,
        debug("attack %u => %d", envelope->attack_level,
              pidff->set_envelope[PID_ATTACK_LEVEL].value[0]);
 
-       hid_submit_report(pidff->hid, pidff->reports[PID_SET_ENVELOPE],
+       usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_ENVELOPE],
                          USB_DIR_OUT);
 }
 
@@ -289,7 +289,7 @@ static void pidff_set_constant_force_report(struct pidff_device *pidff,
        pidff_set_signed(&pidff->set_constant[PID_MAGNITUDE],
                         effect->u.constant.level);
 
-       hid_submit_report(pidff->hid, pidff->reports[PID_SET_CONSTANT],
+       usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_CONSTANT],
                          USB_DIR_OUT);
 }
 
@@ -324,7 +324,7 @@ static void pidff_set_effect_report(struct pidff_device *pidff,
                                pidff->effect_direction);
        pidff->set_effect[PID_START_DELAY].value[0] = effect->replay.delay;
 
-       hid_submit_report(pidff->hid, pidff->reports[PID_SET_EFFECT],
+       usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_EFFECT],
                          USB_DIR_OUT);
 }
 
@@ -356,7 +356,7 @@ static void pidff_set_periodic_report(struct pidff_device *pidff,
        pidff_set(&pidff->set_periodic[PID_PHASE], effect->u.periodic.phase);
        pidff->set_periodic[PID_PERIOD].value[0] = effect->u.periodic.period;
 
-       hid_submit_report(pidff->hid, pidff->reports[PID_SET_PERIODIC],
+       usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_PERIODIC],
                          USB_DIR_OUT);
 
 }
@@ -398,8 +398,8 @@ static void pidff_set_condition_report(struct pidff_device *pidff,
                          effect->u.condition[i].left_saturation);
                pidff_set(&pidff->set_condition[PID_DEAD_BAND],
                          effect->u.condition[i].deadband);
-               hid_wait_io(pidff->hid);
-               hid_submit_report(pidff->hid, pidff->reports[PID_SET_CONDITION],
+               usbhid_wait_io(pidff->hid);
+               usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_CONDITION],
                                  USB_DIR_OUT);
        }
 }
@@ -440,7 +440,7 @@ static void pidff_set_ramp_force_report(struct pidff_device *pidff,
                         effect->u.ramp.start_level);
        pidff_set_signed(&pidff->set_ramp[PID_RAMP_END],
                         effect->u.ramp.end_level);
-       hid_submit_report(pidff->hid, pidff->reports[PID_SET_RAMP],
+       usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_RAMP],
                          USB_DIR_OUT);
 }
 
@@ -465,19 +465,19 @@ static int pidff_request_effect_upload(struct pidff_device *pidff, int efnum)
        int j;
 
        pidff->create_new_effect_type->value[0] = efnum;
-       hid_submit_report(pidff->hid, pidff->reports[PID_CREATE_NEW_EFFECT],
+       usbhid_submit_report(pidff->hid, pidff->reports[PID_CREATE_NEW_EFFECT],
                          USB_DIR_OUT);
        debug("create_new_effect sent, type: %d", efnum);
 
        pidff->block_load[PID_EFFECT_BLOCK_INDEX].value[0] = 0;
        pidff->block_load_status->value[0] = 0;
-       hid_wait_io(pidff->hid);
+       usbhid_wait_io(pidff->hid);
 
        for (j = 0; j < 60; j++) {
                debug("pid_block_load requested");
-               hid_submit_report(pidff->hid, pidff->reports[PID_BLOCK_LOAD],
+               usbhid_submit_report(pidff->hid, pidff->reports[PID_BLOCK_LOAD],
                                  USB_DIR_IN);
-               hid_wait_io(pidff->hid);
+               usbhid_wait_io(pidff->hid);
                if (pidff->block_load_status->value[0] ==
                    pidff->status_id[PID_BLOCK_LOAD_SUCCESS]) {
                        debug("device reported free memory: %d bytes",
@@ -513,8 +513,8 @@ static void pidff_playback_pid(struct pidff_device *pidff, int pid_id, int n)
                pidff->effect_operation[PID_LOOP_COUNT].value[0] = n;
        }
 
-       hid_wait_io(pidff->hid);
-       hid_submit_report(pidff->hid, pidff->reports[PID_EFFECT_OPERATION],
+       usbhid_wait_io(pidff->hid);
+       usbhid_submit_report(pidff->hid, pidff->reports[PID_EFFECT_OPERATION],
                          USB_DIR_OUT);
 }
 
@@ -536,7 +536,7 @@ static int pidff_playback(struct input_dev *dev, int effect_id, int value)
 static void pidff_erase_pid(struct pidff_device *pidff, int pid_id)
 {
        pidff->block_free[PID_EFFECT_BLOCK_INDEX].value[0] = pid_id;
-       hid_submit_report(pidff->hid, pidff->reports[PID_BLOCK_FREE],
+       usbhid_submit_report(pidff->hid, pidff->reports[PID_BLOCK_FREE],
                          USB_DIR_OUT);
 }
 
@@ -716,7 +716,7 @@ static void pidff_set_gain(struct input_dev *dev, u16 gain)
        struct pidff_device *pidff = dev->ff->private;
 
        pidff_set(&pidff->device_gain[PID_DEVICE_GAIN_FIELD], gain);
-       hid_submit_report(pidff->hid, pidff->reports[PID_DEVICE_GAIN],
+       usbhid_submit_report(pidff->hid, pidff->reports[PID_DEVICE_GAIN],
                          USB_DIR_OUT);
 }
 
@@ -741,7 +741,7 @@ static void pidff_autocenter(struct pidff_device *pidff, u16 magnitude)
        pidff_set(&pidff->set_effect[PID_GAIN], magnitude);
        pidff->set_effect[PID_START_DELAY].value[0] = 0;
 
-       hid_submit_report(pidff->hid, pidff->reports[PID_SET_EFFECT],
+       usbhid_submit_report(pidff->hid, pidff->reports[PID_SET_EFFECT],
                          USB_DIR_OUT);
 }
 
@@ -1165,19 +1165,19 @@ static void pidff_reset(struct pidff_device *pidff)
 
        pidff->device_control->value[0] = pidff->control_id[PID_RESET];
        /* We reset twice as sometimes hid_wait_io isn't waiting long enough */
-       hid_submit_report(hid, pidff->reports[PID_DEVICE_CONTROL], USB_DIR_OUT);
-       hid_wait_io(hid);
-       hid_submit_report(hid, pidff->reports[PID_DEVICE_CONTROL], USB_DIR_OUT);
-       hid_wait_io(hid);
+       usbhid_submit_report(hid, pidff->reports[PID_DEVICE_CONTROL], USB_DIR_OUT);
+       usbhid_wait_io(hid);
+       usbhid_submit_report(hid, pidff->reports[PID_DEVICE_CONTROL], USB_DIR_OUT);
+       usbhid_wait_io(hid);
 
        pidff->device_control->value[0] =
                pidff->control_id[PID_ENABLE_ACTUATORS];
-       hid_submit_report(hid, pidff->reports[PID_DEVICE_CONTROL], USB_DIR_OUT);
-       hid_wait_io(hid);
+       usbhid_submit_report(hid, pidff->reports[PID_DEVICE_CONTROL], USB_DIR_OUT);
+       usbhid_wait_io(hid);
 
        /* pool report is sometimes messed up, refetch it */
-       hid_submit_report(hid, pidff->reports[PID_POOL], USB_DIR_IN);
-       hid_wait_io(hid);
+       usbhid_submit_report(hid, pidff->reports[PID_POOL], USB_DIR_IN);
+       usbhid_wait_io(hid);
 
        if (pidff->pool[PID_SIMULTANEOUS_MAX].value) {
                int sim_effects = pidff->pool[PID_SIMULTANEOUS_MAX].value[0];
@@ -1189,9 +1189,9 @@ static void pidff_reset(struct pidff_device *pidff)
                                break;
                        }
                        debug("pid_pool requested again");
-                       hid_submit_report(hid, pidff->reports[PID_POOL],
+                       usbhid_submit_report(hid, pidff->reports[PID_POOL],
                                          USB_DIR_IN);
-                       hid_wait_io(hid);
+                       usbhid_wait_io(hid);
                }
        }
 }
@@ -1277,7 +1277,7 @@ int hid_pidff_init(struct hid_device *hid)
 
        if (test_bit(FF_GAIN, dev->ffbit)) {
                pidff_set(&pidff->device_gain[PID_DEVICE_GAIN_FIELD], 0xffff);
-               hid_submit_report(pidff->hid, pidff->reports[PID_DEVICE_GAIN],
+               usbhid_submit_report(pidff->hid, pidff->reports[PID_DEVICE_GAIN],
                                  USB_DIR_OUT);
        }
 
index 1cd1418..ab67331 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/usb.h>
 
 #include <linux/hid.h>
+#include "usbhid.h"
 
 /* Usages for thrustmaster devices I know about */
 #define THRUSTMASTER_USAGE_RUMBLE_LR   (HID_UP_GENDESK | 0xbb)
@@ -70,7 +71,7 @@ static int hid_tmff_play(struct input_dev *dev, void *data, struct ff_effect *ef
        tmff->rumble->value[0] = left;
        tmff->rumble->value[1] = right;
        dbg("(left,right)=(%08x, %08x)", left, right);
-       hid_submit_report(hid, tmff->report, USB_DIR_OUT);
+       usbhid_submit_report(hid, tmff->report, USB_DIR_OUT);
 
        return 0;
 }
index af1bfae..7bd8238 100644 (file)
@@ -28,6 +28,7 @@
 #include <linux/input.h>
 #include <linux/usb.h>
 #include <linux/hid.h>
+#include "usbhid.h"
 
 struct zpff_device {
        struct hid_report *report;
@@ -56,7 +57,7 @@ static int hid_zpff_play(struct input_dev *dev, void *data,
        zpff->report->field[2]->value[0] = left;
        zpff->report->field[3]->value[0] = right;
        debug("running with 0x%02x 0x%02x", left, right);
-       hid_submit_report(hid, zpff->report, USB_DIR_OUT);
+       usbhid_submit_report(hid, zpff->report, USB_DIR_OUT);
 
        return 0;
 }
@@ -101,7 +102,7 @@ int hid_zpff_init(struct hid_device *hid)
        zpff->report->field[1]->value[0] = 0x02;
        zpff->report->field[2]->value[0] = 0x00;
        zpff->report->field[3]->value[0] = 0x00;
-       hid_submit_report(hid, zpff->report, USB_DIR_OUT);
+       usbhid_submit_report(hid, zpff->report, USB_DIR_OUT);
 
        printk(KERN_INFO "Force feedback for Zeroplus based devices by "
               "Anssi Hannula <anssi.hannula@gmail.com>\n");
index 07d7996..0c2647e 100644 (file)
@@ -240,7 +240,7 @@ static int hiddev_release(struct inode * inode, struct file * file)
 
        if (!--list->hiddev->open) {
                if (list->hiddev->exist)
-                       hid_close(list->hiddev->hid);
+                       usbhid_close(list->hiddev->hid);
                else
                        kfree(list->hiddev);
        }
@@ -271,7 +271,7 @@ static int hiddev_open(struct inode *inode, struct file *file)
 
        if (!list->hiddev->open++)
                if (list->hiddev->exist)
-                       hid_open(hiddev_table[i]->hid);
+                       usbhid_open(hiddev_table[i]->hid);
 
        return 0;
 }
@@ -383,7 +383,7 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
        struct hiddev_list *list = file->private_data;
        struct hiddev *hiddev = list->hiddev;
        struct hid_device *hid = hiddev->hid;
-       struct usb_device *dev = hid->dev;
+       struct usb_device *dev = to_usb_device(hid->dev);
        struct hiddev_collection_info cinfo;
        struct hiddev_report_info rinfo;
        struct hiddev_field_info finfo;
@@ -392,6 +392,7 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
        struct hiddev_devinfo dinfo;
        struct hid_report *report;
        struct hid_field *field;
+       struct usbhid_device *usbhid = hid->driver_data;
        void __user *user_arg = (void __user *)arg;
        int i;
 
@@ -421,7 +422,7 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
                dinfo.bustype = BUS_USB;
                dinfo.busnum = dev->bus->busnum;
                dinfo.devnum = dev->devnum;
-               dinfo.ifnum = hid->ifnum;
+               dinfo.ifnum = usbhid->ifnum;
                dinfo.vendor = le16_to_cpu(dev->descriptor.idVendor);
                dinfo.product = le16_to_cpu(dev->descriptor.idProduct);
                dinfo.version = le16_to_cpu(dev->descriptor.bcdDevice);
@@ -480,7 +481,7 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
                }
 
        case HIDIOCINITREPORT:
-               hid_init_reports(hid);
+               usbhid_init_reports(hid);
 
                return 0;
 
@@ -494,8 +495,8 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
                if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
                        return -EINVAL;
 
-               hid_submit_report(hid, report, USB_DIR_IN);
-               hid_wait_io(hid);
+               usbhid_submit_report(hid, report, USB_DIR_IN);
+               usbhid_wait_io(hid);
 
                return 0;
 
@@ -509,8 +510,8 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
                if ((report = hiddev_lookup_report(hid, &rinfo)) == NULL)
                        return -EINVAL;
 
-               hid_submit_report(hid, report, USB_DIR_OUT);
-               hid_wait_io(hid);
+               usbhid_submit_report(hid, report, USB_DIR_OUT);
+               usbhid_wait_io(hid);
 
                return 0;
 
@@ -746,6 +747,7 @@ static struct usb_class_driver hiddev_class = {
 int hiddev_connect(struct hid_device *hid)
 {
        struct hiddev *hiddev;
+       struct usbhid_device *usbhid = hid->driver_data;
        int i;
        int retval;
 
@@ -761,7 +763,7 @@ int hiddev_connect(struct hid_device *hid)
        if (!(hiddev = kzalloc(sizeof(struct hiddev), GFP_KERNEL)))
                return -1;
 
-       retval = usb_register_dev(hid->intf, &hiddev_class);
+       retval = usb_register_dev(usbhid->intf, &hiddev_class);
        if (retval) {
                err("Not able to get a minor for this device.");
                kfree(hiddev);
@@ -773,10 +775,10 @@ int hiddev_connect(struct hid_device *hid)
        hiddev->hid = hid;
        hiddev->exist = 1;
 
-       hid->minor = hid->intf->minor;
+       hid->minor = usbhid->intf->minor;
        hid->hiddev = hiddev;
 
-       hiddev_table[hid->intf->minor - HIDDEV_MINOR_BASE] = hiddev;
+       hiddev_table[usbhid->intf->minor - HIDDEV_MINOR_BASE] = hiddev;
 
        return 0;
 }
@@ -789,14 +791,15 @@ static struct usb_class_driver hiddev_class;
 void hiddev_disconnect(struct hid_device *hid)
 {
        struct hiddev *hiddev = hid->hiddev;
+       struct usbhid_device *usbhid = hid->driver_data;
 
        hiddev->exist = 0;
 
        hiddev_table[hiddev->hid->minor - HIDDEV_MINOR_BASE] = NULL;
-       usb_deregister_dev(hiddev->hid->intf, &hiddev_class);
+       usb_deregister_dev(usbhid->intf, &hiddev_class);
 
        if (hiddev->open) {
-               hid_close(hiddev->hid);
+               usbhid_close(hiddev->hid);
                wake_up_interruptible(&hiddev->wait);
        } else {
                kfree(hiddev);
diff --git a/drivers/usb/input/usbhid.h b/drivers/usb/input/usbhid.h
new file mode 100644 (file)
index 0000000..830107e
--- /dev/null
@@ -0,0 +1,84 @@
+#ifndef __USBHID_H
+#define __USBHID_H
+
+/*
+ *  Copyright (c) 1999 Andreas Gal
+ *  Copyright (c) 2000-2001 Vojtech Pavlik
+ *  Copyright (c) 2006 Jiri Kosina
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/list.h>
+#include <linux/timer.h>
+#include <linux/workqueue.h>
+#include <linux/input.h>
+
+/*  API provided by hid-core.c for USB HID drivers */
+int usbhid_wait_io(struct hid_device* hid);
+void usbhid_close(struct hid_device *hid);
+int usbhid_open(struct hid_device *hid);
+void usbhid_init_reports(struct hid_device *hid);
+void usbhid_submit_report(struct hid_device *hid, struct hid_report *report, unsigned char dir);
+
+/*
+ * USB-specific HID struct, to be pointed to
+ * from struct hid_device->driver_data
+ */
+
+struct usbhid_device {
+       struct hid_device *hid;                                         /* pointer to corresponding HID dev */
+
+       struct usb_interface *intf;                                     /* USB interface */
+       int ifnum;                                                      /* USB interface number */
+
+       unsigned int bufsize;                                           /* URB buffer size */
+
+       struct urb *urbin;                                              /* Input URB */
+       char *inbuf;                                                    /* Input buffer */
+       dma_addr_t inbuf_dma;                                           /* Input buffer dma */
+       spinlock_t inlock;                                              /* Input fifo spinlock */
+
+       struct urb *urbctrl;                                            /* Control URB */
+       struct usb_ctrlrequest *cr;                                     /* Control request struct */
+       dma_addr_t cr_dma;                                              /* Control request struct dma */
+       struct hid_control_fifo ctrl[HID_CONTROL_FIFO_SIZE];            /* Control fifo */
+       unsigned char ctrlhead, ctrltail;                               /* Control fifo head & tail */
+       char *ctrlbuf;                                                  /* Control buffer */
+       dma_addr_t ctrlbuf_dma;                                         /* Control buffer dma */
+       spinlock_t ctrllock;                                            /* Control fifo spinlock */
+
+       struct urb *urbout;                                             /* Output URB */
+       struct hid_report *out[HID_CONTROL_FIFO_SIZE];                  /* Output pipe fifo */
+       unsigned char outhead, outtail;                                 /* Output pipe fifo head & tail */
+       char *outbuf;                                                   /* Output buffer */
+       dma_addr_t outbuf_dma;                                          /* Output buffer dma */
+       spinlock_t outlock;                                             /* Output fifo spinlock */
+
+       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 */
+       unsigned int retry_delay;                                       /* Delay length in ms */
+       struct work_struct reset_work;                                  /* Task context for resets */
+
+};
+
+#endif
+
index 0473b45..fc6f742 100644 (file)
@@ -410,41 +410,7 @@ struct hid_device {                                                        /* device report descriptor */
        unsigned country;                                               /* HID country */
        struct hid_report_enum report_enum[HID_REPORT_TYPES];
 
-       struct usb_device *dev;                                         /* device */
-
-       /* USB specific fields */
-
-       struct usb_interface *intf;                                     /* USB interface */
-       int ifnum;                                                      /* USB interface number */
-
-       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 */
-       unsigned int retry_delay;                                       /* Delay length in ms */
-       struct work_struct reset_work;                                  /* Task context for resets */
-
-       unsigned int bufsize;                                           /* URB buffer size */
-
-       struct urb *urbin;                                              /* Input URB */
-       char *inbuf;                                                    /* Input buffer */
-       dma_addr_t inbuf_dma;                                           /* Input buffer dma */
-       spinlock_t inlock;                                              /* Input fifo spinlock */
-
-       struct urb *urbctrl;                                            /* Control URB */
-       struct usb_ctrlrequest *cr;                                     /* Control request struct */
-       dma_addr_t cr_dma;                                              /* Control request struct dma */
-       struct hid_control_fifo ctrl[HID_CONTROL_FIFO_SIZE];            /* Control fifo */
-       unsigned char ctrlhead, ctrltail;                               /* Control fifo head & tail */
-       char *ctrlbuf;                                                  /* Control buffer */
-       dma_addr_t ctrlbuf_dma;                                         /* Control buffer dma */
-       spinlock_t ctrllock;                                            /* Control fifo spinlock */
-
-       struct urb *urbout;                                             /* Output URB */
-       struct hid_report *out[HID_CONTROL_FIFO_SIZE];                  /* Output pipe fifo */
-       unsigned char outhead, outtail;                                 /* Output pipe fifo head & tail */
-       char *outbuf;                                                   /* Output buffer */
-       dma_addr_t outbuf_dma;                                          /* Output buffer dma */
-       spinlock_t outlock;                                             /* Output fifo spinlock */
+       struct device *dev;                                             /* device */
 
        unsigned claimed;                                               /* Claimed by hidinput, hiddev? */
        unsigned quirks;                                                /* Various quirks the device can pull on us */