--- /dev/null | 1421 ----------------------------- CREDITS | 10 Documentation/DocBook/gadget.tmpl | 1 Documentation/usb/error-codes.txt | 4 Documentation/usb/mtouchusb.txt | 85 + MAINTAINERS | 15 drivers/char/watchdog/pcwd_usb.c | 2 drivers/input/joystick/iforce/iforce-usb.c | 2 drivers/isdn/hisax/hfc_usb.c | 29 drivers/usb/Kconfig | 44 drivers/usb/Makefile | 6 drivers/usb/class/audio.c | 157 +-- drivers/usb/class/bluetty.c | 2 drivers/usb/class/cdc-acm.c | 6 drivers/usb/class/usb-midi.c | 93 - drivers/usb/class/usblp.c | 16 drivers/usb/core/buffer.c | 16 drivers/usb/core/config.c | 9 drivers/usb/core/devio.c | 21 drivers/usb/core/driverfs.c | 8 drivers/usb/core/hcd-pci.c | 4 drivers/usb/core/hcd.c | 4 drivers/usb/core/hub.c | 12 drivers/usb/core/message.c | 81 + drivers/usb/core/urb.c | 65 + drivers/usb/core/usb.c | 42 drivers/usb/gadget/Kconfig | 19 drivers/usb/gadget/Makefile | 4 drivers/usb/gadget/config.c | 116 ++ drivers/usb/gadget/ether.c | 151 +-- drivers/usb/gadget/net2280.c | 5 drivers/usb/gadget/usbstring.c | 92 + drivers/usb/gadget/zero.c | 193 +-- drivers/usb/host/Kconfig | 9 drivers/usb/host/ehci-dbg.c | 6 drivers/usb/host/ehci-hcd.c | 8 drivers/usb/host/ehci-sched.c | 523 +++++++++- drivers/usb/host/ehci.h | 14 drivers/usb/host/uhci-hcd.c | 91 - drivers/usb/host/uhci-hcd.h | 3 drivers/usb/image/hpusbscsi.c | 2 drivers/usb/image/mdc800.c | 11 drivers/usb/image/microtek.c | 21 drivers/usb/input/Kconfig | 26 drivers/usb/input/Makefile | 6 drivers/usb/input/aiptek.c | 57 - drivers/usb/input/ati_remote.c | 851 +++++++++++++++++ drivers/usb/input/hid-core.c | 2 drivers/usb/input/kbtab.c | 21 drivers/usb/input/mtouchusb.c | 391 +++++++ drivers/usb/input/pid.c | 1 drivers/usb/input/usbkbd.c | 2 drivers/usb/input/usbmouse.c | 2 drivers/usb/input/wacom.c | 22 drivers/usb/misc/Kconfig | 11 drivers/usb/misc/Makefile | 1 drivers/usb/misc/usbtest.c | 62 - drivers/usb/net/Kconfig | 8 drivers/usb/net/pegasus.h | 8 drivers/usb/net/usbnet.c | 35 drivers/usb/serial/ftdi_sio.c | 3 drivers/usb/serial/ftdi_sio.h | 2 drivers/usb/serial/kl5kusb105.c | 5 drivers/usb/serial/pl2303.c | 8 drivers/usb/serial/usb-serial.c | 2 drivers/usb/serial/visor.c | 3 drivers/usb/serial/visor.h | 1 drivers/usb/storage/Kconfig | 2 drivers/usb/storage/scsiglue.c | 14 drivers/usb/storage/transport.c | 22 drivers/usb/storage/unusual_devs.h | 45 drivers/usb/storage/usb.c | 13 drivers/usb/storage/usb.h | 1 include/linux/usb.h | 105 +- include/linux/usb_gadget.h | 16 75 files changed, 2923 insertions(+), 2248 deletions(-) diff -puN CREDITS~bk-usb CREDITS --- 25/CREDITS~bk-usb 2004-03-10 21:44:00.000000000 -0800 +++ 25-akpm/CREDITS 2004-03-10 21:44:00.000000000 -0800 @@ -673,11 +673,6 @@ S: Northampton S: NN1 3QT S: United Kingdom -N: Stephane Dalton -E: sdalton@videotron.ca -D: Tieman Voyager USB Braille display driver. -S: Québec, Canada - N: Uwe Dannowski E: Uwe.Dannowski@ira.uka.de W: http://i30www.ira.uka.de/~dannowsk/ @@ -797,11 +792,6 @@ E: cort@fsmlabs.com W: http://www.fsmlabs.com/linuxppcbk.html D: PowerPC -N: Stéphane Doyon -E: s.doyon@videotron.ca -D: Tieman Voyager USB Braille display driver. -S: Québec, Canada - N: Oleg Drokin E: green@ccssu.crimea.ua W: http://www.ccssu.crimea.ua/~green diff -puN Documentation/DocBook/gadget.tmpl~bk-usb Documentation/DocBook/gadget.tmpl --- 25/Documentation/DocBook/gadget.tmpl~bk-usb 2004-03-10 21:44:00.000000000 -0800 +++ 25-akpm/Documentation/DocBook/gadget.tmpl 2004-03-10 21:44:00.000000000 -0800 @@ -454,6 +454,7 @@ but some optional utilities are provided !Edrivers/usb/gadget/usbstring.c +!Edrivers/usb/gadget/config.c diff -puN -L Documentation/usb/brlvger.txt Documentation/usb/brlvger.txt~bk-usb /dev/null --- 25/Documentation/usb/brlvger.txt +++ /dev/null 2002-08-30 16:31:37.000000000 -0700 @@ -1,36 +0,0 @@ -Kernel Driver for the Tieman Voyager Braille Display (USB) - -Authors: -Stéphane Dalton -Stéphane Doyon - -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 who got this whole -project started and beta-tested all our early buggy attempts. diff -puN Documentation/usb/error-codes.txt~bk-usb Documentation/usb/error-codes.txt --- 25/Documentation/usb/error-codes.txt~bk-usb 2004-03-10 21:44:00.000000000 -0800 +++ 25-akpm/Documentation/usb/error-codes.txt 2004-03-10 21:44:00.000000000 -0800 @@ -70,7 +70,9 @@ one or more packets could finish before (That is, if drivers see this it's a bug.) -EPROTO (*) a) bitstuff error - b) unknown USB error + b) no response packet received within the + prescribed bus turn-around time + c) unknown USB error -EILSEQ (*) CRC mismatch diff -puN /dev/null Documentation/usb/mtouchusb.txt --- /dev/null 2002-08-30 16:31:37.000000000 -0700 +++ 25-akpm/Documentation/usb/mtouchusb.txt 2004-03-10 21:44:00.000000000 -0800 @@ -0,0 +1,85 @@ +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/ + diff -puN -L Documentation/usb/scanner.txt Documentation/usb/scanner.txt~bk-usb /dev/null --- 25/Documentation/usb/scanner.txt +++ /dev/null 2002-08-30 16:31:37.000000000 -0700 @@ -1,336 +0,0 @@ -Copyright (C) 1999, 2000 David E. Nelson -Updated 2003 by Henning Meier-Geinitz - - -OVERVIEW - -This README addresses issues regarding how to configure the kernel to access a -USB scanner. Although the driver was originally conceived for USB HP -scanners, it's general enough so that it can be used with most other USB -scanners. Also, one can pass the USB Vendor and Product IDs using module -parameters for unknown scanners. - -There are two drivers for SCSI-over-USB scanners: -* The "hpusbscsi" module for Hewlett-Packard 53xx series, Hewlett-Packard 7400, - Minolta Scan Dual II, Minolta Elite II -* The "microtek" module for the Microtek Scanmaker X6 - -In addition to the kernel driver, user-space tools like SANE are necessary to -actually use the scanner. SANE ("Scanner Access Now Easy") provides drivers -for a variety of USB scanners. See the appropriate SANE man page for details, -e.g. man sane-usb and man sane-hp (for HP scanners). - -NOTE: Just because a product is detected by this driver does not mean that -applications exist that support the product. It's in the hopes that this will -allow developers a means to produce applications that will support the listed -USB products. - - -ADDITIONAL INFORMATION - -http://www.linux-usb.org/ (General information, mailing lists, links) -http://www.mostang.com/sane/ (SANE user-space tools) -http://www.meier-geinitz.de/kernel/ (USB scanner driver information and patches) - - -REQUIREMENTS - -A host with a USB port. Ideally, either a UHCI (Intel), OHCI (Compaq and -others) or EHCI hardware should work. - -Using "make menuconfig" or your preferred method for configuring the kernel, -select "Support for USB", "OHCI HCD/UHCI HCD/EHCI HCD" depending on your -hardware, "USB Scanner support", and "USB device filesystem". Compile and -install the modules (you may need to execute "depmod -a" to update the module -dependencies). If any of the USB sections were compiled into the kernel, a -reboot is necessary. NOTE: Updating the boot disk with "lilo" may also be -required. Testing was performed only as modules, YMMV. - -Up to 16 scanners can be connected/used simultaneously. If devfs support is -enabled, see next section. Otherwise, the device files must be created -manually if they don't exist yet, either by MAKEDEV or mknod. - -MAKEDEV method: - cd /dev - MAKEDEV usb - Check that the device files "/dev/usb/scanner0" - "/dev/usb/scanner15" have - been created. - -mknod method: - mknod /dev/usb/scanner0 c 180 48 - mknod /dev/usb/scanner1 c 180 49 - . - . - mknod /dev/usb/scanner15 c 180 63 - -Set appropriate permissions for /dev/usb/scanner[0-15] (don't forget -about group and world permissions). Both read and write permissions -are required for proper operation. For example: - chmod 666 /dev/usb/scanner0 - -Load the appropriate modules (if compiled as modules): - - modprobe ohci-hcd (or uhci-hcd, ehci-hcd) - modprobe scanner - - -DEVFS - -The later versions of the Linux kernel (2.4.8'ish) included a dynamic -device filesystem call "devfs". With devfs, there is no need to -create the device files as explained above; instead, they are -dynamically created for you. For USB Scanner, the device is created -in /dev/usb/scannerX where X can range from 0 to 15 depending on the -number of scanners connected to the system. - -To see if you have devfs, issue the command "cat /proc/filesytems". -If devfs is listed you should be ready to go. You should also have a -process running called "devfsd". In order to make sure, issue the -command "ps aux | grep '[d]evfsd'". - - -CONCLUSION - -That's it. SANE should now be able to access the device. To make sure the -device was detected, use "cat /proc/bus/usb/devices". Your scanner should be -listed and the line starting with "I:" should look similar to this example: - - I: If#= 0 Alt= 0 #EPs= 2 Cls=ff(vend.) Sub=ff Prot=ff Driver=usbscanner - -The important part is "Driver=usbscanner". If it reads "Driver=(none)", the -USB scanner driver didn't recognize the scanner. Have a look at the MODULE -PARAMETERS section for what to do in this case. - -For more details on the format of "/proc/bus/usb/devices" see -Documentation/usb/proc_usb_info.txt. - - -MESSAGES - -usb_control/bulk_msg: timeout -- On occasions this message will appear -in "/var/adm/messages", on the console, or both depending on how -your system is configured. This is a side effect that scanners are -sometimes very slow at warming up and/or initializing. In most cases, -however, only several of these messages should appear and is generally -considered to be normal. - -excessive NAK's received -- This message should be considered abnormal -and generally indicates that the USB system is unable to communicate -with the scanner for some particular reason. - -probe_scanner: Undetected endpoint -- The USB Scanner driver is fairly -general when it comes to communicating to scanners. Unfortunately, -some vendors have designed their scanners in one way or another that -this driver doesn't account for. - -probe_scanner: Endpoint determination failed -- This means that the -driver is unable to detect a supported configuration for means to -communicate with the scanner. See also "probe_scanner: Undetected -endpoint". - -funky result -- Most of the time the data flow between the computer -and the scanner goes smoothly. However, due to whatever reason, -whether it be solar flares or stray neutrons, sometimes the -communications don't work as expected. The driver tries to handle -most types of errors but not all. When this message is seen, -something weird happened. Please contact the mailing list (see -CONTACT section for details). - - -MODULE PARAMETERS - -If you have a device that you wish to experiment with or try using -this driver with, but the Vendor and Product IDs are not coded in, -don't despair. If the driver was compiled as a module, you can pass -options to the driver. Simply add - - options scanner vendor=0x#### product=0x**** - -to the /etc/modprobe.conf file replacing the #'s and the *'s with the -correct IDs. The IDs can be retrieved from the messages file or -using "cat /proc/bus/usb/devices". - -If the default timeout is too low, i.e. there are frequent "timeout" messages, -you may want to increase the timeout manually by using the parameter -"read_timeout". The time is given in seconds. This is an example for -modprobe.conf with a timeout of 60 seconds: - - options scanner read_timeout=60 - -If the "scanner" module is already loaded into memory, it must be reloaded for -the module parameters to take effect. In essence, "rmmod scanner; modprobe -scanner" must be performed. - - -BUGS - -Just look at the list of fixes in the source files. - - -CONTACT - -For asking about problems and fixes, use the linux-usb-users mailing list. For -patches, linux-usb-devel should be used. Information on both lists can be -found on http://www.linux-usb.org/. - - -CHANGES - -- Amended for linux-2.5.54 -- Added information about read_timeout -- Added more details about /proc/bus/usb/devices -- Added/updated links -- Added pointers two "special" scanner drivers -- Reordering, spell-checking, formatting -- Used /dev/usb/scanner[0-15] instead of /dev/usbscanner[0-15] -- Removed some basic USB configuration stuff -- Added EHCI -- Removed some more references to HP -- Amended for linux-2.4.12 -- Updated devfs support -- Amended for linux-2.3.99-pre6-3 -- Appended hp_scan.c to end of this README -- Removed most references to HP -- Updated uhci/ohci host controller info -- Updated support for multiple scanner support -- Updated supported scanners list -- Updated usbdevfs info -- Spellcheck - - -HP TEST PROGRAM - -There is a small test program (hp_scan.c -- appended below) that can -be used to test the scanner device if it's an HP scanner that supports -SCL (Scanner Control Language). Known HP scanner that support SCL are -the 4100, 5200, 6200, the 6300 -- note that the 4200 is *not* -supported since it does not understand SCL; it's also strongly -suspected that the 3300 and the PhotoSmart S20 are not SCL compliant. -Hp_scan.c's purpose is to test the driver without having to -retrieve/configure SANE. Hp_scan.c will scan the entire bed and put -the output into a file called "out.dat" in the current directory. The -data in the file is raw data so it's not very useful for imaging. - ---------------- snip -- hp_scan.c -- snip --------------- -/* - -This is a really crude attempt at writing a short test program. It's -mostly only to be used to test connectivity with USB HP scanners that -understand SCL. Currently, the supported models are 4100C, 5200C, -6200C, and the 6300C. Note that the 4200C is *NOT* acceptable. - -Copyright (C) David E. Nelson , 1999 - -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. - -*/ - -#include -#include -#include -#include -#include - -/* - Gray Output produces about a 8945400 byte file. - Color Output produces a 26836200 byte file. - - To compile: gcc -o hp_scan hp_scan.c -*/ - -// #define COLOR /* Undef to scan GrayScale */ - -int send_cmd(int, const char *, int); -int read_cmd(int, char *, int); - -int -main(void) { - - ssize_t cnt = 0, total_cnt = 0; - - FILE *fpout; - - int fp; - int data_size = 32768; - - char *data; - - static char reset_cmd[] = {'\x1b','E'}; - -#ifdef COLOR - static char data_type_cmd[] = {'\x1b','*','a','5','T'}; /* Color */ - static char data_width_cmd[] = {'\x1b','*','a','2','4','G'}; /* 24 Bit Color */ -#else - static char data_type_cmd[] = {'\x1b','*','a','4','T'}; /* Gray */ - static char data_width_cmd[] = {'\x1b','*','a','8','G'}; /* 8 Bit Gray */ -#endif - - static char query_cmd[] = {'\x1b', '*', 's', '2', '5', '7', 'E'}; - static char start_scan_cmd[] = {'\x1b','*','f','0','S'}; - - if(!(data=malloc(data_size))) { - perror("malloc failed"); - exit (1); - } - - if((fp=open("/dev/usb/scanner0", O_RDWR)) < 0) { - perror("Unable to open scanner device"); - exit (1); - } - - if((fpout=fopen("out.dat", "w+")) == NULL) { - perror("Unable to open output file"); - exit(1); - } - - send_cmd(fp, reset_cmd, sizeof(reset_cmd)); - send_cmd(fp, data_type_cmd, sizeof(data_type_cmd)); - send_cmd(fp, data_width_cmd, sizeof(data_width_cmd)); - send_cmd(fp, start_scan_cmd, sizeof(start_scan_cmd)); - - while ((cnt = read(fp, data, data_size)) > 0) { - printf("Read: %u\n", cnt); - if(fwrite(data, sizeof(char), cnt, fpout) < 0) { - perror("Write to output file failed"); - exit (1); - } - total_cnt += cnt; - } - if (cnt < 0) { - perror("Read from scanner failed"); - exit (1); - } - - printf("\nRead %lu bytes.\n", total_cnt); - - send_cmd(fp, reset_cmd, sizeof(reset_cmd)); - - close(fp); - fclose(fpout); - return (0); -} - -int -send_cmd(int fp, const char * cmd, int length) { - - int result; - int x; - - if((result = write(fp, cmd, length)) != length) { - printf ("Write warning: %d bytes requested, %d written\n"); - } else if (result < 0) { - perror ("send_cmd failure"); - exit (1); - } - return (result); -} - -int -read_cmd(int fp, char * response, int length) { - - return read(fp, response, length); - -} diff -puN drivers/char/watchdog/pcwd_usb.c~bk-usb drivers/char/watchdog/pcwd_usb.c --- 25/drivers/char/watchdog/pcwd_usb.c~bk-usb 2004-03-10 21:44:00.000000000 -0800 +++ 25-akpm/drivers/char/watchdog/pcwd_usb.c 2004-03-10 21:44:00.000000000 -0800 @@ -589,7 +589,7 @@ static int usb_pcwd_probe(struct usb_int } /* 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 */ if (!(iface_desc->desc.bInterfaceClass == USB_CLASS_HID)) { diff -puN drivers/input/joystick/iforce/iforce-usb.c~bk-usb drivers/input/joystick/iforce/iforce-usb.c --- 25/drivers/input/joystick/iforce/iforce-usb.c~bk-usb 2004-03-10 21:44:00.000000000 -0800 +++ 25-akpm/drivers/input/joystick/iforce/iforce-usb.c 2004-03-10 21:44:00.000000000 -0800 @@ -135,7 +135,7 @@ static int iforce_usb_probe(struct usb_i struct usb_endpoint_descriptor *epirq, *epout; struct iforce *iforce; - interface = &intf->altsetting[intf->act_altsetting]; + interface = intf->cur_altsetting; epirq = &interface->endpoint[0].desc; epout = &interface->endpoint[1].desc; diff -puN drivers/isdn/hisax/hfc_usb.c~bk-usb drivers/isdn/hisax/hfc_usb.c --- 25/drivers/isdn/hisax/hfc_usb.c~bk-usb 2004-03-10 21:44:00.000000000 -0800 +++ 25-akpm/drivers/isdn/hisax/hfc_usb.c 2004-03-10 21:44:00.000000000 -0800 @@ -1349,9 +1349,11 @@ static int __devinit hfc_usb_probe(struc { struct usb_device *dev= interface_to_usbdev(intf); 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; - 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; // usb_show_device(dev); @@ -1366,7 +1368,7 @@ static int __devinit hfc_usb_probe(struc #ifdef VERBOSE_USB_DEBUG 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 if (vend_idx != 0xffff) { @@ -1374,14 +1376,15 @@ static int __devinit hfc_usb_probe(struc printk(KERN_INFO "HFC-USB: found vendor idx:%d name:%s\n",vend_idx,vdata[vend_idx].vend_name); #endif /* if vendor and product ID is OK, start probing a matching alternate setting ... */ - probe_alt_setting = 0; + alt_idx = 0; small_match=0xffff; // default settings iso_packet_size=16; packet_size=64; - while(probe_alt_setting < intf->num_altsetting) { - iface = intf->altsetting + probe_alt_setting; + while (alt_idx < intf->num_altsetting) { + iface = intf->altsetting + alt_idx; + probe_alt_setting = iface->desc.bAlternateSetting; cfg_used=0; #ifdef VERBOSE_USB_DEBUG @@ -1395,7 +1398,7 @@ static int __devinit hfc_usb_probe(struc #ifdef VERBOSE_USB_DEBUG 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 // copy table memcpy(cmptbl,vcf,16*sizeof(int)); @@ -1448,6 +1451,7 @@ static int __devinit hfc_usb_probe(struc if (cfg_used < small_match) { small_match = cfg_used; alt_used = probe_alt_setting; + iface_used = iface; } #ifdef VERBOSE_USB_DEBUG printk(KERN_INFO "HFC-USB: small_match=%x %x\n", small_match, alt_used); @@ -1457,15 +1461,14 @@ static int __devinit hfc_usb_probe(struc cfg_used++; } - probe_alt_setting++; - } /* (probe_alt_setting < intf->num_altsetting) */ + alt_idx++; + } /* (alt_idx < intf->num_altsetting) */ #ifdef VERBOSE_USB_DEBUG printk(KERN_INFO "HFC-USB: final small_match=%x alt_used=%x\n",small_match, alt_used); #endif // yiipiee, we found a valid config if (small_match != 0xffff) { - intf->act_altsetting = alt_used; - iface = intf->altsetting + intf->act_altsetting; + iface = iface_used; if (!(context = kmalloc(sizeof(hfcusb_data), GFP_KERNEL))) return(-ENOMEM); /* got no mem */ @@ -1542,8 +1545,8 @@ static int __devinit hfc_usb_probe(struc // now share our luck context->dev = dev; /* save device */ - context->if_used = intf->altsetting->desc.bInterfaceNumber; /* save used interface */ - context->alt_used = intf->act_altsetting; /* and alternate config */ + context->if_used = ifnum; /* save used interface */ + context->alt_used = alt_used; /* and alternate config */ context->ctrl_paksize = dev->descriptor.bMaxPacketSize0; /* control size */ context->cfg_used=vcf[16]; // store used config context->vend_idx=vend_idx; // store found vendor diff -puN drivers/usb/class/audio.c~bk-usb drivers/usb/class/audio.c --- 25/drivers/usb/class/audio.c~bk-usb 2004-03-10 21:44:00.000000000 -0800 +++ 25-akpm/drivers/usb/class/audio.c 2004-03-10 21:44:00.000000000 -0800 @@ -3,7 +3,7 @@ /* * audio.c -- USB Audio Class driver * - * Copyright (C) 1999, 2000, 2001 + * Copyright (C) 1999, 2000, 2001, 2003, 2004 * Alan Cox (alan@lxorguk.ukuu.org.uk) * Thomas Sailer (sailer@ife.ee.ethz.ch) * @@ -101,6 +101,11 @@ * Fix SNDCTL_DSP_STEREO API violation * 2003-04-08: Oliver Neukum (oliver@neukum.name): * Setting a configuration is done by usbcore and must not be overridden + * 2004-02-27: Workaround for broken synch descriptors + * 2004-03-07: Alan Stern + * Add usb_ifnum_to_if() and usb_altnum_to_altsetting() support. + * Use the in-memory descriptors instead of reading them from the device. + * */ /* @@ -141,8 +146,8 @@ * * How does the parsing work? First, all interfaces are searched * for an AudioControl class interface. If found, the config descriptor - * that belongs to the current configuration is fetched from the device. - * Then the HEADER descriptor is fetched. It contains a list of + * that belongs to the current configuration is searched and + * the HEADER descriptor is found. It contains a list of * all AudioStreaming and MIDIStreaming devices. This list is then walked, * and all AudioStreaming interfaces are classified into input and output * interfaces (according to the endpoint0 direction in altsetting1) (MIDIStreaming @@ -1512,7 +1517,6 @@ static int find_format(struct audioforma static int set_format_in(struct usb_audiodev *as) { struct usb_device *dev = as->state->usbdev; - struct usb_host_config *config = dev->actconfig; struct usb_host_interface *alts; struct usb_interface *iface; struct usbin *u = &as->usbin; @@ -1522,9 +1526,9 @@ static int set_format_in(struct usb_audi unsigned char data[3]; int fmtnr, ret; - if (u->interface < 0 || u->interface >= config->desc.bNumInterfaces) + iface = usb_ifnum_to_if(dev, u->interface); + if (!iface) return 0; - iface = config->interface[u->interface]; fmtnr = find_format(as->fmtin, as->numfmtin, d->format, d->srate); if (fmtnr < 0) { @@ -1533,7 +1537,7 @@ static int set_format_in(struct usb_audi } fmt = as->fmtin + fmtnr; - alts = &iface->altsetting[fmt->altsetting]; + alts = usb_altnum_to_altsetting(iface, fmt->altsetting); u->format = fmt->format; u->datapipe = usb_rcvisocpipe(dev, alts->endpoint[0].desc.bEndpointAddress & 0xf); u->syncpipe = u->syncinterval = 0; @@ -1542,18 +1546,20 @@ static int set_format_in(struct usb_audi alts->endpoint[1].desc.bmAttributes != 0x01 || alts->endpoint[1].desc.bSynchAddress != 0 || alts->endpoint[1].desc.bEndpointAddress != (alts->endpoint[0].desc.bSynchAddress & 0x7f)) { - printk(KERN_ERR "usbaudio: device %d interface %d altsetting %d invalid synch pipe\n", + printk(KERN_WARNING "usbaudio: device %d interface %d altsetting %d claims adaptive in " + "but has invalid synch pipe; treating as asynchronous in\n", dev->devnum, u->interface, fmt->altsetting); - return -1; + } else { + u->syncpipe = usb_sndisocpipe(dev, alts->endpoint[1].desc.bEndpointAddress & 0xf); + u->syncinterval = alts->endpoint[1].desc.bRefresh; } - u->syncpipe = usb_sndisocpipe(dev, alts->endpoint[1].desc.bEndpointAddress & 0xf); - u->syncinterval = alts->endpoint[1].desc.bRefresh; } if (d->srate < fmt->sratelo) d->srate = fmt->sratelo; if (d->srate > fmt->sratehi) d->srate = fmt->sratehi; - dprintk((KERN_DEBUG "usbaudio: set_format_in: usb_set_interface %u %u\n", alts->desc.bInterfaceNumber, fmt->altsetting)); + dprintk((KERN_DEBUG "usbaudio: set_format_in: usb_set_interface %u %u\n", + u->interface, fmt->altsetting)); if (usb_set_interface(dev, alts->desc.bInterfaceNumber, fmt->altsetting) < 0) { printk(KERN_WARNING "usbaudio: usb_set_interface failed, device %d interface %d altsetting %d\n", dev->devnum, u->interface, fmt->altsetting); @@ -1600,7 +1606,6 @@ static int set_format_in(struct usb_audi static int set_format_out(struct usb_audiodev *as) { struct usb_device *dev = as->state->usbdev; - struct usb_host_config *config = dev->actconfig; struct usb_host_interface *alts; struct usb_interface *iface; struct usbout *u = &as->usbout; @@ -1610,9 +1615,9 @@ static int set_format_out(struct usb_aud unsigned char data[3]; int fmtnr, ret; - if (u->interface < 0 || u->interface >= config->desc.bNumInterfaces) + iface = usb_ifnum_to_if(dev, u->interface); + if (!iface) return 0; - iface = config->interface[u->interface]; fmtnr = find_format(as->fmtout, as->numfmtout, d->format, d->srate); if (fmtnr < 0) { @@ -1622,7 +1627,7 @@ static int set_format_out(struct usb_aud fmt = as->fmtout + fmtnr; u->format = fmt->format; - alts = &iface->altsetting[fmt->altsetting]; + alts = usb_altnum_to_altsetting(iface, fmt->altsetting); u->datapipe = usb_sndisocpipe(dev, alts->endpoint[0].desc.bEndpointAddress & 0xf); u->syncpipe = u->syncinterval = 0; if ((alts->endpoint[0].desc.bmAttributes & 0x0c) == 0x04) { @@ -1637,18 +1642,20 @@ static int set_format_out(struct usb_aud alts->endpoint[1].desc.bmAttributes != 0x01 || alts->endpoint[1].desc.bSynchAddress != 0 || alts->endpoint[1].desc.bEndpointAddress != (alts->endpoint[0].desc.bSynchAddress | 0x80)) { - printk(KERN_ERR "usbaudio: device %d interface %d altsetting %d invalid synch pipe\n", + printk(KERN_WARNING "usbaudio: device %d interface %d altsetting %d claims asynch out " + "but has invalid synch pipe; treating as adaptive out\n", dev->devnum, u->interface, fmt->altsetting); - return -1; + } else { + u->syncpipe = usb_rcvisocpipe(dev, alts->endpoint[1].desc.bEndpointAddress & 0xf); + u->syncinterval = alts->endpoint[1].desc.bRefresh; } - u->syncpipe = usb_rcvisocpipe(dev, alts->endpoint[1].desc.bEndpointAddress & 0xf); - u->syncinterval = alts->endpoint[1].desc.bRefresh; } if (d->srate < fmt->sratelo) d->srate = fmt->sratelo; if (d->srate > fmt->sratehi) d->srate = fmt->sratehi; - dprintk((KERN_DEBUG "usbaudio: set_format_out: usb_set_interface %u %u\n", alts->desc.bInterfaceNumber, fmt->altsetting)); + dprintk((KERN_DEBUG "usbaudio: set_format_out: usb_set_interface %u %u\n", + u->interface, fmt->altsetting)); if (usb_set_interface(dev, u->interface, fmt->altsetting) < 0) { printk(KERN_WARNING "usbaudio: usb_set_interface failed, device %d interface %d altsetting %d\n", dev->devnum, u->interface, fmt->altsetting); @@ -2697,7 +2704,6 @@ static int usb_audio_release(struct inod struct usb_audiodev *as = (struct usb_audiodev *)file->private_data; struct usb_audio_state *s; struct usb_device *dev; - struct usb_interface *iface; lock_kernel(); s = as->state; @@ -2707,19 +2713,15 @@ static int usb_audio_release(struct inod down(&open_sem); if (file->f_mode & FMODE_WRITE) { usbout_stop(as); - if (dev && as->usbout.interface >= 0) { - iface = dev->actconfig->interface[as->usbout.interface]; - usb_set_interface(dev, iface->altsetting->desc.bInterfaceNumber, 0); - } + if (dev && as->usbout.interface >= 0) + usb_set_interface(dev, as->usbout.interface, 0); dmabuf_release(&as->usbout.dma); usbout_release(as); } if (file->f_mode & FMODE_READ) { usbin_stop(as); - if (dev && as->usbin.interface >= 0) { - iface = dev->actconfig->interface[as->usbin.interface]; - usb_set_interface(dev, iface->altsetting->desc.bInterfaceNumber, 0); - } + if (dev && as->usbin.interface >= 0) + usb_set_interface(dev, as->usbin.interface, 0); dmabuf_release(&as->usbin.dma); usbin_release(as); } @@ -2824,12 +2826,11 @@ static void usb_audio_parsestreaming(str { struct usb_device *dev = s->usbdev; struct usb_audiodev *as; - struct usb_host_config *config = dev->actconfig; struct usb_host_interface *alts; struct usb_interface *iface; struct audioformat *fp; unsigned char *fmt, *csep; - unsigned int i, j, k, format; + unsigned int i, j, k, format, idx; if (!(as = kmalloc(sizeof(struct usb_audiodev), GFP_KERNEL))) return; @@ -2870,9 +2871,10 @@ static void usb_audio_parsestreaming(str /* search for input formats */ if (asifin >= 0) { as->usbin.flags = FLG_CONNECTED; - iface = config->interface[asifin]; - for (i = 0; i < iface->num_altsetting; i++) { - alts = &iface->altsetting[i]; + iface = usb_ifnum_to_if(dev, asifin); + for (idx = 0; idx < iface->num_altsetting; idx++) { + alts = &iface->altsetting[idx]; + i = alts->desc.bAlternateSetting; if (alts->desc.bInterfaceClass != USB_CLASS_AUDIO || alts->desc.bInterfaceSubClass != 2) continue; if (alts->desc.bNumEndpoints < 1) { @@ -2951,14 +2953,15 @@ static void usb_audio_parsestreaming(str /* search for output formats */ if (asifout >= 0) { as->usbout.flags = FLG_CONNECTED; - iface = config->interface[asifout]; - for (i = 0; i < iface->num_altsetting; i++) { - alts = &iface->altsetting[i]; + iface = usb_ifnum_to_if(dev, asifout); + for (idx = 0; idx < iface->num_altsetting; idx++) { + alts = &iface->altsetting[idx]; + i = alts->desc.bAlternateSetting; if (alts->desc.bInterfaceClass != USB_CLASS_AUDIO || alts->desc.bInterfaceSubClass != 2) continue; if (alts->desc.bNumEndpoints < 1) { /* altsetting 0 should never have iso EPs */ - if (alts->desc.bAlternateSetting != 0) + if (i != 0) printk(KERN_ERR "usbaudio: device %u interface %u altsetting %u does not have an endpoint\n", dev->devnum, asifout, i); continue; @@ -3655,8 +3658,8 @@ static void usb_audio_constructmixer(str static struct usb_audio_state *usb_audio_parsecontrol(struct usb_device *dev, unsigned char *buffer, unsigned int buflen, unsigned int ctrlif) { struct usb_audio_state *s; - struct usb_host_config *config = dev->actconfig; struct usb_interface *iface; + struct usb_host_interface *alt; unsigned char ifin[USB_MAXINTERFACES], ifout[USB_MAXINTERFACES]; unsigned char *p1; unsigned int i, j, k, numifin = 0, numifout = 0; @@ -3685,54 +3688,63 @@ static struct usb_audio_state *usb_audio dev->devnum, ctrlif); for (i = 0; i < p1[7]; i++) { j = p1[8+i]; - if (j >= config->desc.bNumInterfaces) { + iface = usb_ifnum_to_if(dev, j); + if (!iface) { printk(KERN_ERR "usbaudio: device %d audiocontrol interface %u interface %u does not exist\n", dev->devnum, ctrlif, j); continue; } - iface = config->interface[j]; - if (iface->altsetting[0].desc.bInterfaceClass != USB_CLASS_AUDIO) { - printk(KERN_ERR "usbaudio: device %d audiocontrol interface %u interface %u is not an AudioClass interface\n", - dev->devnum, ctrlif, j); + if (iface->num_altsetting == 1) { + printk(KERN_ERR "usbaudio: device %d audiocontrol interface %u has only 1 altsetting.\n", dev->devnum, ctrlif); continue; } - if (iface->altsetting[0].desc.bInterfaceSubClass == 3) { - printk(KERN_INFO "usbaudio: device %d audiocontrol interface %u interface %u MIDIStreaming not supported\n", + alt = usb_altnum_to_altsetting(iface, 0); + if (!alt) { + printk(KERN_ERR "usbaudio: device %d audiocontrol interface %u interface %u has no altsetting 0\n", dev->devnum, ctrlif, j); continue; } - if (iface->altsetting[0].desc.bInterfaceSubClass != 2) { - printk(KERN_ERR "usbaudio: device %d audiocontrol interface %u interface %u invalid AudioClass subtype\n", + if (alt->desc.bInterfaceClass != USB_CLASS_AUDIO) { + printk(KERN_ERR "usbaudio: device %d audiocontrol interface %u interface %u is not an AudioClass interface\n", dev->devnum, ctrlif, j); continue; } - if (iface->num_altsetting == 0) { - printk(KERN_ERR "usbaudio: device %d audiocontrol interface %u has no working interface.\n", dev->devnum, ctrlif); + if (alt->desc.bInterfaceSubClass == 3) { + printk(KERN_INFO "usbaudio: device %d audiocontrol interface %u interface %u MIDIStreaming not supported\n", + dev->devnum, ctrlif, j); continue; } - if (iface->num_altsetting == 1) { - printk(KERN_ERR "usbaudio: device %d audiocontrol interface %u has only 1 altsetting.\n", dev->devnum, ctrlif); + if (alt->desc.bInterfaceSubClass != 2) { + printk(KERN_ERR "usbaudio: device %d audiocontrol interface %u interface %u invalid AudioClass subtype\n", + dev->devnum, ctrlif, j); continue; } - if (iface->altsetting[0].desc.bNumEndpoints > 0) { + if (alt->desc.bNumEndpoints > 0) { /* Check all endpoints; should they all have a bandwidth of 0 ? */ - for (k = 0; k < iface->altsetting[0].desc.bNumEndpoints; k++) { - if (iface->altsetting[0].endpoint[k].desc.wMaxPacketSize > 0) { + for (k = 0; k < alt->desc.bNumEndpoints; k++) { + if (alt->endpoint[k].desc.wMaxPacketSize > 0) { printk(KERN_ERR "usbaudio: device %d audiocontrol interface %u endpoint %d does not have 0 bandwidth at alt[0]\n", dev->devnum, ctrlif, k); break; } } - if (k < iface->altsetting[0].desc.bNumEndpoints) + if (k < alt->desc.bNumEndpoints) continue; } - if (iface->altsetting[1].desc.bNumEndpoints < 1) { + + alt = usb_altnum_to_altsetting(iface, 1); + if (!alt) { + printk(KERN_ERR "usbaudio: device %d audiocontrol interface %u interface %u has no altsetting 1\n", + dev->devnum, ctrlif, j); + continue; + } + if (alt->desc.bNumEndpoints < 1) { printk(KERN_ERR "usbaudio: device %d audiocontrol interface %u interface %u has no endpoint\n", dev->devnum, ctrlif, j); continue; } /* note: this requires the data endpoint to be ep0 and the optional sync ep to be ep1, which seems to be the case */ - if (iface->altsetting[1].endpoint[0].desc.bEndpointAddress & USB_DIR_IN) { + if (alt->endpoint[0].desc.bEndpointAddress & USB_DIR_IN) { if (numifin < USB_MAXINTERFACES) { ifin[numifin++] = j; usb_driver_claim_interface(&usb_audio_driver, iface, (void *)-1); @@ -3779,12 +3791,9 @@ static int usb_audio_probe(struct usb_in const struct usb_device_id *id) { struct usb_device *dev = interface_to_usbdev (intf); - struct usb_host_config *config = dev->actconfig; struct usb_audio_state *s; unsigned char *buffer; - unsigned char buf[8]; - unsigned int i, buflen; - int ret; + unsigned int buflen; #if 0 printk(KERN_DEBUG "usbaudio: Probing if %i: IC %x, ISC %x\n", ifnum, @@ -3796,26 +3805,8 @@ static int usb_audio_probe(struct usb_in * audiocontrol interface found * find which configuration number is active */ - i = dev->actconfig - config; - - ret = usb_get_descriptor(dev, USB_DT_CONFIG, i, buf, 8); - if (ret < 0) { - printk(KERN_ERR "usbaudio: cannot get first 8 bytes of config descriptor %d of device %d (error %d)\n", i, dev->devnum, ret); - return -EIO; - } - if (buf[1] != USB_DT_CONFIG || buf[0] < 9) { - printk(KERN_ERR "usbaudio: invalid config descriptor %d of device %d\n", i, dev->devnum); - return -EIO; - } - buflen = buf[2] | (buf[3] << 8); - if (!(buffer = kmalloc(buflen, GFP_KERNEL))) - return -ENOMEM; - ret = usb_get_descriptor(dev, USB_DT_CONFIG, i, buffer, buflen); - if (ret < 0) { - kfree(buffer); - printk(KERN_ERR "usbaudio: cannot get config descriptor %d of device %d (error %d)\n", i, dev->devnum, ret); - return -EIO; - } + buffer = dev->rawdescriptors[dev->actconfig - dev->config]; + buflen = dev->actconfig->desc.wTotalLength; s = usb_audio_parsecontrol(dev, buffer, buflen, intf->altsetting->desc.bInterfaceNumber); if (s) { usb_set_intfdata (intf, s); diff -puN drivers/usb/class/bluetty.c~bk-usb drivers/usb/class/bluetty.c --- 25/drivers/usb/class/bluetty.c~bk-usb 2004-03-10 21:44:00.000000000 -0800 +++ 25-akpm/drivers/usb/class/bluetty.c 2004-03-10 21:44:01.000000000 -0800 @@ -1025,7 +1025,7 @@ static int usb_bluetooth_probe (struct u int num_bulk_in = 0; int num_bulk_out = 0; - interface = &intf->altsetting[0]; + interface = intf->cur_altsetting; control_out_endpoint = interface->desc.bInterfaceNumber; /* find the endpoints that we need */ diff -puN drivers/usb/class/cdc-acm.c~bk-usb drivers/usb/class/cdc-acm.c --- 25/drivers/usb/class/cdc-acm.c~bk-usb 2004-03-10 21:44:00.000000000 -0800 +++ 25-akpm/drivers/usb/class/cdc-acm.c 2004-03-10 21:44:01.000000000 -0800 @@ -595,12 +595,12 @@ static int acm_probe (struct usb_interfa * is there it's not for call management ... so use * the cdc union descriptor whenever there is one. */ - ifcom = intf->altsetting + 0; + ifcom = intf->cur_altsetting; if (intf == cfacm->interface[j]) { - ifdata = cfacm->interface[j + 1]->altsetting + 0; + ifdata = cfacm->interface[j + 1]->cur_altsetting; data = 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]; } else continue; diff -puN drivers/usb/class/usblp.c~bk-usb drivers/usb/class/usblp.c --- 25/drivers/usb/class/usblp.c~bk-usb 2004-03-10 21:44:00.000000000 -0800 +++ 25-akpm/drivers/usb/class/usblp.c 2004-03-10 21:44:01.000000000 -0800 @@ -133,6 +133,7 @@ struct usblp { wait_queue_head_t wait; /* Zzzzz ... */ int readcount; /* Counter for reads */ int ifnum; /* Interface number */ + struct usb_interface *intf; /* The interface */ /* Alternate-setting numbers and endpoints for each protocol * (7/1/{index=1,2,3}) that the device supports: */ struct { @@ -609,8 +610,10 @@ static ssize_t usblp_write(struct file * while (writecount < count) { if (!usblp->wcomplete) { barrier(); - if (file->f_flags & O_NONBLOCK) + if (file->f_flags & O_NONBLOCK) { + writecount += transfer_length; return writecount ? writecount : -EAGAIN; + } timeout = USBLP_WRITE_TIMEOUT; add_wait_queue(&usblp->wait, &wait); @@ -670,7 +673,8 @@ static ssize_t usblp_write(struct file * 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); return writecount ? writecount : -EFAULT; } @@ -837,7 +841,8 @@ static int usblp_probe(struct usb_interf usblp->dev = dev; init_MUTEX (&usblp->sem); 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); if (!usblp->writeurb) { @@ -973,7 +978,7 @@ static int usblp_select_alts(struct usbl struct usb_endpoint_descriptor *epd, *epwrite, *epread; int p, i, e; - if_alt = usblp->dev->actconfig->interface[usblp->ifnum]; + if_alt = usblp->intf; for (p = 0; p < USBLP_MAX_PROTOCOLS; p++) usblp->protocol[p].alt_setting = -1; @@ -1022,7 +1027,8 @@ static int usblp_select_alts(struct usbl 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].epread = epread; } diff -puN drivers/usb/class/usb-midi.c~bk-usb drivers/usb/class/usb-midi.c --- 25/drivers/usb/class/usb-midi.c~bk-usb 2004-03-10 21:44:00.000000000 -0800 +++ 25-akpm/drivers/usb/class/usb-midi.c 2004-03-10 21:44:01.000000000 -0800 @@ -39,9 +39,6 @@ #include #include -/** 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" /* ------------------------------------------------------------------------- */ @@ -1519,15 +1516,17 @@ static int on_bits( unsigned short v ) static int get_alt_setting( struct usb_device *d, int ifnum ) { int alts, alt=0; + struct usb_interface *iface; struct usb_host_interface *interface; struct usb_endpoint_descriptor *ep; int epin, epout; int i; - alts = d->actconfig->interface[ifnum]->num_altsetting; + iface = usb_ifnum_to_if( d, ifnum ); + alts = iface->num_altsetting; for ( alt=0 ; altactconfig->interface[ifnum]->altsetting[alt]; + interface = &iface->altsetting[alt]; epin = -1; epout = -1; @@ -1542,7 +1541,7 @@ static int get_alt_setting( struct usb_d epout = i; } if ( epin >= 0 && epout >= 0 ) { - return alt; + return interface->desc.bAlternateSetting; } } } @@ -1780,12 +1779,13 @@ static int alloc_usb_midi_device( struct * 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_midi_device *u; - unsigned char buf[USB_DT_CONFIG_SIZE], *buffer; + unsigned char *buffer; int bufSize; int i; int alts=-1; @@ -1795,13 +1795,13 @@ static int detect_yamaha_device( struct return -EINVAL; } - for ( i=0 ; i < c->interface[ifnum]->num_altsetting; i++ ) { - interface = c->interface[ifnum]->altsetting + i; + for ( i=0 ; i < iface->num_altsetting; i++ ) { + interface = iface->altsetting + i; if ( interface->desc.bInterfaceClass != 255 || interface->desc.bInterfaceSubClass != 0 ) continue; - alts = i; + alts = interface->desc.bAlternateSetting; } if ( alts == -1 ) { return -EINVAL; @@ -1810,30 +1810,11 @@ static int detect_yamaha_device( struct printk(KERN_INFO "usb-midi: Found YAMAHA USB-MIDI device on dev %04x:%04x, iface %d\n", d->descriptor.idVendor, d->descriptor.idProduct, ifnum); - ret = usb_get_descriptor( d, USB_DT_CONFIG, i, buf, USB_DT_CONFIG_SIZE ); - if ( ret < 0 ) { - printk(KERN_INFO "usb-midi: Could not get config (error=%d).\n", ret); - 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; - } + i = d->actconfig - d->config; + buffer = d->rawdescriptors[i]; + bufSize = d->actconfig->desc.wTotalLength; u = parse_descriptor( d, buffer, bufSize, ifnum, alts, 1); - kfree(buffer); if ( u == NULL ) { return -EINVAL; } @@ -1878,24 +1859,25 @@ static int detect_vendor_specific_device * Returns 0 on success, negative on failure. * 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_midi_device *u; - unsigned char buf[USB_DT_CONFIG_SIZE], *buffer; + unsigned char *buffer; int bufSize; int i; int alts=-1; int ret; - for ( i=0 ; i < c->interface[ifnum]->num_altsetting; i++ ) { - interface = c->interface[ifnum]->altsetting + i; + for ( i=0 ; i < iface->num_altsetting; i++ ) { + interface = iface->altsetting + i; if ( interface->desc.bInterfaceClass != USB_CLASS_AUDIO || interface->desc.bInterfaceSubClass != USB_SUBCLASS_MIDISTREAMING ) continue; - alts = i; + alts = interface->desc.bAlternateSetting; } if ( alts == -1 ) { return -EINVAL; @@ -1915,30 +1897,11 @@ static int detect_midi_subclass(struct u descriptor they modify or extend. */ - ret = usb_get_descriptor( d, USB_DT_CONFIG, i, buf, USB_DT_CONFIG_SIZE ); - if ( ret < 0 ) { - printk(KERN_INFO "usb-midi: Could not get config (error=%d).\n", ret); - 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; - } + i = d->actconfig - d->config; + buffer = d->rawdescriptors[i]; + bufSize = d->actconfig->desc.wTotalLength; u = parse_descriptor( d, buffer, bufSize, ifnum, alts, 0); - kfree(buffer); if ( u == NULL ) { return -EINVAL; } @@ -2002,7 +1965,7 @@ static int usb_midi_probe(struct usb_int { struct usb_midi_state *s; 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); if ( !s ) @@ -2018,9 +1981,9 @@ static int usb_midi_probe(struct usb_int if ( 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_yamaha_device( dev, ifnum, s) ) { + detect_yamaha_device( dev, intf, ifnum, s) ) { kfree(s); return -EIO; } diff -puN drivers/usb/core/buffer.c~bk-usb drivers/usb/core/buffer.c --- 25/drivers/usb/core/buffer.c~bk-usb 2004-03-10 21:44:00.000000000 -0800 +++ 25-akpm/drivers/usb/core/buffer.c 2004-03-10 21:44:01.000000000 -0800 @@ -51,8 +51,8 @@ static const size_t pool_max [HCD_BUFFER * @hcd: the bus whose buffer pools are to be initialized * Context: !in_interrupt() * - * Call this as part of initializing a host controller that uses the pci dma - * memory allocators. It initializes some pools of dma-consistent memory that + * Call this as part of initializing a host controller that uses the dma + * memory allocators. It initializes some pools of dma-coherent memory that * will be shared by all drivers using that controller, or returns a negative * errno value on error. * @@ -115,6 +115,12 @@ void *hcd_buffer_alloc ( struct usb_hcd *hcd = bus->hcpriv; 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++) { if (size <= pool_max [i]) return dma_pool_alloc (hcd->pool [i], mem_flags, dma); @@ -134,6 +140,12 @@ void hcd_buffer_free ( if (!addr) return; + + if (!bus->controller->dma_mask) { + kfree (addr); + return; + } + for (i = 0; i < HCD_BUFFER_POOLS; i++) { if (size <= pool_max [i]) { dma_pool_free (hcd->pool [i], addr, dma); diff -puN drivers/usb/core/config.c~bk-usb drivers/usb/core/config.c --- 25/drivers/usb/core/config.c~bk-usb 2004-03-10 21:44:00.000000000 -0800 +++ 25-akpm/drivers/usb/core/config.c 2004-03-10 21:44:01.000000000 -0800 @@ -72,13 +72,10 @@ static int usb_parse_endpoint(struct usb return buffer - buffer0; } -static void usb_release_intf(struct device *dev) +static void usb_free_intf(struct usb_interface *intf) { - struct usb_interface *intf; int j; - intf = to_usb_interface(dev); - if (intf->altsetting) { for (j = 0; j < intf->num_altsetting; j++) { struct usb_host_interface *as = &intf->altsetting[j]; @@ -235,8 +232,6 @@ int usb_parse_configuration(struct usb_h return -ENOMEM; } memset(interface, 0, sizeof(struct usb_interface)); - interface->dev.release = usb_release_intf; - device_initialize(&interface->dev); } /* Go through the descriptors, checking their length and counting the @@ -374,7 +369,7 @@ void usb_destroy_configuration(struct us struct usb_interface *ifp = cf->interface[i]; if (ifp) - put_device(&ifp->dev); + usb_free_intf(ifp); } } kfree(dev->config); diff -puN drivers/usb/core/devio.c~bk-usb drivers/usb/core/devio.c --- 25/drivers/usb/core/devio.c~bk-usb 2004-03-10 21:44:00.000000000 -0800 +++ 25-akpm/drivers/usb/core/devio.c 2004-03-10 21:44:01.000000000 -0800 @@ -430,19 +430,14 @@ static int findintfep(struct usb_device static int findintfif(struct usb_device *dev, unsigned int ifn) { - unsigned int i, j; - struct usb_interface *iface; - struct usb_host_interface *alts; + unsigned int i; if (ifn & ~0xff) return -EINVAL; for (i = 0; i < dev->actconfig->desc.bNumInterfaces; i++) { - iface = dev->actconfig->interface[i]; - for (j = 0; j < iface->num_altsetting; j++) { - alts = &iface->altsetting[j]; - if (alts->desc.bInterfaceNumber == ifn) - return i; - } + if (dev->actconfig->interface[i]-> + altsetting[0].desc.bInterfaceNumber == ifn) + return i; } return -ENOENT; } @@ -688,9 +683,7 @@ static int proc_getdriver(struct dev_sta return -EFAULT; if ((ret = findintfif(ps->dev, gd.interface)) < 0) return ret; - interface = usb_ifnum_to_if(ps->dev, gd.interface); - if (!interface) - return -EINVAL; + interface = ps->dev->actconfig->interface[ret]; if (!interface->driver) return -ENODATA; strcpy(gd.driver, interface->driver->name); @@ -744,9 +737,7 @@ static int proc_setintf(struct dev_state return -EFAULT; if ((ret = findintfif(ps->dev, setintf.interface)) < 0) return ret; - interface = usb_ifnum_to_if(ps->dev, setintf.interface); - if (!interface) - return -EINVAL; + interface = ps->dev->actconfig->interface[ret]; if (interface->driver) { if ((ret = checkintf(ps, ret))) return ret; diff -puN drivers/usb/core/driverfs.c~bk-usb drivers/usb/core/driverfs.c --- 25/drivers/usb/core/driverfs.c~bk-usb 2004-03-10 21:44:00.000000000 -0800 +++ 25-akpm/drivers/usb/core/driverfs.c 2004-03-10 21:44:01.000000000 -0800 @@ -166,13 +166,9 @@ void usb_create_driverfs_dev_files (stru static ssize_t \ show_##field (struct device *dev, char *buf) \ { \ - struct usb_interface *intf; \ - int alt; \ + struct usb_interface *intf = to_usb_interface (dev); \ \ - intf = to_usb_interface (dev); \ - alt = intf->act_altsetting; \ - \ - return sprintf (buf, format_string, intf->altsetting[alt].desc.field); \ + return sprintf (buf, format_string, intf->cur_altsetting->desc.field); \ } \ static DEVICE_ATTR(field, S_IRUGO, show_##field, NULL); diff -puN drivers/usb/core/hcd.c~bk-usb drivers/usb/core/hcd.c --- 25/drivers/usb/core/hcd.c~bk-usb 2004-03-10 21:44:00.000000000 -0800 +++ 25-akpm/drivers/usb/core/hcd.c 2004-03-10 21:44:01.000000000 -0800 @@ -1213,7 +1213,7 @@ static int hcd_unlink_urb (struct urb *u break; } if (tmp != &urb->urb_list) { - retval = -EINVAL; + retval = -EIDRM; goto done; } @@ -1294,7 +1294,7 @@ done: spin_unlock (&hcd_data_lock); spin_unlock_irqrestore (&urb->lock, flags); bye: - if (retval && sys && sys->driver) + if (retval != -EIDRM && sys && sys->driver) dev_dbg (sys, "hcd_unlink_urb %p fail %d\n", urb, retval); return retval; } diff -puN drivers/usb/core/hcd-pci.c~bk-usb drivers/usb/core/hcd-pci.c --- 25/drivers/usb/core/hcd-pci.c~bk-usb 2004-03-10 21:44:00.000000000 -0800 +++ 25-akpm/drivers/usb/core/hcd-pci.c 2004-03-10 21:44:01.000000000 -0800 @@ -147,8 +147,12 @@ clean_2: hcd->driver = driver; hcd->description = driver->description; hcd->self.bus_name = pci_name(dev); +#ifdef CONFIG_PCI_NAMES + hcd->product_desc = dev->pretty_name; +#else if (hcd->product_desc == NULL) hcd->product_desc = "USB Host Controller"; +#endif hcd->self.controller = &dev->dev; if ((retval = hcd_buffer_create (hcd)) != 0) { diff -puN drivers/usb/core/hub.c~bk-usb drivers/usb/core/hub.c --- 25/drivers/usb/core/hub.c~bk-usb 2004-03-10 21:44:00.000000000 -0800 +++ 25-akpm/drivers/usb/core/hub.c 2004-03-10 21:44:01.000000000 -0800 @@ -560,7 +560,7 @@ static int hub_probe(struct usb_interfac struct usb_hub *hub; unsigned long flags; - desc = intf->altsetting + intf->act_altsetting; + desc = intf->cur_altsetting; dev = interface_to_usbdev(intf); /* Some hubs have a subclass of 1, which AFAICT according to the */ @@ -1344,15 +1344,15 @@ int usb_physical_reset_device(struct usb for (i = 0; i < dev->actconfig->desc.bNumInterfaces; i++) { struct usb_interface *intf = dev->actconfig->interface[i]; - struct usb_interface_descriptor *as; + struct usb_interface_descriptor *desc; - as = &intf->altsetting[intf->act_altsetting].desc; - ret = usb_set_interface(dev, as->bInterfaceNumber, - as->bAlternateSetting); + desc = &intf->cur_altsetting->desc; + ret = usb_set_interface(dev, desc->bInterfaceNumber, + desc->bAlternateSetting); if (ret < 0) { err("failed to set active alternate setting " "for dev %s interface %d (error=%d)", - dev->devpath, i, ret); + dev->devpath, desc->bInterfaceNumber, ret); return ret; } } diff -puN drivers/usb/core/message.c~bk-usb drivers/usb/core/message.c --- 25/drivers/usb/core/message.c~bk-usb 2004-03-10 21:44:00.000000000 -0800 +++ 25-akpm/drivers/usb/core/message.c 2004-03-10 21:44:01.000000000 -0800 @@ -783,16 +783,22 @@ void usb_disable_endpoint(struct usb_dev */ void usb_disable_interface(struct usb_device *dev, struct usb_interface *intf) { - struct usb_host_interface *hintf = - &intf->altsetting[intf->act_altsetting]; + struct usb_host_interface *alt = intf->cur_altsetting; int i; - for (i = 0; i < hintf->desc.bNumEndpoints; ++i) { + for (i = 0; i < alt->desc.bNumEndpoints; ++i) { usb_disable_endpoint(dev, - hintf->endpoint[i].desc.bEndpointAddress); + alt->endpoint[i].desc.bEndpointAddress); } } +static void release_interface(struct device *dev) +{ + struct usb_interface *interface = to_usb_interface(dev); + + complete(interface->released); +} + /* * usb_disable_device - Disable all the endpoints for a USB device * @dev: the device whose endpoints are being disabled @@ -822,12 +828,16 @@ void usb_disable_device(struct usb_devic if (dev->actconfig) { for (i = 0; i < dev->actconfig->desc.bNumInterfaces; i++) { struct usb_interface *interface; + struct completion intf_completion; /* remove this interface */ interface = dev->actconfig->interface[i]; dev_dbg (&dev->dev, "unregistering interface %s\n", interface->dev.bus_id); - device_del(&interface->dev); + init_completion (&intf_completion); + interface->released = &intf_completion; + device_unregister (&interface->dev); + wait_for_completion (&intf_completion); } dev->actconfig = 0; if (dev->state == USB_STATE_CONFIGURED) @@ -876,12 +886,11 @@ void usb_enable_endpoint(struct usb_devi void usb_enable_interface(struct usb_device *dev, struct usb_interface *intf) { - struct usb_host_interface *hintf = - &intf->altsetting[intf->act_altsetting]; + struct usb_host_interface *alt = intf->cur_altsetting; int i; - for (i = 0; i < hintf->desc.bNumEndpoints; ++i) - usb_enable_endpoint(dev, &hintf->endpoint[i].desc); + for (i = 0; i < alt->desc.bNumEndpoints; ++i) + usb_enable_endpoint(dev, &alt->endpoint[i].desc); } /** @@ -920,6 +929,7 @@ void usb_enable_interface(struct usb_dev int usb_set_interface(struct usb_device *dev, int interface, int alternate) { struct usb_interface *iface; + struct usb_host_interface *alt; int ret; int manual = 0; @@ -929,14 +939,15 @@ int usb_set_interface(struct usb_device return -EINVAL; } - if (alternate < 0 || alternate >= iface->num_altsetting) + alt = usb_altnum_to_altsetting(iface, alternate); + if (!alt) { + warn("selecting invalid altsetting %d", alternate); return -EINVAL; + } ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), USB_REQ_SET_INTERFACE, USB_RECIP_INTERFACE, - iface->altsetting[alternate] - .desc.bAlternateSetting, - interface, NULL, 0, HZ * 5); + alternate, interface, NULL, 0, HZ * 5); /* 9.4.10 says devices don't need this and are free to STALL the * request if the interface only has one alternate setting. @@ -957,7 +968,7 @@ int usb_set_interface(struct usb_device /* prevent submissions using previous endpoint settings */ usb_disable_interface(dev, iface); - iface->act_altsetting = alternate; + iface->cur_altsetting = alt; /* If the interface only has one altsetting and the device didn't * accept the request, we attempt to carry out the equivalent action @@ -965,13 +976,11 @@ int usb_set_interface(struct usb_device * new altsetting. */ if (manual) { - struct usb_host_interface *iface_as = - &iface->altsetting[alternate]; int i; - for (i = 0; i < iface_as->desc.bNumEndpoints; i++) { + for (i = 0; i < alt->desc.bNumEndpoints; i++) { unsigned int epaddr = - iface_as->endpoint[i].desc.bEndpointAddress; + alt->endpoint[i].desc.bEndpointAddress; unsigned int pipe = __create_pipe(dev, USB_ENDPOINT_NUMBER_MASK & epaddr) | (usb_endpoint_out(epaddr) ? USB_DIR_OUT : USB_DIR_IN); @@ -1045,8 +1054,19 @@ int usb_reset_configuration(struct usb_d /* re-init hc/hcd interface/endpoint state */ for (i = 0; i < config->desc.bNumInterfaces; i++) { struct usb_interface *intf = config->interface[i]; + struct usb_host_interface *alt; + + alt = usb_altnum_to_altsetting(intf, 0); - intf->act_altsetting = 0; + /* No altsetting 0? We'll assume the first altsetting. + * We could use a GetInterface call, but if a device is + * so non-compliant that it doesn't have altsetting 0 + * then I wouldn't trust its reply anyway. + */ + if (!alt) + alt = &intf->altsetting[0]; + + intf->cur_altsetting = alt; usb_enable_interface(dev, intf); } return 0; @@ -1135,25 +1155,34 @@ int usb_set_configuration(struct usb_dev */ for (i = 0; i < cp->desc.bNumInterfaces; ++i) { struct usb_interface *intf = cp->interface[i]; - struct usb_interface_descriptor *desc; + struct usb_host_interface *alt; - intf->act_altsetting = 0; - desc = &intf->altsetting [0].desc; - usb_enable_interface(dev, intf); + alt = usb_altnum_to_altsetting(intf, 0); + /* No altsetting 0? We'll assume the first altsetting. + * We could use a GetInterface call, but if a device is + * so non-compliant that it doesn't have altsetting 0 + * then I wouldn't trust its reply anyway. + */ + if (!alt) + alt = &intf->altsetting[0]; + + intf->cur_altsetting = alt; + usb_enable_interface(dev, intf); intf->dev.parent = &dev->dev; intf->dev.driver = NULL; intf->dev.bus = &usb_bus_type; intf->dev.dma_mask = dev->dev.dma_mask; + intf->dev.release = release_interface; sprintf (&intf->dev.bus_id[0], "%d-%s:%d.%d", dev->bus->busnum, dev->devpath, configuration, - desc->bInterfaceNumber); + alt->desc.bInterfaceNumber); dev_dbg (&dev->dev, "registering %s (config #%d, interface %d)\n", intf->dev.bus_id, configuration, - desc->bInterfaceNumber); - device_add (&intf->dev); + alt->desc.bInterfaceNumber); + device_register (&intf->dev); usb_create_driverfs_intf_files (intf); } } diff -puN drivers/usb/core/urb.c~bk-usb drivers/usb/core/urb.c --- 25/drivers/usb/core/urb.c~bk-usb 2004-03-10 21:44:00.000000000 -0800 +++ 25-akpm/drivers/usb/core/urb.c 2004-03-10 21:44:01.000000000 -0800 @@ -116,7 +116,8 @@ struct urb * usb_get_urb(struct urb *urb * describing that request to the USB subsystem. Request completion will * be indicated later, asynchronously, by calling the completion handler. * 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. * * The caller must have correctly initialized the URB before submitting @@ -127,12 +128,23 @@ struct urb * usb_get_urb(struct urb *urb * * Successful submissions return 0; otherwise this routine returns a * negative error number. If the submission is successful, the complete() - * 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 + * callback from the URB will be called exactly once, when the USB core and + * Host Controller Driver (HCD) are finished with the URB. When the completion * function is called, control of the URB is returned to the device * driver which issued the request. The completion handler may then * 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 * often used (in non-interrupt context) instead of this call. * That is often used through convenience wrappers, for the requests @@ -143,15 +155,17 @@ struct urb * usb_get_urb(struct urb *urb * * URBs may be submitted to endpoints before previous ones complete, to * 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 - * 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 - * completion processing for earlier requests. + * completion processing for earlier (successful) requests. * - * Bulk and Isochronous URBs may always be queued. At this writing, all - * mainstream host controller drivers support queueing for control and - * interrupt transfer requests. + * As of Linux 2.6, all USB endpoint transfer queues support depths greater + * than one. This was previously a HCD-specific behavior, except for ISO + * transfers. Non-isochronous endpoint queues are inactive during cleanup + * after faults (transfer errors or cancelation). * * Reserved Bandwidth Transfers: * @@ -389,7 +403,7 @@ int usb_submit_urb(struct urb *urb, int * When the URB_ASYNC_UNLINK transfer flag for the URB is clear, this * request is synchronous. Success is indicated by returning zero, * 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. * * The synchronous cancelation mode may not be used @@ -400,8 +414,37 @@ int usb_submit_urb(struct urb *urb, int * When the URB_ASYNC_UNLINK transfer flag for the URB is set, this * request is asynchronous. Success is indicated by returning -EINPROGRESS, * 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. + * + * 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) { diff -puN drivers/usb/core/usb.c~bk-usb drivers/usb/core/usb.c --- 25/drivers/usb/core/usb.c~bk-usb 2004-03-10 21:44:00.000000000 -0800 +++ 25-akpm/drivers/usb/core/usb.c 2004-03-10 21:44:01.000000000 -0800 @@ -189,7 +189,7 @@ void usb_deregister(struct usb_driver *d } /** - * usb_ifnum_to_if - get the interface object with a given interface number (usbcore-internal) + * usb_ifnum_to_if - get the interface object with a given interface number * @dev: the device whose current configuration is considered * @ifnum: the desired interface * @@ -220,6 +220,33 @@ struct usb_interface *usb_ifnum_to_if(st } /** + * usb_altnum_to_altsetting - get the altsetting structure with a given + * alternate setting number. + * @intf: the interface containing the altsetting in question + * @altnum: the desired alternate setting number + * + * This searches the altsetting array of the specified interface for + * an entry with the correct bAlternateSetting value and returns a pointer + * to that entry, or null. + * + * Note that altsettings need not be stored sequentially by number, so + * it would be incorrect to assume that the first altsetting entry in + * the array corresponds to altsetting zero. This routine helps device + * drivers avoid such mistakes. + */ +struct usb_host_interface *usb_altnum_to_altsetting(struct usb_interface *intf, + unsigned int altnum) +{ + int i; + + for (i = 0; i < intf->num_altsetting; i++) { + if (intf->altsetting[i].desc.bAlternateSetting == altnum) + return &intf->altsetting[i]; + } + return NULL; +} + +/** * usb_epnum_to_ep_desc - get the endpoint object with a given endpoint number * @dev: the device whose current configuration+altsettings is considered * @epnum: the desired endpoint, masked with USB_DIR_IN as appropriate. @@ -247,7 +274,7 @@ usb_epnum_to_ep_desc(struct usb_device * /* only endpoints in current altsetting are active */ intf = config->interface[i]; - alt = intf->altsetting + intf->act_altsetting; + alt = intf->cur_altsetting; for (k = 0; k < alt->desc.bNumEndpoints; k++) if (epnum == alt->endpoint[k].desc.bEndpointAddress) @@ -421,7 +448,7 @@ usb_match_id(struct usb_interface *inter if (id == NULL) return NULL; - intf = &interface->altsetting [interface->act_altsetting]; + intf = interface->cur_altsetting; dev = interface_to_usbdev(interface); /* It is important to check that id->driver_info is nonzero, @@ -624,7 +651,7 @@ static int usb_hotplug (struct device *d scratch += length; if (usb_dev->descriptor.bDeviceClass == 0) { - int alt = intf->act_altsetting; + struct usb_host_interface *alt = intf->cur_altsetting; /* 2.4 only exposed interface zero. in 2.5, hotplug * agents are called for all interfaces, and can use @@ -633,9 +660,9 @@ static int usb_hotplug (struct device *d envp [i++] = scratch; length += snprintf (scratch, buffer_size - length, "INTERFACE=%d/%d/%d", - intf->altsetting[alt].desc.bInterfaceClass, - intf->altsetting[alt].desc.bInterfaceSubClass, - intf->altsetting[alt].desc.bInterfaceProtocol); + alt->desc.bInterfaceClass, + alt->desc.bInterfaceSubClass, + alt->desc.bInterfaceProtocol); if ((buffer_size - length <= 0) || (i >= num_envp)) return -ENOMEM; ++length; @@ -1582,6 +1609,7 @@ EXPORT_SYMBOL(usb_driver_release_interfa EXPORT_SYMBOL(usb_match_id); EXPORT_SYMBOL(usb_find_interface); EXPORT_SYMBOL(usb_ifnum_to_if); +EXPORT_SYMBOL(usb_altnum_to_altsetting); EXPORT_SYMBOL(usb_reset_device); EXPORT_SYMBOL(usb_disconnect); diff -puN /dev/null drivers/usb/gadget/config.c --- /dev/null 2002-08-30 16:31:37.000000000 -0700 +++ 25-akpm/drivers/usb/gadget/config.c 2004-03-10 21:44:01.000000000 -0800 @@ -0,0 +1,116 @@ +/* + * 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 +#include +#include +#include +#include + +#include + + +/** + * 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; +} + diff -puN drivers/usb/gadget/ether.c~bk-usb drivers/usb/gadget/ether.c --- 25/drivers/usb/gadget/ether.c~bk-usb 2004-03-10 21:44:00.000000000 -0800 +++ 25-akpm/drivers/usb/gadget/ether.c 2004-03-10 21:44:01.000000000 -0800 @@ -124,7 +124,6 @@ struct eth_dev { * DRIVER_VERSION_NUM ... alerts the host side driver to differences * EP_*_NAME ... which endpoints do we use for which purpose? * 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 * usb_gadget_wakeup() call to initiate it, USB_CONFIG_ATT_WAKEUP * @@ -162,7 +161,6 @@ static const char EP_IN_NAME [] = "ep-b" #define EP_IN_NUM 2 static const char EP_STATUS_NAME [] = "ep-f"; #define EP_STATUS_NUM 3 -#define HIGHSPEED /* supports remote wakeup, but this driver doesn't */ extern int net2280_set_fifo_mode (struct usb_gadget *gadget, int mode); @@ -311,7 +309,7 @@ static const char EP_IN_NAME[] = "ep2in- #define DEFAULT_QLEN 2 /* double buffering by default */ #endif -#ifdef HIGHSPEED +#ifdef CONFIG_USB_GADGET_DUALSPEED static unsigned qmult = 5; module_param (qmult, uint, S_IRUGO|S_IWUSR); @@ -324,7 +322,7 @@ module_param (qmult, uint, S_IRUGO|S_IWU /* also defer IRQs on highspeed TX */ #define TX_DELAY DEFAULT_QLEN -#else /* !HIGHSPEED ... full speed: */ +#else /* full speed (low speed doesn't do bulk) */ #define qlen(gadget) DEFAULT_QLEN #endif @@ -607,7 +605,26 @@ fs_sink_desc = { .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 *) ðer_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 @@ -660,6 +677,25 @@ dev_qualifier = { .bNumConfigurations = 1, }; +static const struct usb_descriptor_header *hs_function [] = { +#ifdef DEV_CONFIG_CDC + /* "cdc" mode descriptors */ + (struct usb_descriptor_header *) &control_intf, + (struct usb_descriptor_header *) &header_desc, + (struct usb_descriptor_header *) &union_desc, + (struct usb_descriptor_header *) ðer_desc, +#ifdef EP_STATUS_NUM + (struct usb_descriptor_header *) &hs_status_desc, +#endif + (struct usb_descriptor_header *) &data_nop_intf, +#endif /* DEV_CONFIG_CDC */ + /* minimalist core */ + (struct usb_descriptor_header *) &data_intf, + (struct usb_descriptor_header *) &hs_source_desc, + (struct usb_descriptor_header *) &hs_sink_desc, + 0, +}; + /* maxpacket and other transfer characteristics vary by speed. */ #define ep_desc(g,hs,fs) (((g)->speed==USB_SPEED_HIGH)?(hs):(fs)) @@ -669,7 +705,7 @@ dev_qualifier = { /* if there's no high speed support, maxpacket doesn't change. */ #define ep_desc(g,hs,fs) fs -#endif /* !HIGHSPEED */ +#endif /* !CONFIG_USB_GADGET_DUALSPEED */ /*-------------------------------------------------------------------------*/ @@ -704,86 +740,25 @@ static struct usb_gadget_strings stringt static int config_buf (enum usb_device_speed speed, u8 *buf, u8 type, unsigned index) { - const unsigned config_len = USB_DT_CONFIG_SIZE -#ifdef DEV_CONFIG_CDC - + 2 * USB_DT_INTERFACE_SIZE - + sizeof header_desc - + sizeof union_desc - + sizeof ether_desc -#ifdef EP_STATUS_NUM - + USB_DT_ENDPOINT_SIZE -#endif -#endif /* DEV_CONFIG_CDC */ - + USB_DT_INTERFACE_SIZE - + 2 * USB_DT_ENDPOINT_SIZE; + int len; + const struct usb_descriptor_header **function = fs_function; +#ifdef CONFIG_USB_GADGET_DUALSPEED + int hs = (speed == USB_SPEED_HIGH); -#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, ð_config, USB_DT_CONFIG_SIZE); - buf [1] = type; - ((struct usb_config_descriptor *) buf)->wTotalLength - = __constant_cpu_to_le16 (config_len); - buf += USB_DT_CONFIG_SIZE; -#ifdef HIGHSPEED - hs = (speed == USB_SPEED_HIGH); if (type == USB_DT_OTHER_SPEED_CONFIG) hs = !hs; -#endif - -#ifdef DEV_CONFIG_CDC - /* control interface, class descriptors, optional status endpoint */ - memcpy (buf, &control_intf, USB_DT_INTERFACE_SIZE); - buf += USB_DT_INTERFACE_SIZE; - - memcpy (buf, &header_desc, sizeof header_desc); - buf += sizeof header_desc; - memcpy (buf, &union_desc, sizeof union_desc); - buf += sizeof union_desc; - memcpy (buf, ðer_desc, sizeof ether_desc); - buf += sizeof ether_desc; - -#ifdef EP_STATUS_NUM -#ifdef HIGHSPEED if (hs) - memcpy (buf, &hs_status_desc, USB_DT_ENDPOINT_SIZE); - else -#endif /* HIGHSPEED */ - memcpy (buf, &fs_status_desc, USB_DT_ENDPOINT_SIZE); - buf += USB_DT_ENDPOINT_SIZE; -#endif /* EP_STATUS_NUM */ - - /* default data altsetting has no endpoints */ - memcpy (buf, &data_nop_intf, USB_DT_INTERFACE_SIZE); - buf += USB_DT_INTERFACE_SIZE; -#endif /* DEV_CONFIG_CDC */ - - /* the "real" data interface has two endpoints */ - memcpy (buf, &data_intf, USB_DT_INTERFACE_SIZE); - buf += USB_DT_INTERFACE_SIZE; -#ifdef HIGHSPEED - if (hs) { - memcpy (buf, &hs_source_desc, USB_DT_ENDPOINT_SIZE); - buf += USB_DT_ENDPOINT_SIZE; - memcpy (buf, &hs_sink_desc, USB_DT_ENDPOINT_SIZE); - buf += USB_DT_ENDPOINT_SIZE; - } else + function = hs_function; #endif - { - memcpy (buf, &fs_source_desc, USB_DT_ENDPOINT_SIZE); - buf += USB_DT_ENDPOINT_SIZE; - memcpy (buf, &fs_sink_desc, USB_DT_ENDPOINT_SIZE); - buf += USB_DT_ENDPOINT_SIZE; - } - return config_len; + /* a single configuration must always be index 0 */ + if (index > 0) + return -EINVAL; + len = usb_gadget_config_buf (ð_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, uns switch (gadget->speed) { case USB_SPEED_FULL: speed = "full"; break; -#ifdef HIGHSPEED +#ifdef CONFIG_USB_GADGET_DUALSPEED case USB_SPEED_HIGH: speed = "high"; break; #endif default: speed = "?"; break; @@ -1163,15 +1138,19 @@ eth_setup (struct usb_gadget *gadget, co value = min (ctrl->wLength, (u16) sizeof device_desc); memcpy (req->buf, &device_desc, value); break; -#ifdef HIGHSPEED +#ifdef CONFIG_USB_GADGET_DUALSPEED case USB_DT_DEVICE_QUALIFIER: + if (!gadget->is_dualspeed) + break; value = min (ctrl->wLength, (u16) sizeof dev_qualifier); memcpy (req->buf, &dev_qualifier, value); break; case USB_DT_OTHER_SPEED_CONFIG: + if (!gadget->is_dualspeed) + break; // FALLTHROUGH -#endif /* HIGHSPEED */ +#endif /* CONFIG_USB_GADGET_DUALSPEED */ case USB_DT_CONFIG: value = config_buf (gadget->speed, req->buf, ctrl->wValue >> 8, @@ -1675,7 +1654,7 @@ static int eth_start_xmit (struct sk_buf #endif req->length = length; -#ifdef HIGHSPEED +#ifdef CONFIG_USB_GADGET_DUALSPEED /* throttle highspeed IRQ rate back slightly */ req->no_interrupt = (dev->gadget->speed == USB_SPEED_HIGH) ? ((atomic_read (&dev->tx_qlen) % TX_DELAY) != 0) @@ -1798,7 +1777,7 @@ eth_bind (struct usb_gadget *gadget) #endif device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket; -#ifdef HIGHSPEED +#ifdef CONFIG_USB_GADGET_DUALSPEED /* assumes ep0 uses the same value for both speeds ... */ dev_qualifier.bMaxPacketSize0 = device_desc.bMaxPacketSize0; #endif @@ -1894,7 +1873,7 @@ fail: /*-------------------------------------------------------------------------*/ static struct usb_gadget_driver eth_driver = { -#ifdef HIGHSPEED +#ifdef CONFIG_USB_GADGET_DUALSPEED .speed = USB_SPEED_HIGH, #else .speed = USB_SPEED_FULL, diff -puN drivers/usb/gadget/Kconfig~bk-usb drivers/usb/gadget/Kconfig --- 25/drivers/usb/gadget/Kconfig~bk-usb 2004-03-10 21:44:00.000000000 -0800 +++ 25-akpm/drivers/usb/gadget/Kconfig 2004-03-10 21:44:01.000000000 -0800 @@ -3,6 +3,15 @@ # (a) a peripheral controller, and # (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" config USB_GADGET @@ -11,7 +20,7 @@ config USB_GADGET USB is a master/slave protocol, organized with one master host (such as a PC) controlling up to 127 peripheral devices. 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 you need a low level bus controller driver, and some software @@ -43,6 +52,7 @@ choice config USB_GADGET_NET2280 boolean "NetChip 2280" depends on PCI + select USB_GADGET_DUALSPEED help NetChip 2280 is a PCI based USB peripheral controller which supports both full and high speed USB 2.0 data transfers. @@ -126,6 +136,13 @@ config USB_SA1100 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 diff -puN drivers/usb/gadget/Makefile~bk-usb drivers/usb/gadget/Makefile --- 25/drivers/usb/gadget/Makefile~bk-usb 2004-03-10 21:44:00.000000000 -0800 +++ 25-akpm/drivers/usb/gadget/Makefile 2004-03-10 21:44:01.000000000 -0800 @@ -8,8 +8,8 @@ obj-$(CONFIG_USB_GOKU) += goku_udc.o # # USB gadget drivers # -g_zero-objs := zero.o usbstring.o -g_ether-objs := ether.o usbstring.o +g_zero-objs := zero.o usbstring.o config.o +g_ether-objs := ether.o usbstring.o config.o g_serial-objs := serial.o usbstring.o gadgetfs-objs := inode.o usbstring.o g_file_storage-objs := file_storage.o usbstring.o diff -puN drivers/usb/gadget/net2280.c~bk-usb drivers/usb/gadget/net2280.c --- 25/drivers/usb/gadget/net2280.c~bk-usb 2004-03-10 21:44:00.000000000 -0800 +++ 25-akpm/drivers/usb/gadget/net2280.c 2004-03-10 21:44:01.000000000 -0800 @@ -2663,7 +2663,7 @@ static void gadget_release (struct devic /* 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); @@ -2736,6 +2736,7 @@ static int net2280_probe (struct pci_dev spin_lock_init (&dev->lock); dev->pdev = pdev; dev->gadget.ops = &net2280_ops; + dev->gadget.is_dualspeed = 1; /* the "gadget" abstracts/virtualizes the controller */ strcpy (dev->gadget.dev.bus_id, "gadget"); @@ -2884,7 +2885,7 @@ static struct pci_driver net2280_pci_dri .id_table = pci_ids, .probe = net2280_probe, - .remove = __exit_p(net2280_remove), + .remove = net2280_remove, /* FIXME add power management support */ }; diff -puN drivers/usb/gadget/usbstring.c~bk-usb drivers/usb/gadget/usbstring.c --- 25/drivers/usb/gadget/usbstring.c~bk-usb 2004-03-10 21:44:00.000000000 -0800 +++ 25-akpm/drivers/usb/gadget/usbstring.c 2004-03-10 21:44:01.000000000 -0800 @@ -16,24 +16,89 @@ #include #include +#include + + +static int utf8_to_utf16le(const char *s, u16 *cp, unsigned len) +{ + int count = 0; + u8 c; + u16 uchar; + + /* this insists on correct encodings, though not minimal ones. + * BUT it currently rejects legit 4-byte UTF-8 code points, + * which need surrogate pairs. (Unicode 3.1 can use them.) + */ + while (len != 0 && (c = (u8) *s++) != 0) { + if (unlikely(c & 0x80)) { + // 2-byte sequence: + // 00000yyyyyxxxxxx = 110yyyyy 10xxxxxx + if ((c & 0xe0) == 0xc0) { + uchar = (c & 0x1f) << 6; + + c = (u8) *s++; + if ((c & 0xc0) != 0xc0) + goto fail; + c &= 0x3f; + uchar |= c; + + // 3-byte sequence (most CJKV characters): + // zzzzyyyyyyxxxxxx = 1110zzzz 10yyyyyy 10xxxxxx + } else if ((c & 0xf0) == 0xe0) { + uchar = (c & 0x0f) << 12; + + c = (u8) *s++; + if ((c & 0xc0) != 0xc0) + goto fail; + c &= 0x3f; + uchar |= c << 6; + + c = (u8) *s++; + if ((c & 0xc0) != 0xc0) + goto fail; + c &= 0x3f; + uchar |= c; + + /* no bogus surrogates */ + if (0xd800 <= uchar && uchar <= 0xdfff) + goto fail; + + // 4-byte sequence (surrogate pairs, currently rare): + // 11101110wwwwzzzzyy + 110111yyyyxxxxxx + // = 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx + // (uuuuu = wwww + 1) + // FIXME accept the surrogate code points (only) + + } else + goto fail; + } else + uchar = c; + put_unaligned (cpu_to_le16 (uchar), cp++); + count++; + len--; + } + return count; +fail: + return -1; +} + /** * usb_gadget_get_string - fill out a string descriptor - * @table: of c strings using iso latin/1 characters + * @table: of c strings encoded using UTF-8 * @id: string id, from low byte of wValue in get string descriptor * @buf: at least 256 bytes * - * Finds the iso latin/1 string matching the ID, and converts it into a + * Finds the UTF-8 string matching the ID, and converts it into a * string descriptor in utf16-le. * Returns length of descriptor (always even) or negative errno * - * If your driver needs stings in multiple languages, you'll need to - * to use some alternate solution for languages where the ISO 8859/1 - * (latin/1) character set can't be used. For example, they can't be - * used with Chinese (Big5, GB2312, etc), Japanese, Korean, or many other - * languages. You'd likely "switch (wIndex) { ... }" in your ep0 - * string descriptor logic, using this routine in cases where "western - * european" characters suffice for the strings being returned. + * If your driver needs stings in multiple languages, you'll probably + * "switch (wIndex) { ... }" in your ep0 string descriptor logic, + * using this routine after choosing which set of UTF-8 strings to use. + * Note that US-ASCII is a strict subset of UTF-8; any string bytes with + * the eighth bit set will be multibyte UTF-8 characters, not ISO-8859/1 + * characters (which are also widely used in C strings). */ int usb_gadget_get_string (struct usb_gadget_strings *table, int id, u8 *buf) @@ -59,13 +124,12 @@ usb_gadget_get_string (struct usb_gadget /* string descriptors have length, tag, then UTF16-LE text */ len = min ((size_t) 126, strlen (s->s)); + memset (buf + 2, 0, 2 * len); /* zero all the bytes */ + len = utf8_to_utf16le(s->s, (u16 *)&buf[2], len); + if (len < 0) + return -EINVAL; buf [0] = (len + 1) * 2; buf [1] = USB_DT_STRING; - memset (buf + 2, 0, 2 * len); /* zero all the high bytes */ - while (len) { - buf [2 * len] = s->s [len - 1]; - len--; - } return buf [0]; } diff -puN drivers/usb/gadget/zero.c~bk-usb drivers/usb/gadget/zero.c --- 25/drivers/usb/gadget/zero.c~bk-usb 2004-03-10 21:44:00.000000000 -0800 +++ 25-akpm/drivers/usb/gadget/zero.c 2004-03-10 21:44:01.000000000 -0800 @@ -1,7 +1,7 @@ /* * zero.c -- Gadget Zero, for USB development * - * Copyright (C) 2003 David Brownell + * Copyright (C) 2003-2004 David Brownell * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -103,6 +103,11 @@ static const char loopback [] = "loop in /*-------------------------------------------------------------------------*/ /* + * driver assumes self-powered hardware, and + * has no way for users to trigger remote wakeup. + */ + +/* * hardware-specific configuration, controlled by which device * controller driver was configured. * @@ -110,11 +115,6 @@ static const char loopback [] = "loop in * DRIVER_VERSION_NUM ... alerts the host side driver to differences * EP_*_NAME ... which endpoints do we use for which purpose? * EP_*_NUM ... numbers for them (often limited by hardware) - * HIGHSPEED ... define if ep0 and descriptors need high speed support - * MAX_USB_POWER ... define if we use other than 100 mA bus current - * SELFPOWER ... if we can run on bus power, zero - * WAKEUP ... if hardware supports remote wakeup AND we will issue the - * usb_gadget_wakeup() call to initiate it, USB_CONFIG_ATT_WAKEUP * * add other defines for other portability issues, like hardware that * for some reason doesn't handle full speed bulk maxpacket of 64. @@ -138,9 +138,6 @@ static const char EP_OUT_NAME [] = "ep-a #define EP_OUT_NUM 2 static const char EP_IN_NAME [] = "ep-b"; #define EP_IN_NUM 2 -#define HIGHSPEED -/* specific hardware configs could be bus-powered */ -/* supports remote wakeup, but this driver doesn't */ #endif /* @@ -161,8 +158,6 @@ static const char EP_OUT_NAME [] = "ep12 #define EP_OUT_NUM 12 static const char EP_IN_NAME [] = "ep11in-bulk"; #define EP_IN_NUM 11 -/* doesn't support bus-powered operation */ -/* supports remote wakeup, but this driver doesn't */ #endif /* @@ -183,8 +178,6 @@ static const char EP_OUT_NAME [] = "ep1o #define EP_OUT_NUM 1 static const char EP_IN_NAME [] = "ep2in-bulk"; #define EP_IN_NUM 2 -/* doesn't support bus-powered operation */ -/* doesn't support remote wakeup? */ #endif /* @@ -199,7 +192,6 @@ static const char EP_OUT_NAME [] = "ep1- #define EP_OUT_NUM 1 static const char EP_IN_NAME [] = "ep2-bulk"; #define EP_IN_NUM 2 -/* doesn't support remote wakeup */ #endif /*-------------------------------------------------------------------------*/ @@ -208,30 +200,6 @@ static const char EP_IN_NAME [] = "ep2-b # error Configure some USB peripheral controller driver! #endif -/* power usage is config specific. - * hardware that supports remote wakeup defaults to disabling it. - */ - -#ifndef SELFPOWER -/* default: say we're self-powered */ -#define SELFPOWER USB_CONFIG_ATT_SELFPOWER -/* else: - * - SELFPOWER value must be zero - * - MAX_USB_POWER may be nonzero. - */ -#endif - -#ifndef MAX_USB_POWER -/* any hub supports this steady state bus power consumption */ -#define MAX_USB_POWER 100 /* mA */ -#endif - -#ifndef WAKEUP -/* default: this driver won't do remote wakeup */ -#define WAKEUP 0 -/* else value must be USB_CONFIG_ATT_WAKEUP */ -#endif - /*-------------------------------------------------------------------------*/ /* big enough to hold our biggest descriptor */ @@ -290,8 +258,8 @@ module_param (pattern, uint, S_IRUGO|S_I /* * Normally the "loopback" configuration is second (index 1) so * it's not the default. Here's where to change that order, to - * work better with hosts (like Linux ... for now!) where config - * changes are problematic. + * work better with hosts where config changes are problematic. + * Or controllers (like superh) that only support one config. */ static int loopdefault = 0; @@ -301,7 +269,7 @@ module_param (loopdefault, bool, S_IRUGO /* Thanks to NetChip Technologies for donating this product ID. * - * DO NOT REUSE THESE IDs with any other driver!! Ever!! + * DO NOT REUSE THESE IDs with a protocol-incompatible driver!! Ever!! * Instead: allocate your own, using normal USB-IF procedures. */ #define DRIVER_VENDOR_NUM 0x0525 /* NetChip */ @@ -353,8 +321,8 @@ source_sink_config = { .bNumInterfaces = 1, .bConfigurationValue = CONFIG_SOURCE_SINK, .iConfiguration = STRING_SOURCE_SINK, - .bmAttributes = USB_CONFIG_ATT_ONE | SELFPOWER | WAKEUP, - .bMaxPower = (MAX_USB_POWER + 1) / 2, + .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER, + .bMaxPower = 1, /* self-powered */ }; static const struct usb_config_descriptor @@ -366,8 +334,8 @@ loopback_config = { .bNumInterfaces = 1, .bConfigurationValue = CONFIG_LOOPBACK, .iConfiguration = STRING_LOOPBACK, - .bmAttributes = USB_CONFIG_ATT_ONE | SELFPOWER | WAKEUP, - .bMaxPower = (MAX_USB_POWER + 1) / 2, + .bmAttributes = USB_CONFIG_ATT_ONE | USB_CONFIG_ATT_SELFPOWER, + .bMaxPower = 1, /* self-powered */ }; /* one interface in each configuration */ @@ -414,7 +382,21 @@ fs_sink_desc = { .wMaxPacketSize = __constant_cpu_to_le16 (64), }; -#ifdef HIGHSPEED +static const struct usb_descriptor_header *fs_source_sink_function [] = { + (struct usb_descriptor_header *) &source_sink_intf, + (struct usb_descriptor_header *) &fs_sink_desc, + (struct usb_descriptor_header *) &fs_source_desc, + 0, +}; + +static const struct usb_descriptor_header *fs_loopback_function [] = { + (struct usb_descriptor_header *) &loopback_intf, + (struct usb_descriptor_header *) &fs_sink_desc, + (struct usb_descriptor_header *) &fs_source_desc, + 0, +}; + +#ifdef CONFIG_USB_GADGET_DUALSPEED /* * usb 2.0 devices need to expose both high speed and full speed @@ -425,22 +407,20 @@ fs_sink_desc = { * for the config descriptor. */ -static const struct usb_endpoint_descriptor +static struct usb_endpoint_descriptor hs_source_desc = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = EP_IN_NUM | USB_DIR_IN, .bmAttributes = USB_ENDPOINT_XFER_BULK, .wMaxPacketSize = __constant_cpu_to_le16 (512), }; -static const struct usb_endpoint_descriptor +static struct usb_endpoint_descriptor hs_sink_desc = { .bLength = USB_DT_ENDPOINT_SIZE, .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = EP_OUT_NUM, .bmAttributes = USB_ENDPOINT_XFER_BULK, .wMaxPacketSize = __constant_cpu_to_le16 (512), }; @@ -456,6 +436,20 @@ dev_qualifier = { .bNumConfigurations = 2, }; +static const struct usb_descriptor_header *hs_source_sink_function [] = { + (struct usb_descriptor_header *) &source_sink_intf, + (struct usb_descriptor_header *) &hs_source_desc, + (struct usb_descriptor_header *) &hs_sink_desc, + 0, +}; + +static const struct usb_descriptor_header *hs_loopback_function [] = { + (struct usb_descriptor_header *) &loopback_intf, + (struct usb_descriptor_header *) &hs_source_desc, + (struct usb_descriptor_header *) &hs_sink_desc, + 0, +}; + /* maxpacket and other transfer characteristics vary by speed. */ #define ep_desc(g,hs,fs) (((g)->speed==USB_SPEED_HIGH)?(hs):(fs)) @@ -464,13 +458,14 @@ dev_qualifier = { /* if there's no high speed support, maxpacket doesn't change. */ #define ep_desc(g,hs,fs) fs -#endif /* !HIGHSPEED */ +#endif /* !CONFIG_USB_GADGET_DUALSPEED */ +static char manufacturer [40]; static char serial [40]; /* static strings, in iso 8859/1 */ static struct usb_string strings [] = { - { STRING_MANUFACTURER, UTS_SYSNAME " " UTS_RELEASE " with " CHIP, }, + { STRING_MANUFACTURER, manufacturer, }, { STRING_PRODUCT, longname, }, { STRING_SERIAL, serial, }, { STRING_LOOPBACK, loopback, }, @@ -502,60 +497,42 @@ static struct usb_gadget_strings stringt * device?) */ static int -config_buf (enum usb_device_speed speed, +config_buf (struct usb_gadget *gadget, u8 *buf, u8 type, unsigned index) { - int is_source_sink; - const unsigned config_len = USB_DT_CONFIG_SIZE - + USB_DT_INTERFACE_SIZE - + 2 * USB_DT_ENDPOINT_SIZE; -#ifdef HIGHSPEED - int hs; + int is_source_sink; + int len; + const struct usb_descriptor_header **function; +#ifdef CONFIG_USB_GADGET_DUALSPEED + int hs = (gadget->speed == USB_SPEED_HIGH); #endif + /* two configurations will always be index 0 and index 1 */ if (index > 1) return -EINVAL; - if (config_len > USB_BUFSIZ) - return -EDOM; is_source_sink = loopdefault ? (index == 1) : (index == 0); - /* config (or other speed config) */ - if (is_source_sink) - memcpy (buf, &source_sink_config, USB_DT_CONFIG_SIZE); - else - memcpy (buf, &loopback_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; - - /* one interface */ - if (is_source_sink) - memcpy (buf, &source_sink_intf, USB_DT_INTERFACE_SIZE); - else - memcpy (buf, &loopback_intf, USB_DT_INTERFACE_SIZE); - buf += USB_DT_INTERFACE_SIZE; - - /* the endpoints in that interface (at that speed) */ -#ifdef HIGHSPEED - hs = (speed == USB_SPEED_HIGH); +#ifdef CONFIG_USB_GADGET_DUALSPEED if (type == USB_DT_OTHER_SPEED_CONFIG) hs = !hs; - 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 + if (hs) + function = is_source_sink + ? hs_source_sink_function + : hs_loopback_function; + else #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; + function = is_source_sink + ? fs_source_sink_function + : fs_loopback_function; + + len = usb_gadget_config_buf (is_source_sink + ? &source_sink_config + : &loopback_config, + buf, USB_BUFSIZ, function); + if (len < 0) + return len; + ((struct usb_config_descriptor *) buf)->bDescriptorType = type; + return len; } /*-------------------------------------------------------------------------*/ @@ -1019,17 +996,21 @@ zero_setup (struct usb_gadget *gadget, c value = min (ctrl->wLength, (u16) sizeof device_desc); memcpy (req->buf, &device_desc, value); break; -#ifdef HIGHSPEED +#ifdef CONFIG_USB_GADGET_DUALSPEED case USB_DT_DEVICE_QUALIFIER: + if (!gadget->is_dualspeed) + break; value = min (ctrl->wLength, (u16) sizeof dev_qualifier); memcpy (req->buf, &dev_qualifier, value); break; case USB_DT_OTHER_SPEED_CONFIG: + if (!gadget->is_dualspeed) + break; // FALLTHROUGH -#endif /* HIGHSPEED */ +#endif /* CONFIG_USB_GADGET_DUALSPEED */ case USB_DT_CONFIG: - value = config_buf (gadget->speed, req->buf, + value = config_buf (gadget, req->buf, ctrl->wValue >> 8, ctrl->wValue & 0xff); if (value >= 0) @@ -1212,14 +1193,26 @@ zero_bind (struct usb_gadget *gadget) dev->req->complete = zero_setup_complete; device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket; -#ifdef HIGHSPEED + +#ifdef CONFIG_USB_GADGET_DUALSPEED /* assume ep0 uses the same value for both speeds ... */ dev_qualifier.bMaxPacketSize0 = device_desc.bMaxPacketSize0; + + /* and that all endpoints are dual-speed */ + hs_source_desc.bEndpointAddress = fs_source_desc.bEndpointAddress; + hs_sink_desc.bEndpointAddress = fs_sink_desc.bEndpointAddress; #endif gadget->ep0->driver_data = dev; INFO (dev, "%s, version: " DRIVER_VERSION "\n", longname); + INFO (dev, "using %s, OUT %s IN %s\n", gadget->name, + EP_OUT_NAME, EP_IN_NAME); + + snprintf (manufacturer, sizeof manufacturer, + UTS_SYSNAME " " UTS_RELEASE " with %s", + gadget->name); + return 0; enomem: @@ -1230,7 +1223,7 @@ enomem: /*-------------------------------------------------------------------------*/ static struct usb_gadget_driver zero_driver = { -#ifdef HIGHSPEED +#ifdef CONFIG_USB_GADGET_DUALSPEED .speed = USB_SPEED_HIGH, #else .speed = USB_SPEED_FULL, diff -puN drivers/usb/host/ehci-dbg.c~bk-usb drivers/usb/host/ehci-dbg.c --- 25/drivers/usb/host/ehci-dbg.c~bk-usb 2004-03-10 21:44:00.000000000 -0800 +++ 25-akpm/drivers/usb/host/ehci-dbg.c 2004-03-10 21:44:01.000000000 -0800 @@ -579,7 +579,11 @@ show_periodic (struct class_device *clas break; case Q_TYPE_SITD: temp = scnprintf (next, size, - " sitd/%p", p.sitd); + " sitd%d-%04x/%p", + p.sitd->stream->interval, + le32_to_cpup (&p.sitd->hw_uframe) + & 0x0000ffff, + p.sitd); tag = Q_NEXT_TYPE (p.sitd->hw_next); p = p.sitd->sitd_next; break; diff -puN drivers/usb/host/ehci.h~bk-usb drivers/usb/host/ehci.h --- 25/drivers/usb/host/ehci.h~bk-usb 2004-03-10 21:44:00.000000000 -0800 +++ 25-akpm/drivers/usb/host/ehci.h 2004-03-10 21:44:01.000000000 -0800 @@ -492,16 +492,16 @@ struct ehci_itd { /* * EHCI Specification 0.95 Section 3.4 * siTD, aka split-transaction isochronous Transfer Descriptor - * ... describe low/full speed iso xfers through TT in hubs + * ... describe full speed iso xfers through TT in hubs * see Figure 3-5 "Split-transaction Isochronous Transaction Descriptor (siTD) */ struct ehci_sitd { /* first part defined by EHCI spec */ u32 hw_next; /* uses bit field macros above - see EHCI 0.95 Table 3-8 */ - u32 hw_fullspeed_ep; /* see EHCI table 3-9 */ - u32 hw_uframe; /* see EHCI table 3-10 */ - u32 hw_results; /* see EHCI table 3-11 */ + u32 hw_fullspeed_ep; /* EHCI table 3-9 */ + u32 hw_uframe; /* EHCI table 3-10 */ + u32 hw_results; /* EHCI table 3-11 */ #define SITD_IOC (1 << 31) /* interrupt on completion */ #define SITD_PAGE (1 << 30) /* buffer 0/1 */ #define SITD_LENGTH(x) (0x3ff & ((x)>>16)) @@ -515,8 +515,8 @@ struct ehci_sitd { #define SITD_ACTIVE __constant_cpu_to_le32(SITD_STS_ACTIVE) - u32 hw_buf [2]; /* see EHCI table 3-12 */ - u32 hw_backpointer; /* see EHCI table 3-13 */ + u32 hw_buf [2]; /* EHCI table 3-12 */ + u32 hw_backpointer; /* EHCI table 3-13 */ u32 hw_buf_hi [2]; /* Appendix B */ /* the rest is HCD-private */ @@ -552,8 +552,6 @@ struct ehci_fstn { /*-------------------------------------------------------------------------*/ -#define SUBMIT_URB(urb,mem_flags) usb_submit_urb(urb,mem_flags) - #ifndef DEBUG #define STUB_DEBUG_FILES #endif /* DEBUG */ diff -puN drivers/usb/host/ehci-hcd.c~bk-usb drivers/usb/host/ehci-hcd.c --- 25/drivers/usb/host/ehci-hcd.c~bk-usb 2004-03-10 21:44:00.000000000 -0800 +++ 25-akpm/drivers/usb/host/ehci-hcd.c 2004-03-10 21:44:01.000000000 -0800 @@ -106,8 +106,6 @@ static const char hcd_name [] = "ehci_hc #undef EHCI_VERBOSE_DEBUG #undef EHCI_URB_TRACE -// #define have_split_iso - #ifdef DEBUG #define EHCI_STATS #endif @@ -676,6 +674,7 @@ static void ehci_work (struct ehci_hcd * /* the IO watchdog guards against hardware or driver bugs that * misplace IRQs, and should let us run completely without IRQs. + * such lossage has been observed on both VT6202 and VT8235. */ if ((ehci->async->qh_next.ptr != 0) || (ehci->periodic_sched != 0)) timer_action (ehci, TIMER_IO_WATCHDOG); @@ -796,13 +795,8 @@ static int ehci_urb_enqueue ( case PIPE_ISOCHRONOUS: if (urb->dev->speed == USB_SPEED_HIGH) return itd_submit (ehci, urb, mem_flags); -#ifdef have_split_iso else return sitd_submit (ehci, urb, mem_flags); -#else - dbg ("no split iso support yet"); - return -ENOSYS; -#endif /* have_split_iso */ } } diff -puN drivers/usb/host/ehci-sched.c~bk-usb drivers/usb/host/ehci-sched.c --- 25/drivers/usb/host/ehci-sched.c~bk-usb 2004-03-10 21:44:00.000000000 -0800 +++ 25-akpm/drivers/usb/host/ehci-sched.c 2004-03-10 21:44:01.000000000 -0800 @@ -53,14 +53,10 @@ periodic_next_shadow (union ehci_shadow return &periodic->fstn->fstn_next; case Q_TYPE_ITD: return &periodic->itd->itd_next; -#ifdef have_split_iso - case Q_TYPE_SITD: + // case Q_TYPE_SITD: + default: return &periodic->sitd->sitd_next; -#endif /* have_split_iso */ } - dbg ("BAD shadow %p tag %d", periodic->ptr, tag); - // BUG (); - return 0; } /* returns true after successful unlink */ @@ -133,7 +129,6 @@ periodic_usecs (struct ehci_hcd *ehci, u hw_p = &q->itd->hw_next; q = &q->itd->itd_next; break; -#ifdef have_split_iso case Q_TYPE_SITD: /* is it in the S-mask? (count SPLIT, DATA) */ if (q->sitd->hw_uframe & cpu_to_le32 (1 << uframe)) { @@ -154,7 +149,6 @@ periodic_usecs (struct ehci_hcd *ehci, u hw_p = &q->sitd->hw_next; q = &q->sitd->sitd_next; break; -#endif /* have_split_iso */ default: BUG (); } @@ -229,7 +223,8 @@ static int tt_no_collision ( if (same_tt (dev, here.itd->urb->dev)) { u16 mask; - mask = le32_to_cpu (here.sitd->hw_uframe); + mask = le32_to_cpu (here.sitd + ->hw_uframe); /* FIXME assumes no gap for IN! */ mask |= mask >> 8; if (mask & uf_mask) @@ -237,7 +232,7 @@ static int tt_no_collision ( } type = Q_NEXT_TYPE (here.qh->hw_next); here = here.sitd->sitd_next; - break; + continue; // case Q_TYPE_FSTN: default: ehci_dbg (ehci, @@ -698,12 +693,27 @@ iso_stream_put(struct ehci_hcd *ehci, st // BUG_ON (!list_empty(&stream->td_list)); while (!list_empty (&stream->free_list)) { - struct ehci_itd *itd; + struct list_head *entry; - itd = list_entry (stream->free_list.next, - struct ehci_itd, itd_list); - list_del (&itd->itd_list); - dma_pool_free (ehci->itd_pool, itd, itd->itd_dma); + entry = stream->free_list.next; + list_del (entry); + + /* knows about ITD vs SITD */ + if (stream->highspeed) { + struct ehci_itd *itd; + + itd = list_entry (entry, struct ehci_itd, + itd_list); + dma_pool_free (ehci->itd_pool, itd, + itd->itd_dma); + } else { + struct ehci_sitd *sitd; + + sitd = list_entry (entry, struct ehci_sitd, + sitd_list); + dma_pool_free (ehci->sitd_pool, sitd, + sitd->sitd_dma); + } } is_in = (stream->bEndpointAddress & USB_DIR_IN) ? 0x10 : 0; @@ -858,6 +868,7 @@ itd_urb_transaction ( int i; unsigned num_itds; struct ehci_iso_sched *sched; + unsigned long flags; sched = iso_sched_alloc (urb->number_of_packets, mem_flags); if (unlikely (sched == 0)) @@ -871,6 +882,7 @@ itd_urb_transaction ( num_itds = urb->number_of_packets; /* allocate/init ITDs */ + spin_lock_irqsave (&ehci->lock, flags); for (i = 0; i < num_itds; i++) { /* free_list.next might be cache-hot ... but maybe @@ -884,8 +896,14 @@ itd_urb_transaction ( list_del (&itd->itd_list); itd_dma = itd->itd_dma; } else + itd = 0; + + if (!itd) { + spin_unlock_irqrestore (&ehci->lock, flags); itd = dma_pool_alloc (ehci->itd_pool, mem_flags, &itd_dma); + spin_lock_irqsave (&ehci->lock, flags); + } if (unlikely (0 == itd)) { iso_sched_free (stream, sched); @@ -895,6 +913,7 @@ itd_urb_transaction ( itd->itd_dma = itd_dma; list_add (&itd->itd_list, &sched->td_list); } + spin_unlock_irqrestore (&ehci->lock, flags); /* temporarily store schedule info in hcpriv */ urb->hcpriv = sched; @@ -909,11 +928,11 @@ itd_slot_ok ( struct ehci_hcd *ehci, u32 mod, u32 uframe, - u32 end, u8 usecs, u32 period ) { + uframe %= period; do { /* can't commit more than 80% periodic == 100 usec */ if (periodic_usecs (ehci, uframe >> 3, uframe & 0x7) @@ -922,8 +941,7 @@ itd_slot_ok ( /* we know urb->interval is 2^N uframes */ uframe += period; - uframe %= mod; - } while (uframe != end); + } while (uframe < mod); return 1; } @@ -933,7 +951,6 @@ sitd_slot_ok ( u32 mod, struct ehci_iso_stream *stream, u32 uframe, - u32 end, struct ehci_iso_sched *sched, u32 period_uframes ) @@ -952,12 +969,20 @@ sitd_slot_ok ( */ /* check bandwidth */ + uframe %= period_uframes; do { u32 max_used; frame = uframe >> 3; uf = uframe & 7; + /* tt must be idle for start(s), any gap, and csplit. + * assume scheduling slop leaves 10+% for control/bulk. + */ + if (!tt_no_collision (ehci, period_uframes << 3, + stream->udev, frame, mask)) + return 0; + /* check starts (OUT uses more than one) */ max_used = 100 - stream->usecs; for (tmp = stream->raw_mask & 0xff; tmp; tmp >>= 1, uf++) { @@ -969,25 +994,19 @@ sitd_slot_ok ( if (stream->c_usecs) { max_used = 100 - stream->c_usecs; do { - /* tt is busy in the gap before CSPLIT */ tmp = 1 << uf; - mask |= tmp; tmp <<= 8; - if (stream->raw_mask & tmp) - break; + if ((stream->raw_mask & tmp) == 0) + continue; + if (periodic_usecs (ehci, frame, uf) + > max_used) + return 0; } while (++uf < 8); - if (periodic_usecs (ehci, frame, uf) > max_used) - return 0; } /* we know urb->interval is 2^N uframes */ uframe += period_uframes; - uframe %= mod; - } while (uframe != end); - - /* tt must be idle for start(s), any gap, and csplit */ - if (!tt_no_collision (ehci, period_uframes, stream->udev, frame, mask)) - return 0; + } while (uframe < mod); stream->splits = stream->raw_mask << (uframe & 7); cpu_to_le32s (&stream->splits); @@ -1014,7 +1033,7 @@ iso_stream_schedule ( struct ehci_iso_stream *stream ) { - u32 now, start, end, max, period; + u32 now, start, max, period; int status; unsigned mod = ehci->periodic_size << 3; struct ehci_iso_sched *sched = urb->hcpriv; @@ -1036,8 +1055,6 @@ iso_stream_schedule ( /* when's the last uframe this urb could start? */ max = now + mod; - max -= sched->span; - max -= 8 * SCHEDULE_SLOP; /* typical case: reuse current schedule. stream is still active, * and no gaps from host falling behind (irq delays etc) @@ -1046,9 +1063,11 @@ iso_stream_schedule ( start = stream->next_uframe; if (start < now) start += mod; - if (likely (start < max)) + if (likely ((start + sched->span) < max)) goto ready; - /* else fell behind; try to reschedule */ + /* else fell behind; someday, try to reschedule */ + status = -EL2NSYNC; + goto fail; } /* need to schedule; when's the next (u)frame we could start? @@ -1059,63 +1078,40 @@ iso_stream_schedule ( */ start = SCHEDULE_SLOP * 8 + (now & ~0x07); start %= mod; - end = start; + stream->next_uframe = start; /* NOTE: assumes URB_ISO_ASAP, to limit complexity/bugs */ period = urb->interval; if (!stream->highspeed) period <<= 3; - if (max > (start + period)) - max = start + period; - /* hack: account for itds already scheduled to this endpoint */ - if (list_empty (&stream->td_list)) - end = max; - - /* within [start..max] find a uframe slot with enough bandwidth */ - end %= mod; - do { + /* find a uframe slot with enough bandwidth */ + for (; start < (stream->next_uframe + period); start++) { int enough_space; /* check schedule: enough space? */ if (stream->highspeed) - enough_space = itd_slot_ok (ehci, mod, start, end, + enough_space = itd_slot_ok (ehci, mod, start, stream->usecs, period); else { if ((start % 8) >= 6) continue; enough_space = sitd_slot_ok (ehci, mod, stream, - start, end, sched, period); + start, sched, period); } - /* (re)schedule it here if there's enough bandwidth */ + /* schedule it here if there's enough bandwidth */ if (enough_space) { - start %= mod; - if (unlikely (!list_empty (&stream->td_list))) { - /* host fell behind ... maybe irq latencies - * delayed this request queue for too long. - */ - stream->rescheduled++; - dev_dbg (&urb->dev->dev, - "iso%d%s %d.%d skip %d.%d\n", - stream->bEndpointAddress & 0x0f, - (stream->bEndpointAddress & USB_DIR_IN) - ? "in" : "out", - stream->next_uframe >> 3, - stream->next_uframe & 0x7, - start >> 3, start & 0x7); - } - stream->next_uframe = start; + stream->next_uframe = start % mod; goto ready; } - - } while (++start < max); + } /* no room in the schedule */ - ehci_dbg (ehci, "iso %ssched full %p (now %d end %d max %d)\n", + ehci_dbg (ehci, "iso %ssched full %p (now %d max %d)\n", list_empty (&stream->td_list) ? "" : "re", - urb, now, end, max); + urb, now, max); status = -ENOSPC; fail: @@ -1260,6 +1256,7 @@ itd_link_urb ( iso_sched_free (stream, iso_sched); urb->hcpriv = 0; + timer_action (ehci, TIMER_IO_WATCHDOG); if (unlikely (!ehci->periodic_sched++)) return enable_periodic (ehci); return 0; @@ -1404,18 +1401,392 @@ done: return status; } -#ifdef have_split_iso +#ifdef CONFIG_USB_EHCI_SPLIT_ISO /*-------------------------------------------------------------------------*/ /* - * "Split ISO TDs" ... used for USB 1.1 devices going through - * the TTs in USB 2.0 hubs. - * - * FIXME not yet implemented + * "Split ISO TDs" ... used for USB 1.1 devices going through the + * TTs in USB 2.0 hubs. These need microframe scheduling. */ -#endif /* have_split_iso */ +static inline void +sitd_sched_init ( + struct ehci_iso_sched *iso_sched, + struct ehci_iso_stream *stream, + struct urb *urb +) +{ + unsigned i; + dma_addr_t dma = urb->transfer_dma; + + /* how many frames are needed for these transfers */ + iso_sched->span = urb->number_of_packets * stream->interval; + + /* figure out per-frame sitd fields that we'll need later + * when we fit new sitds into the schedule. + */ + for (i = 0; i < urb->number_of_packets; i++) { + struct ehci_iso_packet *packet = &iso_sched->packet [i]; + unsigned length; + dma_addr_t buf; + u32 trans; + + length = urb->iso_frame_desc [i].length & 0x03ff; + buf = dma + urb->iso_frame_desc [i].offset; + + trans = SITD_STS_ACTIVE; + if (((i + 1) == urb->number_of_packets) + && !(urb->transfer_flags & URB_NO_INTERRUPT)) + trans |= SITD_IOC; + trans |= length << 16; + packet->transaction = cpu_to_le32 (trans); + + /* might need to cross a buffer page within a td */ + packet->bufp = buf; + buf += length; + packet->buf1 = buf & ~0x0fff; + if (packet->buf1 != (buf & ~(u64)0x0fff)) + packet->cross = 1; + + /* OUT uses multiple start-splits */ + if (stream->bEndpointAddress & USB_DIR_IN) + continue; + length = 1 + (length / 188); + packet->buf1 |= length; + if (length > 1) /* BEGIN vs ALL */ + packet->buf1 |= 1 << 3; + } +} + +static int +sitd_urb_transaction ( + struct ehci_iso_stream *stream, + struct ehci_hcd *ehci, + struct urb *urb, + int mem_flags +) +{ + struct ehci_sitd *sitd; + dma_addr_t sitd_dma; + int i; + struct ehci_iso_sched *iso_sched; + unsigned long flags; + + iso_sched = iso_sched_alloc (urb->number_of_packets, mem_flags); + if (iso_sched == 0) + return -ENOMEM; + + sitd_sched_init (iso_sched, stream, urb); + + /* allocate/init sITDs */ + spin_lock_irqsave (&ehci->lock, flags); + for (i = 0; i < urb->number_of_packets; i++) { + + /* NOTE: for now, we don't try to handle wraparound cases + * for IN (using sitd->hw_backpointer, like a FSTN), which + * means we never need two sitds for full speed packets. + */ + + /* free_list.next might be cache-hot ... but maybe + * the HC caches it too. avoid that issue for now. + */ + + /* prefer previously-allocated sitds */ + if (!list_empty(&stream->free_list)) { + sitd = list_entry (stream->free_list.prev, + struct ehci_sitd, sitd_list); + list_del (&sitd->sitd_list); + sitd_dma = sitd->sitd_dma; + } else + sitd = 0; + + if (!sitd) { + spin_unlock_irqrestore (&ehci->lock, flags); + sitd = dma_pool_alloc (ehci->sitd_pool, mem_flags, + &sitd_dma); + spin_lock_irqsave (&ehci->lock, flags); + } + + if (!sitd) { + iso_sched_free (stream, iso_sched); + spin_unlock_irqrestore (&ehci->lock, flags); + return -ENOMEM; + } + memset (sitd, 0, sizeof *sitd); + sitd->sitd_dma = sitd_dma; + list_add (&sitd->sitd_list, &iso_sched->td_list); + } + + /* temporarily store schedule info in hcpriv */ + urb->hcpriv = iso_sched; + urb->error_count = 0; + + spin_unlock_irqrestore (&ehci->lock, flags); + return 0; +} + +/*-------------------------------------------------------------------------*/ + +static inline void +sitd_patch ( + struct ehci_iso_stream *stream, + struct ehci_sitd *sitd, + struct ehci_iso_sched *iso_sched, + unsigned index +) +{ + struct ehci_iso_packet *uf = &iso_sched->packet [index]; + u64 bufp = uf->bufp; + + sitd->hw_next = EHCI_LIST_END; + sitd->hw_fullspeed_ep = stream->address; + sitd->hw_uframe = stream->splits; + sitd->hw_results = uf->transaction; + sitd->hw_backpointer = EHCI_LIST_END; + + bufp = uf->bufp; + sitd->hw_buf [0] = cpu_to_le32 (bufp); + sitd->hw_buf_hi [0] = cpu_to_le32 (bufp >> 32); + + sitd->hw_buf [1] = cpu_to_le32 (uf->buf1); + if (uf->cross) { + bufp += 4096; + sitd->hw_buf_hi [1] = cpu_to_le32 (bufp >> 32); + } + sitd->index = index; +} + +static inline void +sitd_link (struct ehci_hcd *ehci, unsigned frame, struct ehci_sitd *sitd) +{ + /* note: sitd ordering could matter (CSPLIT then SSPLIT) */ + sitd->sitd_next = ehci->pshadow [frame]; + sitd->hw_next = ehci->periodic [frame]; + ehci->pshadow [frame].sitd = sitd; + sitd->frame = frame; + wmb (); + ehci->periodic [frame] = cpu_to_le32 (sitd->sitd_dma) | Q_TYPE_SITD; +} + +/* fit urb's sitds into the selected schedule slot; activate as needed */ +static int +sitd_link_urb ( + struct ehci_hcd *ehci, + struct urb *urb, + unsigned mod, + struct ehci_iso_stream *stream +) +{ + int packet; + unsigned next_uframe; + struct ehci_iso_sched *sched = urb->hcpriv; + struct ehci_sitd *sitd; + + next_uframe = stream->next_uframe; + + if (list_empty(&stream->td_list)) { + /* usbfs ignores TT bandwidth */ + hcd_to_bus (&ehci->hcd)->bandwidth_allocated + += stream->bandwidth; + ehci_vdbg (ehci, + "sched dev%s ep%d%s-iso [%d] %dms/%04x\n", + urb->dev->devpath, stream->bEndpointAddress & 0x0f, + (stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out", + (next_uframe >> 3) % ehci->periodic_size, + stream->interval, le32_to_cpu (stream->splits)); + stream->start = jiffies; + } + hcd_to_bus (&ehci->hcd)->bandwidth_isoc_reqs++; + + /* fill sITDs frame by frame */ + for (packet = 0, sitd = 0; + packet < urb->number_of_packets; + packet++) { + + /* ASSERT: we have all necessary sitds */ + BUG_ON (list_empty (&sched->td_list)); + + /* ASSERT: no itds for this endpoint in this frame */ + + sitd = list_entry (sched->td_list.next, + struct ehci_sitd, sitd_list); + list_move_tail (&sitd->sitd_list, &stream->td_list); + sitd->stream = iso_stream_get (stream); + sitd->urb = usb_get_urb (urb); + + sitd_patch (stream, sitd, sched, packet); + sitd_link (ehci, (next_uframe >> 3) % ehci->periodic_size, + sitd); + + next_uframe += stream->interval << 3; + stream->depth += stream->interval << 3; + } + stream->next_uframe = next_uframe % mod; + + /* don't need that schedule data any more */ + iso_sched_free (stream, sched); + urb->hcpriv = 0; + + timer_action (ehci, TIMER_IO_WATCHDOG); + if (!ehci->periodic_sched++) + return enable_periodic (ehci); + return 0; +} + +/*-------------------------------------------------------------------------*/ + +#define SITD_ERRS (SITD_STS_ERR | SITD_STS_DBE | SITD_STS_BABBLE \ + | SITD_STS_XACT | SITD_STS_MMF | SITD_STS_STS) + +static unsigned +sitd_complete ( + struct ehci_hcd *ehci, + struct ehci_sitd *sitd, + struct pt_regs *regs +) { + struct urb *urb = sitd->urb; + struct usb_iso_packet_descriptor *desc; + u32 t; + int urb_index = -1; + struct ehci_iso_stream *stream = sitd->stream; + struct usb_device *dev; + + urb_index = sitd->index; + desc = &urb->iso_frame_desc [urb_index]; + t = le32_to_cpup (&sitd->hw_results); + + /* report transfer status */ + if (t & SITD_ERRS) { + urb->error_count++; + if (t & SITD_STS_DBE) + desc->status = usb_pipein (urb->pipe) + ? -ENOSR /* hc couldn't read */ + : -ECOMM; /* hc couldn't write */ + else if (t & SITD_STS_BABBLE) + desc->status = -EOVERFLOW; + else /* XACT, MMF, etc */ + desc->status = -EPROTO; + } else { + desc->status = 0; + desc->actual_length = desc->length - SITD_LENGTH (t); + } + + usb_put_urb (urb); + sitd->urb = 0; + sitd->stream = 0; + list_move (&sitd->sitd_list, &stream->free_list); + stream->depth -= stream->interval << 3; + iso_stream_put (ehci, stream); + + /* handle completion now? */ + if ((urb_index + 1) != urb->number_of_packets) + return 0; + + /* ASSERT: it's really the last sitd for this urb + list_for_each_entry (sitd, &stream->td_list, sitd_list) + BUG_ON (sitd->urb == urb); + */ + + /* give urb back to the driver */ + dev = usb_get_dev (urb->dev); + ehci_urb_done (ehci, urb, regs); + urb = 0; + + /* defer stopping schedule; completion can submit */ + ehci->periodic_sched--; + if (!ehci->periodic_sched) + (void) disable_periodic (ehci); + hcd_to_bus (&ehci->hcd)->bandwidth_isoc_reqs--; + + if (list_empty (&stream->td_list)) { + hcd_to_bus (&ehci->hcd)->bandwidth_allocated + -= stream->bandwidth; + ehci_vdbg (ehci, + "deschedule devp %s ep%d%s-iso\n", + dev->devpath, stream->bEndpointAddress & 0x0f, + (stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out"); + } + iso_stream_put (ehci, stream); + usb_put_dev (dev); + + return 1; +} + + +static int sitd_submit (struct ehci_hcd *ehci, struct urb *urb, int mem_flags) +{ + int status = -EINVAL; + unsigned long flags; + struct ehci_iso_stream *stream; + + // FIXME remove when csplits behave + if (usb_pipein(urb->pipe)) { + ehci_dbg (ehci, "no iso-IN split transactions yet\n"); + return -ENOMEM; + } + + /* Get iso_stream head */ + stream = iso_stream_find (ehci, urb); + if (stream == 0) { + ehci_dbg (ehci, "can't get iso stream\n"); + return -ENOMEM; + } + if (urb->interval != stream->interval) { + ehci_dbg (ehci, "can't change iso interval %d --> %d\n", + stream->interval, urb->interval); + goto done; + } + +#ifdef EHCI_URB_TRACE + ehci_dbg (ehci, + "submit %p dev%s ep%d%s-iso len %d\n", + urb, urb->dev->devpath, + usb_pipeendpoint (urb->pipe), + usb_pipein (urb->pipe) ? "in" : "out", + urb->transfer_buffer_length); +#endif + + /* allocate SITDs */ + status = sitd_urb_transaction (stream, ehci, urb, mem_flags); + if (status < 0) { + ehci_dbg (ehci, "can't init sitds\n"); + goto done; + } + + /* schedule ... need to lock */ + spin_lock_irqsave (&ehci->lock, flags); + status = iso_stream_schedule (ehci, urb, stream); + if (status == 0) + sitd_link_urb (ehci, urb, ehci->periodic_size << 3, stream); + spin_unlock_irqrestore (&ehci->lock, flags); + +done: + if (status < 0) + iso_stream_put (ehci, stream); + return status; +} + +#else + +static inline int +sitd_submit (struct ehci_hcd *ehci, struct urb *urb, int mem_flags) +{ + ehci_dbg (ehci, "split iso support is disabled\n"); + return -ENOSYS; +} + +static inline unsigned +sitd_complete ( + struct ehci_hcd *ehci, + struct ehci_sitd *sitd, + struct pt_regs *regs +) { + ehci_err (ehci, "sitd_complete %p?\n", sitd); + return 0; +} + +#endif /* USB_EHCI_SPLIT_ISO */ /*-------------------------------------------------------------------------*/ @@ -1513,7 +1884,6 @@ restart: modified = itd_complete (ehci, q.itd, regs); q = *q_p; break; -#ifdef have_split_iso case Q_TYPE_SITD: if (q.sitd->hw_results & SITD_ACTIVE) { q_p = &q.sitd->sitd_next; @@ -1529,7 +1899,6 @@ restart: modified = sitd_complete (ehci, q.sitd, regs); q = *q_p; break; -#endif /* have_split_iso */ default: dbg ("corrupt type %d frame %d shadow %p", type, frame, q.ptr); diff -puN drivers/usb/host/Kconfig~bk-usb drivers/usb/host/Kconfig --- 25/drivers/usb/host/Kconfig~bk-usb 2004-03-10 21:44:00.000000000 -0800 +++ 25-akpm/drivers/usb/host/Kconfig 2004-03-10 21:44:01.000000000 -0800 @@ -29,6 +29,15 @@ config USB_EHCI_HCD To compile this driver as a module, choose M here: the module will be called ehci-hcd. +config USB_EHCI_SPLIT_ISO + bool "Full speed ISO transactions (EXPERIMENTAL)" + depends on USB_EHCI_HCD && EXPERIMENTAL + default n + ---help--- + This code is new and hasn't been used with many different + EHCI or USB 2.0 transaction translator implementations. + It should work for ISO-OUT transfers, like audio. + config USB_OHCI_HCD tristate "OHCI HCD support" depends on USB diff -puN drivers/usb/host/uhci-hcd.c~bk-usb drivers/usb/host/uhci-hcd.c --- 25/drivers/usb/host/uhci-hcd.c~bk-usb 2004-03-10 21:44:00.000000000 -0800 +++ 25-akpm/drivers/usb/host/uhci-hcd.c 2004-03-10 21:44:01.000000000 -0800 @@ -781,7 +781,8 @@ static void uhci_dec_fsbr(struct uhci_hc /* * Map status to standard result codes * - * is (td->status & 0xFE0000) [a.k.a. uhci_status_bits(td->status)] + * is (td->status & 0xF60000) [a.k.a. uhci_status_bits(td->status)] + * Note: status does not include the TD_CTRL_NAK bit. * is True for output TDs and False for input TDs. */ static int uhci_map_status(int status, int dir_out) @@ -792,22 +793,18 @@ static int uhci_map_status(int status, i return -EPROTO; if (status & TD_CTRL_CRCTIMEO) { /* CRC/Timeout */ if (dir_out) - return -ETIMEDOUT; + return -EPROTO; else return -EILSEQ; } - if (status & TD_CTRL_NAK) /* NAK */ - return -ETIMEDOUT; if (status & TD_CTRL_BABBLE) /* Babble */ return -EOVERFLOW; if (status & TD_CTRL_DBUFERR) /* Buffer error */ return -ENOSR; if (status & TD_CTRL_STALLED) /* Stalled */ return -EPIPE; - if (status & TD_CTRL_ACTIVE) /* Active */ - return 0; - - return -EINVAL; + WARN_ON(status & TD_CTRL_ACTIVE); /* Active */ + return 0; } /* @@ -832,7 +829,7 @@ static int uhci_submit_control(struct uh status |= TD_CTRL_LS; /* - * Build the TD for the control request + * Build the TD for the control request setup packet */ td = uhci_alloc_td(uhci, urb->dev); if (!td) @@ -990,13 +987,13 @@ static int uhci_result_control(struct uh if (urbp->short_control_packet) { tmp = head->prev; - goto status_phase; + goto status_stage; } tmp = head->next; td = list_entry(tmp, struct uhci_td, list); - /* The first TD is the SETUP phase, check the status, but skip */ + /* The first TD is the SETUP stage, check the status, but skip */ /* the count */ status = uhci_status_bits(td_status(td)); if (status & TD_CTRL_ACTIVE) @@ -1037,10 +1034,10 @@ static int uhci_result_control(struct uh } } -status_phase: +status_stage: td = list_entry(tmp, struct uhci_td, list); - /* Control status phase */ + /* Control status stage */ status = td_status(td); #ifdef I_HAVE_BUGGY_APC_BACKUPS @@ -1053,10 +1050,11 @@ status_phase: return 0; #endif + status = uhci_status_bits(status); if (status & TD_CTRL_ACTIVE) return -EINPROGRESS; - if (uhci_status_bits(status)) + if (status) goto td_error; return 0; @@ -1273,12 +1271,6 @@ static inline int uhci_submit_interrupt( } /* - * Bulk and interrupt use common result - */ -#define uhci_result_bulk uhci_result_common -#define uhci_result_interrupt uhci_result_common - -/* * Isochronous transfers */ static int isochronous_find_limits(struct uhci_hcd *uhci, struct urb *urb, unsigned int *start, unsigned int *end) @@ -1403,7 +1395,8 @@ static int uhci_result_isochronous(struc urb->iso_frame_desc[i].actual_length = actlength; urb->actual_length += actlength; - status = uhci_map_status(uhci_status_bits(td_status(td)), usb_pipeout(urb->pipe)); + status = uhci_map_status(uhci_status_bits(td_status(td)), + usb_pipeout(urb->pipe)); urb->iso_frame_desc[i].status = status; if (status) { urb->error_count++; @@ -1508,12 +1501,9 @@ static int uhci_urb_enqueue(struct usb_h struct urb_priv *urbp = urb->hcpriv; list_del_init(&urbp->urb_list); - spin_unlock_irqrestore(&uhci->urb_list_lock, flags); - uhci_destroy_urb_priv (uhci, urb); - - return ret; - } - ret = 0; + uhci_destroy_urb_priv(uhci, urb); + } else + ret = 0; out: spin_unlock_irqrestore(&uhci->urb_list_lock, flags); @@ -1541,11 +1531,9 @@ static void uhci_transfer_result(struct case PIPE_CONTROL: ret = uhci_result_control(uhci, urb); break; - case PIPE_INTERRUPT: - ret = uhci_result_interrupt(uhci, urb); - break; case PIPE_BULK: - ret = uhci_result_bulk(uhci, urb); + case PIPE_INTERRUPT: + ret = uhci_result_common(uhci, urb); break; case PIPE_ISOCHRONOUS: ret = uhci_result_isochronous(uhci, urb); @@ -1649,10 +1637,12 @@ static int uhci_urb_dequeue(struct usb_h { struct uhci_hcd *uhci = hcd_to_uhci(hcd); unsigned long flags; - struct urb_priv *urbp = urb->hcpriv; + struct urb_priv *urbp; spin_lock_irqsave(&uhci->urb_list_lock, flags); - + urbp = urb->hcpriv; + if (!urbp) /* URB was never linked! */ + goto done; list_del_init(&urbp->urb_list); uhci_unlink_generic(uhci, urb); @@ -1665,6 +1655,7 @@ static int uhci_urb_dequeue(struct usb_h list_add_tail(&urbp->urb_list, &uhci->urb_remove_list); spin_unlock(&uhci->urb_remove_list_lock); +done: spin_unlock_irqrestore(&uhci->urb_list_lock, flags); return 0; } @@ -1861,17 +1852,12 @@ static void uhci_finish_completion(struc static void uhci_remove_pending_urbps(struct uhci_hcd *uhci) { - struct list_head *tmp, *head; - spin_lock(&uhci->urb_remove_list_lock); - head = &uhci->urb_remove_list; - tmp = head->next; - while (tmp != head) { - struct urb_priv *urbp = list_entry(tmp, struct urb_priv, urb_list); + spin_lock(&uhci->complete_list_lock); - tmp = tmp->next; - uhci_moveto_complete(uhci, urbp); - } + /* Splice the urb_remove_list onto the end of the complete_list */ + list_splice_init(&uhci->urb_remove_list, uhci->complete_list.prev); + spin_unlock(&uhci->complete_list_lock); spin_unlock(&uhci->urb_remove_list_lock); } @@ -2458,9 +2444,11 @@ static int uhci_suspend(struct usb_hcd * struct uhci_hcd *uhci = hcd_to_uhci(hcd); /* Don't try to suspend broken motherboards, reset instead */ - if (suspend_allowed(uhci)) + if (suspend_allowed(uhci)) { suspend_hc(uhci); - else + uhci->saved_framenumber = + inw(uhci->io_addr + USBFRNUM) & 0x3ff; + } else reset_hc(uhci); return 0; } @@ -2471,9 +2459,20 @@ static int uhci_resume(struct usb_hcd *h 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; - else { + } else { reset_hc(uhci); start_hc(uhci); } diff -puN drivers/usb/host/uhci-hcd.h~bk-usb drivers/usb/host/uhci-hcd.h --- 25/drivers/usb/host/uhci-hcd.h~bk-usb 2004-03-10 21:44:00.000000000 -0800 +++ 25-akpm/drivers/usb/host/uhci-hcd.h 2004-03-10 21:44:01.000000000 -0800 @@ -141,7 +141,7 @@ struct uhci_qh { TD_CTRL_BABBLE | TD_CTRL_CRCTIME | TD_CTRL_BITSTUFF) #define uhci_maxerr(err) ((err) << TD_CTRL_C_ERR_SHIFT) -#define uhci_status_bits(ctrl_sts) ((ctrl_sts) & 0xFE0000) +#define uhci_status_bits(ctrl_sts) ((ctrl_sts) & 0xF60000) #define uhci_actual_length(ctrl_sts) (((ctrl_sts) + 1) & TD_CTRL_ACTLEN_MASK) /* 1-based */ /* @@ -350,6 +350,7 @@ struct uhci_hcd { enum uhci_state state; /* FIXME: needs a spinlock */ unsigned long state_end; /* Time of next transition */ 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 */ spinlock_t urb_list_lock; diff -puN drivers/usb/image/hpusbscsi.c~bk-usb drivers/usb/image/hpusbscsi.c --- 25/drivers/usb/image/hpusbscsi.c~bk-usb 2004-03-10 21:44:00.000000000 -0800 +++ 25-akpm/drivers/usb/image/hpusbscsi.c 2004-03-10 21:44:01.000000000 -0800 @@ -42,7 +42,7 @@ hpusbscsi_usb_probe(struct usb_interface const struct usb_device_id *id) { 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; int error = -ENOMEM; int i; diff -puN drivers/usb/image/mdc800.c~bk-usb drivers/usb/image/mdc800.c --- 25/drivers/usb/image/mdc800.c~bk-usb 2004-03-10 21:44:00.000000000 -0800 +++ 25-akpm/drivers/usb/image/mdc800.c 2004-03-10 21:44:01.000000000 -0800 @@ -431,7 +431,7 @@ static int mdc800_usb_probe (struct usb_ err ("probe fails -> wrong Number of Configuration"); return -ENODEV; } - intf_desc = &intf->altsetting[0]; + intf_desc = intf->cur_altsetting; if ( ( intf_desc->desc.bInterfaceClass != 0xff ) @@ -469,13 +469,6 @@ static int mdc800_usb_probe (struct usb_ } - 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."); down (&mdc800->io_lock); @@ -551,8 +544,6 @@ static void mdc800_usb_disconnect (struc usb_unlink_urb (mdc800->write_urb); usb_unlink_urb (mdc800->download_urb); - usb_driver_release_interface (&mdc800_usb_driver, intf); - mdc800->dev=0; usb_set_intfdata(intf, NULL); } diff -puN drivers/usb/image/microtek.c~bk-usb drivers/usb/image/microtek.c --- 25/drivers/usb/image/microtek.c~bk-usb 2004-03-10 21:44:00.000000000 -0800 +++ 25-akpm/drivers/usb/image/microtek.c 2004-03-10 21:44:01.000000000 -0800 @@ -693,7 +693,6 @@ static int mts_usb_probe(struct usb_inte const struct usb_device_id *id) { int i; - int result; int ep_out = -1; int ep_in_set[3]; /* this will break if we have more than three endpoints which is why we check */ @@ -703,7 +702,7 @@ static int mts_usb_probe(struct usb_inte struct vendor_product const* p; 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; MTS_DEBUG_GOT_HERE(); @@ -724,8 +723,8 @@ static int mts_usb_probe(struct usb_inte MTS_MESSAGE( "model %s is not known to be fully supported, reports welcome!\n", p->name ); - /* the altsettting 0 on the interface we're probing */ - altsetting = &(intf->altsetting[0]); + /* the current altsetting on the interface we're probing */ + altsetting = intf->cur_altsetting; /* Check if the config is sane */ @@ -766,20 +765,6 @@ static int mts_usb_probe(struct usb_inte MTS_WARNING( "couldn't find an output bulk endpoint. Bailing out.\n" ); 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); diff -puN drivers/usb/input/aiptek.c~bk-usb drivers/usb/input/aiptek.c --- 25/drivers/usb/input/aiptek.c~bk-usb 2004-03-10 21:44:00.000000000 -0800 +++ 25-akpm/drivers/usb/input/aiptek.c 2004-03-10 21:44:01.000000000 -0800 @@ -43,7 +43,8 @@ #include #include #include - +#include +#include /* * Version Information */ @@ -160,9 +161,9 @@ aiptek_irq(struct urb *urb, struct pt_re proximity = data[5] & 0x01; input_report_key(dev, BTN_TOOL_PEN, proximity); - x = ((__u32) data[1]) | ((__u32) data[2] << 8); - y = ((__u32) data[3]) | ((__u32) data[4] << 8); - pressure = ((__u32) data[6]) | ((__u32) data[7] << 8); + x = le16_to_cpu(get_unaligned((u16 *) &data[1])); + y = le16_to_cpu(get_unaligned((u16 *) &data[3])); + pressure = le16_to_cpu(*(u16 *) &data[6]); pressure -= aiptek->features->pressure_min; if (pressure < 0) { @@ -209,8 +210,10 @@ aiptek_open(struct input_dev *dev) return 0; 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 0; } @@ -234,19 +237,27 @@ usb_set_report(struct usb_device *dev, s (type << 8) + id, inter->desc.bInterfaceNumber, buf, size, HZ); } -static void +static int aiptek_command(struct usb_device *dev, struct usb_host_interface *inter, 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[1] = command; 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); } + + kfree(buf); + return err < 0 ? err : 0; } static int @@ -257,30 +268,32 @@ aiptek_probe(struct usb_interface *intf, struct usb_host_interface *interface = intf->altsetting + 0; struct usb_endpoint_descriptor *endpoint; struct aiptek *aiptek; + int err = -ENOMEM; if (!(aiptek = kmalloc(sizeof (struct aiptek), GFP_KERNEL))) - return -ENOMEM; + goto error_out_noalloc; 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) { - kfree(aiptek); - return -ENOMEM; + goto error_out_nobuf; } aiptek->irq = usb_alloc_urb(0, GFP_KERNEL); if (!aiptek->irq) { - usb_buffer_free(dev, 10, aiptek->data, aiptek->data_dma); - kfree(aiptek); - return -ENOMEM; + goto error_out_nourb; } /* Resolution500LPI */ - aiptek_command(dev, interface, 0x18, 0x04); + err = aiptek_command(dev, interface, 0x18, 0x04); + if (err) + goto error_out; /* 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; @@ -340,6 +353,16 @@ aiptek_probe(struct usb_interface *intf, usb_set_intfdata(intf, aiptek); 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 diff -puN /dev/null drivers/usb/input/ati_remote.c --- /dev/null 2002-08-30 16:31:37.000000000 -0700 +++ 25-akpm/drivers/usb/input/ati_remote.c 2004-03-10 21:44:01.000000000 -0800 @@ -0,0 +1,851 @@ +/* + * USB ATI Remote support + * + * Version 2.2.0 Copyright (c) 2004 Torrey Hoffman + * Version 2.1.1 Copyright (c) 2002 Vladimir Dergachev + * + * This 2.2.0 version is a rewrite / cleanup of the 2.1.1 driver, including + * porting to the 2.6 kernel interfaces, along with other modification + * to better match the style of the existing usb/input drivers. However, the + * protocol and hardware handling is essentially unchanged from 2.1.1. + * + * The 2.1.1 driver was derived from the usbati_remote and usbkbd drivers by + * Vojtech Pavlik. + * + * Changes: + * + * Feb 2004: Torrey Hoffman + * Version 2.2.0 + * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * + * 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 + * + * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * + * + * Hardware & software notes + * + * These remote controls are distributed by ATI as part of their + * "All-In-Wonder" video card packages. The receiver self-identifies as a + * "USB Receiver" with manufacturer "X10 Wireless Technology Inc". + * + * It is possible to use multiple receivers and remotes on multiple computers + * simultaneously by configuring them to use specific channels. + * + * The RF protocol used by the remote supports 16 distinct channels, 1 to 16. + * Actually, it may even support more, at least in some revisions of the + * hardware. + * + * Each remote can be configured to transmit on one channel as follows: + * - Press and hold the "hand icon" button. + * - When the red LED starts to blink, let go of the "hand icon" button. + * - When it stops blinking, input the channel code as two digits, from 01 + * to 16, and press the hand icon again. + * + * The timing can be a little tricky. Try loading the module with debug=1 + * to have the kernel print out messages about the remote control number + * and mask. Note: debugging prints remote numbers as zero-based hexadecimal. + * + * The driver has a "channel_mask" parameter. This bitmask specifies which + * channels will be ignored by the module. To mask out channels, just add + * all the 2^channel_number values together. + * + * For instance, set channel_mask = 2^4 = 16 (binary 10000) to make ati_remote + * ignore signals coming from remote controls transmitting on channel 4, but + * accept all other channels. + * + * Or, set channel_mask = 65533, (0xFFFD), and all channels except 1 will be + * ignored. + * + * The default is 0 (respond to all channels). Bit 0 and bits 17-32 of this + * parameter are unused. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * Module and Version Information, Module Parameters + */ + +#define ATI_REMOTE_VENDOR_ID 0x0bc7 +#define ATI_REMOTE_PRODUCT_ID 0x004 + +#define DRIVER_VERSION "2.2.0" +#define DRIVER_AUTHOR "Torrey Hoffman " +#define DRIVER_DESC "ATI/X10 RF USB Remote Control" + +#define NAME_BUFSIZE 80 /* size of product name, path buffers */ +#define DATA_BUFSIZE 63 /* size of URB data buffers */ +#define ATI_INPUTNUM 1 /* Which input device to register as */ + +unsigned long channel_mask = 0; +module_param(channel_mask, ulong, 444); +MODULE_PARM_DESC(channel_mask, "Bitmask of remote control channels to ignore"); + +static int debug = 0; +module_param(debug, int, 444); +MODULE_PARM_DESC(debug, "Enable extra debug messages and information"); + +#define dbginfo(dev, format, arg...) do { if (debug) dev_info(dev , format , ## arg); } while (0) +#undef err +#define err(format, arg...) printk(KERN_ERR format , ## arg) + +static struct usb_device_id ati_remote_table[] = { + { USB_DEVICE(ATI_REMOTE_VENDOR_ID, ATI_REMOTE_PRODUCT_ID) }, + {} /* Terminating entry */ +}; + +MODULE_DEVICE_TABLE(usb, ati_remote_table); + +/* Get hi and low bytes of a 16-bits int */ +#define HI(a) ((unsigned char)((a) >> 8)) +#define LO(a) ((unsigned char)((a) & 0xff)) + +#define SEND_FLAG_IN_PROGRESS 1 +#define SEND_FLAG_COMPLETE 2 + +/* Device initialization strings */ +static char init1[] = { 0x01, 0x00, 0x20, 0x14 }; +static char init2[] = { 0x01, 0x00, 0x20, 0x14, 0x20, 0x20, 0x20 }; + +/* Acceleration curve for directional control pad */ +static char accel[] = { 1, 2, 4, 6, 9, 13, 20 }; + +/* Duplicate event filtering time. + * Sequential, identical KIND_FILTERED inputs with less than + * FILTER_TIME jiffies between them are dropped. + * (HZ >> 4) == 1/16th of a second and works well for me. + */ +#define FILTER_TIME (HZ >> 4) + +struct ati_remote { + struct input_dev idev; + struct usb_device *udev; + struct usb_interface *interface; + + struct urb *irq_urb; + struct urb *out_urb; + struct usb_endpoint_descriptor *endpoint_in; + struct usb_endpoint_descriptor *endpoint_out; + unsigned char *inbuf; + unsigned char *outbuf; + dma_addr_t inbuf_dma; + dma_addr_t outbuf_dma; + + int open; /* open counter */ + int present; /* device plugged in? */ + + unsigned char old_data[2]; /* Detect duplicate events */ + unsigned long old_jiffies; + unsigned long acc_jiffies; /* handle acceleration */ + + char name[NAME_BUFSIZE]; + char phys[NAME_BUFSIZE]; + + wait_queue_head_t wait; + int send_flags; +}; + +/* "Kinds" of messages sent from the hardware to the driver. */ +#define KIND_END 0 +#define KIND_LITERAL 1 /* Simply pass to input system */ +#define KIND_FILTERED 2 /* Add artificial key-up events, drop keyrepeats */ +#define KIND_LU 3 /* Directional keypad diagonals - left up, */ +#define KIND_RU 4 /* right up, */ +#define KIND_LD 5 /* left down, */ +#define KIND_RD 6 /* right down */ +#define KIND_ACCEL 7 /* Directional keypad - left, right, up, down.*/ + +/* Translation table from hardware messages to input events. */ +static struct +{ + short kind; + unsigned char data1, data2; + int type; + unsigned int code; + int value; +} ati_remote_tbl[] = +{ + /* Directional control pad axes */ + {KIND_ACCEL, 0x35, 0x70, EV_REL, REL_X, -1}, /* left */ + {KIND_ACCEL, 0x36, 0x71, EV_REL, REL_X, 1}, /* right */ + {KIND_ACCEL, 0x37, 0x72, EV_REL, REL_Y, -1}, /* up */ + {KIND_ACCEL, 0x38, 0x73, EV_REL, REL_Y, 1}, /* down */ + /* Directional control pad diagonals */ + {KIND_LU, 0x39, 0x74, EV_REL, 0, 0}, /* left up */ + {KIND_RU, 0x3a, 0x75, EV_REL, 0, 0}, /* right up */ + {KIND_LD, 0x3c, 0x77, EV_REL, 0, 0}, /* left down */ + {KIND_RD, 0x3b, 0x76, EV_REL, 0, 0}, /* right down */ + + /* "Mouse button" buttons */ + {KIND_LITERAL, 0x3d, 0x78, EV_KEY, BTN_LEFT, 1}, /* left btn down */ + {KIND_LITERAL, 0x3e, 0x79, EV_KEY, BTN_LEFT, 0}, /* left btn up */ + {KIND_LITERAL, 0x41, 0x7c, EV_KEY, BTN_RIGHT, 1},/* right btn down */ + {KIND_LITERAL, 0x42, 0x7d, EV_KEY, BTN_RIGHT, 0},/* right btn up */ + + /* Artificial "doubleclick" events are generated by the hardware. + * They are mapped to the "side" and "extra" mouse buttons here. */ + {KIND_FILTERED, 0x3f, 0x7a, EV_KEY, BTN_SIDE, 1}, /* left dblclick */ + {KIND_FILTERED, 0x43, 0x7e, EV_KEY, BTN_EXTRA, 1},/* right dblclick */ + + /* keyboard. */ + {KIND_FILTERED, 0xd2, 0x0d, EV_KEY, KEY_1, 1}, + {KIND_FILTERED, 0xd3, 0x0e, EV_KEY, KEY_2, 1}, + {KIND_FILTERED, 0xd4, 0x0f, EV_KEY, KEY_3, 1}, + {KIND_FILTERED, 0xd5, 0x10, EV_KEY, KEY_4, 1}, + {KIND_FILTERED, 0xd6, 0x11, EV_KEY, KEY_5, 1}, + {KIND_FILTERED, 0xd7, 0x12, EV_KEY, KEY_6, 1}, + {KIND_FILTERED, 0xd8, 0x13, EV_KEY, KEY_7, 1}, + {KIND_FILTERED, 0xd9, 0x14, EV_KEY, KEY_8, 1}, + {KIND_FILTERED, 0xda, 0x15, EV_KEY, KEY_9, 1}, + {KIND_FILTERED, 0xdc, 0x17, EV_KEY, KEY_0, 1}, + {KIND_FILTERED, 0xc5, 0x00, EV_KEY, KEY_A, 1}, + {KIND_FILTERED, 0xc6, 0x01, EV_KEY, KEY_B, 1}, + {KIND_FILTERED, 0xde, 0x19, EV_KEY, KEY_C, 1}, + {KIND_FILTERED, 0xe0, 0x1b, EV_KEY, KEY_D, 1}, + {KIND_FILTERED, 0xe6, 0x21, EV_KEY, KEY_E, 1}, + {KIND_FILTERED, 0xe8, 0x23, EV_KEY, KEY_F, 1}, + + /* "special" keys */ + {KIND_FILTERED, 0xdd, 0x18, EV_KEY, KEY_KPENTER, 1}, /* "check" */ + {KIND_FILTERED, 0xdb, 0x16, EV_KEY, KEY_MENU, 1}, /* "menu" */ + {KIND_FILTERED, 0xc7, 0x02, EV_KEY, KEY_POWER, 1}, /* Power */ + {KIND_FILTERED, 0xc8, 0x03, EV_KEY, KEY_PROG1, 1}, /* TV */ + {KIND_FILTERED, 0xc9, 0x04, EV_KEY, KEY_PROG2, 1}, /* DVD */ + {KIND_FILTERED, 0xca, 0x05, EV_KEY, KEY_WWW, 1}, /* WEB */ + {KIND_FILTERED, 0xcb, 0x06, EV_KEY, KEY_BOOKMARKS, 1}, /* "book" */ + {KIND_FILTERED, 0xcc, 0x07, EV_KEY, KEY_EDIT, 1}, /* "hand" */ + {KIND_FILTERED, 0xe1, 0x1c, EV_KEY, KEY_COFFEE, 1}, /* "timer" */ + {KIND_FILTERED, 0xe5, 0x20, EV_KEY, KEY_FRONT, 1}, /* "max" */ + {KIND_FILTERED, 0xe2, 0x1d, EV_KEY, KEY_LEFT, 1}, /* left */ + {KIND_FILTERED, 0xe4, 0x1f, EV_KEY, KEY_RIGHT, 1}, /* right */ + {KIND_FILTERED, 0xe7, 0x22, EV_KEY, KEY_DOWN, 1}, /* down */ + {KIND_FILTERED, 0xdf, 0x1a, EV_KEY, KEY_UP, 1}, /* up */ + {KIND_FILTERED, 0xe3, 0x1e, EV_KEY, KEY_ENTER, 1}, /* "OK" */ + {KIND_FILTERED, 0xce, 0x09, EV_KEY, KEY_VOLUMEDOWN, 1}, /* VOL + */ + {KIND_FILTERED, 0xcd, 0x08, EV_KEY, KEY_VOLUMEUP, 1}, /* VOL - */ + {KIND_FILTERED, 0xcf, 0x0a, EV_KEY, KEY_MUTE, 1}, /* MUTE */ + {KIND_FILTERED, 0xd1, 0x0c, EV_KEY, KEY_CHANNELUP, 1}, /* CH + */ + {KIND_FILTERED, 0xd0, 0x0b, EV_KEY, KEY_CHANNELDOWN, 1},/* CH - */ + {KIND_FILTERED, 0xec, 0x27, EV_KEY, KEY_RECORD, 1}, /* ( o) red */ + {KIND_FILTERED, 0xea, 0x25, EV_KEY, KEY_PLAYCD, 1}, /* ( >) */ + {KIND_FILTERED, 0xe9, 0x24, EV_KEY, KEY_REWIND, 1}, /* (<<) */ + {KIND_FILTERED, 0xeb, 0x26, EV_KEY, KEY_FORWARD, 1}, /* (>>) */ + {KIND_FILTERED, 0xed, 0x28, EV_KEY, KEY_STOP, 1}, /* ([]) */ + {KIND_FILTERED, 0xee, 0x29, EV_KEY, KEY_PAUSE, 1}, /* ('') */ + + {KIND_END, 0x00, 0x00, EV_MAX + 1, 0, 0} +}; + +/* Local function prototypes */ +static void ati_remote_dump (unsigned char *data, unsigned int actual_length); +static void ati_remote_delete (struct ati_remote *dev); +static int ati_remote_open (struct input_dev *inputdev); +static void ati_remote_close (struct input_dev *inputdev); +static int ati_remote_sendpacket (struct ati_remote *ati_remote, u16 cmd, unsigned char *data); +static void ati_remote_irq_out (struct urb *urb, struct pt_regs *regs); +static void ati_remote_irq_in (struct urb *urb, struct pt_regs *regs); +static void ati_remote_input_report (struct urb *urb, struct pt_regs *regs); +static int ati_remote_initialize (struct ati_remote *ati_remote); +static int ati_remote_probe (struct usb_interface *interface, const struct usb_device_id *id); +static void ati_remote_disconnect (struct usb_interface *interface); + +/* usb specific object to register with the usb subsystem */ +static struct usb_driver ati_remote_driver = { + .owner = THIS_MODULE, + .name = "ati_remote", + .probe = ati_remote_probe, + .disconnect = ati_remote_disconnect, + .id_table = ati_remote_table, +}; + +/* + * ati_remote_dump_input + */ +static void ati_remote_dump(unsigned char *data, unsigned int len) +{ + if ((len == 1) && (data[0] != (unsigned char)0xff) && (data[0] != 0x00)) + warn("Weird byte 0x%02x\n", data[0]); + else if (len == 4) + warn("Weird key %02x %02x %02x %02x\n", + data[0], data[1], data[2], data[3]); + else + warn("Weird data, len=%d %02x %02x %02x %02x %02x %02x ...\n", + len, data[0], data[1], data[2], data[3], data[4], data[5]); +} + +/* + * ati_remote_open + */ +static int ati_remote_open(struct input_dev *inputdev) +{ + struct ati_remote *ati_remote = inputdev->private; + + if (ati_remote->open++) + return 0; + + /* On first open, submit the read urb which was set up previously. */ + ati_remote->irq_urb->dev = ati_remote->udev; + if (usb_submit_urb(ati_remote->irq_urb, GFP_KERNEL)) { + dev_err(&ati_remote->interface->dev, + "%s: usb_submit_urb failed!\n", __FUNCTION__); + ati_remote->open--; + return -EIO; + } + + return 0; +} + +/* + * ati_remote_close + */ +static void ati_remote_close(struct input_dev *inputdev) +{ + struct ati_remote *ati_remote = inputdev->private; + + if (ati_remote == NULL) { + err("ati_remote: %s: object is NULL!\n", __FUNCTION__); + return; + } + + if (ati_remote->open <= 0) + dev_dbg(&ati_remote->interface->dev, "%s: Not open.\n", __FUNCTION__); + else + --ati_remote->open; + + /* If still present, disconnect will call delete. */ + if (!ati_remote->present && !ati_remote->open) + ati_remote_delete(ati_remote); +} + +/* + * ati_remote_irq_out + */ +static void ati_remote_irq_out(struct urb *urb, struct pt_regs *regs) +{ + struct ati_remote *ati_remote = urb->context; + + if (urb->status) { + dev_dbg(&ati_remote->interface->dev, "%s: status %d\n", + __FUNCTION__, urb->status); + return; + } + + ati_remote->send_flags |= SEND_FLAG_COMPLETE; + wmb(); + if (waitqueue_active(&ati_remote->wait)) + wake_up(&ati_remote->wait); +} + +/* + * ati_remote_sendpacket + * + * Used to send device initialization strings + */ +static int ati_remote_sendpacket(struct ati_remote *ati_remote, u16 cmd, unsigned char *data) +{ + DECLARE_WAITQUEUE(wait, current); + int timeout = HZ; /* 1 second */ + int retval = 0; + + /* Set up out_urb */ + memcpy(ati_remote->out_urb->transfer_buffer + 1, data, LO(cmd)); + ((char *) ati_remote->out_urb->transfer_buffer)[0] = HI(cmd); + + ati_remote->out_urb->transfer_buffer_length = LO(cmd) + 1; + ati_remote->out_urb->dev = ati_remote->udev; + ati_remote->send_flags = SEND_FLAG_IN_PROGRESS; + + set_current_state(TASK_INTERRUPTIBLE); + add_wait_queue(&ati_remote->wait, &wait); + + retval = usb_submit_urb(ati_remote->out_urb, GFP_KERNEL); + if (retval) { + set_current_state(TASK_RUNNING); + remove_wait_queue(&ati_remote->wait, &wait); + dev_dbg(&ati_remote->interface->dev, + "sendpacket: usb_submit_urb failed: %d\n", retval); + return retval; + } + + while (timeout && (ati_remote->out_urb->status == -EINPROGRESS) + && !(ati_remote->send_flags & SEND_FLAG_COMPLETE)) { + timeout = schedule_timeout(timeout); + rmb(); + } + + set_current_state(TASK_RUNNING); + remove_wait_queue(&ati_remote->wait, &wait); + usb_unlink_urb(ati_remote->out_urb); + + return retval; +} + +/* + * ati_remote_event_lookup + */ +static int ati_remote_event_lookup(int rem, unsigned char d1, unsigned char d2) +{ + int i; + + for (i = 0; ati_remote_tbl[i].kind != KIND_END; i++) { + /* + * Decide if the table entry matches the remote input. + */ + if ((((ati_remote_tbl[i].data1 & 0x0f) == (d1 & 0x0f))) && + ((((ati_remote_tbl[i].data1 >> 4) - + (d1 >> 4) + rem) & 0x0f) == 0x0f) && + (ati_remote_tbl[i].data2 == d2)) + return i; + + } + return -1; +} + +/* + * ati_remote_report_input + */ +static void ati_remote_input_report(struct urb *urb, struct pt_regs *regs) +{ + struct ati_remote *ati_remote = urb->context; + unsigned char *data= ati_remote->inbuf; + struct input_dev *dev = &ati_remote->idev; + int index, acc; + int remote_num; + + /* Deal with strange looking inputs */ + if ( (urb->actual_length != 4) || (data[0] != 0x14) || + ((data[3] & 0x0f) != 0x00) ) { + ati_remote_dump(data, urb->actual_length); + return; + } + + /* Mask unwanted remote channels. */ + /* note: remote_num is 0-based, channel 1 on remote == 0 here */ + remote_num = (data[3] >> 4) & 0x0f; + if (channel_mask & (1 << (remote_num + 1))) { + dbginfo(&ati_remote->interface->dev, + "Masked input from channel 0x%02x: data %02x,%02x, mask= 0x%02lx\n", + remote_num, data[1], data[2], channel_mask); + return; + } + + /* Look up event code index in translation table */ + index = ati_remote_event_lookup(remote_num, data[1], data[2]); + if (index < 0) { + dev_warn(&ati_remote->interface->dev, + "Unknown input from channel 0x%02x: data %02x,%02x\n", + remote_num, data[1], data[2]); + return; + } + dbginfo(&ati_remote->interface->dev, + "channel 0x%02x; data %02x,%02x; index %d; keycode %d\n", + remote_num, data[1], data[2], index, ati_remote_tbl[index].code); + + if (ati_remote_tbl[index].kind == KIND_LITERAL) { + input_regs(dev, regs); + input_event(dev, ati_remote_tbl[index].type, + ati_remote_tbl[index].code, + ati_remote_tbl[index].value); + input_sync(dev); + + ati_remote->old_jiffies = jiffies; + return; + } + + if (ati_remote_tbl[index].kind == KIND_FILTERED) { + /* Filter duplicate events which happen "too close" together. */ + if ((ati_remote->old_data[0] == data[1]) && + (ati_remote->old_data[1] == data[2]) && + ((ati_remote->old_jiffies + FILTER_TIME) > jiffies)) { + ati_remote->old_jiffies = jiffies; + return; + } + + input_regs(dev, regs); + input_event(dev, ati_remote_tbl[index].type, + ati_remote_tbl[index].code, 1); + input_event(dev, ati_remote_tbl[index].type, + ati_remote_tbl[index].code, 0); + input_sync(dev); + + ati_remote->old_data[0] = data[1]; + ati_remote->old_data[1] = data[2]; + ati_remote->old_jiffies = jiffies; + return; + } + + /* + * Other event kinds are from the directional control pad, and have an + * acceleration factor applied to them. Without this acceleration, the + * control pad is mostly unusable. + * + * If elapsed time since last event is > 1/4 second, user "stopped", + * so reset acceleration. Otherwise, user is probably holding the control + * pad down, so we increase acceleration, ramping up over two seconds to + * a maximum speed. The acceleration curve is #defined above. + */ + if ((jiffies - ati_remote->old_jiffies) > (HZ >> 2)) { + acc = 1; + ati_remote->acc_jiffies = jiffies; + } + else if ((jiffies - ati_remote->acc_jiffies) < (HZ >> 3)) acc = accel[0]; + else if ((jiffies - ati_remote->acc_jiffies) < (HZ >> 2)) acc = accel[1]; + else if ((jiffies - ati_remote->acc_jiffies) < (HZ >> 1)) acc = accel[2]; + else if ((jiffies - ati_remote->acc_jiffies) < HZ ) acc = accel[3]; + else if ((jiffies - ati_remote->acc_jiffies) < HZ+(HZ>>1)) acc = accel[4]; + else if ((jiffies - ati_remote->acc_jiffies) < (HZ << 1)) acc = accel[5]; + else acc = accel[6]; + + input_regs(dev, regs); + switch (ati_remote_tbl[index].kind) { + case KIND_ACCEL: + input_event(dev, ati_remote_tbl[index].type, + ati_remote_tbl[index].code, + ati_remote_tbl[index].value * acc); + break; + case KIND_LU: + input_report_rel(dev, REL_X, -acc); + input_report_rel(dev, REL_Y, -acc); + break; + case KIND_RU: + input_report_rel(dev, REL_X, acc); + input_report_rel(dev, REL_Y, -acc); + break; + case KIND_LD: + input_report_rel(dev, REL_X, -acc); + input_report_rel(dev, REL_Y, acc); + break; + case KIND_RD: + input_report_rel(dev, REL_X, acc); + input_report_rel(dev, REL_Y, acc); + break; + default: + dev_dbg(&ati_remote->interface->dev, "ati_remote kind=%d\n", + ati_remote_tbl[index].kind); + } + input_sync(dev); + + ati_remote->old_jiffies = jiffies; + ati_remote->old_data[0] = data[1]; + ati_remote->old_data[1] = data[2]; +} + +/* + * ati_remote_irq_in + */ +static void ati_remote_irq_in(struct urb *urb, struct pt_regs *regs) +{ + struct ati_remote *ati_remote = urb->context; + int retval; + + switch (urb->status) { + case 0: /* success */ + ati_remote_input_report(urb, regs); + break; + case -ECONNRESET: /* unlink */ + case -ENOENT: + case -ESHUTDOWN: + dev_dbg(&ati_remote->interface->dev, "%s: urb error status, unlink? \n", + __FUNCTION__); + return; + default: /* error */ + dev_dbg(&ati_remote->interface->dev, "%s: Nonzero urb status %d\n", + __FUNCTION__, urb->status); + } + + retval = usb_submit_urb(urb, SLAB_ATOMIC); + if (retval) + dev_err(&ati_remote->interface->dev, "%s: usb_submit_urb()=%d\n", + __FUNCTION__, retval); +} + +/* + * ati_remote_delete + */ +static void ati_remote_delete(struct ati_remote *ati_remote) +{ + if (!ati_remote) return; + + if (ati_remote->irq_urb) + usb_unlink_urb(ati_remote->irq_urb); + + if (ati_remote->out_urb) + usb_unlink_urb(ati_remote->out_urb); + + if (ati_remote->irq_urb) + usb_free_urb(ati_remote->irq_urb); + + if (ati_remote->out_urb) + usb_free_urb(ati_remote->out_urb); + + if (ati_remote->inbuf) + usb_buffer_free(ati_remote->udev, DATA_BUFSIZE, + ati_remote->inbuf, ati_remote->inbuf_dma); + + if (ati_remote->outbuf) + usb_buffer_free(ati_remote->udev, DATA_BUFSIZE, + ati_remote->inbuf, ati_remote->outbuf_dma); + + kfree(ati_remote); +} + +static void ati_remote_input_init(struct ati_remote *ati_remote) +{ + struct input_dev *idev = &(ati_remote->idev); + int i; + + idev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL); + idev->keybit[LONG(BTN_MOUSE)] = ( BIT(BTN_LEFT) | BIT(BTN_RIGHT) | + BIT(BTN_SIDE) | BIT(BTN_EXTRA) ); + idev->relbit[0] = BIT(REL_X) | BIT(REL_Y); + for (i = 0; ati_remote_tbl[i].kind != KIND_END; i++) + if (ati_remote_tbl[i].type == EV_KEY) + set_bit(ati_remote_tbl[i].code, idev->keybit); + + idev->private = ati_remote; + idev->open = ati_remote_open; + idev->close = ati_remote_close; + + idev->name = ati_remote->name; + idev->phys = ati_remote->phys; + + idev->id.bustype = BUS_USB; + idev->id.vendor = ati_remote->udev->descriptor.idVendor; + idev->id.product = ati_remote->udev->descriptor.idProduct; + idev->id.version = ati_remote->udev->descriptor.bcdDevice; +} + +static int ati_remote_initialize(struct ati_remote *ati_remote) +{ + struct usb_device *udev = ati_remote->udev; + int pipe, maxp; + + init_waitqueue_head(&ati_remote->wait); + + /* Set up irq_urb */ + pipe = usb_rcvintpipe(udev, ati_remote->endpoint_in->bEndpointAddress); + maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe)); + maxp = (maxp > DATA_BUFSIZE) ? DATA_BUFSIZE : maxp; + + usb_fill_int_urb(ati_remote->irq_urb, udev, pipe, ati_remote->inbuf, + maxp, ati_remote_irq_in, ati_remote, + ati_remote->endpoint_in->bInterval); + ati_remote->irq_urb->transfer_dma = ati_remote->inbuf_dma; + ati_remote->irq_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; + + /* Set up out_urb */ + pipe = usb_sndintpipe(udev, ati_remote->endpoint_out->bEndpointAddress); + maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe)); + maxp = (maxp > DATA_BUFSIZE) ? DATA_BUFSIZE : maxp; + + usb_fill_int_urb(ati_remote->out_urb, udev, pipe, ati_remote->outbuf, + maxp, ati_remote_irq_out, ati_remote, + ati_remote->endpoint_out->bInterval); + ati_remote->out_urb->transfer_dma = ati_remote->outbuf_dma; + ati_remote->out_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; + + /* send initialization strings */ + if ((ati_remote_sendpacket(ati_remote, 0x8004, init1)) || + (ati_remote_sendpacket(ati_remote, 0x8007, init2))) { + dev_err(&ati_remote->interface->dev, + "Initializing ati_remote hardware failed.\n"); + return 1; + } + + return 0; +} + +/* + * ati_remote_probe + */ +static int ati_remote_probe(struct usb_interface *interface, const struct usb_device_id *id) +{ + struct usb_device *udev = interface_to_usbdev(interface); + struct ati_remote *ati_remote = NULL; + struct usb_host_interface *iface_host; + int retval = -ENOMEM; + char path[64]; + char *buf = NULL; + + /* See if the offered device matches what we can accept */ + if ((udev->descriptor.idVendor != ATI_REMOTE_VENDOR_ID) || + (udev->descriptor.idProduct != ATI_REMOTE_PRODUCT_ID)) { + return -ENODEV; + } + + /* Allocate and clear an ati_remote struct */ + if (!(ati_remote = kmalloc(sizeof (struct ati_remote), GFP_KERNEL))) + return -ENOMEM; + memset(ati_remote, 0x00, sizeof (struct ati_remote)); + + iface_host = interface->cur_altsetting; + if (iface_host->desc.bNumEndpoints != 2) { + err("%s: Unexpected desc.bNumEndpoints\n", __FUNCTION__); + retval = -ENODEV; + goto error; + } + + ati_remote->endpoint_in = &(iface_host->endpoint[0].desc); + ati_remote->endpoint_out = &(iface_host->endpoint[1].desc); + ati_remote->udev = udev; + ati_remote->interface = interface; + + if (!(ati_remote->endpoint_in->bEndpointAddress & 0x80)) { + err("%s: Unexpected endpoint_in->bEndpointAddress\n", __FUNCTION__); + retval = -ENODEV; + goto error; + } + if ((ati_remote->endpoint_in->bmAttributes & 3) != 3) { + err("%s: Unexpected endpoint_in->bmAttributes\n", __FUNCTION__); + retval = -ENODEV; + goto error; + } + if (ati_remote->endpoint_in->wMaxPacketSize == 0) { + err("%s: endpoint_in message size==0? \n", __FUNCTION__); + retval = -ENODEV; + goto error; + } + if (!(buf = kmalloc(NAME_BUFSIZE, GFP_KERNEL))) + goto error; + + /* Allocate URB buffers, URBs */ + ati_remote->inbuf = usb_buffer_alloc(udev, DATA_BUFSIZE, SLAB_ATOMIC, + &ati_remote->inbuf_dma); + if (!ati_remote->inbuf) + goto error; + + ati_remote->outbuf = usb_buffer_alloc(udev, DATA_BUFSIZE, SLAB_ATOMIC, + &ati_remote->outbuf_dma); + if (!ati_remote->outbuf) + goto error; + + ati_remote->irq_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!ati_remote->irq_urb) + goto error; + + ati_remote->out_urb = usb_alloc_urb(0, GFP_KERNEL); + if (!ati_remote->out_urb) + goto error; + + usb_make_path(udev, path, NAME_BUFSIZE); + sprintf(ati_remote->phys, "%s/input%d", path, ATI_INPUTNUM); + if (udev->descriptor.iManufacturer && + (usb_string(udev, udev->descriptor.iManufacturer, buf, + NAME_BUFSIZE) > 0)) + strcat(ati_remote->name, buf); + + if (udev->descriptor.iProduct && + (usb_string(udev, udev->descriptor.iProduct, buf, NAME_BUFSIZE) > 0)) + sprintf(ati_remote->name, "%s %s", ati_remote->name, buf); + + if (!strlen(ati_remote->name)) + sprintf(ati_remote->name, DRIVER_DESC "(%04x,%04x)", + ati_remote->udev->descriptor.idVendor, + ati_remote->udev->descriptor.idProduct); + + /* Device Hardware Initialization - fills in ati_remote->idev from udev. */ + retval = ati_remote_initialize(ati_remote); + if (retval) + goto error; + + /* Set up and register input device */ + ati_remote_input_init(ati_remote); + input_register_device(&ati_remote->idev); + + dev_info(&ati_remote->interface->dev, "Input registered: %s on %s\n", + ati_remote->name, path); + + usb_set_intfdata(interface, ati_remote); + ati_remote->present = 1; + kfree(buf); + return 0; + +error: + if (buf) + kfree(buf); + + ati_remote_delete(ati_remote); + return retval; +} + +/* + * ati_remote_disconnect + */ +static void ati_remote_disconnect(struct usb_interface *interface) +{ + struct ati_remote *ati_remote; + + ati_remote = usb_get_intfdata(interface); + usb_set_intfdata(interface, NULL); + if (!ati_remote) { + warn("%s - null device?\n", __FUNCTION__); + return; + } + + input_unregister_device(&ati_remote->idev); + + /* Mark device as unplugged */ + ati_remote->present = 0; + + /* If device is still open, ati_remote_close will call delete. */ + if (!ati_remote->open) + ati_remote_delete(ati_remote); +} + +/* + * ati_remote_init + */ +static int __init ati_remote_init(void) +{ + int result; + + result = usb_register(&ati_remote_driver); + if (result) + err("usb_register error #%d\n", result); + else + info("Registered USB driver " DRIVER_DESC " v. " DRIVER_VERSION); + + return result; +} + +/* + * ati_remote_exit + */ +static void __exit ati_remote_exit(void) +{ + usb_deregister(&ati_remote_driver); +} + +/* + * module specification + */ + +module_init(ati_remote_init); +module_exit(ati_remote_exit); + +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); +MODULE_LICENSE("GPL"); + diff -puN drivers/usb/input/hid-core.c~bk-usb drivers/usb/input/hid-core.c --- 25/drivers/usb/input/hid-core.c~bk-usb 2004-03-10 21:44:00.000000000 -0800 +++ 25-akpm/drivers/usb/input/hid-core.c 2004-03-10 21:44:01.000000000 -0800 @@ -1510,7 +1510,7 @@ static void hid_free_buffers(struct usb_ static struct hid_device *usb_hid_configure(struct usb_interface *intf) { - struct usb_host_interface *interface = intf->altsetting + intf->act_altsetting; + struct usb_host_interface *interface = intf->cur_altsetting; struct usb_device *dev = interface_to_usbdev (intf); struct hid_descriptor *hdesc; struct hid_device *hid; diff -puN drivers/usb/input/kbtab.c~bk-usb drivers/usb/input/kbtab.c --- 25/drivers/usb/input/kbtab.c~bk-usb 2004-03-10 21:44:00.000000000 -0800 +++ 25-akpm/drivers/usb/input/kbtab.c 2004-03-10 21:44:01.000000000 -0800 @@ -4,6 +4,8 @@ #include #include #include +#include +#include /* * Version Information @@ -65,8 +67,8 @@ static void kbtab_irq(struct urb *urb, s goto exit; } - kbtab->x = (data[2] << 8) + data[1]; - kbtab->y = (data[4] << 8) + data[3]; + kbtab->x = le16_to_cpu(get_unaligned((u16 *) &data[1])); + kbtab->y = le16_to_cpu(get_unaligned((u16 *) &data[3])); kbtab->pressure = (data[5]); @@ -74,12 +76,15 @@ static void kbtab_irq(struct urb *urb, s input_report_abs(dev, ABS_X, kbtab->x); input_report_abs(dev, ABS_Y, kbtab->y); - /*input_report_abs(dev, ABS_PRESSURE, kbtab->pressure);*/ /*input_report_key(dev, BTN_TOUCH , data[0] & 0x01);*/ input_report_key(dev, BTN_RIGHT, data[0] & 0x02); - - input_report_key(dev, BTN_LEFT, (kbtab->pressure > kb_pressure_click) ? 1 : 0); + + if( -1 == kb_pressure_click){ + input_report_abs(dev, ABS_PRESSURE, kbtab->pressure); + } else { + input_report_key(dev, BTN_LEFT, (kbtab->pressure > kb_pressure_click) ? 1 : 0); + }; input_sync(dev); @@ -105,8 +110,10 @@ static int kbtab_open(struct input_dev * return 0; 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 0; } @@ -130,7 +137,7 @@ static int kbtab_probe(struct usb_interf return -ENOMEM; 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) { kfree(kbtab); return -ENOMEM; diff -puN drivers/usb/input/Kconfig~bk-usb drivers/usb/input/Kconfig --- 25/drivers/usb/input/Kconfig~bk-usb 2004-03-10 21:44:00.000000000 -0800 +++ 25-akpm/drivers/usb/input/Kconfig 2004-03-10 21:44:01.000000000 -0800 @@ -179,6 +179,18 @@ config USB_POWERMATE To compile this driver as a module, choose M here: the module will be called powermate. +config USB_MTOUCH + tristate "MicroTouch USB Touchscreen Driver" + depends on USB && INPUT + ---help--- + Say Y here if you want to use a MicroTouch (Now 3M) USB + Touchscreen controller. + + See for additional information. + + To compile this driver as a module, choose M here: the + module will be called mtouchusb. + config USB_XPAD tristate "X-Box gamepad support" depends on USB && INPUT @@ -192,3 +204,17 @@ config USB_XPAD To compile this driver as a module, choose M here: the module will be called xpad. + +config USB_ATI_REMOTE + tristate "ATI USB RF remote control" + depends on USB && INPUT + ---help--- + Say Y here if you want to use one of ATI's USB remote controls. + These are RF remotes with USB receivers. They come with many of ATI's + All-In-Wonder video cards. This driver provides mouse pointer, left + and right mouse buttons, and maps all the other remote buttons to + keypress events. + + To compile this driver as a module, choose M here: the module will be + called ati_remote. + diff -puN drivers/usb/input/Makefile~bk-usb drivers/usb/input/Makefile --- 25/drivers/usb/input/Makefile~bk-usb 2004-03-10 21:44:00.000000000 -0800 +++ 25-akpm/drivers/usb/input/Makefile 2004-03-10 21:44:01.000000000 -0800 @@ -27,10 +27,12 @@ ifeq ($(CONFIG_HID_FF),y) endif obj-$(CONFIG_USB_AIPTEK) += aiptek.o +obj-$(CONFIG_USB_ATI_REMOTE) += ati_remote.o obj-$(CONFIG_USB_HID) += hid.o obj-$(CONFIG_USB_KBD) += usbkbd.o -obj-$(CONFIG_USB_MOUSE) += usbmouse.o -obj-$(CONFIG_USB_WACOM) += wacom.o obj-$(CONFIG_USB_KBTAB) += kbtab.o +obj-$(CONFIG_USB_MOUSE) += usbmouse.o +obj-$(CONFIG_USB_MTOUCH) += mtouchusb.o obj-$(CONFIG_USB_POWERMATE) += powermate.o +obj-$(CONFIG_USB_WACOM) += wacom.o obj-$(CONFIG_USB_XPAD) += xpad.o diff -puN /dev/null drivers/usb/input/mtouchusb.c --- /dev/null 2002-08-30 16:31:37.000000000 -0700 +++ 25-akpm/drivers/usb/input/mtouchusb.c 2004-03-10 21:44:01.000000000 -0800 @@ -0,0 +1,391 @@ +/****************************************************************************** + * mtouchusb.c -- Driver for Microtouch (Now 3M) USB Touchscreens + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Based upon original work by Radoslaw Garbacz (usb-support@ite.pl) + * (http://freshmeat.net/projects/3mtouchscreendriver) + * + * History + * + * 0.3 & 0.4 2002 (TEJ) tejohnson@yahoo.com + * Updated to 2.4.18, then 2.4.19 + * Old version still relied on stealing a minor + * + * 0.5 02/26/2004 (TEJ) tejohnson@yahoo.com + * Complete rewrite using Linux Input in 2.6.3 + * Unfortunately no calibration support at this time + * + *****************************************************************************/ + +#include + +#ifdef CONFIG_USB_DEBUG + #define DEBUG +#else + #undef DEBUG +#endif + +#include +#include +#include +#include +#include +#include + +#define MTOUCHUSB_MIN_XC 0xc8 +#define MTOUCHUSB_MAX_XC 0xff78 +#define MTOUCHUSB_XC_FUZZ 0x0 +#define MTOUCHUSB_XC_FLAT 0x0 +#define MTOUCHUSB_MIN_YC 0x0 +#define MTOUCHUSB_MAX_YC 0xff78 +#define MTOUCHUSB_YC_FUZZ 0x0 +#define MTOUCHUSB_YC_FLAT 0x0 +#define MTOUCHUSB_ASYC_REPORT 1 +#define MTOUCHUSB_REPORT_SIZE_DATA 11 +#define MTOUCHUSB_REQ_CTRLLR_ID 10 + +#define MTOUCHUSB_GET_XC(data) (data[4]<<8 | data[3]) +#define MTOUCHUSB_GET_YC(data) (data[6]<<8 | data[5]) +#define MTOUCHUSB_GET_TOUCHED(data) ((data[2] & 0x40) ? 1:0) + +#define DRIVER_VERSION "v0.1" +#define DRIVER_AUTHOR "Todd E. Johnson, tejohnson@yahoo.com" +#define DRIVER_DESC "Microtouch USB HID Touchscreen Driver" + +struct mtouch_usb { + unsigned char *data; + dma_addr_t data_dma; + struct urb *irq; + struct usb_device *udev; + struct input_dev input; + int open; + char name[128]; + char phys[64]; +}; + +static __s32 vendor=-1, product=-1; + +static struct usb_device_id mtouchusb_devices [] = { + { USB_DEVICE(0x0596, 0x0001) }, /* 3M (Formerly MicroTouch) 14-206 */ + { } /* Terminating entry */ +}; + +static void mtouchusb_irq(struct urb *urb, struct pt_regs *regs) +{ + struct mtouch_usb *mtouch = urb->context; + int retval; + + switch (urb->status) { + case 0: + /* success */ + break; + case -ETIMEDOUT: + /* this urb is timing out */ + dbg("%s - urb timed out - was the device unplugged?", + __FUNCTION__); + return; + case -ECONNRESET: + case -ENOENT: + case -ESHUTDOWN: + /* this urb is terminated, clean up */ + dbg("%s - urb shutting down with status: %d", + __FUNCTION__, urb->status); + return; + default: + dbg("%s - nonzero urb status received: %d", + __FUNCTION__, urb->status); + goto exit; + } + + input_regs(&mtouch->input, regs); + input_report_key(&mtouch->input, BTN_TOUCH, + MTOUCHUSB_GET_TOUCHED(mtouch->data)); + input_report_abs(&mtouch->input, ABS_X, + MTOUCHUSB_GET_XC(mtouch->data)); + input_report_abs(&mtouch->input, ABS_Y, + MTOUCHUSB_GET_YC(mtouch->data)); + input_sync(&mtouch->input); + +exit: + retval = usb_submit_urb (urb, GFP_ATOMIC); + if (retval) + err ("%s - usb_submit_urb failed with result: %d", + __FUNCTION__, retval); +} + +static int mtouchusb_open (struct input_dev *input) +{ + struct mtouch_usb *mtouch = input->private; + + if (mtouch->open++) + return 0; + + mtouch->irq->dev = mtouch->udev; + + if (usb_submit_urb (mtouch->irq, GFP_ATOMIC)) + return -EIO; + + return 0; +} + +static void mtouchusb_close (struct input_dev *input) +{ + struct mtouch_usb *mtouch = input->private; + + if (!--mtouch->open) + usb_unlink_urb (mtouch->irq); +} + +static int mtouchusb_alloc_buffers(struct usb_device *udev, struct mtouch_usb *mtouch) +{ + dbg("%s - called", __FUNCTION__); + + mtouch->data = usb_buffer_alloc(udev, MTOUCHUSB_REPORT_SIZE_DATA, + SLAB_ATOMIC, &mtouch->data_dma); + + if (!mtouch->data) + return -1; + + return 0; +} + +static void mtouchusb_free_buffers(struct usb_device *udev, struct mtouch_usb *mtouch) +{ + dbg("%s - called", __FUNCTION__); + + if (mtouch->data) + usb_buffer_free(udev, MTOUCHUSB_REPORT_SIZE_DATA, + mtouch->data, mtouch->data_dma); +} + +static int mtouchusb_probe(struct usb_interface *intf, const struct usb_device_id *id) +{ + struct mtouch_usb *mtouch; + struct usb_host_interface *interface; + struct usb_endpoint_descriptor *endpoint; + struct usb_device *udev = interface_to_usbdev (intf); + char path[64]; + char *buf; + int nRet; + int ix; + char valid_device = 0; + + dbg("%s - called", __FUNCTION__); + if (vendor != -1 && product != -1) { + info("%s - User specified USB Touch -- Vend:Prod - %x:%x", + __FUNCTION__, vendor, product); + } + + for (ix = 0; ix < sizeof (mtouchusb_devices) / + sizeof (struct usb_device_id); ix++) { + if ((udev->descriptor.idVendor == + mtouchusb_devices [ix].idVendor) && + (udev->descriptor.idProduct == + mtouchusb_devices [ix].idProduct)) { + valid_device = 1; + break; + } + } + + if (udev->descriptor.idVendor == vendor && + udev->descriptor.idProduct == product) { /* User specified */ + valid_device = 1; + } + + if (!valid_device) { + err("%s - No valid device!", __FUNCTION__); + return -EIO; + } + + if (udev->descriptor.bNumConfigurations != 1) { + err("%s - Only one device configuration is supported.", + __FUNCTION__); + return -EIO; + } + + dbg("%s - setting interface", __FUNCTION__); + interface = intf->cur_altsetting; + + dbg("%s - setting endpoint", __FUNCTION__); + endpoint = &interface->endpoint[0].desc; + + if (interface->desc.bNumEndpoints != 1) { + err("%s - Only one endpoint is supported.", __FUNCTION__); + return -EIO; + } + + if (!(mtouch = kmalloc (sizeof (struct mtouch_usb), GFP_KERNEL))) { + err("%s - Out of memory.", __FUNCTION__); + return -ENOMEM; + } + + memset(mtouch, 0, sizeof(struct mtouch_usb)); + mtouch->udev = udev; + + dbg("%s - allocating buffers", __FUNCTION__); + if (mtouchusb_alloc_buffers(udev, mtouch)) { + mtouchusb_free_buffers(udev, mtouch); + kfree(mtouch); + return -ENOMEM; + } + + mtouch->input.private = mtouch; + mtouch->input.open = mtouchusb_open; + mtouch->input.close = mtouchusb_close; + + usb_make_path(udev, path, 64); + sprintf(mtouch->phys, "%s/input0", path); + + mtouch->input.name = mtouch->name; + mtouch->input.phys = mtouch->phys; + mtouch->input.id.bustype = BUS_USB; + mtouch->input.id.vendor = udev->descriptor.idVendor; + mtouch->input.id.product = udev->descriptor.idProduct; + mtouch->input.id.version = udev->descriptor.bcdDevice; + mtouch->input.dev = &intf->dev; + + mtouch->input.evbit[0] = BIT(EV_KEY) | BIT(EV_ABS); + mtouch->input.absbit[0] = BIT(ABS_X) | BIT(ABS_Y); + mtouch->input.keybit[LONG(BTN_TOUCH)] = BIT(BTN_TOUCH); + + /* Used to Scale Compensated Data and Flip Y */ + mtouch->input.absmin[ABS_X] = MTOUCHUSB_MIN_XC; + mtouch->input.absmax[ABS_X] = MTOUCHUSB_MAX_XC; + mtouch->input.absfuzz[ABS_X] = MTOUCHUSB_XC_FUZZ; + mtouch->input.absflat[ABS_X] = MTOUCHUSB_XC_FLAT; + mtouch->input.absmin[ABS_Y] = MTOUCHUSB_MAX_YC; + mtouch->input.absmax[ABS_Y] = MTOUCHUSB_MIN_YC; + mtouch->input.absfuzz[ABS_Y] = MTOUCHUSB_YC_FUZZ; + mtouch->input.absflat[ABS_Y] = MTOUCHUSB_YC_FLAT; + + if (!(buf = kmalloc(63, GFP_KERNEL))) { + kfree(mtouch); + return -ENOMEM; + } + + if (udev->descriptor.iManufacturer && + usb_string(udev, udev->descriptor.iManufacturer, buf, 63) > 0) + strcat(mtouch->name, buf); + if (udev->descriptor.iProduct && + usb_string(udev, udev->descriptor.iProduct, buf, 63) > 0) + sprintf(mtouch->name, "%s %s", mtouch->name, buf); + + if (!strlen(mtouch->name)) + sprintf(mtouch->name, "USB Touchscreen %04x:%04x", + mtouch->input.id.vendor, mtouch->input.id.product); + + kfree(buf); + + nRet = usb_control_msg(mtouch->udev, + usb_rcvctrlpipe(udev, 0x80), + USB_REQ_GET_CONFIGURATION, + USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE, + 0, + 0x81, + NULL, + 0, + HZ * USB_CTRL_SET_TIMEOUT); + dbg("%s - usb_control_msg - USB_REQ_GET_CONFIGURATION - bytes|err: %d", + __FUNCTION__, nRet); + + dbg("%s - usb_alloc_urb: mtouch->irq", __FUNCTION__); + mtouch->irq = usb_alloc_urb(0, GFP_KERNEL); + if (!mtouch->irq) { + dbg("%s - usb_alloc_urb failed: mtouch->irq", __FUNCTION__); + mtouchusb_free_buffers(udev, mtouch); + kfree(mtouch); + return -ENOMEM; + } + + dbg("%s - usb_fill_int_urb", __FUNCTION__); + usb_fill_int_urb(mtouch->irq, + mtouch->udev, + usb_rcvintpipe(mtouch->udev, 0x81), + mtouch->data, + MTOUCHUSB_REPORT_SIZE_DATA, + mtouchusb_irq, + mtouch, + endpoint->bInterval); + + dbg("%s - input_register_device", __FUNCTION__); + input_register_device(&mtouch->input); + + nRet = usb_control_msg(mtouch->udev, + usb_rcvctrlpipe(udev, 0x80), + MTOUCHUSB_ASYC_REPORT, + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, + MTOUCHUSB_ASYC_REPORT, + MTOUCHUSB_ASYC_REPORT, + NULL, + 0, + HZ * USB_CTRL_SET_TIMEOUT); + dbg("%s - usb_control_msg - MTOUCHUSB_ASYC_REPORT - bytes|err: %d", + __FUNCTION__, nRet); + + printk(KERN_INFO "input: %s on %s\n", mtouch->name, path); + usb_set_intfdata(intf, mtouch); + + return 0; +} + +static void mtouchusb_disconnect(struct usb_interface *intf) +{ + struct mtouch_usb *mtouch = usb_get_intfdata (intf); + + dbg("%s - called", __FUNCTION__); + usb_set_intfdata(intf, NULL); + if (mtouch) { + dbg("%s - mtouch is initialized, cleaning up", __FUNCTION__); + usb_unlink_urb(mtouch->irq); + input_unregister_device(&mtouch->input); + usb_free_urb(mtouch->irq); + mtouchusb_free_buffers(interface_to_usbdev(intf), mtouch); + kfree(mtouch); + } +} + +MODULE_DEVICE_TABLE (usb, mtouchusb_devices); + +static struct usb_driver mtouchusb_driver = { + .owner = THIS_MODULE, + .name = "mtouchusb", + .probe = mtouchusb_probe, + .disconnect = mtouchusb_disconnect, + .id_table = mtouchusb_devices, +}; + +static int __init mtouchusb_init(void) { + dbg("%s - called", __FUNCTION__); + return usb_register(&mtouchusb_driver); +} + +static void __exit mtouchusb_cleanup(void) { + dbg("%s - called", __FUNCTION__); + usb_deregister(&mtouchusb_driver); +} + +module_init(mtouchusb_init); +module_exit(mtouchusb_cleanup); + +MODULE_AUTHOR( DRIVER_AUTHOR ); +MODULE_DESCRIPTION( DRIVER_DESC ); +MODULE_LICENSE("GPL"); +MODULE_PARM(vendor, "i"); +MODULE_PARM_DESC(vendor, "User specified USB idVendor"); +MODULE_PARM(product, "i"); +MODULE_PARM_DESC(product, "User specified USB idProduct"); + + diff -puN drivers/usb/input/pid.c~bk-usb drivers/usb/input/pid.c --- 25/drivers/usb/input/pid.c~bk-usb 2004-03-10 21:44:00.000000000 -0800 +++ 25-akpm/drivers/usb/input/pid.c 2004-03-10 21:44:01.000000000 -0800 @@ -200,6 +200,7 @@ static int hid_pid_upload_effect(struct break; 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) { dev_dbg(&pid_private->hid->dev->dev, "Not enough device memory\n"); return -ENOMEM; diff -puN drivers/usb/input/usbkbd.c~bk-usb drivers/usb/input/usbkbd.c --- 25/drivers/usb/input/usbkbd.c~bk-usb 2004-03-10 21:44:00.000000000 -0800 +++ 25-akpm/drivers/usb/input/usbkbd.c 2004-03-10 21:44:01.000000000 -0800 @@ -240,7 +240,7 @@ static int usb_kbd_probe(struct usb_inte char path[64]; char *buf; - interface = &iface->altsetting[iface->act_altsetting]; + interface = iface->cur_altsetting; if (interface->desc.bNumEndpoints != 1) return -ENODEV; diff -puN drivers/usb/input/usbmouse.c~bk-usb drivers/usb/input/usbmouse.c --- 25/drivers/usb/input/usbmouse.c~bk-usb 2004-03-10 21:44:00.000000000 -0800 +++ 25-akpm/drivers/usb/input/usbmouse.c 2004-03-10 21:44:01.000000000 -0800 @@ -131,7 +131,7 @@ static int usb_mouse_probe(struct usb_in char path[64]; char *buf; - interface = &intf->altsetting[intf->act_altsetting]; + interface = intf->cur_altsetting; if (interface->desc.bNumEndpoints != 1) return -ENODEV; diff -puN drivers/usb/input/wacom.c~bk-usb drivers/usb/input/wacom.c --- 25/drivers/usb/input/wacom.c~bk-usb 2004-03-10 21:44:00.000000000 -0800 +++ 25-akpm/drivers/usb/input/wacom.c 2004-03-10 21:45:08.000000000 -0800 @@ -66,6 +66,8 @@ #include #include #include +#include +#include /* * Version Information @@ -283,8 +285,8 @@ static void wacom_penpartner_irq(struct input_regs(dev, regs); input_report_key(dev, BTN_TOOL_PEN, 1); - input_report_abs(dev, ABS_X, data[2] << 8 | data[1]); - input_report_abs(dev, ABS_Y, data[4] << 8 | data[3]); + input_report_abs(dev, ABS_X, le16_to_cpu(get_unaligned((u16 *) &data[1]))); + input_report_abs(dev, ABS_Y, le16_to_cpu(get_unaligned((u16 *) &data[3]))); input_report_abs(dev, ABS_PRESSURE, (signed char)data[6] + 127); input_report_key(dev, BTN_TOUCH, ((signed char)data[6] > -80) && !(data[5] & 0x20)); input_report_key(dev, BTN_STYLUS, (data[5] & 0x40)); @@ -327,8 +329,8 @@ static void wacom_graphire_irq(struct ur if (data[0] != 2) dbg("wacom_graphire_irq: received unknown report #%d", data[0]); - x = data[2] | ((__u32)data[3] << 8); - y = data[4] | ((__u32)data[5] << 8); + x = le16_to_cpu(*(u16 *) &data[2]); + y = le16_to_cpu(*(u16 *) &data[4]); input_regs(dev, regs); @@ -365,7 +367,7 @@ static void wacom_graphire_irq(struct ur input_report_abs(dev, ABS_Y, y); } - input_report_abs(dev, ABS_PRESSURE, data[6] | ((__u32)data[7] << 8)); + input_report_abs(dev, ABS_PRESSURE, le16_to_cpu(*(u16 *) &data[6])); input_report_key(dev, BTN_TOUCH, data[1] & 0x01); input_report_key(dev, BTN_STYLUS, data[1] & 0x02); input_report_key(dev, BTN_STYLUS2, data[1] & 0x04); @@ -454,8 +456,8 @@ static void wacom_intuos_irq(struct urb goto exit; } - input_report_abs(dev, ABS_X, ((__u32)data[2] << 8) | data[3]); - input_report_abs(dev, ABS_Y, ((__u32)data[4] << 8) | data[5]); + input_report_abs(dev, ABS_X, be16_to_cpu(*(u16 *) &data[2])); + input_report_abs(dev, ABS_Y, be16_to_cpu(*(u16 *) &data[4])); input_report_abs(dev, ABS_DISTANCE, data[9]); if ((data[1] & 0xb8) == 0xa0) { /* general pen packet */ @@ -593,8 +595,10 @@ static int wacom_open(struct input_dev * return 0; wacom->irq->dev = wacom->usbdev; - if (usb_submit_urb(wacom->irq, GFP_KERNEL)) + if (usb_submit_urb(wacom->irq, GFP_KERNEL)) { + wacom->open--; return -EIO; + } return 0; } @@ -619,7 +623,7 @@ static int wacom_probe(struct usb_interf return -ENOMEM; memset(wacom, 0, sizeof(struct wacom)); - wacom->data = usb_buffer_alloc(dev, 10, SLAB_ATOMIC, &wacom->data_dma); + wacom->data = usb_buffer_alloc(dev, 10, GFP_KERNEL, &wacom->data_dma); if (!wacom->data) { kfree(wacom); return -ENOMEM; diff -puN drivers/usb/Kconfig~bk-usb drivers/usb/Kconfig --- 25/drivers/usb/Kconfig~bk-usb 2004-03-10 21:44:00.000000000 -0800 +++ 25-akpm/drivers/usb/Kconfig 2004-03-10 21:44:00.000000000 -0800 @@ -6,32 +6,36 @@ menu "USB support" # ARM SA1111 chips have a non-PCI based "OHCI-compatible" USB host interface. config USB - tristate "Support for USB" + tristate "Support for Host-side USB" depends on PCI || SA1111 || ARCH_OMAP1510 || ARCH_OMAP1610 ---help--- Universal Serial Bus (USB) is a specification for a serial bus subsystem which offers higher speeds and more features than the traditional PC serial port. The bus supplies power to peripherals 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 - 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 - ports and newer peripherals such as scanners, keyboards, mice, - modems, and printers support the USB protocol and can be connected - to the PC via those ports. - - 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" - or "OHCI HCD support" below (the type of interface that the USB hardware - in your computer provides to the operating system) and then choose - from amongst the drivers for USB peripherals. You may want to check - out the information provided in and - especially the links given in . - - 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. - - It doesn't normally hurt to select them all if you are not certain. + connected to a single USB host in a tree structure. + + The USB host is the root of the tree, the peripherals are the + leaves and the inner nodes are special USB devices called hubs. + Most PCs now have USB host ports, used to connect peripherals + 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 host-side USB port and you want + to use USB devices. You then need to say Y to at least one of the + Host Controller Driver (HCD) options below. Choose a USB 1.1 + controller, such as "UHCI HCD support" or "OHCI HCD support", + and "EHCI HCD (USB 2.0) support" except for older systems that + do not have USB 2.0 support. It doesn't normally hurt to select + them all if you are not certain. + + If your system has a device-side USB port, used in the peripheral + side of the USB protocol, see the "USB Gadget" framework instead. + + 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 and especially the links given in + . To compile this driver as a module, choose M here: the module will be called usbcore. diff -puN drivers/usb/Makefile~bk-usb drivers/usb/Makefile --- 25/drivers/usb/Makefile~bk-usb 2004-03-10 21:44:00.000000000 -0800 +++ 25-akpm/drivers/usb/Makefile 2004-03-10 21:44:00.000000000 -0800 @@ -20,10 +20,15 @@ obj-$(CONFIG_USB_PRINTER) += class/ obj-$(CONFIG_USB_STORAGE) += storage/ obj-$(CONFIG_USB_AIPTEK) += input/ +obj-$(CONFIG_USB_ATI_REMOTE) += input/ obj-$(CONFIG_USB_HID) += input/ obj-$(CONFIG_USB_KBD) += input/ +obj-$(CONFIG_USB_KBTAB) += input/ obj-$(CONFIG_USB_MOUSE) += input/ +obj-$(CONFIG_USB_MTOUCH) += input/ +obj-$(CONFIG_USB_POWERMATE) += input/ obj-$(CONFIG_USB_WACOM) += input/ +obj-$(CONFIG_USB_XPAD) += input/ obj-$(CONFIG_USB_DABUSB) += media/ obj-$(CONFIG_USB_DSBR) += media/ @@ -50,7 +55,6 @@ obj-$(CONFIG_USB_MICROTEK) += image/ obj-$(CONFIG_USB_SERIAL) += serial/ obj-$(CONFIG_USB_AUERSWALD) += misc/ -obj-$(CONFIG_USB_BRLVGER) += misc/ obj-$(CONFIG_USB_EMI26) += misc/ obj-$(CONFIG_USB_LCD) += misc/ obj-$(CONFIG_USB_LEGOTOWER) += misc/ diff -puN -L drivers/usb/misc/brlvger.c drivers/usb/misc/brlvger.c~bk-usb /dev/null --- 25/drivers/usb/misc/brlvger.c +++ /dev/null 2002-08-30 16:31:37.000000000 -0700 @@ -1,1016 +0,0 @@ -/* - * Tieman Voyager braille display USB driver. - * - * Copyright 2001-2002 Stephane Dalton - * and Stéphane Doyon - * Maintained by Stéphane Doyon . - */ -/* - * 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 - */ -/* History: - * 0.8 April 2002: Integration into the kernel tree. - * 0.7 October 2001: First public release as a module, distributed with - * the BRLTTY package (beta versions around 2.99y). - */ - -#define DRIVER_VERSION "v0.8" -#define DATE "April 2002" -#define DRIVER_AUTHOR \ - "Stephane Dalton " \ - "and Stéphane Doyon " -#define DRIVER_DESC "Tieman Voyager braille display USB driver for Linux 2.4" -#define DRIVER_SHORTDESC "Voyager" - -#define BANNER \ - KERN_INFO DRIVER_SHORTDESC " " DRIVER_VERSION " (" DATE ")\n" \ - KERN_INFO " by " DRIVER_AUTHOR "\n" - -static const char longbanner[] = { - DRIVER_DESC ", " DRIVER_VERSION " (" DATE "), by " DRIVER_AUTHOR -}; - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -MODULE_AUTHOR( DRIVER_AUTHOR ); -MODULE_DESCRIPTION( DRIVER_DESC ); -MODULE_LICENSE("GPL"); - -/* Module parameters */ - -static int debug = 1; -MODULE_PARM(debug, "i"); -MODULE_PARM_DESC(debug, "Debug level, 0-3"); - -static int write_repeats = 2; -MODULE_PARM(write_repeats, "i"); -MODULE_PARM_DESC(write_repeats, "Hack: repetitions for command to " - "display braille pattern"); - /* to get rid of weird extra dots (perhaps only on - early hardware versions?) */ - -static int stall_tries = 3; -MODULE_PARM(stall_tries, "i"); -MODULE_PARM_DESC(stall_tries, "Hack: retransmits of stalled USB " - "control messages"); - /* broken early hardware versions? */ - -#define BRLVGER_RAW_VOLTAGE 89 -/* from 0->300V to 255->200V, we are told 265V is normal operating voltage, - but we don't know the scale. Assuming it is linear. */ -static int raw_voltage = BRLVGER_RAW_VOLTAGE; -MODULE_PARM(raw_voltage, "i"); -MODULE_PARM_DESC(raw_voltage, "Parameter for the call to SET_DISPLAY_VOLTAGE"); - - -/* protocol and display type defines */ -#define MAX_BRLVGER_CELLS 72 -#define MAX_INTERRUPT_DATA 8 -/* control message request types */ -#define BRLVGER_READ_REQ 0xC2 -#define BRLVGER_WRITE_REQ 0x42 -/* control message request codes */ -#define BRLVGER_SET_DISPLAY_ON 0 -#define BRLVGER_SET_DISPLAY_VOLTAGE 1 -#define BRLVGER_GET_SERIAL 3 -#define BRLVGER_GET_HWVERSION 4 -#define BRLVGER_GET_FWVERSION 5 -#define BRLVGER_GET_LENGTH 6 -#define BRLVGER_SEND_BRAILLE 7 -#define BRLVGER_BEEP 9 -#if 0 /* not used and not sure they're working */ -#define BRLVGER_GET_DISPLAY_VOLTAGE 2 -#define BRLVGER_GET_CURRENT 8 -#endif - -/* Prototypes */ -static int brlvger_probe (struct usb_interface *intf, - const struct usb_device_id *id); -static void brlvger_disconnect(struct usb_interface *intf); -static int brlvger_open(struct inode *inode, struct file *file); -static int brlvger_release(struct inode *inode, struct file *file); -static ssize_t brlvger_write(struct file *file, const char __user *buffer, - size_t count, loff_t *pos); -static ssize_t brlvger_read(struct file *file, char __user *buffer, - size_t count, loff_t *unused_pos); -static int brlvger_ioctl(struct inode *inode, struct file *file, - unsigned cmd, unsigned long arg); -static unsigned brlvger_poll(struct file *file, poll_table *wait); -static loff_t brlvger_llseek(struct file * file, loff_t offset, int orig); -static void intr_callback(struct urb *urb, struct pt_regs *regs); -struct brlvger_priv; -static int brlvger_get_hw_version(struct brlvger_priv *priv, - unsigned char *verbuf); -static int brlvger_get_fw_version(struct brlvger_priv *priv, - unsigned char *buf); -static int brlvger_get_serial(struct brlvger_priv *priv, - unsigned char *buf); -static int brlvger_get_display_length(struct brlvger_priv *priv); -static int brlvger_set_display_on_off(struct brlvger_priv *priv, __u16 on); -static int brlvger_beep(struct brlvger_priv *priv, __u16 duration); -static int brlvger_set_display_voltage(struct brlvger_priv *priv, - __u16 voltage); -static int mycontrolmsg(const char *funcname, - struct brlvger_priv *priv, unsigned pipe_dir, - __u8 request, __u8 requesttype, __u16 value, - __u16 index, void *data, __u16 size); - -#define controlmsg(priv,pipe_dir,a,b,c,d,e,f) \ - mycontrolmsg(__FUNCTION__, priv, pipe_dir, \ - a,b,c,d,e,f) -#define sndcontrolmsg(priv,a,b,c,d,e,f) \ - controlmsg(priv, 0, a,b,c,d,e,f) -#define rcvcontrolmsg(priv,a,b,c,d,e,f) \ - controlmsg(priv, USB_DIR_IN, a,b,c,d,e,f) - -/* ----------------------------------------------------------------------- */ - -/* Data */ - -/* key event queue size */ -#define MAX_INTERRUPT_BUFFER 10 - -/* private state */ -struct brlvger_priv { - struct usb_device *dev; /* USB device handle */ - struct usb_endpoint_descriptor *in_interrupt; - struct urb *intr_urb; - - int subminor; /* which minor dev #? */ - - unsigned char hwver[BRLVGER_HWVER_SIZE]; /* hardware version */ - unsigned char fwver[BRLVGER_FWVER_SIZE]; /* firmware version */ - unsigned char serialnum[BRLVGER_SERIAL_SIZE]; - - int llength; /* logical length */ - int plength; /* physical length */ - - __u8 obuf[MAX_BRLVGER_CELLS]; - __u8 intr_buff[MAX_INTERRUPT_DATA]; - __u8 event_queue[MAX_INTERRUPT_BUFFER][MAX_INTERRUPT_DATA]; - atomic_t intr_idx, read_idx; - spinlock_t intr_idx_lock; /* protects intr_idx */ - wait_queue_head_t read_wait; - - int opened; - struct semaphore open_sem; /* protects ->opened */ - struct semaphore dev_sem; /* protects ->dev */ -}; - -/* Globals */ - -/* For blocking open */ -static DECLARE_WAIT_QUEUE_HEAD(open_wait); - -/* Some print macros */ -#ifdef dbg -#undef dbg -#endif -#ifdef info -#undef info -#endif -#ifdef err -#undef err -#endif -#define info(args...) \ - ({ printk(KERN_INFO "Voyager: " args); \ - printk("\n"); }) -#define err(args...) \ - ({ printk(KERN_ERR "Voyager: " args); \ - printk("\n"); }) -#define dbgprint(fmt, args...) \ - ({ printk(KERN_DEBUG "Voyager: %s: " fmt, __FUNCTION__ , ##args); \ - printk("\n"); }) -#define dbg(args...) \ - ({ if(debug >= 1) dbgprint(args); }) -#define dbg2(args...) \ - ({ if(debug >= 2) dbgprint(args); }) -#define dbg3(args...) \ - ({ if(debug >= 3) dbgprint(args); }) - -/* ----------------------------------------------------------------------- */ - -/* Driver registration */ - -static struct usb_device_id brlvger_ids [] = { - { USB_DEVICE(0x0798, 0x0001) }, - { } /* Terminating entry */ -}; -MODULE_DEVICE_TABLE (usb, brlvger_ids); - -static struct file_operations brlvger_fops = -{ - .owner = THIS_MODULE, - .llseek = brlvger_llseek, - .read = brlvger_read, - .write = brlvger_write, - .ioctl = brlvger_ioctl, - .open = brlvger_open, - .release = brlvger_release, - .poll = brlvger_poll, -}; - -static struct usb_class_driver brlvger_class = { - .name = "usb/brlvger%d", - .fops = &brlvger_fops, - .mode = S_IFCHR | S_IRUSR |S_IWUSR | S_IRGRP | S_IWGRP, - .minor_base = BRLVGER_MINOR, -}; - -static struct usb_driver brlvger_driver = -{ - .owner = THIS_MODULE, - .name = "brlvger", - .probe = brlvger_probe, - .disconnect = brlvger_disconnect, - .id_table = brlvger_ids, -}; - -static int -__init brlvger_init (void) -{ - int retval; - printk(BANNER); - - if(stall_tries < 1 || write_repeats < 1) - return -EINVAL; - - retval = usb_register(&brlvger_driver); - if (retval) { - err("USB registration failed"); - goto out; - } - -out: - return retval; -} - -static void -__exit brlvger_cleanup (void) -{ - usb_deregister (&brlvger_driver); - dbg("Driver unregistered"); -} - -module_init (brlvger_init); -module_exit (brlvger_cleanup); - -/* ----------------------------------------------------------------------- */ - -/* Probe and disconnect functions */ - -static int -brlvger_probe (struct usb_interface *intf, - const struct usb_device_id *id) -{ - struct usb_device *dev = interface_to_usbdev(intf); - struct brlvger_priv *priv = NULL; - int retval; - struct usb_endpoint_descriptor *endpoint; - struct usb_host_interface *actifsettings; - /* protects against reentrance: once we've found a free slot - we reserve it.*/ - static DECLARE_MUTEX(reserve_sem); - - actifsettings = dev->actconfig->interface[0]->altsetting; - - if( dev->descriptor.bNumConfigurations != 1 - || dev->config->desc.bNumInterfaces != 1 - || actifsettings->desc.bNumEndpoints != 1 ) { - err ("Bogus braille display config info"); - return -ENODEV; - } - - endpoint = &actifsettings->endpoint [0].desc; - if (!(endpoint->bEndpointAddress & 0x80) || - ((endpoint->bmAttributes & 3) != 0x03)) { - err ("Bogus braille display config info, wrong endpoints"); - return -ENODEV; - } - - down(&reserve_sem); - - retval = usb_register_dev(intf, &brlvger_class); - if (retval) { - err("Not able to get a minor for this device."); - goto error; - } - - if( !(priv = kmalloc (sizeof *priv, GFP_KERNEL)) ){ - err("No more memory"); - goto error; - } - - memset(priv, 0, sizeof(*priv)); - atomic_set(&priv->intr_idx, 0); - atomic_set(&priv->read_idx, MAX_INTERRUPT_BUFFER-1); - spin_lock_init(&priv->intr_idx_lock); - init_waitqueue_head(&priv->read_wait); - /* opened is memset'ed to 0 */ - init_MUTEX(&priv->open_sem); - init_MUTEX(&priv->dev_sem); - - priv->subminor = intf->minor; - - /* we found a interrupt in endpoint */ - priv->in_interrupt = endpoint; - - priv->dev = dev; - - if(brlvger_get_hw_version(priv, priv->hwver) <0) { - err("Unable to get hardware version"); - goto error; - } - dbg("Hw ver %d.%d", priv->hwver[0], priv->hwver[1]); - if(brlvger_get_fw_version(priv, priv->fwver) <0) { - err("Unable to get firmware version"); - goto error; - } - dbg("Fw ver: %s", priv->fwver); - - if(brlvger_get_serial(priv, priv->serialnum) <0) { - err("Unable to get serial number"); - goto error; - } - dbg("Serial number: %s", priv->serialnum); - - if( (priv->llength = brlvger_get_display_length(priv)) <0 ){ - err("Unable to get display length"); - goto error; - } - switch(priv->llength) { - case 48: - priv->plength = 44; - break; - case 72: - priv->plength = 70; - break; - default: - err("Unsupported display length: %d", priv->llength); - goto error; - }; - dbg("Display length: %d", priv->plength); - - usb_set_intfdata (intf, priv); - info( "Braille display %d is device major %d minor %d", - intf->minor, USB_MAJOR, BRLVGER_MINOR + intf->minor); - - /* Tell anyone waiting on a blocking open */ - wake_up_interruptible(&open_wait); - - goto out; - - error: - if(priv) { - kfree( priv ); - priv = NULL; - } - - out: - up(&reserve_sem); - if (priv) { - usb_set_intfdata (intf, priv); - return 0; - } - return -EIO; -} - -static void -brlvger_disconnect(struct usb_interface *intf) -{ - struct brlvger_priv *priv = usb_get_intfdata (intf); - int r; - - usb_set_intfdata (intf, NULL); - if(priv){ - info("Display %d disconnecting", priv->subminor); - - usb_deregister_dev(intf, &brlvger_class); - - down(&priv->open_sem); - down(&priv->dev_sem); - if(priv->opened) { - /* Disable interrupts */ - if((r = usb_unlink_urb(priv->intr_urb)) <0) - err("usb_unlink_urb returns %d", r); - usb_free_urb(priv->intr_urb); - /* mark device as dead and prevent control - messages to it */ - priv->dev = NULL; - /* Tell anyone hung up on a read that it - won't be coming */ - wake_up_interruptible(&priv->read_wait); - up(&priv->dev_sem); - up(&priv->open_sem); - }else - /* no corresponding up()s */ - kfree(priv); - } -} - -/* ----------------------------------------------------------------------- */ - -/* fops implementation */ - -static int -brlvger_open(struct inode *inode, struct file *file) -{ - int devnum = iminor(inode); - struct usb_interface *intf = NULL; - struct brlvger_priv *priv = NULL; - int n, ret; - - if (devnum < 0) - return -ENXIO; - - n = devnum - BRLVGER_MINOR; - - do { - intf = usb_find_interface(&brlvger_driver, devnum); - if (!intf) { - if (file->f_flags & O_NONBLOCK) { - dbg3("Failing non-blocking open: " - "device %d not connected", n); - return -EAGAIN; - } - /* Blocking open. One global wait queue will - suffice. We wait until a device for the selected - minor is connected. */ - dbg2("Waiting for device %d to be connected", n); - ret = wait_event_interruptible(open_wait, - (intf = usb_find_interface(&brlvger_driver, devnum))); - if (ret) { - dbg2("Interrupted wait for device %d", n); - return ret; - } - } - } while(!intf); - priv = usb_get_intfdata(intf); - - /* We grabbed an existing device. */ - if(down_interruptible(&priv->open_sem)) - return -ERESTARTSYS; - - /* Only one process can open each device, no sharing. */ - ret = -EBUSY; - if(priv->opened) - goto out; - - dbg("Opening display %d", priv->subminor); - - /* Setup interrupt handler for receiving key input */ - priv->intr_urb = usb_alloc_urb(0, GFP_KERNEL); - if(!priv->intr_urb) { - err("Unable to allocate URB"); - goto out; - } - usb_fill_int_urb( priv->intr_urb, priv->dev, - usb_rcvintpipe(priv->dev, - priv->in_interrupt->bEndpointAddress), - priv->intr_buff, sizeof(priv->intr_buff), - intr_callback, priv, priv->in_interrupt->bInterval); - if((ret = usb_submit_urb(priv->intr_urb, GFP_KERNEL)) <0){ - err("Error %d while submitting URB", ret); - goto out; - } - - /* Set voltage */ - if(brlvger_set_display_voltage(priv, raw_voltage) <0) { - err("Unable to set voltage"); - goto out; - } - - /* Turn display on */ - if((ret = brlvger_set_display_on_off(priv, 1)) <0) { - err("Error %d while turning display on", ret); - goto out; - } - - /* Mark as opened, so disconnect cannot free priv. */ - priv->opened = 1; - - file->private_data = priv; - - ret = 0; - goto out; - - out: - up(&priv->open_sem); - return ret; -} - -static int -brlvger_release(struct inode *inode, struct file *file) -{ - struct brlvger_priv *priv = file->private_data; - int r; - - /* Turn display off. Safe even if disconnected. */ - brlvger_set_display_on_off(priv, 0); - - /* mutex with disconnect and with open */ - down(&priv->open_sem); - - if(!priv->dev) { - dbg("Releasing disconnected device %d", priv->subminor); - /* no up(&priv->open_sem) */ - kfree(priv); - }else{ - dbg("Closing display %d", priv->subminor); - /* Disable interrupts */ - if((r = usb_unlink_urb(priv->intr_urb)) <0) - err("usb_unlink_urb returns %d", r); - usb_free_urb(priv->intr_urb); - priv->opened = 0; - up(&priv->open_sem); - } - - return 0; -} - -static ssize_t -brlvger_write(struct file *file, const char __user *buffer, - size_t count, loff_t *pos) -{ - struct brlvger_priv *priv = file->private_data; - char buf[MAX_BRLVGER_CELLS]; - int ret; - size_t rs; - loff_t off; - __u16 written; - - if(!priv->dev) - return -ENOLINK; - - off = *pos; - - if(off > priv->plength) - return -ESPIPE;; - - rs = priv->plength - off; - - if(count > rs) - count = rs; - written = count; - - if (copy_from_user (buf, buffer, count ) ) - return -EFAULT; - - memset(priv->obuf, 0xaa, sizeof(priv->obuf)); - - /* Firmware supports multiples of 8cells, so some cells are absent - and for some reason there actually are holes! euurkkk! */ - - if( priv->plength == 44 ) { - /* Two ghost cells at the beginning of the display, plus - two more after the sixth physical cell. */ - if(off > 5) { - off +=4; - memcpy(priv->obuf, buf, count); - }else{ - int firstpart = 6 - off; - -#ifdef WRITE_DEBUG - dbg3("off: %lld, rs: %d, count: %d, firstpart: %d", - off, rs, count, firstpart); -#endif - - firstpart = (firstpart < count) ? firstpart : count; - -#ifdef WRITE_DEBUG - dbg3("off: %lld", off); - dbg3("firstpart: %d", firstpart); -#endif - - memcpy(priv->obuf, buf, firstpart); - - if(firstpart != count) { - int secondpart = count - firstpart; -#ifdef WRITE_DEBUG - dbg3("secondpart: %d", secondpart); -#endif - - memcpy(priv->obuf+(firstpart+2), - buf+firstpart, secondpart); - written +=2; - } - - off +=2; - -#ifdef WRITE_DEBUG - dbg3("off: %lld, rs: %d, count: %d, firstpart: %d, " - "written: %d", off, rs, count, firstpart, written); -#endif - } - }else{ - /* Two ghost cells at the beginningg of the display. */ - memcpy(priv->obuf, buf, count); - off += 2; - } - - { - int repeat = write_repeats; - /* Dirty hack: sometimes some of the dots are wrong and somehow - right themselves if the command is repeated. */ - while(repeat--) { - ret = sndcontrolmsg(priv, - BRLVGER_SEND_BRAILLE, BRLVGER_WRITE_REQ, 0, - off, priv->obuf, written); - if(ret <0) - return ret; - } - } - - return count; -} - -static int -read_index(struct brlvger_priv *priv) -{ - int intr_idx, read_idx; - - read_idx = atomic_read(&priv->read_idx); - read_idx = ++read_idx == MAX_INTERRUPT_BUFFER ? 0 : read_idx; - - intr_idx = atomic_read(&priv->intr_idx); - - return(read_idx == intr_idx ? -1 : read_idx); -} - -static ssize_t -brlvger_read(struct file *file, char __user *buffer, - size_t count, loff_t *unused_pos) -{ - struct brlvger_priv *priv = file->private_data; - int read_idx; - - if(count != MAX_INTERRUPT_DATA) - return -EINVAL; - - if(!priv->dev) - return -ENOLINK; - - if((read_idx = read_index(priv)) == -1) { - /* queue empty */ - if (file->f_flags & O_NONBLOCK) - return -EAGAIN; - else{ - int r = wait_event_interruptible(priv->read_wait, - (!priv->dev || (read_idx = read_index(priv)) != -1)); - if(!priv->dev) - return -ENOLINK; - if(r) - return r; - if(read_idx == -1) - /* should not happen */ - return 0; - } - } - - if (copy_to_user (buffer, priv->event_queue[read_idx], count) ) - return( -EFAULT); - - atomic_set(&priv->read_idx, read_idx); - /* Multiple opens are not allowed. Yet on SMP, two processes could - read at the same time (on a shared file descriptor); then it is not - deterministic whether or not they will get duplicates of a key - event. */ - return MAX_INTERRUPT_DATA; -} - -static int -brlvger_ioctl(struct inode *inode, struct file *file, - unsigned cmd, unsigned long arg) -{ - struct brlvger_priv *priv = file->private_data; - - if(!priv->dev) - return -ENOLINK; - - switch(cmd) { - case BRLVGER_GET_INFO: { - struct brlvger_info vi; - - memset(&vi, 0, sizeof(vi)); - strlcpy(vi.driver_version, DRIVER_VERSION, - sizeof(vi.driver_version)); - strlcpy(vi.driver_banner, longbanner, - sizeof(vi.driver_banner)); - - vi.display_length = priv->plength; - - memcpy(&vi.hwver, priv->hwver, BRLVGER_HWVER_SIZE); - memcpy(&vi.fwver, priv->fwver, BRLVGER_FWVER_SIZE); - memcpy(&vi.serialnum, priv->serialnum, BRLVGER_SERIAL_SIZE); - - if(copy_to_user((void __user *)arg, &vi, sizeof(vi))) - return -EFAULT; - return 0; - } - case BRLVGER_DISPLAY_ON: - return brlvger_set_display_on_off(priv, 1); - case BRLVGER_DISPLAY_OFF: - return brlvger_set_display_on_off(priv, 0); - case BRLVGER_BUZZ: { - __u16 duration; - if(get_user(duration, (__u16 *)arg)) - return -EFAULT; - return brlvger_beep(priv, duration); - } - -#if 0 /* Underlying commands don't seem to work for some reason; not clear if - we'd want to export these anyway. */ - case BRLVGER_SET_VOLTAGE: { - __u16 voltage; - if(get_user(voltage, (__u16 *)arg)) - return -EFAULT; - return brlvger_set_display_voltage(priv, voltage); - } - case BRLVGER_GET_VOLTAGE: { - __u8 voltage; - int r = brlvger_get_display_voltage(priv); - if(r <0) - return r; - voltage = r; - if(put_user(voltage, (__u8 *)arg)) - return -EFAULT; - return 0; - } -#endif - default: - return -EINVAL; - }; -} - -static loff_t -brlvger_llseek(struct file *file, loff_t offset, int orig) -{ - struct brlvger_priv *priv = file->private_data; - - if(!priv->dev) - return -ENOLINK; - - switch (orig) { - case 0: - /* nothing to do */ - break; - case 1: - offset +=file->f_pos; - break; - case 2: - offset += priv->plength; - default: - return -EINVAL; - } - - if((offset >= priv->plength) || (offset < 0)) - return -EINVAL; - - return (file->f_pos = offset); -} - -static unsigned -brlvger_poll(struct file *file, poll_table *wait) -{ - struct brlvger_priv *priv = file->private_data; - - if(!priv->dev) - return POLLERR | POLLHUP; - - poll_wait(file, &priv->read_wait, wait); - - if(!priv->dev) - return POLLERR | POLLHUP; - if(read_index(priv) != -1) - return POLLIN | POLLRDNORM; - - return 0; -} - -static void -intr_callback(struct urb *urb, struct pt_regs *regs) -{ - struct brlvger_priv *priv = urb->context; - int intr_idx, read_idx; - int status; - - switch (urb->status) { - case 0: - /* success */ - break; - case -ECONNRESET: - case -ENOENT: - case -ESHUTDOWN: - /* this urb is terminated, clean up */ - dbg("%s - urb shutting down with status: %d", __FUNCTION__, urb->status); - return; - default: - dbg("%s - nonzero urb status received: %d", __FUNCTION__, urb->status); - goto exit; - } - - read_idx = atomic_read(&priv->read_idx); - spin_lock(&priv->intr_idx_lock); - intr_idx = atomic_read(&priv->intr_idx); - if(read_idx == intr_idx) { - dbg2("Queue full, dropping braille display input"); - spin_unlock(&priv->intr_idx_lock); - goto exit; /* queue full */ - } - - memcpy(priv->event_queue[intr_idx], urb->transfer_buffer, - MAX_INTERRUPT_DATA); - - intr_idx = (++intr_idx == MAX_INTERRUPT_BUFFER)? 0 : intr_idx; - atomic_set(&priv->intr_idx, intr_idx); - spin_unlock(&priv->intr_idx_lock); - - wake_up_interruptible(&priv->read_wait); - -exit: - status = usb_submit_urb (urb, GFP_ATOMIC); - if (status) - err ("%s - usb_submit_urb failed with result %d", - __FUNCTION__, status); -} - -/* ----------------------------------------------------------------------- */ - -/* Hardware access functions */ - -static int -mycontrolmsg(const char *funcname, - struct brlvger_priv *priv, unsigned pipe_dir, - __u8 request, __u8 requesttype, __u16 value, - __u16 index, void *data, __u16 size) -{ - int ret=0, tries = stall_tries; - - /* Make sure the device was not disconnected */ - if(down_interruptible(&priv->dev_sem)) - return -ERESTARTSYS; - if(!priv->dev) { - up(&priv->dev_sem); - return -ENOLINK; - } - - /* Dirty hack for retransmission: stalls and fails all the time - without this on the hardware we tested. */ - while(tries--) { - ret = usb_control_msg(priv->dev, - usb_sndctrlpipe(priv->dev,0) |pipe_dir, - request, requesttype, value, - index, data, size, - HZ); - if(ret != -EPIPE) - break; - dbg2("Stalled, remaining %d tries", tries); - } - up(&priv->dev_sem); - if(ret <0) { - err("%s: usb_control_msg returns %d", - funcname, ret); - return -EIO; - } - return 0; -} - -static int -brlvger_get_hw_version(struct brlvger_priv *priv, unsigned char *verbuf) -{ - return rcvcontrolmsg(priv, - BRLVGER_GET_HWVERSION, BRLVGER_READ_REQ, 0, - 0, verbuf, BRLVGER_HWVER_SIZE); - /* verbuf should be 2 bytes */ -} - -static int -brlvger_get_fw_version(struct brlvger_priv *priv, unsigned char *buf) -{ - unsigned char rawbuf[(BRLVGER_FWVER_SIZE-1)*2+2]; - int i, len; - int r = rcvcontrolmsg(priv, - BRLVGER_GET_FWVERSION, BRLVGER_READ_REQ, 0, - 0, rawbuf, sizeof(rawbuf)); - if(r<0) - return r; - - /* If I guess correctly: succession of 16bit words, the string is - formed of the first byte of each of these words. First byte in - buffer indicates total length of data; not sure what second byte is - for. */ - len = rawbuf[0]-2; - if(len<0) - len = 0; - else if(len+1 > BRLVGER_FWVER_SIZE) - len = BRLVGER_FWVER_SIZE-1; - for(i=0; i9) ? (n)+'A' : (n)+'0') - buf[2*i] = NUM_TO_HEX(rawserial[i] >>4); - buf[2*i+1] = NUM_TO_HEX(rawserial[i] &0xf); - } - buf[2*i] = 0; - return 0; -} - -static int -brlvger_get_display_length(struct brlvger_priv *priv) -{ - unsigned char data[2]; - int ret = rcvcontrolmsg(priv, - BRLVGER_GET_LENGTH, BRLVGER_READ_REQ, 0, - 0, data, 2); - if(ret<0) - return ret; - return data[1]; -} - -static int -brlvger_beep(struct brlvger_priv *priv, __u16 duration) -{ - return sndcontrolmsg(priv, - BRLVGER_BEEP, BRLVGER_WRITE_REQ, duration, - 0, NULL, 0); -} - -static int -brlvger_set_display_on_off(struct brlvger_priv *priv, __u16 on) -{ - dbg2("Turning display %s", ((on) ? "on" : "off")); - return sndcontrolmsg(priv, - BRLVGER_SET_DISPLAY_ON, BRLVGER_WRITE_REQ, on, - 0, NULL, 0); -} - -static int -brlvger_set_display_voltage(struct brlvger_priv *priv, __u16 voltage) -{ - dbg("SET_DISPLAY_VOLTAGE to %u", voltage); - return sndcontrolmsg(priv, - BRLVGER_SET_DISPLAY_VOLTAGE, BRLVGER_WRITE_REQ, voltage, - 0, NULL, 0); -} - -#if 0 /* Had problems testing these commands. Not particularly useful anyway.*/ - -static int -brlvger_get_display_voltage(struct brlvger_priv *priv) -{ - __u8 voltage = 0; - int ret = rcvcontrolmsg(priv, - BRLVGER_GET_DISPLAY_VOLTAGE, BRLVGER_READ_REQ, 0, - 0, &voltage, 1); - if(ret<0) - return ret; - return voltage; -} - -static int -brlvger_get_current(struct brlvger_priv *priv) -{ - unsigned char data; - int ret = rcvcontrolmsg(priv, - BRLVGER_GET_CURRENT, BRLVGER_READ_REQ, 0, - 0, &data, 1); - if(ret<0) - return ret; - return data; -} -#endif diff -puN drivers/usb/misc/Kconfig~bk-usb drivers/usb/misc/Kconfig --- 25/drivers/usb/misc/Kconfig~bk-usb 2004-03-10 21:44:00.000000000 -0800 +++ 25-akpm/drivers/usb/misc/Kconfig 2004-03-10 21:44:01.000000000 -0800 @@ -86,17 +86,6 @@ config USB_LEGOTOWER a module, say M here and read . -config USB_BRLVGER - tristate "Tieman Voyager USB Braille display support (EXPERIMENTAL)" - depends on USB && EXPERIMENTAL - help - Say Y here if you want to use the Voyager USB Braille display from - Tieman. See for more - information. - - To compile this driver as a module, choose M here: the - module will be called brlvger. - config USB_LCD tristate "USB LCD driver support" depends on USB diff -puN drivers/usb/misc/Makefile~bk-usb drivers/usb/misc/Makefile --- 25/drivers/usb/misc/Makefile~bk-usb 2004-03-10 21:44:00.000000000 -0800 +++ 25-akpm/drivers/usb/misc/Makefile 2004-03-10 21:44:01.000000000 -0800 @@ -4,7 +4,6 @@ # obj-$(CONFIG_USB_AUERSWALD) += auerswald.o -obj-$(CONFIG_USB_BRLVGER) += brlvger.o obj-$(CONFIG_USB_EMI62) += emi62.o obj-$(CONFIG_USB_EMI26) += emi26.o obj-$(CONFIG_USB_LCD) += usblcd.o diff -puN drivers/usb/misc/usbtest.c~bk-usb drivers/usb/misc/usbtest.c --- 25/drivers/usb/misc/usbtest.c~bk-usb 2004-03-10 21:44:00.000000000 -0800 +++ 25-akpm/drivers/usb/misc/usbtest.c 2004-03-10 21:44:01.000000000 -0800 @@ -149,8 +149,6 @@ get_endpoints (struct usbtest_dev *dev, if (!out) out = e; } - if (in && out) - goto found; continue; try_iso: if (e->desc.bEndpointAddress & USB_DIR_IN) { @@ -160,9 +158,9 @@ try_iso: if (!iso_out) iso_out = e; } - if (iso_in && iso_out) - goto found; } + if ((in && out) || (iso_in && iso_out)) + goto found; } return -EINVAL; @@ -181,7 +179,8 @@ found: in->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK); dev->out_pipe = usb_sndbulkpipe (udev, out->desc.bEndpointAddress & USB_ENDPOINT_NUMBER_MASK); - } else if (iso_in) { + } + if (iso_in) { dev->iso_in = &iso_in->desc; dev->in_iso_pipe = usb_rcvisocpipe (udev, iso_in->desc.bEndpointAddress @@ -211,7 +210,7 @@ static void simple_callback (struct urb static struct urb *simple_alloc_urb ( struct usb_device *udev, int pipe, - long bytes + unsigned long bytes ) { struct urb *urb; @@ -490,7 +489,7 @@ static int set_altsetting (struct usbtes struct usb_interface *iface = dev->intf; struct usb_device *udev; - if (alternate < 0 || alternate >= iface->num_altsetting) + if (alternate < 0 || alternate >= 256) return -EINVAL; udev = interface_to_usbdev (iface); @@ -556,23 +555,19 @@ static int ch9_postconfig (struct usbtes { struct usb_interface *iface = dev->intf; struct usb_device *udev = interface_to_usbdev (iface); - int i, retval; + int i, alt, retval; /* [9.2.3] if there's more than one altsetting, we need to be able to * set and get each one. mostly trusts the descriptors from usbcore. */ for (i = 0; i < iface->num_altsetting; i++) { - /* 9.2.3 constrains the range here, and Linux ensures - * they're ordered meaningfully in this array - */ - if (iface->altsetting [i].desc.bAlternateSetting != i) { + /* 9.2.3 constrains the range here */ + alt = iface->altsetting [i].desc.bAlternateSetting; + if (alt < 0 || alt >= iface->num_altsetting) { dev_dbg (&iface->dev, "invalid alt [%d].bAltSetting = %d\n", - i, - iface->altsetting [i].desc - .bAlternateSetting); - return -EDOM; + i, alt); } /* [real world] get/set unimplemented if there's only one */ @@ -580,18 +575,18 @@ static int ch9_postconfig (struct usbtes continue; /* [9.4.10] set_interface */ - retval = set_altsetting (dev, i); + retval = set_altsetting (dev, alt); if (retval) { dev_dbg (&iface->dev, "can't set_interface = %d, %d\n", - i, retval); + alt, retval); return retval; } /* [9.4.4] get_interface always works */ retval = get_altsetting (dev); - if (retval != i) { + if (retval != alt) { dev_dbg (&iface->dev, "get alt should be %d, was %d\n", - i, retval); + alt, retval); return (retval < 0) ? retval : -EDOM; } @@ -916,7 +911,7 @@ test_ctrl_queue (struct usbtest_dev *dev req.wValue = cpu_to_le16 (USB_DT_INTERFACE << 8); // interface == 0 len = sizeof (struct usb_interface_descriptor); - expected = -EPIPE; + expected = EPIPE; break; // NOTE: two consecutive stalls in the queue here. // that tests fault recovery a bit more aggressively. @@ -945,7 +940,7 @@ test_ctrl_queue (struct usbtest_dev *dev req.wValue = cpu_to_le16 (USB_DT_ENDPOINT << 8); // endpoint == 0 len = sizeof (struct usb_interface_descriptor); - expected = -EPIPE; + expected = EPIPE; break; // NOTE: sometimes even a third fault in the queue! case 12: // get string 0 descriptor (MAY STALL) @@ -1072,7 +1067,7 @@ static int unlink1 (struct usbtest_dev * * due to errors, or is just NAKing requests. */ if ((retval = usb_submit_urb (urb, SLAB_KERNEL)) != 0) { - dbg ("submit/unlink fail %d", retval); + dev_dbg (&dev->intf->dev, "submit fail %d\n", retval); return retval; } @@ -1087,18 +1082,22 @@ retry: * "normal" drivers would prevent resubmission, but * since we're testing unlink paths, we can't. */ - dbg ("unlink retry"); + dev_dbg (&dev->intf->dev, "unlink retry\n"); goto retry; } if (!(retval == 0 || retval == -EINPROGRESS)) { - dbg ("submit/unlink fail %d", retval); + dev_dbg (&dev->intf->dev, "unlink fail %d\n", retval); return retval; } wait_for_completion (&completion); retval = urb->status; simple_free_urb (urb); - return retval; + + if (async) + return (retval != -ECONNRESET) ? -ECONNRESET : 0; + else + return (retval != -ENOENT) ? -ENOENT : 0; } static int unlink_simple (struct usbtest_dev *dev, int pipe, int len) @@ -1723,7 +1722,8 @@ usbtest_ioctl (struct usb_interface *int retval = unlink_simple (dev, dev->in_pipe, param->length); if (retval) - dbg ("unlink reads failed, iterations left %d", i); + dev_dbg (&intf->dev, "unlink reads failed %d, " + "iterations left %d\n", retval, i); break; case 12: if (dev->out_pipe == 0 || !param->length) @@ -1735,7 +1735,8 @@ usbtest_ioctl (struct usb_interface *int retval = unlink_simple (dev, dev->out_pipe, param->length); if (retval) - dbg ("unlink writes failed, iterations left %d", i); + dev_dbg (&intf->dev, "unlink writes failed %d, " + "iterations left %d\n", retval, i); break; /* ep halt tests */ @@ -1965,7 +1966,10 @@ static struct usbtest_info fw_info = { .name = "usb test device", .ep_in = 2, .ep_out = 2, - .alt = 0, + .alt = 1, + .autoconf = 1, // iso and ctrl_out need autoconf + .ctrl_out = 1, + .iso = 1, // iso_ep's are #8 in/out }; /* peripheral running Linux and 'zero.c' test firmware, or diff -puN drivers/usb/net/Kconfig~bk-usb drivers/usb/net/Kconfig --- 25/drivers/usb/net/Kconfig~bk-usb 2004-03-10 21:44:00.000000000 -0800 +++ 25-akpm/drivers/usb/net/Kconfig 2004-03-10 21:44:01.000000000 -0800 @@ -131,6 +131,14 @@ config USB_USBNET comment "USB Host-to-Host Cables" depends on USB_USBNET +config USB_ALI_M5632 + boolean "ALi M5632 based 'USB 2.0 Data Link' cables" + depends on USB_USBNET + default y + help + Choose this option if you're using a host-to-host cable + based on this design, which supports USB 2.0 high speed. + config USB_AN2720 boolean "AnchorChips 2720 based cables (Xircom PGUNET, ...)" depends on USB_USBNET diff -puN drivers/usb/net/pegasus.h~bk-usb drivers/usb/net/pegasus.h --- 25/drivers/usb/net/pegasus.h~bk-usb 2004-03-10 21:44:00.000000000 -0800 +++ 25-akpm/drivers/usb/net/pegasus.h 2004-03-10 21:44:01.000000000 -0800 @@ -128,6 +128,7 @@ struct usb_eth_dev { #define VENDOR_DLINK 0x2001 #define VENDOR_ELCON 0x0db7 #define VENDOR_ELSA 0x05cc +#define VENDOR_GIGABYTE 0x1044 #define VENDOR_HAWKING 0x0e66 #define VENDOR_HP 0x03f0 #define VENDOR_IODATA 0x04bb @@ -178,6 +179,9 @@ PEGASUS_DEV( "ADMtek ADM8511 \"Pegasus I PEGASUS_DEV( "ADMtek ADM8513 \"Pegasus II\" USB Ethernet", VENDOR_ADMTEK, 0x8513, DEFAULT_GPIO_RESET | PEGASUS_II ) +PEGASUS_DEV( "ADMtek ADM8515 \"Pegasus II\" USB-2.0 Ethernet", + VENDOR_ADMTEK, 0x8515, + DEFAULT_GPIO_RESET | PEGASUS_II ) PEGASUS_DEV( "ADMtek AN986 \"Pegasus\" USB Ethernet (evaluation board)", VENDOR_ADMTEK, 0x0986, DEFAULT_GPIO_RESET | HAS_HOME_PNA ) @@ -223,6 +227,8 @@ PEGASUS_DEV( "EasiDock Ethernet", VENDOR DEFAULT_GPIO_RESET ) PEGASUS_DEV( "Elsa Micolink USB2Ethernet", VENDOR_ELSA, 0x3000, DEFAULT_GPIO_RESET ) +PEGASUS_DEV( "GIGABYTE GN-BR402W Wireless Router", VENDOR_GIGABYTE, 0x8002, + DEFAULT_GPIO_RESET ) PEGASUS_DEV( "Hawking UF100 10/100 Ethernet", VENDOR_HAWKING, 0x400c, DEFAULT_GPIO_RESET | PEGASUS_II ) PEGASUS_DEV( "HP hn210c Ethernet USB", VENDOR_HP, 0x811c, @@ -263,6 +269,8 @@ PEGASUS_DEV( "NETGEAR FA101", VENDOR_NET DEFAULT_GPIO_RESET | PEGASUS_II ) PEGASUS_DEV( "OCT Inc.", VENDOR_OCT, 0x0109, DEFAULT_GPIO_RESET | PEGASUS_II ) +PEGASUS_DEV( "OCT USB TO Ethernet", VENDOR_OCT, 0x0901, + DEFAULT_GPIO_RESET | PEGASUS_II ) PEGASUS_DEV( "smartNIC 2 PnP Adapter", VENDOR_SMARTBRIDGES, 0x0003, DEFAULT_GPIO_RESET | PEGASUS_II ) PEGASUS_DEV( "SMC 202 USB Ethernet", VENDOR_SMC, 0x0200, diff -puN drivers/usb/net/usbnet.c~bk-usb drivers/usb/net/usbnet.c --- 25/drivers/usb/net/usbnet.c~bk-usb 2004-03-10 21:44:00.000000000 -0800 +++ 25-akpm/drivers/usb/net/usbnet.c 2004-03-10 21:44:01.000000000 -0800 @@ -384,6 +384,23 @@ static void skb_return (struct usbnet *d } +#ifdef CONFIG_USB_ALI_M5632 +#define HAVE_HARDWARE + +/*------------------------------------------------------------------------- + * + * ALi M5632 driver ... does high speed + * + *-------------------------------------------------------------------------*/ + +static const struct driver_info ali_m5632_info = { + .description = "ALi M5632", +}; + + +#endif + + #ifdef CONFIG_USB_AN2720 #define HAVE_HARDWARE @@ -3009,7 +3026,7 @@ usbnet_probe (struct usb_interface *udev return -ENODEV; } xdev = interface_to_usbdev (udev); - interface = &udev->altsetting [udev->act_altsetting]; + interface = udev->cur_altsetting; usb_get_dev (xdev); @@ -3133,6 +3150,13 @@ out: static const struct usb_device_id products [] = { +#ifdef CONFIG_USB_ALI_M5632 +{ + USB_DEVICE (0x0402, 0x5632), // ALi defaults + .driver_info = (unsigned long) &ali_m5632_info, +}, +#endif + #ifdef CONFIG_USB_AN2720 { USB_DEVICE (0x0547, 0x2720), // AnchorChips defaults @@ -3314,6 +3338,15 @@ static const struct usb_device_id produc .bInterfaceSubClass = 0x0a, .bInterfaceProtocol = 0x00, .driver_info = (unsigned long) &zaurus_pxa_info, +}, { + .match_flags = USB_DEVICE_ID_MATCH_INT_INFO + | USB_DEVICE_ID_MATCH_DEVICE, + .idVendor = 0x04DD, + .idProduct = 0x9050, /* C-860 */ + .bInterfaceClass = 0x02, + .bInterfaceSubClass = 0x0a, + .bInterfaceProtocol = 0x00, + .driver_info = (unsigned long) &zaurus_pxa_info, }, #endif diff -puN drivers/usb/serial/ftdi_sio.c~bk-usb drivers/usb/serial/ftdi_sio.c --- 25/drivers/usb/serial/ftdi_sio.c~bk-usb 2004-03-10 21:44:00.000000000 -0800 +++ 25-akpm/drivers/usb/serial/ftdi_sio.c 2004-03-10 21:44:01.000000000 -0800 @@ -286,6 +286,7 @@ static struct usb_device_id id_table_sio static struct usb_device_id id_table_8U232AM [] = { + { USB_DEVICE_VER(FTDI_VID, FTDI_IRTRANS_PID, 0, 0x3ff) }, { USB_DEVICE_VER(FTDI_VID, FTDI_8U232AM_PID, 0, 0x3ff) }, { USB_DEVICE_VER(FTDI_VID, FTDI_8U232AM_ALT_PID, 0, 0x3ff) }, { USB_DEVICE_VER(FTDI_VID, FTDI_RELAIS_PID, 0, 0x3ff) }, @@ -358,6 +359,7 @@ static struct usb_device_id id_table_8U2 static struct usb_device_id id_table_FT232BM [] = { + { USB_DEVICE_VER(FTDI_VID, FTDI_IRTRANS_PID, 0x400, 0xffff) }, { USB_DEVICE_VER(FTDI_VID, FTDI_8U232AM_PID, 0x400, 0xffff) }, { USB_DEVICE_VER(FTDI_VID, FTDI_8U232AM_ALT_PID, 0x400, 0xffff) }, { USB_DEVICE_VER(FTDI_VID, FTDI_RELAIS_PID, 0x400, 0xffff) }, @@ -451,6 +453,7 @@ static struct usb_device_id id_table_HE_ static struct usb_device_id id_table_combined [] = { + { USB_DEVICE(FTDI_VID, FTDI_IRTRANS_PID) }, { USB_DEVICE(FTDI_VID, FTDI_SIO_PID) }, { USB_DEVICE(FTDI_VID, FTDI_8U232AM_PID) }, { USB_DEVICE(FTDI_VID, FTDI_8U232AM_ALT_PID) }, diff -puN drivers/usb/serial/ftdi_sio.h~bk-usb drivers/usb/serial/ftdi_sio.h --- 25/drivers/usb/serial/ftdi_sio.h~bk-usb 2004-03-10 21:44:00.000000000 -0800 +++ 25-akpm/drivers/usb/serial/ftdi_sio.h 2004-03-10 21:44:01.000000000 -0800 @@ -30,6 +30,8 @@ #define FTDI_NF_RIC_VID 0x0DCD /* Vendor Id */ #define FTDI_NF_RIC_PID 0x0001 /* Product Id */ +/* www.irtrans.de device */ +#define FTDI_IRTRANS_PID 0xFC60 /* Product Id */ /* www.crystalfontz.com devices - thanx for providing free devices for evaluation ! */ /* they use the ftdi chipset for the USB interface and the vendor id is the same */ diff -puN drivers/usb/serial/kl5kusb105.c~bk-usb drivers/usb/serial/kl5kusb105.c --- 25/drivers/usb/serial/kl5kusb105.c~bk-usb 2004-03-10 21:44:00.000000000 -0800 +++ 25-akpm/drivers/usb/serial/kl5kusb105.c 2004-03-10 21:44:01.000000000 -0800 @@ -273,6 +273,7 @@ static int klsi_105_startup (struct usb_ /* allocate the private data structure */ for (i=0; inum_ports; i++) { + int j; priv = kmalloc(sizeof(struct klsi_105_private), GFP_KERNEL); if (!priv) { @@ -293,10 +294,10 @@ static int klsi_105_startup (struct usb_ usb_set_serial_port_data(serial->port[i], priv); spin_lock_init (&priv->lock); - for (i=0; iwrite_urb_pool[i] = urb; + priv->write_urb_pool[j] = urb; if (urb == NULL) { err("No more urbs???"); continue; diff -puN drivers/usb/serial/pl2303.c~bk-usb drivers/usb/serial/pl2303.c --- 25/drivers/usb/serial/pl2303.c~bk-usb 2004-03-10 21:44:00.000000000 -0800 +++ 25-akpm/drivers/usb/serial/pl2303.c 2004-03-10 21:44:01.000000000 -0800 @@ -403,7 +403,7 @@ static int pl2303_open (struct usb_seria { struct termios tmp_termios; struct usb_serial *serial = port->serial; - unsigned char buf[10]; + unsigned char *buf; int result; if (port_paranoia_check (port, __FUNCTION__)) @@ -414,6 +414,10 @@ static int pl2303_open (struct usb_seria usb_clear_halt(serial->dev, port->write_urb->pipe); usb_clear_halt(serial->dev, port->read_urb->pipe); + buf = kmalloc(10, GFP_KERNEL); + if (buf==NULL) + return -ENOMEM; + #define FISH(a,b,c,d) \ result=usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev,0), \ b, a, c, d, buf, 1, 100); \ @@ -433,6 +437,8 @@ static int pl2303_open (struct usb_seria FISH (VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, 0x8484, 0); FISH (VENDOR_READ_REQUEST_TYPE, VENDOR_READ_REQUEST, 0x8383, 0); + kfree(buf); + /* Setup termios */ if (port->tty) { pl2303_set_termios (port, &tmp_termios); diff -puN drivers/usb/serial/usb-serial.c~bk-usb drivers/usb/serial/usb-serial.c --- 25/drivers/usb/serial/usb-serial.c~bk-usb 2004-03-10 21:44:00.000000000 -0800 +++ 25-akpm/drivers/usb/serial/usb-serial.c 2004-03-10 21:44:01.000000000 -0800 @@ -1006,7 +1006,7 @@ int usb_serial_probe(struct usb_interfac /* descriptor matches, let's find the endpoints needed */ /* check out the endpoints */ - iface_desc = &interface->altsetting[0]; + iface_desc = interface->cur_altsetting; for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { endpoint = &iface_desc->endpoint[i].desc; diff -puN drivers/usb/serial/visor.c~bk-usb drivers/usb/serial/visor.c --- 25/drivers/usb/serial/visor.c~bk-usb 2004-03-10 21:44:00.000000000 -0800 +++ 25-akpm/drivers/usb/serial/visor.c 2004-03-10 21:44:01.000000000 -0800 @@ -239,6 +239,8 @@ static struct usb_device_id id_table [] .driver_info = (kernel_ulong_t)&palm_os_4_probe }, { USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_SCH_I330_ID), .driver_info = (kernel_ulong_t)&palm_os_4_probe }, + { USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_SPH_I500_ID), + .driver_info = (kernel_ulong_t)&palm_os_4_probe }, { USB_DEVICE(GARMIN_VENDOR_ID, GARMIN_IQUE_3600_ID), .driver_info = (kernel_ulong_t)&palm_os_4_probe }, { USB_DEVICE(ACEECA_VENDOR_ID, ACEECA_MEZ1000_ID), @@ -275,6 +277,7 @@ static struct usb_device_id id_table_com { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_UX50_ID) }, { USB_DEVICE(SONY_VENDOR_ID, SONY_CLIE_TJ25_ID) }, { USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_SCH_I330_ID) }, + { USB_DEVICE(SAMSUNG_VENDOR_ID, SAMSUNG_SPH_I500_ID) }, { USB_DEVICE(GARMIN_VENDOR_ID, GARMIN_IQUE_3600_ID) }, { USB_DEVICE(ACEECA_VENDOR_ID, ACEECA_MEZ1000_ID) }, { }, /* optional parameter entry */ diff -puN drivers/usb/serial/visor.h~bk-usb drivers/usb/serial/visor.h --- 25/drivers/usb/serial/visor.h~bk-usb 2004-03-10 21:44:00.000000000 -0800 +++ 25-akpm/drivers/usb/serial/visor.h 2004-03-10 21:44:01.000000000 -0800 @@ -46,6 +46,7 @@ #define SAMSUNG_VENDOR_ID 0x04E8 #define SAMSUNG_SCH_I330_ID 0x8001 +#define SAMSUNG_SPH_I500_ID 0x6601 #define GARMIN_VENDOR_ID 0x091E #define GARMIN_IQUE_3600_ID 0x0004 diff -puN drivers/usb/storage/Kconfig~bk-usb drivers/usb/storage/Kconfig --- 25/drivers/usb/storage/Kconfig~bk-usb 2004-03-10 21:44:00.000000000 -0800 +++ 25-akpm/drivers/usb/storage/Kconfig 2004-03-10 21:44:01.000000000 -0800 @@ -1,8 +1,6 @@ # # USB Storage driver configuration # -comment "SCSI support is needed for USB Storage" - depends on USB && SCSI=n config USB_STORAGE tristate "USB Mass Storage support" diff -puN drivers/usb/storage/scsiglue.c~bk-usb drivers/usb/storage/scsiglue.c --- 25/drivers/usb/storage/scsiglue.c~bk-usb 2004-03-10 21:44:00.000000000 -0800 +++ 25-akpm/drivers/usb/storage/scsiglue.c 2004-03-10 21:44:01.000000000 -0800 @@ -64,8 +64,10 @@ static const char* host_info(struct Scsi return "SCSI emulation for USB Mass Storage devices"; } -static int slave_configure (struct scsi_device *sdev) +static int slave_configure(struct scsi_device *sdev) { + struct us_data *us = (struct us_data *) sdev->host->hostdata[0]; + /* Scatter-gather buffers (all but the last) must have a length * divisible by the bulk maxpacket size. Otherwise a data packet * would end up being short, causing a premature end to the data @@ -76,6 +78,16 @@ static int slave_configure (struct scsi_ * the end, scatter-gather buffers follow page boundaries. */ blk_queue_dma_alignment(sdev->request_queue, (512 - 1)); + /* Devices using Genesys Logic chips cause a lot of trouble for + * high-speed transfers; they die unpredictably when given more + * than 64 KB of data at a time. If we detect such a device, + * reduce the maximum transfer size to 64 KB = 128 sectors. */ + +#define USB_VENDOR_ID_GENESYS 0x05e3 // Needs a standard location + if (us->pusb_dev->descriptor.idVendor == USB_VENDOR_ID_GENESYS && + us->pusb_dev->speed == USB_SPEED_HIGH) + blk_queue_max_sectors(sdev->request_queue, 128); + /* this is to satisify the compiler, tho I don't think the * return code is ever checked anywhere. */ return 0; diff -puN drivers/usb/storage/transport.c~bk-usb drivers/usb/storage/transport.c --- 25/drivers/usb/storage/transport.c~bk-usb 2004-03-10 21:44:00.000000000 -0800 +++ 25-akpm/drivers/usb/storage/transport.c 2004-03-10 21:44:01.000000000 -0800 @@ -563,9 +563,9 @@ void usb_stor_invoke_transport(Scsi_Cmnd /* * If we're running the CB transport, which is incapable - * of determining status on its own, we need to auto-sense + * of determining status on its own, we will auto-sense * unless the operation involved a data-in transfer. Devices - * can signal data-in errors by stalling the bulk-in pipe. + * can signal most data-in errors by stalling the bulk-in pipe. */ if ((us->protocol == US_PR_CB || us->protocol == US_PR_DPCM_USB) && srb->sc_data_direction != SCSI_DATA_READ) { @@ -698,7 +698,11 @@ void usb_stor_invoke_transport(Scsi_Cmnd * out the sense buffer so the higher layers won't realize * we did an unsolicited auto-sense. */ if (result == USB_STOR_TRANSPORT_GOOD && - (srb->sense_buffer[2] & 0xf) == 0x0) { + /* Filemark 0, ignore EOM, ILI 0, no sense */ + (srb->sense_buffer[2] & 0xaf) == 0 && + /* No ASC or ASCQ */ + srb->sense_buffer[12] == 0 && + srb->sense_buffer[13] == 0) { srb->result = SAM_STAT_GOOD; srb->sense_buffer[0] = 0x0; } @@ -809,15 +813,19 @@ int usb_stor_CBI_transport(Scsi_Cmnd *sr } /* If not UFI, we interpret the data as a result code - * The first byte should always be a 0x0 - * The second byte & 0x0F should be 0x0 for good, otherwise error + * The first byte should always be a 0x0. + * + * Some bogus devices don't follow that rule. They stuff the ASC + * into the first byte -- so if it's non-zero, call it a failure. */ if (us->iobuf[0]) { - US_DEBUGP("CBI IRQ data showed reserved bType %d\n", + US_DEBUGP("CBI IRQ data showed reserved bType 0x%x\n", us->iobuf[0]); - return USB_STOR_TRANSPORT_ERROR; + goto Failed; + } + /* The second byte & 0x0F should be 0x0 for good, otherwise error */ switch (us->iobuf[1] & 0x0F) { case 0x00: return USB_STOR_TRANSPORT_GOOD; diff -puN drivers/usb/storage/unusual_devs.h~bk-usb drivers/usb/storage/unusual_devs.h --- 25/drivers/usb/storage/unusual_devs.h~bk-usb 2004-03-10 21:44:00.000000000 -0800 +++ 25-akpm/drivers/usb/storage/unusual_devs.h 2004-03-10 21:44:01.000000000 -0800 @@ -261,6 +261,14 @@ UNUSUAL_DEV( 0x054c, 0x0010, 0x0106, 0x US_SC_SCSI, US_PR_DEVICE, NULL, US_FL_SINGLE_LUN | US_FL_MODE_XLATE ), +/* This entry is needed because the device reports Sub=ff */ +UNUSUAL_DEV( 0x054c, 0x0010, 0x0500, 0x0500, + "Sony", + "DSC-T1", + US_SC_8070, US_PR_DEVICE, NULL, + US_FL_SINGLE_LUN | US_FL_MODE_XLATE ), + + /* Reported by wim@geeks.nl */ UNUSUAL_DEV( 0x054c, 0x0025, 0x0100, 0x0100, "Sony", @@ -368,7 +376,7 @@ UNUSUAL_DEV( 0x05ab, 0x5701, 0x0100, 0x UNUSUAL_DEV( 0x05dc, 0x0001, 0x0000, 0x0001, "Lexar", "Jumpshot USB CF Reader", - US_SC_SCSI, US_PR_JUMPSHOT, NULL, + US_SC_DEVICE, US_PR_JUMPSHOT, NULL, US_FL_MODE_XLATE ), #endif @@ -409,6 +417,13 @@ UNUSUAL_DEV( 0x05e3, 0x0702, 0x0000, 0x US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_INQUIRY ), +/* Reported by Henning Schild */ +UNUSUAL_DEV( 0x05e3, 0x0702, 0x0113, 0x0113, + "EagleTec", + "External Hard Disk", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_FIX_INQUIRY ), + /* Reported by Hanno Boeck * Taken from the Lycoris Kernel */ UNUSUAL_DEV( 0x0636, 0x0003, 0x0000, 0x9999, @@ -440,12 +455,6 @@ UNUSUAL_DEV( 0x0686, 0x4006, 0x0001, 0x0 US_SC_SCSI, US_PR_DEVICE, NULL, 0 ), -UNUSUAL_DEV( 0x0686, 0x400b, 0x0001, 0x0001, - "Minolta", - "DiMAGE 7i", - US_SC_SCSI, US_PR_DEVICE, NULL, - 0 ), - UNUSUAL_DEV( 0x0686, 0x400f, 0x0001, 0x0001, "Minolta", "DiMAGE 7Hi", @@ -619,6 +628,9 @@ UNUSUAL_DEV( 0x07c4, 0xa400, 0x0000, 0x * are using transport protocol CB. * - They don't like the INQUIRY command. So we must handle this command * of the SCSI layer ourselves. + * - Some cameras with idProduct=0x1001 and bcdDevice=0x1000 have + * bInterfaceProtocol=0x00 (US_PR_CBI) while others have 0x01 (US_PR_CB). + * So don't remove the US_PR_CB override! */ UNUSUAL_DEV( 0x07cf, 0x1001, 0x1000, 0x9009, "Casio", @@ -649,6 +661,17 @@ UNUSUAL_DEV( 0x08ca, 0x2011, 0x0000, 0x US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_MODE_XLATE ), +/* Entry needed for flags. Moreover, all devices with this ID use + * bulk-only transport, but _some_ falsely report Control/Bulk instead. + * One example is "Trumpion Digital Research MYMP3". + * Submitted by Bjoern Brill + */ +UNUSUAL_DEV( 0x090a, 0x1001, 0x0100, 0x0100, + "Trumpion", + "t33520 USB Flash Card Controller", + US_SC_DEVICE, US_PR_BULK, NULL, + US_FL_MODE_XLATE), + /* Trumpion Microelectronics MP3 player (felipe_alfaro@linuxmail.org) */ UNUSUAL_DEV( 0x090a, 0x1200, 0x0000, 0x9999, "Trumpion", @@ -688,15 +711,9 @@ UNUSUAL_DEV( 0x0a17, 0x0004, 0x1000, 0x1 US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_FIX_INQUIRY ), -/* This entry from in the Debian mailing list */ -UNUSUAL_DEV( 0x0a17, 0x0006, 0x0000, 0xffff, - "Pentax", - "Optio 330GS", - US_SC_8070, US_PR_CB, NULL, - US_FL_MODE_XLATE | US_FL_FIX_INQUIRY ), /* Submitted by Per Winkvist */ -UNUSUAL_DEV( 0x0a17, 0x006, 0x1000, 0x9009, +UNUSUAL_DEV( 0x0a17, 0x006, 0x0000, 0xffff, "Pentax", "Optio S/S4", US_SC_DEVICE, US_PR_DEVICE, NULL, diff -puN drivers/usb/storage/usb.c~bk-usb drivers/usb/storage/usb.c --- 25/drivers/usb/storage/usb.c~bk-usb 2004-03-10 21:44:00.000000000 -0800 +++ 25-akpm/drivers/usb/storage/usb.c 2004-03-10 21:44:01.000000000 -0800 @@ -423,7 +423,7 @@ static int associate_dev(struct us_data /* Fill in the device-related fields */ us->pusb_dev = interface_to_usbdev(intf); us->pusb_intf = intf; - us->ifnum = intf->altsetting->desc.bInterfaceNumber; + us->ifnum = intf->cur_altsetting->desc.bInterfaceNumber; /* Store our private data in the interface and increment the * device's reference count */ @@ -452,7 +452,7 @@ static void get_device_info(struct us_da { struct usb_device *dev = us->pusb_dev; struct usb_interface_descriptor *idesc = - &us->pusb_intf->altsetting[us->pusb_intf->act_altsetting].desc; + &us->pusb_intf->cur_altsetting->desc; struct us_unusual_dev *unusual_dev = &us_unusual_dev_list[id_index]; struct usb_device_id *id = &storage_usb_ids[id_index]; @@ -686,7 +686,7 @@ static int get_protocol(struct us_data * static int get_pipes(struct us_data *us) { struct usb_host_interface *altsetting = - &us->pusb_intf->altsetting[us->pusb_intf->act_altsetting]; + us->pusb_intf->cur_altsetting; int i; struct usb_endpoint_descriptor *ep; struct usb_endpoint_descriptor *ep_in = NULL; @@ -877,8 +877,9 @@ static int storage_probe(struct usb_inte int result; US_DEBUGP("USB Mass Storage device detected\n"); - US_DEBUGP("act_altsetting is %d, id_index is %d\n", - intf->act_altsetting, id_index); + US_DEBUGP("altsetting is %d, id_index is %d\n", + intf->cur_altsetting->desc.bAlternateSetting, + id_index); /* Allocate the us_data structure and initialize the mutexes */ us = (struct us_data *) kmalloc(sizeof(*us), GFP_KERNEL); @@ -954,8 +955,6 @@ static int storage_probe(struct usb_inte scsi_scan_host(us->host); printk(KERN_DEBUG - "WARNING: USB Mass Storage data integrity not assured\n"); - printk(KERN_DEBUG "USB Mass Storage device found at %d\n", us->pusb_dev->devnum); return 0; diff -puN drivers/usb/storage/usb.h~bk-usb drivers/usb/storage/usb.h --- 25/drivers/usb/storage/usb.h~bk-usb 2004-03-10 21:44:00.000000000 -0800 +++ 25-akpm/drivers/usb/storage/usb.h 2004-03-10 21:44:01.000000000 -0800 @@ -176,6 +176,5 @@ extern void fill_inquiry_response(struct * single queue element srb for write access */ #define scsi_unlock(host) spin_unlock_irq(host->host_lock) #define scsi_lock(host) spin_lock_irq(host->host_lock) -#define sg_address(psg) (page_address((psg).page) + (psg).offset) #endif diff -puN -L include/linux/brlvger.h include/linux/brlvger.h~bk-usb /dev/null --- 25/include/linux/brlvger.h +++ /dev/null 2002-08-30 16:31:37.000000000 -0700 @@ -1,54 +0,0 @@ -/* - * Tieman Voyager braille display USB driver. - * - * Copyright 2001-2002 Stephane Dalton - * and Stéphane Doyon - * Maintained by Stéphane Doyon . - */ -/* - * 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 - */ - -#ifndef _LINUX_BRLVGER_H -#define _LINUX_BRLVGER_H - -/* Ioctl request codes */ -#define BRLVGER_GET_INFO 0 -#define BRLVGER_DISPLAY_ON 2 -#define BRLVGER_DISPLAY_OFF 3 -#define BRLVGER_BUZZ 4 - -/* Base minor for the char devices */ -#define BRLVGER_MINOR 128 - -/* Size of some fields */ -#define BRLVGER_HWVER_SIZE 2 -#define BRLVGER_FWVER_SIZE 200 /* arbitrary, a long string */ -#define BRLVGER_SERIAL_BIN_SIZE 8 -#define BRLVGER_SERIAL_SIZE ((2*BRLVGER_SERIAL_BIN_SIZE)+1) - -struct brlvger_info { - __u8 driver_version[12]; - __u8 driver_banner[200]; - - __u32 display_length; - /* All other char[] fields are strings except this one. - Hardware version: first byte is major, second byte is minor. */ - __u8 hwver[BRLVGER_HWVER_SIZE]; - __u8 fwver[BRLVGER_FWVER_SIZE]; - __u8 serialnum[BRLVGER_SERIAL_SIZE]; -}; - -#endif diff -puN include/linux/usb_gadget.h~bk-usb include/linux/usb_gadget.h --- 25/include/linux/usb_gadget.h~bk-usb 2004-03-10 21:44:00.000000000 -0800 +++ 25-akpm/include/linux/usb_gadget.h 2004-03-10 21:44:01.000000000 -0800 @@ -465,6 +465,8 @@ struct usb_gadget_ops { * driver setup() requests * @ep_list: List of other endpoints supported by the device. * @speed: Speed of current connection to USB host. + * @is_dualspeed: True if the controller supports both high and full speed + * operation. If it does, the gadget driver must also support both. * @name: Identifies the controller hardware type. Used in diagnostics * and sometimes configuration. * @dev: Driver model state for this abstract device. @@ -488,6 +490,7 @@ struct usb_gadget { struct usb_ep *ep0; struct list_head ep_list; /* of usb_ep */ enum usb_device_speed speed; + unsigned is_dualspeed:1; const char *name; struct device dev; }; @@ -690,7 +693,7 @@ int usb_gadget_unregister_driver (struct /** * struct usb_string - wraps a C string and its USB id * @id:the (nonzero) ID for this string - * @s:the string, in ISO-8859/1 characters + * @s:the string, in UTF-8 encoding * * If you're using usb_gadget_get_string(), use this to wrap a string * together with its ID. @@ -716,6 +719,17 @@ struct usb_gadget_strings { /* put descriptor for string with that id into buf (buflen >= 256) */ int usb_gadget_get_string (struct usb_gadget_strings *table, int id, u8 *buf); +/*-------------------------------------------------------------------------*/ + +/* utility to simplify managing config descriptors */ + +/* write vector of descriptors into buffer */ +int usb_descriptor_fillbuf(void *, unsigned, + const struct usb_descriptor_header **); + +/* build config descriptor from single descriptor vector */ +int usb_gadget_config_buf(const struct usb_config_descriptor *config, + void *buf, unsigned buflen, const struct usb_descriptor_header **desc); #endif /* __KERNEL__ */ diff -puN include/linux/usb.h~bk-usb include/linux/usb.h --- 25/include/linux/usb.h~bk-usb 2004-03-10 21:44:00.000000000 -0800 +++ 25-akpm/include/linux/usb.h 2004-03-10 21:44:01.000000000 -0800 @@ -72,14 +72,11 @@ struct usb_host_interface { /** * struct usb_interface - what usb device drivers talk to - * @altsetting: array of interface descriptors, one for each alternate + * @altsetting: array of interface structures, one for each alternate * setting that may be selected. Each one includes a set of - * endpoint configurations and will be in numberic order, - * 0..num_altsetting. + * endpoint configurations. They will be in no particular order. * @num_altsetting: number of altsettings defined. - * @act_altsetting: index of current altsetting. this number is always - * less than num_altsetting. after the device is configured, each - * interface uses its default setting of zero. + * @cur_altsetting: the current altsetting. * @driver: the USB driver that is bound to this interface. * @minor: the minor number assigned to this interface, if this * interface is bound to a driver that uses the USB major number. @@ -89,6 +86,8 @@ struct usb_host_interface { * number from the USB core by calling usb_register_dev(). * @dev: driver model's view of this device * @class_dev: driver model's class view of this device. + * @released: wait for the interface to be released when changing + * configurations. * * USB device drivers attach to interfaces on a physical device. Each * interface encapsulates a single high level function, such as feeding @@ -102,26 +101,33 @@ struct usb_host_interface { * calls such as dev_get_drvdata() on the dev member of this structure. * * Each interface may have alternate settings. The initial configuration - * of a device sets the first of these, but the device driver can change + * of a device sets altsetting 0, but the device driver can change * that setting using usb_set_interface(). Alternate settings are often * used to control the the use of periodic endpoints, such as by having * different endpoints use different amounts of reserved USB bandwidth. * All standards-conformant USB devices that use isochronous endpoints * will use them in non-default settings. + * + * The USB specification says that alternate setting numbers must run from + * 0 to one less than the total number of alternate settings. But some + * devices manage to mess this up, and the structures aren't necessarily + * stored in numerical order anyhow. Use usb_altnum_to_altsetting() to + * look up an alternate setting in the altsetting array based on its number. */ struct usb_interface { - /* array of alternate settings for this interface. - * these will be in numeric order, 0..num_altsettting - */ + /* array of alternate settings for this interface, + * stored in no particular order */ struct usb_host_interface *altsetting; - unsigned act_altsetting; /* active alternate setting */ + struct usb_host_interface *cur_altsetting; /* the currently + * active alternate setting */ unsigned num_altsetting; /* number of alternate settings */ struct usb_driver *driver; /* driver */ int minor; /* minor number this interface is bound to */ struct device dev; /* interface specific device info */ struct class_device *class_dev; + struct completion *released; /* wait for release */ }; #define to_usb_interface(d) container_of(d, struct usb_interface, dev) #define interface_to_usbdev(intf) \ @@ -140,19 +146,43 @@ static inline void usb_set_intfdata (str /* this maximum is arbitrary */ #define USB_MAXINTERFACES 32 -/* USB_DT_CONFIG: Configuration descriptor information. - * - * USB_DT_OTHER_SPEED_CONFIG is the same descriptor, except that the - * descriptor type is different. Highspeed-capable devices can look - * different depending on what speed they're currently running. Only - * devices with a USB_DT_DEVICE_QUALIFIER have an OTHER_SPEED_CONFIG. +/** + * struct usb_host_config - representation of a device's configuration + * @desc: the device's configuration descriptor. + * @interface: array of usb_interface structures, one for each interface + * in the configuration. The number of interfaces is stored in + * desc.bNumInterfaces. + * @extra: pointer to buffer containing all extra descriptors associated + * with this configuration (those preceding the first interface + * descriptor). + * @extralen: length of the extra descriptors buffer. + * + * USB devices may have multiple configurations, but only one can be active + * at any time. Each encapsulates a different operational environment; + * for example, a dual-speed device would have separate configurations for + * full-speed and high-speed operation. The number of configurations + * available is stored in the device descriptor as bNumConfigurations. + * + * A configuration can contain multiple interfaces. Each corresponds to + * a different function of the USB device, and all are available whenever + * the configuration is active. The USB standard says that interfaces + * are supposed to be numbered from 0 to desc.bNumInterfaces-1, but a lot + * of devices get this wrong. In addition, the interface array is not + * guaranteed to be sorted in numerical order. Use usb_ifnum_to_if() to + * look up an interface entry based on its number. + * + * Device drivers should not attempt to activate configurations. The choice + * of which configuration to install is a policy decision based on such + * considerations as available power, functionality provided, and the user's + * desires (expressed through hotplug scripts). However, drivers can call + * usb_reset_configuration() to reinitialize the current configuration and + * all its interfaces. */ struct usb_host_config { struct usb_config_descriptor desc; - /* the interfaces associated with this configuration - * these will be in numeric order, 0..desc.bNumInterfaces - */ + /* the interfaces associated with this configuration, + * stored in no particular order */ struct usb_interface *interface[USB_MAXINTERFACES]; unsigned char *extra; /* Extra descriptors */ @@ -294,8 +324,12 @@ extern void usb_driver_release_interface const struct usb_device_id *usb_match_id(struct usb_interface *interface, const struct usb_device_id *id); -extern struct usb_interface *usb_find_interface(struct usb_driver *drv, int minor); -extern struct usb_interface *usb_ifnum_to_if(struct usb_device *dev, unsigned ifnum); +extern struct usb_interface *usb_find_interface(struct usb_driver *drv, + int minor); +extern struct usb_interface *usb_ifnum_to_if(struct usb_device *dev, + unsigned ifnum); +extern struct usb_host_interface *usb_altnum_to_altsetting( + struct usb_interface *intf, unsigned int altnum); /** @@ -461,8 +495,8 @@ extern struct bus_type usb_bus_type; * @minor_base: the start of the minor range for this driver. * * This structure is used for the usb_register_dev() and - * usb_unregister_dev() functions, to consolodate a number of the - * paramaters used for them. + * usb_unregister_dev() functions, to consolidate a number of the + * parameters used for them. */ struct usb_class_driver { char *name; @@ -520,7 +554,7 @@ typedef void (*usb_complete_t)(struct ur * @urb_list: For use by current owner of the URB. * @pipe: Holds endpoint number, direction, type, and more. * Create these values with the eight macros available; - * usb_{snd,rcv}TYPEpipe(dev,endpoint), where the type is "ctrl" + * usb_{snd,rcv}TYPEpipe(dev,endpoint), where the TYPE is "ctrl" * (control), "bulk", "int" (interrupt), or "iso" (isochronous). * For example usb_sndbulkpipe() or usb_rcvintpipe(). Endpoint * numbers range from zero to fifteen. Note that "in" endpoint two @@ -539,8 +573,8 @@ typedef void (*usb_complete_t)(struct ur * the I/O request will be performed (unless URB_NO_TRANSFER_DMA_MAP * is set). This buffer must be suitable for DMA; allocate it with * kmalloc() or equivalent. For transfers to "in" endpoints, contents - * of this buffer will be modified. This buffer is used for data - * phases of control transfers. + * of this buffer will be modified. This buffer is used for the data + * stage of control transfers. * @transfer_dma: When transfer_flags includes URB_NO_TRANSFER_DMA_MAP, * the device driver is saying that it provided this DMA address, * which the host controller driver should use in preference to the @@ -563,8 +597,7 @@ typedef void (*usb_complete_t)(struct ur * device driver has provided this DMA address for the setup packet. * The host controller driver should use this in preference to * setup_packet. - * @start_frame: Returns the initial frame for interrupt or isochronous - * transfers. + * @start_frame: Returns the initial frame for isochronous transfers. * @number_of_packets: Lists the number of ISO transfer buffers. * @interval: Specifies the polling interval for interrupt or isochronous * transfers. The units are frames (milliseconds) for for full and low @@ -632,13 +665,14 @@ typedef void (*usb_complete_t)(struct ur * Interrupt UBS must provide an interval, saying how often (in milliseconds * or, for highspeed devices, 125 microsecond units) * to poll for transfers. After the URB has been submitted, the interval - * and start_frame fields reflect how the transfer was actually scheduled. + * field reflects how the transfer was actually scheduled. * The polling interval may be more frequent than requested. * For example, some controllers have a maximum interval of 32 microseconds, * while others support intervals of up to 1024 microseconds. * Isochronous URBs also have transfer intervals. (Note that for isochronous * endpoints, as well as high speed interrupt endpoints, the encoding of - * the transfer interval in the endpoint descriptor is logarithmic.) + * the transfer interval in the endpoint descriptor is logarithmic. + * Device drivers must convert that value to linear units themselves.) * * Isochronous URBs normally use the URB_ISO_ASAP transfer flag, telling * the host controller to schedule the transfer as soon as bandwidth @@ -671,8 +705,9 @@ typedef void (*usb_complete_t)(struct ur * The context field is normally used to link URBs back to the relevant * driver or request state. * - * When completion callback is invoked for non-isochronous URBs, the - * actual_length field tells how many bytes were transferred. + * When the completion callback is invoked for non-isochronous URBs, the + * actual_length field tells how many bytes were transferred. This field + * is updated even when the URB terminated with an error or was unlinked. * * ISO transfer status is reported in the status and actual_length fields * of the iso_frame_desc array, and the number of errors is reported in @@ -699,9 +734,9 @@ struct urb int actual_length; /* (return) actual transfer length */ unsigned char *setup_packet; /* (in) setup packet (control only) */ dma_addr_t setup_dma; /* (in) dma addr for setup_packet */ - int start_frame; /* (modify) start frame (INT/ISO) */ + int start_frame; /* (modify) start frame (ISO) */ int number_of_packets; /* (in) number of ISO packets */ - int interval; /* (in) transfer interval (INT/ISO) */ + int interval; /* (modify) transfer interval (INT/ISO) */ int error_count; /* (return) number of ISO errors */ int timeout; /* (in) timeout, in jiffies */ void *context; /* (in) context for completion */ diff -puN MAINTAINERS~bk-usb MAINTAINERS --- 25/MAINTAINERS~bk-usb 2004-03-10 21:44:00.000000000 -0800 +++ 25-akpm/MAINTAINERS 2004-03-10 21:44:00.000000000 -0800 @@ -1966,13 +1966,6 @@ P: Romain Lievin M: roms@lpg.ticalc.org S: Maintained -TIEMAN VOYAGER USB BRAILLE DISPLAY DRIVER -P: Stephane Dalton -M: sdalton@videotron.ca -P: Stéphane Doyon -M: s.doyon@videotron.ca -S: Maintained - TLAN NETWORK DRIVER P: Samuel Chessman M: chessman@tux.org @@ -2154,14 +2147,6 @@ L: linux-usb-devel@lists.sourceforge.net W: http://pegasus2.sourceforge.net/ 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 P: Jeroen Vreeken M: pe1rxq@amsat.org _