[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:
Jiri Kosina 2006-12-08 18:41:03 +01:00 committed by Greg Kroah-Hartman
parent 229695e51e
commit 4916b3a57f
10 changed files with 371 additions and 282 deletions

View 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;
}

View 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;
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;

View 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)

View 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;

View 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);
}

View 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;
}

View 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");

View 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);

View File

@ -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

View 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 */