Commit eba9fb15 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

merge

parents 52d820cb 118d79a8
......@@ -454,6 +454,7 @@ but some optional utilities are provided to simplify common tasks.
</para>
!Edrivers/usb/gadget/usbstring.c
!Edrivers/usb/gadget/config.c
</sect1>
</chapter>
......
......@@ -70,7 +70,9 @@ one or more packets could finish before an error stops further endpoint I/O.
(That is, if drivers see this it's a bug.)
-EPROTO (*) a) bitstuff error
b) unknown USB error
b) no response packet received within the
prescribed bus turn-around time
c) unknown USB error
-EILSEQ (*) CRC mismatch
......
CHANGES
- Created based off of scanner & INSTALL from the original touchscreen
driver on freshmeat (http://freshmeat.net/projects/3mtouchscreendriver)
- Amended for linux-2.4.18, then 2.4.19
- Complete rewrite using Linux Input in 2.6.3
Unfortunately no calibration support at this time
DRIVER NOTES:
Installation is simple, you only need to add Linux Input, Linux USB, and the
driver to the kernel. The driver can also be optionally built as a module.
If you have another MicroTouch device that you wish to experiment with
or try using this driver with, but the Vendor and Product ID's are not
coded in, don't despair. If the driver was compiled as a module, you can
pass options to the driver. Simply try:
/sbin/modprobe mtouchusb vendor=0x#### product=0x****
If it works, send me the iVendor & iProduct (or a patch) and I will add...
This driver appears to be one of possible 2 Linux USB Input Touchscreen
drivers. Although 3M produces a binary only driver available for
download, I persist in updating this driver since I would like to use the
touchscreen for embedded apps using QTEmbedded, DirectFB, etc. So I feel the
logical choice is to use Linux Imput.
A little info about the MicroTouch USB controller (14-206):
Y is inverted, and the device has a total possible resolution of 0 - 65535.
Y is inverted by the driver by:
input.absmin[ABS_Y] = MTOUCHUSB_MAX_YC;
input.absmax[ABS_Y] = MTOUCHUSB_MIN_YC;
absmin & absmax are also used to scale the data, sine it is rather high
resolution.
---------------touch screen area-----------------
I MicroTouch (xmax,ymax) @I
I X I
I ########visible monitor area############## I
I #@ (xmin,ymin) # I
I # # I
I # # I
I # # I
I # # I
I # # I
I Y # # I
I # # I
I # # I
I # # I
I # # I
I # # I
I # (xmax,ymax) @# I
I ########################################## I
I I
I@ MicroTouch (xmin,ymin) I
-------------------------------------------------
Currently there is no way to calibrate the device via this driver. Perhaps
at some point an abstract function will be placed into evdev so generic
functions like calibrations, resets, and vendor information can be requested
(And the drivers would handle the vendor specific tasks).
ADDITIONAL INFORMATION/UPDATES:
http://groomlakelabs.com/grandamp/code/microtouch/
TODO:
Implement a control urb again to handle requests to and from the device
such as calibration, etc.
DISCLAMER:
I am not a MicroTouch/3M employee, nor have I ever been. 3M does not support
this driver! If you want touch drivers only supported within X, please go to:
http://www.3m.com/3MTouchSystems/downloads/
This diff is collapsed.
......@@ -135,7 +135,7 @@ static int iforce_usb_probe(struct usb_interface *intf,
struct usb_endpoint_descriptor *epirq, *epout;
struct iforce *iforce;
interface = &intf->altsetting[intf->act_altsetting];
interface = intf->cur_altsetting;
epirq = &interface->endpoint[0].desc;
epout = &interface->endpoint[1].desc;
......
......@@ -1040,6 +1040,52 @@ static struct net_device_stats *stir_net_get_stats(struct net_device *dev)
return &stir->stats;
}
/*
* Parse the various endpoints and find the one we need.
*
* The endpoint are the pipes used to communicate with the USB device.
* The spec defines 2 endpoints of type bulk transfer, one in, and one out.
* These are used to pass frames back and forth with the dongle.
*/
static int stir_setup_usb(struct stir_cb *stir, struct usb_interface *intf)
{
struct usb_device *usbdev = interface_to_usbdev(intf);
const struct usb_host_interface *interface = intf->cur_altsetting;
const struct usb_endpoint_descriptor *ep_in = NULL;
const struct usb_endpoint_descriptor *ep_out = NULL;
int i;
if (interface->desc.bNumEndpoints != 2) {
WARNING("%s: expected two endpoints\n", __FUNCTION__);
return -ENODEV;
}
for(i = 0; i < interface->desc.bNumEndpoints; i++) {
const struct usb_endpoint_descriptor *ep
= &interface->endpoint[i].desc;
if ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
== USB_ENDPOINT_XFER_BULK) {
/* We need to find an IN and an OUT */
if ((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN)
ep_in = ep;
else
ep_out = ep;
} else
WARNING("%s: unknown endpoint type 0x%x\n",
__FUNCTION__, ep->bmAttributes);
}
if (!ep_in || !ep_out)
return -EIO;
stir->tx_bulkpipe = usb_sndbulkpipe(usbdev,
ep_out->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
stir->rx_intpipe = usb_rcvintpipe(usbdev,
ep_in->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK);
return 0;
}
/*
* This routine is called by the USB subsystem for each new device
* in the system. We need to check if the device is ours, and in
......
......@@ -20,10 +20,15 @@ obj-$(CONFIG_USB_PRINTER) += class/
obj-$(CONFIG_USB_STORAGE) += storage/
obj-$(CONFIG_USB_AIPTEK) += input/
obj-$(CONFIG_USB_ATI_REMOTE) += input/
obj-$(CONFIG_USB_HID) += input/
obj-$(CONFIG_USB_KBD) += input/
obj-$(CONFIG_USB_KBTAB) += input/
obj-$(CONFIG_USB_MOUSE) += input/
obj-$(CONFIG_USB_MTOUCH) += input/
obj-$(CONFIG_USB_POWERMATE) += input/
obj-$(CONFIG_USB_WACOM) += input/
obj-$(CONFIG_USB_XPAD) += input/
obj-$(CONFIG_USB_DABUSB) += media/
obj-$(CONFIG_USB_DSBR) += media/
......
......@@ -3,7 +3,7 @@
/*
* audio.c -- USB Audio Class driver
*
* Copyright (C) 1999, 2000, 2001
* Copyright (C) 1999, 2000, 2001, 2003, 2004
* Alan Cox (alan@lxorguk.ukuu.org.uk)
* Thomas Sailer (sailer@ife.ee.ethz.ch)
*
......@@ -101,6 +101,8 @@
* Fix SNDCTL_DSP_STEREO API violation
* 2003-04-08: Oliver Neukum (oliver@neukum.name):
* Setting a configuration is done by usbcore and must not be overridden
* 2004-02-27: Workaround for broken synch descriptors
*
*/
/*
......@@ -1542,12 +1544,13 @@ static int set_format_in(struct usb_audiodev *as)
alts->endpoint[1].desc.bmAttributes != 0x01 ||
alts->endpoint[1].desc.bSynchAddress != 0 ||
alts->endpoint[1].desc.bEndpointAddress != (alts->endpoint[0].desc.bSynchAddress & 0x7f)) {
printk(KERN_ERR "usbaudio: device %d interface %d altsetting %d invalid synch pipe\n",
printk(KERN_WARNING "usbaudio: device %d interface %d altsetting %d claims adaptive in "
"but has invalid synch pipe; treating as asynchronous in\n",
dev->devnum, u->interface, fmt->altsetting);
return -1;
} else {
u->syncpipe = usb_sndisocpipe(dev, alts->endpoint[1].desc.bEndpointAddress & 0xf);
u->syncinterval = alts->endpoint[1].desc.bRefresh;
}
u->syncpipe = usb_sndisocpipe(dev, alts->endpoint[1].desc.bEndpointAddress & 0xf);
u->syncinterval = alts->endpoint[1].desc.bRefresh;
}
if (d->srate < fmt->sratelo)
d->srate = fmt->sratelo;
......@@ -1637,12 +1640,13 @@ static int set_format_out(struct usb_audiodev *as)
alts->endpoint[1].desc.bmAttributes != 0x01 ||
alts->endpoint[1].desc.bSynchAddress != 0 ||
alts->endpoint[1].desc.bEndpointAddress != (alts->endpoint[0].desc.bSynchAddress | 0x80)) {
printk(KERN_ERR "usbaudio: device %d interface %d altsetting %d invalid synch pipe\n",
printk(KERN_WARNING "usbaudio: device %d interface %d altsetting %d claims asynch out "
"but has invalid synch pipe; treating as adaptive out\n",
dev->devnum, u->interface, fmt->altsetting);
return -1;
} else {
u->syncpipe = usb_rcvisocpipe(dev, alts->endpoint[1].desc.bEndpointAddress & 0xf);
u->syncinterval = alts->endpoint[1].desc.bRefresh;
}
u->syncpipe = usb_rcvisocpipe(dev, alts->endpoint[1].desc.bEndpointAddress & 0xf);
u->syncinterval = alts->endpoint[1].desc.bRefresh;
}
if (d->srate < fmt->sratelo)
d->srate = fmt->sratelo;
......
......@@ -72,13 +72,10 @@ static int usb_parse_endpoint(struct usb_host_endpoint *endpoint, unsigned char
return buffer - buffer0;
}
static void usb_release_intf(struct device *dev)
static void usb_free_intf(struct usb_interface *intf)
{
struct usb_interface *intf;
int j;
intf = to_usb_interface(dev);
if (intf->altsetting) {
for (j = 0; j < intf->num_altsetting; j++) {
struct usb_host_interface *as = &intf->altsetting[j];
......@@ -235,8 +232,6 @@ int usb_parse_configuration(struct usb_host_config *config, char *buffer, int si
return -ENOMEM;
}
memset(interface, 0, sizeof(struct usb_interface));
interface->dev.release = usb_release_intf;
device_initialize(&interface->dev);
}
/* Go through the descriptors, checking their length and counting the
......@@ -374,7 +369,7 @@ void usb_destroy_configuration(struct usb_device *dev)
struct usb_interface *ifp = cf->interface[i];
if (ifp)
put_device(&ifp->dev);
usb_free_intf(ifp);
}
}
kfree(dev->config);
......
......@@ -430,19 +430,14 @@ static int findintfep(struct usb_device *dev, unsigned int ep)
static int findintfif(struct usb_device *dev, unsigned int ifn)
{
unsigned int i, j;
struct usb_interface *iface;
struct usb_host_interface *alts;
unsigned int i;
if (ifn & ~0xff)
return -EINVAL;
for (i = 0; i < dev->actconfig->desc.bNumInterfaces; i++) {
iface = dev->actconfig->interface[i];
for (j = 0; j < iface->num_altsetting; j++) {
alts = &iface->altsetting[j];
if (alts->desc.bInterfaceNumber == ifn)
return i;
}
if (dev->actconfig->interface[i]->
altsetting[0].desc.bInterfaceNumber == ifn)
return i;
}
return -ENOENT;
}
......@@ -688,9 +683,7 @@ static int proc_getdriver(struct dev_state *ps, void __user *arg)
return -EFAULT;
if ((ret = findintfif(ps->dev, gd.interface)) < 0)
return ret;
interface = usb_ifnum_to_if(ps->dev, gd.interface);
if (!interface)
return -EINVAL;
interface = ps->dev->actconfig->interface[ret];
if (!interface->driver)
return -ENODATA;
strcpy(gd.driver, interface->driver->name);
......@@ -744,9 +737,7 @@ static int proc_setintf(struct dev_state *ps, void __user *arg)
return -EFAULT;
if ((ret = findintfif(ps->dev, setintf.interface)) < 0)
return ret;
interface = usb_ifnum_to_if(ps->dev, setintf.interface);
if (!interface)
return -EINVAL;
interface = ps->dev->actconfig->interface[ret];
if (interface->driver) {
if ((ret = checkintf(ps, ret)))
return ret;
......
......@@ -166,13 +166,9 @@ void usb_create_driverfs_dev_files (struct usb_device *udev)
static ssize_t \
show_##field (struct device *dev, char *buf) \
{ \
struct usb_interface *intf; \
int alt; \
struct usb_interface *intf = to_usb_interface (dev); \
\
intf = to_usb_interface (dev); \
alt = intf->act_altsetting; \
\
return sprintf (buf, format_string, intf->altsetting[alt].desc.field); \
return sprintf (buf, format_string, intf->cur_altsetting->desc.field); \
} \
static DEVICE_ATTR(field, S_IRUGO, show_##field, NULL);
......
......@@ -147,8 +147,12 @@ int usb_hcd_pci_probe (struct pci_dev *dev, const struct pci_device_id *id)
hcd->driver = driver;
hcd->description = driver->description;
hcd->self.bus_name = pci_name(dev);
#ifdef CONFIG_PCI_NAMES
hcd->product_desc = dev->pretty_name;
#else
if (hcd->product_desc == NULL)
hcd->product_desc = "USB Host Controller";
#endif
hcd->self.controller = &dev->dev;
if ((retval = hcd_buffer_create (hcd)) != 0) {
......
......@@ -560,7 +560,7 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)
struct usb_hub *hub;
unsigned long flags;
desc = intf->altsetting + intf->act_altsetting;
desc = intf->cur_altsetting;
dev = interface_to_usbdev(intf);
/* Some hubs have a subclass of 1, which AFAICT according to the */
......@@ -1344,15 +1344,15 @@ int usb_physical_reset_device(struct usb_device *dev)
for (i = 0; i < dev->actconfig->desc.bNumInterfaces; i++) {
struct usb_interface *intf = dev->actconfig->interface[i];
struct usb_interface_descriptor *as;
struct usb_interface_descriptor *desc;
as = &intf->altsetting[intf->act_altsetting].desc;
ret = usb_set_interface(dev, as->bInterfaceNumber,
as->bAlternateSetting);
desc = &intf->cur_altsetting->desc;
ret = usb_set_interface(dev, desc->bInterfaceNumber,
desc->bAlternateSetting);
if (ret < 0) {
err("failed to set active alternate setting "
"for dev %s interface %d (error=%d)",
dev->devpath, i, ret);
dev->devpath, desc->bInterfaceNumber, ret);
return ret;
}
}
......
......@@ -783,16 +783,22 @@ void usb_disable_endpoint(struct usb_device *dev, unsigned int epaddr)
*/
void usb_disable_interface(struct usb_device *dev, struct usb_interface *intf)
{
struct usb_host_interface *hintf =
&intf->altsetting[intf->act_altsetting];
struct usb_host_interface *alt = intf->cur_altsetting;
int i;
for (i = 0; i < hintf->desc.bNumEndpoints; ++i) {
for (i = 0; i < alt->desc.bNumEndpoints; ++i) {
usb_disable_endpoint(dev,
hintf->endpoint[i].desc.bEndpointAddress);
alt->endpoint[i].desc.bEndpointAddress);
}
}
static void release_interface(struct device *dev)
{
struct usb_interface *interface = to_usb_interface(dev);
complete(interface->released);
}
/*
* usb_disable_device - Disable all the endpoints for a USB device
* @dev: the device whose endpoints are being disabled
......@@ -822,12 +828,16 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0)
if (dev->actconfig) {
for (i = 0; i < dev->actconfig->desc.bNumInterfaces; i++) {
struct usb_interface *interface;
struct completion intf_completion;
/* remove this interface */
interface = dev->actconfig->interface[i];
dev_dbg (&dev->dev, "unregistering interface %s\n",
interface->dev.bus_id);
device_del(&interface->dev);
init_completion (&intf_completion);
interface->released = &intf_completion;
device_unregister (&interface->dev);
wait_for_completion (&intf_completion);
}
dev->actconfig = 0;
if (dev->state == USB_STATE_CONFIGURED)
......@@ -876,12 +886,11 @@ void usb_enable_endpoint(struct usb_device *dev,
void usb_enable_interface(struct usb_device *dev,
struct usb_interface *intf)
{
struct usb_host_interface *hintf =
&intf->altsetting[intf->act_altsetting];
struct usb_host_interface *alt = intf->cur_altsetting;
int i;
for (i = 0; i < hintf->desc.bNumEndpoints; ++i)
usb_enable_endpoint(dev, &hintf->endpoint[i].desc);
for (i = 0; i < alt->desc.bNumEndpoints; ++i)
usb_enable_endpoint(dev, &alt->endpoint[i].desc);
}
/**
......@@ -920,6 +929,7 @@ void usb_enable_interface(struct usb_device *dev,
int usb_set_interface(struct usb_device *dev, int interface, int alternate)
{
struct usb_interface *iface;
struct usb_host_interface *alt;
int ret;
int manual = 0;
......@@ -929,14 +939,15 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
return -EINVAL;
}
if (alternate < 0 || alternate >= iface->num_altsetting)
alt = usb_altnum_to_altsetting(iface, alternate);
if (!alt) {
warn("selecting invalid altsetting %d", alternate);
return -EINVAL;
}
ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
USB_REQ_SET_INTERFACE, USB_RECIP_INTERFACE,
iface->altsetting[alternate]
.desc.bAlternateSetting,
interface, NULL, 0, HZ * 5);
alternate, interface, NULL, 0, HZ * 5);
/* 9.4.10 says devices don't need this and are free to STALL the
* request if the interface only has one alternate setting.
......@@ -957,7 +968,7 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
/* prevent submissions using previous endpoint settings */
usb_disable_interface(dev, iface);
iface->act_altsetting = alternate;
iface->cur_altsetting = alt;
/* If the interface only has one altsetting and the device didn't
* accept the request, we attempt to carry out the equivalent action
......@@ -965,13 +976,11 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
* new altsetting.
*/
if (manual) {
struct usb_host_interface *iface_as =
&iface->altsetting[alternate];
int i;
for (i = 0; i < iface_as->desc.bNumEndpoints; i++) {
for (i = 0; i < alt->desc.bNumEndpoints; i++) {
unsigned int epaddr =
iface_as->endpoint[i].desc.bEndpointAddress;
alt->endpoint[i].desc.bEndpointAddress;
unsigned int pipe =
__create_pipe(dev, USB_ENDPOINT_NUMBER_MASK & epaddr)
| (usb_endpoint_out(epaddr) ? USB_DIR_OUT : USB_DIR_IN);
......@@ -1045,8 +1054,19 @@ int usb_reset_configuration(struct usb_device *dev)
/* re-init hc/hcd interface/endpoint state */
for (i = 0; i < config->desc.bNumInterfaces; i++) {
struct usb_interface *intf = config->interface[i];
struct usb_host_interface *alt;
alt = usb_altnum_to_altsetting(intf, 0);
intf->act_altsetting = 0;
/* No altsetting 0? We'll assume the first altsetting.
* We could use a GetInterface call, but if a device is
* so non-compliant that it doesn't have altsetting 0
* then I wouldn't trust its reply anyway.
*/
if (!alt)
alt = &intf->altsetting[0];
intf->cur_altsetting = alt;
usb_enable_interface(dev, intf);
}
return 0;
......@@ -1135,25 +1155,34 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
*/
for (i = 0; i < cp->desc.bNumInterfaces; ++i) {
struct usb_interface *intf = cp->interface[i];
struct usb_interface_descriptor *desc;
struct usb_host_interface *alt;
intf->act_altsetting = 0;
desc = &intf->altsetting [0].desc;
usb_enable_interface(dev, intf);
alt = usb_altnum_to_altsetting(intf, 0);
/* No altsetting 0? We'll assume the first altsetting.
* We could use a GetInterface call, but if a device is
* so non-compliant that it doesn't have altsetting 0
* then I wouldn't trust its reply anyway.
*/
if (!alt)
alt = &intf->altsetting[0];
intf->cur_altsetting = alt;
usb_enable_interface(dev, intf);
intf->dev.parent = &dev->dev;
intf->dev.driver = NULL;
intf->dev.bus = &usb_bus_type;
intf->dev.dma_mask = dev->dev.dma_mask;
intf->dev.release = release_interface;
sprintf (&intf->dev.bus_id[0], "%d-%s:%d.%d",
dev->bus->busnum, dev->devpath,
configuration,
desc->bInterfaceNumber);
alt->desc.bInterfaceNumber);
dev_dbg (&dev->dev,
"registering %s (config #%d, interface %d)\n",
intf->dev.bus_id, configuration,
desc->bInterfaceNumber);
device_add (&intf->dev);
alt->desc.bInterfaceNumber);
device_register (&intf->dev);
usb_create_driverfs_intf_files (intf);
}
}
......
......@@ -189,7 +189,7 @@ void usb_deregister(struct usb_driver *driver)
}
/**
* usb_ifnum_to_if - get the interface object with a given interface number (usbcore-internal)
* usb_ifnum_to_if - get the interface object with a given interface number
* @dev: the device whose current configuration is considered
* @ifnum: the desired interface
*
......@@ -219,6 +219,33 @@ struct usb_interface *usb_ifnum_to_if(struct usb_device *dev, unsigned ifnum)
return NULL;
}
/**
* usb_altnum_to_altsetting - get the altsetting structure with a given
* alternate setting number.
* @intf: the interface containing the altsetting in question
* @altnum: the desired alternate setting number
*
* This searches the altsetting array of the specified interface for
* an entry with the correct bAlternateSetting value and returns a pointer
* to that entry, or null.
*
* Note that altsettings need not be stored sequentially by number, so
* it would be incorrect to assume that the first altsetting entry in
* the array corresponds to altsetting zero. This routine helps device
* drivers avoid such mistakes.
*/
struct usb_host_interface *usb_altnum_to_altsetting(struct usb_interface *intf,
unsigned int altnum)
{
int i;
for (i = 0; i < intf->num_altsetting; i++) {
if (intf->altsetting[i].desc.bAlternateSetting == altnum)
return &intf->altsetting[i];
}
return NULL;
}
/**
* usb_epnum_to_ep_desc - get the endpoint object with a given endpoint number
* @dev: the device whose current configuration+altsettings is considered
......@@ -247,7 +274,7 @@ usb_epnum_to_ep_desc(struct usb_device *dev, unsigned epnum)
/* only endpoints in current altsetting are active */
intf = config->interface[i];
alt = intf->altsetting + intf->act_altsetting;
alt = intf->cur_altsetting;
for (k = 0; k < alt->desc.bNumEndpoints; k++)
if (epnum == alt->endpoint[k].desc.bEndpointAddress)
......@@ -421,7 +448,7 @@ usb_match_id(struct usb_interface *interface, const struct usb_device_id *id)
if (id == NULL)
return NULL;
intf = &interface->altsetting [interface->act_altsetting];
intf = interface->cur_altsetting;
dev = interface_to_usbdev(interface);
/* It is important to check that id->driver_info is nonzero,
......@@ -624,7 +651,7 @@ static int usb_hotplug (struct device *dev, char **envp, int num_envp,
scratch += length;
if (usb_dev->descriptor.bDeviceClass == 0) {
int alt = intf->act_altsetting;
struct usb_host_interface *alt = intf->cur_altsetting;
/* 2.4 only exposed interface zero. in 2.5, hotplug
* agents are called for all interfaces, and can use
......@@ -633,9 +660,9 @@ static int usb_hotplug (struct device *dev, char **envp, int num_envp,
envp [i++] = scratch;
length += snprintf (scratch, buffer_size - length,
"INTERFACE=%d/%d/%d",
intf->altsetting[alt].desc.bInterfaceClass,
intf->altsetting[alt].desc.bInterfaceSubClass,
intf->altsetting[alt].desc.bInterfaceProtocol);
alt->desc.bInterfaceClass,
alt->desc.bInterfaceSubClass,
alt->desc.bInterfaceProtocol);
if ((buffer_size - length <= 0) || (i >= num_envp))
return -ENOMEM;
++length;
......@@ -1582,6 +1609,7 @@ EXPORT_SYMBOL(usb_driver_release_interface);
EXPORT_SYMBOL(usb_match_id);
EXPORT_SYMBOL(usb_find_interface);
EXPORT_SYMBOL(usb_ifnum_to_if);
EXPORT_SYMBOL(usb_altnum_to_altsetting);
EXPORT_SYMBOL(usb_reset_device);
EXPORT_SYMBOL(usb_disconnect);
......
......@@ -9,7 +9,7 @@ obj-$(CONFIG_USB_GOKU) += goku_udc.o
# USB gadget drivers
#
g_zero-objs := zero.o usbstring.o
g_ether-objs := ether.o usbstring.o
g_ether-objs := ether.o usbstring.o config.o
g_serial-objs := serial.o usbstring.o
gadgetfs-objs := inode.o usbstring.o
g_file_storage-objs := file_storage.o usbstring.o
......
/*
* usb/gadget/config.c -- simplify building config descriptors
*
* Copyright (C) 2003 David Brownell
*
* 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/errno.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/string.h>
#include <linux/device.h>
#include <linux/usb_ch9.h>
/**
* usb_descriptor_fillbuf - fill buffer with descriptors
* @buf: Buffer to be filled
* @buflen: Size of buf
* @src: Array of descriptor pointers, terminated by null pointer.
*
* Copies descriptors into the buffer, returning the length or a
* negative error code if they can't all be copied. Useful when
* assembling descriptors for an associated set of interfaces used
* as part of configuring a composite device; or in other cases where
* sets of descriptors need to be marshaled.
*/
int
usb_descriptor_fillbuf(void *buf, unsigned buflen,
const struct usb_descriptor_header **src)
{
u8 *dest = buf;
if (!src)
return -EINVAL;
/* fill buffer from src[] until null descriptor ptr */
for (; 0 != *src; src++) {
unsigned len = (*src)->bLength;
if (len > buflen);
return -EINVAL;
memcpy(dest, *src, len);
buflen -= len;
dest += len;
}
return dest - (u8 *)buf;
}
/**
* usb_gadget_config_buf - builts a complete configuration descriptor
* @config: Header for the descriptor, including characteristics such
* as power requirements and number of interfaces.
* @desc: Null-terminated vector of pointers to the descriptors (interface,
* endpoint, etc) defining all functions in this device configuration.
* @buf: Buffer for the resulting configuration descriptor.
* @length: Length of buffer. If this is not big enough to hold the
* entire configuration descriptor, an error code will be returned.
*
* This copies descriptors into the response buffer, building a descriptor
* for that configuration. It returns the buffer length or a negative
* status code. The config.wTotalLength field is set to match the length
* of the result, but other descriptor fields (including power usage and
* interface count) must be set by the caller.
*
* Gadget drivers could use this when constructing a config descriptor
* in response to USB_REQ_GET_DESCRIPTOR. They will need to patch the
* resulting bDescriptorType value if USB_DT_OTHER_SPEED_CONFIG is needed.
*/
int usb_gadget_config_buf(
const struct usb_config_descriptor *config,
void *buf,
unsigned length,
const struct usb_descriptor_header **desc
)
{
struct usb_config_descriptor *cp = buf;
int len;
/* config descriptor first */
if (length < USB_DT_CONFIG_SIZE || !desc)
return -EINVAL;
*cp = *config;
/* then interface/endpoint/class/vendor/... */
len = usb_descriptor_fillbuf(USB_DT_CONFIG_SIZE + (u8*)buf,
length - USB_DT_CONFIG_SIZE, desc);
if (len < 0)
return len;
len += USB_DT_CONFIG_SIZE;
if (len > 0xffff)
return -EINVAL;
/* patch up the config descriptor */
cp->bLength = USB_DT_CONFIG_SIZE;
cp->bDescriptorType = USB_DT_CONFIG;
cp->wTotalLength = cpu_to_le16(len);
cp->bmAttributes |= USB_CONFIG_ATT_ONE;
return len;
}
......@@ -607,6 +607,25 @@ fs_sink_desc = {
.wMaxPacketSize = __constant_cpu_to_le16 (64),
};
static const struct usb_descriptor_header *fs_function [] = {
#ifdef DEV_CONFIG_CDC
/* "cdc" mode descriptors */
(struct usb_descriptor_header *) &control_intf,
(struct usb_descriptor_header *) &header_desc,
(struct usb_descriptor_header *) &union_desc,
(struct usb_descriptor_header *) &ether_desc,
#ifdef EP_STATUS_NUM
(struct usb_descriptor_header *) &fs_status_desc,
#endif
(struct usb_descriptor_header *) &data_nop_intf,
#endif /* DEV_CONFIG_CDC */
/* minimalist core */
(struct usb_descriptor_header *) &data_intf,
(struct usb_descriptor_header *) &fs_source_desc,
(struct usb_descriptor_header *) &fs_sink_desc,
0,
};
#ifdef HIGHSPEED
/*
......@@ -660,6 +679,25 @@ dev_qualifier = {
.bNumConfigurations = 1,
};
static const struct usb_descriptor_header *hs_function [] = {
#ifdef DEV_CONFIG_CDC
/* "cdc" mode descriptors */
(struct usb_descriptor_header *) &control_intf,
(struct usb_descriptor_header *) &header_desc,
(struct usb_descriptor_header *) &union_desc,
(struct usb_descriptor_header *) &ether_desc,
#ifdef EP_STATUS_NUM
(struct usb_descriptor_header *) &hs_status_desc,
#endif
(struct usb_descriptor_header *) &data_nop_intf,
#endif /* DEV_CONFIG_CDC */
/* minimalist core */
(struct usb_descriptor_header *) &data_intf,
(struct usb_descriptor_header *) &hs_source_desc,
(struct usb_descriptor_header *) &hs_sink_desc,
0,
};
/* maxpacket and other transfer characteristics vary by speed. */
#define ep_desc(g,hs,fs) (((g)->speed==USB_SPEED_HIGH)?(hs):(fs))
......@@ -704,86 +742,25 @@ static struct usb_gadget_strings stringtab = {
static int
config_buf (enum usb_device_speed speed, u8 *buf, u8 type, unsigned index)
{
const unsigned config_len = USB_DT_CONFIG_SIZE
#ifdef DEV_CONFIG_CDC
+ 2 * USB_DT_INTERFACE_SIZE
+ sizeof header_desc
+ sizeof union_desc
+ sizeof ether_desc
#ifdef EP_STATUS_NUM
+ USB_DT_ENDPOINT_SIZE
#endif
#endif /* DEV_CONFIG_CDC */
+ USB_DT_INTERFACE_SIZE
+ 2 * USB_DT_ENDPOINT_SIZE;
int len;
const struct usb_descriptor_header **function = fs_function;
#ifdef HIGHSPEED
int hs;
#endif
/* a single configuration must always be index 0 */
if (index > 0)
return -EINVAL;
if (config_len > USB_BUFSIZ)
return -EDOM;
int hs = (speed == USB_SPEED_HIGH);
/* config (or other speed config) */
memcpy (buf, &eth_config, USB_DT_CONFIG_SIZE);
buf [1] = type;
((struct usb_config_descriptor *) buf)->wTotalLength
= __constant_cpu_to_le16 (config_len);
buf += USB_DT_CONFIG_SIZE;
#ifdef HIGHSPEED
hs = (speed == USB_SPEED_HIGH);
if (type == USB_DT_OTHER_SPEED_CONFIG)
hs = !hs;
#endif
#ifdef DEV_CONFIG_CDC
/* control interface, class descriptors, optional status endpoint */
memcpy (buf, &control_intf, USB_DT_INTERFACE_SIZE);
buf += USB_DT_INTERFACE_SIZE;
memcpy (buf, &header_desc, sizeof header_desc);
buf += sizeof header_desc;
memcpy (buf, &union_desc, sizeof union_desc);
buf += sizeof union_desc;
memcpy (buf, &ether_desc, sizeof ether_desc);
buf += sizeof ether_desc;
#ifdef EP_STATUS_NUM
#ifdef HIGHSPEED
if (hs)
memcpy (buf, &hs_status_desc, USB_DT_ENDPOINT_SIZE);
else
#endif /* HIGHSPEED */
memcpy (buf, &fs_status_desc, USB_DT_ENDPOINT_SIZE);
buf += USB_DT_ENDPOINT_SIZE;
#endif /* EP_STATUS_NUM */
/* default data altsetting has no endpoints */
memcpy (buf, &data_nop_intf, USB_DT_INTERFACE_SIZE);
buf += USB_DT_INTERFACE_SIZE;
#endif /* DEV_CONFIG_CDC */
/* the "real" data interface has two endpoints */
memcpy (buf, &data_intf, USB_DT_INTERFACE_SIZE);
buf += USB_DT_INTERFACE_SIZE;
#ifdef HIGHSPEED
if (hs) {
memcpy (buf, &hs_source_desc, USB_DT_ENDPOINT_SIZE);
buf += USB_DT_ENDPOINT_SIZE;
memcpy (buf, &hs_sink_desc, USB_DT_ENDPOINT_SIZE);
buf += USB_DT_ENDPOINT_SIZE;
} else
function = hs_function;
#endif
{
memcpy (buf, &fs_source_desc, USB_DT_ENDPOINT_SIZE);
buf += USB_DT_ENDPOINT_SIZE;
memcpy (buf, &fs_sink_desc, USB_DT_ENDPOINT_SIZE);
buf += USB_DT_ENDPOINT_SIZE;
}
return config_len;
/* a single configuration must always be index 0 */
if (index > 0)
return -EINVAL;
len = usb_gadget_config_buf (&eth_config, buf, USB_BUFSIZ, function);
if (len < 0)
return len;
((struct usb_config_descriptor *) buf)->bDescriptorType = type;
return len;
}
/*-------------------------------------------------------------------------*/
......
......@@ -16,24 +16,89 @@
#include <linux/usb_ch9.h>
#include <linux/usb_gadget.h>
#include <asm/unaligned.h>
static int utf8_to_utf16le(const char *s, u16 *cp, unsigned len)
{
int count = 0;
u8 c;
u16 uchar;
/* this insists on correct encodings, though not minimal ones.
* BUT it currently rejects legit 4-byte UTF-8 code points,
* which need surrogate pairs. (Unicode 3.1 can use them.)
*/
while (len != 0 && (c = (u8) *s++) != 0) {
if (unlikely(c & 0x80)) {
// 2-byte sequence:
// 00000yyyyyxxxxxx = 110yyyyy 10xxxxxx
if ((c & 0xe0) == 0xc0) {
uchar = (c & 0x1f) << 6;
c = (u8) *s++;
if ((c & 0xc0) != 0xc0)
goto fail;
c &= 0x3f;
uchar |= c;
// 3-byte sequence (most CJKV characters):
// zzzzyyyyyyxxxxxx = 1110zzzz 10yyyyyy 10xxxxxx
} else if ((c & 0xf0) == 0xe0) {
uchar = (c & 0x0f) << 12;
c = (u8) *s++;
if ((c & 0xc0) != 0xc0)
goto fail;
c &= 0x3f;
uchar |= c << 6;
c = (u8) *s++;
if ((c & 0xc0) != 0xc0)
goto fail;
c &= 0x3f;
uchar |= c;
/* no bogus surrogates */
if (0xd800 <= uchar && uchar <= 0xdfff)
goto fail;
// 4-byte sequence (surrogate pairs, currently rare):
// 11101110wwwwzzzzyy + 110111yyyyxxxxxx
// = 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx
// (uuuuu = wwww + 1)
// FIXME accept the surrogate code points (only)
} else
goto fail;
} else
uchar = c;
put_unaligned (cpu_to_le16 (uchar), cp++);
count++;
len--;
}
return count;
fail:
return -1;
}
/**
* usb_gadget_get_string - fill out a string descriptor
* @table: of c strings using iso latin/1 characters
* @table: of c strings encoded using UTF-8
* @id: string id, from low byte of wValue in get string descriptor
* @buf: at least 256 bytes
*
* Finds the iso latin/1 string matching the ID, and converts it into a
* Finds the UTF-8 string matching the ID, and converts it into a
* string descriptor in utf16-le.
* Returns length of descriptor (always even) or negative errno
*
* If your driver needs stings in multiple languages, you'll need to
* to use some alternate solution for languages where the ISO 8859/1
* (latin/1) character set can't be used. For example, they can't be
* used with Chinese (Big5, GB2312, etc), Japanese, Korean, or many other
* languages. You'd likely "switch (wIndex) { ... }" in your ep0
* string descriptor logic, using this routine in cases where "western
* european" characters suffice for the strings being returned.
* If your driver needs stings in multiple languages, you'll probably
* "switch (wIndex) { ... }" in your ep0 string descriptor logic,
* using this routine after choosing which set of UTF-8 strings to use.
* Note that US-ASCII is a strict subset of UTF-8; any string bytes with
* the eighth bit set will be multibyte UTF-8 characters, not ISO-8859/1
* characters (which are also widely used in C strings).
*/
int
usb_gadget_get_string (struct usb_gadget_strings *table, int id, u8 *buf)
......@@ -59,13 +124,12 @@ usb_gadget_get_string (struct usb_gadget_strings *table, int id, u8 *buf)
/* string descriptors have length, tag, then UTF16-LE text */
len = min ((size_t) 126, strlen (s->s));
memset (buf + 2, 0, 2 * len); /* zero all the bytes */
len = utf8_to_utf16le(s->s, (u16 *)&buf[2], len);
if (len < 0)
return -EINVAL;
buf [0] = (len + 1) * 2;
buf [1] = USB_DT_STRING;
memset (buf + 2, 0, 2 * len); /* zero all the high bytes */
while (len) {
buf [2 * len] = s->s [len - 1];
len--;
}
return buf [0];
}
......@@ -29,6 +29,15 @@ config USB_EHCI_HCD
To compile this driver as a module, choose M here: the
module will be called ehci-hcd.
config USB_EHCI_SPLIT_ISO
bool "Full speed ISO transactions (EXPERIMENTAL)"
depends on USB_EHCI_HCD && EXPERIMENTAL
default n
---help---
This code is new and hasn't been used with many different
EHCI or USB 2.0 transaction translator implementations.
It should work for ISO-OUT transfers, like audio.
config USB_OHCI_HCD
tristate "OHCI HCD support"
depends on USB
......
......@@ -579,7 +579,11 @@ show_periodic (struct class_device *class_dev, char *buf)
break;
case Q_TYPE_SITD:
temp = scnprintf (next, size,
" sitd/%p", p.sitd);
" sitd%d-%04x/%p",
p.sitd->stream->interval,
le32_to_cpup (&p.sitd->hw_uframe)
& 0x0000ffff,
p.sitd);
tag = Q_NEXT_TYPE (p.sitd->hw_next);
p = p.sitd->sitd_next;
break;
......
......@@ -106,8 +106,6 @@ static const char hcd_name [] = "ehci_hcd";
#undef EHCI_VERBOSE_DEBUG
#undef EHCI_URB_TRACE
// #define have_split_iso
#ifdef DEBUG
#define EHCI_STATS
#endif
......@@ -676,6 +674,7 @@ static void ehci_work (struct ehci_hcd *ehci, struct pt_regs *regs)
/* the IO watchdog guards against hardware or driver bugs that
* misplace IRQs, and should let us run completely without IRQs.
* such lossage has been observed on both VT6202 and VT8235.
*/
if ((ehci->async->qh_next.ptr != 0) || (ehci->periodic_sched != 0))
timer_action (ehci, TIMER_IO_WATCHDOG);
......@@ -796,13 +795,8 @@ static int ehci_urb_enqueue (
case PIPE_ISOCHRONOUS:
if (urb->dev->speed == USB_SPEED_HIGH)
return itd_submit (ehci, urb, mem_flags);
#ifdef have_split_iso
else
return sitd_submit (ehci, urb, mem_flags);
#else
dbg ("no split iso support yet");
return -ENOSYS;
#endif /* have_split_iso */
}
}
......
This diff is collapsed.
......@@ -492,16 +492,16 @@ struct ehci_itd {
/*
* EHCI Specification 0.95 Section 3.4
* siTD, aka split-transaction isochronous Transfer Descriptor
* ... describe low/full speed iso xfers through TT in hubs
* ... describe full speed iso xfers through TT in hubs
* see Figure 3-5 "Split-transaction Isochronous Transaction Descriptor (siTD)
*/
struct ehci_sitd {
/* first part defined by EHCI spec */
u32 hw_next;
/* uses bit field macros above - see EHCI 0.95 Table 3-8 */
u32 hw_fullspeed_ep; /* see EHCI table 3-9 */
u32 hw_uframe; /* see EHCI table 3-10 */
u32 hw_results; /* see EHCI table 3-11 */
u32 hw_fullspeed_ep; /* EHCI table 3-9 */
u32 hw_uframe; /* EHCI table 3-10 */
u32 hw_results; /* EHCI table 3-11 */
#define SITD_IOC (1 << 31) /* interrupt on completion */
#define SITD_PAGE (1 << 30) /* buffer 0/1 */
#define SITD_LENGTH(x) (0x3ff & ((x)>>16))
......@@ -515,8 +515,8 @@ struct ehci_sitd {
#define SITD_ACTIVE __constant_cpu_to_le32(SITD_STS_ACTIVE)
u32 hw_buf [2]; /* see EHCI table 3-12 */
u32 hw_backpointer; /* see EHCI table 3-13 */
u32 hw_buf [2]; /* EHCI table 3-12 */
u32 hw_backpointer; /* EHCI table 3-13 */
u32 hw_buf_hi [2]; /* Appendix B */
/* the rest is HCD-private */
......@@ -552,8 +552,6 @@ struct ehci_fstn {
/*-------------------------------------------------------------------------*/
#define SUBMIT_URB(urb,mem_flags) usb_submit_urb(urb,mem_flags)
#ifndef DEBUG
#define STUB_DEBUG_FILES
#endif /* DEBUG */
......
......@@ -781,7 +781,8 @@ static void uhci_dec_fsbr(struct uhci_hcd *uhci, struct urb *urb)
/*
* Map status to standard result codes
*
* <status> is (td->status & 0xFE0000) [a.k.a. uhci_status_bits(td->status)]
* <status> is (td->status & 0xF60000) [a.k.a. uhci_status_bits(td->status)]
* Note: status does not include the TD_CTRL_NAK bit.
* <dir_out> is True for output TDs and False for input TDs.
*/
static int uhci_map_status(int status, int dir_out)
......@@ -792,22 +793,18 @@ static int uhci_map_status(int status, int dir_out)
return -EPROTO;
if (status & TD_CTRL_CRCTIMEO) { /* CRC/Timeout */
if (dir_out)
return -ETIMEDOUT;
return -EPROTO;
else
return -EILSEQ;
}
if (status & TD_CTRL_NAK) /* NAK */
return -ETIMEDOUT;
if (status & TD_CTRL_BABBLE) /* Babble */
return -EOVERFLOW;
if (status & TD_CTRL_DBUFERR) /* Buffer error */
return -ENOSR;
if (status & TD_CTRL_STALLED) /* Stalled */
return -EPIPE;
if (status & TD_CTRL_ACTIVE) /* Active */
return 0;
return -EINVAL;
WARN_ON(status & TD_CTRL_ACTIVE); /* Active */
return 0;
}
/*
......@@ -832,7 +829,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, struct ur
status |= TD_CTRL_LS;
/*
* Build the TD for the control request
* Build the TD for the control request setup packet
*/
td = uhci_alloc_td(uhci, urb->dev);
if (!td)
......@@ -990,13 +987,13 @@ static int uhci_result_control(struct uhci_hcd *uhci, struct urb *urb)
if (urbp->short_control_packet) {
tmp = head->prev;
goto status_phase;
goto status_stage;
}
tmp = head->next;
td = list_entry(tmp, struct uhci_td, list);
/* The first TD is the SETUP phase, check the status, but skip */
/* The first TD is the SETUP stage, check the status, but skip */
/* the count */
status = uhci_status_bits(td_status(td));
if (status & TD_CTRL_ACTIVE)
......@@ -1037,10 +1034,10 @@ static int uhci_result_control(struct uhci_hcd *uhci, struct urb *urb)
}
}
status_phase:
status_stage:
td = list_entry(tmp, struct uhci_td, list);
/* Control status phase */
/* Control status stage */
status = td_status(td);
#ifdef I_HAVE_BUGGY_APC_BACKUPS
......@@ -1053,10 +1050,11 @@ static int uhci_result_control(struct uhci_hcd *uhci, struct urb *urb)
return 0;
#endif
status = uhci_status_bits(status);
if (status & TD_CTRL_ACTIVE)
return -EINPROGRESS;
if (uhci_status_bits(status))
if (status)
goto td_error;
return 0;
......@@ -1272,12 +1270,6 @@ static inline int uhci_submit_interrupt(struct uhci_hcd *uhci, struct urb *urb,
return uhci_submit_common(uhci, urb, eurb, uhci->skelqh[__interval_to_skel(urb->interval)]);
}
/*
* Bulk and interrupt use common result
*/
#define uhci_result_bulk uhci_result_common
#define uhci_result_interrupt uhci_result_common
/*
* Isochronous transfers
*/
......@@ -1403,7 +1395,8 @@ static int uhci_result_isochronous(struct uhci_hcd *uhci, struct urb *urb)
urb->iso_frame_desc[i].actual_length = actlength;
urb->actual_length += actlength;
status = uhci_map_status(uhci_status_bits(td_status(td)), usb_pipeout(urb->pipe));
status = uhci_map_status(uhci_status_bits(td_status(td)),
usb_pipeout(urb->pipe));
urb->iso_frame_desc[i].status = status;
if (status) {
urb->error_count++;
......@@ -1508,12 +1501,9 @@ static int uhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, int mem_flags)
struct urb_priv *urbp = urb->hcpriv;
list_del_init(&urbp->urb_list);
spin_unlock_irqrestore(&uhci->urb_list_lock, flags);
uhci_destroy_urb_priv (uhci, urb);
return ret;
}
ret = 0;
uhci_destroy_urb_priv(uhci, urb);
} else
ret = 0;
out:
spin_unlock_irqrestore(&uhci->urb_list_lock, flags);
......@@ -1541,11 +1531,9 @@ static void uhci_transfer_result(struct uhci_hcd *uhci, struct urb *urb)
case PIPE_CONTROL:
ret = uhci_result_control(uhci, urb);
break;
case PIPE_INTERRUPT:
ret = uhci_result_interrupt(uhci, urb);
break;
case PIPE_BULK:
ret = uhci_result_bulk(uhci, urb);
case PIPE_INTERRUPT:
ret = uhci_result_common(uhci, urb);
break;
case PIPE_ISOCHRONOUS:
ret = uhci_result_isochronous(uhci, urb);
......@@ -1649,10 +1637,12 @@ static int uhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb)
{
struct uhci_hcd *uhci = hcd_to_uhci(hcd);
unsigned long flags;
struct urb_priv *urbp = urb->hcpriv;
struct urb_priv *urbp;
spin_lock_irqsave(&uhci->urb_list_lock, flags);
urbp = urb->hcpriv;
if (!urbp) /* URB was never linked! */
goto done;
list_del_init(&urbp->urb_list);
uhci_unlink_generic(uhci, urb);
......@@ -1665,6 +1655,7 @@ static int uhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb)
list_add_tail(&urbp->urb_list, &uhci->urb_remove_list);
spin_unlock(&uhci->urb_remove_list_lock);
done:
spin_unlock_irqrestore(&uhci->urb_list_lock, flags);
return 0;
}
......@@ -1861,17 +1852,12 @@ static void uhci_finish_completion(struct usb_hcd *hcd, struct pt_regs *regs)
static void uhci_remove_pending_urbps(struct uhci_hcd *uhci)
{
struct list_head *tmp, *head;
spin_lock(&uhci->urb_remove_list_lock);
head = &uhci->urb_remove_list;
tmp = head->next;
while (tmp != head) {
struct urb_priv *urbp = list_entry(tmp, struct urb_priv, urb_list);
spin_lock(&uhci->complete_list_lock);
tmp = tmp->next;
uhci_moveto_complete(uhci, urbp);
}
/* Splice the urb_remove_list onto the end of the complete_list */
list_splice_init(&uhci->urb_remove_list, uhci->complete_list.prev);
spin_unlock(&uhci->complete_list_lock);
spin_unlock(&uhci->urb_remove_list_lock);
}
......@@ -2471,9 +2457,16 @@ static int uhci_resume(struct usb_hcd *hcd)
pci_set_master(to_pci_dev(uhci_dev(uhci)));
if (uhci->state == UHCI_SUSPENDED)
if (uhci->state == UHCI_SUSPENDED) {
/*
* Some systems clear the Interrupt Enable register during
* PM suspend/resume, so reinitialize it.
*/
outw(USBINTR_TIMEOUT | USBINTR_RESUME | USBINTR_IOC |
USBINTR_SP, uhci->io_addr + USBINTR);
uhci->resume_detect = 1;
else {
} else {
reset_hc(uhci);
start_hc(uhci);
}
......
......@@ -141,7 +141,7 @@ struct uhci_qh {
TD_CTRL_BABBLE | TD_CTRL_CRCTIME | TD_CTRL_BITSTUFF)
#define uhci_maxerr(err) ((err) << TD_CTRL_C_ERR_SHIFT)
#define uhci_status_bits(ctrl_sts) ((ctrl_sts) & 0xFE0000)
#define uhci_status_bits(ctrl_sts) ((ctrl_sts) & 0xF60000)
#define uhci_actual_length(ctrl_sts) (((ctrl_sts) + 1) & TD_CTRL_ACTLEN_MASK) /* 1-based */
/*
......
......@@ -179,6 +179,18 @@ config USB_POWERMATE
To compile this driver as a module, choose M here: the
module will be called powermate.
config USB_MTOUCH
tristate "MicroTouch USB Touchscreen Driver"
depends on USB && INPUT
---help---
Say Y here if you want to use a MicroTouch (Now 3M) USB
Touchscreen controller.
See <file:Documentation/usb/mtouch.txt> for additional information.
To compile this driver as a module, choose M here: the
module will be called mtouchusb.
config USB_XPAD
tristate "X-Box gamepad support"
depends on USB && INPUT
......@@ -192,3 +204,17 @@ config USB_XPAD
To compile this driver as a module, choose M here: the
module will be called xpad.
config USB_ATI_REMOTE
tristate "ATI USB RF remote control"
depends on USB && INPUT
---help---
Say Y here if you want to use one of ATI's USB remote controls.
These are RF remotes with USB receivers. They come with many of ATI's
All-In-Wonder video cards. This driver provides mouse pointer, left
and right mouse buttons, and maps all the other remote buttons to
keypress events.
To compile this driver as a module, choose M here: the module will be
called ati_remote.
......@@ -27,10 +27,12 @@ ifeq ($(CONFIG_HID_FF),y)
endif
obj-$(CONFIG_USB_AIPTEK) += aiptek.o
obj-$(CONFIG_USB_ATI_REMOTE) += ati_remote.o
obj-$(CONFIG_USB_HID) += hid.o
obj-$(CONFIG_USB_KBD) += usbkbd.o
obj-$(CONFIG_USB_MOUSE) += usbmouse.o
obj-$(CONFIG_USB_WACOM) += wacom.o
obj-$(CONFIG_USB_KBTAB) += kbtab.o
obj-$(CONFIG_USB_MOUSE) += usbmouse.o
obj-$(CONFIG_USB_MTOUCH) += mtouchusb.o
obj-$(CONFIG_USB_POWERMATE) += powermate.o
obj-$(CONFIG_USB_WACOM) += wacom.o
obj-$(CONFIG_USB_XPAD) += xpad.o
This diff is collapsed.
......@@ -1445,7 +1445,7 @@ static void hid_free_buffers(struct usb_device *dev, struct hid_device *hid)
static struct hid_device *usb_hid_configure(struct usb_interface *intf)
{
struct usb_host_interface *interface = intf->altsetting + intf->act_altsetting;
struct usb_host_interface *interface = intf->cur_altsetting;
struct usb_device *dev = interface_to_usbdev (intf);
struct hid_descriptor *hdesc;
struct hid_device *hid;
......
......@@ -74,12 +74,15 @@ static void kbtab_irq(struct urb *urb, struct pt_regs *regs)
input_report_abs(dev, ABS_X, kbtab->x);
input_report_abs(dev, ABS_Y, kbtab->y);
/*input_report_abs(dev, ABS_PRESSURE, kbtab->pressure);*/
/*input_report_key(dev, BTN_TOUCH , data[0] & 0x01);*/
input_report_key(dev, BTN_RIGHT, data[0] & 0x02);
input_report_key(dev, BTN_LEFT, (kbtab->pressure > kb_pressure_click) ? 1 : 0);
if( -1 == kb_pressure_click){
input_report_abs(dev, ABS_PRESSURE, kbtab->pressure);
} else {
input_report_key(dev, BTN_LEFT, (kbtab->pressure > kb_pressure_click) ? 1 : 0);
};
input_sync(dev);
......
This diff is collapsed.
......@@ -240,7 +240,7 @@ static int usb_kbd_probe(struct usb_interface *iface,
char path[64];
char *buf;
interface = &iface->altsetting[iface->act_altsetting];
interface = iface->cur_altsetting;
if (interface->desc.bNumEndpoints != 1)
return -ENODEV;
......
......@@ -131,7 +131,7 @@ static int usb_mouse_probe(struct usb_interface * intf, const struct usb_device_
char path[64];
char *buf;
interface = &intf->altsetting[intf->act_altsetting];
interface = intf->cur_altsetting;
if (interface->desc.bNumEndpoints != 1)
return -ENODEV;
......
......@@ -490,7 +490,7 @@ static int set_altsetting (struct usbtest_dev *dev, int alternate)
struct usb_interface *iface = dev->intf;
struct usb_device *udev;
if (alternate < 0 || alternate >= iface->num_altsetting)
if (alternate < 0 || alternate >= 256)
return -EINVAL;
udev = interface_to_usbdev (iface);
......@@ -556,23 +556,19 @@ static int ch9_postconfig (struct usbtest_dev *dev)
{
struct usb_interface *iface = dev->intf;
struct usb_device *udev = interface_to_usbdev (iface);
int i, retval;
int i, alt, retval;
/* [9.2.3] if there's more than one altsetting, we need to be able to
* set and get each one. mostly trusts the descriptors from usbcore.
*/
for (i = 0; i < iface->num_altsetting; i++) {
/* 9.2.3 constrains the range here, and Linux ensures
* they're ordered meaningfully in this array
*/
if (iface->altsetting [i].desc.bAlternateSetting != i) {
/* 9.2.3 constrains the range here */
alt = iface->altsetting [i].desc.bAlternateSetting;
if (alt < 0 || alt >= iface->num_altsetting) {
dev_dbg (&iface->dev,
"invalid alt [%d].bAltSetting = %d\n",
i,
iface->altsetting [i].desc
.bAlternateSetting);
return -EDOM;
i, alt);
}
/* [real world] get/set unimplemented if there's only one */
......@@ -580,18 +576,18 @@ static int ch9_postconfig (struct usbtest_dev *dev)
continue;
/* [9.4.10] set_interface */
retval = set_altsetting (dev, i);
retval = set_altsetting (dev, alt);
if (retval) {
dev_dbg (&iface->dev, "can't set_interface = %d, %d\n",
i, retval);
alt, retval);
return retval;
}
/* [9.4.4] get_interface always works */
retval = get_altsetting (dev);
if (retval != i) {
if (retval != alt) {
dev_dbg (&iface->dev, "get alt should be %d, was %d\n",
i, retval);
alt, retval);
return (retval < 0) ? retval : -EDOM;
}
......
......@@ -3009,7 +3009,7 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
return -ENODEV;
}
xdev = interface_to_usbdev (udev);
interface = &udev->altsetting [udev->act_altsetting];
interface = udev->cur_altsetting;
usb_get_dev (xdev);
......@@ -3314,6 +3314,15 @@ static const struct usb_device_id products [] = {
.bInterfaceSubClass = 0x0a,
.bInterfaceProtocol = 0x00,
.driver_info = (unsigned long) &zaurus_pxa_info,
}, {
.match_flags = USB_DEVICE_ID_MATCH_INT_INFO
| USB_DEVICE_ID_MATCH_DEVICE,
.idVendor = 0x04DD,
.idProduct = 0x9050, /* C-860 */
.bInterfaceClass = 0x02,
.bInterfaceSubClass = 0x0a,
.bInterfaceProtocol = 0x00,
.driver_info = (unsigned long) &zaurus_pxa_info,
},
#endif
......
......@@ -286,6 +286,7 @@ static struct usb_device_id id_table_sio [] = {
static struct usb_device_id id_table_8U232AM [] = {
{ USB_DEVICE_VER(FTDI_VID, FTDI_IRTRANS_PID, 0, 0x3ff) },
{ USB_DEVICE_VER(FTDI_VID, FTDI_8U232AM_PID, 0, 0x3ff) },
{ USB_DEVICE_VER(FTDI_VID, FTDI_8U232AM_ALT_PID, 0, 0x3ff) },
{ USB_DEVICE_VER(FTDI_VID, FTDI_RELAIS_PID, 0, 0x3ff) },
......@@ -358,6 +359,7 @@ static struct usb_device_id id_table_8U232AM [] = {
static struct usb_device_id id_table_FT232BM [] = {
{ USB_DEVICE_VER(FTDI_VID, FTDI_IRTRANS_PID, 0x400, 0xffff) },
{ USB_DEVICE_VER(FTDI_VID, FTDI_8U232AM_PID, 0x400, 0xffff) },
{ USB_DEVICE_VER(FTDI_VID, FTDI_8U232AM_ALT_PID, 0x400, 0xffff) },
{ USB_DEVICE_VER(FTDI_VID, FTDI_RELAIS_PID, 0x400, 0xffff) },
......@@ -451,6 +453,7 @@ static struct usb_device_id id_table_HE_TIRA1 [] = {
static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(FTDI_VID, FTDI_IRTRANS_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_SIO_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_8U232AM_PID) },
{ USB_DEVICE(FTDI_VID, FTDI_8U232AM_ALT_PID) },
......
......@@ -30,6 +30,8 @@
#define FTDI_NF_RIC_VID 0x0DCD /* Vendor Id */
#define FTDI_NF_RIC_PID 0x0001 /* Product Id */
/* www.irtrans.de device */
#define FTDI_IRTRANS_PID 0xFC60 /* Product Id */
/* www.crystalfontz.com devices - thanx for providing free devices for evaluation ! */
/* they use the ftdi chipset for the USB interface and the vendor id is the same */
......
......@@ -273,6 +273,7 @@ static int klsi_105_startup (struct usb_serial *serial)
/* allocate the private data structure */
for (i=0; i<serial->num_ports; i++) {
int j;
priv = kmalloc(sizeof(struct klsi_105_private),
GFP_KERNEL);
if (!priv) {
......@@ -293,10 +294,10 @@ static int klsi_105_startup (struct usb_serial *serial)
usb_set_serial_port_data(serial->port[i], priv);
spin_lock_init (&priv->lock);
for (i=0; i<NUM_URBS; i++) {
for (j=0; j<NUM_URBS; j++) {
struct urb* urb = usb_alloc_urb(0, GFP_KERNEL);
priv->write_urb_pool[i] = urb;
priv->write_urb_pool[j] = urb;
if (urb == NULL) {
err("No more urbs???");
continue;
......
......@@ -239,6 +239,8 @@ static struct usb_device_id id_table [] = {
.driver_info = (kernel_ulong_t)&palm_os_4_probe },
{ USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_SCH_I330_ID),
.driver_info = (kernel_ulong_t)&palm_os_4_probe },
{ USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_SPH_I500_ID),
.driver_info = (kernel_ulong_t)&palm_os_4_probe },
{ USB_DEVICE(GARMIN_VENDOR_ID, GARMIN_IQUE_3600_ID),
.driver_info = (kernel_ulong_t)&palm_os_4_probe },
{ USB_DEVICE(ACEECA_VENDOR_ID, ACEECA_MEZ1000_ID),
......@@ -275,6 +277,7 @@ static struct usb_device_id id_table_combined [] = {
{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_UX50_ID) },
{ USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_TJ25_ID) },
{ USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_SCH_I330_ID) },
{ USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_SPH_I500_ID) },
{ USB_DEVICE(GARMIN_VENDOR_ID, GARMIN_IQUE_3600_ID) },
{ USB_DEVICE(ACEECA_VENDOR_ID, ACEECA_MEZ1000_ID) },
{ }, /* optional parameter entry */
......
......@@ -46,6 +46,7 @@
#define SAMSUNG_VENDOR_ID 0x04E8
#define SAMSUNG_SCH_I330_ID 0x8001
#define SAMSUNG_SPH_I500_ID 0x6601
#define GARMIN_VENDOR_ID 0x091E
#define GARMIN_IQUE_3600_ID 0x0004
......
......@@ -64,8 +64,10 @@ static const char* host_info(struct Scsi_Host *host)
return "SCSI emulation for USB Mass Storage devices";
}
static int slave_configure (struct scsi_device *sdev)
static int slave_configure(struct scsi_device *sdev)
{
struct us_data *us = (struct us_data *) sdev->host->hostdata[0];
/* Scatter-gather buffers (all but the last) must have a length
* divisible by the bulk maxpacket size. Otherwise a data packet
* would end up being short, causing a premature end to the data
......@@ -76,6 +78,16 @@ static int slave_configure (struct scsi_device *sdev)
* the end, scatter-gather buffers follow page boundaries. */
blk_queue_dma_alignment(sdev->request_queue, (512 - 1));
/* Devices using Genesys Logic chips cause a lot of trouble for
* high-speed transfers; they die unpredictably when given more
* than 64 KB of data at a time. If we detect such a device,
* reduce the maximum transfer size to 64 KB = 128 sectors. */
#define USB_VENDOR_ID_GENESYS 0x05e3 // Needs a standard location
if (us->pusb_dev->descriptor.idVendor == USB_VENDOR_ID_GENESYS &&
us->pusb_dev->speed == USB_SPEED_HIGH)
blk_queue_max_sectors(sdev->request_queue, 128);
/* this is to satisify the compiler, tho I don't think the
* return code is ever checked anywhere. */
return 0;
......
......@@ -563,9 +563,9 @@ void usb_stor_invoke_transport(Scsi_Cmnd *srb, struct us_data *us)
/*
* If we're running the CB transport, which is incapable
* of determining status on its own, we need to auto-sense
* of determining status on its own, we will auto-sense
* unless the operation involved a data-in transfer. Devices
* can signal data-in errors by stalling the bulk-in pipe.
* can signal most data-in errors by stalling the bulk-in pipe.
*/
if ((us->protocol == US_PR_CB || us->protocol == US_PR_DPCM_USB) &&
srb->sc_data_direction != SCSI_DATA_READ) {
......@@ -698,7 +698,11 @@ void usb_stor_invoke_transport(Scsi_Cmnd *srb, struct us_data *us)
* out the sense buffer so the higher layers won't realize
* we did an unsolicited auto-sense. */
if (result == USB_STOR_TRANSPORT_GOOD &&
(srb->sense_buffer[2] & 0xf) == 0x0) {
/* Filemark 0, ignore EOM, ILI 0, no sense */
(srb->sense_buffer[2] & 0xaf) == 0 &&
/* No ASC or ASCQ */
srb->sense_buffer[12] == 0 &&
srb->sense_buffer[13] == 0) {
srb->result = SAM_STAT_GOOD;
srb->sense_buffer[0] = 0x0;
}
......@@ -809,15 +813,19 @@ int usb_stor_CBI_transport(Scsi_Cmnd *srb, struct us_data *us)
}
/* If not UFI, we interpret the data as a result code
* The first byte should always be a 0x0
* The second byte & 0x0F should be 0x0 for good, otherwise error
* The first byte should always be a 0x0.
*
* Some bogus devices don't follow that rule. They stuff the ASC
* into the first byte -- so if it's non-zero, call it a failure.
*/
if (us->iobuf[0]) {
US_DEBUGP("CBI IRQ data showed reserved bType %d\n",
US_DEBUGP("CBI IRQ data showed reserved bType 0x%x\n",
us->iobuf[0]);
return USB_STOR_TRANSPORT_ERROR;
goto Failed;
}
/* The second byte & 0x0F should be 0x0 for good, otherwise error */
switch (us->iobuf[1] & 0x0F) {
case 0x00:
return USB_STOR_TRANSPORT_GOOD;
......
......@@ -261,6 +261,14 @@ UNUSUAL_DEV( 0x054c, 0x0010, 0x0106, 0x0450,
US_SC_SCSI, US_PR_DEVICE, NULL,
US_FL_SINGLE_LUN | US_FL_MODE_XLATE ),
/* This entry is needed because the device reports Sub=ff */
UNUSUAL_DEV( 0x054c, 0x0010, 0x0500, 0x0500,
"Sony",
"DSC-T1",
US_SC_8070, US_PR_DEVICE, NULL,
US_FL_SINGLE_LUN | US_FL_MODE_XLATE ),
/* Reported by wim@geeks.nl */
UNUSUAL_DEV( 0x054c, 0x0025, 0x0100, 0x0100,
"Sony",
......@@ -368,7 +376,7 @@ UNUSUAL_DEV( 0x05ab, 0x5701, 0x0100, 0x0110,
UNUSUAL_DEV( 0x05dc, 0x0001, 0x0000, 0x0001,
"Lexar",
"Jumpshot USB CF Reader",
US_SC_SCSI, US_PR_JUMPSHOT, NULL,
US_SC_DEVICE, US_PR_JUMPSHOT, NULL,
US_FL_MODE_XLATE ),
#endif
......@@ -440,12 +448,6 @@ UNUSUAL_DEV( 0x0686, 0x4006, 0x0001, 0x0001,
US_SC_SCSI, US_PR_DEVICE, NULL,
0 ),
UNUSUAL_DEV( 0x0686, 0x400b, 0x0001, 0x0001,
"Minolta",
"DiMAGE 7i",
US_SC_SCSI, US_PR_DEVICE, NULL,
0 ),
UNUSUAL_DEV( 0x0686, 0x400f, 0x0001, 0x0001,
"Minolta",
"DiMAGE 7Hi",
......@@ -619,6 +621,9 @@ UNUSUAL_DEV( 0x07c4, 0xa400, 0x0000, 0xffff,
* are using transport protocol CB.
* - They don't like the INQUIRY command. So we must handle this command
* of the SCSI layer ourselves.
* - Some cameras with idProduct=0x1001 and bcdDevice=0x1000 have
* bInterfaceProtocol=0x00 (US_PR_CBI) while others have 0x01 (US_PR_CB).
* So don't remove the US_PR_CB override!
*/
UNUSUAL_DEV( 0x07cf, 0x1001, 0x1000, 0x9009,
"Casio",
......@@ -649,6 +654,17 @@ UNUSUAL_DEV( 0x08ca, 0x2011, 0x0000, 0x9999,
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_MODE_XLATE ),
/* Entry needed for flags. Moreover, all devices with this ID use
* bulk-only transport, but _some_ falsely report Control/Bulk instead.
* One example is "Trumpion Digital Research MYMP3".
* Submitted by Bjoern Brill <brill(at)fs.math.uni-frankfurt.de>
*/
UNUSUAL_DEV( 0x090a, 0x1001, 0x0100, 0x0100,
"Trumpion",
"t33520 USB Flash Card Controller",
US_SC_DEVICE, US_PR_BULK, NULL,
US_FL_MODE_XLATE),
/* Trumpion Microelectronics MP3 player (felipe_alfaro@linuxmail.org) */
UNUSUAL_DEV( 0x090a, 0x1200, 0x0000, 0x9999,
"Trumpion",
......@@ -688,15 +704,9 @@ UNUSUAL_DEV( 0x0a17, 0x0004, 0x1000, 0x1000,
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_FIX_INQUIRY ),
/* This entry from <matthias@ma-c.de> in the Debian mailing list */
UNUSUAL_DEV( 0x0a17, 0x0006, 0x0000, 0xffff,
"Pentax",
"Optio 330GS",
US_SC_8070, US_PR_CB, NULL,
US_FL_MODE_XLATE | US_FL_FIX_INQUIRY ),
/* Submitted by Per Winkvist <per.winkvist@uk.com> */
UNUSUAL_DEV( 0x0a17, 0x006, 0x1000, 0x9009,
UNUSUAL_DEV( 0x0a17, 0x006, 0x0000, 0xffff,
"Pentax",
"Optio S/S4",
US_SC_DEVICE, US_PR_DEVICE, NULL,
......
......@@ -423,7 +423,7 @@ static int associate_dev(struct us_data *us, struct usb_interface *intf)
/* Fill in the device-related fields */
us->pusb_dev = interface_to_usbdev(intf);
us->pusb_intf = intf;
us->ifnum = intf->altsetting->desc.bInterfaceNumber;
us->ifnum = intf->cur_altsetting->desc.bInterfaceNumber;
/* Store our private data in the interface and increment the
* device's reference count */
......@@ -452,7 +452,7 @@ static void get_device_info(struct us_data *us, int id_index)
{
struct usb_device *dev = us->pusb_dev;
struct usb_interface_descriptor *idesc =
&us->pusb_intf->altsetting[us->pusb_intf->act_altsetting].desc;
&us->pusb_intf->cur_altsetting->desc;
struct us_unusual_dev *unusual_dev = &us_unusual_dev_list[id_index];
struct usb_device_id *id = &storage_usb_ids[id_index];
......@@ -686,7 +686,7 @@ static int get_protocol(struct us_data *us)
static int get_pipes(struct us_data *us)
{
struct usb_host_interface *altsetting =
&us->pusb_intf->altsetting[us->pusb_intf->act_altsetting];
us->pusb_intf->cur_altsetting;
int i;
struct usb_endpoint_descriptor *ep;
struct usb_endpoint_descriptor *ep_in = NULL;
......@@ -877,8 +877,9 @@ static int storage_probe(struct usb_interface *intf,
int result;
US_DEBUGP("USB Mass Storage device detected\n");
US_DEBUGP("act_altsetting is %d, id_index is %d\n",
intf->act_altsetting, id_index);
US_DEBUGP("altsetting is %d, id_index is %d\n",
intf->cur_altsetting->desc.bAlternateSetting,
id_index);
/* Allocate the us_data structure and initialize the mutexes */
us = (struct us_data *) kmalloc(sizeof(*us), GFP_KERNEL);
......@@ -953,8 +954,6 @@ static int storage_probe(struct usb_interface *intf,
scsi_scan_host(us->host);
printk(KERN_DEBUG
"WARNING: USB Mass Storage data integrity not assured\n");
printk(KERN_DEBUG
"USB Mass Storage device found at %d\n", us->pusb_dev->devnum);
return 0;
......
......@@ -176,6 +176,5 @@ extern void fill_inquiry_response(struct us_data *us,
* single queue element srb for write access */
#define scsi_unlock(host) spin_unlock_irq(host->host_lock)
#define scsi_lock(host) spin_lock_irq(host->host_lock)
#define sg_address(psg) (page_address((psg).page) + (psg).offset)
#endif
......@@ -72,14 +72,11 @@ struct usb_host_interface {
/**
* struct usb_interface - what usb device drivers talk to
* @altsetting: array of interface descriptors, one for each alternate
* @altsetting: array of interface structures, one for each alternate
* setting that may be selected. Each one includes a set of
* endpoint configurations and will be in numberic order,
* 0..num_altsetting.
* endpoint configurations. They will be in no particular order.
* @num_altsetting: number of altsettings defined.
* @act_altsetting: index of current altsetting. this number is always
* less than num_altsetting. after the device is configured, each
* interface uses its default setting of zero.
* @cur_altsetting: the current altsetting.
* @driver: the USB driver that is bound to this interface.
* @minor: the minor number assigned to this interface, if this
* interface is bound to a driver that uses the USB major number.
......@@ -89,6 +86,8 @@ struct usb_host_interface {
* number from the USB core by calling usb_register_dev().
* @dev: driver model's view of this device
* @class_dev: driver model's class view of this device.
* @released: wait for the interface to be released when changing
* configurations.
*
* USB device drivers attach to interfaces on a physical device. Each
* interface encapsulates a single high level function, such as feeding
......@@ -102,26 +101,33 @@ struct usb_host_interface {
* calls such as dev_get_drvdata() on the dev member of this structure.
*
* Each interface may have alternate settings. The initial configuration
* of a device sets the first of these, but the device driver can change
* of a device sets altsetting 0, but the device driver can change
* that setting using usb_set_interface(). Alternate settings are often
* used to control the the use of periodic endpoints, such as by having
* different endpoints use different amounts of reserved USB bandwidth.
* All standards-conformant USB devices that use isochronous endpoints
* will use them in non-default settings.
*
* The USB specification says that alternate setting numbers must run from
* 0 to one less than the total number of alternate settings. But some
* devices manage to mess this up, and the structures aren't necessarily
* stored in numerical order anyhow. Use usb_altnum_to_altsetting() to
* look up an alternate setting in the altsetting array based on its number.
*/
struct usb_interface {
/* array of alternate settings for this interface.
* these will be in numeric order, 0..num_altsettting
*/
/* array of alternate settings for this interface,
* stored in no particular order */
struct usb_host_interface *altsetting;
unsigned act_altsetting; /* active alternate setting */
struct usb_host_interface *cur_altsetting; /* the currently
* active alternate setting */
unsigned num_altsetting; /* number of alternate settings */
struct usb_driver *driver; /* driver */
int minor; /* minor number this interface is bound to */
struct device dev; /* interface specific device info */
struct class_device *class_dev;
struct completion *released; /* wait for release */
};
#define to_usb_interface(d) container_of(d, struct usb_interface, dev)
#define interface_to_usbdev(intf) \
......@@ -140,19 +146,43 @@ static inline void usb_set_intfdata (struct usb_interface *intf, void *data)
/* this maximum is arbitrary */
#define USB_MAXINTERFACES 32
/* USB_DT_CONFIG: Configuration descriptor information.
/**
* struct usb_host_config - representation of a device's configuration
* @desc: the device's configuration descriptor.
* @interface: array of usb_interface structures, one for each interface
* in the configuration. The number of interfaces is stored in
* desc.bNumInterfaces.
* @extra: pointer to buffer containing all extra descriptors associated
* with this configuration (those preceding the first interface
* descriptor).
* @extralen: length of the extra descriptors buffer.
*
* USB_DT_OTHER_SPEED_CONFIG is the same descriptor, except that the
* descriptor type is different. Highspeed-capable devices can look
* different depending on what speed they're currently running. Only
* devices with a USB_DT_DEVICE_QUALIFIER have an OTHER_SPEED_CONFIG.
* USB devices may have multiple configurations, but only one can be active
* at any time. Each encapsulates a different operational environment;
* for example, a dual-speed device would have separate configurations for
* full-speed and high-speed operation. The number of configurations
* available is stored in the device descriptor as bNumConfigurations.
*
* A configuration can contain multiple interfaces. Each corresponds to
* a different function of the USB device, and all are available whenever
* the configuration is active. The USB standard says that interfaces
* are supposed to be numbered from 0 to desc.bNumInterfaces-1, but a lot
* of devices get this wrong. In addition, the interface array is not
* guaranteed to be sorted in numerical order. Use usb_ifnum_to_if() to
* look up an interface entry based on its number.
*
* Device drivers should not attempt to activate configurations. The choice
* of which configuration to install is a policy decision based on such
* considerations as available power, functionality provided, and the user's
* desires (expressed through hotplug scripts). However, drivers can call
* usb_reset_configuration() to reinitialize the current configuration and
* all its interfaces.
*/
struct usb_host_config {
struct usb_config_descriptor desc;
/* the interfaces associated with this configuration
* these will be in numeric order, 0..desc.bNumInterfaces
*/
/* the interfaces associated with this configuration,
* stored in no particular order */
struct usb_interface *interface[USB_MAXINTERFACES];
unsigned char *extra; /* Extra descriptors */
......@@ -294,8 +324,12 @@ extern void usb_driver_release_interface(struct usb_driver *driver,
const struct usb_device_id *usb_match_id(struct usb_interface *interface,
const struct usb_device_id *id);
extern struct usb_interface *usb_find_interface(struct usb_driver *drv, int minor);
extern struct usb_interface *usb_ifnum_to_if(struct usb_device *dev, unsigned ifnum);
extern struct usb_interface *usb_find_interface(struct usb_driver *drv,
int minor);
extern struct usb_interface *usb_ifnum_to_if(struct usb_device *dev,
unsigned ifnum);
extern struct usb_host_interface *usb_altnum_to_altsetting(
struct usb_interface *intf, unsigned int altnum);
/**
......
......@@ -690,7 +690,7 @@ int usb_gadget_unregister_driver (struct usb_gadget_driver *driver);
/**
* struct usb_string - wraps a C string and its USB id
* @id:the (nonzero) ID for this string
* @s:the string, in ISO-8859/1 characters
* @s:the string, in UTF-8 encoding
*
* If you're using usb_gadget_get_string(), use this to wrap a string
* together with its ID.
......@@ -716,6 +716,17 @@ struct usb_gadget_strings {
/* put descriptor for string with that id into buf (buflen >= 256) */
int usb_gadget_get_string (struct usb_gadget_strings *table, int id, u8 *buf);
/*-------------------------------------------------------------------------*/
/* utility to simplify managing config descriptors */
/* write vector of descriptors into buffer */
int usb_descriptor_fillbuf(void *, unsigned,
const struct usb_descriptor_header **);
/* build config descriptor from single descriptor vector */
int usb_gadget_config_buf(const struct usb_config_descriptor *config,
void *buf, unsigned buflen, const struct usb_descriptor_header **desc);
#endif /* __KERNEL__ */
......
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