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

Merge kroah.com:/home/greg/linux/BK/bleed-2.6

into kroah.com:/home/greg/linux/BK/usb-2.6
parents 13264682 da53a89c
...@@ -673,11 +673,6 @@ S: Northampton ...@@ -673,11 +673,6 @@ S: Northampton
S: NN1 3QT S: NN1 3QT
S: United Kingdom S: United Kingdom
N: Stephane Dalton
E: sdalton@videotron.ca
D: Tieman Voyager USB Braille display driver.
S: Qubec, Canada
N: Uwe Dannowski N: Uwe Dannowski
E: Uwe.Dannowski@ira.uka.de E: Uwe.Dannowski@ira.uka.de
W: http://i30www.ira.uka.de/~dannowsk/ W: http://i30www.ira.uka.de/~dannowsk/
...@@ -797,11 +792,6 @@ E: cort@fsmlabs.com ...@@ -797,11 +792,6 @@ E: cort@fsmlabs.com
W: http://www.fsmlabs.com/linuxppcbk.html W: http://www.fsmlabs.com/linuxppcbk.html
D: PowerPC D: PowerPC
N: Stphane Doyon
E: s.doyon@videotron.ca
D: Tieman Voyager USB Braille display driver.
S: Qubec, Canada
N: Oleg Drokin N: Oleg Drokin
E: green@ccssu.crimea.ua E: green@ccssu.crimea.ua
W: http://www.ccssu.crimea.ua/~green W: http://www.ccssu.crimea.ua/~green
......
...@@ -454,6 +454,7 @@ but some optional utilities are provided to simplify common tasks. ...@@ -454,6 +454,7 @@ but some optional utilities are provided to simplify common tasks.
</para> </para>
!Edrivers/usb/gadget/usbstring.c !Edrivers/usb/gadget/usbstring.c
!Edrivers/usb/gadget/config.c
</sect1> </sect1>
</chapter> </chapter>
......
Kernel Driver for the Tieman Voyager Braille Display (USB)
Authors:
Stéphane Dalton <sdalton@videotron.ca>
Stéphane Doyon <s.doyon@videotron.ca>
Version 0.8, April 17, 2002
The brlvger driver supports a Braille display (aka Braille terminal)
model Voyager from Tieman.
The driver has been in heavy use for about six months now (as of April
17th 2002) by a very few users (about 3-4), who say it has worked very
well for them.
We have tested it with a Voyager 44, but it should also support
the Voyager 70.
This driver implements a character device which allows userspace programs
access to the braille displays raw functions. You still need a userspace
program to perform the screen-review functions and control the
display. Get BRLTTY from http://mielke.cc/brltty/ (version 2.99.8 or
later). It has a Voyager driver which interfaces with this kernel driver.
The interface is through a character device, major 180, minor 128, called
"brlvger" under devfs.
Many thanks to the Tieman people: Corand van Strien, Ivar Illing, Daphne
Vogelaar and Ingrid Vogel. They provided us with a Braille display (as
well as programming information) so that we could write this driver. They
replaced the display when it broke and they answered our technical
questions. It is very motivating when companies take an interest in such
projects and are so supportive.
Thanks to Andor Demarteau <ademarte@students.cs.uu.nl> who got this whole
project started and beta-tested all our early buggy attempts.
...@@ -70,7 +70,9 @@ one or more packets could finish before an error stops further endpoint I/O. ...@@ -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.) (That is, if drivers see this it's a bug.)
-EPROTO (*) a) bitstuff error -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 -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.
...@@ -1966,13 +1966,6 @@ P: Romain Lievin ...@@ -1966,13 +1966,6 @@ P: Romain Lievin
M: roms@lpg.ticalc.org M: roms@lpg.ticalc.org
S: Maintained S: Maintained
TIEMAN VOYAGER USB BRAILLE DISPLAY DRIVER
P: Stephane Dalton
M: sdalton@videotron.ca
P: Stphane Doyon
M: s.doyon@videotron.ca
S: Maintained
TLAN NETWORK DRIVER TLAN NETWORK DRIVER
P: Samuel Chessman P: Samuel Chessman
M: chessman@tux.org M: chessman@tux.org
...@@ -2152,14 +2145,6 @@ L: linux-usb-devel@lists.sourceforge.net ...@@ -2152,14 +2145,6 @@ L: linux-usb-devel@lists.sourceforge.net
W: http://pegasus2.sourceforge.net/ W: http://pegasus2.sourceforge.net/
S: Maintained S: Maintained
USB SCANNER DRIVER
P: Henning Meier-Geinitz
M: henning@meier-geinitz.de
L: linux-usb-users@lists.sourceforge.net
L: linux-usb-devel@lists.sourceforge.net
W: http://www.meier-geinitz.de/kernel/
S: Maintained
USB SE401 DRIVER USB SE401 DRIVER
P: Jeroen Vreeken P: Jeroen Vreeken
M: pe1rxq@amsat.org M: pe1rxq@amsat.org
......
...@@ -589,7 +589,7 @@ static int usb_pcwd_probe(struct usb_interface *interface, const struct usb_devi ...@@ -589,7 +589,7 @@ static int usb_pcwd_probe(struct usb_interface *interface, const struct usb_devi
} }
/* get the active interface descriptor */ /* get the active interface descriptor */
iface_desc = &interface->altsetting[interface->act_altsetting]; iface_desc = interface->cur_altsetting;
/* check out that we have a HID device */ /* check out that we have a HID device */
if (!(iface_desc->desc.bInterfaceClass == USB_CLASS_HID)) { if (!(iface_desc->desc.bInterfaceClass == USB_CLASS_HID)) {
......
...@@ -135,7 +135,7 @@ static int iforce_usb_probe(struct usb_interface *intf, ...@@ -135,7 +135,7 @@ static int iforce_usb_probe(struct usb_interface *intf,
struct usb_endpoint_descriptor *epirq, *epout; struct usb_endpoint_descriptor *epirq, *epout;
struct iforce *iforce; struct iforce *iforce;
interface = &intf->altsetting[intf->act_altsetting]; interface = intf->cur_altsetting;
epirq = &interface->endpoint[0].desc; epirq = &interface->endpoint[0].desc;
epout = &interface->endpoint[1].desc; epout = &interface->endpoint[1].desc;
......
...@@ -1349,9 +1349,11 @@ static int __devinit hfc_usb_probe(struct usb_interface *intf, const struct usb_ ...@@ -1349,9 +1349,11 @@ static int __devinit hfc_usb_probe(struct usb_interface *intf, const struct usb_
{ {
struct usb_device *dev= interface_to_usbdev(intf); struct usb_device *dev= interface_to_usbdev(intf);
hfcusb_data *context; hfcusb_data *context;
struct usb_host_interface *iface = intf->altsetting + intf->act_altsetting; struct usb_host_interface *iface = intf->cur_altsetting;
struct usb_host_interface *iface_used = NULL;
struct usb_host_endpoint *ep; struct usb_host_endpoint *ep;
int i, idx, probe_alt_setting,vend_idx, cfg_used, *vcf, attr, cfg_found, cidx, ep_addr; int ifnum = iface->desc.bInterfaceNumber;
int i, idx, alt_idx, probe_alt_setting, vend_idx, cfg_used, *vcf, attr, cfg_found, cidx, ep_addr;
int cmptbl[16],small_match,iso_packet_size,packet_size,alt_used=0; int cmptbl[16],small_match,iso_packet_size,packet_size,alt_used=0;
// usb_show_device(dev); // usb_show_device(dev);
...@@ -1366,7 +1368,7 @@ static int __devinit hfc_usb_probe(struct usb_interface *intf, const struct usb_ ...@@ -1366,7 +1368,7 @@ static int __devinit hfc_usb_probe(struct usb_interface *intf, const struct usb_
#ifdef VERBOSE_USB_DEBUG #ifdef VERBOSE_USB_DEBUG
printk(KERN_INFO "HFC-USB: probing interface(%d) actalt(%d) minor(%d)\n", printk(KERN_INFO "HFC-USB: probing interface(%d) actalt(%d) minor(%d)\n",
intf->altsetting->desc.bInterfaceNumber, intf->act_altsetting, intf->minor); ifnum, iface->desc.bAlternateSetting, intf->minor);
#endif #endif
if (vend_idx != 0xffff) { if (vend_idx != 0xffff) {
...@@ -1374,14 +1376,15 @@ static int __devinit hfc_usb_probe(struct usb_interface *intf, const struct usb_ ...@@ -1374,14 +1376,15 @@ static int __devinit hfc_usb_probe(struct usb_interface *intf, const struct usb_
printk(KERN_INFO "HFC-USB: found vendor idx:%d name:%s\n",vend_idx,vdata[vend_idx].vend_name); printk(KERN_INFO "HFC-USB: found vendor idx:%d name:%s\n",vend_idx,vdata[vend_idx].vend_name);
#endif #endif
/* if vendor and product ID is OK, start probing a matching alternate setting ... */ /* if vendor and product ID is OK, start probing a matching alternate setting ... */
probe_alt_setting = 0; alt_idx = 0;
small_match=0xffff; small_match=0xffff;
// default settings // default settings
iso_packet_size=16; iso_packet_size=16;
packet_size=64; packet_size=64;
while(probe_alt_setting < intf->num_altsetting) { while (alt_idx < intf->num_altsetting) {
iface = intf->altsetting + probe_alt_setting; iface = intf->altsetting + alt_idx;
probe_alt_setting = iface->desc.bAlternateSetting;
cfg_used=0; cfg_used=0;
#ifdef VERBOSE_USB_DEBUG #ifdef VERBOSE_USB_DEBUG
...@@ -1395,7 +1398,7 @@ static int __devinit hfc_usb_probe(struct usb_interface *intf, const struct usb_ ...@@ -1395,7 +1398,7 @@ static int __devinit hfc_usb_probe(struct usb_interface *intf, const struct usb_
#ifdef VERBOSE_USB_DEBUG #ifdef VERBOSE_USB_DEBUG
printk(KERN_INFO "HFC-USB: (if=%d alt=%d cfg_used=%d)\n", printk(KERN_INFO "HFC-USB: (if=%d alt=%d cfg_used=%d)\n",
probe_alt_setting, intf->act_altsetting,cfg_used); ifnum, probe_alt_setting, cfg_used);
#endif #endif
// copy table // copy table
memcpy(cmptbl,vcf,16*sizeof(int)); memcpy(cmptbl,vcf,16*sizeof(int));
...@@ -1448,6 +1451,7 @@ static int __devinit hfc_usb_probe(struct usb_interface *intf, const struct usb_ ...@@ -1448,6 +1451,7 @@ static int __devinit hfc_usb_probe(struct usb_interface *intf, const struct usb_
if (cfg_used < small_match) { if (cfg_used < small_match) {
small_match = cfg_used; small_match = cfg_used;
alt_used = probe_alt_setting; alt_used = probe_alt_setting;
iface_used = iface;
} }
#ifdef VERBOSE_USB_DEBUG #ifdef VERBOSE_USB_DEBUG
printk(KERN_INFO "HFC-USB: small_match=%x %x\n", small_match, alt_used); printk(KERN_INFO "HFC-USB: small_match=%x %x\n", small_match, alt_used);
...@@ -1457,15 +1461,14 @@ static int __devinit hfc_usb_probe(struct usb_interface *intf, const struct usb_ ...@@ -1457,15 +1461,14 @@ static int __devinit hfc_usb_probe(struct usb_interface *intf, const struct usb_
cfg_used++; cfg_used++;
} }
probe_alt_setting++; alt_idx++;
} /* (probe_alt_setting < intf->num_altsetting) */ } /* (alt_idx < intf->num_altsetting) */
#ifdef VERBOSE_USB_DEBUG #ifdef VERBOSE_USB_DEBUG
printk(KERN_INFO "HFC-USB: final small_match=%x alt_used=%x\n",small_match, alt_used); printk(KERN_INFO "HFC-USB: final small_match=%x alt_used=%x\n",small_match, alt_used);
#endif #endif
// yiipiee, we found a valid config // yiipiee, we found a valid config
if (small_match != 0xffff) { if (small_match != 0xffff) {
intf->act_altsetting = alt_used; iface = iface_used;
iface = intf->altsetting + intf->act_altsetting;
if (!(context = kmalloc(sizeof(hfcusb_data), GFP_KERNEL))) if (!(context = kmalloc(sizeof(hfcusb_data), GFP_KERNEL)))
return(-ENOMEM); /* got no mem */ return(-ENOMEM); /* got no mem */
...@@ -1542,8 +1545,8 @@ static int __devinit hfc_usb_probe(struct usb_interface *intf, const struct usb_ ...@@ -1542,8 +1545,8 @@ static int __devinit hfc_usb_probe(struct usb_interface *intf, const struct usb_
// now share our luck // now share our luck
context->dev = dev; /* save device */ context->dev = dev; /* save device */
context->if_used = intf->altsetting->desc.bInterfaceNumber; /* save used interface */ context->if_used = ifnum; /* save used interface */
context->alt_used = intf->act_altsetting; /* and alternate config */ context->alt_used = alt_used; /* and alternate config */
context->ctrl_paksize = dev->descriptor.bMaxPacketSize0; /* control size */ context->ctrl_paksize = dev->descriptor.bMaxPacketSize0; /* control size */
context->cfg_used=vcf[16]; // store used config context->cfg_used=vcf[16]; // store used config
context->vend_idx=vend_idx; // store found vendor context->vend_idx=vend_idx; // store found vendor
......
...@@ -6,32 +6,36 @@ menu "USB support" ...@@ -6,32 +6,36 @@ menu "USB support"
# ARM SA1111 chips have a non-PCI based "OHCI-compatible" USB host interface. # ARM SA1111 chips have a non-PCI based "OHCI-compatible" USB host interface.
config USB config USB
tristate "Support for USB" tristate "Support for Host-side USB"
depends on PCI || SA1111 || ARCH_OMAP1510 || ARCH_OMAP1610 depends on PCI || SA1111 || ARCH_OMAP1510 || ARCH_OMAP1610
---help--- ---help---
Universal Serial Bus (USB) is a specification for a serial bus Universal Serial Bus (USB) is a specification for a serial bus
subsystem which offers higher speeds and more features than the subsystem which offers higher speeds and more features than the
traditional PC serial port. The bus supplies power to peripherals traditional PC serial port. The bus supplies power to peripherals
and allows for hot swapping. Up to 127 USB peripherals can be and allows for hot swapping. Up to 127 USB peripherals can be
connected to a single USB port in a tree structure. The USB port is connected to a single USB host in a tree structure.
the root of the tree, the peripherals are the leaves and the inner
nodes are special USB devices called hubs. Many newer PC's have USB The USB host is the root of the tree, the peripherals are the
ports and newer peripherals such as scanners, keyboards, mice, leaves and the inner nodes are special USB devices called hubs.
modems, and printers support the USB protocol and can be connected Most PCs now have USB host ports, used to connect peripherals
to the PC via those ports. such as scanners, keyboards, mice, modems, cameras, disks,
flash memory, network links, and printers to the PC.
Say Y here if your computer has a USB port and you want to use USB
devices. You then need to say Y to at least one of "UHCI HCD support" Say Y here if your computer has a host-side USB port and you want
or "OHCI HCD support" below (the type of interface that the USB hardware to use USB devices. You then need to say Y to at least one of the
in your computer provides to the operating system) and then choose Host Controller Driver (HCD) options below. Choose a USB 1.1
from amongst the drivers for USB peripherals. You may want to check controller, such as "UHCI HCD support" or "OHCI HCD support",
out the information provided in <file:Documentation/usb/> and and "EHCI HCD (USB 2.0) support" except for older systems that
especially the links given in <file:Documentation/usb/usb-help.txt>. do not have USB 2.0 support. It doesn't normally hurt to select
them all if you are not certain.
If you have a new USB 2.0 High Speed system, you should also choose
"EHCI HCD (USB 2.0) support" as well as at least one of UHCI or OHCI. If your system has a device-side USB port, used in the peripheral
side of the USB protocol, see the "USB Gadget" framework instead.
It doesn't normally hurt to select them all if you are not certain.
After choosing your HCD, then select drivers for the USB peripherals
you'll be using. You may want to check out the information provided
in <file:Documentation/usb/> and especially the links given in
<file:Documentation/usb/usb-help.txt>.
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
module will be called usbcore. module will be called usbcore.
......
...@@ -20,10 +20,15 @@ obj-$(CONFIG_USB_PRINTER) += class/ ...@@ -20,10 +20,15 @@ obj-$(CONFIG_USB_PRINTER) += class/
obj-$(CONFIG_USB_STORAGE) += storage/ obj-$(CONFIG_USB_STORAGE) += storage/
obj-$(CONFIG_USB_AIPTEK) += input/ obj-$(CONFIG_USB_AIPTEK) += input/
obj-$(CONFIG_USB_ATI_REMOTE) += input/
obj-$(CONFIG_USB_HID) += input/ obj-$(CONFIG_USB_HID) += input/
obj-$(CONFIG_USB_KBD) += input/ obj-$(CONFIG_USB_KBD) += input/
obj-$(CONFIG_USB_KBTAB) += input/
obj-$(CONFIG_USB_MOUSE) += input/ obj-$(CONFIG_USB_MOUSE) += input/
obj-$(CONFIG_USB_MTOUCH) += input/
obj-$(CONFIG_USB_POWERMATE) += input/
obj-$(CONFIG_USB_WACOM) += input/ obj-$(CONFIG_USB_WACOM) += input/
obj-$(CONFIG_USB_XPAD) += input/
obj-$(CONFIG_USB_DABUSB) += media/ obj-$(CONFIG_USB_DABUSB) += media/
obj-$(CONFIG_USB_DSBR) += media/ obj-$(CONFIG_USB_DSBR) += media/
...@@ -50,7 +55,6 @@ obj-$(CONFIG_USB_MICROTEK) += image/ ...@@ -50,7 +55,6 @@ obj-$(CONFIG_USB_MICROTEK) += image/
obj-$(CONFIG_USB_SERIAL) += serial/ obj-$(CONFIG_USB_SERIAL) += serial/
obj-$(CONFIG_USB_AUERSWALD) += misc/ obj-$(CONFIG_USB_AUERSWALD) += misc/
obj-$(CONFIG_USB_BRLVGER) += misc/
obj-$(CONFIG_USB_EMI26) += misc/ obj-$(CONFIG_USB_EMI26) += misc/
obj-$(CONFIG_USB_LCD) += misc/ obj-$(CONFIG_USB_LCD) += misc/
obj-$(CONFIG_USB_LEGOTOWER) += misc/ obj-$(CONFIG_USB_LEGOTOWER) += misc/
......
This diff is collapsed.
...@@ -1025,7 +1025,7 @@ static int usb_bluetooth_probe (struct usb_interface *intf, ...@@ -1025,7 +1025,7 @@ static int usb_bluetooth_probe (struct usb_interface *intf,
int num_bulk_in = 0; int num_bulk_in = 0;
int num_bulk_out = 0; int num_bulk_out = 0;
interface = &intf->altsetting[0]; interface = intf->cur_altsetting;
control_out_endpoint = interface->desc.bInterfaceNumber; control_out_endpoint = interface->desc.bInterfaceNumber;
/* find the endpoints that we need */ /* find the endpoints that we need */
......
...@@ -595,12 +595,12 @@ static int acm_probe (struct usb_interface *intf, ...@@ -595,12 +595,12 @@ static int acm_probe (struct usb_interface *intf,
* is there it's not for call management ... so use * is there it's not for call management ... so use
* the cdc union descriptor whenever there is one. * the cdc union descriptor whenever there is one.
*/ */
ifcom = intf->altsetting + 0; ifcom = intf->cur_altsetting;
if (intf == cfacm->interface[j]) { if (intf == cfacm->interface[j]) {
ifdata = cfacm->interface[j + 1]->altsetting + 0; ifdata = cfacm->interface[j + 1]->cur_altsetting;
data = cfacm->interface[j + 1]; data = cfacm->interface[j + 1];
} else if (intf == cfacm->interface[j + 1]) { } else if (intf == cfacm->interface[j + 1]) {
ifdata = cfacm->interface[j]->altsetting + 0; ifdata = cfacm->interface[j]->cur_altsetting;
data = cfacm->interface[j]; data = cfacm->interface[j];
} else } else
continue; continue;
......
...@@ -39,9 +39,6 @@ ...@@ -39,9 +39,6 @@
#include <linux/init.h> #include <linux/init.h>
#include <asm/semaphore.h> #include <asm/semaphore.h>
/** This declaration is missing from linux/usb.h **/
extern int usb_get_string(struct usb_device *dev, unsigned short langid, unsigned char index, void *buf, int size);
#include "usb-midi.h" #include "usb-midi.h"
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
...@@ -1519,15 +1516,17 @@ static int on_bits( unsigned short v ) ...@@ -1519,15 +1516,17 @@ static int on_bits( unsigned short v )
static int get_alt_setting( struct usb_device *d, int ifnum ) static int get_alt_setting( struct usb_device *d, int ifnum )
{ {
int alts, alt=0; int alts, alt=0;
struct usb_interface *iface;
struct usb_host_interface *interface; struct usb_host_interface *interface;
struct usb_endpoint_descriptor *ep; struct usb_endpoint_descriptor *ep;
int epin, epout; int epin, epout;
int i; int i;
alts = d->actconfig->interface[ifnum]->num_altsetting; iface = usb_ifnum_to_if( d, ifnum );
alts = iface->num_altsetting;
for ( alt=0 ; alt<alts ; alt++ ) { for ( alt=0 ; alt<alts ; alt++ ) {
interface = &d->actconfig->interface[ifnum]->altsetting[alt]; interface = &iface->altsetting[alt];
epin = -1; epin = -1;
epout = -1; epout = -1;
...@@ -1542,7 +1541,7 @@ static int get_alt_setting( struct usb_device *d, int ifnum ) ...@@ -1542,7 +1541,7 @@ static int get_alt_setting( struct usb_device *d, int ifnum )
epout = i; epout = i;
} }
if ( epin >= 0 && epout >= 0 ) { if ( epin >= 0 && epout >= 0 ) {
return alt; return interface->desc.bAlternateSetting;
} }
} }
} }
...@@ -1780,12 +1779,13 @@ static int alloc_usb_midi_device( struct usb_device *d, struct usb_midi_state *s ...@@ -1780,12 +1779,13 @@ static int alloc_usb_midi_device( struct usb_device *d, struct usb_midi_state *s
* Called by usb_midi_probe(); * Called by usb_midi_probe();
**/ **/
static int detect_yamaha_device( struct usb_device *d, unsigned int ifnum, struct usb_midi_state *s) static int detect_yamaha_device( struct usb_device *d,
struct usb_interface *iface, unsigned int ifnum,
struct usb_midi_state *s)
{ {
struct usb_host_config *c = d->actconfig;
struct usb_host_interface *interface; struct usb_host_interface *interface;
struct usb_midi_device *u; struct usb_midi_device *u;
unsigned char buf[USB_DT_CONFIG_SIZE], *buffer; unsigned char *buffer;
int bufSize; int bufSize;
int i; int i;
int alts=-1; int alts=-1;
...@@ -1795,13 +1795,13 @@ static int detect_yamaha_device( struct usb_device *d, unsigned int ifnum, struc ...@@ -1795,13 +1795,13 @@ static int detect_yamaha_device( struct usb_device *d, unsigned int ifnum, struc
return -EINVAL; return -EINVAL;
} }
for ( i=0 ; i < c->interface[ifnum]->num_altsetting; i++ ) { for ( i=0 ; i < iface->num_altsetting; i++ ) {
interface = c->interface[ifnum]->altsetting + i; interface = iface->altsetting + i;
if ( interface->desc.bInterfaceClass != 255 || if ( interface->desc.bInterfaceClass != 255 ||
interface->desc.bInterfaceSubClass != 0 ) interface->desc.bInterfaceSubClass != 0 )
continue; continue;
alts = i; alts = interface->desc.bAlternateSetting;
} }
if ( alts == -1 ) { if ( alts == -1 ) {
return -EINVAL; return -EINVAL;
...@@ -1810,30 +1810,11 @@ static int detect_yamaha_device( struct usb_device *d, unsigned int ifnum, struc ...@@ -1810,30 +1810,11 @@ static int detect_yamaha_device( struct usb_device *d, unsigned int ifnum, struc
printk(KERN_INFO "usb-midi: Found YAMAHA USB-MIDI device on dev %04x:%04x, iface %d\n", printk(KERN_INFO "usb-midi: Found YAMAHA USB-MIDI device on dev %04x:%04x, iface %d\n",
d->descriptor.idVendor, d->descriptor.idProduct, ifnum); d->descriptor.idVendor, d->descriptor.idProduct, ifnum);
ret = usb_get_descriptor( d, USB_DT_CONFIG, i, buf, USB_DT_CONFIG_SIZE ); i = d->actconfig - d->config;
if ( ret < 0 ) { buffer = d->rawdescriptors[i];
printk(KERN_INFO "usb-midi: Could not get config (error=%d).\n", ret); bufSize = d->actconfig->desc.wTotalLength;
return -EINVAL;
}
if ( buf[1] != USB_DT_CONFIG || buf[0] < USB_DT_CONFIG_SIZE ) {
printk(KERN_INFO "usb-midi: config not as expected.\n");
return -EINVAL;
}
bufSize = buf[2] | buf[3]<<8;
buffer = (unsigned char *)kmalloc(sizeof(unsigned char)*bufSize, GFP_KERNEL);
if ( !buffer ) {
printk(KERN_INFO "usb-midi: Could not allocate memory.\n");
return -EINVAL;
}
ret = usb_get_descriptor( d, USB_DT_CONFIG, i, buffer, bufSize );
if ( ret < 0 ) {
printk(KERN_INFO "usb-midi: Could not get full config (error=%d).\n", ret);
kfree(buffer);
return -EINVAL;
}
u = parse_descriptor( d, buffer, bufSize, ifnum, alts, 1); u = parse_descriptor( d, buffer, bufSize, ifnum, alts, 1);
kfree(buffer);
if ( u == NULL ) { if ( u == NULL ) {
return -EINVAL; return -EINVAL;
} }
...@@ -1878,24 +1859,25 @@ static int detect_vendor_specific_device( struct usb_device *d, unsigned int ifn ...@@ -1878,24 +1859,25 @@ static int detect_vendor_specific_device( struct usb_device *d, unsigned int ifn
* Returns 0 on success, negative on failure. * Returns 0 on success, negative on failure.
* Called by usb_midi_probe(); * Called by usb_midi_probe();
**/ **/
static int detect_midi_subclass(struct usb_device *d, unsigned int ifnum, struct usb_midi_state *s) static int detect_midi_subclass(struct usb_device *d,
struct usb_interface *iface, unsigned int ifnum,
struct usb_midi_state *s)
{ {
struct usb_host_config *c = d->actconfig;
struct usb_host_interface *interface; struct usb_host_interface *interface;
struct usb_midi_device *u; struct usb_midi_device *u;
unsigned char buf[USB_DT_CONFIG_SIZE], *buffer; unsigned char *buffer;
int bufSize; int bufSize;
int i; int i;
int alts=-1; int alts=-1;
int ret; int ret;
for ( i=0 ; i < c->interface[ifnum]->num_altsetting; i++ ) { for ( i=0 ; i < iface->num_altsetting; i++ ) {
interface = c->interface[ifnum]->altsetting + i; interface = iface->altsetting + i;
if ( interface->desc.bInterfaceClass != USB_CLASS_AUDIO || if ( interface->desc.bInterfaceClass != USB_CLASS_AUDIO ||
interface->desc.bInterfaceSubClass != USB_SUBCLASS_MIDISTREAMING ) interface->desc.bInterfaceSubClass != USB_SUBCLASS_MIDISTREAMING )
continue; continue;
alts = i; alts = interface->desc.bAlternateSetting;
} }
if ( alts == -1 ) { if ( alts == -1 ) {
return -EINVAL; return -EINVAL;
...@@ -1915,30 +1897,11 @@ static int detect_midi_subclass(struct usb_device *d, unsigned int ifnum, struct ...@@ -1915,30 +1897,11 @@ static int detect_midi_subclass(struct usb_device *d, unsigned int ifnum, struct
descriptor they modify or extend. descriptor they modify or extend.
*/ */
ret = usb_get_descriptor( d, USB_DT_CONFIG, i, buf, USB_DT_CONFIG_SIZE ); i = d->actconfig - d->config;
if ( ret < 0 ) { buffer = d->rawdescriptors[i];
printk(KERN_INFO "usb-midi: Could not get config (error=%d).\n", ret); bufSize = d->actconfig->desc.wTotalLength;
return -EINVAL;
}
if ( buf[1] != USB_DT_CONFIG || buf[0] < USB_DT_CONFIG_SIZE ) {
printk(KERN_INFO "usb-midi: config not as expected.\n");
return -EINVAL;
}
bufSize = buf[2] | buf[3]<<8;
buffer = (unsigned char *)kmalloc(sizeof(unsigned char)*bufSize, GFP_KERNEL);
if ( !buffer ) {
printk(KERN_INFO "usb-midi: Could not allocate memory.\n");
return -EINVAL;
}
ret = usb_get_descriptor( d, USB_DT_CONFIG, i, buffer, bufSize );
if ( ret < 0 ) {
printk(KERN_INFO "usb-midi: Could not get full config (error=%d).\n", ret);
kfree(buffer);
return -EINVAL;
}
u = parse_descriptor( d, buffer, bufSize, ifnum, alts, 0); u = parse_descriptor( d, buffer, bufSize, ifnum, alts, 0);
kfree(buffer);
if ( u == NULL ) { if ( u == NULL ) {
return -EINVAL; return -EINVAL;
} }
...@@ -2002,7 +1965,7 @@ static int usb_midi_probe(struct usb_interface *intf, ...@@ -2002,7 +1965,7 @@ static int usb_midi_probe(struct usb_interface *intf,
{ {
struct usb_midi_state *s; struct usb_midi_state *s;
struct usb_device *dev = interface_to_usbdev(intf); struct usb_device *dev = interface_to_usbdev(intf);
int ifnum = intf->altsetting->desc.bInterfaceNumber; int ifnum = intf->cur_altsetting->desc.bInterfaceNumber;
s = (struct usb_midi_state *)kmalloc(sizeof(struct usb_midi_state), GFP_KERNEL); s = (struct usb_midi_state *)kmalloc(sizeof(struct usb_midi_state), GFP_KERNEL);
if ( !s ) if ( !s )
...@@ -2018,9 +1981,9 @@ static int usb_midi_probe(struct usb_interface *intf, ...@@ -2018,9 +1981,9 @@ static int usb_midi_probe(struct usb_interface *intf,
if ( if (
detect_by_hand( dev, ifnum, s ) && detect_by_hand( dev, ifnum, s ) &&
detect_midi_subclass( dev, ifnum, s ) && detect_midi_subclass( dev, intf, ifnum, s ) &&
detect_vendor_specific_device( dev, ifnum, s ) && detect_vendor_specific_device( dev, ifnum, s ) &&
detect_yamaha_device( dev, ifnum, s) ) { detect_yamaha_device( dev, intf, ifnum, s) ) {
kfree(s); kfree(s);
return -EIO; return -EIO;
} }
......
...@@ -133,6 +133,7 @@ struct usblp { ...@@ -133,6 +133,7 @@ struct usblp {
wait_queue_head_t wait; /* Zzzzz ... */ wait_queue_head_t wait; /* Zzzzz ... */
int readcount; /* Counter for reads */ int readcount; /* Counter for reads */
int ifnum; /* Interface number */ int ifnum; /* Interface number */
struct usb_interface *intf; /* The interface */
/* Alternate-setting numbers and endpoints for each protocol /* Alternate-setting numbers and endpoints for each protocol
* (7/1/{index=1,2,3}) that the device supports: */ * (7/1/{index=1,2,3}) that the device supports: */
struct { struct {
...@@ -609,8 +610,10 @@ static ssize_t usblp_write(struct file *file, const char __user *buffer, size_t ...@@ -609,8 +610,10 @@ static ssize_t usblp_write(struct file *file, const char __user *buffer, size_t
while (writecount < count) { while (writecount < count) {
if (!usblp->wcomplete) { if (!usblp->wcomplete) {
barrier(); barrier();
if (file->f_flags & O_NONBLOCK) if (file->f_flags & O_NONBLOCK) {
writecount += transfer_length;
return writecount ? writecount : -EAGAIN; return writecount ? writecount : -EAGAIN;
}
timeout = USBLP_WRITE_TIMEOUT; timeout = USBLP_WRITE_TIMEOUT;
add_wait_queue(&usblp->wait, &wait); add_wait_queue(&usblp->wait, &wait);
...@@ -670,7 +673,8 @@ static ssize_t usblp_write(struct file *file, const char __user *buffer, size_t ...@@ -670,7 +673,8 @@ static ssize_t usblp_write(struct file *file, const char __user *buffer, size_t
usblp->writeurb->transfer_buffer_length = transfer_length; usblp->writeurb->transfer_buffer_length = transfer_length;
if (copy_from_user(usblp->writeurb->transfer_buffer, buffer + writecount, transfer_length)) { if (copy_from_user(usblp->writeurb->transfer_buffer,
buffer + writecount, transfer_length)) {
up(&usblp->sem); up(&usblp->sem);
return writecount ? writecount : -EFAULT; return writecount ? writecount : -EFAULT;
} }
...@@ -837,7 +841,8 @@ static int usblp_probe(struct usb_interface *intf, ...@@ -837,7 +841,8 @@ static int usblp_probe(struct usb_interface *intf,
usblp->dev = dev; usblp->dev = dev;
init_MUTEX (&usblp->sem); init_MUTEX (&usblp->sem);
init_waitqueue_head(&usblp->wait); init_waitqueue_head(&usblp->wait);
usblp->ifnum = intf->altsetting->desc.bInterfaceNumber; usblp->ifnum = intf->cur_altsetting->desc.bInterfaceNumber;
usblp->intf = intf;
usblp->writeurb = usb_alloc_urb(0, GFP_KERNEL); usblp->writeurb = usb_alloc_urb(0, GFP_KERNEL);
if (!usblp->writeurb) { if (!usblp->writeurb) {
...@@ -973,7 +978,7 @@ static int usblp_select_alts(struct usblp *usblp) ...@@ -973,7 +978,7 @@ static int usblp_select_alts(struct usblp *usblp)
struct usb_endpoint_descriptor *epd, *epwrite, *epread; struct usb_endpoint_descriptor *epd, *epwrite, *epread;
int p, i, e; int p, i, e;
if_alt = usblp->dev->actconfig->interface[usblp->ifnum]; if_alt = usblp->intf;
for (p = 0; p < USBLP_MAX_PROTOCOLS; p++) for (p = 0; p < USBLP_MAX_PROTOCOLS; p++)
usblp->protocol[p].alt_setting = -1; usblp->protocol[p].alt_setting = -1;
...@@ -1022,7 +1027,8 @@ static int usblp_select_alts(struct usblp *usblp) ...@@ -1022,7 +1027,8 @@ static int usblp_select_alts(struct usblp *usblp)
epread = NULL; epread = NULL;
} }
usblp->protocol[ifd->desc.bInterfaceProtocol].alt_setting = i; usblp->protocol[ifd->desc.bInterfaceProtocol].alt_setting =
ifd->desc.bAlternateSetting;
usblp->protocol[ifd->desc.bInterfaceProtocol].epwrite = epwrite; usblp->protocol[ifd->desc.bInterfaceProtocol].epwrite = epwrite;
usblp->protocol[ifd->desc.bInterfaceProtocol].epread = epread; usblp->protocol[ifd->desc.bInterfaceProtocol].epread = epread;
} }
......
...@@ -51,8 +51,8 @@ static const size_t pool_max [HCD_BUFFER_POOLS] = { ...@@ -51,8 +51,8 @@ static const size_t pool_max [HCD_BUFFER_POOLS] = {
* @hcd: the bus whose buffer pools are to be initialized * @hcd: the bus whose buffer pools are to be initialized
* Context: !in_interrupt() * Context: !in_interrupt()
* *
* Call this as part of initializing a host controller that uses the pci dma * Call this as part of initializing a host controller that uses the dma
* memory allocators. It initializes some pools of dma-consistent memory that * memory allocators. It initializes some pools of dma-coherent memory that
* will be shared by all drivers using that controller, or returns a negative * will be shared by all drivers using that controller, or returns a negative
* errno value on error. * errno value on error.
* *
...@@ -115,6 +115,12 @@ void *hcd_buffer_alloc ( ...@@ -115,6 +115,12 @@ void *hcd_buffer_alloc (
struct usb_hcd *hcd = bus->hcpriv; struct usb_hcd *hcd = bus->hcpriv;
int i; int i;
/* some USB hosts just use PIO */
if (!bus->controller->dma_mask) {
*dma = ~(dma_addr_t) 0;
return kmalloc (size, mem_flags);
}
for (i = 0; i < HCD_BUFFER_POOLS; i++) { for (i = 0; i < HCD_BUFFER_POOLS; i++) {
if (size <= pool_max [i]) if (size <= pool_max [i])
return dma_pool_alloc (hcd->pool [i], mem_flags, dma); return dma_pool_alloc (hcd->pool [i], mem_flags, dma);
...@@ -134,6 +140,12 @@ void hcd_buffer_free ( ...@@ -134,6 +140,12 @@ void hcd_buffer_free (
if (!addr) if (!addr)
return; return;
if (!bus->controller->dma_mask) {
kfree (addr);
return;
}
for (i = 0; i < HCD_BUFFER_POOLS; i++) { for (i = 0; i < HCD_BUFFER_POOLS; i++) {
if (size <= pool_max [i]) { if (size <= pool_max [i]) {
dma_pool_free (hcd->pool [i], addr, dma); dma_pool_free (hcd->pool [i], addr, dma);
......
...@@ -72,13 +72,10 @@ static int usb_parse_endpoint(struct usb_host_endpoint *endpoint, unsigned char ...@@ -72,13 +72,10 @@ static int usb_parse_endpoint(struct usb_host_endpoint *endpoint, unsigned char
return buffer - buffer0; 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; int j;
intf = to_usb_interface(dev);
if (intf->altsetting) { if (intf->altsetting) {
for (j = 0; j < intf->num_altsetting; j++) { for (j = 0; j < intf->num_altsetting; j++) {
struct usb_host_interface *as = &intf->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 ...@@ -235,8 +232,6 @@ int usb_parse_configuration(struct usb_host_config *config, char *buffer, int si
return -ENOMEM; return -ENOMEM;
} }
memset(interface, 0, sizeof(struct usb_interface)); 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 /* Go through the descriptors, checking their length and counting the
...@@ -374,7 +369,7 @@ void usb_destroy_configuration(struct usb_device *dev) ...@@ -374,7 +369,7 @@ void usb_destroy_configuration(struct usb_device *dev)
struct usb_interface *ifp = cf->interface[i]; struct usb_interface *ifp = cf->interface[i];
if (ifp) if (ifp)
put_device(&ifp->dev); usb_free_intf(ifp);
} }
} }
kfree(dev->config); kfree(dev->config);
......
...@@ -430,19 +430,14 @@ static int findintfep(struct usb_device *dev, unsigned int ep) ...@@ -430,19 +430,14 @@ static int findintfep(struct usb_device *dev, unsigned int ep)
static int findintfif(struct usb_device *dev, unsigned int ifn) static int findintfif(struct usb_device *dev, unsigned int ifn)
{ {
unsigned int i, j; unsigned int i;
struct usb_interface *iface;
struct usb_host_interface *alts;
if (ifn & ~0xff) if (ifn & ~0xff)
return -EINVAL; return -EINVAL;
for (i = 0; i < dev->actconfig->desc.bNumInterfaces; i++) { for (i = 0; i < dev->actconfig->desc.bNumInterfaces; i++) {
iface = dev->actconfig->interface[i]; if (dev->actconfig->interface[i]->
for (j = 0; j < iface->num_altsetting; j++) { altsetting[0].desc.bInterfaceNumber == ifn)
alts = &iface->altsetting[j]; return i;
if (alts->desc.bInterfaceNumber == ifn)
return i;
}
} }
return -ENOENT; return -ENOENT;
} }
...@@ -688,9 +683,7 @@ static int proc_getdriver(struct dev_state *ps, void __user *arg) ...@@ -688,9 +683,7 @@ static int proc_getdriver(struct dev_state *ps, void __user *arg)
return -EFAULT; return -EFAULT;
if ((ret = findintfif(ps->dev, gd.interface)) < 0) if ((ret = findintfif(ps->dev, gd.interface)) < 0)
return ret; return ret;
interface = usb_ifnum_to_if(ps->dev, gd.interface); interface = ps->dev->actconfig->interface[ret];
if (!interface)
return -EINVAL;
if (!interface->driver) if (!interface->driver)
return -ENODATA; return -ENODATA;
strcpy(gd.driver, interface->driver->name); strcpy(gd.driver, interface->driver->name);
...@@ -744,9 +737,7 @@ static int proc_setintf(struct dev_state *ps, void __user *arg) ...@@ -744,9 +737,7 @@ static int proc_setintf(struct dev_state *ps, void __user *arg)
return -EFAULT; return -EFAULT;
if ((ret = findintfif(ps->dev, setintf.interface)) < 0) if ((ret = findintfif(ps->dev, setintf.interface)) < 0)
return ret; return ret;
interface = usb_ifnum_to_if(ps->dev, setintf.interface); interface = ps->dev->actconfig->interface[ret];
if (!interface)
return -EINVAL;
if (interface->driver) { if (interface->driver) {
if ((ret = checkintf(ps, ret))) if ((ret = checkintf(ps, ret)))
return ret; return ret;
......
...@@ -166,13 +166,9 @@ void usb_create_driverfs_dev_files (struct usb_device *udev) ...@@ -166,13 +166,9 @@ void usb_create_driverfs_dev_files (struct usb_device *udev)
static ssize_t \ static ssize_t \
show_##field (struct device *dev, char *buf) \ show_##field (struct device *dev, char *buf) \
{ \ { \
struct usb_interface *intf; \ struct usb_interface *intf = to_usb_interface (dev); \
int alt; \
\ \
intf = to_usb_interface (dev); \ return sprintf (buf, format_string, intf->cur_altsetting->desc.field); \
alt = intf->act_altsetting; \
\
return sprintf (buf, format_string, intf->altsetting[alt].desc.field); \
} \ } \
static DEVICE_ATTR(field, S_IRUGO, show_##field, NULL); 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) ...@@ -147,8 +147,12 @@ int usb_hcd_pci_probe (struct pci_dev *dev, const struct pci_device_id *id)
hcd->driver = driver; hcd->driver = driver;
hcd->description = driver->description; hcd->description = driver->description;
hcd->self.bus_name = pci_name(dev); hcd->self.bus_name = pci_name(dev);
#ifdef CONFIG_PCI_NAMES
hcd->product_desc = dev->pretty_name;
#else
if (hcd->product_desc == NULL) if (hcd->product_desc == NULL)
hcd->product_desc = "USB Host Controller"; hcd->product_desc = "USB Host Controller";
#endif
hcd->self.controller = &dev->dev; hcd->self.controller = &dev->dev;
if ((retval = hcd_buffer_create (hcd)) != 0) { if ((retval = hcd_buffer_create (hcd)) != 0) {
......
...@@ -1213,7 +1213,7 @@ static int hcd_unlink_urb (struct urb *urb) ...@@ -1213,7 +1213,7 @@ static int hcd_unlink_urb (struct urb *urb)
break; break;
} }
if (tmp != &urb->urb_list) { if (tmp != &urb->urb_list) {
retval = -EINVAL; retval = -EIDRM;
goto done; goto done;
} }
...@@ -1294,7 +1294,7 @@ static int hcd_unlink_urb (struct urb *urb) ...@@ -1294,7 +1294,7 @@ static int hcd_unlink_urb (struct urb *urb)
spin_unlock (&hcd_data_lock); spin_unlock (&hcd_data_lock);
spin_unlock_irqrestore (&urb->lock, flags); spin_unlock_irqrestore (&urb->lock, flags);
bye: bye:
if (retval && sys && sys->driver) if (retval != -EIDRM && sys && sys->driver)
dev_dbg (sys, "hcd_unlink_urb %p fail %d\n", urb, retval); dev_dbg (sys, "hcd_unlink_urb %p fail %d\n", urb, retval);
return retval; return retval;
} }
......
...@@ -560,7 +560,7 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id) ...@@ -560,7 +560,7 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)
struct usb_hub *hub; struct usb_hub *hub;
unsigned long flags; unsigned long flags;
desc = intf->altsetting + intf->act_altsetting; desc = intf->cur_altsetting;
dev = interface_to_usbdev(intf); dev = interface_to_usbdev(intf);
/* Some hubs have a subclass of 1, which AFAICT according to the */ /* 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) ...@@ -1344,15 +1344,15 @@ int usb_physical_reset_device(struct usb_device *dev)
for (i = 0; i < dev->actconfig->desc.bNumInterfaces; i++) { for (i = 0; i < dev->actconfig->desc.bNumInterfaces; i++) {
struct usb_interface *intf = dev->actconfig->interface[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; desc = &intf->cur_altsetting->desc;
ret = usb_set_interface(dev, as->bInterfaceNumber, ret = usb_set_interface(dev, desc->bInterfaceNumber,
as->bAlternateSetting); desc->bAlternateSetting);
if (ret < 0) { if (ret < 0) {
err("failed to set active alternate setting " err("failed to set active alternate setting "
"for dev %s interface %d (error=%d)", "for dev %s interface %d (error=%d)",
dev->devpath, i, ret); dev->devpath, desc->bInterfaceNumber, ret);
return ret; return ret;
} }
} }
......
...@@ -783,16 +783,22 @@ void usb_disable_endpoint(struct usb_device *dev, unsigned int epaddr) ...@@ -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) void usb_disable_interface(struct usb_device *dev, struct usb_interface *intf)
{ {
struct usb_host_interface *hintf = struct usb_host_interface *alt = intf->cur_altsetting;
&intf->altsetting[intf->act_altsetting];
int i; int i;
for (i = 0; i < hintf->desc.bNumEndpoints; ++i) { for (i = 0; i < alt->desc.bNumEndpoints; ++i) {
usb_disable_endpoint(dev, 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 * usb_disable_device - Disable all the endpoints for a USB device
* @dev: the device whose endpoints are being disabled * @dev: the device whose endpoints are being disabled
...@@ -822,12 +828,16 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0) ...@@ -822,12 +828,16 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0)
if (dev->actconfig) { if (dev->actconfig) {
for (i = 0; i < dev->actconfig->desc.bNumInterfaces; i++) { for (i = 0; i < dev->actconfig->desc.bNumInterfaces; i++) {
struct usb_interface *interface; struct usb_interface *interface;
struct completion intf_completion;
/* remove this interface */ /* remove this interface */
interface = dev->actconfig->interface[i]; interface = dev->actconfig->interface[i];
dev_dbg (&dev->dev, "unregistering interface %s\n", dev_dbg (&dev->dev, "unregistering interface %s\n",
interface->dev.bus_id); 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; dev->actconfig = 0;
if (dev->state == USB_STATE_CONFIGURED) if (dev->state == USB_STATE_CONFIGURED)
...@@ -876,12 +886,11 @@ void usb_enable_endpoint(struct usb_device *dev, ...@@ -876,12 +886,11 @@ void usb_enable_endpoint(struct usb_device *dev,
void usb_enable_interface(struct usb_device *dev, void usb_enable_interface(struct usb_device *dev,
struct usb_interface *intf) struct usb_interface *intf)
{ {
struct usb_host_interface *hintf = struct usb_host_interface *alt = intf->cur_altsetting;
&intf->altsetting[intf->act_altsetting];
int i; int i;
for (i = 0; i < hintf->desc.bNumEndpoints; ++i) for (i = 0; i < alt->desc.bNumEndpoints; ++i)
usb_enable_endpoint(dev, &hintf->endpoint[i].desc); usb_enable_endpoint(dev, &alt->endpoint[i].desc);
} }
/** /**
...@@ -920,6 +929,7 @@ void usb_enable_interface(struct usb_device *dev, ...@@ -920,6 +929,7 @@ void usb_enable_interface(struct usb_device *dev,
int usb_set_interface(struct usb_device *dev, int interface, int alternate) int usb_set_interface(struct usb_device *dev, int interface, int alternate)
{ {
struct usb_interface *iface; struct usb_interface *iface;
struct usb_host_interface *alt;
int ret; int ret;
int manual = 0; int manual = 0;
...@@ -929,14 +939,15 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate) ...@@ -929,14 +939,15 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
return -EINVAL; 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; return -EINVAL;
}
ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
USB_REQ_SET_INTERFACE, USB_RECIP_INTERFACE, USB_REQ_SET_INTERFACE, USB_RECIP_INTERFACE,
iface->altsetting[alternate] alternate, interface, NULL, 0, HZ * 5);
.desc.bAlternateSetting,
interface, NULL, 0, HZ * 5);
/* 9.4.10 says devices don't need this and are free to STALL the /* 9.4.10 says devices don't need this and are free to STALL the
* request if the interface only has one alternate setting. * 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) ...@@ -957,7 +968,7 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
/* prevent submissions using previous endpoint settings */ /* prevent submissions using previous endpoint settings */
usb_disable_interface(dev, iface); 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 /* If the interface only has one altsetting and the device didn't
* accept the request, we attempt to carry out the equivalent action * 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) ...@@ -965,13 +976,11 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
* new altsetting. * new altsetting.
*/ */
if (manual) { if (manual) {
struct usb_host_interface *iface_as =
&iface->altsetting[alternate];
int i; int i;
for (i = 0; i < iface_as->desc.bNumEndpoints; i++) { for (i = 0; i < alt->desc.bNumEndpoints; i++) {
unsigned int epaddr = unsigned int epaddr =
iface_as->endpoint[i].desc.bEndpointAddress; alt->endpoint[i].desc.bEndpointAddress;
unsigned int pipe = unsigned int pipe =
__create_pipe(dev, USB_ENDPOINT_NUMBER_MASK & epaddr) __create_pipe(dev, USB_ENDPOINT_NUMBER_MASK & epaddr)
| (usb_endpoint_out(epaddr) ? USB_DIR_OUT : USB_DIR_IN); | (usb_endpoint_out(epaddr) ? USB_DIR_OUT : USB_DIR_IN);
...@@ -1045,8 +1054,19 @@ int usb_reset_configuration(struct usb_device *dev) ...@@ -1045,8 +1054,19 @@ int usb_reset_configuration(struct usb_device *dev)
/* re-init hc/hcd interface/endpoint state */ /* re-init hc/hcd interface/endpoint state */
for (i = 0; i < config->desc.bNumInterfaces; i++) { for (i = 0; i < config->desc.bNumInterfaces; i++) {
struct usb_interface *intf = config->interface[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); usb_enable_interface(dev, intf);
} }
return 0; return 0;
...@@ -1135,25 +1155,34 @@ int usb_set_configuration(struct usb_device *dev, int configuration) ...@@ -1135,25 +1155,34 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
*/ */
for (i = 0; i < cp->desc.bNumInterfaces; ++i) { for (i = 0; i < cp->desc.bNumInterfaces; ++i) {
struct usb_interface *intf = cp->interface[i]; struct usb_interface *intf = cp->interface[i];
struct usb_interface_descriptor *desc; struct usb_host_interface *alt;
intf->act_altsetting = 0; alt = usb_altnum_to_altsetting(intf, 0);
desc = &intf->altsetting [0].desc;
usb_enable_interface(dev, intf);
/* 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.parent = &dev->dev;
intf->dev.driver = NULL; intf->dev.driver = NULL;
intf->dev.bus = &usb_bus_type; intf->dev.bus = &usb_bus_type;
intf->dev.dma_mask = dev->dev.dma_mask; intf->dev.dma_mask = dev->dev.dma_mask;
intf->dev.release = release_interface;
sprintf (&intf->dev.bus_id[0], "%d-%s:%d.%d", sprintf (&intf->dev.bus_id[0], "%d-%s:%d.%d",
dev->bus->busnum, dev->devpath, dev->bus->busnum, dev->devpath,
configuration, configuration,
desc->bInterfaceNumber); alt->desc.bInterfaceNumber);
dev_dbg (&dev->dev, dev_dbg (&dev->dev,
"registering %s (config #%d, interface %d)\n", "registering %s (config #%d, interface %d)\n",
intf->dev.bus_id, configuration, intf->dev.bus_id, configuration,
desc->bInterfaceNumber); alt->desc.bInterfaceNumber);
device_add (&intf->dev); device_register (&intf->dev);
usb_create_driverfs_intf_files (intf); usb_create_driverfs_intf_files (intf);
} }
} }
......
...@@ -116,7 +116,8 @@ struct urb * usb_get_urb(struct urb *urb) ...@@ -116,7 +116,8 @@ struct urb * usb_get_urb(struct urb *urb)
* describing that request to the USB subsystem. Request completion will * describing that request to the USB subsystem. Request completion will
* be indicated later, asynchronously, by calling the completion handler. * be indicated later, asynchronously, by calling the completion handler.
* The three types of completion are success, error, and unlink * The three types of completion are success, error, and unlink
* (also called "request cancellation"). * (a software-induced fault, also called "request cancelation").
*
* URBs may be submitted in interrupt context. * URBs may be submitted in interrupt context.
* *
* The caller must have correctly initialized the URB before submitting * The caller must have correctly initialized the URB before submitting
...@@ -127,12 +128,23 @@ struct urb * usb_get_urb(struct urb *urb) ...@@ -127,12 +128,23 @@ struct urb * usb_get_urb(struct urb *urb)
* *
* Successful submissions return 0; otherwise this routine returns a * Successful submissions return 0; otherwise this routine returns a
* negative error number. If the submission is successful, the complete() * negative error number. If the submission is successful, the complete()
* callback from the urb will be called exactly once, when the USB core and * callback from the URB will be called exactly once, when the USB core and
* host controller driver are finished with the urb. When the completion * Host Controller Driver (HCD) are finished with the URB. When the completion
* function is called, control of the URB is returned to the device * function is called, control of the URB is returned to the device
* driver which issued the request. The completion handler may then * driver which issued the request. The completion handler may then
* immediately free or reuse that URB. * immediately free or reuse that URB.
* *
* With few exceptions, USB device drivers should never access URB fields
* provided by usbcore or the HCD until its complete() is called.
* The exceptions relate to periodic transfer scheduling. For both
* interrupt and isochronous urbs, as part of successful URB submission
* urb->interval is modified to reflect the actual transfer period used
* (normally some power of two units). And for isochronous urbs,
* urb->start_frame is modified to reflect when the URB's transfers were
* scheduled to start. Not all isochronous transfer scheduling policies
* will work, but most host controller drivers should easily handle ISO
* queues going from now until 10-200 msec into the future.
*
* For control endpoints, the synchronous usb_control_msg() call is * For control endpoints, the synchronous usb_control_msg() call is
* often used (in non-interrupt context) instead of this call. * often used (in non-interrupt context) instead of this call.
* That is often used through convenience wrappers, for the requests * That is often used through convenience wrappers, for the requests
...@@ -143,15 +155,17 @@ struct urb * usb_get_urb(struct urb *urb) ...@@ -143,15 +155,17 @@ struct urb * usb_get_urb(struct urb *urb)
* *
* URBs may be submitted to endpoints before previous ones complete, to * URBs may be submitted to endpoints before previous ones complete, to
* minimize the impact of interrupt latencies and system overhead on data * minimize the impact of interrupt latencies and system overhead on data
* throughput. This is required for continuous isochronous data streams, * throughput. With that queuing policy, an endpoint's queue would never
* be empty. This is required for continuous isochronous data streams,
* and may also be required for some kinds of interrupt transfers. Such * and may also be required for some kinds of interrupt transfers. Such
* queueing also maximizes bandwidth utilization by letting USB controllers * queuing also maximizes bandwidth utilization by letting USB controllers
* start work on later requests before driver software has finished the * start work on later requests before driver software has finished the
* completion processing for earlier requests. * completion processing for earlier (successful) requests.
* *
* Bulk and Isochronous URBs may always be queued. At this writing, all * As of Linux 2.6, all USB endpoint transfer queues support depths greater
* mainstream host controller drivers support queueing for control and * than one. This was previously a HCD-specific behavior, except for ISO
* interrupt transfer requests. * transfers. Non-isochronous endpoint queues are inactive during cleanup
* after faults (transfer errors or cancelation).
* *
* Reserved Bandwidth Transfers: * Reserved Bandwidth Transfers:
* *
...@@ -389,7 +403,7 @@ int usb_submit_urb(struct urb *urb, int mem_flags) ...@@ -389,7 +403,7 @@ int usb_submit_urb(struct urb *urb, int mem_flags)
* When the URB_ASYNC_UNLINK transfer flag for the URB is clear, this * When the URB_ASYNC_UNLINK transfer flag for the URB is clear, this
* request is synchronous. Success is indicated by returning zero, * request is synchronous. Success is indicated by returning zero,
* at which time the urb will have been unlinked and its completion * at which time the urb will have been unlinked and its completion
* handler will have been called with urb->status -ENOENT. Failure is * handler will have been called with urb->status == -ENOENT. Failure is
* indicated by any other return value. * indicated by any other return value.
* *
* The synchronous cancelation mode may not be used * The synchronous cancelation mode may not be used
...@@ -400,8 +414,37 @@ int usb_submit_urb(struct urb *urb, int mem_flags) ...@@ -400,8 +414,37 @@ int usb_submit_urb(struct urb *urb, int mem_flags)
* When the URB_ASYNC_UNLINK transfer flag for the URB is set, this * When the URB_ASYNC_UNLINK transfer flag for the URB is set, this
* request is asynchronous. Success is indicated by returning -EINPROGRESS, * request is asynchronous. Success is indicated by returning -EINPROGRESS,
* at which time the urb will normally not have been unlinked. * at which time the urb will normally not have been unlinked.
* The completion function will see urb->status -ECONNRESET. Failure * The completion function will see urb->status == -ECONNRESET. Failure
* is indicated by any other return value. * is indicated by any other return value.
*
* Unlinking and Endpoint Queues:
*
* Host Controller Driver (HCDs) place all the URBs for a particular
* endpoint in a queue. Normally the queue advances as the controller
* hardware processes each request. But when an URB terminates with any
* fault (such as an error, or being unlinked) its queue stops, at least
* until that URB's completion routine returns. It is guaranteed that
* the queue will not restart until all its unlinked URBs have been fully
* retired, with their completion routines run, even if that's not until
* some time after the original completion handler returns.
*
* This means that USB device drivers can safely build deep queues for
* large or complex transfers, and clean them up reliably after any sort
* of aborted transfer by unlinking all pending URBs at the first fault.
*
* Note that an URB terminating early because a short packet was received
* will count as an error if and only if the URB_SHORT_NOT_OK flag is set.
* Also, that all unlinks performed in any URB completion handler must
* be asynchronous.
*
* Queues for isochronous endpoints are treated differently, because they
* advance at fixed rates. Such queues do not stop when an URB is unlinked.
* An unlinked URB may leave a gap in the stream of packets. It is undefined
* whether such gaps can be filled in.
*
* When control URBs terminates with an error, it is likely that the
* status stage of the transfer will not take place, even if it is merely
* a soft error resulting from a short-packet with URB_SHORT_NOT_OK set.
*/ */
int usb_unlink_urb(struct urb *urb) int usb_unlink_urb(struct urb *urb)
{ {
......
...@@ -189,7 +189,7 @@ void usb_deregister(struct usb_driver *driver) ...@@ -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 * @dev: the device whose current configuration is considered
* @ifnum: the desired interface * @ifnum: the desired interface
* *
...@@ -219,6 +219,33 @@ struct usb_interface *usb_ifnum_to_if(struct usb_device *dev, unsigned ifnum) ...@@ -219,6 +219,33 @@ struct usb_interface *usb_ifnum_to_if(struct usb_device *dev, unsigned ifnum)
return NULL; 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 * usb_epnum_to_ep_desc - get the endpoint object with a given endpoint number
* @dev: the device whose current configuration+altsettings is considered * @dev: the device whose current configuration+altsettings is considered
...@@ -247,7 +274,7 @@ usb_epnum_to_ep_desc(struct usb_device *dev, unsigned epnum) ...@@ -247,7 +274,7 @@ usb_epnum_to_ep_desc(struct usb_device *dev, unsigned epnum)
/* only endpoints in current altsetting are active */ /* only endpoints in current altsetting are active */
intf = config->interface[i]; intf = config->interface[i];
alt = intf->altsetting + intf->act_altsetting; alt = intf->cur_altsetting;
for (k = 0; k < alt->desc.bNumEndpoints; k++) for (k = 0; k < alt->desc.bNumEndpoints; k++)
if (epnum == alt->endpoint[k].desc.bEndpointAddress) if (epnum == alt->endpoint[k].desc.bEndpointAddress)
...@@ -421,7 +448,7 @@ usb_match_id(struct usb_interface *interface, const struct usb_device_id *id) ...@@ -421,7 +448,7 @@ usb_match_id(struct usb_interface *interface, const struct usb_device_id *id)
if (id == NULL) if (id == NULL)
return NULL; return NULL;
intf = &interface->altsetting [interface->act_altsetting]; intf = interface->cur_altsetting;
dev = interface_to_usbdev(interface); dev = interface_to_usbdev(interface);
/* It is important to check that id->driver_info is nonzero, /* 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, ...@@ -624,7 +651,7 @@ static int usb_hotplug (struct device *dev, char **envp, int num_envp,
scratch += length; scratch += length;
if (usb_dev->descriptor.bDeviceClass == 0) { 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 /* 2.4 only exposed interface zero. in 2.5, hotplug
* agents are called for all interfaces, and can use * 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, ...@@ -633,9 +660,9 @@ static int usb_hotplug (struct device *dev, char **envp, int num_envp,
envp [i++] = scratch; envp [i++] = scratch;
length += snprintf (scratch, buffer_size - length, length += snprintf (scratch, buffer_size - length,
"INTERFACE=%d/%d/%d", "INTERFACE=%d/%d/%d",
intf->altsetting[alt].desc.bInterfaceClass, alt->desc.bInterfaceClass,
intf->altsetting[alt].desc.bInterfaceSubClass, alt->desc.bInterfaceSubClass,
intf->altsetting[alt].desc.bInterfaceProtocol); alt->desc.bInterfaceProtocol);
if ((buffer_size - length <= 0) || (i >= num_envp)) if ((buffer_size - length <= 0) || (i >= num_envp))
return -ENOMEM; return -ENOMEM;
++length; ++length;
...@@ -1598,6 +1625,7 @@ EXPORT_SYMBOL(usb_driver_release_interface); ...@@ -1598,6 +1625,7 @@ EXPORT_SYMBOL(usb_driver_release_interface);
EXPORT_SYMBOL(usb_match_id); EXPORT_SYMBOL(usb_match_id);
EXPORT_SYMBOL(usb_find_interface); EXPORT_SYMBOL(usb_find_interface);
EXPORT_SYMBOL(usb_ifnum_to_if); EXPORT_SYMBOL(usb_ifnum_to_if);
EXPORT_SYMBOL(usb_altnum_to_altsetting);
EXPORT_SYMBOL(usb_reset_device); EXPORT_SYMBOL(usb_reset_device);
EXPORT_SYMBOL(usb_disconnect); EXPORT_SYMBOL(usb_disconnect);
......
...@@ -3,6 +3,15 @@ ...@@ -3,6 +3,15 @@
# (a) a peripheral controller, and # (a) a peripheral controller, and
# (b) the gadget driver using it. # (b) the gadget driver using it.
# #
# NOTE: Gadget support ** DOES NOT ** depend on host-side CONFIG_USB !!
#
# - Host systems (like PCs) need CONFIG_USB (with "A" jacks).
# - Peripherals (like PDAs) need CONFIG_USB_GADGET (with "B" jacks).
# - Some systems have both kinds of of controller.
#
# With help from a special transceiver and a "Mini-AB" jack, systems with
# both kinds of controller can also support "USB On-the-Go" (CONFIG_USB_OTG).
#
menu "USB Gadget Support" menu "USB Gadget Support"
config USB_GADGET config USB_GADGET
...@@ -11,7 +20,7 @@ config USB_GADGET ...@@ -11,7 +20,7 @@ config USB_GADGET
USB is a master/slave protocol, organized with one master USB is a master/slave protocol, organized with one master
host (such as a PC) controlling up to 127 peripheral devices. host (such as a PC) controlling up to 127 peripheral devices.
The USB hardware is asymmetric, which makes it easier to set up: The USB hardware is asymmetric, which makes it easier to set up:
you can't connect two "to-the-host" connectors to each other. you can't connect a "to-the-host" connector to a peripheral.
Linux can run in the host, or in the peripheral. In both cases Linux can run in the host, or in the peripheral. In both cases
you need a low level bus controller driver, and some software you need a low level bus controller driver, and some software
...@@ -43,6 +52,7 @@ choice ...@@ -43,6 +52,7 @@ choice
config USB_GADGET_NET2280 config USB_GADGET_NET2280
boolean "NetChip 2280" boolean "NetChip 2280"
depends on PCI depends on PCI
select USB_GADGET_DUALSPEED
help help
NetChip 2280 is a PCI based USB peripheral controller which NetChip 2280 is a PCI based USB peripheral controller which
supports both full and high speed USB 2.0 data transfers. supports both full and high speed USB 2.0 data transfers.
...@@ -126,6 +136,13 @@ config USB_SA1100 ...@@ -126,6 +136,13 @@ config USB_SA1100
endchoice endchoice
config USB_GADGET_DUALSPEED
bool
depends on USB_GADGET
default n
help
Means that gadget drivers should include extra descriptors
and code to handle dual-speed controllers.
# #
# USB Gadget Drivers # USB Gadget Drivers
......
...@@ -8,8 +8,8 @@ obj-$(CONFIG_USB_GOKU) += goku_udc.o ...@@ -8,8 +8,8 @@ obj-$(CONFIG_USB_GOKU) += goku_udc.o
# #
# USB gadget drivers # USB gadget drivers
# #
g_zero-objs := zero.o usbstring.o g_zero-objs := zero.o usbstring.o config.o
g_ether-objs := ether.o usbstring.o g_ether-objs := ether.o usbstring.o config.o
g_serial-objs := serial.o usbstring.o g_serial-objs := serial.o usbstring.o
gadgetfs-objs := inode.o usbstring.o gadgetfs-objs := inode.o usbstring.o
g_file_storage-objs := file_storage.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;
}
...@@ -124,7 +124,6 @@ struct eth_dev { ...@@ -124,7 +124,6 @@ struct eth_dev {
* DRIVER_VERSION_NUM ... alerts the host side driver to differences * DRIVER_VERSION_NUM ... alerts the host side driver to differences
* EP_*_NAME ... which endpoints do we use for which purpose? * EP_*_NAME ... which endpoints do we use for which purpose?
* EP_*_NUM ... numbers for them (often limited by hardware) * EP_*_NUM ... numbers for them (often limited by hardware)
* HIGHSPEED ... define if ep0 and descriptors need high speed support
* WAKEUP ... if hardware supports remote wakeup AND we will issue the * WAKEUP ... if hardware supports remote wakeup AND we will issue the
* usb_gadget_wakeup() call to initiate it, USB_CONFIG_ATT_WAKEUP * usb_gadget_wakeup() call to initiate it, USB_CONFIG_ATT_WAKEUP
* *
...@@ -162,7 +161,6 @@ static const char EP_IN_NAME [] = "ep-b"; ...@@ -162,7 +161,6 @@ static const char EP_IN_NAME [] = "ep-b";
#define EP_IN_NUM 2 #define EP_IN_NUM 2
static const char EP_STATUS_NAME [] = "ep-f"; static const char EP_STATUS_NAME [] = "ep-f";
#define EP_STATUS_NUM 3 #define EP_STATUS_NUM 3
#define HIGHSPEED
/* supports remote wakeup, but this driver doesn't */ /* supports remote wakeup, but this driver doesn't */
extern int net2280_set_fifo_mode (struct usb_gadget *gadget, int mode); extern int net2280_set_fifo_mode (struct usb_gadget *gadget, int mode);
...@@ -311,7 +309,7 @@ static const char EP_IN_NAME[] = "ep2in-bulk"; ...@@ -311,7 +309,7 @@ static const char EP_IN_NAME[] = "ep2in-bulk";
#define DEFAULT_QLEN 2 /* double buffering by default */ #define DEFAULT_QLEN 2 /* double buffering by default */
#endif #endif
#ifdef HIGHSPEED #ifdef CONFIG_USB_GADGET_DUALSPEED
static unsigned qmult = 5; static unsigned qmult = 5;
module_param (qmult, uint, S_IRUGO|S_IWUSR); module_param (qmult, uint, S_IRUGO|S_IWUSR);
...@@ -324,7 +322,7 @@ module_param (qmult, uint, S_IRUGO|S_IWUSR); ...@@ -324,7 +322,7 @@ module_param (qmult, uint, S_IRUGO|S_IWUSR);
/* also defer IRQs on highspeed TX */ /* also defer IRQs on highspeed TX */
#define TX_DELAY DEFAULT_QLEN #define TX_DELAY DEFAULT_QLEN
#else /* !HIGHSPEED ... full speed: */ #else /* full speed (low speed doesn't do bulk) */
#define qlen(gadget) DEFAULT_QLEN #define qlen(gadget) DEFAULT_QLEN
#endif #endif
...@@ -607,7 +605,26 @@ fs_sink_desc = { ...@@ -607,7 +605,26 @@ fs_sink_desc = {
.wMaxPacketSize = __constant_cpu_to_le16 (64), .wMaxPacketSize = __constant_cpu_to_le16 (64),
}; };
#ifdef HIGHSPEED 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 CONFIG_USB_GADGET_DUALSPEED
/* /*
* usb 2.0 devices need to expose both high speed and full speed * usb 2.0 devices need to expose both high speed and full speed
...@@ -660,6 +677,25 @@ dev_qualifier = { ...@@ -660,6 +677,25 @@ dev_qualifier = {
.bNumConfigurations = 1, .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. */ /* maxpacket and other transfer characteristics vary by speed. */
#define ep_desc(g,hs,fs) (((g)->speed==USB_SPEED_HIGH)?(hs):(fs)) #define ep_desc(g,hs,fs) (((g)->speed==USB_SPEED_HIGH)?(hs):(fs))
...@@ -669,7 +705,7 @@ dev_qualifier = { ...@@ -669,7 +705,7 @@ dev_qualifier = {
/* if there's no high speed support, maxpacket doesn't change. */ /* if there's no high speed support, maxpacket doesn't change. */
#define ep_desc(g,hs,fs) fs #define ep_desc(g,hs,fs) fs
#endif /* !HIGHSPEED */ #endif /* !CONFIG_USB_GADGET_DUALSPEED */
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
...@@ -704,86 +740,25 @@ static struct usb_gadget_strings stringtab = { ...@@ -704,86 +740,25 @@ static struct usb_gadget_strings stringtab = {
static int static int
config_buf (enum usb_device_speed speed, u8 *buf, u8 type, unsigned index) config_buf (enum usb_device_speed speed, u8 *buf, u8 type, unsigned index)
{ {
const unsigned config_len = USB_DT_CONFIG_SIZE int len;
#ifdef DEV_CONFIG_CDC const struct usb_descriptor_header **function = fs_function;
+ 2 * USB_DT_INTERFACE_SIZE #ifdef CONFIG_USB_GADGET_DUALSPEED
+ sizeof header_desc int hs = (speed == USB_SPEED_HIGH);
+ 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;
#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;
/* 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) if (type == USB_DT_OTHER_SPEED_CONFIG)
hs = !hs; 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) if (hs)
memcpy (buf, &hs_status_desc, USB_DT_ENDPOINT_SIZE); function = hs_function;
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
#endif #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;
} }
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
...@@ -992,7 +967,7 @@ eth_set_config (struct eth_dev *dev, unsigned number, int gfp_flags) ...@@ -992,7 +967,7 @@ eth_set_config (struct eth_dev *dev, unsigned number, int gfp_flags)
switch (gadget->speed) { switch (gadget->speed) {
case USB_SPEED_FULL: speed = "full"; break; case USB_SPEED_FULL: speed = "full"; break;
#ifdef HIGHSPEED #ifdef CONFIG_USB_GADGET_DUALSPEED
case USB_SPEED_HIGH: speed = "high"; break; case USB_SPEED_HIGH: speed = "high"; break;
#endif #endif
default: speed = "?"; break; default: speed = "?"; break;
...@@ -1163,15 +1138,19 @@ eth_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) ...@@ -1163,15 +1138,19 @@ eth_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
value = min (ctrl->wLength, (u16) sizeof device_desc); value = min (ctrl->wLength, (u16) sizeof device_desc);
memcpy (req->buf, &device_desc, value); memcpy (req->buf, &device_desc, value);
break; break;
#ifdef HIGHSPEED #ifdef CONFIG_USB_GADGET_DUALSPEED
case USB_DT_DEVICE_QUALIFIER: case USB_DT_DEVICE_QUALIFIER:
if (!gadget->is_dualspeed)
break;
value = min (ctrl->wLength, (u16) sizeof dev_qualifier); value = min (ctrl->wLength, (u16) sizeof dev_qualifier);
memcpy (req->buf, &dev_qualifier, value); memcpy (req->buf, &dev_qualifier, value);
break; break;
case USB_DT_OTHER_SPEED_CONFIG: case USB_DT_OTHER_SPEED_CONFIG:
if (!gadget->is_dualspeed)
break;
// FALLTHROUGH // FALLTHROUGH
#endif /* HIGHSPEED */ #endif /* CONFIG_USB_GADGET_DUALSPEED */
case USB_DT_CONFIG: case USB_DT_CONFIG:
value = config_buf (gadget->speed, req->buf, value = config_buf (gadget->speed, req->buf,
ctrl->wValue >> 8, ctrl->wValue >> 8,
...@@ -1675,7 +1654,7 @@ static int eth_start_xmit (struct sk_buff *skb, struct net_device *net) ...@@ -1675,7 +1654,7 @@ static int eth_start_xmit (struct sk_buff *skb, struct net_device *net)
#endif #endif
req->length = length; req->length = length;
#ifdef HIGHSPEED #ifdef CONFIG_USB_GADGET_DUALSPEED
/* throttle highspeed IRQ rate back slightly */ /* throttle highspeed IRQ rate back slightly */
req->no_interrupt = (dev->gadget->speed == USB_SPEED_HIGH) req->no_interrupt = (dev->gadget->speed == USB_SPEED_HIGH)
? ((atomic_read (&dev->tx_qlen) % TX_DELAY) != 0) ? ((atomic_read (&dev->tx_qlen) % TX_DELAY) != 0)
...@@ -1798,7 +1777,7 @@ eth_bind (struct usb_gadget *gadget) ...@@ -1798,7 +1777,7 @@ eth_bind (struct usb_gadget *gadget)
#endif #endif
device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket; device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket;
#ifdef HIGHSPEED #ifdef CONFIG_USB_GADGET_DUALSPEED
/* assumes ep0 uses the same value for both speeds ... */ /* assumes ep0 uses the same value for both speeds ... */
dev_qualifier.bMaxPacketSize0 = device_desc.bMaxPacketSize0; dev_qualifier.bMaxPacketSize0 = device_desc.bMaxPacketSize0;
#endif #endif
...@@ -1894,7 +1873,7 @@ eth_bind (struct usb_gadget *gadget) ...@@ -1894,7 +1873,7 @@ eth_bind (struct usb_gadget *gadget)
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
static struct usb_gadget_driver eth_driver = { static struct usb_gadget_driver eth_driver = {
#ifdef HIGHSPEED #ifdef CONFIG_USB_GADGET_DUALSPEED
.speed = USB_SPEED_HIGH, .speed = USB_SPEED_HIGH,
#else #else
.speed = USB_SPEED_FULL, .speed = USB_SPEED_FULL,
......
/*
* USB device controllers have lots of quirks. Use these macros in
* gadget drivers or other code that needs to deal with them, and which
* autoconfigures instead of using early binding to the hardware.
*
* This could eventually work like the ARM mach_is_*() stuff, driven by
* some config file that gets updated as new hardware is supported.
*
* NOTE: some of these controller drivers may not be available yet.
*/
#ifdef CONFIG_USB_GADGET_NET2280
#define gadget_is_net2280(g) !strcmp("net2280", (g)->name)
#else
#define gadget_is_net2280(g) 0
#endif
#ifdef CONFIG_USB_GADGET_PXA
#define gadget_is_pxa(g) !strcmp("pxa2xx_udc", (g)->name)
#else
#define gadget_is_pxa(g) 0
#endif
#ifdef CONFIG_USB_GADGET_GOKU
#define gadget_is_goku(g) !strcmp("goku_udc", (g)->name)
#else
#define gadget_is_goku(g) 0
#endif
#ifdef CONFIG_USB_GADGET_SUPERH
#define gadget_is_sh(g) !strcmp("sh_udc", (g)->name)
#else
#define gadget_is_sh(g) 0
#endif
#ifdef CONFIG_USB_GADGET_SA1100
#define gadget_is_sa1100(g) !strcmp("sa1100_udc", (g)->name)
#else
#define gadget_is_sa1100(g) 0
#endif
#ifdef CONFIG_USB_GADGET_MQ11XX
#define gadget_is_mq11xx(g) !strcmp("mq11xx_udc", (g)->name)
#else
#define gadget_is_mq11xx(g) 0
#endif
#ifdef CONFIG_USB_GADGET_OMAP
#define gadget_is_omap(g) !strcmp("omap_udc", (g)->name)
#else
#define gadget_is_omap(g) 0
#endif
// CONFIG_USB_GADGET_AT91RM9200
// CONFIG_USB_GADGET_SX2
// CONFIG_USB_GADGET_AU1X00
// ...
...@@ -2663,7 +2663,7 @@ static void gadget_release (struct device *_dev) ...@@ -2663,7 +2663,7 @@ static void gadget_release (struct device *_dev)
/* tear down the binding between this driver and the pci device */ /* tear down the binding between this driver and the pci device */
static void __exit net2280_remove (struct pci_dev *pdev) static void net2280_remove (struct pci_dev *pdev)
{ {
struct net2280 *dev = pci_get_drvdata (pdev); struct net2280 *dev = pci_get_drvdata (pdev);
...@@ -2736,6 +2736,7 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -2736,6 +2736,7 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id)
spin_lock_init (&dev->lock); spin_lock_init (&dev->lock);
dev->pdev = pdev; dev->pdev = pdev;
dev->gadget.ops = &net2280_ops; dev->gadget.ops = &net2280_ops;
dev->gadget.is_dualspeed = 1;
/* the "gadget" abstracts/virtualizes the controller */ /* the "gadget" abstracts/virtualizes the controller */
strcpy (dev->gadget.dev.bus_id, "gadget"); strcpy (dev->gadget.dev.bus_id, "gadget");
...@@ -2884,7 +2885,7 @@ static struct pci_driver net2280_pci_driver = { ...@@ -2884,7 +2885,7 @@ static struct pci_driver net2280_pci_driver = {
.id_table = pci_ids, .id_table = pci_ids,
.probe = net2280_probe, .probe = net2280_probe,
.remove = __exit_p(net2280_remove), .remove = net2280_remove,
/* FIXME add power management support */ /* FIXME add power management support */
}; };
......
...@@ -16,24 +16,89 @@ ...@@ -16,24 +16,89 @@
#include <linux/usb_ch9.h> #include <linux/usb_ch9.h>
#include <linux/usb_gadget.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 * 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 * @id: string id, from low byte of wValue in get string descriptor
* @buf: at least 256 bytes * @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. * string descriptor in utf16-le.
* Returns length of descriptor (always even) or negative errno * Returns length of descriptor (always even) or negative errno
* *
* If your driver needs stings in multiple languages, you'll need to * If your driver needs stings in multiple languages, you'll probably
* to use some alternate solution for languages where the ISO 8859/1 * "switch (wIndex) { ... }" in your ep0 string descriptor logic,
* (latin/1) character set can't be used. For example, they can't be * using this routine after choosing which set of UTF-8 strings to use.
* used with Chinese (Big5, GB2312, etc), Japanese, Korean, or many other * Note that US-ASCII is a strict subset of UTF-8; any string bytes with
* languages. You'd likely "switch (wIndex) { ... }" in your ep0 * the eighth bit set will be multibyte UTF-8 characters, not ISO-8859/1
* string descriptor logic, using this routine in cases where "western * characters (which are also widely used in C strings).
* european" characters suffice for the strings being returned.
*/ */
int int
usb_gadget_get_string (struct usb_gadget_strings *table, int id, u8 *buf) 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) ...@@ -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 */ /* string descriptors have length, tag, then UTF16-LE text */
len = min ((size_t) 126, strlen (s->s)); 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 [0] = (len + 1) * 2;
buf [1] = USB_DT_STRING; 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]; return buf [0];
} }
This diff is collapsed.
...@@ -29,6 +29,15 @@ config USB_EHCI_HCD ...@@ -29,6 +29,15 @@ config USB_EHCI_HCD
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
module will be called ehci-hcd. 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 config USB_OHCI_HCD
tristate "OHCI HCD support" tristate "OHCI HCD support"
depends on USB depends on USB
......
...@@ -579,7 +579,11 @@ show_periodic (struct class_device *class_dev, char *buf) ...@@ -579,7 +579,11 @@ show_periodic (struct class_device *class_dev, char *buf)
break; break;
case Q_TYPE_SITD: case Q_TYPE_SITD:
temp = scnprintf (next, size, 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); tag = Q_NEXT_TYPE (p.sitd->hw_next);
p = p.sitd->sitd_next; p = p.sitd->sitd_next;
break; break;
......
...@@ -106,8 +106,6 @@ static const char hcd_name [] = "ehci_hcd"; ...@@ -106,8 +106,6 @@ static const char hcd_name [] = "ehci_hcd";
#undef EHCI_VERBOSE_DEBUG #undef EHCI_VERBOSE_DEBUG
#undef EHCI_URB_TRACE #undef EHCI_URB_TRACE
// #define have_split_iso
#ifdef DEBUG #ifdef DEBUG
#define EHCI_STATS #define EHCI_STATS
#endif #endif
...@@ -676,6 +674,7 @@ static void ehci_work (struct ehci_hcd *ehci, struct pt_regs *regs) ...@@ -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 /* the IO watchdog guards against hardware or driver bugs that
* misplace IRQs, and should let us run completely without IRQs. * 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)) if ((ehci->async->qh_next.ptr != 0) || (ehci->periodic_sched != 0))
timer_action (ehci, TIMER_IO_WATCHDOG); timer_action (ehci, TIMER_IO_WATCHDOG);
...@@ -796,13 +795,8 @@ static int ehci_urb_enqueue ( ...@@ -796,13 +795,8 @@ static int ehci_urb_enqueue (
case PIPE_ISOCHRONOUS: case PIPE_ISOCHRONOUS:
if (urb->dev->speed == USB_SPEED_HIGH) if (urb->dev->speed == USB_SPEED_HIGH)
return itd_submit (ehci, urb, mem_flags); return itd_submit (ehci, urb, mem_flags);
#ifdef have_split_iso
else else
return sitd_submit (ehci, urb, mem_flags); 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 { ...@@ -492,16 +492,16 @@ struct ehci_itd {
/* /*
* EHCI Specification 0.95 Section 3.4 * EHCI Specification 0.95 Section 3.4
* siTD, aka split-transaction isochronous Transfer Descriptor * 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) * see Figure 3-5 "Split-transaction Isochronous Transaction Descriptor (siTD)
*/ */
struct ehci_sitd { struct ehci_sitd {
/* first part defined by EHCI spec */ /* first part defined by EHCI spec */
u32 hw_next; u32 hw_next;
/* uses bit field macros above - see EHCI 0.95 Table 3-8 */ /* uses bit field macros above - see EHCI 0.95 Table 3-8 */
u32 hw_fullspeed_ep; /* see EHCI table 3-9 */ u32 hw_fullspeed_ep; /* EHCI table 3-9 */
u32 hw_uframe; /* see EHCI table 3-10 */ u32 hw_uframe; /* EHCI table 3-10 */
u32 hw_results; /* see EHCI table 3-11 */ u32 hw_results; /* EHCI table 3-11 */
#define SITD_IOC (1 << 31) /* interrupt on completion */ #define SITD_IOC (1 << 31) /* interrupt on completion */
#define SITD_PAGE (1 << 30) /* buffer 0/1 */ #define SITD_PAGE (1 << 30) /* buffer 0/1 */
#define SITD_LENGTH(x) (0x3ff & ((x)>>16)) #define SITD_LENGTH(x) (0x3ff & ((x)>>16))
...@@ -515,8 +515,8 @@ struct ehci_sitd { ...@@ -515,8 +515,8 @@ struct ehci_sitd {
#define SITD_ACTIVE __constant_cpu_to_le32(SITD_STS_ACTIVE) #define SITD_ACTIVE __constant_cpu_to_le32(SITD_STS_ACTIVE)
u32 hw_buf [2]; /* see EHCI table 3-12 */ u32 hw_buf [2]; /* EHCI table 3-12 */
u32 hw_backpointer; /* see EHCI table 3-13 */ u32 hw_backpointer; /* EHCI table 3-13 */
u32 hw_buf_hi [2]; /* Appendix B */ u32 hw_buf_hi [2]; /* Appendix B */
/* the rest is HCD-private */ /* the rest is HCD-private */
...@@ -552,8 +552,6 @@ struct ehci_fstn { ...@@ -552,8 +552,6 @@ struct ehci_fstn {
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
#define SUBMIT_URB(urb,mem_flags) usb_submit_urb(urb,mem_flags)
#ifndef DEBUG #ifndef DEBUG
#define STUB_DEBUG_FILES #define STUB_DEBUG_FILES
#endif /* DEBUG */ #endif /* DEBUG */
......
...@@ -781,7 +781,8 @@ static void uhci_dec_fsbr(struct uhci_hcd *uhci, struct urb *urb) ...@@ -781,7 +781,8 @@ static void uhci_dec_fsbr(struct uhci_hcd *uhci, struct urb *urb)
/* /*
* Map status to standard result codes * 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. * <dir_out> is True for output TDs and False for input TDs.
*/ */
static int uhci_map_status(int status, int dir_out) static int uhci_map_status(int status, int dir_out)
...@@ -792,22 +793,18 @@ 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; return -EPROTO;
if (status & TD_CTRL_CRCTIMEO) { /* CRC/Timeout */ if (status & TD_CTRL_CRCTIMEO) { /* CRC/Timeout */
if (dir_out) if (dir_out)
return -ETIMEDOUT; return -EPROTO;
else else
return -EILSEQ; return -EILSEQ;
} }
if (status & TD_CTRL_NAK) /* NAK */
return -ETIMEDOUT;
if (status & TD_CTRL_BABBLE) /* Babble */ if (status & TD_CTRL_BABBLE) /* Babble */
return -EOVERFLOW; return -EOVERFLOW;
if (status & TD_CTRL_DBUFERR) /* Buffer error */ if (status & TD_CTRL_DBUFERR) /* Buffer error */
return -ENOSR; return -ENOSR;
if (status & TD_CTRL_STALLED) /* Stalled */ if (status & TD_CTRL_STALLED) /* Stalled */
return -EPIPE; return -EPIPE;
if (status & TD_CTRL_ACTIVE) /* Active */ WARN_ON(status & TD_CTRL_ACTIVE); /* Active */
return 0; return 0;
return -EINVAL;
} }
/* /*
...@@ -832,7 +829,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, struct ur ...@@ -832,7 +829,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, struct ur
status |= TD_CTRL_LS; 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); td = uhci_alloc_td(uhci, urb->dev);
if (!td) if (!td)
...@@ -990,13 +987,13 @@ static int uhci_result_control(struct uhci_hcd *uhci, struct urb *urb) ...@@ -990,13 +987,13 @@ static int uhci_result_control(struct uhci_hcd *uhci, struct urb *urb)
if (urbp->short_control_packet) { if (urbp->short_control_packet) {
tmp = head->prev; tmp = head->prev;
goto status_phase; goto status_stage;
} }
tmp = head->next; tmp = head->next;
td = list_entry(tmp, struct uhci_td, list); 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 */ /* the count */
status = uhci_status_bits(td_status(td)); status = uhci_status_bits(td_status(td));
if (status & TD_CTRL_ACTIVE) if (status & TD_CTRL_ACTIVE)
...@@ -1037,10 +1034,10 @@ static int uhci_result_control(struct uhci_hcd *uhci, struct urb *urb) ...@@ -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); td = list_entry(tmp, struct uhci_td, list);
/* Control status phase */ /* Control status stage */
status = td_status(td); status = td_status(td);
#ifdef I_HAVE_BUGGY_APC_BACKUPS #ifdef I_HAVE_BUGGY_APC_BACKUPS
...@@ -1053,10 +1050,11 @@ static int uhci_result_control(struct uhci_hcd *uhci, struct urb *urb) ...@@ -1053,10 +1050,11 @@ static int uhci_result_control(struct uhci_hcd *uhci, struct urb *urb)
return 0; return 0;
#endif #endif
status = uhci_status_bits(status);
if (status & TD_CTRL_ACTIVE) if (status & TD_CTRL_ACTIVE)
return -EINPROGRESS; return -EINPROGRESS;
if (uhci_status_bits(status)) if (status)
goto td_error; goto td_error;
return 0; return 0;
...@@ -1272,12 +1270,6 @@ static inline int uhci_submit_interrupt(struct uhci_hcd *uhci, struct urb *urb, ...@@ -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)]); 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 * Isochronous transfers
*/ */
...@@ -1403,7 +1395,8 @@ static int uhci_result_isochronous(struct uhci_hcd *uhci, struct urb *urb) ...@@ -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->iso_frame_desc[i].actual_length = actlength;
urb->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; urb->iso_frame_desc[i].status = status;
if (status) { if (status) {
urb->error_count++; urb->error_count++;
...@@ -1508,12 +1501,9 @@ static int uhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, int mem_flags) ...@@ -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; struct urb_priv *urbp = urb->hcpriv;
list_del_init(&urbp->urb_list); list_del_init(&urbp->urb_list);
spin_unlock_irqrestore(&uhci->urb_list_lock, flags); uhci_destroy_urb_priv(uhci, urb);
uhci_destroy_urb_priv (uhci, urb); } else
ret = 0;
return ret;
}
ret = 0;
out: out:
spin_unlock_irqrestore(&uhci->urb_list_lock, flags); spin_unlock_irqrestore(&uhci->urb_list_lock, flags);
...@@ -1541,11 +1531,9 @@ static void uhci_transfer_result(struct uhci_hcd *uhci, struct urb *urb) ...@@ -1541,11 +1531,9 @@ static void uhci_transfer_result(struct uhci_hcd *uhci, struct urb *urb)
case PIPE_CONTROL: case PIPE_CONTROL:
ret = uhci_result_control(uhci, urb); ret = uhci_result_control(uhci, urb);
break; break;
case PIPE_INTERRUPT:
ret = uhci_result_interrupt(uhci, urb);
break;
case PIPE_BULK: case PIPE_BULK:
ret = uhci_result_bulk(uhci, urb); case PIPE_INTERRUPT:
ret = uhci_result_common(uhci, urb);
break; break;
case PIPE_ISOCHRONOUS: case PIPE_ISOCHRONOUS:
ret = uhci_result_isochronous(uhci, urb); ret = uhci_result_isochronous(uhci, urb);
...@@ -1649,10 +1637,12 @@ static int uhci_urb_dequeue(struct usb_hcd *hcd, struct urb *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); struct uhci_hcd *uhci = hcd_to_uhci(hcd);
unsigned long flags; unsigned long flags;
struct urb_priv *urbp = urb->hcpriv; struct urb_priv *urbp;
spin_lock_irqsave(&uhci->urb_list_lock, flags); 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); list_del_init(&urbp->urb_list);
uhci_unlink_generic(uhci, urb); uhci_unlink_generic(uhci, urb);
...@@ -1665,6 +1655,7 @@ static int uhci_urb_dequeue(struct usb_hcd *hcd, struct urb *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); list_add_tail(&urbp->urb_list, &uhci->urb_remove_list);
spin_unlock(&uhci->urb_remove_list_lock); spin_unlock(&uhci->urb_remove_list_lock);
done:
spin_unlock_irqrestore(&uhci->urb_list_lock, flags); spin_unlock_irqrestore(&uhci->urb_list_lock, flags);
return 0; return 0;
} }
...@@ -1861,17 +1852,12 @@ static void uhci_finish_completion(struct usb_hcd *hcd, struct pt_regs *regs) ...@@ -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) static void uhci_remove_pending_urbps(struct uhci_hcd *uhci)
{ {
struct list_head *tmp, *head;
spin_lock(&uhci->urb_remove_list_lock); spin_lock(&uhci->urb_remove_list_lock);
head = &uhci->urb_remove_list; spin_lock(&uhci->complete_list_lock);
tmp = head->next;
while (tmp != head) {
struct urb_priv *urbp = list_entry(tmp, struct urb_priv, urb_list);
tmp = tmp->next; /* Splice the urb_remove_list onto the end of the complete_list */
uhci_moveto_complete(uhci, urbp); list_splice_init(&uhci->urb_remove_list, uhci->complete_list.prev);
} spin_unlock(&uhci->complete_list_lock);
spin_unlock(&uhci->urb_remove_list_lock); spin_unlock(&uhci->urb_remove_list_lock);
} }
...@@ -2458,9 +2444,11 @@ static int uhci_suspend(struct usb_hcd *hcd, u32 state) ...@@ -2458,9 +2444,11 @@ static int uhci_suspend(struct usb_hcd *hcd, u32 state)
struct uhci_hcd *uhci = hcd_to_uhci(hcd); struct uhci_hcd *uhci = hcd_to_uhci(hcd);
/* Don't try to suspend broken motherboards, reset instead */ /* Don't try to suspend broken motherboards, reset instead */
if (suspend_allowed(uhci)) if (suspend_allowed(uhci)) {
suspend_hc(uhci); suspend_hc(uhci);
else uhci->saved_framenumber =
inw(uhci->io_addr + USBFRNUM) & 0x3ff;
} else
reset_hc(uhci); reset_hc(uhci);
return 0; return 0;
} }
...@@ -2471,9 +2459,20 @@ static int uhci_resume(struct usb_hcd *hcd) ...@@ -2471,9 +2459,20 @@ static int uhci_resume(struct usb_hcd *hcd)
pci_set_master(to_pci_dev(uhci_dev(uhci))); pci_set_master(to_pci_dev(uhci_dev(uhci)));
if (uhci->state == UHCI_SUSPENDED) if (uhci->state == UHCI_SUSPENDED) {
/*
* Some systems don't maintain the UHCI register values
* during a PM suspend/resume cycle, so reinitialize
* the Frame Number, the Framelist Base Address, and the
* Interrupt Enable registers.
*/
outw(uhci->saved_framenumber, uhci->io_addr + USBFRNUM);
outl(uhci->fl->dma_handle, uhci->io_addr + USBFLBASEADD);
outw(USBINTR_TIMEOUT | USBINTR_RESUME | USBINTR_IOC |
USBINTR_SP, uhci->io_addr + USBINTR);
uhci->resume_detect = 1; uhci->resume_detect = 1;
else { } else {
reset_hc(uhci); reset_hc(uhci);
start_hc(uhci); start_hc(uhci);
} }
......
...@@ -141,7 +141,7 @@ struct uhci_qh { ...@@ -141,7 +141,7 @@ struct uhci_qh {
TD_CTRL_BABBLE | TD_CTRL_CRCTIME | TD_CTRL_BITSTUFF) TD_CTRL_BABBLE | TD_CTRL_CRCTIME | TD_CTRL_BITSTUFF)
#define uhci_maxerr(err) ((err) << TD_CTRL_C_ERR_SHIFT) #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 */ #define uhci_actual_length(ctrl_sts) (((ctrl_sts) + 1) & TD_CTRL_ACTLEN_MASK) /* 1-based */
/* /*
...@@ -350,6 +350,7 @@ struct uhci_hcd { ...@@ -350,6 +350,7 @@ struct uhci_hcd {
enum uhci_state state; /* FIXME: needs a spinlock */ enum uhci_state state; /* FIXME: needs a spinlock */
unsigned long state_end; /* Time of next transition */ unsigned long state_end; /* Time of next transition */
int resume_detect; /* Need a Global Resume */ int resume_detect; /* Need a Global Resume */
unsigned int saved_framenumber; /* Save during PM suspend */
/* Main list of URB's currently controlled by this HC */ /* Main list of URB's currently controlled by this HC */
spinlock_t urb_list_lock; spinlock_t urb_list_lock;
......
...@@ -42,7 +42,7 @@ hpusbscsi_usb_probe(struct usb_interface *intf, ...@@ -42,7 +42,7 @@ hpusbscsi_usb_probe(struct usb_interface *intf,
const struct usb_device_id *id) const struct usb_device_id *id)
{ {
struct usb_device *dev = interface_to_usbdev(intf); struct usb_device *dev = interface_to_usbdev(intf);
struct usb_host_interface *altsetting = intf->altsetting; struct usb_host_interface *altsetting = intf->cur_altsetting;
struct hpusbscsi *new; struct hpusbscsi *new;
int error = -ENOMEM; int error = -ENOMEM;
int i; int i;
......
...@@ -431,7 +431,7 @@ static int mdc800_usb_probe (struct usb_interface *intf, ...@@ -431,7 +431,7 @@ static int mdc800_usb_probe (struct usb_interface *intf,
err ("probe fails -> wrong Number of Configuration"); err ("probe fails -> wrong Number of Configuration");
return -ENODEV; return -ENODEV;
} }
intf_desc = &intf->altsetting[0]; intf_desc = intf->cur_altsetting;
if ( if (
( intf_desc->desc.bInterfaceClass != 0xff ) ( intf_desc->desc.bInterfaceClass != 0xff )
...@@ -469,13 +469,6 @@ static int mdc800_usb_probe (struct usb_interface *intf, ...@@ -469,13 +469,6 @@ static int mdc800_usb_probe (struct usb_interface *intf,
} }
usb_driver_claim_interface (&mdc800_usb_driver, intf, mdc800);
if (usb_set_interface (dev, intf_desc->desc.bInterfaceNumber, 0) < 0)
{
err ("MDC800 Configuration fails.");
return -ENODEV;
}
info ("Found Mustek MDC800 on USB."); info ("Found Mustek MDC800 on USB.");
down (&mdc800->io_lock); down (&mdc800->io_lock);
...@@ -551,8 +544,6 @@ static void mdc800_usb_disconnect (struct usb_interface *intf) ...@@ -551,8 +544,6 @@ static void mdc800_usb_disconnect (struct usb_interface *intf)
usb_unlink_urb (mdc800->write_urb); usb_unlink_urb (mdc800->write_urb);
usb_unlink_urb (mdc800->download_urb); usb_unlink_urb (mdc800->download_urb);
usb_driver_release_interface (&mdc800_usb_driver, intf);
mdc800->dev=0; mdc800->dev=0;
usb_set_intfdata(intf, NULL); usb_set_intfdata(intf, NULL);
} }
......
...@@ -693,7 +693,6 @@ static int mts_usb_probe(struct usb_interface *intf, ...@@ -693,7 +693,6 @@ static int mts_usb_probe(struct usb_interface *intf,
const struct usb_device_id *id) const struct usb_device_id *id)
{ {
int i; int i;
int result;
int ep_out = -1; int ep_out = -1;
int ep_in_set[3]; /* this will break if we have more than three endpoints int ep_in_set[3]; /* this will break if we have more than three endpoints
which is why we check */ which is why we check */
...@@ -703,7 +702,7 @@ static int mts_usb_probe(struct usb_interface *intf, ...@@ -703,7 +702,7 @@ static int mts_usb_probe(struct usb_interface *intf,
struct vendor_product const* p; struct vendor_product const* p;
struct usb_device *dev = interface_to_usbdev (intf); struct usb_device *dev = interface_to_usbdev (intf);
/* the altsettting 0 on the interface we're probing */ /* the current altsetting on the interface we're probing */
struct usb_host_interface *altsetting; struct usb_host_interface *altsetting;
MTS_DEBUG_GOT_HERE(); MTS_DEBUG_GOT_HERE();
...@@ -724,8 +723,8 @@ static int mts_usb_probe(struct usb_interface *intf, ...@@ -724,8 +723,8 @@ static int mts_usb_probe(struct usb_interface *intf,
MTS_MESSAGE( "model %s is not known to be fully supported, reports welcome!\n", MTS_MESSAGE( "model %s is not known to be fully supported, reports welcome!\n",
p->name ); p->name );
/* the altsettting 0 on the interface we're probing */ /* the current altsetting on the interface we're probing */
altsetting = &(intf->altsetting[0]); altsetting = intf->cur_altsetting;
/* Check if the config is sane */ /* Check if the config is sane */
...@@ -766,20 +765,6 @@ static int mts_usb_probe(struct usb_interface *intf, ...@@ -766,20 +765,6 @@ static int mts_usb_probe(struct usb_interface *intf,
MTS_WARNING( "couldn't find an output bulk endpoint. Bailing out.\n" ); MTS_WARNING( "couldn't find an output bulk endpoint. Bailing out.\n" );
return -ENODEV; return -ENODEV;
} }
result = usb_set_interface(dev, altsetting->desc.bInterfaceNumber, 0);
MTS_DEBUG("usb_set_interface returned %d.\n",result);
switch( result )
{
case 0: /* no error */
break;
default:
MTS_DEBUG( "unknown error %d from usb_set_interface\n",
(int)result );
return -ENODEV;
}
new_desc = kmalloc(sizeof(struct mts_desc), GFP_KERNEL); new_desc = kmalloc(sizeof(struct mts_desc), GFP_KERNEL);
......
...@@ -179,6 +179,18 @@ config USB_POWERMATE ...@@ -179,6 +179,18 @@ config USB_POWERMATE
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
module will be called powermate. 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 config USB_XPAD
tristate "X-Box gamepad support" tristate "X-Box gamepad support"
depends on USB && INPUT depends on USB && INPUT
...@@ -192,3 +204,17 @@ config USB_XPAD ...@@ -192,3 +204,17 @@ config USB_XPAD
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
module will be called xpad. 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) ...@@ -27,10 +27,12 @@ ifeq ($(CONFIG_HID_FF),y)
endif endif
obj-$(CONFIG_USB_AIPTEK) += aiptek.o obj-$(CONFIG_USB_AIPTEK) += aiptek.o
obj-$(CONFIG_USB_ATI_REMOTE) += ati_remote.o
obj-$(CONFIG_USB_HID) += hid.o obj-$(CONFIG_USB_HID) += hid.o
obj-$(CONFIG_USB_KBD) += usbkbd.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_KBTAB) += kbtab.o
obj-$(CONFIG_USB_MOUSE) += usbmouse.o
obj-$(CONFIG_USB_MTOUCH) += mtouchusb.o
obj-$(CONFIG_USB_POWERMATE) += powermate.o obj-$(CONFIG_USB_POWERMATE) += powermate.o
obj-$(CONFIG_USB_WACOM) += wacom.o
obj-$(CONFIG_USB_XPAD) += xpad.o obj-$(CONFIG_USB_XPAD) += xpad.o
...@@ -43,7 +43,8 @@ ...@@ -43,7 +43,8 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/usb.h> #include <linux/usb.h>
#include <asm/unaligned.h>
#include <asm/byteorder.h>
/* /*
* Version Information * Version Information
*/ */
...@@ -160,9 +161,9 @@ aiptek_irq(struct urb *urb, struct pt_regs *regs) ...@@ -160,9 +161,9 @@ aiptek_irq(struct urb *urb, struct pt_regs *regs)
proximity = data[5] & 0x01; proximity = data[5] & 0x01;
input_report_key(dev, BTN_TOOL_PEN, proximity); input_report_key(dev, BTN_TOOL_PEN, proximity);
x = ((__u32) data[1]) | ((__u32) data[2] << 8); x = le16_to_cpu(get_unaligned((u16 *) &data[1]));
y = ((__u32) data[3]) | ((__u32) data[4] << 8); y = le16_to_cpu(get_unaligned((u16 *) &data[3]));
pressure = ((__u32) data[6]) | ((__u32) data[7] << 8); pressure = le16_to_cpu(*(u16 *) &data[6]);
pressure -= aiptek->features->pressure_min; pressure -= aiptek->features->pressure_min;
if (pressure < 0) { if (pressure < 0) {
...@@ -209,8 +210,10 @@ aiptek_open(struct input_dev *dev) ...@@ -209,8 +210,10 @@ aiptek_open(struct input_dev *dev)
return 0; return 0;
aiptek->irq->dev = aiptek->usbdev; aiptek->irq->dev = aiptek->usbdev;
if (usb_submit_urb(aiptek->irq, GFP_KERNEL)) if (usb_submit_urb(aiptek->irq, GFP_KERNEL)) {
aiptek->open--;
return -EIO; return -EIO;
}
return 0; return 0;
} }
...@@ -234,19 +237,27 @@ usb_set_report(struct usb_device *dev, struct usb_host_interface *inter, unsigne ...@@ -234,19 +237,27 @@ usb_set_report(struct usb_device *dev, struct usb_host_interface *inter, unsigne
(type << 8) + id, inter->desc.bInterfaceNumber, buf, size, HZ); (type << 8) + id, inter->desc.bInterfaceNumber, buf, size, HZ);
} }
static void static int
aiptek_command(struct usb_device *dev, struct usb_host_interface *inter, aiptek_command(struct usb_device *dev, struct usb_host_interface *inter,
unsigned char command, unsigned char data) unsigned char command, unsigned char data)
{ {
__u8 buf[3]; u8 *buf;
int err;
buf = kmalloc(3, GFP_KERNEL);
if (!buf)
return -ENOMEM;
buf[0] = 4; buf[0] = 4;
buf[1] = command; buf[1] = command;
buf[2] = data; buf[2] = data;
if (usb_set_report(dev, inter, 3, 2, buf, 3) != 3) { if ((err = usb_set_report(dev, inter, 3, 2, buf, 3)) != 3) {
dbg("aiptek_command: 0x%x 0x%x\n", command, data); dbg("aiptek_command: 0x%x 0x%x\n", command, data);
} }
kfree(buf);
return err < 0 ? err : 0;
} }
static int static int
...@@ -257,30 +268,32 @@ aiptek_probe(struct usb_interface *intf, ...@@ -257,30 +268,32 @@ aiptek_probe(struct usb_interface *intf,
struct usb_host_interface *interface = intf->altsetting + 0; struct usb_host_interface *interface = intf->altsetting + 0;
struct usb_endpoint_descriptor *endpoint; struct usb_endpoint_descriptor *endpoint;
struct aiptek *aiptek; struct aiptek *aiptek;
int err = -ENOMEM;
if (!(aiptek = kmalloc(sizeof (struct aiptek), GFP_KERNEL))) if (!(aiptek = kmalloc(sizeof (struct aiptek), GFP_KERNEL)))
return -ENOMEM; goto error_out_noalloc;
memset(aiptek, 0, sizeof (struct aiptek)); memset(aiptek, 0, sizeof (struct aiptek));
aiptek->data = usb_buffer_alloc(dev, 10, SLAB_ATOMIC, &aiptek->data_dma); aiptek->data = usb_buffer_alloc(dev, 10, GFP_KERNEL, &aiptek->data_dma);
if (!aiptek->data) { if (!aiptek->data) {
kfree(aiptek); goto error_out_nobuf;
return -ENOMEM;
} }
aiptek->irq = usb_alloc_urb(0, GFP_KERNEL); aiptek->irq = usb_alloc_urb(0, GFP_KERNEL);
if (!aiptek->irq) { if (!aiptek->irq) {
usb_buffer_free(dev, 10, aiptek->data, aiptek->data_dma); goto error_out_nourb;
kfree(aiptek);
return -ENOMEM;
} }
/* Resolution500LPI */ /* Resolution500LPI */
aiptek_command(dev, interface, 0x18, 0x04); err = aiptek_command(dev, interface, 0x18, 0x04);
if (err)
goto error_out;
/* SwitchToTablet */ /* SwitchToTablet */
aiptek_command(dev, interface, 0x10, 0x01); err = aiptek_command(dev, interface, 0x10, 0x01);
if (err)
goto error_out;
aiptek->features = aiptek_features + id->driver_info; aiptek->features = aiptek_features + id->driver_info;
...@@ -340,6 +353,16 @@ aiptek_probe(struct usb_interface *intf, ...@@ -340,6 +353,16 @@ aiptek_probe(struct usb_interface *intf,
usb_set_intfdata(intf, aiptek); usb_set_intfdata(intf, aiptek);
return 0; return 0;
error_out:
usb_free_urb(aiptek->irq);
error_out_nourb:
usb_buffer_free(dev, 10, aiptek->data, aiptek->data_dma);
error_out_nobuf:
kfree(aiptek);
error_out_noalloc:
return err;
} }
static void static void
......
This diff is collapsed.
...@@ -1510,7 +1510,7 @@ static void hid_free_buffers(struct usb_device *dev, struct hid_device *hid) ...@@ -1510,7 +1510,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) 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 usb_device *dev = interface_to_usbdev (intf);
struct hid_descriptor *hdesc; struct hid_descriptor *hdesc;
struct hid_device *hid; struct hid_device *hid;
......
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
#include <linux/module.h> #include <linux/module.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/usb.h> #include <linux/usb.h>
#include <asm/unaligned.h>
#include <asm/byteorder.h>
/* /*
* Version Information * Version Information
...@@ -65,8 +67,8 @@ static void kbtab_irq(struct urb *urb, struct pt_regs *regs) ...@@ -65,8 +67,8 @@ static void kbtab_irq(struct urb *urb, struct pt_regs *regs)
goto exit; goto exit;
} }
kbtab->x = (data[2] << 8) + data[1]; kbtab->x = le16_to_cpu(get_unaligned((u16 *) &data[1]));
kbtab->y = (data[4] << 8) + data[3]; kbtab->y = le16_to_cpu(get_unaligned((u16 *) &data[3]));
kbtab->pressure = (data[5]); kbtab->pressure = (data[5]);
...@@ -74,12 +76,15 @@ static void kbtab_irq(struct urb *urb, struct pt_regs *regs) ...@@ -74,12 +76,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_X, kbtab->x);
input_report_abs(dev, ABS_Y, kbtab->y); 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_TOUCH , data[0] & 0x01);*/
input_report_key(dev, BTN_RIGHT, data[0] & 0x02); 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); input_sync(dev);
...@@ -105,8 +110,10 @@ static int kbtab_open(struct input_dev *dev) ...@@ -105,8 +110,10 @@ static int kbtab_open(struct input_dev *dev)
return 0; return 0;
kbtab->irq->dev = kbtab->usbdev; kbtab->irq->dev = kbtab->usbdev;
if (usb_submit_urb(kbtab->irq, GFP_KERNEL)) if (usb_submit_urb(kbtab->irq, GFP_KERNEL)) {
kbtab->open--;
return -EIO; return -EIO;
}
return 0; return 0;
} }
...@@ -130,7 +137,7 @@ static int kbtab_probe(struct usb_interface *intf, const struct usb_device_id *i ...@@ -130,7 +137,7 @@ static int kbtab_probe(struct usb_interface *intf, const struct usb_device_id *i
return -ENOMEM; return -ENOMEM;
memset(kbtab, 0, sizeof(struct kbtab)); memset(kbtab, 0, sizeof(struct kbtab));
kbtab->data = usb_buffer_alloc(dev, 8, SLAB_ATOMIC, &kbtab->data_dma); kbtab->data = usb_buffer_alloc(dev, 8, GFP_KERNEL, &kbtab->data_dma);
if (!kbtab->data) { if (!kbtab->data) {
kfree(kbtab); kfree(kbtab);
return -ENOMEM; return -ENOMEM;
......
This diff is collapsed.
...@@ -200,6 +200,7 @@ static int hid_pid_upload_effect(struct input_dev *dev, ...@@ -200,6 +200,7 @@ static int hid_pid_upload_effect(struct input_dev *dev,
break; break;
if ( id == FF_EFFECTS_MAX) { if ( id == FF_EFFECTS_MAX) {
spin_unlock_irqrestore(&pid_private->lock,flags);
// TEMP - We need to get ff_effects_max correctly first: || id >= dev->ff_effects_max) { // TEMP - We need to get ff_effects_max correctly first: || id >= dev->ff_effects_max) {
dev_dbg(&pid_private->hid->dev->dev, "Not enough device memory\n"); dev_dbg(&pid_private->hid->dev->dev, "Not enough device memory\n");
return -ENOMEM; return -ENOMEM;
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -4,7 +4,6 @@ ...@@ -4,7 +4,6 @@
# #
obj-$(CONFIG_USB_AUERSWALD) += auerswald.o obj-$(CONFIG_USB_AUERSWALD) += auerswald.o
obj-$(CONFIG_USB_BRLVGER) += brlvger.o
obj-$(CONFIG_USB_EMI62) += emi62.o obj-$(CONFIG_USB_EMI62) += emi62.o
obj-$(CONFIG_USB_EMI26) += emi26.o obj-$(CONFIG_USB_EMI26) += emi26.o
obj-$(CONFIG_USB_LCD) += usblcd.o obj-$(CONFIG_USB_LCD) += usblcd.o
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
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