Commit 4916b3a5 authored by Jiri Kosina's avatar Jiri Kosina Committed by Greg Kroah-Hartman

[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: default avatarJiri Kosina <jkosina@suse.cz>
Signed-off-by: Marcel Holtmann's avatarMarcel Holtmann <marcel@holtmann.org>
Cc: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 229695e5
......@@ -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;
}
......
This diff is collapsed.
......@@ -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);
......
#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 */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment