[PATCH] Generic HID layer - USB API
- '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>
This commit is contained in:
Родитель
229695e51e
Коммит
4916b3a57f
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
if (hid->bufsize > HID_MAX_BUFFER_SIZE)
|
||||
hid->bufsize = HID_MAX_BUFFER_SIZE;
|
||||
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 (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 */
|
||||
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);
|
||||
usbhid = hid->driver_data;
|
||||
|
||||
del_timer_sync(&hid->io_retry);
|
||||
spin_lock_irq(&usbhid->inlock); /* Sync with error handler */
|
||||
usb_set_intfdata(intf, NULL);
|
||||
spin_unlock_irq(&usbhid->inlock);
|
||||
usb_kill_urb(usbhid->urbin);
|
||||
usb_kill_urb(usbhid->urbout);
|
||||
usb_kill_urb(usbhid->urbctrl);
|
||||
|
||||
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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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 */
|
||||
|
|
Загрузка…
Ссылка в новой задаче