Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
L
linux
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
linux
Commits
eba9fb15
Commit
eba9fb15
authored
Mar 07, 2004
by
Greg Kroah-Hartman
Browse files
Options
Browse Files
Download
Plain Diff
merge
parents
52d820cb
118d79a8
Changes
48
Hide whitespace changes
Inline
Side-by-side
Showing
48 changed files
with
2453 additions
and
718 deletions
+2453
-718
Documentation/DocBook/gadget.tmpl
Documentation/DocBook/gadget.tmpl
+1
-0
Documentation/usb/error-codes.txt
Documentation/usb/error-codes.txt
+3
-1
Documentation/usb/mtouchusb.txt
Documentation/usb/mtouchusb.txt
+85
-0
Documentation/usb/scanner.txt
Documentation/usb/scanner.txt
+0
-336
drivers/input/joystick/iforce/iforce-usb.c
drivers/input/joystick/iforce/iforce-usb.c
+1
-1
drivers/net/irda/stir4200.c
drivers/net/irda/stir4200.c
+46
-0
drivers/usb/Makefile
drivers/usb/Makefile
+5
-0
drivers/usb/class/audio.c
drivers/usb/class/audio.c
+13
-9
drivers/usb/core/config.c
drivers/usb/core/config.c
+2
-7
drivers/usb/core/devio.c
drivers/usb/core/devio.c
+6
-15
drivers/usb/core/driverfs.c
drivers/usb/core/driverfs.c
+2
-6
drivers/usb/core/hcd-pci.c
drivers/usb/core/hcd-pci.c
+4
-0
drivers/usb/core/hub.c
drivers/usb/core/hub.c
+6
-6
drivers/usb/core/message.c
drivers/usb/core/message.c
+55
-26
drivers/usb/core/usb.c
drivers/usb/core/usb.c
+35
-7
drivers/usb/gadget/Makefile
drivers/usb/gadget/Makefile
+1
-1
drivers/usb/gadget/config.c
drivers/usb/gadget/config.c
+116
-0
drivers/usb/gadget/ether.c
drivers/usb/gadget/ether.c
+50
-73
drivers/usb/gadget/usbstring.c
drivers/usb/gadget/usbstring.c
+78
-14
drivers/usb/host/Kconfig
drivers/usb/host/Kconfig
+9
-0
drivers/usb/host/ehci-dbg.c
drivers/usb/host/ehci-dbg.c
+5
-1
drivers/usb/host/ehci-hcd.c
drivers/usb/host/ehci-hcd.c
+1
-7
drivers/usb/host/ehci-sched.c
drivers/usb/host/ehci-sched.c
+447
-78
drivers/usb/host/ehci.h
drivers/usb/host/ehci.h
+6
-8
drivers/usb/host/uhci-hcd.c
drivers/usb/host/uhci-hcd.c
+37
-44
drivers/usb/host/uhci-hcd.h
drivers/usb/host/uhci-hcd.h
+1
-1
drivers/usb/input/Kconfig
drivers/usb/input/Kconfig
+26
-0
drivers/usb/input/Makefile
drivers/usb/input/Makefile
+4
-2
drivers/usb/input/ati_remote.c
drivers/usb/input/ati_remote.c
+851
-0
drivers/usb/input/hid-core.c
drivers/usb/input/hid-core.c
+1
-1
drivers/usb/input/kbtab.c
drivers/usb/input/kbtab.c
+6
-3
drivers/usb/input/mtouchusb.c
drivers/usb/input/mtouchusb.c
+391
-0
drivers/usb/input/usbkbd.c
drivers/usb/input/usbkbd.c
+1
-1
drivers/usb/input/usbmouse.c
drivers/usb/input/usbmouse.c
+1
-1
drivers/usb/misc/usbtest.c
drivers/usb/misc/usbtest.c
+10
-14
drivers/usb/net/usbnet.c
drivers/usb/net/usbnet.c
+10
-1
drivers/usb/serial/ftdi_sio.c
drivers/usb/serial/ftdi_sio.c
+3
-0
drivers/usb/serial/ftdi_sio.h
drivers/usb/serial/ftdi_sio.h
+2
-0
drivers/usb/serial/kl5kusb105.c
drivers/usb/serial/kl5kusb105.c
+3
-2
drivers/usb/serial/visor.c
drivers/usb/serial/visor.c
+3
-0
drivers/usb/serial/visor.h
drivers/usb/serial/visor.h
+1
-0
drivers/usb/storage/scsiglue.c
drivers/usb/storage/scsiglue.c
+13
-1
drivers/usb/storage/transport.c
drivers/usb/storage/transport.c
+15
-7
drivers/usb/storage/unusual_devs.h
drivers/usb/storage/unusual_devs.h
+24
-14
drivers/usb/storage/usb.c
drivers/usb/storage/usb.c
+6
-7
drivers/usb/storage/usb.h
drivers/usb/storage/usb.h
+0
-1
include/linux/usb.h
include/linux/usb.h
+55
-21
include/linux/usb_gadget.h
include/linux/usb_gadget.h
+12
-1
No files found.
Documentation/DocBook/gadget.tmpl
View file @
eba9fb15
...
...
@@ -454,6 +454,7 @@ but some optional utilities are provided to simplify common tasks.
</para>
!Edrivers/usb/gadget/usbstring.c
!Edrivers/usb/gadget/config.c
</sect1>
</chapter>
...
...
Documentation/usb/error-codes.txt
View file @
eba9fb15
...
...
@@ -70,7 +70,9 @@ one or more packets could finish before an error stops further endpoint I/O.
(That is, if drivers see this it's a bug.)
-EPROTO (*) a) bitstuff error
b) unknown USB error
b) no response packet received within the
prescribed bus turn-around time
c) unknown USB error
-EILSEQ (*) CRC mismatch
...
...
Documentation/usb/mtouchusb.txt
0 → 100644
View file @
eba9fb15
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/
Documentation/usb/scanner.txt
deleted
100644 → 0
View file @
52d820cb
Copyright (C) 1999, 2000 David E. Nelson <dnelson@jump.net>
Updated 2003 by Henning Meier-Geinitz <henning@meier-geinitz.de>
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 <dnelson@jump.net>, 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 <stdio.h>
#include <stdlib.h>
#include <error.h>
#include <unistd.h>
#include <fcntl.h>
/*
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);
}
drivers/input/joystick/iforce/iforce-usb.c
View file @
eba9fb15
...
...
@@ -135,7 +135,7 @@ static int iforce_usb_probe(struct usb_interface *intf,
struct
usb_endpoint_descriptor
*
epirq
,
*
epout
;
struct
iforce
*
iforce
;
interface
=
&
intf
->
altsetting
[
intf
->
act_altsetting
]
;
interface
=
intf
->
cur_altsetting
;
epirq
=
&
interface
->
endpoint
[
0
].
desc
;
epout
=
&
interface
->
endpoint
[
1
].
desc
;
...
...
drivers/net/irda/stir4200.c
View file @
eba9fb15
...
...
@@ -1040,6 +1040,52 @@ static struct net_device_stats *stir_net_get_stats(struct net_device *dev)
return
&
stir
->
stats
;
}
/*
* Parse the various endpoints and find the one we need.
*
* The endpoint are the pipes used to communicate with the USB device.
* The spec defines 2 endpoints of type bulk transfer, one in, and one out.
* These are used to pass frames back and forth with the dongle.
*/
static
int
stir_setup_usb
(
struct
stir_cb
*
stir
,
struct
usb_interface
*
intf
)
{
struct
usb_device
*
usbdev
=
interface_to_usbdev
(
intf
);
const
struct
usb_host_interface
*
interface
=
intf
->
cur_altsetting
;
const
struct
usb_endpoint_descriptor
*
ep_in
=
NULL
;
const
struct
usb_endpoint_descriptor
*
ep_out
=
NULL
;
int
i
;
if
(
interface
->
desc
.
bNumEndpoints
!=
2
)
{
WARNING
(
"%s: expected two endpoints
\n
"
,
__FUNCTION__
);
return
-
ENODEV
;
}
for
(
i
=
0
;
i
<
interface
->
desc
.
bNumEndpoints
;
i
++
)
{
const
struct
usb_endpoint_descriptor
*
ep
=
&
interface
->
endpoint
[
i
].
desc
;
if
((
ep
->
bmAttributes
&
USB_ENDPOINT_XFERTYPE_MASK
)
==
USB_ENDPOINT_XFER_BULK
)
{
/* We need to find an IN and an OUT */
if
((
ep
->
bEndpointAddress
&
USB_ENDPOINT_DIR_MASK
)
==
USB_DIR_IN
)
ep_in
=
ep
;
else
ep_out
=
ep
;
}
else
WARNING
(
"%s: unknown endpoint type 0x%x
\n
"
,
__FUNCTION__
,
ep
->
bmAttributes
);
}
if
(
!
ep_in
||
!
ep_out
)
return
-
EIO
;
stir
->
tx_bulkpipe
=
usb_sndbulkpipe
(
usbdev
,
ep_out
->
bEndpointAddress
&
USB_ENDPOINT_NUMBER_MASK
);
stir
->
rx_intpipe
=
usb_rcvintpipe
(
usbdev
,
ep_in
->
bEndpointAddress
&
USB_ENDPOINT_NUMBER_MASK
);
return
0
;
}
/*
* This routine is called by the USB subsystem for each new device
* in the system. We need to check if the device is ours, and in
...
...
drivers/usb/Makefile
View file @
eba9fb15
...
...
@@ -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/
...
...
drivers/usb/class/audio.c
View file @
eba9fb15
...
...
@@ -3,7 +3,7 @@
/*
* audio.c -- USB Audio Class driver
*
* Copyright (C) 1999, 2000, 2001
* Copyright (C) 1999, 2000, 2001
, 2003, 2004
* Alan Cox (alan@lxorguk.ukuu.org.uk)
* Thomas Sailer (sailer@ife.ee.ethz.ch)
*
...
...
@@ -101,6 +101,8 @@
* Fix SNDCTL_DSP_STEREO API violation
* 2003-04-08: Oliver Neukum (oliver@neukum.name):
* Setting a configuration is done by usbcore and must not be overridden
* 2004-02-27: Workaround for broken synch descriptors
*
*/
/*
...
...
@@ -1542,12 +1544,13 @@ static int set_format_in(struct usb_audiodev *as)
alts
->
endpoint
[
1
].
desc
.
bmAttributes
!=
0x01
||
alts
->
endpoint
[
1
].
desc
.
bSynchAddress
!=
0
||
alts
->
endpoint
[
1
].
desc
.
bEndpointAddress
!=
(
alts
->
endpoint
[
0
].
desc
.
bSynchAddress
&
0x7f
))
{
printk
(
KERN_ERR
"usbaudio: device %d interface %d altsetting %d invalid synch pipe
\n
"
,
printk
(
KERN_WARNING
"usbaudio: device %d interface %d altsetting %d claims adaptive in "
"but has invalid synch pipe; treating as asynchronous in
\n
"
,
dev
->
devnum
,
u
->
interface
,
fmt
->
altsetting
);
return
-
1
;
}
else
{
u
->
syncpipe
=
usb_sndisocpipe
(
dev
,
alts
->
endpoint
[
1
].
desc
.
bEndpointAddress
&
0xf
);
u
->
syncinterval
=
alts
->
endpoint
[
1
].
desc
.
bRefresh
;
}
u
->
syncpipe
=
usb_sndisocpipe
(
dev
,
alts
->
endpoint
[
1
].
desc
.
bEndpointAddress
&
0xf
);
u
->
syncinterval
=
alts
->
endpoint
[
1
].
desc
.
bRefresh
;
}
if
(
d
->
srate
<
fmt
->
sratelo
)
d
->
srate
=
fmt
->
sratelo
;
...
...
@@ -1637,12 +1640,13 @@ static int set_format_out(struct usb_audiodev *as)
alts
->
endpoint
[
1
].
desc
.
bmAttributes
!=
0x01
||
alts
->
endpoint
[
1
].
desc
.
bSynchAddress
!=
0
||
alts
->
endpoint
[
1
].
desc
.
bEndpointAddress
!=
(
alts
->
endpoint
[
0
].
desc
.
bSynchAddress
|
0x80
))
{
printk
(
KERN_ERR
"usbaudio: device %d interface %d altsetting %d invalid synch pipe
\n
"
,
printk
(
KERN_WARNING
"usbaudio: device %d interface %d altsetting %d claims asynch out "
"but has invalid synch pipe; treating as adaptive out
\n
"
,
dev
->
devnum
,
u
->
interface
,
fmt
->
altsetting
);
return
-
1
;
}
else
{
u
->
syncpipe
=
usb_rcvisocpipe
(
dev
,
alts
->
endpoint
[
1
].
desc
.
bEndpointAddress
&
0xf
);
u
->
syncinterval
=
alts
->
endpoint
[
1
].
desc
.
bRefresh
;
}
u
->
syncpipe
=
usb_rcvisocpipe
(
dev
,
alts
->
endpoint
[
1
].
desc
.
bEndpointAddress
&
0xf
);
u
->
syncinterval
=
alts
->
endpoint
[
1
].
desc
.
bRefresh
;
}
if
(
d
->
srate
<
fmt
->
sratelo
)
d
->
srate
=
fmt
->
sratelo
;
...
...
drivers/usb/core/config.c
View file @
eba9fb15
...
...
@@ -72,13 +72,10 @@ static int usb_parse_endpoint(struct usb_host_endpoint *endpoint, unsigned char
return
buffer
-
buffer0
;
}
static
void
usb_
release_intf
(
struct
device
*
dev
)
static
void
usb_
free_intf
(
struct
usb_interface
*
intf
)
{
struct
usb_interface
*
intf
;
int
j
;
intf
=
to_usb_interface
(
dev
);
if
(
intf
->
altsetting
)
{
for
(
j
=
0
;
j
<
intf
->
num_altsetting
;
j
++
)
{
struct
usb_host_interface
*
as
=
&
intf
->
altsetting
[
j
];
...
...
@@ -235,8 +232,6 @@ int usb_parse_configuration(struct usb_host_config *config, char *buffer, int si
return
-
ENOMEM
;
}
memset
(
interface
,
0
,
sizeof
(
struct
usb_interface
));
interface
->
dev
.
release
=
usb_release_intf
;
device_initialize
(
&
interface
->
dev
);
}
/* Go through the descriptors, checking their length and counting the
...
...
@@ -374,7 +369,7 @@ void usb_destroy_configuration(struct usb_device *dev)
struct
usb_interface
*
ifp
=
cf
->
interface
[
i
];
if
(
ifp
)
put_device
(
&
ifp
->
dev
);
usb_free_intf
(
ifp
);
}
}
kfree
(
dev
->
config
);
...
...
drivers/usb/core/devio.c
View file @
eba9fb15
...
...
@@ -430,19 +430,14 @@ static int findintfep(struct usb_device *dev, unsigned int ep)
static
int
findintfif
(
struct
usb_device
*
dev
,
unsigned
int
ifn
)
{
unsigned
int
i
,
j
;
struct
usb_interface
*
iface
;
struct
usb_host_interface
*
alts
;
unsigned
int
i
;
if
(
ifn
&
~
0xff
)
return
-
EINVAL
;
for
(
i
=
0
;
i
<
dev
->
actconfig
->
desc
.
bNumInterfaces
;
i
++
)
{
iface
=
dev
->
actconfig
->
interface
[
i
];
for
(
j
=
0
;
j
<
iface
->
num_altsetting
;
j
++
)
{
alts
=
&
iface
->
altsetting
[
j
];
if
(
alts
->
desc
.
bInterfaceNumber
==
ifn
)
return
i
;
}
if
(
dev
->
actconfig
->
interface
[
i
]
->
altsetting
[
0
].
desc
.
bInterfaceNumber
==
ifn
)
return
i
;
}
return
-
ENOENT
;
}
...
...
@@ -688,9 +683,7 @@ static int proc_getdriver(struct dev_state *ps, void __user *arg)
return
-
EFAULT
;
if
((
ret
=
findintfif
(
ps
->
dev
,
gd
.
interface
))
<
0
)
return
ret
;
interface
=
usb_ifnum_to_if
(
ps
->
dev
,
gd
.
interface
);
if
(
!
interface
)
return
-
EINVAL
;
interface
=
ps
->
dev
->
actconfig
->
interface
[
ret
];
if
(
!
interface
->
driver
)
return
-
ENODATA
;
strcpy
(
gd
.
driver
,
interface
->
driver
->
name
);
...
...
@@ -744,9 +737,7 @@ static int proc_setintf(struct dev_state *ps, void __user *arg)
return
-
EFAULT
;
if
((
ret
=
findintfif
(
ps
->
dev
,
setintf
.
interface
))
<
0
)
return
ret
;
interface
=
usb_ifnum_to_if
(
ps
->
dev
,
setintf
.
interface
);
if
(
!
interface
)
return
-
EINVAL
;
interface
=
ps
->
dev
->
actconfig
->
interface
[
ret
];
if
(
interface
->
driver
)
{
if
((
ret
=
checkintf
(
ps
,
ret
)))
return
ret
;
...
...
drivers/usb/core/driverfs.c
View file @
eba9fb15
...
...
@@ -166,13 +166,9 @@ void usb_create_driverfs_dev_files (struct usb_device *udev)
static ssize_t \
show_##field (struct device *dev, char *buf) \
{ \
struct usb_interface *intf; \
int alt; \
struct usb_interface *intf = to_usb_interface (dev); \
\
intf = to_usb_interface (dev); \
alt = intf->act_altsetting; \
\
return sprintf (buf, format_string, intf->altsetting[alt].desc.field); \
return sprintf (buf, format_string, intf->cur_altsetting->desc.field); \
} \
static DEVICE_ATTR(field, S_IRUGO, show_##field, NULL);
...
...
drivers/usb/core/hcd-pci.c
View file @
eba9fb15
...
...
@@ -147,8 +147,12 @@ int usb_hcd_pci_probe (struct pci_dev *dev, const struct pci_device_id *id)
hcd
->
driver
=
driver
;
hcd
->
description
=
driver
->
description
;
hcd
->
self
.
bus_name
=
pci_name
(
dev
);
#ifdef CONFIG_PCI_NAMES
hcd
->
product_desc
=
dev
->
pretty_name
;
#else
if
(
hcd
->
product_desc
==
NULL
)
hcd
->
product_desc
=
"USB Host Controller"
;
#endif
hcd
->
self
.
controller
=
&
dev
->
dev
;
if
((
retval
=
hcd_buffer_create
(
hcd
))
!=
0
)
{
...
...
drivers/usb/core/hub.c
View file @
eba9fb15
...
...
@@ -560,7 +560,7 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)
struct
usb_hub
*
hub
;
unsigned
long
flags
;
desc
=
intf
->
altsetting
+
intf
->
act
_altsetting
;
desc
=
intf
->
cur
_altsetting
;
dev
=
interface_to_usbdev
(
intf
);
/* Some hubs have a subclass of 1, which AFAICT according to the */
...
...
@@ -1344,15 +1344,15 @@ int usb_physical_reset_device(struct usb_device *dev)
for
(
i
=
0
;
i
<
dev
->
actconfig
->
desc
.
bNumInterfaces
;
i
++
)
{
struct
usb_interface
*
intf
=
dev
->
actconfig
->
interface
[
i
];
struct
usb_interface_descriptor
*
as
;
struct
usb_interface_descriptor
*
desc
;
as
=
&
intf
->
altsetting
[
intf
->
act_altsetting
].
desc
;
ret
=
usb_set_interface
(
dev
,
as
->
bInterfaceNumber
,
as
->
bAlternateSetting
);
desc
=
&
intf
->
cur_altsetting
->
desc
;
ret
=
usb_set_interface
(
dev
,
desc
->
bInterfaceNumber
,
desc
->
bAlternateSetting
);
if
(
ret
<
0
)
{
err
(
"failed to set active alternate setting "
"for dev %s interface %d (error=%d)"
,
dev
->
devpath
,
i
,
ret
);
dev
->
devpath
,
desc
->
bInterfaceNumber
,
ret
);
return
ret
;
}
}
...
...
drivers/usb/core/message.c
View file @
eba9fb15
...
...
@@ -783,16 +783,22 @@ void usb_disable_endpoint(struct usb_device *dev, unsigned int epaddr)
*/
void
usb_disable_interface
(
struct
usb_device
*
dev
,
struct
usb_interface
*
intf
)
{
struct
usb_host_interface
*
hintf
=
&
intf
->
altsetting
[
intf
->
act_altsetting
];
struct
usb_host_interface
*
alt
=
intf
->
cur_altsetting
;
int
i
;
for
(
i
=
0
;
i
<
hintf
->
desc
.
bNumEndpoints
;
++
i
)
{
for
(
i
=
0
;
i
<
alt
->
desc
.
bNumEndpoints
;
++
i
)
{
usb_disable_endpoint
(
dev
,
hintf
->
endpoint
[
i
].
desc
.
bEndpointAddress
);
alt
->
endpoint
[
i
].
desc
.
bEndpointAddress
);
}
}
static
void
release_interface
(
struct
device
*
dev
)
{
struct
usb_interface
*
interface
=
to_usb_interface
(
dev
);
complete
(
interface
->
released
);
}
/*
* usb_disable_device - Disable all the endpoints for a USB device
* @dev: the device whose endpoints are being disabled
...
...
@@ -822,12 +828,16 @@ void usb_disable_device(struct usb_device *dev, int skip_ep0)
if
(
dev
->
actconfig
)
{
for
(
i
=
0
;
i
<
dev
->
actconfig
->
desc
.
bNumInterfaces
;
i
++
)
{
struct
usb_interface
*
interface
;
struct
completion
intf_completion
;
/* remove this interface */
interface
=
dev
->
actconfig
->
interface
[
i
];
dev_dbg
(
&
dev
->
dev
,
"unregistering interface %s
\n
"
,
interface
->
dev
.
bus_id
);
device_del
(
&
interface
->
dev
);
init_completion
(
&
intf_completion
);
interface
->
released
=
&
intf_completion
;
device_unregister
(
&
interface
->
dev
);
wait_for_completion
(
&
intf_completion
);
}
dev
->
actconfig
=
0
;
if
(
dev
->
state
==
USB_STATE_CONFIGURED
)
...
...
@@ -876,12 +886,11 @@ void usb_enable_endpoint(struct usb_device *dev,
void
usb_enable_interface
(
struct
usb_device
*
dev
,
struct
usb_interface
*
intf
)
{
struct
usb_host_interface
*
hintf
=
&
intf
->
altsetting
[
intf
->
act_altsetting
];
struct
usb_host_interface
*
alt
=
intf
->
cur_altsetting
;
int
i
;
for
(
i
=
0
;
i
<
hintf
->
desc
.
bNumEndpoints
;
++
i
)
usb_enable_endpoint
(
dev
,
&
hintf
->
endpoint
[
i
].
desc
);
for
(
i
=
0
;
i
<
alt
->
desc
.
bNumEndpoints
;
++
i
)
usb_enable_endpoint
(
dev
,
&
alt
->
endpoint
[
i
].
desc
);
}
/**
...
...
@@ -920,6 +929,7 @@ void usb_enable_interface(struct usb_device *dev,
int
usb_set_interface
(
struct
usb_device
*
dev
,
int
interface
,
int
alternate
)
{
struct
usb_interface
*
iface
;
struct
usb_host_interface
*
alt
;
int
ret
;
int
manual
=
0
;
...
...
@@ -929,14 +939,15 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
return
-
EINVAL
;
}
if
(
alternate
<
0
||
alternate
>=
iface
->
num_altsetting
)
alt
=
usb_altnum_to_altsetting
(
iface
,
alternate
);
if
(
!
alt
)
{
warn
(
"selecting invalid altsetting %d"
,
alternate
);
return
-
EINVAL
;
}
ret
=
usb_control_msg
(
dev
,
usb_sndctrlpipe
(
dev
,
0
),
USB_REQ_SET_INTERFACE
,
USB_RECIP_INTERFACE
,
iface
->
altsetting
[
alternate
]
.
desc
.
bAlternateSetting
,
interface
,
NULL
,
0
,
HZ
*
5
);
alternate
,
interface
,
NULL
,
0
,
HZ
*
5
);
/* 9.4.10 says devices don't need this and are free to STALL the
* request if the interface only has one alternate setting.
...
...
@@ -957,7 +968,7 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
/* prevent submissions using previous endpoint settings */
usb_disable_interface
(
dev
,
iface
);
iface
->
act_altsetting
=
alternate
;
iface
->
cur_altsetting
=
alt
;
/* If the interface only has one altsetting and the device didn't
* accept the request, we attempt to carry out the equivalent action
...
...
@@ -965,13 +976,11 @@ int usb_set_interface(struct usb_device *dev, int interface, int alternate)
* new altsetting.
*/
if
(
manual
)
{
struct
usb_host_interface
*
iface_as
=
&
iface
->
altsetting
[
alternate
];
int
i
;
for
(
i
=
0
;
i
<
iface_as
->
desc
.
bNumEndpoints
;
i
++
)
{
for
(
i
=
0
;
i
<
alt
->
desc
.
bNumEndpoints
;
i
++
)
{
unsigned
int
epaddr
=
iface_as
->
endpoint
[
i
].
desc
.
bEndpointAddress
;
alt
->
endpoint
[
i
].
desc
.
bEndpointAddress
;
unsigned
int
pipe
=
__create_pipe
(
dev
,
USB_ENDPOINT_NUMBER_MASK
&
epaddr
)
|
(
usb_endpoint_out
(
epaddr
)
?
USB_DIR_OUT
:
USB_DIR_IN
);
...
...
@@ -1045,8 +1054,19 @@ int usb_reset_configuration(struct usb_device *dev)
/* re-init hc/hcd interface/endpoint state */
for
(
i
=
0
;
i
<
config
->
desc
.
bNumInterfaces
;
i
++
)
{
struct
usb_interface
*
intf
=
config
->
interface
[
i
];
struct
usb_host_interface
*
alt
;
alt
=
usb_altnum_to_altsetting
(
intf
,
0
);
intf
->
act_altsetting
=
0
;
/* No altsetting 0? We'll assume the first altsetting.
* We could use a GetInterface call, but if a device is
* so non-compliant that it doesn't have altsetting 0
* then I wouldn't trust its reply anyway.
*/
if
(
!
alt
)
alt
=
&
intf
->
altsetting
[
0
];
intf
->
cur_altsetting
=
alt
;
usb_enable_interface
(
dev
,
intf
);
}
return
0
;
...
...
@@ -1135,25 +1155,34 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
*/
for
(
i
=
0
;
i
<
cp
->
desc
.
bNumInterfaces
;
++
i
)
{
struct
usb_interface
*
intf
=
cp
->
interface
[
i
];
struct
usb_
interface_descriptor
*
desc
;
struct
usb_
host_interface
*
alt
;
intf
->
act_altsetting
=
0
;
desc
=
&
intf
->
altsetting
[
0
].
desc
;
usb_enable_interface
(
dev
,
intf
);
alt
=
usb_altnum_to_altsetting
(
intf
,
0
);
/* No altsetting 0? We'll assume the first altsetting.
* We could use a GetInterface call, but if a device is
* so non-compliant that it doesn't have altsetting 0
* then I wouldn't trust its reply anyway.
*/
if
(
!
alt
)
alt
=
&
intf
->
altsetting
[
0
];
intf
->
cur_altsetting
=
alt
;
usb_enable_interface
(
dev
,
intf
);
intf
->
dev
.
parent
=
&
dev
->
dev
;
intf
->
dev
.
driver
=
NULL
;
intf
->
dev
.
bus
=
&
usb_bus_type
;
intf
->
dev
.
dma_mask
=
dev
->
dev
.
dma_mask
;
intf
->
dev
.
release
=
release_interface
;
sprintf
(
&
intf
->
dev
.
bus_id
[
0
],
"%d-%s:%d.%d"
,
dev
->
bus
->
busnum
,
dev
->
devpath
,
configuration
,
desc
->
bInterfaceNumber
);
alt
->
desc
.
bInterfaceNumber
);
dev_dbg
(
&
dev
->
dev
,
"registering %s (config #%d, interface %d)
\n
"
,
intf
->
dev
.
bus_id
,
configuration
,
desc
->
bInterfaceNumber
);
device_
add
(
&
intf
->
dev
);
alt
->
desc
.
bInterfaceNumber
);
device_
register
(
&
intf
->
dev
);
usb_create_driverfs_intf_files
(
intf
);
}
}
...
...
drivers/usb/core/usb.c
View file @
eba9fb15
...
...
@@ -189,7 +189,7 @@ void usb_deregister(struct usb_driver *driver)
}
/**
* usb_ifnum_to_if - get the interface object with a given interface number
(usbcore-internal)
* usb_ifnum_to_if - get the interface object with a given interface number
* @dev: the device whose current configuration is considered
* @ifnum: the desired interface
*
...
...
@@ -219,6 +219,33 @@ struct usb_interface *usb_ifnum_to_if(struct usb_device *dev, unsigned ifnum)
return
NULL
;
}
/**
* usb_altnum_to_altsetting - get the altsetting structure with a given
* alternate setting number.
* @intf: the interface containing the altsetting in question
* @altnum: the desired alternate setting number
*
* This searches the altsetting array of the specified interface for
* an entry with the correct bAlternateSetting value and returns a pointer
* to that entry, or null.
*
* Note that altsettings need not be stored sequentially by number, so
* it would be incorrect to assume that the first altsetting entry in
* the array corresponds to altsetting zero. This routine helps device
* drivers avoid such mistakes.
*/
struct
usb_host_interface
*
usb_altnum_to_altsetting
(
struct
usb_interface
*
intf
,
unsigned
int
altnum
)
{
int
i
;
for
(
i
=
0
;
i
<
intf
->
num_altsetting
;
i
++
)
{
if
(
intf
->
altsetting
[
i
].
desc
.
bAlternateSetting
==
altnum
)
return
&
intf
->
altsetting
[
i
];
}
return
NULL
;
}
/**
* usb_epnum_to_ep_desc - get the endpoint object with a given endpoint number
* @dev: the device whose current configuration+altsettings is considered
...
...
@@ -247,7 +274,7 @@ usb_epnum_to_ep_desc(struct usb_device *dev, unsigned epnum)
/* only endpoints in current altsetting are active */
intf
=
config
->
interface
[
i
];
alt
=
intf
->
altsetting
+
intf
->
act
_altsetting
;
alt
=
intf
->
cur
_altsetting
;
for
(
k
=
0
;
k
<
alt
->
desc
.
bNumEndpoints
;
k
++
)
if
(
epnum
==
alt
->
endpoint
[
k
].
desc
.
bEndpointAddress
)
...
...
@@ -421,7 +448,7 @@ usb_match_id(struct usb_interface *interface, const struct usb_device_id *id)
if
(
id
==
NULL
)
return
NULL
;
intf
=
&
interface
->
altsetting
[
interface
->
act_altsetting
]
;
intf
=
interface
->
cur_altsetting
;
dev
=
interface_to_usbdev
(
interface
);
/* It is important to check that id->driver_info is nonzero,
...
...
@@ -624,7 +651,7 @@ static int usb_hotplug (struct device *dev, char **envp, int num_envp,
scratch
+=
length
;
if
(
usb_dev
->
descriptor
.
bDeviceClass
==
0
)
{
int
alt
=
intf
->
act
_altsetting
;
struct
usb_host_interface
*
alt
=
intf
->
cur
_altsetting
;
/* 2.4 only exposed interface zero. in 2.5, hotplug
* agents are called for all interfaces, and can use
...
...
@@ -633,9 +660,9 @@ static int usb_hotplug (struct device *dev, char **envp, int num_envp,
envp
[
i
++
]
=
scratch
;
length
+=
snprintf
(
scratch
,
buffer_size
-
length
,
"INTERFACE=%d/%d/%d"
,
intf
->
altsetting
[
alt
].
desc
.
bInterfaceClass
,
intf
->
altsetting
[
alt
].
desc
.
bInterfaceSubClass
,
intf
->
altsetting
[
alt
].
desc
.
bInterfaceProtocol
);
alt
->
desc
.
bInterfaceClass
,
alt
->
desc
.
bInterfaceSubClass
,
alt
->
desc
.
bInterfaceProtocol
);
if
((
buffer_size
-
length
<=
0
)
||
(
i
>=
num_envp
))
return
-
ENOMEM
;
++
length
;
...
...
@@ -1582,6 +1609,7 @@ EXPORT_SYMBOL(usb_driver_release_interface);
EXPORT_SYMBOL
(
usb_match_id
);
EXPORT_SYMBOL
(
usb_find_interface
);
EXPORT_SYMBOL
(
usb_ifnum_to_if
);
EXPORT_SYMBOL
(
usb_altnum_to_altsetting
);
EXPORT_SYMBOL
(
usb_reset_device
);
EXPORT_SYMBOL
(
usb_disconnect
);
...
...
drivers/usb/gadget/Makefile
View file @
eba9fb15
...
...
@@ -9,7 +9,7 @@ obj-$(CONFIG_USB_GOKU) += goku_udc.o
# USB gadget drivers
#
g_zero-objs
:=
zero.o usbstring.o
g_ether-objs
:=
ether.o usbstring.o
g_ether-objs
:=
ether.o usbstring.o
config.o
g_serial-objs
:=
serial.o usbstring.o
gadgetfs-objs
:=
inode.o usbstring.o
g_file_storage-objs
:=
file_storage.o usbstring.o
...
...
drivers/usb/gadget/config.c
0 → 100644
View file @
eba9fb15
/*
* usb/gadget/config.c -- simplify building config descriptors
*
* Copyright (C) 2003 David Brownell
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/string.h>
#include <linux/device.h>
#include <linux/usb_ch9.h>
/**
* usb_descriptor_fillbuf - fill buffer with descriptors
* @buf: Buffer to be filled
* @buflen: Size of buf
* @src: Array of descriptor pointers, terminated by null pointer.
*
* Copies descriptors into the buffer, returning the length or a
* negative error code if they can't all be copied. Useful when
* assembling descriptors for an associated set of interfaces used
* as part of configuring a composite device; or in other cases where
* sets of descriptors need to be marshaled.
*/
int
usb_descriptor_fillbuf
(
void
*
buf
,
unsigned
buflen
,
const
struct
usb_descriptor_header
**
src
)
{
u8
*
dest
=
buf
;
if
(
!
src
)
return
-
EINVAL
;
/* fill buffer from src[] until null descriptor ptr */
for
(;
0
!=
*
src
;
src
++
)
{
unsigned
len
=
(
*
src
)
->
bLength
;
if
(
len
>
buflen
);
return
-
EINVAL
;
memcpy
(
dest
,
*
src
,
len
);
buflen
-=
len
;
dest
+=
len
;
}
return
dest
-
(
u8
*
)
buf
;
}
/**
* usb_gadget_config_buf - builts a complete configuration descriptor
* @config: Header for the descriptor, including characteristics such
* as power requirements and number of interfaces.
* @desc: Null-terminated vector of pointers to the descriptors (interface,
* endpoint, etc) defining all functions in this device configuration.
* @buf: Buffer for the resulting configuration descriptor.
* @length: Length of buffer. If this is not big enough to hold the
* entire configuration descriptor, an error code will be returned.
*
* This copies descriptors into the response buffer, building a descriptor
* for that configuration. It returns the buffer length or a negative
* status code. The config.wTotalLength field is set to match the length
* of the result, but other descriptor fields (including power usage and
* interface count) must be set by the caller.
*
* Gadget drivers could use this when constructing a config descriptor
* in response to USB_REQ_GET_DESCRIPTOR. They will need to patch the
* resulting bDescriptorType value if USB_DT_OTHER_SPEED_CONFIG is needed.
*/
int
usb_gadget_config_buf
(
const
struct
usb_config_descriptor
*
config
,
void
*
buf
,
unsigned
length
,
const
struct
usb_descriptor_header
**
desc
)
{
struct
usb_config_descriptor
*
cp
=
buf
;
int
len
;
/* config descriptor first */
if
(
length
<
USB_DT_CONFIG_SIZE
||
!
desc
)
return
-
EINVAL
;
*
cp
=
*
config
;
/* then interface/endpoint/class/vendor/... */
len
=
usb_descriptor_fillbuf
(
USB_DT_CONFIG_SIZE
+
(
u8
*
)
buf
,
length
-
USB_DT_CONFIG_SIZE
,
desc
);
if
(
len
<
0
)
return
len
;
len
+=
USB_DT_CONFIG_SIZE
;
if
(
len
>
0xffff
)
return
-
EINVAL
;
/* patch up the config descriptor */
cp
->
bLength
=
USB_DT_CONFIG_SIZE
;
cp
->
bDescriptorType
=
USB_DT_CONFIG
;
cp
->
wTotalLength
=
cpu_to_le16
(
len
);
cp
->
bmAttributes
|=
USB_CONFIG_ATT_ONE
;
return
len
;
}
drivers/usb/gadget/ether.c
View file @
eba9fb15
...
...
@@ -607,6 +607,25 @@ fs_sink_desc = {
.
wMaxPacketSize
=
__constant_cpu_to_le16
(
64
),
};
static
const
struct
usb_descriptor_header
*
fs_function
[]
=
{
#ifdef DEV_CONFIG_CDC
/* "cdc" mode descriptors */
(
struct
usb_descriptor_header
*
)
&
control_intf
,
(
struct
usb_descriptor_header
*
)
&
header_desc
,
(
struct
usb_descriptor_header
*
)
&
union_desc
,
(
struct
usb_descriptor_header
*
)
&
ether_desc
,
#ifdef EP_STATUS_NUM
(
struct
usb_descriptor_header
*
)
&
fs_status_desc
,
#endif
(
struct
usb_descriptor_header
*
)
&
data_nop_intf
,
#endif
/* DEV_CONFIG_CDC */
/* minimalist core */
(
struct
usb_descriptor_header
*
)
&
data_intf
,
(
struct
usb_descriptor_header
*
)
&
fs_source_desc
,
(
struct
usb_descriptor_header
*
)
&
fs_sink_desc
,
0
,
};
#ifdef HIGHSPEED
/*
...
...
@@ -660,6 +679,25 @@ dev_qualifier = {
.
bNumConfigurations
=
1
,
};
static
const
struct
usb_descriptor_header
*
hs_function
[]
=
{
#ifdef DEV_CONFIG_CDC
/* "cdc" mode descriptors */
(
struct
usb_descriptor_header
*
)
&
control_intf
,
(
struct
usb_descriptor_header
*
)
&
header_desc
,
(
struct
usb_descriptor_header
*
)
&
union_desc
,
(
struct
usb_descriptor_header
*
)
&
ether_desc
,
#ifdef EP_STATUS_NUM
(
struct
usb_descriptor_header
*
)
&
hs_status_desc
,
#endif
(
struct
usb_descriptor_header
*
)
&
data_nop_intf
,
#endif
/* DEV_CONFIG_CDC */
/* minimalist core */
(
struct
usb_descriptor_header
*
)
&
data_intf
,
(
struct
usb_descriptor_header
*
)
&
hs_source_desc
,
(
struct
usb_descriptor_header
*
)
&
hs_sink_desc
,
0
,
};
/* maxpacket and other transfer characteristics vary by speed. */
#define ep_desc(g,hs,fs) (((g)->speed==USB_SPEED_HIGH)?(hs):(fs))
...
...
@@ -704,86 +742,25 @@ static struct usb_gadget_strings stringtab = {
static
int
config_buf
(
enum
usb_device_speed
speed
,
u8
*
buf
,
u8
type
,
unsigned
index
)
{
const
unsigned
config_len
=
USB_DT_CONFIG_SIZE
#ifdef DEV_CONFIG_CDC
+
2
*
USB_DT_INTERFACE_SIZE
+
sizeof
header_desc
+
sizeof
union_desc
+
sizeof
ether_desc
#ifdef EP_STATUS_NUM
+
USB_DT_ENDPOINT_SIZE
#endif
#endif
/* DEV_CONFIG_CDC */
+
USB_DT_INTERFACE_SIZE
+
2
*
USB_DT_ENDPOINT_SIZE
;
int
len
;
const
struct
usb_descriptor_header
**
function
=
fs_function
;
#ifdef HIGHSPEED
int
hs
;
#endif
/* a single configuration must always be index 0 */
if
(
index
>
0
)
return
-
EINVAL
;
if
(
config_len
>
USB_BUFSIZ
)
return
-
EDOM
;
int
hs
=
(
speed
==
USB_SPEED_HIGH
);
/* config (or other speed config) */
memcpy
(
buf
,
&
eth_config
,
USB_DT_CONFIG_SIZE
);
buf
[
1
]
=
type
;
((
struct
usb_config_descriptor
*
)
buf
)
->
wTotalLength
=
__constant_cpu_to_le16
(
config_len
);
buf
+=
USB_DT_CONFIG_SIZE
;
#ifdef HIGHSPEED
hs
=
(
speed
==
USB_SPEED_HIGH
);
if
(
type
==
USB_DT_OTHER_SPEED_CONFIG
)
hs
=
!
hs
;
#endif
#ifdef DEV_CONFIG_CDC
/* control interface, class descriptors, optional status endpoint */
memcpy
(
buf
,
&
control_intf
,
USB_DT_INTERFACE_SIZE
);
buf
+=
USB_DT_INTERFACE_SIZE
;
memcpy
(
buf
,
&
header_desc
,
sizeof
header_desc
);
buf
+=
sizeof
header_desc
;
memcpy
(
buf
,
&
union_desc
,
sizeof
union_desc
);
buf
+=
sizeof
union_desc
;
memcpy
(
buf
,
&
ether_desc
,
sizeof
ether_desc
);
buf
+=
sizeof
ether_desc
;
#ifdef EP_STATUS_NUM
#ifdef HIGHSPEED
if
(
hs
)
memcpy
(
buf
,
&
hs_status_desc
,
USB_DT_ENDPOINT_SIZE
);
else
#endif
/* HIGHSPEED */
memcpy
(
buf
,
&
fs_status_desc
,
USB_DT_ENDPOINT_SIZE
);
buf
+=
USB_DT_ENDPOINT_SIZE
;
#endif
/* EP_STATUS_NUM */
/* default data altsetting has no endpoints */
memcpy
(
buf
,
&
data_nop_intf
,
USB_DT_INTERFACE_SIZE
);
buf
+=
USB_DT_INTERFACE_SIZE
;
#endif
/* DEV_CONFIG_CDC */
/* the "real" data interface has two endpoints */
memcpy
(
buf
,
&
data_intf
,
USB_DT_INTERFACE_SIZE
);
buf
+=
USB_DT_INTERFACE_SIZE
;
#ifdef HIGHSPEED
if
(
hs
)
{
memcpy
(
buf
,
&
hs_source_desc
,
USB_DT_ENDPOINT_SIZE
);
buf
+=
USB_DT_ENDPOINT_SIZE
;
memcpy
(
buf
,
&
hs_sink_desc
,
USB_DT_ENDPOINT_SIZE
);
buf
+=
USB_DT_ENDPOINT_SIZE
;
}
else
function
=
hs_function
;
#endif
{
memcpy
(
buf
,
&
fs_source_desc
,
USB_DT_ENDPOINT_SIZE
);
buf
+=
USB_DT_ENDPOINT_SIZE
;
memcpy
(
buf
,
&
fs_sink_desc
,
USB_DT_ENDPOINT_SIZE
);
buf
+=
USB_DT_ENDPOINT_SIZE
;
}
return
config_len
;
/* a single configuration must always be index 0 */
if
(
index
>
0
)
return
-
EINVAL
;
len
=
usb_gadget_config_buf
(
&
eth_config
,
buf
,
USB_BUFSIZ
,
function
);
if
(
len
<
0
)
return
len
;
((
struct
usb_config_descriptor
*
)
buf
)
->
bDescriptorType
=
type
;
return
len
;
}
/*-------------------------------------------------------------------------*/
...
...
drivers/usb/gadget/usbstring.c
View file @
eba9fb15
...
...
@@ -16,24 +16,89 @@
#include <linux/usb_ch9.h>
#include <linux/usb_gadget.h>
#include <asm/unaligned.h>
static
int
utf8_to_utf16le
(
const
char
*
s
,
u16
*
cp
,
unsigned
len
)
{
int
count
=
0
;
u8
c
;
u16
uchar
;
/* this insists on correct encodings, though not minimal ones.
* BUT it currently rejects legit 4-byte UTF-8 code points,
* which need surrogate pairs. (Unicode 3.1 can use them.)
*/
while
(
len
!=
0
&&
(
c
=
(
u8
)
*
s
++
)
!=
0
)
{
if
(
unlikely
(
c
&
0x80
))
{
// 2-byte sequence:
// 00000yyyyyxxxxxx = 110yyyyy 10xxxxxx
if
((
c
&
0xe0
)
==
0xc0
)
{
uchar
=
(
c
&
0x1f
)
<<
6
;
c
=
(
u8
)
*
s
++
;
if
((
c
&
0xc0
)
!=
0xc0
)
goto
fail
;
c
&=
0x3f
;
uchar
|=
c
;
// 3-byte sequence (most CJKV characters):
// zzzzyyyyyyxxxxxx = 1110zzzz 10yyyyyy 10xxxxxx
}
else
if
((
c
&
0xf0
)
==
0xe0
)
{
uchar
=
(
c
&
0x0f
)
<<
12
;
c
=
(
u8
)
*
s
++
;
if
((
c
&
0xc0
)
!=
0xc0
)
goto
fail
;
c
&=
0x3f
;
uchar
|=
c
<<
6
;
c
=
(
u8
)
*
s
++
;
if
((
c
&
0xc0
)
!=
0xc0
)
goto
fail
;
c
&=
0x3f
;
uchar
|=
c
;
/* no bogus surrogates */
if
(
0xd800
<=
uchar
&&
uchar
<=
0xdfff
)
goto
fail
;
// 4-byte sequence (surrogate pairs, currently rare):
// 11101110wwwwzzzzyy + 110111yyyyxxxxxx
// = 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx
// (uuuuu = wwww + 1)
// FIXME accept the surrogate code points (only)
}
else
goto
fail
;
}
else
uchar
=
c
;
put_unaligned
(
cpu_to_le16
(
uchar
),
cp
++
);
count
++
;
len
--
;
}
return
count
;
fail:
return
-
1
;
}
/**
* usb_gadget_get_string - fill out a string descriptor
* @table: of c strings
using iso latin/1 characters
* @table: of c strings
encoded using UTF-8
* @id: string id, from low byte of wValue in get string descriptor
* @buf: at least 256 bytes
*
* Finds the
iso latin/1
string matching the ID, and converts it into a
* Finds the
UTF-8
string matching the ID, and converts it into a
* string descriptor in utf16-le.
* Returns length of descriptor (always even) or negative errno
*
* If your driver needs stings in multiple languages, you'll need to
* to use some alternate solution for languages where the ISO 8859/1
* (latin/1) character set can't be used. For example, they can't be
* used with Chinese (Big5, GB2312, etc), Japanese, Korean, or many other
* languages. You'd likely "switch (wIndex) { ... }" in your ep0
* string descriptor logic, using this routine in cases where "western
* european" characters suffice for the strings being returned.
* If your driver needs stings in multiple languages, you'll probably
* "switch (wIndex) { ... }" in your ep0 string descriptor logic,
* using this routine after choosing which set of UTF-8 strings to use.
* Note that US-ASCII is a strict subset of UTF-8; any string bytes with
* the eighth bit set will be multibyte UTF-8 characters, not ISO-8859/1
* characters (which are also widely used in C strings).
*/
int
usb_gadget_get_string
(
struct
usb_gadget_strings
*
table
,
int
id
,
u8
*
buf
)
...
...
@@ -59,13 +124,12 @@ usb_gadget_get_string (struct usb_gadget_strings *table, int id, u8 *buf)
/* string descriptors have length, tag, then UTF16-LE text */
len
=
min
((
size_t
)
126
,
strlen
(
s
->
s
));
memset
(
buf
+
2
,
0
,
2
*
len
);
/* zero all the bytes */
len
=
utf8_to_utf16le
(
s
->
s
,
(
u16
*
)
&
buf
[
2
],
len
);
if
(
len
<
0
)
return
-
EINVAL
;
buf
[
0
]
=
(
len
+
1
)
*
2
;
buf
[
1
]
=
USB_DT_STRING
;
memset
(
buf
+
2
,
0
,
2
*
len
);
/* zero all the high bytes */
while
(
len
)
{
buf
[
2
*
len
]
=
s
->
s
[
len
-
1
];
len
--
;
}
return
buf
[
0
];
}
drivers/usb/host/Kconfig
View file @
eba9fb15
...
...
@@ -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
...
...
drivers/usb/host/ehci-dbg.c
View file @
eba9fb15
...
...
@@ -579,7 +579,11 @@ show_periodic (struct class_device *class_dev, char *buf)
break
;
case
Q_TYPE_SITD
:
temp
=
scnprintf
(
next
,
size
,
" sitd/%p"
,
p
.
sitd
);
" sitd%d-%04x/%p"
,
p
.
sitd
->
stream
->
interval
,
le32_to_cpup
(
&
p
.
sitd
->
hw_uframe
)
&
0x0000ffff
,
p
.
sitd
);
tag
=
Q_NEXT_TYPE
(
p
.
sitd
->
hw_next
);
p
=
p
.
sitd
->
sitd_next
;
break
;
...
...
drivers/usb/host/ehci-hcd.c
View file @
eba9fb15
...
...
@@ -106,8 +106,6 @@ static const char hcd_name [] = "ehci_hcd";
#undef EHCI_VERBOSE_DEBUG
#undef EHCI_URB_TRACE
// #define have_split_iso
#ifdef DEBUG
#define EHCI_STATS
#endif
...
...
@@ -676,6 +674,7 @@ static void ehci_work (struct ehci_hcd *ehci, struct pt_regs *regs)
/* the IO watchdog guards against hardware or driver bugs that
* misplace IRQs, and should let us run completely without IRQs.
* such lossage has been observed on both VT6202 and VT8235.
*/
if
((
ehci
->
async
->
qh_next
.
ptr
!=
0
)
||
(
ehci
->
periodic_sched
!=
0
))
timer_action
(
ehci
,
TIMER_IO_WATCHDOG
);
...
...
@@ -796,13 +795,8 @@ static int ehci_urb_enqueue (
case
PIPE_ISOCHRONOUS
:
if
(
urb
->
dev
->
speed
==
USB_SPEED_HIGH
)
return
itd_submit
(
ehci
,
urb
,
mem_flags
);
#ifdef have_split_iso
else
return
sitd_submit
(
ehci
,
urb
,
mem_flags
);
#else
dbg
(
"no split iso support yet"
);
return
-
ENOSYS
;
#endif
/* have_split_iso */
}
}
...
...
drivers/usb/host/ehci-sched.c
View file @
eba9fb15
...
...
@@ -53,14 +53,10 @@ periodic_next_shadow (union ehci_shadow *periodic, int tag)
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, unsigned frame, unsigned uframe)
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, unsigned frame, unsigned uframe)
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, struct ehci_iso_stream *stream)
// BUG_ON (!list_empty(&stream->td_list));
while
(
!
list_empty
(
&
stream
->
free_list
))
{
struct
ehci_itd
*
itd
;
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
);
struct
list_head
*
entry
;
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 @@ static int itd_submit (struct ehci_hcd *ehci, struct urb *urb, int mem_flags)
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 @@ scan_periodic (struct ehci_hcd *ehci, struct pt_regs *regs)
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 @@ scan_periodic (struct ehci_hcd *ehci, struct pt_regs *regs)
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
);
...
...
drivers/usb/host/ehci.h
View file @
eba9fb15
...
...
@@ -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 */
...
...
drivers/usb/host/uhci-hcd.c
View file @
eba9fb15
...
...
@@ -781,7 +781,8 @@ static void uhci_dec_fsbr(struct uhci_hcd *uhci, struct urb *urb)
/*
* Map status to standard result codes
*
* <status> is (td->status & 0xFE0000) [a.k.a. uhci_status_bits(td->status)]
* <status> is (td->status & 0xF60000) [a.k.a. uhci_status_bits(td->status)]
* Note: status does not include the TD_CTRL_NAK bit.
* <dir_out> is True for output TDs and False for input TDs.
*/
static
int
uhci_map_status
(
int
status
,
int
dir_out
)
...
...
@@ -792,22 +793,18 @@ static int uhci_map_status(int status, int dir_out)
return
-
EPROTO
;
if
(
status
&
TD_CTRL_CRCTIMEO
)
{
/* CRC/Timeout */
if
(
dir_out
)
return
-
E
TIMEDOUT
;
return
-
E
PROTO
;
else
return
-
EILSEQ
;
}
if
(
status
&
TD_CTRL_NAK
)
/* NAK */
return
-
ETIMEDOUT
;
if
(
status
&
TD_CTRL_BABBLE
)
/* Babble */
return
-
EOVERFLOW
;
if
(
status
&
TD_CTRL_DBUFERR
)
/* Buffer error */
return
-
ENOSR
;
if
(
status
&
TD_CTRL_STALLED
)
/* Stalled */
return
-
EPIPE
;
if
(
status
&
TD_CTRL_ACTIVE
)
/* Active */
return
0
;
return
-
EINVAL
;
WARN_ON
(
status
&
TD_CTRL_ACTIVE
);
/* Active */
return
0
;
}
/*
...
...
@@ -832,7 +829,7 @@ static int uhci_submit_control(struct uhci_hcd *uhci, struct urb *urb, struct ur
status
|=
TD_CTRL_LS
;
/*
* Build the TD for the control request
* Build the TD for the control request
setup packet
*/
td
=
uhci_alloc_td
(
uhci
,
urb
->
dev
);
if
(
!
td
)
...
...
@@ -990,13 +987,13 @@ static int uhci_result_control(struct uhci_hcd *uhci, struct urb *urb)
if
(
urbp
->
short_control_packet
)
{
tmp
=
head
->
prev
;
goto
status_
phas
e
;
goto
status_
stag
e
;
}
tmp
=
head
->
next
;
td
=
list_entry
(
tmp
,
struct
uhci_td
,
list
);
/* The first TD is the SETUP
phas
e, check the status, but skip */
/* The first TD is the SETUP
stag
e, check the status, but skip */
/* the count */
status
=
uhci_status_bits
(
td_status
(
td
));
if
(
status
&
TD_CTRL_ACTIVE
)
...
...
@@ -1037,10 +1034,10 @@ static int uhci_result_control(struct uhci_hcd *uhci, struct urb *urb)
}
}
status_
phas
e:
status_
stag
e:
td
=
list_entry
(
tmp
,
struct
uhci_td
,
list
);
/* Control status
phas
e */
/* Control status
stag
e */
status
=
td_status
(
td
);
#ifdef I_HAVE_BUGGY_APC_BACKUPS
...
...
@@ -1053,10 +1050,11 @@ static int uhci_result_control(struct uhci_hcd *uhci, struct urb *urb)
return
0
;
#endif
status
=
uhci_status_bits
(
status
);
if
(
status
&
TD_CTRL_ACTIVE
)
return
-
EINPROGRESS
;
if
(
uhci_status_bits
(
status
)
)
if
(
status
)
goto
td_error
;
return
0
;
...
...
@@ -1272,12 +1270,6 @@ static inline int uhci_submit_interrupt(struct uhci_hcd *uhci, struct urb *urb,
return
uhci_submit_common
(
uhci
,
urb
,
eurb
,
uhci
->
skelqh
[
__interval_to_skel
(
urb
->
interval
)]);
}
/*
* Bulk and interrupt use common result
*/
#define uhci_result_bulk uhci_result_common
#define uhci_result_interrupt uhci_result_common
/*
* Isochronous transfers
*/
...
...
@@ -1403,7 +1395,8 @@ static int uhci_result_isochronous(struct uhci_hcd *uhci, struct urb *urb)
urb
->
iso_frame_desc
[
i
].
actual_length
=
actlength
;
urb
->
actual_length
+=
actlength
;
status
=
uhci_map_status
(
uhci_status_bits
(
td_status
(
td
)),
usb_pipeout
(
urb
->
pipe
));
status
=
uhci_map_status
(
uhci_status_bits
(
td_status
(
td
)),
usb_pipeout
(
urb
->
pipe
));
urb
->
iso_frame_desc
[
i
].
status
=
status
;
if
(
status
)
{
urb
->
error_count
++
;
...
...
@@ -1508,12 +1501,9 @@ static int uhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, int mem_flags)
struct
urb_priv
*
urbp
=
urb
->
hcpriv
;
list_del_init
(
&
urbp
->
urb_list
);
spin_unlock_irqrestore
(
&
uhci
->
urb_list_lock
,
flags
);
uhci_destroy_urb_priv
(
uhci
,
urb
);
return
ret
;
}
ret
=
0
;
uhci_destroy_urb_priv
(
uhci
,
urb
);
}
else
ret
=
0
;
out:
spin_unlock_irqrestore
(
&
uhci
->
urb_list_lock
,
flags
);
...
...
@@ -1541,11 +1531,9 @@ static void uhci_transfer_result(struct uhci_hcd *uhci, struct urb *urb)
case
PIPE_CONTROL
:
ret
=
uhci_result_control
(
uhci
,
urb
);
break
;
case
PIPE_INTERRUPT
:
ret
=
uhci_result_interrupt
(
uhci
,
urb
);
break
;
case
PIPE_BULK
:
ret
=
uhci_result_bulk
(
uhci
,
urb
);
case
PIPE_INTERRUPT
:
ret
=
uhci_result_common
(
uhci
,
urb
);
break
;
case
PIPE_ISOCHRONOUS
:
ret
=
uhci_result_isochronous
(
uhci
,
urb
);
...
...
@@ -1649,10 +1637,12 @@ static int uhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb)
{
struct
uhci_hcd
*
uhci
=
hcd_to_uhci
(
hcd
);
unsigned
long
flags
;
struct
urb_priv
*
urbp
=
urb
->
hcpriv
;
struct
urb_priv
*
urbp
;
spin_lock_irqsave
(
&
uhci
->
urb_list_lock
,
flags
);
urbp
=
urb
->
hcpriv
;
if
(
!
urbp
)
/* URB was never linked! */
goto
done
;
list_del_init
(
&
urbp
->
urb_list
);
uhci_unlink_generic
(
uhci
,
urb
);
...
...
@@ -1665,6 +1655,7 @@ static int uhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb)
list_add_tail
(
&
urbp
->
urb_list
,
&
uhci
->
urb_remove_list
);
spin_unlock
(
&
uhci
->
urb_remove_list_lock
);
done:
spin_unlock_irqrestore
(
&
uhci
->
urb_list_lock
,
flags
);
return
0
;
}
...
...
@@ -1861,17 +1852,12 @@ static void uhci_finish_completion(struct usb_hcd *hcd, struct pt_regs *regs)
static
void
uhci_remove_pending_urbps
(
struct
uhci_hcd
*
uhci
)
{
struct
list_head
*
tmp
,
*
head
;
spin_lock
(
&
uhci
->
urb_remove_list_lock
);
head
=
&
uhci
->
urb_remove_list
;
tmp
=
head
->
next
;
while
(
tmp
!=
head
)
{
struct
urb_priv
*
urbp
=
list_entry
(
tmp
,
struct
urb_priv
,
urb_list
);
spin_lock
(
&
uhci
->
complete_list_lock
);
tmp
=
tmp
->
next
;
uhci_moveto_complete
(
uhci
,
urbp
);
}
/* Splice the urb_remove_list onto the end of the complete_list */
list_splice_init
(
&
uhci
->
urb_remove_list
,
uhci
->
complete_list
.
prev
);
spin_unlock
(
&
uhci
->
complete_list_lock
);
spin_unlock
(
&
uhci
->
urb_remove_list_lock
);
}
...
...
@@ -2471,9 +2457,16 @@ static int uhci_resume(struct usb_hcd *hcd)
pci_set_master
(
to_pci_dev
(
uhci_dev
(
uhci
)));
if
(
uhci
->
state
==
UHCI_SUSPENDED
)
if
(
uhci
->
state
==
UHCI_SUSPENDED
)
{
/*
* Some systems clear the Interrupt Enable register during
* PM suspend/resume, so reinitialize it.
*/
outw
(
USBINTR_TIMEOUT
|
USBINTR_RESUME
|
USBINTR_IOC
|
USBINTR_SP
,
uhci
->
io_addr
+
USBINTR
);
uhci
->
resume_detect
=
1
;
else
{
}
else
{
reset_hc
(
uhci
);
start_hc
(
uhci
);
}
...
...
drivers/usb/host/uhci-hcd.h
View file @
eba9fb15
...
...
@@ -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) & 0xF
E
0000)
#define uhci_status_bits(ctrl_sts) ((ctrl_sts) & 0xF
6
0000)
#define uhci_actual_length(ctrl_sts) (((ctrl_sts) + 1) & TD_CTRL_ACTLEN_MASK)
/* 1-based */
/*
...
...
drivers/usb/input/Kconfig
View file @
eba9fb15
...
...
@@ -179,6 +179,18 @@ config USB_POWERMATE
To compile this driver as a module, choose M here: the
module will be called powermate.
config USB_MTOUCH
tristate "MicroTouch USB Touchscreen Driver"
depends on USB && INPUT
---help---
Say Y here if you want to use a MicroTouch (Now 3M) USB
Touchscreen controller.
See <file:Documentation/usb/mtouch.txt> for additional information.
To compile this driver as a module, choose M here: the
module will be called mtouchusb.
config USB_XPAD
tristate "X-Box gamepad support"
depends on USB && INPUT
...
...
@@ -192,3 +204,17 @@ config USB_XPAD
To compile this driver as a module, choose M here: the
module will be called xpad.
config USB_ATI_REMOTE
tristate "ATI USB RF remote control"
depends on USB && INPUT
---help---
Say Y here if you want to use one of ATI's USB remote controls.
These are RF remotes with USB receivers. They come with many of ATI's
All-In-Wonder video cards. This driver provides mouse pointer, left
and right mouse buttons, and maps all the other remote buttons to
keypress events.
To compile this driver as a module, choose M here: the module will be
called ati_remote.
drivers/usb/input/Makefile
View file @
eba9fb15
...
...
@@ -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
drivers/usb/input/ati_remote.c
0 → 100644
View file @
eba9fb15
/*
* USB ATI Remote support
*
* Version 2.2.0 Copyright (c) 2004 Torrey Hoffman <thoffman@arnor.net>
* 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 <thoffman@arnor.net>
* 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 <linux/config.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/input.h>
#include <linux/usb.h>
/*
* 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 <thoffman@arnor.net>"
#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"
);
drivers/usb/input/hid-core.c
View file @
eba9fb15
...
...
@@ -1445,7 +1445,7 @@ static void hid_free_buffers(struct usb_device *dev, struct hid_device *hid)
static
struct
hid_device
*
usb_hid_configure
(
struct
usb_interface
*
intf
)
{
struct
usb_host_interface
*
interface
=
intf
->
altsetting
+
intf
->
act
_altsetting
;
struct
usb_host_interface
*
interface
=
intf
->
cur
_altsetting
;
struct
usb_device
*
dev
=
interface_to_usbdev
(
intf
);
struct
hid_descriptor
*
hdesc
;
struct
hid_device
*
hid
;
...
...
drivers/usb/input/kbtab.c
View file @
eba9fb15
...
...
@@ -74,12 +74,15 @@ static void kbtab_irq(struct urb *urb, struct pt_regs *regs)
input_report_abs
(
dev
,
ABS_X
,
kbtab
->
x
);
input_report_abs
(
dev
,
ABS_Y
,
kbtab
->
y
);
/*input_report_abs(dev, ABS_PRESSURE, kbtab->pressure);*/
/*input_report_key(dev, BTN_TOUCH , data[0] & 0x01);*/
input_report_key
(
dev
,
BTN_RIGHT
,
data
[
0
]
&
0x02
);
input_report_key
(
dev
,
BTN_LEFT
,
(
kbtab
->
pressure
>
kb_pressure_click
)
?
1
:
0
);
if
(
-
1
==
kb_pressure_click
){
input_report_abs
(
dev
,
ABS_PRESSURE
,
kbtab
->
pressure
);
}
else
{
input_report_key
(
dev
,
BTN_LEFT
,
(
kbtab
->
pressure
>
kb_pressure_click
)
?
1
:
0
);
};
input_sync
(
dev
);
...
...
drivers/usb/input/mtouchusb.c
0 → 100644
View file @
eba9fb15
/******************************************************************************
* 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 <linux/config.h>
#ifdef CONFIG_USB_DEBUG
#define DEBUG
#else
#undef DEBUG
#endif
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/input.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/usb.h>
#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"
);
drivers/usb/input/usbkbd.c
View file @
eba9fb15
...
...
@@ -240,7 +240,7 @@ static int usb_kbd_probe(struct usb_interface *iface,
char
path
[
64
];
char
*
buf
;
interface
=
&
iface
->
altsetting
[
iface
->
act_altsetting
]
;
interface
=
iface
->
cur_altsetting
;
if
(
interface
->
desc
.
bNumEndpoints
!=
1
)
return
-
ENODEV
;
...
...
drivers/usb/input/usbmouse.c
View file @
eba9fb15
...
...
@@ -131,7 +131,7 @@ static int usb_mouse_probe(struct usb_interface * intf, const struct usb_device_
char
path
[
64
];
char
*
buf
;
interface
=
&
intf
->
altsetting
[
intf
->
act_altsetting
]
;
interface
=
intf
->
cur_altsetting
;
if
(
interface
->
desc
.
bNumEndpoints
!=
1
)
return
-
ENODEV
;
...
...
drivers/usb/misc/usbtest.c
View file @
eba9fb15
...
...
@@ -490,7 +490,7 @@ static int set_altsetting (struct usbtest_dev *dev, int alternate)
struct
usb_interface
*
iface
=
dev
->
intf
;
struct
usb_device
*
udev
;
if
(
alternate
<
0
||
alternate
>=
iface
->
num_altsetting
)
if
(
alternate
<
0
||
alternate
>=
256
)
return
-
EINVAL
;
udev
=
interface_to_usbdev
(
iface
);
...
...
@@ -556,23 +556,19 @@ static int ch9_postconfig (struct usbtest_dev *dev)
{
struct
usb_interface
*
iface
=
dev
->
intf
;
struct
usb_device
*
udev
=
interface_to_usbdev
(
iface
);
int
i
,
retval
;
int
i
,
alt
,
retval
;
/* [9.2.3] if there's more than one altsetting, we need to be able to
* set and get each one. mostly trusts the descriptors from usbcore.
*/
for
(
i
=
0
;
i
<
iface
->
num_altsetting
;
i
++
)
{
/* 9.2.3 constrains the range here, and Linux ensures
* they're ordered meaningfully in this array
*/
if
(
iface
->
altsetting
[
i
].
desc
.
bAlternateSetting
!=
i
)
{
/* 9.2.3 constrains the range here */
alt
=
iface
->
altsetting
[
i
].
desc
.
bAlternateSetting
;
if
(
alt
<
0
||
alt
>=
iface
->
num_altsetting
)
{
dev_dbg
(
&
iface
->
dev
,
"invalid alt [%d].bAltSetting = %d
\n
"
,
i
,
iface
->
altsetting
[
i
].
desc
.
bAlternateSetting
);
return
-
EDOM
;
i
,
alt
);
}
/* [real world] get/set unimplemented if there's only one */
...
...
@@ -580,18 +576,18 @@ static int ch9_postconfig (struct usbtest_dev *dev)
continue
;
/* [9.4.10] set_interface */
retval
=
set_altsetting
(
dev
,
i
);
retval
=
set_altsetting
(
dev
,
alt
);
if
(
retval
)
{
dev_dbg
(
&
iface
->
dev
,
"can't set_interface = %d, %d
\n
"
,
i
,
retval
);
alt
,
retval
);
return
retval
;
}
/* [9.4.4] get_interface always works */
retval
=
get_altsetting
(
dev
);
if
(
retval
!=
i
)
{
if
(
retval
!=
alt
)
{
dev_dbg
(
&
iface
->
dev
,
"get alt should be %d, was %d
\n
"
,
i
,
retval
);
alt
,
retval
);
return
(
retval
<
0
)
?
retval
:
-
EDOM
;
}
...
...
drivers/usb/net/usbnet.c
View file @
eba9fb15
...
...
@@ -3009,7 +3009,7 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod)
return
-
ENODEV
;
}
xdev
=
interface_to_usbdev
(
udev
);
interface
=
&
udev
->
altsetting
[
udev
->
act_altsetting
]
;
interface
=
udev
->
cur_altsetting
;
usb_get_dev
(
xdev
);
...
...
@@ -3314,6 +3314,15 @@ static const struct usb_device_id products [] = {
.
bInterfaceSubClass
=
0x0a
,
.
bInterfaceProtocol
=
0x00
,
.
driver_info
=
(
unsigned
long
)
&
zaurus_pxa_info
,
},
{
.
match_flags
=
USB_DEVICE_ID_MATCH_INT_INFO
|
USB_DEVICE_ID_MATCH_DEVICE
,
.
idVendor
=
0x04DD
,
.
idProduct
=
0x9050
,
/* C-860 */
.
bInterfaceClass
=
0x02
,
.
bInterfaceSubClass
=
0x0a
,
.
bInterfaceProtocol
=
0x00
,
.
driver_info
=
(
unsigned
long
)
&
zaurus_pxa_info
,
},
#endif
...
...
drivers/usb/serial/ftdi_sio.c
View file @
eba9fb15
...
...
@@ -286,6 +286,7 @@ static struct usb_device_id id_table_sio [] = {
static
struct
usb_device_id
id_table_8U232AM
[]
=
{
{
USB_DEVICE_VER
(
FTDI_VID
,
FTDI_IRTRANS_PID
,
0
,
0x3ff
)
},
{
USB_DEVICE_VER
(
FTDI_VID
,
FTDI_8U232AM_PID
,
0
,
0x3ff
)
},
{
USB_DEVICE_VER
(
FTDI_VID
,
FTDI_8U232AM_ALT_PID
,
0
,
0x3ff
)
},
{
USB_DEVICE_VER
(
FTDI_VID
,
FTDI_RELAIS_PID
,
0
,
0x3ff
)
},
...
...
@@ -358,6 +359,7 @@ static struct usb_device_id id_table_8U232AM [] = {
static
struct
usb_device_id
id_table_FT232BM
[]
=
{
{
USB_DEVICE_VER
(
FTDI_VID
,
FTDI_IRTRANS_PID
,
0x400
,
0xffff
)
},
{
USB_DEVICE_VER
(
FTDI_VID
,
FTDI_8U232AM_PID
,
0x400
,
0xffff
)
},
{
USB_DEVICE_VER
(
FTDI_VID
,
FTDI_8U232AM_ALT_PID
,
0x400
,
0xffff
)
},
{
USB_DEVICE_VER
(
FTDI_VID
,
FTDI_RELAIS_PID
,
0x400
,
0xffff
)
},
...
...
@@ -451,6 +453,7 @@ static struct usb_device_id id_table_HE_TIRA1 [] = {
static
struct
usb_device_id
id_table_combined
[]
=
{
{
USB_DEVICE
(
FTDI_VID
,
FTDI_IRTRANS_PID
)
},
{
USB_DEVICE
(
FTDI_VID
,
FTDI_SIO_PID
)
},
{
USB_DEVICE
(
FTDI_VID
,
FTDI_8U232AM_PID
)
},
{
USB_DEVICE
(
FTDI_VID
,
FTDI_8U232AM_ALT_PID
)
},
...
...
drivers/usb/serial/ftdi_sio.h
View file @
eba9fb15
...
...
@@ -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 */
...
...
drivers/usb/serial/kl5kusb105.c
View file @
eba9fb15
...
...
@@ -273,6 +273,7 @@ static int klsi_105_startup (struct usb_serial *serial)
/* allocate the private data structure */
for
(
i
=
0
;
i
<
serial
->
num_ports
;
i
++
)
{
int
j
;
priv
=
kmalloc
(
sizeof
(
struct
klsi_105_private
),
GFP_KERNEL
);
if
(
!
priv
)
{
...
...
@@ -293,10 +294,10 @@ static int klsi_105_startup (struct usb_serial *serial)
usb_set_serial_port_data
(
serial
->
port
[
i
],
priv
);
spin_lock_init
(
&
priv
->
lock
);
for
(
i
=
0
;
i
<
NUM_URBS
;
i
++
)
{
for
(
j
=
0
;
j
<
NUM_URBS
;
j
++
)
{
struct
urb
*
urb
=
usb_alloc_urb
(
0
,
GFP_KERNEL
);
priv
->
write_urb_pool
[
i
]
=
urb
;
priv
->
write_urb_pool
[
j
]
=
urb
;
if
(
urb
==
NULL
)
{
err
(
"No more urbs???"
);
continue
;
...
...
drivers/usb/serial/visor.c
View file @
eba9fb15
...
...
@@ -239,6 +239,8 @@ static struct usb_device_id id_table [] = {
.
driver_info
=
(
kernel_ulong_t
)
&
palm_os_4_probe
},
{
USB_DEVICE
(
SAMSUNG_VENDOR_ID
,
SAMSUNG_SCH_I330_ID
),
.
driver_info
=
(
kernel_ulong_t
)
&
palm_os_4_probe
},
{
USB_DEVICE
(
SAMSUNG_VENDOR_ID
,
SAMSUNG_SPH_I500_ID
),
.
driver_info
=
(
kernel_ulong_t
)
&
palm_os_4_probe
},
{
USB_DEVICE
(
GARMIN_VENDOR_ID
,
GARMIN_IQUE_3600_ID
),
.
driver_info
=
(
kernel_ulong_t
)
&
palm_os_4_probe
},
{
USB_DEVICE
(
ACEECA_VENDOR_ID
,
ACEECA_MEZ1000_ID
),
...
...
@@ -275,6 +277,7 @@ static struct usb_device_id id_table_combined [] = {
{
USB_DEVICE
(
SONY_VENDOR_ID
,
SONY_CLIE_UX50_ID
)
},
{
USB_DEVICE
(
SONY_VENDOR_ID
,
SONY_CLIE_TJ25_ID
)
},
{
USB_DEVICE
(
SAMSUNG_VENDOR_ID
,
SAMSUNG_SCH_I330_ID
)
},
{
USB_DEVICE
(
SAMSUNG_VENDOR_ID
,
SAMSUNG_SPH_I500_ID
)
},
{
USB_DEVICE
(
GARMIN_VENDOR_ID
,
GARMIN_IQUE_3600_ID
)
},
{
USB_DEVICE
(
ACEECA_VENDOR_ID
,
ACEECA_MEZ1000_ID
)
},
{
},
/* optional parameter entry */
...
...
drivers/usb/serial/visor.h
View file @
eba9fb15
...
...
@@ -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
...
...
drivers/usb/storage/scsiglue.c
View file @
eba9fb15
...
...
@@ -64,8 +64,10 @@ static const char* host_info(struct Scsi_Host *host)
return
"SCSI emulation for USB Mass Storage devices"
;
}
static
int
slave_configure
(
struct
scsi_device
*
sdev
)
static
int
slave_configure
(
struct
scsi_device
*
sdev
)
{
struct
us_data
*
us
=
(
struct
us_data
*
)
sdev
->
host
->
hostdata
[
0
];
/* Scatter-gather buffers (all but the last) must have a length
* divisible by the bulk maxpacket size. Otherwise a data packet
* would end up being short, causing a premature end to the data
...
...
@@ -76,6 +78,16 @@ static int slave_configure (struct scsi_device *sdev)
* the end, scatter-gather buffers follow page boundaries. */
blk_queue_dma_alignment
(
sdev
->
request_queue
,
(
512
-
1
));
/* Devices using Genesys Logic chips cause a lot of trouble for
* high-speed transfers; they die unpredictably when given more
* than 64 KB of data at a time. If we detect such a device,
* reduce the maximum transfer size to 64 KB = 128 sectors. */
#define USB_VENDOR_ID_GENESYS 0x05e3 // Needs a standard location
if
(
us
->
pusb_dev
->
descriptor
.
idVendor
==
USB_VENDOR_ID_GENESYS
&&
us
->
pusb_dev
->
speed
==
USB_SPEED_HIGH
)
blk_queue_max_sectors
(
sdev
->
request_queue
,
128
);
/* this is to satisify the compiler, tho I don't think the
* return code is ever checked anywhere. */
return
0
;
...
...
drivers/usb/storage/transport.c
View file @
eba9fb15
...
...
@@ -563,9 +563,9 @@ void usb_stor_invoke_transport(Scsi_Cmnd *srb, struct us_data *us)
/*
* If we're running the CB transport, which is incapable
* of determining status on its own, we
need to
auto-sense
* of determining status on its own, we
will
auto-sense
* unless the operation involved a data-in transfer. Devices
* can signal data-in errors by stalling the bulk-in pipe.
* can signal
most
data-in errors by stalling the bulk-in pipe.
*/
if
((
us
->
protocol
==
US_PR_CB
||
us
->
protocol
==
US_PR_DPCM_USB
)
&&
srb
->
sc_data_direction
!=
SCSI_DATA_READ
)
{
...
...
@@ -698,7 +698,11 @@ void usb_stor_invoke_transport(Scsi_Cmnd *srb, struct us_data *us)
* out the sense buffer so the higher layers won't realize
* we did an unsolicited auto-sense. */
if
(
result
==
USB_STOR_TRANSPORT_GOOD
&&
(
srb
->
sense_buffer
[
2
]
&
0xf
)
==
0x0
)
{
/* Filemark 0, ignore EOM, ILI 0, no sense */
(
srb
->
sense_buffer
[
2
]
&
0xaf
)
==
0
&&
/* No ASC or ASCQ */
srb
->
sense_buffer
[
12
]
==
0
&&
srb
->
sense_buffer
[
13
]
==
0
)
{
srb
->
result
=
SAM_STAT_GOOD
;
srb
->
sense_buffer
[
0
]
=
0x0
;
}
...
...
@@ -809,15 +813,19 @@ int usb_stor_CBI_transport(Scsi_Cmnd *srb, struct us_data *us)
}
/* If not UFI, we interpret the data as a result code
* The first byte should always be a 0x0
* The second byte & 0x0F should be 0x0 for good, otherwise error
* The first byte should always be a 0x0.
*
* Some bogus devices don't follow that rule. They stuff the ASC
* into the first byte -- so if it's non-zero, call it a failure.
*/
if
(
us
->
iobuf
[
0
])
{
US_DEBUGP
(
"CBI IRQ data showed reserved bType
%d
\n
"
,
US_DEBUGP
(
"CBI IRQ data showed reserved bType
0x%x
\n
"
,
us
->
iobuf
[
0
]);
return
USB_STOR_TRANSPORT_ERROR
;
goto
Failed
;
}
/* The second byte & 0x0F should be 0x0 for good, otherwise error */
switch
(
us
->
iobuf
[
1
]
&
0x0F
)
{
case
0x00
:
return
USB_STOR_TRANSPORT_GOOD
;
...
...
drivers/usb/storage/unusual_devs.h
View file @
eba9fb15
...
...
@@ -261,6 +261,14 @@ UNUSUAL_DEV( 0x054c, 0x0010, 0x0106, 0x0450,
US_SC_SCSI
,
US_PR_DEVICE
,
NULL
,
US_FL_SINGLE_LUN
|
US_FL_MODE_XLATE
),
/* This entry is needed because the device reports Sub=ff */
UNUSUAL_DEV
(
0x054c
,
0x0010
,
0x0500
,
0x0500
,
"Sony"
,
"DSC-T1"
,
US_SC_8070
,
US_PR_DEVICE
,
NULL
,
US_FL_SINGLE_LUN
|
US_FL_MODE_XLATE
),
/* Reported by wim@geeks.nl */
UNUSUAL_DEV
(
0x054c
,
0x0025
,
0x0100
,
0x0100
,
"Sony"
,
...
...
@@ -368,7 +376,7 @@ UNUSUAL_DEV( 0x05ab, 0x5701, 0x0100, 0x0110,
UNUSUAL_DEV
(
0x05dc
,
0x0001
,
0x0000
,
0x0001
,
"Lexar"
,
"Jumpshot USB CF Reader"
,
US_SC_
SCSI
,
US_PR_JUMPSHOT
,
NULL
,
US_SC_
DEVICE
,
US_PR_JUMPSHOT
,
NULL
,
US_FL_MODE_XLATE
),
#endif
...
...
@@ -440,12 +448,6 @@ UNUSUAL_DEV( 0x0686, 0x4006, 0x0001, 0x0001,
US_SC_SCSI
,
US_PR_DEVICE
,
NULL
,
0
),
UNUSUAL_DEV
(
0x0686
,
0x400b
,
0x0001
,
0x0001
,
"Minolta"
,
"DiMAGE 7i"
,
US_SC_SCSI
,
US_PR_DEVICE
,
NULL
,
0
),
UNUSUAL_DEV
(
0x0686
,
0x400f
,
0x0001
,
0x0001
,
"Minolta"
,
"DiMAGE 7Hi"
,
...
...
@@ -619,6 +621,9 @@ UNUSUAL_DEV( 0x07c4, 0xa400, 0x0000, 0xffff,
* are using transport protocol CB.
* - They don't like the INQUIRY command. So we must handle this command
* of the SCSI layer ourselves.
* - Some cameras with idProduct=0x1001 and bcdDevice=0x1000 have
* bInterfaceProtocol=0x00 (US_PR_CBI) while others have 0x01 (US_PR_CB).
* So don't remove the US_PR_CB override!
*/
UNUSUAL_DEV
(
0x07cf
,
0x1001
,
0x1000
,
0x9009
,
"Casio"
,
...
...
@@ -649,6 +654,17 @@ UNUSUAL_DEV( 0x08ca, 0x2011, 0x0000, 0x9999,
US_SC_DEVICE
,
US_PR_DEVICE
,
NULL
,
US_FL_MODE_XLATE
),
/* Entry needed for flags. Moreover, all devices with this ID use
* bulk-only transport, but _some_ falsely report Control/Bulk instead.
* One example is "Trumpion Digital Research MYMP3".
* Submitted by Bjoern Brill <brill(at)fs.math.uni-frankfurt.de>
*/
UNUSUAL_DEV
(
0x090a
,
0x1001
,
0x0100
,
0x0100
,
"Trumpion"
,
"t33520 USB Flash Card Controller"
,
US_SC_DEVICE
,
US_PR_BULK
,
NULL
,
US_FL_MODE_XLATE
),
/* Trumpion Microelectronics MP3 player (felipe_alfaro@linuxmail.org) */
UNUSUAL_DEV
(
0x090a
,
0x1200
,
0x0000
,
0x9999
,
"Trumpion"
,
...
...
@@ -688,15 +704,9 @@ UNUSUAL_DEV( 0x0a17, 0x0004, 0x1000, 0x1000,
US_SC_DEVICE
,
US_PR_DEVICE
,
NULL
,
US_FL_FIX_INQUIRY
),
/* This entry from <matthias@ma-c.de> in the Debian mailing list */
UNUSUAL_DEV
(
0x0a17
,
0x0006
,
0x0000
,
0xffff
,
"Pentax"
,
"Optio 330GS"
,
US_SC_8070
,
US_PR_CB
,
NULL
,
US_FL_MODE_XLATE
|
US_FL_FIX_INQUIRY
),
/* Submitted by Per Winkvist <per.winkvist@uk.com> */
UNUSUAL_DEV
(
0x0a17
,
0x006
,
0x
1000
,
0x9009
,
UNUSUAL_DEV
(
0x0a17
,
0x006
,
0x
0000
,
0xffff
,
"Pentax"
,
"Optio S/S4"
,
US_SC_DEVICE
,
US_PR_DEVICE
,
NULL
,
...
...
drivers/usb/storage/usb.c
View file @
eba9fb15
...
...
@@ -423,7 +423,7 @@ static int associate_dev(struct us_data *us, struct usb_interface *intf)
/* Fill in the device-related fields */
us
->
pusb_dev
=
interface_to_usbdev
(
intf
);
us
->
pusb_intf
=
intf
;
us
->
ifnum
=
intf
->
altsetting
->
desc
.
bInterfaceNumber
;
us
->
ifnum
=
intf
->
cur_
altsetting
->
desc
.
bInterfaceNumber
;
/* Store our private data in the interface and increment the
* device's reference count */
...
...
@@ -452,7 +452,7 @@ static void get_device_info(struct us_data *us, int id_index)
{
struct
usb_device
*
dev
=
us
->
pusb_dev
;
struct
usb_interface_descriptor
*
idesc
=
&
us
->
pusb_intf
->
altsetting
[
us
->
pusb_intf
->
act_altsetting
].
desc
;
&
us
->
pusb_intf
->
cur_altsetting
->
desc
;
struct
us_unusual_dev
*
unusual_dev
=
&
us_unusual_dev_list
[
id_index
];
struct
usb_device_id
*
id
=
&
storage_usb_ids
[
id_index
];
...
...
@@ -686,7 +686,7 @@ static int get_protocol(struct us_data *us)
static
int
get_pipes
(
struct
us_data
*
us
)
{
struct
usb_host_interface
*
altsetting
=
&
us
->
pusb_intf
->
altsetting
[
us
->
pusb_intf
->
act_altsetting
]
;
us
->
pusb_intf
->
cur_altsetting
;
int
i
;
struct
usb_endpoint_descriptor
*
ep
;
struct
usb_endpoint_descriptor
*
ep_in
=
NULL
;
...
...
@@ -877,8 +877,9 @@ static int storage_probe(struct usb_interface *intf,
int
result
;
US_DEBUGP
(
"USB Mass Storage device detected
\n
"
);
US_DEBUGP
(
"act_altsetting is %d, id_index is %d
\n
"
,
intf
->
act_altsetting
,
id_index
);
US_DEBUGP
(
"altsetting is %d, id_index is %d
\n
"
,
intf
->
cur_altsetting
->
desc
.
bAlternateSetting
,
id_index
);
/* Allocate the us_data structure and initialize the mutexes */
us
=
(
struct
us_data
*
)
kmalloc
(
sizeof
(
*
us
),
GFP_KERNEL
);
...
...
@@ -953,8 +954,6 @@ static int storage_probe(struct usb_interface *intf,
scsi_scan_host
(
us
->
host
);
printk
(
KERN_DEBUG
"WARNING: USB Mass Storage data integrity not assured
\n
"
);
printk
(
KERN_DEBUG
"USB Mass Storage device found at %d
\n
"
,
us
->
pusb_dev
->
devnum
);
return
0
;
...
...
drivers/usb/storage/usb.h
View file @
eba9fb15
...
...
@@ -176,6 +176,5 @@ extern void fill_inquiry_response(struct us_data *us,
* single queue element srb for write access */
#define scsi_unlock(host) spin_unlock_irq(host->host_lock)
#define scsi_lock(host) spin_lock_irq(host->host_lock)
#define sg_address(psg) (page_address((psg).page) + (psg).offset)
#endif
include/linux/usb.h
View file @
eba9fb15
...
...
@@ -72,14 +72,11 @@ struct usb_host_interface {
/**
* struct usb_interface - what usb device drivers talk to
* @altsetting: array of interface
descriptor
s, one for each alternate
* @altsetting: array of interface
structure
s, one for each alternate
* setting that may be selected. Each one includes a set of
* endpoint configurations and will be in numberic order,
* 0..num_altsetting.
* endpoint configurations. They will be in no particular order.
* @num_altsetting: number of altsettings defined.
* @act_altsetting: index of current altsetting. this number is always
* less than num_altsetting. after the device is configured, each
* interface uses its default setting of zero.
* @cur_altsetting: the current altsetting.
* @driver: the USB driver that is bound to this interface.
* @minor: the minor number assigned to this interface, if this
* interface is bound to a driver that uses the USB major number.
...
...
@@ -89,6 +86,8 @@ struct usb_host_interface {
* number from the USB core by calling usb_register_dev().
* @dev: driver model's view of this device
* @class_dev: driver model's class view of this device.
* @released: wait for the interface to be released when changing
* configurations.
*
* USB device drivers attach to interfaces on a physical device. Each
* interface encapsulates a single high level function, such as feeding
...
...
@@ -102,26 +101,33 @@ struct usb_host_interface {
* calls such as dev_get_drvdata() on the dev member of this structure.
*
* Each interface may have alternate settings. The initial configuration
* of a device sets
the first of these
, but the device driver can change
* of a device sets
altsetting 0
, but the device driver can change
* that setting using usb_set_interface(). Alternate settings are often
* used to control the the use of periodic endpoints, such as by having
* different endpoints use different amounts of reserved USB bandwidth.
* All standards-conformant USB devices that use isochronous endpoints
* will use them in non-default settings.
*
* The USB specification says that alternate setting numbers must run from
* 0 to one less than the total number of alternate settings. But some
* devices manage to mess this up, and the structures aren't necessarily
* stored in numerical order anyhow. Use usb_altnum_to_altsetting() to
* look up an alternate setting in the altsetting array based on its number.
*/
struct
usb_interface
{
/* array of alternate settings for this interface.
* these will be in numeric order, 0..num_altsettting
*/
/* array of alternate settings for this interface,
* stored in no particular order */
struct
usb_host_interface
*
altsetting
;
unsigned
act_altsetting
;
/* active alternate setting */
struct
usb_host_interface
*
cur_altsetting
;
/* the currently
* active alternate setting */
unsigned
num_altsetting
;
/* number of alternate settings */
struct
usb_driver
*
driver
;
/* driver */
int
minor
;
/* minor number this interface is bound to */
struct
device
dev
;
/* interface specific device info */
struct
class_device
*
class_dev
;
struct
completion
*
released
;
/* wait for release */
};
#define to_usb_interface(d) container_of(d, struct usb_interface, dev)
#define interface_to_usbdev(intf) \
...
...
@@ -140,19 +146,43 @@ static inline void usb_set_intfdata (struct usb_interface *intf, void *data)
/* this maximum is arbitrary */
#define USB_MAXINTERFACES 32
/* USB_DT_CONFIG: Configuration descriptor information.
/**
* struct usb_host_config - representation of a device's configuration
* @desc: the device's configuration descriptor.
* @interface: array of usb_interface structures, one for each interface
* in the configuration. The number of interfaces is stored in
* desc.bNumInterfaces.
* @extra: pointer to buffer containing all extra descriptors associated
* with this configuration (those preceding the first interface
* descriptor).
* @extralen: length of the extra descriptors buffer.
*
* USB_DT_OTHER_SPEED_CONFIG is the same descriptor, except that the
* descriptor type is different. Highspeed-capable devices can look
* different depending on what speed they're currently running. Only
* devices with a USB_DT_DEVICE_QUALIFIER have an OTHER_SPEED_CONFIG.
* USB devices may have multiple configurations, but only one can be active
* at any time. Each encapsulates a different operational environment;
* for example, a dual-speed device would have separate configurations for
* full-speed and high-speed operation. The number of configurations
* available is stored in the device descriptor as bNumConfigurations.
*
* A configuration can contain multiple interfaces. Each corresponds to
* a different function of the USB device, and all are available whenever
* the configuration is active. The USB standard says that interfaces
* are supposed to be numbered from 0 to desc.bNumInterfaces-1, but a lot
* of devices get this wrong. In addition, the interface array is not
* guaranteed to be sorted in numerical order. Use usb_ifnum_to_if() to
* look up an interface entry based on its number.
*
* Device drivers should not attempt to activate configurations. The choice
* of which configuration to install is a policy decision based on such
* considerations as available power, functionality provided, and the user's
* desires (expressed through hotplug scripts). However, drivers can call
* usb_reset_configuration() to reinitialize the current configuration and
* all its interfaces.
*/
struct
usb_host_config
{
struct
usb_config_descriptor
desc
;
/* the interfaces associated with this configuration
* these will be in numeric order, 0..desc.bNumInterfaces
*/
/* the interfaces associated with this configuration,
* stored in no particular order */
struct
usb_interface
*
interface
[
USB_MAXINTERFACES
];
unsigned
char
*
extra
;
/* Extra descriptors */
...
...
@@ -294,8 +324,12 @@ extern void usb_driver_release_interface(struct usb_driver *driver,
const
struct
usb_device_id
*
usb_match_id
(
struct
usb_interface
*
interface
,
const
struct
usb_device_id
*
id
);
extern
struct
usb_interface
*
usb_find_interface
(
struct
usb_driver
*
drv
,
int
minor
);
extern
struct
usb_interface
*
usb_ifnum_to_if
(
struct
usb_device
*
dev
,
unsigned
ifnum
);
extern
struct
usb_interface
*
usb_find_interface
(
struct
usb_driver
*
drv
,
int
minor
);
extern
struct
usb_interface
*
usb_ifnum_to_if
(
struct
usb_device
*
dev
,
unsigned
ifnum
);
extern
struct
usb_host_interface
*
usb_altnum_to_altsetting
(
struct
usb_interface
*
intf
,
unsigned
int
altnum
);
/**
...
...
include/linux/usb_gadget.h
View file @
eba9fb15
...
...
@@ -690,7 +690,7 @@ int usb_gadget_unregister_driver (struct usb_gadget_driver *driver);
/**
* struct usb_string - wraps a C string and its USB id
* @id:the (nonzero) ID for this string
* @s:the string, in
ISO-8859/1 characters
* @s:the string, in
UTF-8 encoding
*
* If you're using usb_gadget_get_string(), use this to wrap a string
* together with its ID.
...
...
@@ -716,6 +716,17 @@ struct usb_gadget_strings {
/* put descriptor for string with that id into buf (buflen >= 256) */
int
usb_gadget_get_string
(
struct
usb_gadget_strings
*
table
,
int
id
,
u8
*
buf
);
/*-------------------------------------------------------------------------*/
/* utility to simplify managing config descriptors */
/* write vector of descriptors into buffer */
int
usb_descriptor_fillbuf
(
void
*
,
unsigned
,
const
struct
usb_descriptor_header
**
);
/* build config descriptor from single descriptor vector */
int
usb_gadget_config_buf
(
const
struct
usb_config_descriptor
*
config
,
void
*
buf
,
unsigned
buflen
,
const
struct
usb_descriptor_header
**
desc
);
#endif
/* __KERNEL__ */
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment