提交 1f9bd4c9 编写于 作者: L Linus Torvalds

Merge master.kernel.org:/pub/scm/linux/kernel/git/gregkh/usb-2.6

* master.kernel.org:/pub/scm/linux/kernel/git/gregkh/usb-2.6: (129 commits)
  [PATCH] USB Storage: fix Rio Karma eject support build error
  USB: Airprime driver improvements to allow full speed EvDO transfers
  USB: remove OTG build warning
  USB: EHCI update VIA workaround
  USB: force root hub resume after power loss
  USB: ohci_usb can oops on shutdown
  USB: Dealias -110 code (more complete)
  USB: Remove unneeded void * casts in core files
  USB: u132-hcd: host controller driver for ELAN U132 adapter
  USB: ftdi-elan: client driver for ELAN Uxxx adapters
  usb serial: support Alcor Micro Corp. USB 2.0 TO RS-232 through pl2303 driver
  USB: Moschip 7840 USB-Serial Driver
  USB: add PlayStation 2 Trance Vibrator driver
  USB: Add ADU support for Ontrak ADU devices
  aircable: fix printk format warnings
  Add AIRcable USB Bluetooth Dongle Driver
  cypress_m8: implement graceful failure handling
  cypress_m8: improve control endpoint error handling
  cypress_m8: use usb_fill_int_urb where appropriate
  cypress_m8: use appropriate URB polling interval
  ...
......@@ -43,59 +43,52 @@
<para>A Universal Serial Bus (USB) is used to connect a host,
such as a PC or workstation, to a number of peripheral
devices. USB uses a tree structure, with the host at the
devices. USB uses a tree structure, with the host as the
root (the system's master), hubs as interior nodes, and
peripheral devices as leaves (and slaves).
peripherals as leaves (and slaves).
Modern PCs support several such trees of USB devices, usually
one USB 2.0 tree (480 Mbit/sec each) with
a few USB 1.1 trees (12 Mbit/sec each) that are used when you
connect a USB 1.1 device directly to the machine's "root hub".
</para>
<para>That master/slave asymmetry was designed in part for
ease of use. It is not physically possible to assemble
(legal) USB cables incorrectly: all upstream "to-the-host"
connectors are the rectangular type, matching the sockets on
root hubs, and the downstream type are the squarish type
(or they are built in to the peripheral).
Software doesn't need to deal with distributed autoconfiguration
since the pre-designated master node manages all that.
At the electrical level, bus protocol overhead is reduced by
eliminating arbitration and moving scheduling into host software.
<para>That master/slave asymmetry was designed-in for a number of
reasons, one being ease of use. It is not physically possible to
assemble (legal) USB cables incorrectly: all upstream "to the host"
connectors are the rectangular type (matching the sockets on
root hubs), and all downstream connectors are the squarish type
(or they are built into the peripheral).
Also, the host software doesn't need to deal with distributed
auto-configuration since the pre-designated master node manages all that.
And finally, at the electrical level, bus protocol overhead is reduced by
eliminating arbitration and moving scheduling into the host software.
</para>
<para>USB 1.0 was announced in January 1996, and was revised
<para>USB 1.0 was announced in January 1996 and was revised
as USB 1.1 (with improvements in hub specification and
support for interrupt-out transfers) in September 1998.
USB 2.0 was released in April 2000, including high speed
transfers and transaction translating hubs (used for USB 1.1
USB 2.0 was released in April 2000, adding high-speed
transfers and transaction-translating hubs (used for USB 1.1
and 1.0 backward compatibility).
</para>
<para>USB support was added to Linux early in the 2.2 kernel series
shortly before the 2.3 development forked off. Updates
from 2.3 were regularly folded back into 2.2 releases, bringing
new features such as <filename>/sbin/hotplug</filename> support,
more drivers, and more robustness.
The 2.5 kernel series continued such improvements, and also
worked on USB 2.0 support,
higher performance,
better consistency between host controller drivers,
API simplification (to make bugs less likely),
and providing internal "kerneldoc" documentation.
<para>Kernel developers added USB support to Linux early in the 2.2 kernel
series, shortly before 2.3 development forked. Updates from 2.3 were
regularly folded back into 2.2 releases, which improved reliability and
brought <filename>/sbin/hotplug</filename> support as well more drivers.
Such improvements were continued in the 2.5 kernel series, where they added
USB 2.0 support, improved performance, and made the host controller drivers
(HCDs) more consistent. They also simplified the API (to make bugs less
likely) and added internal "kerneldoc" documentation.
</para>
<para>Linux can run inside USB devices as well as on
the hosts that control the devices.
Because the Linux 2.x USB support evolved to support mass market
platforms such as Apple Macintosh or PC-compatible systems,
it didn't address design concerns for those types of USB systems.
So it can't be used inside mass-market PDAs, or other peripherals.
USB device drivers running inside those Linux peripherals
But USB device drivers running inside those peripherals
don't do the same things as the ones running inside hosts,
and so they've been given a different name:
they're called <emphasis>gadget drivers</emphasis>.
This document does not present gadget drivers.
so they've been given a different name:
<emphasis>gadget drivers</emphasis>.
This document does not cover gadget drivers.
</para>
</chapter>
......@@ -103,17 +96,14 @@
<chapter id="host">
<title>USB Host-Side API Model</title>
<para>Within the kernel,
host-side drivers for USB devices talk to the "usbcore" APIs.
There are two types of public "usbcore" APIs, targetted at two different
layers of USB driver. Those are
<emphasis>general purpose</emphasis> drivers, exposed through
driver frameworks such as block, character, or network devices;
and drivers that are <emphasis>part of the core</emphasis>,
which are involved in managing a USB bus.
Such core drivers include the <emphasis>hub</emphasis> driver,
which manages trees of USB devices, and several different kinds
of <emphasis>host controller driver (HCD)</emphasis>,
<para>Host-side drivers for USB devices talk to the "usbcore" APIs.
There are two. One is intended for
<emphasis>general-purpose</emphasis> drivers (exposed through
driver frameworks), and the other is for drivers that are
<emphasis>part of the core</emphasis>.
Such core drivers include the <emphasis>hub</emphasis> driver
(which manages trees of USB devices) and several different kinds
of <emphasis>host controller drivers</emphasis>,
which control individual busses.
</para>
......@@ -122,21 +112,21 @@
<itemizedlist>
<listitem><para>USB supports four kinds of data transfer
(control, bulk, interrupt, and isochronous). Two transfer
types use bandwidth as it's available (control and bulk),
while the other two types of transfer (interrupt and isochronous)
<listitem><para>USB supports four kinds of data transfers
(control, bulk, interrupt, and isochronous). Two of them (control
and bulk) use bandwidth as it's available,
while the other two (interrupt and isochronous)
are scheduled to provide guaranteed bandwidth.
</para></listitem>
<listitem><para>The device description model includes one or more
"configurations" per device, only one of which is active at a time.
Devices that are capable of high speed operation must also support
full speed configurations, along with a way to ask about the
"other speed" configurations that might be used.
Devices that are capable of high-speed operation must also support
full-speed configurations, along with a way to ask about the
"other speed" configurations which might be used.
</para></listitem>
<listitem><para>Configurations have one or more "interface", each
<listitem><para>Configurations have one or more "interfaces", each
of which may have "alternate settings". Interfaces may be
standardized by USB "Class" specifications, or may be specific to
a vendor or device.</para>
......@@ -162,7 +152,7 @@
</para></listitem>
<listitem><para>The Linux USB API supports synchronous calls for
control and bulk messaging.
control and bulk messages.
It also supports asynchnous calls for all kinds of data transfer,
using request structures called "URBs" (USB Request Blocks).
</para></listitem>
......@@ -463,14 +453,25 @@
file in your Linux kernel sources.
</para>
<para>Otherwise the main use for this file from programs
is to poll() it to get notifications of usb devices
as they're plugged or unplugged.
To see what changed, you'd need to read the file and
compare "before" and "after" contents, scan the filesystem,
or see its hotplug event.
<para>This file, in combination with the poll() system call, can
also be used to detect when devices are added or removed:
<programlisting>int fd;
struct pollfd pfd;
fd = open("/proc/bus/usb/devices", O_RDONLY);
pfd = { fd, POLLIN, 0 };
for (;;) {
/* The first time through, this call will return immediately. */
poll(&amp;pfd, 1, -1);
/* To see what's changed, compare the file's previous and current
contents or scan the filesystem. (Scanning is more precise.) */
}</programlisting>
Note that this behavior is intended to be used for informational
and debug purposes. It would be more appropriate to use programs
such as udev or HAL to initialize a device or start a user-mode
helper program, for instance.
</para>
</sect1>
<sect1>
......
......@@ -2543,6 +2543,9 @@ Your cooperation is appreciated.
64 = /dev/usb/rio500 Diamond Rio 500
65 = /dev/usb/usblcd USBLCD Interface (info@usblcd.de)
66 = /dev/usb/cpad0 Synaptics cPad (mouse/LCD)
67 = /dev/usb/adutux0 1st Ontrak ADU device
...
76 = /dev/usb/adutux10 10th Ontrak ADU device
96 = /dev/usb/hiddev0 1st USB HID device
...
111 = /dev/usb/hiddev15 16th USB HID device
......
......@@ -98,13 +98,13 @@ one or more packets could finish before an error stops further endpoint I/O.
error, a failure to respond (often caused by
device disconnect), or some other fault.
-ETIMEDOUT (**) No response packet received within the prescribed
-ETIME (**) No response packet received within the prescribed
bus turn-around time. This error may instead be
reported as -EPROTO or -EILSEQ.
Note that the synchronous USB message functions
also use this code to indicate timeout expired
before the transfer completed.
-ETIMEDOUT Synchronous USB message functions use this code
to indicate timeout expired before the transfer
completed, and no other error was reported by HC.
-EPIPE (**) Endpoint stalled. For non-control endpoints,
reset this status with usb_clear_halt().
......@@ -163,6 +163,3 @@ usb_get_*/usb_set_*():
usb_control_msg():
usb_bulk_msg():
-ETIMEDOUT Timeout expired before the transfer completed.
In the future this code may change to -ETIME,
whose definition is a closer match to this sort
of error.
......@@ -433,6 +433,11 @@ Options supported:
See http://www.uuhaus.de/linux/palmconnect.html for up-to-date
information on this driver.
AIRcable USB Dongle Bluetooth driver
If there is the cdc_acm driver loaded in the system, you will find that the
cdc_acm claims the device before AIRcable can. This is simply corrected
by unloading both modules and then loading the aircable module before
cdc_acm module
Generic Serial driver
......
......@@ -284,21 +284,9 @@ static struct pxaficp_platform_data corgi_ficp_platform_data = {
/*
* USB Device Controller
*/
static void corgi_udc_command(int cmd)
{
switch(cmd) {
case PXA2XX_UDC_CMD_CONNECT:
GPSR(CORGI_GPIO_USB_PULLUP) = GPIO_bit(CORGI_GPIO_USB_PULLUP);
break;
case PXA2XX_UDC_CMD_DISCONNECT:
GPCR(CORGI_GPIO_USB_PULLUP) = GPIO_bit(CORGI_GPIO_USB_PULLUP);
break;
}
}
static struct pxa2xx_udc_mach_info udc_info __initdata = {
/* no connect GPIO; corgi can't tell connection status */
.udc_command = corgi_udc_command,
.gpio_pullup = CORGI_GPIO_USB_PULLUP,
};
......@@ -350,7 +338,6 @@ static void __init corgi_init(void)
corgi_ssp_set_machinfo(&corgi_ssp_machinfo);
pxa_gpio_mode(CORGI_GPIO_IR_ON | GPIO_OUT);
pxa_gpio_mode(CORGI_GPIO_USB_PULLUP | GPIO_OUT);
pxa_gpio_mode(CORGI_GPIO_HSYNC | GPIO_IN);
pxa_set_udc_info(&udc_info);
......
......@@ -26,7 +26,7 @@
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/platform_device.h>
#include <linux/usb_otg.h>
#include <linux/usb/otg.h>
#include <asm/io.h>
#include <asm/irq.h>
......
......@@ -358,7 +358,7 @@ static void ub_cmd_build_block(struct ub_dev *sc, struct ub_lun *lun,
static void ub_cmd_build_packet(struct ub_dev *sc, struct ub_lun *lun,
struct ub_scsi_cmd *cmd, struct ub_request *urq);
static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd);
static void ub_end_rq(struct request *rq, int uptodate);
static void ub_end_rq(struct request *rq, unsigned int status);
static int ub_rw_cmd_retry(struct ub_dev *sc, struct ub_lun *lun,
struct ub_request *urq, struct ub_scsi_cmd *cmd);
static int ub_submit_scsi(struct ub_dev *sc, struct ub_scsi_cmd *cmd);
......@@ -639,9 +639,15 @@ static int ub_request_fn_1(struct ub_lun *lun, struct request *rq)
struct ub_request *urq;
int n_elem;
if (atomic_read(&sc->poison) || lun->changed) {
if (atomic_read(&sc->poison)) {
blkdev_dequeue_request(rq);
ub_end_rq(rq, DID_NO_CONNECT << 16);
return 0;
}
if (lun->changed && !blk_pc_request(rq)) {
blkdev_dequeue_request(rq);
ub_end_rq(rq, 0);
ub_end_rq(rq, SAM_STAT_CHECK_CONDITION);
return 0;
}
......@@ -693,7 +699,7 @@ static int ub_request_fn_1(struct ub_lun *lun, struct request *rq)
drop:
ub_put_cmd(lun, cmd);
ub_end_rq(rq, 0);
ub_end_rq(rq, DID_ERROR << 16);
return 0;
}
......@@ -761,47 +767,53 @@ static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd)
struct ub_lun *lun = cmd->lun;
struct ub_request *urq = cmd->back;
struct request *rq;
int uptodate;
unsigned int scsi_status;
rq = urq->rq;
if (cmd->error == 0) {
uptodate = 1;
if (blk_pc_request(rq)) {
if (cmd->act_len >= rq->data_len)
rq->data_len = 0;
else
rq->data_len -= cmd->act_len;
}
scsi_status = 0;
} else {
uptodate = 0;
if (blk_pc_request(rq)) {
/* UB_SENSE_SIZE is smaller than SCSI_SENSE_BUFFERSIZE */
memcpy(rq->sense, sc->top_sense, UB_SENSE_SIZE);
rq->sense_len = UB_SENSE_SIZE;
if (sc->top_sense[0] != 0)
rq->errors = SAM_STAT_CHECK_CONDITION;
scsi_status = SAM_STAT_CHECK_CONDITION;
else
rq->errors = DID_ERROR << 16;
scsi_status = DID_ERROR << 16;
} else {
if (cmd->error == -EIO) {
if (ub_rw_cmd_retry(sc, lun, urq, cmd) == 0)
return;
}
scsi_status = SAM_STAT_CHECK_CONDITION;
}
}
urq->rq = NULL;
ub_put_cmd(lun, cmd);
ub_end_rq(rq, uptodate);
ub_end_rq(rq, scsi_status);
blk_start_queue(lun->disk->queue);
}
static void ub_end_rq(struct request *rq, int uptodate)
static void ub_end_rq(struct request *rq, unsigned int scsi_status)
{
int uptodate;
if (scsi_status == 0) {
uptodate = 1;
} else {
uptodate = 0;
rq->errors = scsi_status;
}
end_that_request_first(rq, uptodate, rq->hard_nr_sectors);
end_that_request_last(rq, uptodate);
}
......
......@@ -30,7 +30,7 @@
#include <linux/usb_ch9.h>
#include <linux/usb_gadget.h>
#include <linux/usb.h>
#include <linux/usb_otg.h>
#include <linux/usb/otg.h>
#include <linux/i2c.h>
#include <linux/workqueue.h>
......
......@@ -192,7 +192,7 @@ static char *get_usb_statmsg(int status)
return "bit stuffing error, timeout, or unknown USB error";
case -EILSEQ:
return "CRC mismatch, timeout, or unknown USB error";
case -ETIMEDOUT:
case -ETIME:
return "timed out";
case -EPIPE:
return "endpoint stalled";
......
......@@ -137,11 +137,11 @@ static struct hfcusb_symbolic_list urb_errlist[] = {
{-ENXIO, "URB already queued"},
{-EFBIG, "Too much ISO frames requested"},
{-ENOSR, "Buffer error (overrun)"},
{-EPIPE, "Specified endpoint is stalled (device not responding)"},
{-EPIPE, "Specified endpoint is stalled"},
{-EOVERFLOW, "Babble (bad cable?)"},
{-EPROTO, "Bit-stuff error (bad cable?)"},
{-EILSEQ, "CRC/Timeout"},
{-ETIMEDOUT, "NAK (device does not respond)"},
{-EILSEQ, "CRC or missing token"},
{-ETIME, "Device did not respond"},
{-ESHUTDOWN, "Device unplugged"},
{-1, NULL}
};
......
......@@ -80,7 +80,6 @@ static void dvb_usb_urb_complete(struct urb *urb, struct pt_regs *ptregs)
switch (urb->status) {
case 0: /* success */
case -ETIMEDOUT: /* NAK */
break;
case -ECONNRESET: /* kill */
case -ENOENT:
......
......@@ -215,7 +215,7 @@ static void ttusb_dec_handle_irq( struct urb *urb, struct pt_regs *regs)
case -ECONNRESET:
case -ENOENT:
case -ESHUTDOWN:
case -ETIMEDOUT:
case -ETIME:
/* this urb is dead, cleanup */
dprintk("%s:urb shutting down with status: %d\n",
__FUNCTION__, urb->status);
......
......@@ -301,10 +301,11 @@ static struct symbolic_list senlist[] = {
static struct symbolic_list urb_errlist[] = {
{ -ENOSR, "Buffer error (overrun)" },
{ -EPIPE, "Stalled (device not responding)" },
{ -EOVERFLOW, "Babble (bad cable?)" },
{ -EOVERFLOW, "Babble (device sends too much data)" },
{ -EPROTO, "Bit-stuff error (bad cable?)" },
{ -EILSEQ, "CRC/Timeout" },
{ -ETIMEDOUT, "NAK (device does not respond)" },
{ -EILSEQ, "CRC/Timeout (bad cable?)" },
{ -ETIME, "Device does not respond to token" },
{ -ETIMEDOUT, "Device does not respond to command" },
{ -1, NULL }
};
......
......@@ -711,7 +711,7 @@ static void pwc_isoc_handler(struct urb *urb, struct pt_regs *regs)
case -EOVERFLOW: errmsg = "Babble (bad cable?)"; break;
case -EPROTO: errmsg = "Bit-stuff error (bad cable?)"; break;
case -EILSEQ: errmsg = "CRC/Timeout (could be anything)"; break;
case -ETIMEDOUT: errmsg = "NAK (device does not respond)"; break;
case -ETIME: errmsg = "Device does not respond"; break;
}
PWC_DEBUG_FLOW("pwc_isoc_handler() called with status %d [%s].\n", urb->status, errmsg);
/* Give up after a number of contiguous errors on the USB bus.
......
......@@ -586,15 +586,14 @@ static struct w9968cf_symbolic_list urb_errlist[] = {
{ -EFBIG, "Too much ISO frames requested" },
{ -ENOSR, "Buffer error (overrun)" },
{ -EPIPE, "Specified endpoint is stalled (device not responding)"},
{ -EOVERFLOW, "Babble (bad cable?)" },
{ -EOVERFLOW, "Babble (too much data)" },
{ -EPROTO, "Bit-stuff error (bad cable?)" },
{ -EILSEQ, "CRC/Timeout" },
{ -ETIMEDOUT, "NAK (device does not respond)" },
{ -ETIME, "Device does not respond to token" },
{ -ETIMEDOUT, "Device does not respond to command" },
{ -1, NULL }
};
/****************************************************************************
* Memory management functions *
****************************************************************************/
......
......@@ -671,10 +671,8 @@ static void irda_usb_net_timeout(struct net_device *netdev)
* Jean II */
done = 1;
break;
case -ECONNABORTED: /* -103 */
case -ECONNRESET: /* -104 */
case -ETIMEDOUT: /* -110 */
case -ENOENT: /* -2 (urb unlinked by us) */
case -ECONNRESET:
case -ENOENT: /* urb unlinked by us */
default: /* ??? - Play safe */
urb->status = 0;
netif_wake_queue(self->netdev);
......@@ -712,10 +710,8 @@ static void irda_usb_net_timeout(struct net_device *netdev)
* Jean II */
done = 1;
break;
case -ECONNABORTED: /* -103 */
case -ECONNRESET: /* -104 */
case -ETIMEDOUT: /* -110 */
case -ENOENT: /* -2 (urb unlinked by us) */
case -ECONNRESET:
case -ENOENT: /* urb unlinked by us */
default: /* ??? - Play safe */
if(skb != NULL) {
dev_kfree_skb_any(skb);
......@@ -845,14 +841,14 @@ static void irda_usb_receive(struct urb *urb, struct pt_regs *regs)
self->stats.rx_crc_errors++;
/* Also precursor to a hot-unplug on UHCI. */
/* Fallthrough... */
case -ECONNRESET: /* -104 */
case -ECONNRESET:
/* Random error, if I remember correctly */
/* uhci_cleanup_unlink() is going to kill the Rx
* URB just after we return. No problem, at this
* point the URB will be idle ;-) - Jean II */
case -ESHUTDOWN: /* -108 */
case -ESHUTDOWN:
/* That's usually a hot-unplug. Submit will fail... */
case -ETIMEDOUT: /* -110 */
case -ETIME:
/* Usually precursor to a hot-unplug on OHCI. */
default:
self->stats.rx_errors++;
......
......@@ -119,7 +119,7 @@ static void zd1201_usbfree(struct urb *urb, struct pt_regs *regs)
switch(urb->status) {
case -EILSEQ:
case -ENODEV:
case -ETIMEDOUT:
case -ETIME:
case -ENOENT:
case -EPIPE:
case -EOVERFLOW:
......@@ -201,7 +201,7 @@ static void zd1201_usbrx(struct urb *urb, struct pt_regs *regs)
switch(urb->status) {
case -EILSEQ:
case -ENODEV:
case -ETIMEDOUT:
case -ETIME:
case -ENOENT:
case -EPIPE:
case -EOVERFLOW:
......
......@@ -25,6 +25,7 @@ config USB_ARCH_HAS_OHCI
default y if PXA27x
default y if ARCH_EP93XX
default y if (ARCH_AT91RM9200 || ARCH_AT91SAM9261)
default y if ARCH_PNX4008
# PPC:
default y if STB03xxx
default y if PPC_MPC52xx
......
......@@ -14,6 +14,7 @@ obj-$(CONFIG_USB_ISP116X_HCD) += host/
obj-$(CONFIG_USB_OHCI_HCD) += host/
obj-$(CONFIG_USB_UHCI_HCD) += host/
obj-$(CONFIG_USB_SL811_HCD) += host/
obj-$(CONFIG_USB_U132_HCD) += host/
obj-$(CONFIG_ETRAX_USB_HOST) += host/
obj-$(CONFIG_USB_OHCI_AT91) += host/
......@@ -23,6 +24,7 @@ obj-$(CONFIG_USB_PRINTER) += class/
obj-$(CONFIG_USB_STORAGE) += storage/
obj-$(CONFIG_USB) += storage/
obj-$(CONFIG_USB_ACECAD) += input/
obj-$(CONFIG_USB_AIPTEK) += input/
obj-$(CONFIG_USB_ATI_REMOTE) += input/
obj-$(CONFIG_USB_HID) += input/
......@@ -31,8 +33,8 @@ obj-$(CONFIG_USB_KBTAB) += input/
obj-$(CONFIG_USB_MOUSE) += input/
obj-$(CONFIG_USB_MTOUCH) += input/
obj-$(CONFIG_USB_POWERMATE) += input/
obj-$(CONFIG_USB_TRANCEVIBRATOR)+= input/
obj-$(CONFIG_USB_WACOM) += input/
obj-$(CONFIG_USB_ACECAD) += input/
obj-$(CONFIG_USB_XPAD) += input/
obj-$(CONFIG_USB_CATC) += net/
......@@ -47,22 +49,24 @@ obj-$(CONFIG_USB_MICROTEK) += image/
obj-$(CONFIG_USB_SERIAL) += serial/
obj-$(CONFIG_USB_ADUTUX) += misc/
obj-$(CONFIG_USB_APPLEDISPLAY) += misc/
obj-$(CONFIG_USB_AUERSWALD) += misc/
obj-$(CONFIG_USB_CYPRESS_CY7C63)+= misc/
obj-$(CONFIG_USB_CYTHERM) += misc/
obj-$(CONFIG_USB_EMI26) += misc/
obj-$(CONFIG_USB_EMI62) += misc/
obj-$(CONFIG_USB_FTDI_ELAN) += misc/
obj-$(CONFIG_USB_IDMOUSE) += misc/
obj-$(CONFIG_USB_LCD) += misc/
obj-$(CONFIG_USB_LD) += misc/
obj-$(CONFIG_USB_LED) += misc/
obj-$(CONFIG_USB_LEGOTOWER) += misc/
obj-$(CONFIG_USB_PHIDGETSERVO) += misc/
obj-$(CONFIG_USB_RIO500) += misc/
obj-$(CONFIG_USB_SISUSBVGA) += misc/
obj-$(CONFIG_USB_TEST) += misc/
obj-$(CONFIG_USB_USS720) += misc/
obj-$(CONFIG_USB_PHIDGETSERVO) += misc/
obj-$(CONFIG_USB_SISUSBVGA) += misc/
obj-$(CONFIG_USB_APPLEDISPLAY) += misc/
obj-$(CONFIG_USB_ATM) += atm/
obj-$(CONFIG_USB_SPEEDTOUCH) += atm/
......@@ -1621,26 +1621,32 @@ static int claim_interface(struct usb_device *usb_dev,
return ret;
}
static void create_fs_entries(struct uea_softc *sc, struct usb_interface *intf)
static struct attribute *attrs[] = {
&dev_attr_stat_status.attr,
&dev_attr_stat_mflags.attr,
&dev_attr_stat_human_status.attr,
&dev_attr_stat_delin.attr,
&dev_attr_stat_vidcpe.attr,
&dev_attr_stat_usrate.attr,
&dev_attr_stat_dsrate.attr,
&dev_attr_stat_usattenuation.attr,
&dev_attr_stat_dsattenuation.attr,
&dev_attr_stat_usmargin.attr,
&dev_attr_stat_dsmargin.attr,
&dev_attr_stat_txflow.attr,
&dev_attr_stat_rxflow.attr,
&dev_attr_stat_uscorr.attr,
&dev_attr_stat_dscorr.attr,
&dev_attr_stat_usunc.attr,
&dev_attr_stat_dsunc.attr,
};
static struct attribute_group attr_grp = {
.attrs = attrs,
};
static int create_fs_entries(struct usb_interface *intf)
{
/* sysfs interface */
device_create_file(&intf->dev, &dev_attr_stat_status);
device_create_file(&intf->dev, &dev_attr_stat_mflags);
device_create_file(&intf->dev, &dev_attr_stat_human_status);
device_create_file(&intf->dev, &dev_attr_stat_delin);
device_create_file(&intf->dev, &dev_attr_stat_vidcpe);
device_create_file(&intf->dev, &dev_attr_stat_usrate);
device_create_file(&intf->dev, &dev_attr_stat_dsrate);
device_create_file(&intf->dev, &dev_attr_stat_usattenuation);
device_create_file(&intf->dev, &dev_attr_stat_dsattenuation);
device_create_file(&intf->dev, &dev_attr_stat_usmargin);
device_create_file(&intf->dev, &dev_attr_stat_dsmargin);
device_create_file(&intf->dev, &dev_attr_stat_txflow);
device_create_file(&intf->dev, &dev_attr_stat_rxflow);
device_create_file(&intf->dev, &dev_attr_stat_uscorr);
device_create_file(&intf->dev, &dev_attr_stat_dscorr);
device_create_file(&intf->dev, &dev_attr_stat_usunc);
device_create_file(&intf->dev, &dev_attr_stat_dsunc);
return sysfs_create_group(&intf->dev.kobj, &attr_grp);
}
static int uea_bind(struct usbatm_data *usbatm, struct usb_interface *intf,
......@@ -1708,37 +1714,25 @@ static int uea_bind(struct usbatm_data *usbatm, struct usb_interface *intf,
return ret;
}
create_fs_entries(sc, intf);
ret = create_fs_entries(intf);
if (ret) {
uea_stop(sc);
kfree(sc);
return ret;
}
return 0;
}
static void destroy_fs_entries(struct uea_softc *sc, struct usb_interface *intf)
static void destroy_fs_entries(struct usb_interface *intf)
{
/* sysfs interface */
device_remove_file(&intf->dev, &dev_attr_stat_status);
device_remove_file(&intf->dev, &dev_attr_stat_mflags);
device_remove_file(&intf->dev, &dev_attr_stat_human_status);
device_remove_file(&intf->dev, &dev_attr_stat_delin);
device_remove_file(&intf->dev, &dev_attr_stat_vidcpe);
device_remove_file(&intf->dev, &dev_attr_stat_usrate);
device_remove_file(&intf->dev, &dev_attr_stat_dsrate);
device_remove_file(&intf->dev, &dev_attr_stat_usattenuation);
device_remove_file(&intf->dev, &dev_attr_stat_dsattenuation);
device_remove_file(&intf->dev, &dev_attr_stat_usmargin);
device_remove_file(&intf->dev, &dev_attr_stat_dsmargin);
device_remove_file(&intf->dev, &dev_attr_stat_txflow);
device_remove_file(&intf->dev, &dev_attr_stat_rxflow);
device_remove_file(&intf->dev, &dev_attr_stat_uscorr);
device_remove_file(&intf->dev, &dev_attr_stat_dscorr);
device_remove_file(&intf->dev, &dev_attr_stat_usunc);
device_remove_file(&intf->dev, &dev_attr_stat_dsunc);
sysfs_remove_group(&intf->dev.kobj, &attr_grp);
}
static void uea_unbind(struct usbatm_data *usbatm, struct usb_interface *intf)
{
struct uea_softc *sc = usbatm->driver_data;
destroy_fs_entries(sc, intf);
destroy_fs_entries(intf);
uea_stop(sc);
kfree(sc);
}
......
......@@ -813,7 +813,7 @@ static unsigned int usblp_quirks (__u16 vendor, __u16 product)
return 0;
}
static struct file_operations usblp_fops = {
static const struct file_operations usblp_fops = {
.owner = THIS_MODULE,
.read = usblp_read,
.write = usblp_write,
......@@ -927,7 +927,9 @@ static int usblp_probe(struct usb_interface *intf,
/* Retrieve and store the device ID string. */
usblp_cache_device_id_string(usblp);
device_create_file(&intf->dev, &dev_attr_ieee1284_id);
retval = device_create_file(&intf->dev, &dev_attr_ieee1284_id);
if (retval)
goto abort_intfdata;
#ifdef DEBUG
usblp_check_status(usblp, 0);
......@@ -1021,18 +1023,13 @@ static int usblp_select_alts(struct usblp *usblp)
for (e = 0; e < ifd->desc.bNumEndpoints; e++) {
epd = &ifd->endpoint[e].desc;
if ((epd->bmAttributes&USB_ENDPOINT_XFERTYPE_MASK)!=
USB_ENDPOINT_XFER_BULK)
continue;
if (!(epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK)) {
if (usb_endpoint_is_bulk_out(epd))
if (!epwrite)
epwrite = epd;
} else {
if (usb_endpoint_is_bulk_in(epd))
if (!epread)
epread = epd;
}
}
/* Ignore buggy hardware without the right endpoints. */
......
......@@ -4,7 +4,7 @@
usbcore-objs := usb.o hub.o hcd.o urb.o message.o driver.o \
config.o file.o buffer.o sysfs.o endpoint.o \
devio.o notify.o
devio.o notify.o generic.o
ifeq ($(CONFIG_PCI),y)
usbcore-objs += hcd-pci.o
......
......@@ -104,7 +104,7 @@ void *hcd_buffer_alloc (
dma_addr_t *dma
)
{
struct usb_hcd *hcd = bus->hcpriv;
struct usb_hcd *hcd = bus_to_hcd(bus);
int i;
/* some USB hosts just use PIO */
......@@ -127,7 +127,7 @@ void hcd_buffer_free (
dma_addr_t dma
)
{
struct usb_hcd *hcd = bus->hcpriv;
struct usb_hcd *hcd = bus_to_hcd(bus);
int i;
if (!addr)
......
......@@ -475,7 +475,9 @@ int usb_get_configuration(struct usb_device *dev)
if (result < 0) {
dev_err(ddev, "unable to read config index %d "
"descriptor/%s\n", cfgno, "start");
goto err;
dev_err(ddev, "chopping to %d config(s)\n", cfgno);
dev->descriptor.bNumConfigurations = cfgno;
break;
} else if (result < 4) {
dev_err(ddev, "config index %d descriptor too short "
"(expected %i, got %i)\n", cfgno,
......
......@@ -593,7 +593,7 @@ static ssize_t usb_device_read(struct file *file, char __user *buf, size_t nbyte
/* Kernel lock for "lastev" protection */
static unsigned int usb_device_poll(struct file *file, struct poll_table_struct *wait)
{
struct usb_device_status *st = (struct usb_device_status *)file->private_data;
struct usb_device_status *st = file->private_data;
unsigned int mask = 0;
lock_kernel();
......@@ -603,7 +603,7 @@ static unsigned int usb_device_poll(struct file *file, struct poll_table_struct
unlock_kernel();
return POLLIN;
}
/* we may have dropped BKL - need to check for having lost the race */
if (file->private_data) {
kfree(st);
......@@ -667,7 +667,7 @@ static loff_t usb_device_lseek(struct file * file, loff_t offset, int orig)
return ret;
}
struct file_operations usbfs_devices_fops = {
const struct file_operations usbfs_devices_fops = {
.llseek = usb_device_lseek,
.read = usb_device_read,
.poll = usb_device_poll,
......
......@@ -59,6 +59,9 @@
#define USB_DEVICE_MAX USB_MAXBUS * 128
static struct class *usb_device_class;
/* Mutual exclusion for removal, open, and release */
DEFINE_MUTEX(usbfs_mutex);
struct async {
struct list_head asynclist;
struct dev_state *ps;
......@@ -87,9 +90,10 @@ MODULE_PARM_DESC (usbfs_snoop, "true to log all usbfs traffic");
#define MAX_USBFS_BUFFER_SIZE 16384
static inline int connected (struct usb_device *dev)
static inline int connected (struct dev_state *ps)
{
return dev->state != USB_STATE_NOTATTACHED;
return (!list_empty(&ps->list) &&
ps->dev->state != USB_STATE_NOTATTACHED);
}
static loff_t usbdev_lseek(struct file *file, loff_t offset, int orig)
......@@ -118,7 +122,7 @@ static loff_t usbdev_lseek(struct file *file, loff_t offset, int orig)
static ssize_t usbdev_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos)
{
struct dev_state *ps = (struct dev_state *)file->private_data;
struct dev_state *ps = file->private_data;
struct usb_device *dev = ps->dev;
ssize_t ret = 0;
unsigned len;
......@@ -127,7 +131,7 @@ static ssize_t usbdev_read(struct file *file, char __user *buf, size_t nbytes, l
pos = *ppos;
usb_lock_device(dev);
if (!connected(dev)) {
if (!connected(ps)) {
ret = -ENODEV;
goto err;
} else if (pos < 0) {
......@@ -301,7 +305,7 @@ static void snoop_urb(struct urb *urb, void __user *userurb)
static void async_completed(struct urb *urb, struct pt_regs *regs)
{
struct async *as = (struct async *)urb->context;
struct async *as = urb->context;
struct dev_state *ps = as->ps;
struct siginfo sinfo;
......@@ -541,25 +545,25 @@ static int usbdev_open(struct inode *inode, struct file *file)
struct dev_state *ps;
int ret;
/*
* no locking necessary here, as chrdev_open has the kernel lock
* (still acquire the kernel lock for safety)
*/
/* Protect against simultaneous removal or release */
mutex_lock(&usbfs_mutex);
ret = -ENOMEM;
if (!(ps = kmalloc(sizeof(struct dev_state), GFP_KERNEL)))
goto out_nolock;
goto out;
lock_kernel();
ret = -ENOENT;
/* check if we are called from a real node or usbfs */
if (imajor(inode) == USB_DEVICE_MAJOR)
dev = usbdev_lookup_minor(iminor(inode));
if (!dev)
dev = inode->i_private;
if (!dev) {
kfree(ps);
if (!dev)
goto out;
}
ret = usb_autoresume_device(dev, 1);
if (ret)
goto out;
usb_get_dev(dev);
ret = 0;
ps->dev = dev;
......@@ -579,30 +583,36 @@ static int usbdev_open(struct inode *inode, struct file *file)
list_add_tail(&ps->list, &dev->filelist);
file->private_data = ps;
out:
unlock_kernel();
out_nolock:
return ret;
if (ret)
kfree(ps);
mutex_unlock(&usbfs_mutex);
return ret;
}
static int usbdev_release(struct inode *inode, struct file *file)
{
struct dev_state *ps = (struct dev_state *)file->private_data;
struct dev_state *ps = file->private_data;
struct usb_device *dev = ps->dev;
unsigned int ifnum;
usb_lock_device(dev);
/* Protect against simultaneous open */
mutex_lock(&usbfs_mutex);
list_del_init(&ps->list);
mutex_unlock(&usbfs_mutex);
for (ifnum = 0; ps->ifclaimed && ifnum < 8*sizeof(ps->ifclaimed);
ifnum++) {
if (test_bit(ifnum, &ps->ifclaimed))
releaseintf(ps, ifnum);
}
destroy_all_async(ps);
usb_autosuspend_device(dev, 1);
usb_unlock_device(dev);
usb_put_dev(dev);
ps->dev = NULL;
kfree(ps);
return 0;
return 0;
}
static int proc_control(struct dev_state *ps, void __user *arg)
......@@ -1322,7 +1332,7 @@ static int proc_ioctl(struct dev_state *ps, struct usbdevfs_ioctl *ctl)
}
}
if (!connected(ps->dev)) {
if (!connected(ps)) {
kfree(buf);
return -ENODEV;
}
......@@ -1349,7 +1359,7 @@ static int proc_ioctl(struct dev_state *ps, struct usbdevfs_ioctl *ctl)
/* let kernel drivers try to (re)bind to the interface */
case USBDEVFS_CONNECT:
usb_unlock_device(ps->dev);
bus_rescan_devices(intf->dev.bus);
retval = bus_rescan_devices(intf->dev.bus);
usb_lock_device(ps->dev);
break;
......@@ -1413,7 +1423,7 @@ static int proc_ioctl_compat(struct dev_state *ps, compat_uptr_t arg)
*/
static int usbdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
struct dev_state *ps = (struct dev_state *)file->private_data;
struct dev_state *ps = file->private_data;
struct usb_device *dev = ps->dev;
void __user *p = (void __user *)arg;
int ret = -ENOTTY;
......@@ -1421,7 +1431,7 @@ static int usbdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
if (!(file->f_mode & FMODE_WRITE))
return -EPERM;
usb_lock_device(dev);
if (!connected(dev)) {
if (!connected(ps)) {
usb_unlock_device(dev);
return -ENODEV;
}
......@@ -1556,18 +1566,18 @@ static int usbdev_ioctl(struct inode *inode, struct file *file, unsigned int cmd
/* No kernel lock - fine */
static unsigned int usbdev_poll(struct file *file, struct poll_table_struct *wait)
{
struct dev_state *ps = (struct dev_state *)file->private_data;
unsigned int mask = 0;
struct dev_state *ps = file->private_data;
unsigned int mask = 0;
poll_wait(file, &ps->wait, wait);
if (file->f_mode & FMODE_WRITE && !list_empty(&ps->async_completed))
mask |= POLLOUT | POLLWRNORM;
if (!connected(ps->dev))
if (!connected(ps))
mask |= POLLERR | POLLHUP;
return mask;
}
struct file_operations usbfs_device_file_operations = {
const struct file_operations usbfs_device_file_operations = {
.llseek = usbdev_lseek,
.read = usbdev_read,
.poll = usbdev_poll,
......
此差异已折叠。
......@@ -207,9 +207,9 @@ static void ep_device_release(struct device *dev)
kfree(ep_dev);
}
void usb_create_ep_files(struct device *parent,
struct usb_host_endpoint *endpoint,
struct usb_device *udev)
int usb_create_ep_files(struct device *parent,
struct usb_host_endpoint *endpoint,
struct usb_device *udev)
{
char name[8];
struct ep_device *ep_dev;
......@@ -242,19 +242,33 @@ void usb_create_ep_files(struct device *parent,
retval = device_register(&ep_dev->dev);
if (retval)
goto error;
sysfs_create_group(&ep_dev->dev.kobj, &ep_dev_attr_grp);
retval = sysfs_create_group(&ep_dev->dev.kobj, &ep_dev_attr_grp);
if (retval)
goto error_group;
endpoint->ep_dev = ep_dev;
/* create the symlink to the old-style "ep_XX" directory */
sprintf(name, "ep_%02x", endpoint->desc.bEndpointAddress);
sysfs_create_link(&parent->kobj, &endpoint->ep_dev->dev.kobj, name);
retval = sysfs_create_link(&parent->kobj,
&endpoint->ep_dev->dev.kobj, name);
if (retval)
goto error_link;
exit:
return;
return retval;
error_link:
sysfs_remove_group(&ep_dev->dev.kobj, &ep_dev_attr_grp);
error_group:
device_unregister(&ep_dev->dev);
endpoint->ep_dev = NULL;
destroy_endpoint_class();
return retval;
error:
kfree(ep_dev);
return;
destroy_endpoint_class();
return retval;
}
void usb_remove_ep_files(struct usb_host_endpoint *endpoint)
......
......@@ -55,7 +55,7 @@ static int usb_open(struct inode * inode, struct file * file)
return err;
}
static struct file_operations usb_fops = {
static const struct file_operations usb_fops = {
.owner = THIS_MODULE,
.open = usb_open,
};
......
/*
* drivers/usb/generic.c - generic driver for USB devices (not interfaces)
*
* (C) Copyright 2005 Greg Kroah-Hartman <gregkh@suse.de>
*
* based on drivers/usb/usb.c which had the following copyrights:
* (C) Copyright Linus Torvalds 1999
* (C) Copyright Johannes Erdfelt 1999-2001
* (C) Copyright Andreas Gal 1999
* (C) Copyright Gregory P. Smith 1999
* (C) Copyright Deti Fliegl 1999 (new USB architecture)
* (C) Copyright Randy Dunlap 2000
* (C) Copyright David Brownell 2000-2004
* (C) Copyright Yggdrasil Computing, Inc. 2000
* (usb_device_id matching changes by Adam J. Richter)
* (C) Copyright Greg Kroah-Hartman 2002-2003
*
*/
#include <linux/config.h>
#include <linux/usb.h>
#include "usb.h"
static inline const char *plural(int n)
{
return (n == 1 ? "" : "s");
}
static int choose_configuration(struct usb_device *udev)
{
int i;
int num_configs;
int insufficient_power = 0;
struct usb_host_config *c, *best;
best = NULL;
c = udev->config;
num_configs = udev->descriptor.bNumConfigurations;
for (i = 0; i < num_configs; (i++, c++)) {
struct usb_interface_descriptor *desc = NULL;
/* It's possible that a config has no interfaces! */
if (c->desc.bNumInterfaces > 0)
desc = &c->intf_cache[0]->altsetting->desc;
/*
* HP's USB bus-powered keyboard has only one configuration
* and it claims to be self-powered; other devices may have
* similar errors in their descriptors. If the next test
* were allowed to execute, such configurations would always
* be rejected and the devices would not work as expected.
* In the meantime, we run the risk of selecting a config
* that requires external power at a time when that power
* isn't available. It seems to be the lesser of two evils.
*
* Bugzilla #6448 reports a device that appears to crash
* when it receives a GET_DEVICE_STATUS request! We don't
* have any other way to tell whether a device is self-powered,
* but since we don't use that information anywhere but here,
* the call has been removed.
*
* Maybe the GET_DEVICE_STATUS call and the test below can
* be reinstated when device firmwares become more reliable.
* Don't hold your breath.
*/
#if 0
/* Rule out self-powered configs for a bus-powered device */
if (bus_powered && (c->desc.bmAttributes &
USB_CONFIG_ATT_SELFPOWER))
continue;
#endif
/*
* The next test may not be as effective as it should be.
* Some hubs have errors in their descriptor, claiming
* to be self-powered when they are really bus-powered.
* We will overestimate the amount of current such hubs
* make available for each port.
*
* This is a fairly benign sort of failure. It won't
* cause us to reject configurations that we should have
* accepted.
*/
/* Rule out configs that draw too much bus current */
if (c->desc.bMaxPower * 2 > udev->bus_mA) {
insufficient_power++;
continue;
}
/* If the first config's first interface is COMM/2/0xff
* (MSFT RNDIS), rule it out unless Linux has host-side
* RNDIS support. */
if (i == 0 && desc
&& desc->bInterfaceClass == USB_CLASS_COMM
&& desc->bInterfaceSubClass == 2
&& desc->bInterfaceProtocol == 0xff) {
#ifndef CONFIG_USB_NET_RNDIS_HOST
continue;
#else
best = c;
#endif
}
/* From the remaining configs, choose the first one whose
* first interface is for a non-vendor-specific class.
* Reason: Linux is more likely to have a class driver
* than a vendor-specific driver. */
else if (udev->descriptor.bDeviceClass !=
USB_CLASS_VENDOR_SPEC &&
(!desc || desc->bInterfaceClass !=
USB_CLASS_VENDOR_SPEC)) {
best = c;
break;
}
/* If all the remaining configs are vendor-specific,
* choose the first one. */
else if (!best)
best = c;
}
if (insufficient_power > 0)
dev_info(&udev->dev, "rejected %d configuration%s "
"due to insufficient available bus power\n",
insufficient_power, plural(insufficient_power));
if (best) {
i = best->desc.bConfigurationValue;
dev_info(&udev->dev,
"configuration #%d chosen from %d choice%s\n",
i, num_configs, plural(num_configs));
} else {
i = -1;
dev_warn(&udev->dev,
"no configuration chosen from %d choice%s\n",
num_configs, plural(num_configs));
}
return i;
}
static int generic_probe(struct usb_device *udev)
{
int err, c;
/* put device-specific files into sysfs */
usb_create_sysfs_dev_files(udev);
/* Choose and set the configuration. This registers the interfaces
* with the driver core and lets interface drivers bind to them.
*/
c = choose_configuration(udev);
if (c >= 0) {
err = usb_set_configuration(udev, c);
if (err) {
dev_err(&udev->dev, "can't set config #%d, error %d\n",
c, err);
/* This need not be fatal. The user can try to
* set other configurations. */
}
}
/* USB device state == configured ... usable */
usb_notify_add_device(udev);
return 0;
}
static void generic_disconnect(struct usb_device *udev)
{
usb_notify_remove_device(udev);
/* if this is only an unbind, not a physical disconnect, then
* unconfigure the device */
if (udev->actconfig)
usb_set_configuration(udev, 0);
usb_remove_sysfs_dev_files(udev);
}
#ifdef CONFIG_PM
static int generic_suspend(struct usb_device *udev, pm_message_t msg)
{
/* USB devices enter SUSPEND state through their hubs, but can be
* marked for FREEZE as soon as their children are already idled.
* But those semantics are useless, so we equate the two (sigh).
*/
return usb_port_suspend(udev);
}
static int generic_resume(struct usb_device *udev)
{
return usb_port_resume(udev);
}
#endif /* CONFIG_PM */
struct usb_device_driver usb_generic_driver = {
.name = "usb",
.probe = generic_probe,
.disconnect = generic_disconnect,
#ifdef CONFIG_PM
.suspend = generic_suspend,
.resume = generic_resume,
#endif
.supports_autosuspend = 1,
};
......@@ -413,4 +413,20 @@ EXPORT_SYMBOL (usb_hcd_pci_resume);
#endif /* CONFIG_PM */
/**
* usb_hcd_pci_shutdown - shutdown host controller
* @dev: USB Host Controller being shutdown
*/
void usb_hcd_pci_shutdown (struct pci_dev *dev)
{
struct usb_hcd *hcd;
hcd = pci_get_drvdata(dev);
if (!hcd)
return;
if (hcd->driver->shutdown)
hcd->driver->shutdown(hcd);
}
EXPORT_SYMBOL (usb_hcd_pci_shutdown);
......@@ -36,6 +36,7 @@
#include <linux/mutex.h>
#include <asm/irq.h>
#include <asm/byteorder.h>
#include <linux/platform_device.h>
#include <linux/usb.h>
......@@ -632,31 +633,20 @@ static int rh_urb_enqueue (struct usb_hcd *hcd, struct urb *urb)
/*-------------------------------------------------------------------------*/
/* Asynchronous unlinks of root-hub control URBs are legal, but they
* don't do anything. Status URB unlinks must be made in process context
* with interrupts enabled.
/* Unlinks of root-hub control URBs are legal, but they don't do anything
* since these URBs always execute synchronously.
*/
static int usb_rh_urb_dequeue (struct usb_hcd *hcd, struct urb *urb)
{
if (usb_pipeendpoint(urb->pipe) == 0) { /* Control URB */
if (in_interrupt())
return 0; /* nothing to do */
spin_lock_irq(&urb->lock); /* from usb_kill_urb */
++urb->reject;
spin_unlock_irq(&urb->lock);
wait_event(usb_kill_urb_queue,
atomic_read(&urb->use_count) == 0);
unsigned long flags;
spin_lock_irq(&urb->lock);
--urb->reject;
spin_unlock_irq(&urb->lock);
if (usb_pipeendpoint(urb->pipe) == 0) { /* Control URB */
; /* Do nothing */
} else { /* Status URB */
if (!hcd->uses_new_polling)
del_timer_sync (&hcd->rh_timer);
local_irq_disable ();
del_timer (&hcd->rh_timer);
local_irq_save (flags);
spin_lock (&hcd_root_hub_lock);
if (urb == hcd->status_urb) {
hcd->status_urb = NULL;
......@@ -666,7 +656,7 @@ static int usb_rh_urb_dequeue (struct usb_hcd *hcd, struct urb *urb)
spin_unlock (&hcd_root_hub_lock);
if (urb)
usb_hcd_giveback_urb (hcd, urb, NULL);
local_irq_enable ();
local_irq_restore (flags);
}
return 0;
......@@ -674,31 +664,6 @@ static int usb_rh_urb_dequeue (struct usb_hcd *hcd, struct urb *urb)
/*-------------------------------------------------------------------------*/
/* exported only within usbcore */
struct usb_bus *usb_bus_get(struct usb_bus *bus)
{
if (bus)
kref_get(&bus->kref);
return bus;
}
static void usb_host_release(struct kref *kref)
{
struct usb_bus *bus = container_of(kref, struct usb_bus, kref);
if (bus->release)
bus->release(bus);
}
/* exported only within usbcore */
void usb_bus_put(struct usb_bus *bus)
{
if (bus)
kref_put(&bus->kref, usb_host_release);
}
/*-------------------------------------------------------------------------*/
static struct class *usb_host_class;
int usb_host_init(void)
......@@ -730,39 +695,12 @@ static void usb_bus_init (struct usb_bus *bus)
bus->devnum_next = 1;
bus->root_hub = NULL;
bus->hcpriv = NULL;
bus->busnum = -1;
bus->bandwidth_allocated = 0;
bus->bandwidth_int_reqs = 0;
bus->bandwidth_isoc_reqs = 0;
INIT_LIST_HEAD (&bus->bus_list);
kref_init(&bus->kref);
}
/**
* usb_alloc_bus - creates a new USB host controller structure
* @op: pointer to a struct usb_operations that this bus structure should use
* Context: !in_interrupt()
*
* Creates a USB host controller bus structure with the specified
* usb_operations and initializes all the necessary internal objects.
*
* If no memory is available, NULL is returned.
*
* The caller should call usb_put_bus() when it is finished with the structure.
*/
struct usb_bus *usb_alloc_bus (struct usb_operations *op)
{
struct usb_bus *bus;
bus = kzalloc (sizeof *bus, GFP_KERNEL);
if (!bus)
return NULL;
usb_bus_init (bus);
bus->op = op;
return bus;
}
/*-------------------------------------------------------------------------*/
......@@ -1112,10 +1050,10 @@ static void urb_unlink (struct urb *urb)
* expects usb_submit_urb() to have sanity checked and conditioned all
* inputs in the urb
*/
static int hcd_submit_urb (struct urb *urb, gfp_t mem_flags)
int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags)
{
int status;
struct usb_hcd *hcd = urb->dev->bus->hcpriv;
struct usb_hcd *hcd = bus_to_hcd(urb->dev->bus);
struct usb_host_endpoint *ep;
unsigned long flags;
......@@ -1186,7 +1124,7 @@ static int hcd_submit_urb (struct urb *urb, gfp_t mem_flags)
/* lower level hcd code should use *_dma exclusively,
* unless it uses pio or talks to another transport.
*/
if (hcd->self.controller->dma_mask) {
if (hcd->self.uses_dma) {
if (usb_pipecontrol (urb->pipe)
&& !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP))
urb->setup_dma = dma_map_single (
......@@ -1221,9 +1159,10 @@ static int hcd_submit_urb (struct urb *urb, gfp_t mem_flags)
/*-------------------------------------------------------------------------*/
/* called in any context */
static int hcd_get_frame_number (struct usb_device *udev)
int usb_hcd_get_frame_number (struct usb_device *udev)
{
struct usb_hcd *hcd = (struct usb_hcd *)udev->bus->hcpriv;
struct usb_hcd *hcd = bus_to_hcd(udev->bus);
if (!HC_IS_RUNNING (hcd->state))
return -ESHUTDOWN;
return hcd->driver->get_frame_number (hcd);
......@@ -1263,7 +1202,7 @@ unlink1 (struct usb_hcd *hcd, struct urb *urb)
* caller guarantees urb won't be recycled till both unlink()
* and the urb's completion function return
*/
static int hcd_unlink_urb (struct urb *urb, int status)
int usb_hcd_unlink_urb (struct urb *urb, int status)
{
struct usb_host_endpoint *ep;
struct usb_hcd *hcd = NULL;
......@@ -1296,7 +1235,7 @@ static int hcd_unlink_urb (struct urb *urb, int status)
spin_lock (&hcd_data_lock);
sys = &urb->dev->dev;
hcd = urb->dev->bus->hcpriv;
hcd = bus_to_hcd(urb->dev->bus);
if (hcd == NULL) {
retval = -ENODEV;
goto done;
......@@ -1354,41 +1293,33 @@ static int hcd_unlink_urb (struct urb *urb, int status)
/*-------------------------------------------------------------------------*/
/* disables the endpoint: cancels any pending urbs, then synchronizes with
* the hcd to make sure all endpoint state is gone from hardware. use for
* the hcd to make sure all endpoint state is gone from hardware, and then
* waits until the endpoint's queue is completely drained. use for
* set_configuration, set_interface, driver removal, physical disconnect.
*
* example: a qh stored in ep->hcpriv, holding state related to endpoint
* type, maxpacket size, toggle, halt status, and scheduling.
*/
static void
hcd_endpoint_disable (struct usb_device *udev, struct usb_host_endpoint *ep)
void usb_hcd_endpoint_disable (struct usb_device *udev,
struct usb_host_endpoint *ep)
{
struct usb_hcd *hcd;
struct urb *urb;
hcd = udev->bus->hcpriv;
hcd = bus_to_hcd(udev->bus);
WARN_ON (!HC_IS_RUNNING (hcd->state) && hcd->state != HC_STATE_HALT &&
udev->state != USB_STATE_NOTATTACHED);
local_irq_disable ();
/* FIXME move most of this into message.c as part of its
* endpoint disable logic
*/
/* ep is already gone from udev->ep_{in,out}[]; no more submits */
rescan:
spin_lock (&hcd_data_lock);
list_for_each_entry (urb, &ep->urb_list, urb_list) {
int tmp;
/* another cpu may be in hcd, spinning on hcd_data_lock
* to giveback() this urb. the races here should be
* small, but a full fix needs a new "can't submit"
* urb state.
* FIXME urb->reject should allow that...
*/
/* the urb may already have been unlinked */
if (urb->status != -EINPROGRESS)
continue;
usb_get_urb (urb);
......@@ -1430,6 +1361,30 @@ hcd_endpoint_disable (struct usb_device *udev, struct usb_host_endpoint *ep)
might_sleep ();
if (hcd->driver->endpoint_disable)
hcd->driver->endpoint_disable (hcd, ep);
/* Wait until the endpoint queue is completely empty. Most HCDs
* will have done this already in their endpoint_disable method,
* but some might not. And there could be root-hub control URBs
* still pending since they aren't affected by the HCDs'
* endpoint_disable methods.
*/
while (!list_empty (&ep->urb_list)) {
spin_lock_irq (&hcd_data_lock);
/* The list may have changed while we acquired the spinlock */
urb = NULL;
if (!list_empty (&ep->urb_list)) {
urb = list_entry (ep->urb_list.prev, struct urb,
urb_list);
usb_get_urb (urb);
}
spin_unlock_irq (&hcd_data_lock);
if (urb) {
usb_kill_urb (urb);
usb_put_urb (urb);
}
}
}
/*-------------------------------------------------------------------------*/
......@@ -1476,50 +1431,6 @@ int hcd_bus_resume (struct usb_bus *bus)
return status;
}
/*
* usb_hcd_suspend_root_hub - HCD autosuspends downstream ports
* @hcd: host controller for this root hub
*
* This call arranges that usb_hcd_resume_root_hub() is safe to call later;
* that the HCD's root hub polling is deactivated; and that the root's hub
* driver is suspended. HCDs may call this to autosuspend when their root
* hub's downstream ports are all inactive: unpowered, disconnected,
* disabled, or suspended.
*
* The HCD will autoresume on device connect change detection (using SRP
* or a D+/D- pullup). The HCD also autoresumes on remote wakeup signaling
* from any ports that are suspended (if that is enabled). In most cases,
* overcurrent signaling (on powered ports) will also start autoresume.
*
* Always called with IRQs blocked.
*/
void usb_hcd_suspend_root_hub (struct usb_hcd *hcd)
{
struct urb *urb;
spin_lock (&hcd_root_hub_lock);
usb_suspend_root_hub (hcd->self.root_hub);
/* force status urb to complete/unlink while suspended */
if (hcd->status_urb) {
urb = hcd->status_urb;
urb->status = -ECONNRESET;
urb->hcpriv = NULL;
urb->actual_length = 0;
del_timer (&hcd->rh_timer);
hcd->poll_pending = 0;
hcd->status_urb = NULL;
} else
urb = NULL;
spin_unlock (&hcd_root_hub_lock);
hcd->state = HC_STATE_SUSPENDED;
if (urb)
usb_hcd_giveback_urb (hcd, urb, NULL);
}
EXPORT_SYMBOL_GPL(usb_hcd_suspend_root_hub);
/**
* usb_hcd_resume_root_hub - called by HCD to resume its root hub
* @hcd: host controller for this root hub
......@@ -1583,20 +1494,6 @@ EXPORT_SYMBOL (usb_bus_start_enum);
/*-------------------------------------------------------------------------*/
/*
* usb_hcd_operations - adapts usb_bus framework to HCD framework (bus glue)
*/
static struct usb_operations usb_hcd_operations = {
.get_frame_number = hcd_get_frame_number,
.submit_urb = hcd_submit_urb,
.unlink_urb = hcd_unlink_urb,
.buffer_alloc = hcd_buffer_alloc,
.buffer_free = hcd_buffer_free,
.disable = hcd_endpoint_disable,
};
/*-------------------------------------------------------------------------*/
/**
* usb_hcd_giveback_urb - return URB from HCD to device driver
* @hcd: host controller returning the URB
......@@ -1617,8 +1514,9 @@ void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb, struct pt_regs
at_root_hub = (urb->dev == hcd->self.root_hub);
urb_unlink (urb);
/* lower level hcd code should use *_dma exclusively */
if (hcd->self.controller->dma_mask && !at_root_hub) {
/* lower level hcd code should use *_dma exclusively if the
* host controller does DMA */
if (hcd->self.uses_dma && !at_root_hub) {
if (usb_pipecontrol (urb->pipe)
&& !(urb->transfer_flags & URB_NO_SETUP_DMA_MAP))
dma_unmap_single (hcd->self.controller, urb->setup_dma,
......@@ -1704,14 +1602,6 @@ EXPORT_SYMBOL_GPL (usb_hc_died);
/*-------------------------------------------------------------------------*/
static void hcd_release (struct usb_bus *bus)
{
struct usb_hcd *hcd;
hcd = container_of(bus, struct usb_hcd, self);
kfree(hcd);
}
/**
* usb_create_hcd - create and initialize an HCD structure
* @driver: HC driver that will use this hcd
......@@ -1736,13 +1626,12 @@ struct usb_hcd *usb_create_hcd (const struct hc_driver *driver,
return NULL;
}
dev_set_drvdata(dev, hcd);
kref_init(&hcd->kref);
usb_bus_init(&hcd->self);
hcd->self.op = &usb_hcd_operations;
hcd->self.hcpriv = hcd;
hcd->self.release = &hcd_release;
hcd->self.controller = dev;
hcd->self.bus_name = bus_name;
hcd->self.uses_dma = (dev->dma_mask != NULL);
init_timer(&hcd->rh_timer);
hcd->rh_timer.function = rh_timer_func;
......@@ -1756,10 +1645,25 @@ struct usb_hcd *usb_create_hcd (const struct hc_driver *driver,
}
EXPORT_SYMBOL (usb_create_hcd);
static void hcd_release (struct kref *kref)
{
struct usb_hcd *hcd = container_of (kref, struct usb_hcd, kref);
kfree(hcd);
}
struct usb_hcd *usb_get_hcd (struct usb_hcd *hcd)
{
if (hcd)
kref_get (&hcd->kref);
return hcd;
}
EXPORT_SYMBOL (usb_get_hcd);
void usb_put_hcd (struct usb_hcd *hcd)
{
dev_set_drvdata(hcd->self.controller, NULL);
usb_bus_put(&hcd->self);
if (hcd)
kref_put (&hcd->kref, hcd_release);
}
EXPORT_SYMBOL (usb_put_hcd);
......@@ -1915,6 +1819,16 @@ void usb_remove_hcd(struct usb_hcd *hcd)
}
EXPORT_SYMBOL (usb_remove_hcd);
void
usb_hcd_platform_shutdown(struct platform_device* dev)
{
struct usb_hcd *hcd = platform_get_drvdata(dev);
if (hcd->driver->shutdown)
hcd->driver->shutdown(hcd);
}
EXPORT_SYMBOL (usb_hcd_platform_shutdown);
/*-------------------------------------------------------------------------*/
#if defined(CONFIG_USB_MON)
......
......@@ -55,12 +55,13 @@
/*-------------------------------------------------------------------------*/
struct usb_hcd { /* usb_bus.hcpriv points to this */
struct usb_hcd {
/*
* housekeeping
*/
struct usb_bus self; /* hcd is-a bus */
struct kref kref; /* reference counter */
const char *product_desc; /* product/vendor string */
char irq_descr[24]; /* driver + bus # */
......@@ -85,6 +86,7 @@ struct usb_hcd { /* usb_bus.hcpriv points to this */
unsigned uses_new_polling:1;
unsigned poll_rh:1; /* poll for rh status? */
unsigned poll_pending:1; /* status has changed? */
unsigned wireless:1; /* Wireless USB HCD */
int irq; /* irq allocated */
void __iomem *regs; /* device memory/io */
......@@ -128,8 +130,10 @@ static inline struct usb_bus *hcd_to_bus (struct usb_hcd *hcd)
return &hcd->self;
}
// urb.hcpriv is really hardware-specific
static inline struct usb_hcd *bus_to_hcd (struct usb_bus *bus)
{
return container_of(bus, struct usb_hcd, self);
}
struct hcd_timeout { /* timeouts we allocate */
struct list_head timeout_list;
......@@ -138,28 +142,6 @@ struct hcd_timeout { /* timeouts we allocate */
/*-------------------------------------------------------------------------*/
/*
* FIXME usb_operations should vanish or become hc_driver,
* when usb_bus and usb_hcd become the same thing.
*/
struct usb_operations {
int (*get_frame_number) (struct usb_device *usb_dev);
int (*submit_urb) (struct urb *urb, gfp_t mem_flags);
int (*unlink_urb) (struct urb *urb, int status);
/* allocate dma-consistent buffer for URB_DMA_NOMAPPING */
void *(*buffer_alloc)(struct usb_bus *bus, size_t size,
gfp_t mem_flags,
dma_addr_t *dma);
void (*buffer_free)(struct usb_bus *bus, size_t size,
void *addr, dma_addr_t dma);
void (*disable)(struct usb_device *udev,
struct usb_host_endpoint *ep);
};
/* each driver provides one of these, and hardware init support */
struct pt_regs;
......@@ -192,6 +174,9 @@ struct hc_driver {
/* cleanly make HCD stop writing memory and doing I/O */
void (*stop) (struct usb_hcd *hcd);
/* shutdown HCD */
void (*shutdown) (struct usb_hcd *hcd);
/* return current frame number */
int (*get_frame_number) (struct usb_hcd *hcd);
......@@ -218,15 +203,25 @@ struct hc_driver {
/* Needed only if port-change IRQs are level-triggered */
};
extern void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb, struct pt_regs *regs);
extern int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags);
extern int usb_hcd_unlink_urb (struct urb *urb, int status);
extern void usb_hcd_giveback_urb (struct usb_hcd *hcd, struct urb *urb,
struct pt_regs *regs);
extern void usb_hcd_endpoint_disable (struct usb_device *udev,
struct usb_host_endpoint *ep);
extern int usb_hcd_get_frame_number (struct usb_device *udev);
extern struct usb_hcd *usb_create_hcd (const struct hc_driver *driver,
struct device *dev, char *bus_name);
extern struct usb_hcd *usb_get_hcd (struct usb_hcd *hcd);
extern void usb_put_hcd (struct usb_hcd *hcd);
extern int usb_add_hcd(struct usb_hcd *hcd,
unsigned int irqnum, unsigned long irqflags);
extern void usb_remove_hcd(struct usb_hcd *hcd);
struct platform_device;
extern void usb_hcd_platform_shutdown(struct platform_device* dev);
#ifdef CONFIG_PCI
struct pci_dev;
struct pci_device_id;
......@@ -239,6 +234,8 @@ extern int usb_hcd_pci_suspend (struct pci_dev *dev, pm_message_t state);
extern int usb_hcd_pci_resume (struct pci_dev *dev);
#endif /* CONFIG_PM */
extern void usb_hcd_pci_shutdown (struct pci_dev *dev);
#endif /* CONFIG_PCI */
/* pci-ish (pdev null is ok) buffer alloc/mapping support */
......@@ -352,8 +349,6 @@ extern long usb_calc_bus_time (int speed, int is_input,
/*-------------------------------------------------------------------------*/
extern struct usb_bus *usb_alloc_bus (struct usb_operations *);
extern void usb_set_device_state(struct usb_device *udev,
enum usb_device_state new_state);
......@@ -365,9 +360,6 @@ extern struct list_head usb_bus_list;
extern struct mutex usb_bus_list_lock;
extern wait_queue_head_t usb_kill_urb_queue;
extern struct usb_bus *usb_bus_get (struct usb_bus *bus);
extern void usb_bus_put (struct usb_bus *bus);
extern void usb_enable_root_hub_irq (struct usb_bus *bus);
extern int usb_find_interface_driver (struct usb_device *dev,
......@@ -376,17 +368,11 @@ extern int usb_find_interface_driver (struct usb_device *dev,
#define usb_endpoint_out(ep_dir) (!((ep_dir) & USB_DIR_IN))
#ifdef CONFIG_PM
extern void usb_hcd_suspend_root_hub (struct usb_hcd *hcd);
extern void usb_hcd_resume_root_hub (struct usb_hcd *hcd);
extern void usb_root_hub_lost_power (struct usb_device *rhdev);
extern int hcd_bus_suspend (struct usb_bus *bus);
extern int hcd_bus_resume (struct usb_bus *bus);
#else
static inline void usb_hcd_suspend_root_hub(struct usb_hcd *hcd)
{
return;
}
static inline void usb_hcd_resume_root_hub(struct usb_hcd *hcd)
{
return;
......
此差异已折叠。
......@@ -212,7 +212,8 @@ struct usb_hub {
unsigned long event_bits[1]; /* status change bitmask */
unsigned long change_bits[1]; /* ports with logical connect
status change */
unsigned long busy_bits[1]; /* ports being reset */
unsigned long busy_bits[1]; /* ports being reset or
resumed */
#if USB_MAXCHILDREN > 31 /* 8*sizeof(unsigned long) - 1 */
#error event_bits[] is too short!
#endif
......
......@@ -44,7 +44,7 @@
#include "hcd.h"
static struct super_operations usbfs_ops;
static struct file_operations default_file_operations;
static const struct file_operations default_file_operations;
static struct vfsmount *usbfs_mount;
static int usbfs_mount_count; /* = 0 */
static int ignore_mount = 0;
......@@ -407,7 +407,7 @@ static int default_open (struct inode *inode, struct file *file)
return 0;
}
static struct file_operations default_file_operations = {
static const struct file_operations default_file_operations = {
.read = default_read_file,
.write = default_write_file,
.open = default_open,
......@@ -494,7 +494,7 @@ static int fs_create_by_name (const char *name, mode_t mode,
static struct dentry *fs_create_file (const char *name, mode_t mode,
struct dentry *parent, void *data,
struct file_operations *fops,
const struct file_operations *fops,
uid_t uid, gid_t gid)
{
struct dentry *dentry;
......
......@@ -23,59 +23,44 @@ static void usb_api_blocking_completion(struct urb *urb, struct pt_regs *regs)
}
static void timeout_kill(unsigned long data)
{
struct urb *urb = (struct urb *) data;
usb_unlink_urb(urb);
}
// Starts urb and waits for completion or timeout
// note that this call is NOT interruptible, while
// many device driver i/o requests should be interruptible
static int usb_start_wait_urb(struct urb *urb, int timeout, int* actual_length)
/*
* Starts urb and waits for completion or timeout. Note that this call
* is NOT interruptible. Many device driver i/o requests should be
* interruptible and therefore these drivers should implement their
* own interruptible routines.
*/
static int usb_start_wait_urb(struct urb *urb, int timeout, int *actual_length)
{
struct completion done;
struct timer_list timer;
int status;
struct completion done;
unsigned long expire;
int status;
init_completion(&done);
urb->context = &done;
urb->actual_length = 0;
status = usb_submit_urb(urb, GFP_NOIO);
if (status == 0) {
if (timeout > 0) {
init_timer(&timer);
timer.expires = jiffies + msecs_to_jiffies(timeout);
timer.data = (unsigned long)urb;
timer.function = timeout_kill;
/* grr. timeout _should_ include submit delays. */
add_timer(&timer);
}
wait_for_completion(&done);
if (unlikely(status))
goto out;
expire = timeout ? msecs_to_jiffies(timeout) : MAX_SCHEDULE_TIMEOUT;
if (!wait_for_completion_timeout(&done, expire)) {
dev_dbg(&urb->dev->dev,
"%s timed out on ep%d%s len=%d/%d\n",
current->comm,
usb_pipeendpoint(urb->pipe),
usb_pipein(urb->pipe) ? "in" : "out",
urb->actual_length,
urb->transfer_buffer_length);
usb_kill_urb(urb);
status = urb->status == -ENOENT ? -ETIMEDOUT : urb->status;
} else
status = urb->status;
/* note: HCDs return ETIMEDOUT for other reasons too */
if (status == -ECONNRESET) {
dev_dbg(&urb->dev->dev,
"%s timed out on ep%d%s len=%d/%d\n",
current->comm,
usb_pipeendpoint(urb->pipe),
usb_pipein(urb->pipe) ? "in" : "out",
urb->actual_length,
urb->transfer_buffer_length
);
if (urb->actual_length > 0)
status = 0;
else
status = -ETIMEDOUT;
}
if (timeout > 0)
del_timer_sync(&timer);
}
out:
if (actual_length)
*actual_length = urb->actual_length;
usb_free_urb(urb);
return status;
}
......@@ -263,7 +248,7 @@ static void sg_clean (struct usb_sg_request *io)
static void sg_complete (struct urb *urb, struct pt_regs *regs)
{
struct usb_sg_request *io = (struct usb_sg_request *) urb->context;
struct usb_sg_request *io = urb->context;
spin_lock (&io->lock);
......@@ -999,8 +984,8 @@ void usb_disable_endpoint(struct usb_device *dev, unsigned int epaddr)
ep = dev->ep_in[epnum];
dev->ep_in[epnum] = NULL;
}
if (ep && dev->bus && dev->bus->op && dev->bus->op->disable)
dev->bus->op->disable(dev, ep);
if (ep && dev->bus)
usb_hcd_endpoint_disable(dev, ep);
}
/**
......@@ -1381,9 +1366,6 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
if (cp && configuration == 0)
dev_warn(&dev->dev, "config 0 descriptor??\n");
if (dev->state == USB_STATE_SUSPENDED)
return -EHOSTUNREACH;
/* Allocate memory for new interfaces before doing anything else,
* so that if we run out then nothing will have changed. */
n = nintf = 0;
......@@ -1418,6 +1400,11 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
configuration, -i);
}
/* Wake up the device so we can send it the Set-Config request */
ret = usb_autoresume_device(dev, 1);
if (ret)
goto free_interfaces;
/* if it's already configured, clear out old state first.
* getting rid of old interfaces means unbinding their drivers.
*/
......@@ -1437,6 +1424,7 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
dev->actconfig = cp;
if (!cp) {
usb_set_device_state(dev, USB_STATE_ADDRESS);
usb_autosuspend_device(dev, 1);
goto free_interfaces;
}
usb_set_device_state(dev, USB_STATE_CONFIGURED);
......@@ -1505,8 +1493,68 @@ int usb_set_configuration(struct usb_device *dev, int configuration)
usb_create_sysfs_intf_files (intf);
}
usb_autosuspend_device(dev, 1);
return 0;
}
struct set_config_request {
struct usb_device *udev;
int config;
struct work_struct work;
};
/* Worker routine for usb_driver_set_configuration() */
static void driver_set_config_work(void *_req)
{
struct set_config_request *req = _req;
usb_lock_device(req->udev);
usb_set_configuration(req->udev, req->config);
usb_unlock_device(req->udev);
usb_put_dev(req->udev);
kfree(req);
}
/**
* usb_driver_set_configuration - Provide a way for drivers to change device configurations
* @udev: the device whose configuration is being updated
* @config: the configuration being chosen.
* Context: In process context, must be able to sleep
*
* Device interface drivers are not allowed to change device configurations.
* This is because changing configurations will destroy the interface the
* driver is bound to and create new ones; it would be like a floppy-disk
* driver telling the computer to replace the floppy-disk drive with a
* tape drive!
*
* Still, in certain specialized circumstances the need may arise. This
* routine gets around the normal restrictions by using a work thread to
* submit the change-config request.
*
* Returns 0 if the request was succesfully queued, error code otherwise.
* The caller has no way to know whether the queued request will eventually
* succeed.
*/
int usb_driver_set_configuration(struct usb_device *udev, int config)
{
struct set_config_request *req;
req = kmalloc(sizeof(*req), GFP_KERNEL);
if (!req)
return -ENOMEM;
req->udev = udev;
req->config = config;
INIT_WORK(&req->work, driver_set_config_work, req);
usb_get_dev(udev);
if (!schedule_work(&req->work)) {
usb_put_dev(udev);
kfree(req);
return -EINVAL;
}
return 0;
}
EXPORT_SYMBOL_GPL(usb_driver_set_configuration);
// synchronous request completion model
EXPORT_SYMBOL(usb_control_msg);
......
......@@ -50,8 +50,11 @@ void usb_notify_add_device(struct usb_device *udev)
void usb_notify_remove_device(struct usb_device *udev)
{
/* Protect against simultaneous usbfs open */
mutex_lock(&usbfs_mutex);
blocking_notifier_call_chain(&usb_notifier_list,
USB_DEVICE_REMOVE, udev);
mutex_unlock(&usbfs_mutex);
}
void usb_notify_add_bus(struct usb_bus *ubus)
......
......@@ -60,7 +60,7 @@ static ssize_t
set_bConfigurationValue (struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
struct usb_device *udev = udev = to_usb_device (dev);
struct usb_device *udev = to_usb_device (dev);
int config, value;
if (sscanf (buf, "%u", &config) != 1 || config > 255)
......@@ -186,6 +186,7 @@ usb_descriptor_attr (bMaxPacketSize0, "%d\n")
static struct attribute *dev_attrs[] = {
/* current configuration's attributes */
&dev_attr_configuration.attr,
&dev_attr_bNumInterfaces.attr,
&dev_attr_bConfigurationValue.attr,
&dev_attr_bmAttributes.attr,
......@@ -209,20 +210,40 @@ static struct attribute_group dev_attr_grp = {
.attrs = dev_attrs,
};
void usb_create_sysfs_dev_files (struct usb_device *udev)
int usb_create_sysfs_dev_files(struct usb_device *udev)
{
struct device *dev = &udev->dev;
int retval;
sysfs_create_group(&dev->kobj, &dev_attr_grp);
retval = sysfs_create_group(&dev->kobj, &dev_attr_grp);
if (retval)
return retval;
if (udev->manufacturer)
device_create_file (dev, &dev_attr_manufacturer);
if (udev->product)
device_create_file (dev, &dev_attr_product);
if (udev->serial)
device_create_file (dev, &dev_attr_serial);
device_create_file (dev, &dev_attr_configuration);
usb_create_ep_files(dev, &udev->ep0, udev);
if (udev->manufacturer) {
retval = device_create_file (dev, &dev_attr_manufacturer);
if (retval)
goto error;
}
if (udev->product) {
retval = device_create_file (dev, &dev_attr_product);
if (retval)
goto error;
}
if (udev->serial) {
retval = device_create_file (dev, &dev_attr_serial);
if (retval)
goto error;
}
retval = usb_create_ep_files(dev, &udev->ep0, udev);
if (retval)
goto error;
return 0;
error:
usb_remove_ep_files(&udev->ep0);
device_remove_file(dev, &dev_attr_manufacturer);
device_remove_file(dev, &dev_attr_product);
device_remove_file(dev, &dev_attr_serial);
return retval;
}
void usb_remove_sysfs_dev_files (struct usb_device *udev)
......@@ -238,7 +259,6 @@ void usb_remove_sysfs_dev_files (struct usb_device *udev)
device_remove_file(dev, &dev_attr_product);
if (udev->serial)
device_remove_file(dev, &dev_attr_serial);
device_remove_file (dev, &dev_attr_configuration);
}
/* Interface fields */
......@@ -340,18 +360,28 @@ static inline void usb_remove_intf_ep_files(struct usb_interface *intf)
usb_remove_ep_files(&iface_desc->endpoint[i]);
}
void usb_create_sysfs_intf_files (struct usb_interface *intf)
int usb_create_sysfs_intf_files(struct usb_interface *intf)
{
struct usb_device *udev = interface_to_usbdev(intf);
struct usb_host_interface *alt = intf->cur_altsetting;
int retval;
sysfs_create_group(&intf->dev.kobj, &intf_attr_grp);
retval = sysfs_create_group(&intf->dev.kobj, &intf_attr_grp);
if (retval)
goto error;
if (alt->string == NULL)
alt->string = usb_cache_string(udev, alt->desc.iInterface);
if (alt->string)
device_create_file(&intf->dev, &dev_attr_interface);
retval = device_create_file(&intf->dev, &dev_attr_interface);
usb_create_intf_ep_files(intf, udev);
return 0;
error:
if (alt->string)
device_remove_file(&intf->dev, &dev_attr_interface);
sysfs_remove_group(&intf->dev.kobj, &intf_attr_grp);
usb_remove_intf_ep_files(intf);
return retval;
}
void usb_remove_sysfs_intf_files (struct usb_interface *intf)
......
......@@ -57,7 +57,7 @@ struct urb *usb_alloc_urb(int iso_packets, gfp_t mem_flags)
{
struct urb *urb;
urb = (struct urb *)kmalloc(sizeof(struct urb) +
urb = kmalloc(sizeof(struct urb) +
iso_packets * sizeof(struct usb_iso_packet_descriptor),
mem_flags);
if (!urb) {
......@@ -221,7 +221,6 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
{
int pipe, temp, max;
struct usb_device *dev;
struct usb_operations *op;
int is_out;
if (!urb || urb->hcpriv || !urb->complete)
......@@ -233,8 +232,6 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
if (dev->bus->controller->power.power_state.event != PM_EVENT_ON
|| dev->state == USB_STATE_SUSPENDED)
return -EHOSTUNREACH;
if (!(op = dev->bus->op) || !op->submit_urb)
return -ENODEV;
urb->status = -EINPROGRESS;
urb->actual_length = 0;
......@@ -376,7 +373,7 @@ int usb_submit_urb(struct urb *urb, gfp_t mem_flags)
urb->interval = temp;
}
return op->submit_urb (urb, mem_flags);
return usb_hcd_submit_urb (urb, mem_flags);
}
/*-------------------------------------------------------------------*/
......@@ -440,9 +437,9 @@ int usb_unlink_urb(struct urb *urb)
{
if (!urb)
return -EINVAL;
if (!(urb->dev && urb->dev->bus && urb->dev->bus->op))
if (!(urb->dev && urb->dev->bus))
return -ENODEV;
return urb->dev->bus->op->unlink_urb(urb, -ECONNRESET);
return usb_hcd_unlink_urb(urb, -ECONNRESET);
}
/**
......@@ -468,13 +465,13 @@ int usb_unlink_urb(struct urb *urb)
void usb_kill_urb(struct urb *urb)
{
might_sleep();
if (!(urb && urb->dev && urb->dev->bus && urb->dev->bus->op))
if (!(urb && urb->dev && urb->dev->bus))
return;
spin_lock_irq(&urb->lock);
++urb->reject;
spin_unlock_irq(&urb->lock);
urb->dev->bus->op->unlink_urb(urb, -ENOENT);
usb_hcd_unlink_urb(urb, -ENOENT);
wait_event(usb_kill_urb_queue, atomic_read(&urb->use_count) == 0);
spin_lock_irq(&urb->lock);
......
此差异已折叠。
此差异已折叠。
......@@ -26,7 +26,7 @@ config USB_GADGET
you need a low level bus controller driver, and some software
talking to it. Peripheral controllers are often discrete silicon,
or are integrated with the CPU in a microcontroller. The more
familiar host side controllers have names like like "EHCI", "OHCI",
familiar host side controllers have names like "EHCI", "OHCI",
or "UHCI", and are usually integrated into southbridges on PC
motherboards.
......@@ -404,6 +404,20 @@ config USB_G_SERIAL
which includes instructions and a "driver info file" needed to
make MS-Windows work with this driver.
config USB_MIDI_GADGET
tristate "MIDI Gadget (EXPERIMENTAL)"
depends on SND && EXPERIMENTAL
select SND_RAWMIDI
help
The MIDI Gadget acts as a USB Audio device, with one MIDI
input and one MIDI output. These MIDI jacks appear as
a sound "card" in the ALSA sound system. Other MIDI
connections can then be made on the gadget system, using
ALSA's aconnect utility etc.
Say "y" to link the driver statically, or "m" to build a
dynamically linked module called "g_midi".
# put drivers that need isochronous transfer support (for audio
# or video class gadget drivers), or specific hardware, here.
......
......@@ -15,6 +15,7 @@ obj-$(CONFIG_USB_AT91) += at91_udc.o
g_zero-objs := zero.o usbstring.o config.o epautoconf.o
g_ether-objs := ether.o usbstring.o config.o epautoconf.o
g_serial-objs := serial.o usbstring.o config.o epautoconf.o
g_midi-objs := gmidi.o usbstring.o config.o epautoconf.o
gadgetfs-objs := inode.o
g_file_storage-objs := file_storage.o usbstring.o config.o \
epautoconf.o
......@@ -28,4 +29,5 @@ obj-$(CONFIG_USB_ETH) += g_ether.o
obj-$(CONFIG_USB_GADGETFS) += gadgetfs.o
obj-$(CONFIG_USB_FILE_STORAGE) += g_file_storage.o
obj-$(CONFIG_USB_G_SERIAL) += g_serial.o
obj-$(CONFIG_USB_MIDI_GADGET) += g_midi.o
......@@ -247,7 +247,7 @@ static int proc_udc_open(struct inode *inode, struct file *file)
return single_open(file, proc_udc_show, PDE(inode)->data);
}
static struct file_operations proc_ops = {
static const struct file_operations proc_ops = {
.open = proc_udc_open,
.read = seq_read,
.llseek = seq_lseek,
......
......@@ -889,11 +889,9 @@ EXPORT_SYMBOL (net2280_set_fifo_mode);
static void
dummy_gadget_release (struct device *dev)
{
#if 0 /* usb_bus_put isn't EXPORTed! */
struct dummy *dum = gadget_dev_to_dummy (dev);
usb_bus_put (&dummy_to_hcd (dum)->self);
#endif
usb_put_hcd (dummy_to_hcd (dum));
}
static int dummy_udc_probe (struct platform_device *pdev)
......@@ -915,9 +913,7 @@ static int dummy_udc_probe (struct platform_device *pdev)
if (rc < 0)
return rc;
#if 0 /* usb_bus_get isn't EXPORTed! */
usb_bus_get (&dummy_to_hcd (dum)->self);
#endif
usb_get_hcd (dummy_to_hcd (dum));
platform_set_drvdata (pdev, dum);
device_create_file (&dum->gadget.dev, &dev_attr_function);
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
......@@ -40,7 +40,7 @@
#include <linux/platform_device.h>
#include <linux/usb_ch9.h>
#include <linux/usb_gadget.h>
#include <linux/usb_otg.h>
#include <linux/usb/otg.h>
#include <linux/dma-mapping.h>
#include <asm/byteorder.h>
......@@ -2437,7 +2437,7 @@ static int proc_udc_open(struct inode *inode, struct file *file)
return single_open(file, proc_udc_show, NULL);
}
static struct file_operations proc_ops = {
static const struct file_operations proc_ops = {
.open = proc_udc_open,
.read = seq_read,
.llseek = seq_lseek,
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册