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: (103 commits)
  usbcore: remove unused argument in autosuspend
  USB: keep count of unsuspended children
  USB hub: simplify remote-wakeup handling
  USB: struct usb_device: change flag to bitflag
  OHCI: make autostop conditional on CONFIG_PM
  USB: Add autosuspend support to the hub driver
  EHCI: Fix root-hub and port suspend/resume problems
  USB: create a new thread for every USB device found during the probe sequence
  USB: add driver for the USB debug devices
  USB: added dynamic major number for USB endpoints
  USB: pegasus error path not resetting task's state
  USB: endianness fix for asix.c
  USB: build the appledisplay driver
  USB serial: replace kmalloc+memset with kzalloc
  USB: hid-core: canonical defines for Apple USB device IDs
  USB: idmouse cleanup
  USB: make drivers/usb/core/driver.c:usb_device_match() static
  USB: lh7a40x_udc remove double declaration
  USB: pxa2xx_udc recognizes ixp425 rev b0 chip
  usbtouchscreen: add support for DMC TSC-10/25 devices
  ...
This commit is contained in:
Linus Torvalds 2006-12-01 16:41:58 -08:00
commit 9641219825
98 changed files with 1269 additions and 856 deletions

View file

@ -345,8 +345,7 @@ static inline void skel_delete (struct usb_skel *dev)
usb_buffer_free (dev->udev, dev->bulk_out_size, usb_buffer_free (dev->udev, dev->bulk_out_size,
dev->bulk_out_buffer, dev->bulk_out_buffer,
dev->write_urb->transfer_dma); dev->write_urb->transfer_dma);
if (dev->write_urb != NULL) usb_free_urb (dev->write_urb);
usb_free_urb (dev->write_urb);
kfree (dev); kfree (dev);
} }
</programlisting> </programlisting>

View file

@ -561,8 +561,7 @@ static struct notifier_block usb_pcwd_notifier = {
*/ */
static inline void usb_pcwd_delete (struct usb_pcwd_private *usb_pcwd) static inline void usb_pcwd_delete (struct usb_pcwd_private *usb_pcwd)
{ {
if (usb_pcwd->intr_urb != NULL) usb_free_urb(usb_pcwd->intr_urb);
usb_free_urb (usb_pcwd->intr_urb);
if (usb_pcwd->intr_buffer != NULL) if (usb_pcwd->intr_buffer != NULL)
usb_buffer_free(usb_pcwd->udev, usb_pcwd->intr_size, usb_buffer_free(usb_pcwd->udev, usb_pcwd->intr_size,
usb_pcwd->intr_buffer, usb_pcwd->intr_dma); usb_pcwd->intr_buffer, usb_pcwd->intr_dma);

View file

@ -178,9 +178,9 @@ static int iforce_usb_probe(struct usb_interface *intf,
fail: fail:
if (iforce) { if (iforce) {
if (iforce->irq) usb_free_urb(iforce->irq); usb_free_urb(iforce->irq);
if (iforce->out) usb_free_urb(iforce->out); usb_free_urb(iforce->out);
if (iforce->ctrl) usb_free_urb(iforce->ctrl); usb_free_urb(iforce->ctrl);
kfree(iforce); kfree(iforce);
} }

View file

@ -815,14 +815,11 @@ static int gigaset_probe(struct usb_interface *interface,
return 0; return 0;
error: error:
if (ucs->read_urb) usb_kill_urb(ucs->read_urb);
usb_kill_urb(ucs->read_urb);
kfree(ucs->bulk_out_buffer); kfree(ucs->bulk_out_buffer);
if (ucs->bulk_out_urb != NULL) usb_free_urb(ucs->bulk_out_urb);
usb_free_urb(ucs->bulk_out_urb);
kfree(cs->inbuf[0].rcvbuf); kfree(cs->inbuf[0].rcvbuf);
if (ucs->read_urb != NULL) usb_free_urb(ucs->read_urb);
usb_free_urb(ucs->read_urb);
usb_set_intfdata(interface, NULL); usb_set_intfdata(interface, NULL);
ucs->read_urb = ucs->bulk_out_urb = NULL; ucs->read_urb = ucs->bulk_out_urb = NULL;
cs->inbuf[0].rcvbuf = ucs->bulk_out_buffer = NULL; cs->inbuf[0].rcvbuf = ucs->bulk_out_buffer = NULL;
@ -850,11 +847,9 @@ static void gigaset_disconnect(struct usb_interface *interface)
usb_kill_urb(ucs->bulk_out_urb); /* FIXME: only if active? */ usb_kill_urb(ucs->bulk_out_urb); /* FIXME: only if active? */
kfree(ucs->bulk_out_buffer); kfree(ucs->bulk_out_buffer);
if (ucs->bulk_out_urb != NULL) usb_free_urb(ucs->bulk_out_urb);
usb_free_urb(ucs->bulk_out_urb);
kfree(cs->inbuf[0].rcvbuf); kfree(cs->inbuf[0].rcvbuf);
if (ucs->read_urb != NULL) usb_free_urb(ucs->read_urb);
usb_free_urb(ucs->read_urb);
ucs->read_urb = ucs->bulk_out_urb = NULL; ucs->read_urb = ucs->bulk_out_urb = NULL;
cs->inbuf[0].rcvbuf = ucs->bulk_out_buffer = NULL; cs->inbuf[0].rcvbuf = ucs->bulk_out_buffer = NULL;

View file

@ -275,8 +275,7 @@ static void cinergyt2_free_stream_urbs (struct cinergyt2 *cinergyt2)
int i; int i;
for (i=0; i<STREAM_URB_COUNT; i++) for (i=0; i<STREAM_URB_COUNT; i++)
if (cinergyt2->stream_urb[i]) usb_free_urb(cinergyt2->stream_urb[i]);
usb_free_urb(cinergyt2->stream_urb[i]);
usb_buffer_free(cinergyt2->udev, STREAM_URB_COUNT*STREAM_BUF_SIZE, usb_buffer_free(cinergyt2->udev, STREAM_URB_COUNT*STREAM_BUF_SIZE,
cinergyt2->streambuf, cinergyt2->streambuf_dmahandle); cinergyt2->streambuf, cinergyt2->streambuf_dmahandle);
@ -320,8 +319,7 @@ static void cinergyt2_stop_stream_xfer (struct cinergyt2 *cinergyt2)
cinergyt2_control_stream_transfer(cinergyt2, 0); cinergyt2_control_stream_transfer(cinergyt2, 0);
for (i=0; i<STREAM_URB_COUNT; i++) for (i=0; i<STREAM_URB_COUNT; i++)
if (cinergyt2->stream_urb[i]) usb_kill_urb(cinergyt2->stream_urb[i]);
usb_kill_urb(cinergyt2->stream_urb[i]);
} }
static int cinergyt2_start_stream_xfer (struct cinergyt2 *cinergyt2) static int cinergyt2_start_stream_xfer (struct cinergyt2 *cinergyt2)

View file

@ -1135,8 +1135,7 @@ static void ttusb_dec_free_iso_urbs(struct ttusb_dec *dec)
dprintk("%s\n", __FUNCTION__); dprintk("%s\n", __FUNCTION__);
for (i = 0; i < ISO_BUF_COUNT; i++) for (i = 0; i < ISO_BUF_COUNT; i++)
if (dec->iso_urb[i]) usb_free_urb(dec->iso_urb[i]);
usb_free_urb(dec->iso_urb[i]);
pci_free_consistent(NULL, pci_free_consistent(NULL,
ISO_FRAME_SIZE * (FRAMES_PER_ISO_BUF * ISO_FRAME_SIZE * (FRAMES_PER_ISO_BUF *

View file

@ -1953,8 +1953,8 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
return hdw; return hdw;
fail: fail:
if (hdw) { if (hdw) {
if (hdw->ctl_read_urb) usb_free_urb(hdw->ctl_read_urb); usb_free_urb(hdw->ctl_read_urb);
if (hdw->ctl_write_urb) usb_free_urb(hdw->ctl_write_urb); usb_free_urb(hdw->ctl_write_urb);
if (hdw->ctl_read_buffer) kfree(hdw->ctl_read_buffer); if (hdw->ctl_read_buffer) kfree(hdw->ctl_read_buffer);
if (hdw->ctl_write_buffer) kfree(hdw->ctl_write_buffer); if (hdw->ctl_write_buffer) kfree(hdw->ctl_write_buffer);
if (hdw->controls) kfree(hdw->controls); if (hdw->controls) kfree(hdw->controls);
@ -2575,12 +2575,10 @@ static void pvr2_ctl_timeout(unsigned long data)
struct pvr2_hdw *hdw = (struct pvr2_hdw *)data; struct pvr2_hdw *hdw = (struct pvr2_hdw *)data;
if (hdw->ctl_write_pend_flag || hdw->ctl_read_pend_flag) { if (hdw->ctl_write_pend_flag || hdw->ctl_read_pend_flag) {
hdw->ctl_timeout_flag = !0; hdw->ctl_timeout_flag = !0;
if (hdw->ctl_write_pend_flag && hdw->ctl_write_urb) { if (hdw->ctl_write_pend_flag)
usb_unlink_urb(hdw->ctl_write_urb); usb_unlink_urb(hdw->ctl_write_urb);
} if (hdw->ctl_read_pend_flag)
if (hdw->ctl_read_pend_flag && hdw->ctl_read_urb) {
usb_unlink_urb(hdw->ctl_read_urb); usb_unlink_urb(hdw->ctl_read_urb);
}
} }
} }

View file

@ -289,7 +289,7 @@ static void pvr2_buffer_done(struct pvr2_buffer *bp)
pvr2_buffer_set_none(bp); pvr2_buffer_set_none(bp);
bp->signature = 0; bp->signature = 0;
bp->stream = NULL; bp->stream = NULL;
if (bp->purb) usb_free_urb(bp->purb); usb_free_urb(bp->purb);
pvr2_trace(PVR2_TRACE_BUF_POOL,"/*---TRACE_FLOW---*/" pvr2_trace(PVR2_TRACE_BUF_POOL,"/*---TRACE_FLOW---*/"
" bufferDone %p",bp); " bufferDone %p",bp);
} }

View file

@ -866,11 +866,9 @@ int pwc_isoc_init(struct pwc_device *pdev)
} }
if (ret) { if (ret) {
/* De-allocate in reverse order */ /* De-allocate in reverse order */
while (i >= 0) { while (i--) {
if (pdev->sbuf[i].urb != NULL) usb_free_urb(pdev->sbuf[i].urb);
usb_free_urb(pdev->sbuf[i].urb);
pdev->sbuf[i].urb = NULL; pdev->sbuf[i].urb = NULL;
i--;
} }
return ret; return ret;
} }

View file

@ -775,7 +775,7 @@ static int sn9c102_start_transfer(struct sn9c102_device* cam)
return 0; return 0;
free_urbs: free_urbs:
for (i = 0; (i < SN9C102_URBS) && cam->urb[i]; i++) for (i = 0; i < SN9C102_URBS; i++)
usb_free_urb(cam->urb[i]); usb_free_urb(cam->urb[i]);
free_buffers: free_buffers:

View file

@ -190,8 +190,7 @@ static int qcm_alloc_int_urb(struct qcm *cam)
static void qcm_free_int(struct qcm *cam) static void qcm_free_int(struct qcm *cam)
{ {
if (cam->button_urb) usb_free_urb(cam->button_urb);
usb_free_urb(cam->button_urb);
} }
#endif /* CONFIG_INPUT */ #endif /* CONFIG_INPUT */

View file

@ -489,7 +489,7 @@ static int zc0301_start_transfer(struct zc0301_device* cam)
return 0; return 0;
free_urbs: free_urbs:
for (i = 0; (i < ZC0301_URBS) && cam->urb[i]; i++) for (i = 0; i < ZC0301_URBS; i++)
usb_free_urb(cam->urb[i]); usb_free_urb(cam->urb[i]);
free_buffers: free_buffers:

View file

@ -1793,10 +1793,8 @@ err_out_3:
err_out_2: err_out_2:
usb_free_urb(self->tx_urb); usb_free_urb(self->tx_urb);
err_out_1: err_out_1:
for (i = 0; i < self->max_rx_urb; i++) { for (i = 0; i < self->max_rx_urb; i++)
if (self->rx_urb[i]) usb_free_urb(self->rx_urb[i]);
usb_free_urb(self->rx_urb[i]);
}
free_netdev(net); free_netdev(net);
err_out: err_out:
return ret; return ret;

View file

@ -1828,10 +1828,8 @@ err_start:
/* Leave the device in reset state */ /* Leave the device in reset state */
zd1201_docmd(zd, ZD1201_CMDCODE_INIT, 0, 0, 0); zd1201_docmd(zd, ZD1201_CMDCODE_INIT, 0, 0, 0);
err_zd: err_zd:
if (zd->tx_urb) usb_free_urb(zd->tx_urb);
usb_free_urb(zd->tx_urb); usb_free_urb(zd->rx_urb);
if (zd->rx_urb)
usb_free_urb(zd->rx_urb);
kfree(zd); kfree(zd);
return err; return err;
} }

View file

@ -834,8 +834,8 @@ static int speedtch_bind(struct usbatm_data *usbatm,
const struct usb_endpoint_descriptor *endpoint_desc = &desc->endpoint[i].desc; const struct usb_endpoint_descriptor *endpoint_desc = &desc->endpoint[i].desc;
if ((endpoint_desc->bEndpointAddress == target_address)) { if ((endpoint_desc->bEndpointAddress == target_address)) {
use_isoc = (endpoint_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == use_isoc =
USB_ENDPOINT_XFER_ISOC; usb_endpoint_xfer_isoc(endpoint_desc);
break; break;
} }
} }

View file

@ -401,9 +401,8 @@ static int uea_send_modem_cmd(struct usb_device *usb,
int ret = -ENOMEM; int ret = -ENOMEM;
u8 *xfer_buff; u8 *xfer_buff;
xfer_buff = kmalloc(size, GFP_KERNEL); xfer_buff = kmemdup(buff, size, GFP_KERNEL);
if (xfer_buff) { if (xfer_buff) {
memcpy(xfer_buff, buff, size);
ret = usb_control_msg(usb, ret = usb_control_msg(usb,
usb_sndctrlpipe(usb, 0), usb_sndctrlpipe(usb, 0),
LOAD_INTERNAL, LOAD_INTERNAL,
@ -595,14 +594,12 @@ static int uea_idma_write(struct uea_softc *sc, void *data, u32 size)
u8 *xfer_buff; u8 *xfer_buff;
int bytes_read; int bytes_read;
xfer_buff = kmalloc(size, GFP_KERNEL); xfer_buff = kmemdup(data, size, GFP_KERNEL);
if (!xfer_buff) { if (!xfer_buff) {
uea_err(INS_TO_USBDEV(sc), "can't allocate xfer_buff\n"); uea_err(INS_TO_USBDEV(sc), "can't allocate xfer_buff\n");
return ret; return ret;
} }
memcpy(xfer_buff, data, size);
ret = usb_bulk_msg(sc->usb_dev, ret = usb_bulk_msg(sc->usb_dev,
usb_sndbulkpipe(sc->usb_dev, UEA_IDMA_PIPE), usb_sndbulkpipe(sc->usb_dev, UEA_IDMA_PIPE),
xfer_buff, size, &bytes_read, BULK_TIMEOUT); xfer_buff, size, &bytes_read, BULK_TIMEOUT);
@ -765,12 +762,11 @@ static int uea_request(struct uea_softc *sc,
u8 *xfer_buff; u8 *xfer_buff;
int ret = -ENOMEM; int ret = -ENOMEM;
xfer_buff = kmalloc(size, GFP_KERNEL); xfer_buff = kmemdup(data, size, GFP_KERNEL);
if (!xfer_buff) { if (!xfer_buff) {
uea_err(INS_TO_USBDEV(sc), "can't allocate xfer_buff\n"); uea_err(INS_TO_USBDEV(sc), "can't allocate xfer_buff\n");
return ret; return ret;
} }
memcpy(xfer_buff, data, size);
ret = usb_control_msg(sc->usb_dev, usb_sndctrlpipe(sc->usb_dev, 0), ret = usb_control_msg(sc->usb_dev, usb_sndctrlpipe(sc->usb_dev, 0),
UCDC_SEND_ENCAPSULATED_COMMAND, UCDC_SEND_ENCAPSULATED_COMMAND,

View file

@ -892,7 +892,7 @@ skip_normal_probe:
/* workaround for switched endpoints */ /* workaround for switched endpoints */
if ((epread->bEndpointAddress & USB_DIR_IN) != USB_DIR_IN) { if (!usb_endpoint_dir_in(epread)) {
/* descriptors are swapped */ /* descriptors are swapped */
struct usb_endpoint_descriptor *t; struct usb_endpoint_descriptor *t;
dev_dbg(&intf->dev,"The data interface has switched endpoints"); dev_dbg(&intf->dev,"The data interface has switched endpoints");

View file

@ -72,6 +72,21 @@ config USB_SUSPEND
If you are unsure about this, say N here. If you are unsure about this, say N here.
config USB_MULTITHREAD_PROBE
bool "USB Multi-threaded probe (EXPERIMENTAL)"
depends on USB && EXPERIMENTAL
default n
help
Say Y here if you want the USB core to spawn a new thread for
every USB device that is probed. This can cause a small speedup
in boot times on systems with a lot of different USB devices.
This option should be safe to enable, but if any odd probing
problems are found, please disable it, or dynamically turn it
off in the /sys/module/usbcore/parameters/multithread_probe
file
When in doubt, say N.
config USB_OTG config USB_OTG
bool bool

View file

@ -175,12 +175,13 @@ static char *usb_dump_endpoint_descriptor (
) )
{ {
char dir, unit, *type; char dir, unit, *type;
unsigned interval, in, bandwidth = 1; unsigned interval, bandwidth = 1;
if (start > end) if (start > end)
return start; return start;
in = (desc->bEndpointAddress & USB_DIR_IN);
dir = in ? 'I' : 'O'; dir = usb_endpoint_dir_in(desc) ? 'I' : 'O';
if (speed == USB_SPEED_HIGH) { if (speed == USB_SPEED_HIGH) {
switch (le16_to_cpu(desc->wMaxPacketSize) & (0x03 << 11)) { switch (le16_to_cpu(desc->wMaxPacketSize) & (0x03 << 11)) {
case 1 << 11: bandwidth = 2; break; case 1 << 11: bandwidth = 2; break;
@ -204,7 +205,7 @@ static char *usb_dump_endpoint_descriptor (
break; break;
case USB_ENDPOINT_XFER_BULK: case USB_ENDPOINT_XFER_BULK:
type = "Bulk"; type = "Bulk";
if (speed == USB_SPEED_HIGH && !in) /* uframes per NAK */ if (speed == USB_SPEED_HIGH && dir == 'O') /* uframes per NAK */
interval = desc->bInterval; interval = desc->bInterval;
else else
interval = 0; interval = 0;

View file

@ -561,7 +561,7 @@ static int usbdev_open(struct inode *inode, struct file *file)
dev = inode->i_private; dev = inode->i_private;
if (!dev) if (!dev)
goto out; goto out;
ret = usb_autoresume_device(dev, 1); ret = usb_autoresume_device(dev);
if (ret) if (ret)
goto out; goto out;
@ -609,7 +609,7 @@ static int usbdev_release(struct inode *inode, struct file *file)
releaseintf(ps, ifnum); releaseintf(ps, ifnum);
} }
destroy_all_async(ps); destroy_all_async(ps);
usb_autosuspend_device(dev, 1); usb_autosuspend_device(dev);
usb_unlock_device(dev); usb_unlock_device(dev);
usb_put_dev(dev); usb_put_dev(dev);
put_pid(ps->disc_pid); put_pid(ps->disc_pid);

View file

@ -205,7 +205,7 @@ static int usb_probe_interface(struct device *dev)
if (id) { if (id) {
dev_dbg(dev, "%s - got id\n", __FUNCTION__); dev_dbg(dev, "%s - got id\n", __FUNCTION__);
error = usb_autoresume_device(udev, 1); error = usb_autoresume_device(udev);
if (error) if (error)
return error; return error;
@ -229,7 +229,7 @@ static int usb_probe_interface(struct device *dev)
} else } else
intf->condition = USB_INTERFACE_BOUND; intf->condition = USB_INTERFACE_BOUND;
usb_autosuspend_device(udev, 1); usb_autosuspend_device(udev);
} }
return error; return error;
@ -247,7 +247,7 @@ static int usb_unbind_interface(struct device *dev)
/* Autoresume for set_interface call below */ /* Autoresume for set_interface call below */
udev = interface_to_usbdev(intf); udev = interface_to_usbdev(intf);
error = usb_autoresume_device(udev, 1); error = usb_autoresume_device(udev);
/* release all urbs for this interface */ /* release all urbs for this interface */
usb_disable_interface(interface_to_usbdev(intf), intf); usb_disable_interface(interface_to_usbdev(intf), intf);
@ -265,7 +265,7 @@ static int usb_unbind_interface(struct device *dev)
intf->needs_remote_wakeup = 0; intf->needs_remote_wakeup = 0;
if (!error) if (!error)
usb_autosuspend_device(udev, 1); usb_autosuspend_device(udev);
return 0; return 0;
} }
@ -408,6 +408,16 @@ static int usb_match_one_id(struct usb_interface *interface,
(id->bDeviceProtocol != dev->descriptor.bDeviceProtocol)) (id->bDeviceProtocol != dev->descriptor.bDeviceProtocol))
return 0; return 0;
/* The interface class, subclass, and protocol should never be
* checked for a match if the device class is Vendor Specific,
* unless the match record specifies the Vendor ID. */
if (dev->descriptor.bDeviceClass == USB_CLASS_VENDOR_SPEC &&
!(id->match_flags & USB_DEVICE_ID_MATCH_VENDOR) &&
(id->match_flags & (USB_DEVICE_ID_MATCH_INT_CLASS |
USB_DEVICE_ID_MATCH_INT_SUBCLASS |
USB_DEVICE_ID_MATCH_INT_PROTOCOL)))
return 0;
if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_CLASS) && if ((id->match_flags & USB_DEVICE_ID_MATCH_INT_CLASS) &&
(id->bInterfaceClass != intf->desc.bInterfaceClass)) (id->bInterfaceClass != intf->desc.bInterfaceClass))
return 0; return 0;
@ -476,7 +486,17 @@ static int usb_match_one_id(struct usb_interface *interface,
* most general; they let drivers bind to any interface on a * most general; they let drivers bind to any interface on a
* multiple-function device. Use the USB_INTERFACE_INFO * multiple-function device. Use the USB_INTERFACE_INFO
* macro, or its siblings, to match class-per-interface style * macro, or its siblings, to match class-per-interface style
* devices (as recorded in bDeviceClass). * devices (as recorded in bInterfaceClass).
*
* Note that an entry created by USB_INTERFACE_INFO won't match
* any interface if the device class is set to Vendor-Specific.
* This is deliberate; according to the USB spec the meanings of
* the interface class/subclass/protocol for these devices are also
* vendor-specific, and hence matching against a standard product
* class wouldn't work anyway. If you really want to use an
* interface-based match for such a device, create a match record
* that also specifies the vendor ID. (Unforunately there isn't a
* standard macro for creating records like this.)
* *
* Within those groups, remember that not all combinations are * Within those groups, remember that not all combinations are
* meaningful. For example, don't give a product version range * meaningful. For example, don't give a product version range
@ -505,7 +525,7 @@ const struct usb_device_id *usb_match_id(struct usb_interface *interface,
} }
EXPORT_SYMBOL_GPL_FUTURE(usb_match_id); EXPORT_SYMBOL_GPL_FUTURE(usb_match_id);
int usb_device_match(struct device *dev, struct device_driver *drv) static int usb_device_match(struct device *dev, struct device_driver *drv)
{ {
/* devices and interfaces are handled separately */ /* devices and interfaces are handled separately */
if (is_usb_device(dev)) { if (is_usb_device(dev)) {
@ -790,7 +810,7 @@ EXPORT_SYMBOL_GPL_FUTURE(usb_deregister);
#ifdef CONFIG_PM #ifdef CONFIG_PM
/* Caller has locked udev's pm_mutex */ /* Caller has locked udev's pm_mutex */
static int suspend_device(struct usb_device *udev, pm_message_t msg) static int usb_suspend_device(struct usb_device *udev, pm_message_t msg)
{ {
struct usb_device_driver *udriver; struct usb_device_driver *udriver;
int status = 0; int status = 0;
@ -817,7 +837,7 @@ done:
} }
/* Caller has locked udev's pm_mutex */ /* Caller has locked udev's pm_mutex */
static int resume_device(struct usb_device *udev) static int usb_resume_device(struct usb_device *udev)
{ {
struct usb_device_driver *udriver; struct usb_device_driver *udriver;
int status = 0; int status = 0;
@ -843,7 +863,7 @@ done:
} }
/* Caller has locked intf's usb_device's pm mutex */ /* Caller has locked intf's usb_device's pm mutex */
static int suspend_interface(struct usb_interface *intf, pm_message_t msg) static int usb_suspend_interface(struct usb_interface *intf, pm_message_t msg)
{ {
struct usb_driver *driver; struct usb_driver *driver;
int status = 0; int status = 0;
@ -880,7 +900,7 @@ done:
} }
/* Caller has locked intf's usb_device's pm_mutex */ /* Caller has locked intf's usb_device's pm_mutex */
static int resume_interface(struct usb_interface *intf) static int usb_resume_interface(struct usb_interface *intf)
{ {
struct usb_driver *driver; struct usb_driver *driver;
int status = 0; int status = 0;
@ -920,6 +940,44 @@ done:
return status; return status;
} }
#ifdef CONFIG_USB_SUSPEND
/* Internal routine to check whether we may autosuspend a device. */
static int autosuspend_check(struct usb_device *udev)
{
int i;
struct usb_interface *intf;
/* For autosuspend, fail fast if anything is in use.
* Also fail if any interfaces require remote wakeup but it
* isn't available. */
udev->do_remote_wakeup = device_may_wakeup(&udev->dev);
if (udev->pm_usage_cnt > 0)
return -EBUSY;
if (udev->actconfig) {
for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
intf = udev->actconfig->interface[i];
if (!is_active(intf))
continue;
if (intf->pm_usage_cnt > 0)
return -EBUSY;
if (intf->needs_remote_wakeup &&
!udev->do_remote_wakeup) {
dev_dbg(&udev->dev, "remote wakeup needed "
"for autosuspend\n");
return -EOPNOTSUPP;
}
}
}
return 0;
}
#else
#define autosuspend_check(udev) 0
#endif
/** /**
* usb_suspend_both - suspend a USB device and its interfaces * usb_suspend_both - suspend a USB device and its interfaces
* @udev: the usb_device to suspend * @udev: the usb_device to suspend
@ -971,52 +1029,34 @@ int usb_suspend_both(struct usb_device *udev, pm_message_t msg)
udev->do_remote_wakeup = device_may_wakeup(&udev->dev); udev->do_remote_wakeup = device_may_wakeup(&udev->dev);
/* For autosuspend, fail fast if anything is in use.
* Also fail if any interfaces require remote wakeup but it
* isn't available. */
if (udev->auto_pm) { if (udev->auto_pm) {
if (udev->pm_usage_cnt > 0) status = autosuspend_check(udev);
return -EBUSY; if (status < 0)
if (udev->actconfig) { return status;
for (; i < udev->actconfig->desc.bNumInterfaces; i++) {
intf = udev->actconfig->interface[i];
if (!is_active(intf))
continue;
if (intf->pm_usage_cnt > 0)
return -EBUSY;
if (intf->needs_remote_wakeup &&
!udev->do_remote_wakeup) {
dev_dbg(&udev->dev,
"remote wakeup needed for autosuspend\n");
return -EOPNOTSUPP;
}
}
i = 0;
}
} }
/* Suspend all the interfaces and then udev itself */ /* Suspend all the interfaces and then udev itself */
if (udev->actconfig) { if (udev->actconfig) {
for (; i < udev->actconfig->desc.bNumInterfaces; i++) { for (; i < udev->actconfig->desc.bNumInterfaces; i++) {
intf = udev->actconfig->interface[i]; intf = udev->actconfig->interface[i];
status = suspend_interface(intf, msg); status = usb_suspend_interface(intf, msg);
if (status != 0) if (status != 0)
break; break;
} }
} }
if (status == 0) if (status == 0)
status = suspend_device(udev, msg); status = usb_suspend_device(udev, msg);
/* If the suspend failed, resume interfaces that did get suspended */ /* If the suspend failed, resume interfaces that did get suspended */
if (status != 0) { if (status != 0) {
while (--i >= 0) { while (--i >= 0) {
intf = udev->actconfig->interface[i]; intf = udev->actconfig->interface[i];
resume_interface(intf); usb_resume_interface(intf);
} }
/* If the suspend succeeded, propagate it up the tree */ /* If the suspend succeeded, propagate it up the tree */
} else if (parent) } else if (parent)
usb_autosuspend_device(parent, 0); usb_autosuspend_device(parent);
// dev_dbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status); // dev_dbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status);
return status; return status;
@ -1064,9 +1104,25 @@ int usb_resume_both(struct usb_device *udev)
/* Propagate the resume up the tree, if necessary */ /* Propagate the resume up the tree, if necessary */
if (udev->state == USB_STATE_SUSPENDED) { if (udev->state == USB_STATE_SUSPENDED) {
if (parent) { if (parent) {
usb_pm_lock(parent); status = usb_autoresume_device(parent);
parent->auto_pm = 1; if (status == 0) {
status = usb_resume_both(parent); status = usb_resume_device(udev);
if (status) {
usb_autosuspend_device(parent);
/* It's possible usb_resume_device()
* failed after the port was
* unsuspended, causing udev to be
* logically disconnected. We don't
* want usb_disconnect() to autosuspend
* the parent again, so tell it that
* udev disconnected while still
* suspended. */
if (udev->state ==
USB_STATE_NOTATTACHED)
udev->discon_suspended = 1;
}
}
} else { } else {
/* We can't progagate beyond the USB subsystem, /* We can't progagate beyond the USB subsystem,
@ -1075,24 +1131,20 @@ int usb_resume_both(struct usb_device *udev)
if (udev->dev.parent->power.power_state.event != if (udev->dev.parent->power.power_state.event !=
PM_EVENT_ON) PM_EVENT_ON)
status = -EHOSTUNREACH; status = -EHOSTUNREACH;
} else
if (status == 0) status = usb_resume_device(udev);
status = resume_device(udev); }
if (parent)
usb_pm_unlock(parent);
} else { } else {
/* Needed only for setting udev->dev.power.power_state.event /* Needed only for setting udev->dev.power.power_state.event
* and for possible debugging message. */ * and for possible debugging message. */
status = resume_device(udev); status = usb_resume_device(udev);
} }
/* Now the parent won't suspend until we are finished */
if (status == 0 && udev->actconfig) { if (status == 0 && udev->actconfig) {
for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) { for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {
intf = udev->actconfig->interface[i]; intf = udev->actconfig->interface[i];
resume_interface(intf); usb_resume_interface(intf);
} }
} }
@ -1102,39 +1154,53 @@ int usb_resume_both(struct usb_device *udev)
#ifdef CONFIG_USB_SUSPEND #ifdef CONFIG_USB_SUSPEND
/* Internal routine to adjust a device's usage counter and change
* its autosuspend state.
*/
static int usb_autopm_do_device(struct usb_device *udev, int inc_usage_cnt)
{
int status = 0;
usb_pm_lock(udev);
udev->pm_usage_cnt += inc_usage_cnt;
WARN_ON(udev->pm_usage_cnt < 0);
if (inc_usage_cnt >= 0 && udev->pm_usage_cnt > 0) {
udev->auto_pm = 1;
status = usb_resume_both(udev);
if (status != 0)
udev->pm_usage_cnt -= inc_usage_cnt;
} else if (inc_usage_cnt <= 0 && autosuspend_check(udev) == 0)
queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend,
USB_AUTOSUSPEND_DELAY);
usb_pm_unlock(udev);
return status;
}
/** /**
* usb_autosuspend_device - delayed autosuspend of a USB device and its interfaces * usb_autosuspend_device - delayed autosuspend of a USB device and its interfaces
* @udev: the usb_device to autosuspend * @udev: the usb_device to autosuspend
* @dec_usage_cnt: flag to decrement @udev's PM-usage counter
* *
* This routine should be called when a core subsystem is finished using * This routine should be called when a core subsystem is finished using
* @udev and wants to allow it to autosuspend. Examples would be when * @udev and wants to allow it to autosuspend. Examples would be when
* @udev's device file in usbfs is closed or after a configuration change. * @udev's device file in usbfs is closed or after a configuration change.
* *
* @dec_usage_cnt should be 1 if the subsystem previously incremented * @udev's usage counter is decremented. If it or any of the usage counters
* @udev's usage counter (such as by passing 1 to usb_autoresume_device); * for an active interface is greater than 0, no autosuspend request will be
* otherwise it should be 0. * queued. (If an interface driver does not support autosuspend then its
* * usage counter is permanently positive.) Furthermore, if an interface
* If the usage counter for @udev or any of its active interfaces is greater * driver requires remote-wakeup capability during autosuspend but remote
* than 0, the autosuspend request will not be queued. (If an interface * wakeup is disabled, the autosuspend will fail.
* driver does not support autosuspend then its usage counter is permanently
* positive.) Likewise, if an interface driver requires remote-wakeup
* capability during autosuspend but remote wakeup is disabled, the
* autosuspend will fail.
* *
* Often the caller will hold @udev's device lock, but this is not * Often the caller will hold @udev's device lock, but this is not
* necessary. * necessary.
* *
* This routine can run only in process context. * This routine can run only in process context.
*/ */
void usb_autosuspend_device(struct usb_device *udev, int dec_usage_cnt) void usb_autosuspend_device(struct usb_device *udev)
{ {
usb_pm_lock(udev); int status;
udev->pm_usage_cnt -= dec_usage_cnt;
if (udev->pm_usage_cnt <= 0) status = usb_autopm_do_device(udev, -1);
queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend,
USB_AUTOSUSPEND_DELAY);
usb_pm_unlock(udev);
// dev_dbg(&udev->dev, "%s: cnt %d\n", // dev_dbg(&udev->dev, "%s: cnt %d\n",
// __FUNCTION__, udev->pm_usage_cnt); // __FUNCTION__, udev->pm_usage_cnt);
} }
@ -1142,44 +1208,59 @@ void usb_autosuspend_device(struct usb_device *udev, int dec_usage_cnt)
/** /**
* usb_autoresume_device - immediately autoresume a USB device and its interfaces * usb_autoresume_device - immediately autoresume a USB device and its interfaces
* @udev: the usb_device to autoresume * @udev: the usb_device to autoresume
* @inc_usage_cnt: flag to increment @udev's PM-usage counter
* *
* This routine should be called when a core subsystem wants to use @udev * This routine should be called when a core subsystem wants to use @udev
* and needs to guarantee that it is not suspended. In addition, the * and needs to guarantee that it is not suspended. No autosuspend will
* caller can prevent @udev from being autosuspended subsequently. (Note * occur until usb_autosuspend_device is called. (Note that this will not
* that this will not prevent suspend events originating in the PM core.) * prevent suspend events originating in the PM core.) Examples would be
* Examples would be when @udev's device file in usbfs is opened (autosuspend * when @udev's device file in usbfs is opened or when a remote-wakeup
* should be prevented until the file is closed) or when a remote-wakeup * request is received.
* request is received (later autosuspends should not be prevented).
* *
* @inc_usage_cnt should be 1 to increment @udev's usage counter and prevent * @udev's usage counter is incremented to prevent subsequent autosuspends.
* autosuspends. This prevention will persist until the usage counter is * However if the autoresume fails then the usage counter is re-decremented.
* decremented again (such as by passing 1 to usb_autosuspend_device).
* Otherwise @inc_usage_cnt should be 0 to leave the usage counter unchanged.
* Regardless, if the autoresume fails then the usage counter is not
* incremented.
* *
* Often the caller will hold @udev's device lock, but this is not * Often the caller will hold @udev's device lock, but this is not
* necessary (and attempting it might cause deadlock). * necessary (and attempting it might cause deadlock).
* *
* This routine can run only in process context. * This routine can run only in process context.
*/ */
int usb_autoresume_device(struct usb_device *udev, int inc_usage_cnt) int usb_autoresume_device(struct usb_device *udev)
{ {
int status; int status;
usb_pm_lock(udev); status = usb_autopm_do_device(udev, 1);
udev->pm_usage_cnt += inc_usage_cnt;
udev->auto_pm = 1;
status = usb_resume_both(udev);
if (status != 0)
udev->pm_usage_cnt -= inc_usage_cnt;
usb_pm_unlock(udev);
// dev_dbg(&udev->dev, "%s: status %d cnt %d\n", // dev_dbg(&udev->dev, "%s: status %d cnt %d\n",
// __FUNCTION__, status, udev->pm_usage_cnt); // __FUNCTION__, status, udev->pm_usage_cnt);
return status; return status;
} }
/* Internal routine to adjust an interface's usage counter and change
* its device's autosuspend state.
*/
static int usb_autopm_do_interface(struct usb_interface *intf,
int inc_usage_cnt)
{
struct usb_device *udev = interface_to_usbdev(intf);
int status = 0;
usb_pm_lock(udev);
if (intf->condition == USB_INTERFACE_UNBOUND)
status = -ENODEV;
else {
intf->pm_usage_cnt += inc_usage_cnt;
if (inc_usage_cnt >= 0 && intf->pm_usage_cnt > 0) {
udev->auto_pm = 1;
status = usb_resume_both(udev);
if (status != 0)
intf->pm_usage_cnt -= inc_usage_cnt;
} else if (inc_usage_cnt <= 0 && autosuspend_check(udev) == 0)
queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend,
USB_AUTOSUSPEND_DELAY);
}
usb_pm_unlock(udev);
return status;
}
/** /**
* usb_autopm_put_interface - decrement a USB interface's PM-usage counter * usb_autopm_put_interface - decrement a USB interface's PM-usage counter
* @intf: the usb_interface whose counter should be decremented * @intf: the usb_interface whose counter should be decremented
@ -1213,17 +1294,11 @@ int usb_autoresume_device(struct usb_device *udev, int inc_usage_cnt)
*/ */
void usb_autopm_put_interface(struct usb_interface *intf) void usb_autopm_put_interface(struct usb_interface *intf)
{ {
struct usb_device *udev = interface_to_usbdev(intf); int status;
usb_pm_lock(udev); status = usb_autopm_do_interface(intf, -1);
if (intf->condition != USB_INTERFACE_UNBOUND && // dev_dbg(&intf->dev, "%s: status %d cnt %d\n",
--intf->pm_usage_cnt <= 0) { // __FUNCTION__, status, intf->pm_usage_cnt);
queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend,
USB_AUTOSUSPEND_DELAY);
}
usb_pm_unlock(udev);
// dev_dbg(&intf->dev, "%s: cnt %d\n",
// __FUNCTION__, intf->pm_usage_cnt);
} }
EXPORT_SYMBOL_GPL(usb_autopm_put_interface); EXPORT_SYMBOL_GPL(usb_autopm_put_interface);
@ -1260,26 +1335,37 @@ EXPORT_SYMBOL_GPL(usb_autopm_put_interface);
*/ */
int usb_autopm_get_interface(struct usb_interface *intf) int usb_autopm_get_interface(struct usb_interface *intf)
{ {
struct usb_device *udev = interface_to_usbdev(intf); int status;
int status;
usb_pm_lock(udev); status = usb_autopm_do_interface(intf, 1);
if (intf->condition == USB_INTERFACE_UNBOUND)
status = -ENODEV;
else {
++intf->pm_usage_cnt;
udev->auto_pm = 1;
status = usb_resume_both(udev);
if (status != 0)
--intf->pm_usage_cnt;
}
usb_pm_unlock(udev);
// dev_dbg(&intf->dev, "%s: status %d cnt %d\n", // dev_dbg(&intf->dev, "%s: status %d cnt %d\n",
// __FUNCTION__, status, intf->pm_usage_cnt); // __FUNCTION__, status, intf->pm_usage_cnt);
return status; return status;
} }
EXPORT_SYMBOL_GPL(usb_autopm_get_interface); EXPORT_SYMBOL_GPL(usb_autopm_get_interface);
/**
* usb_autopm_set_interface - set a USB interface's autosuspend state
* @intf: the usb_interface whose state should be set
*
* This routine sets the autosuspend state of @intf's device according
* to @intf's usage counter, which the caller must have set previously.
* If the counter is <= 0, the device is autosuspended (if it isn't
* already suspended and if nothing else prevents the autosuspend). If
* the counter is > 0, the device is autoresumed (if it isn't already
* awake).
*/
int usb_autopm_set_interface(struct usb_interface *intf)
{
int status;
status = usb_autopm_do_interface(intf, 0);
// dev_dbg(&intf->dev, "%s: status %d cnt %d\n",
// __FUNCTION__, status, intf->pm_usage_cnt);
return status;
}
EXPORT_SYMBOL_GPL(usb_autopm_set_interface);
#endif /* CONFIG_USB_SUSPEND */ #endif /* CONFIG_USB_SUSPEND */
static int usb_suspend(struct device *dev, pm_message_t message) static int usb_suspend(struct device *dev, pm_message_t message)

View file

@ -10,15 +10,20 @@
*/ */
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/spinlock.h>
#include <linux/idr.h>
#include <linux/usb.h> #include <linux/usb.h>
#include "usb.h" #include "usb.h"
/* endpoint stuff */ #define MAX_ENDPOINT_MINORS (64*128*32)
static int usb_endpoint_major;
static DEFINE_IDR(endpoint_idr);
struct ep_device { struct ep_device {
struct usb_endpoint_descriptor *desc; struct usb_endpoint_descriptor *desc;
struct usb_device *udev; struct usb_device *udev;
struct device dev; struct device dev;
int minor;
}; };
#define to_ep_device(_dev) \ #define to_ep_device(_dev) \
container_of(_dev, struct ep_device, dev) container_of(_dev, struct ep_device, dev)
@ -152,6 +157,55 @@ static struct attribute_group ep_dev_attr_grp = {
.attrs = ep_dev_attrs, .attrs = ep_dev_attrs,
}; };
static int usb_endpoint_major_init(void)
{
dev_t dev;
int error;
error = alloc_chrdev_region(&dev, 0, MAX_ENDPOINT_MINORS,
"usb_endpoint");
if (error) {
err("unable to get a dynamic major for usb endpoints");
return error;
}
usb_endpoint_major = MAJOR(dev);
return error;
}
static void usb_endpoint_major_cleanup(void)
{
unregister_chrdev_region(MKDEV(usb_endpoint_major, 0),
MAX_ENDPOINT_MINORS);
}
static int endpoint_get_minor(struct ep_device *ep_dev)
{
static DEFINE_MUTEX(minor_lock);
int retval = -ENOMEM;
int id;
mutex_lock(&minor_lock);
if (idr_pre_get(&endpoint_idr, GFP_KERNEL) == 0)
goto exit;
retval = idr_get_new(&endpoint_idr, ep_dev, &id);
if (retval < 0) {
if (retval == -EAGAIN)
retval = -ENOMEM;
goto exit;
}
ep_dev->minor = id & MAX_ID_MASK;
exit:
mutex_unlock(&minor_lock);
return retval;
}
static void endpoint_free_minor(struct ep_device *ep_dev)
{
idr_remove(&endpoint_idr, ep_dev->minor);
}
static struct endpoint_class { static struct endpoint_class {
struct kref kref; struct kref kref;
struct class *class; struct class *class;
@ -176,11 +230,20 @@ static int init_endpoint_class(void)
ep_class->class = class_create(THIS_MODULE, "usb_endpoint"); ep_class->class = class_create(THIS_MODULE, "usb_endpoint");
if (IS_ERR(ep_class->class)) { if (IS_ERR(ep_class->class)) {
result = IS_ERR(ep_class->class); result = IS_ERR(ep_class->class);
kfree(ep_class); goto class_create_error;
ep_class = NULL;
goto exit;
} }
result = usb_endpoint_major_init();
if (result)
goto endpoint_major_error;
goto exit;
endpoint_major_error:
class_destroy(ep_class->class);
class_create_error:
kfree(ep_class);
ep_class = NULL;
exit: exit:
return result; return result;
} }
@ -191,6 +254,7 @@ static void release_endpoint_class(struct kref *kref)
class_destroy(ep_class->class); class_destroy(ep_class->class);
kfree(ep_class); kfree(ep_class);
ep_class = NULL; ep_class = NULL;
usb_endpoint_major_cleanup();
} }
static void destroy_endpoint_class(void) static void destroy_endpoint_class(void)
@ -213,7 +277,6 @@ int usb_create_ep_files(struct device *parent,
{ {
char name[8]; char name[8];
struct ep_device *ep_dev; struct ep_device *ep_dev;
int minor;
int retval; int retval;
retval = init_endpoint_class(); retval = init_endpoint_class();
@ -226,12 +289,16 @@ int usb_create_ep_files(struct device *parent,
goto error_alloc; goto error_alloc;
} }
/* fun calculation to determine the minor of this endpoint */ retval = endpoint_get_minor(ep_dev);
minor = (((udev->bus->busnum - 1) * 128) * 16) + (udev->devnum - 1); if (retval) {
dev_err(parent, "can not allocate minor number for %s",
ep_dev->dev.bus_id);
goto error_register;
}
ep_dev->desc = &endpoint->desc; ep_dev->desc = &endpoint->desc;
ep_dev->udev = udev; ep_dev->udev = udev;
ep_dev->dev.devt = MKDEV(442, minor); // FIXME fake number... ep_dev->dev.devt = MKDEV(usb_endpoint_major, ep_dev->minor);
ep_dev->dev.class = ep_class->class; ep_dev->dev.class = ep_class->class;
ep_dev->dev.parent = parent; ep_dev->dev.parent = parent;
ep_dev->dev.release = ep_device_release; ep_dev->dev.release = ep_device_release;
@ -241,7 +308,7 @@ int usb_create_ep_files(struct device *parent,
retval = device_register(&ep_dev->dev); retval = device_register(&ep_dev->dev);
if (retval) if (retval)
goto error_register; goto error_chrdev;
retval = 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) if (retval)
goto error_group; goto error_group;
@ -261,6 +328,9 @@ error_group:
destroy_endpoint_class(); destroy_endpoint_class();
return retval; return retval;
error_chrdev:
endpoint_free_minor(ep_dev);
error_register: error_register:
kfree(ep_dev); kfree(ep_dev);
error_alloc: error_alloc:
@ -271,14 +341,16 @@ exit:
void usb_remove_ep_files(struct usb_host_endpoint *endpoint) void usb_remove_ep_files(struct usb_host_endpoint *endpoint)
{ {
struct ep_device *ep_dev = endpoint->ep_dev;
if (endpoint->ep_dev) { if (ep_dev) {
char name[8]; char name[8];
sprintf(name, "ep_%02x", endpoint->desc.bEndpointAddress); sprintf(name, "ep_%02x", endpoint->desc.bEndpointAddress);
sysfs_remove_link(&endpoint->ep_dev->dev.parent->kobj, name); sysfs_remove_link(&ep_dev->dev.parent->kobj, name);
sysfs_remove_group(&endpoint->ep_dev->dev.kobj, &ep_dev_attr_grp); sysfs_remove_group(&ep_dev->dev.kobj, &ep_dev_attr_grp);
device_unregister(&endpoint->ep_dev->dev); endpoint_free_minor(ep_dev);
device_unregister(&ep_dev->dev);
endpoint->ep_dev = NULL; endpoint->ep_dev = NULL;
destroy_endpoint_class(); destroy_endpoint_class();
} }

View file

@ -256,7 +256,9 @@ static const u8 hs_rh_config_descriptor [] = {
0x05, /* __u8 ep_bDescriptorType; Endpoint */ 0x05, /* __u8 ep_bDescriptorType; Endpoint */
0x81, /* __u8 ep_bEndpointAddress; IN Endpoint 1 */ 0x81, /* __u8 ep_bEndpointAddress; IN Endpoint 1 */
0x03, /* __u8 ep_bmAttributes; Interrupt */ 0x03, /* __u8 ep_bmAttributes; Interrupt */
0x02, 0x00, /* __le16 ep_wMaxPacketSize; 1 + (MAX_ROOT_PORTS / 8) */ /* __le16 ep_wMaxPacketSize; 1 + (MAX_ROOT_PORTS / 8)
* see hub.c:hub_configure() for details. */
(USB_MAXCHILDREN + 1 + 7) / 8, 0x00,
0x0c /* __u8 ep_bInterval; (256ms -- usb 2.0 spec) */ 0x0c /* __u8 ep_bInterval; (256ms -- usb 2.0 spec) */
}; };

View file

@ -31,6 +31,47 @@
#include "hcd.h" #include "hcd.h"
#include "hub.h" #include "hub.h"
struct usb_hub {
struct device *intfdev; /* the "interface" device */
struct usb_device *hdev;
struct urb *urb; /* for interrupt polling pipe */
/* buffer for urb ... with extra space in case of babble */
char (*buffer)[8];
dma_addr_t buffer_dma; /* DMA address for buffer */
union {
struct usb_hub_status hub;
struct usb_port_status port;
} *status; /* buffer for status reports */
int error; /* last reported error */
int nerrors; /* track consecutive errors */
struct list_head event_list; /* hubs w/data or errs ready */
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 or
resumed */
#if USB_MAXCHILDREN > 31 /* 8*sizeof(unsigned long) - 1 */
#error event_bits[] is too short!
#endif
struct usb_hub_descriptor *descriptor; /* class descriptor */
struct usb_tt tt; /* Transaction Translator */
unsigned mA_per_port; /* current for each child */
unsigned limited_power:1;
unsigned quiescing:1;
unsigned activating:1;
unsigned has_indicators:1;
u8 indicator[USB_MAXCHILDREN];
struct work_struct leds;
};
/* Protect struct usb_device->state and ->children members /* Protect struct usb_device->state and ->children members
* Note: Both are also protected by ->dev.sem, except that ->state can * Note: Both are also protected by ->dev.sem, except that ->state can
* change to USB_STATE_NOTATTACHED even when the semaphore isn't held. */ * change to USB_STATE_NOTATTACHED even when the semaphore isn't held. */
@ -45,6 +86,16 @@ static DECLARE_WAIT_QUEUE_HEAD(khubd_wait);
static struct task_struct *khubd_task; static struct task_struct *khubd_task;
/* multithreaded probe logic */
static int multithread_probe =
#ifdef CONFIG_USB_MULTITHREAD_PROBE
1;
#else
0;
#endif
module_param(multithread_probe, bool, S_IRUGO);
MODULE_PARM_DESC(multithread_probe, "Run each USB device probe in a new thread");
/* cycle leds on hubs that aren't blinking for attention */ /* cycle leds on hubs that aren't blinking for attention */
static int blinkenlights = 0; static int blinkenlights = 0;
module_param (blinkenlights, bool, S_IRUGO); module_param (blinkenlights, bool, S_IRUGO);
@ -276,6 +327,9 @@ static void kick_khubd(struct usb_hub *hub)
{ {
unsigned long flags; unsigned long flags;
/* Suppress autosuspend until khubd runs */
to_usb_interface(hub->intfdev)->pm_usage_cnt = 1;
spin_lock_irqsave(&hub_event_lock, flags); spin_lock_irqsave(&hub_event_lock, flags);
if (list_empty(&hub->event_list)) { if (list_empty(&hub->event_list)) {
list_add_tail(&hub->event_list, &hub_event_list); list_add_tail(&hub->event_list, &hub_event_list);
@ -457,7 +511,6 @@ static void hub_quiesce(struct usb_hub *hub)
/* (nonblocking) khubd and related activity won't re-trigger */ /* (nonblocking) khubd and related activity won't re-trigger */
hub->quiescing = 1; hub->quiescing = 1;
hub->activating = 0; hub->activating = 0;
hub->resume_root_hub = 0;
/* (blocking) stop khubd and related activity */ /* (blocking) stop khubd and related activity */
usb_kill_urb(hub->urb); usb_kill_urb(hub->urb);
@ -473,7 +526,7 @@ static void hub_activate(struct usb_hub *hub)
hub->quiescing = 0; hub->quiescing = 0;
hub->activating = 1; hub->activating = 1;
hub->resume_root_hub = 0;
status = usb_submit_urb(hub->urb, GFP_NOIO); status = usb_submit_urb(hub->urb, GFP_NOIO);
if (status < 0) if (status < 0)
dev_err(hub->intfdev, "activate --> %d\n", status); dev_err(hub->intfdev, "activate --> %d\n", status);
@ -759,7 +812,12 @@ static int hub_configure(struct usb_hub *hub,
dev_dbg(hub_dev, "%sover-current condition exists\n", dev_dbg(hub_dev, "%sover-current condition exists\n",
(hubstatus & HUB_STATUS_OVERCURRENT) ? "" : "no "); (hubstatus & HUB_STATUS_OVERCURRENT) ? "" : "no ");
/* set up the interrupt endpoint */ /* set up the interrupt endpoint
* We use the EP's maxpacket size instead of (PORTS+1+7)/8
* bytes as USB2.0[11.12.3] says because some hubs are known
* to send more data (and thus cause overflow). For root hubs,
* maxpktsize is defined in hcd.c's fake endpoint descriptors
* to be big enough for at least USB_MAXCHILDREN ports. */
pipe = usb_rcvintpipe(hdev, endpoint->bEndpointAddress); pipe = usb_rcvintpipe(hdev, endpoint->bEndpointAddress);
maxp = usb_maxpacket(hdev, pipe, usb_pipeout(pipe)); maxp = usb_maxpacket(hdev, pipe, usb_pipeout(pipe));
@ -883,6 +941,7 @@ descriptor_error:
INIT_WORK(&hub->leds, led_work, hub); INIT_WORK(&hub->leds, led_work, hub);
usb_set_intfdata (intf, hub); usb_set_intfdata (intf, hub);
intf->needs_remote_wakeup = 1;
if (hdev->speed == USB_SPEED_HIGH) if (hdev->speed == USB_SPEED_HIGH)
highspeed_hubs++; highspeed_hubs++;
@ -980,6 +1039,8 @@ static void recursively_mark_NOTATTACHED(struct usb_device *udev)
if (udev->children[i]) if (udev->children[i])
recursively_mark_NOTATTACHED(udev->children[i]); recursively_mark_NOTATTACHED(udev->children[i]);
} }
if (udev->state == USB_STATE_SUSPENDED)
udev->discon_suspended = 1;
udev->state = USB_STATE_NOTATTACHED; udev->state = USB_STATE_NOTATTACHED;
} }
@ -1169,6 +1230,14 @@ void usb_disconnect(struct usb_device **pdev)
*pdev = NULL; *pdev = NULL;
spin_unlock_irq(&device_state_lock); spin_unlock_irq(&device_state_lock);
/* Decrement the parent's count of unsuspended children */
if (udev->parent) {
usb_pm_lock(udev);
if (!udev->discon_suspended)
usb_autosuspend_device(udev->parent);
usb_pm_unlock(udev);
}
put_device(&udev->dev); put_device(&udev->dev);
} }
@ -1191,29 +1260,17 @@ static inline void show_string(struct usb_device *udev, char *id, char *string)
static int __usb_port_suspend(struct usb_device *, int port1); static int __usb_port_suspend(struct usb_device *, int port1);
#endif #endif
/** static int __usb_new_device(void *void_data)
* usb_new_device - perform initial device setup (usbcore-internal)
* @udev: newly addressed device (in ADDRESS state)
*
* This is called with devices which have been enumerated, but not yet
* configured. The device descriptor is available, but not descriptors
* for any device configuration. The caller must have locked either
* the parent hub (if udev is a normal device) or else the
* usb_bus_list_lock (if udev is a root hub). The parent's pointer to
* udev has already been installed, but udev is not yet visible through
* sysfs or other filesystem code.
*
* Returns 0 for success (device is configured and listed, with its
* interfaces, in sysfs); else a negative errno value.
*
* This call is synchronous, and may not be used in an interrupt context.
*
* Only the hub driver or root-hub registrar should ever call this.
*/
int usb_new_device(struct usb_device *udev)
{ {
struct usb_device *udev = void_data;
int err; int err;
/* Lock ourself into memory in order to keep a probe sequence
* sleeping in a new thread from allowing us to be unloaded.
*/
if (!try_module_get(THIS_MODULE))
return -EINVAL;
err = usb_get_configuration(udev); err = usb_get_configuration(udev);
if (err < 0) { if (err < 0) {
dev_err(&udev->dev, "can't read configurations, error %d\n", dev_err(&udev->dev, "can't read configurations, error %d\n",
@ -1309,13 +1366,56 @@ int usb_new_device(struct usb_device *udev)
goto fail; goto fail;
} }
return 0; /* Increment the parent's count of unsuspended children */
if (udev->parent)
usb_autoresume_device(udev->parent);
exit:
module_put(THIS_MODULE);
return err;
fail: fail:
usb_set_device_state(udev, USB_STATE_NOTATTACHED); usb_set_device_state(udev, USB_STATE_NOTATTACHED);
return err; goto exit;
} }
/**
* usb_new_device - perform initial device setup (usbcore-internal)
* @udev: newly addressed device (in ADDRESS state)
*
* This is called with devices which have been enumerated, but not yet
* configured. The device descriptor is available, but not descriptors
* for any device configuration. The caller must have locked either
* the parent hub (if udev is a normal device) or else the
* usb_bus_list_lock (if udev is a root hub). The parent's pointer to
* udev has already been installed, but udev is not yet visible through
* sysfs or other filesystem code.
*
* The return value for this function depends on if the
* multithread_probe variable is set or not. If it's set, it will
* return a if the probe thread was successfully created or not. If the
* variable is not set, it will return if the device is configured
* properly or not. interfaces, in sysfs); else a negative errno value.
*
* This call is synchronous, and may not be used in an interrupt context.
*
* Only the hub driver or root-hub registrar should ever call this.
*/
int usb_new_device(struct usb_device *udev)
{
struct task_struct *probe_task;
int ret = 0;
if (multithread_probe) {
probe_task = kthread_run(__usb_new_device, udev,
"usb-probe-%s", udev->devnum);
if (IS_ERR(probe_task))
ret = PTR_ERR(probe_task);
} else
ret = __usb_new_device(udev);
return ret;
}
static int hub_port_status(struct usb_hub *hub, int port1, static int hub_port_status(struct usb_hub *hub, int port1,
u16 *status, u16 *change) u16 *status, u16 *change)
@ -1323,10 +1423,12 @@ static int hub_port_status(struct usb_hub *hub, int port1,
int ret; int ret;
ret = get_port_status(hub->hdev, port1, &hub->status->port); ret = get_port_status(hub->hdev, port1, &hub->status->port);
if (ret < 0) if (ret < 4) {
dev_err (hub->intfdev, dev_err (hub->intfdev,
"%s failed (err = %d)\n", __FUNCTION__, ret); "%s failed (err = %d)\n", __FUNCTION__, ret);
else { if (ret >= 0)
ret = -EIO;
} else {
*status = le16_to_cpu(hub->status->port.wPortStatus); *status = le16_to_cpu(hub->status->port.wPortStatus);
*change = le16_to_cpu(hub->status->port.wPortChange); *change = le16_to_cpu(hub->status->port.wPortChange);
ret = 0; ret = 0;
@ -1674,6 +1776,12 @@ static int
hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev) hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev)
{ {
int status; int status;
u16 portchange, portstatus;
/* Skip the initial Clear-Suspend step for a remote wakeup */
status = hub_port_status(hub, port1, &portstatus, &portchange);
if (status == 0 && !(portstatus & USB_PORT_STAT_SUSPEND))
goto SuspendCleared;
// dev_dbg(hub->intfdev, "resume port %d\n", port1); // dev_dbg(hub->intfdev, "resume port %d\n", port1);
@ -1687,9 +1795,6 @@ hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev)
"can't resume port %d, status %d\n", "can't resume port %d, status %d\n",
port1, status); port1, status);
} else { } else {
u16 devstatus;
u16 portchange;
/* drive resume for at least 20 msec */ /* drive resume for at least 20 msec */
if (udev) if (udev)
dev_dbg(&udev->dev, "usb %sresume\n", dev_dbg(&udev->dev, "usb %sresume\n",
@ -1704,16 +1809,15 @@ hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev)
* stop resume signaling. Then finish the resume * stop resume signaling. Then finish the resume
* sequence. * sequence.
*/ */
devstatus = portchange = 0; status = hub_port_status(hub, port1, &portstatus, &portchange);
status = hub_port_status(hub, port1, SuspendCleared:
&devstatus, &portchange);
if (status < 0 if (status < 0
|| (devstatus & LIVE_FLAGS) != LIVE_FLAGS || (portstatus & LIVE_FLAGS) != LIVE_FLAGS
|| (devstatus & USB_PORT_STAT_SUSPEND) != 0 || (portstatus & USB_PORT_STAT_SUSPEND) != 0
) { ) {
dev_dbg(hub->intfdev, dev_dbg(hub->intfdev,
"port %d status %04x.%04x after resume, %d\n", "port %d status %04x.%04x after resume, %d\n",
port1, portchange, devstatus, status); port1, portchange, portstatus, status);
if (status >= 0) if (status >= 0)
status = -ENODEV; status = -ENODEV;
} else { } else {
@ -1774,23 +1878,16 @@ static int remote_wakeup(struct usb_device *udev)
{ {
int status = 0; int status = 0;
/* All this just to avoid sending a port-resume message
* to the parent hub! */
usb_lock_device(udev); usb_lock_device(udev);
usb_pm_lock(udev);
if (udev->state == USB_STATE_SUSPENDED) { if (udev->state == USB_STATE_SUSPENDED) {
dev_dbg(&udev->dev, "usb %sresume\n", "wakeup-"); dev_dbg(&udev->dev, "usb %sresume\n", "wakeup-");
/* TRSMRCY = 10 msec */ status = usb_autoresume_device(udev);
msleep(10);
status = finish_port_resume(udev);
if (status == 0)
udev->dev.power.power_state.event = PM_EVENT_ON;
}
usb_pm_unlock(udev);
if (status == 0) /* Give the interface drivers a chance to do something,
usb_autoresume_device(udev, 0); * then autosuspend the device again. */
if (status == 0)
usb_autosuspend_device(udev);
}
usb_unlock_device(udev); usb_unlock_device(udev);
return status; return status;
} }
@ -1854,6 +1951,8 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
} }
} }
dev_dbg(&intf->dev, "%s\n", __FUNCTION__);
/* "global suspend" of the downstream HC-to-USB interface */ /* "global suspend" of the downstream HC-to-USB interface */
if (!hdev->parent) { if (!hdev->parent) {
struct usb_bus *bus = hdev->bus; struct usb_bus *bus = hdev->bus;
@ -1876,10 +1975,12 @@ static int hub_suspend(struct usb_interface *intf, pm_message_t msg)
static int hub_resume(struct usb_interface *intf) static int hub_resume(struct usb_interface *intf)
{ {
struct usb_device *hdev = interface_to_usbdev(intf);
struct usb_hub *hub = usb_get_intfdata (intf); struct usb_hub *hub = usb_get_intfdata (intf);
struct usb_device *hdev = hub->hdev;
int status; int status;
dev_dbg(&intf->dev, "%s\n", __FUNCTION__);
/* "global resume" of the downstream HC-to-USB interface */ /* "global resume" of the downstream HC-to-USB interface */
if (!hdev->parent) { if (!hdev->parent) {
struct usb_bus *bus = hdev->bus; struct usb_bus *bus = hdev->bus;
@ -1918,7 +2019,6 @@ void usb_resume_root_hub(struct usb_device *hdev)
{ {
struct usb_hub *hub = hdev_to_hub(hdev); struct usb_hub *hub = hdev_to_hub(hdev);
hub->resume_root_hub = 1;
kick_khubd(hub); kick_khubd(hub);
} }
@ -2555,16 +2655,13 @@ static void hub_events(void)
intf = to_usb_interface(hub->intfdev); intf = to_usb_interface(hub->intfdev);
hub_dev = &intf->dev; hub_dev = &intf->dev;
i = hub->resume_root_hub; dev_dbg(hub_dev, "state %d ports %d chg %04x evt %04x\n",
dev_dbg(hub_dev, "state %d ports %d chg %04x evt %04x%s\n",
hdev->state, hub->descriptor hdev->state, hub->descriptor
? hub->descriptor->bNbrPorts ? hub->descriptor->bNbrPorts
: 0, : 0,
/* NOTE: expects max 15 ports... */ /* NOTE: expects max 15 ports... */
(u16) hub->change_bits[0], (u16) hub->change_bits[0],
(u16) hub->event_bits[0], (u16) hub->event_bits[0]);
i ? ", resume root" : "");
usb_get_intf(intf); usb_get_intf(intf);
spin_unlock_irq(&hub_event_lock); spin_unlock_irq(&hub_event_lock);
@ -2585,16 +2682,16 @@ static void hub_events(void)
goto loop; goto loop;
} }
/* Is this is a root hub wanting to reactivate the downstream /* Autoresume */
* ports? If so, be sure the interface resumes even if its ret = usb_autopm_get_interface(intf);
* stub "device" node was never suspended. if (ret) {
*/ dev_dbg(hub_dev, "Can't autoresume: %d\n", ret);
if (i)
usb_autoresume_device(hdev, 0);
/* If this is an inactive or suspended hub, do nothing */
if (hub->quiescing)
goto loop; goto loop;
}
/* If this is an inactive hub, do nothing */
if (hub->quiescing)
goto loop_autopm;
if (hub->error) { if (hub->error) {
dev_dbg (hub_dev, "resetting for error %d\n", dev_dbg (hub_dev, "resetting for error %d\n",
@ -2604,7 +2701,7 @@ static void hub_events(void)
if (ret) { if (ret) {
dev_dbg (hub_dev, dev_dbg (hub_dev,
"error resetting hub: %d\n", ret); "error resetting hub: %d\n", ret);
goto loop; goto loop_autopm;
} }
hub->nerrors = 0; hub->nerrors = 0;
@ -2732,6 +2829,10 @@ static void hub_events(void)
if (!hdev->parent && !hub->busy_bits[0]) if (!hdev->parent && !hub->busy_bits[0])
usb_enable_root_hub_irq(hdev->bus); usb_enable_root_hub_irq(hdev->bus);
loop_autopm:
/* Allow autosuspend if we're not going to run again */
if (list_empty(&hub->event_list))
usb_autopm_enable(intf);
loop: loop:
usb_unlock_device(hdev); usb_unlock_device(hdev);
usb_put_intf(intf); usb_put_intf(intf);
@ -2773,6 +2874,7 @@ static struct usb_driver hub_driver = {
.post_reset = hub_post_reset, .post_reset = hub_post_reset,
.ioctl = hub_ioctl, .ioctl = hub_ioctl,
.id_table = hub_id_table, .id_table = hub_id_table,
.supports_autosuspend = 1,
}; };
int usb_hub_init(void) int usb_hub_init(void)
@ -2997,7 +3099,7 @@ int usb_reset_composite_device(struct usb_device *udev,
} }
/* Prevent autosuspend during the reset */ /* Prevent autosuspend during the reset */
usb_autoresume_device(udev, 1); usb_autoresume_device(udev);
if (iface && iface->condition != USB_INTERFACE_BINDING) if (iface && iface->condition != USB_INTERFACE_BINDING)
iface = NULL; iface = NULL;
@ -3040,7 +3142,7 @@ int usb_reset_composite_device(struct usb_device *udev,
} }
} }
usb_autosuspend_device(udev, 1); usb_autosuspend_device(udev);
return ret; return ret;
} }
EXPORT_SYMBOL(usb_reset_composite_device); EXPORT_SYMBOL(usb_reset_composite_device);

View file

@ -192,45 +192,4 @@ struct usb_tt_clear {
extern void usb_hub_tt_clear_buffer (struct usb_device *dev, int pipe); extern void usb_hub_tt_clear_buffer (struct usb_device *dev, int pipe);
struct usb_hub {
struct device *intfdev; /* the "interface" device */
struct usb_device *hdev;
struct urb *urb; /* for interrupt polling pipe */
/* buffer for urb ... with extra space in case of babble */
char (*buffer)[8];
dma_addr_t buffer_dma; /* DMA address for buffer */
union {
struct usb_hub_status hub;
struct usb_port_status port;
} *status; /* buffer for status reports */
int error; /* last reported error */
int nerrors; /* track consecutive errors */
struct list_head event_list; /* hubs w/data or errs ready */
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 or
resumed */
#if USB_MAXCHILDREN > 31 /* 8*sizeof(unsigned long) - 1 */
#error event_bits[] is too short!
#endif
struct usb_hub_descriptor *descriptor; /* class descriptor */
struct usb_tt tt; /* Transaction Translator */
unsigned mA_per_port; /* current for each child */
unsigned limited_power:1;
unsigned quiescing:1;
unsigned activating:1;
unsigned resume_root_hub:1;
unsigned has_indicators:1;
enum hub_led_mode indicator[USB_MAXCHILDREN];
struct work_struct leds;
};
#endif /* __LINUX_HUB_H */ #endif /* __LINUX_HUB_H */

View file

@ -764,7 +764,7 @@ int usb_string(struct usb_device *dev, int index, char *buf, size_t size)
err = -EINVAL; err = -EINVAL;
goto errout; goto errout;
} else { } else {
dev->have_langid = -1; dev->have_langid = 1;
dev->string_langid = tbuf[2] | (tbuf[3]<< 8); dev->string_langid = tbuf[2] | (tbuf[3]<< 8);
/* always use the first langid listed */ /* always use the first langid listed */
dev_dbg (&dev->dev, "default language 0x%04x\n", dev_dbg (&dev->dev, "default language 0x%04x\n",
@ -1398,7 +1398,7 @@ free_interfaces:
} }
/* Wake up the device so we can send it the Set-Config request */ /* Wake up the device so we can send it the Set-Config request */
ret = usb_autoresume_device(dev, 1); ret = usb_autoresume_device(dev);
if (ret) if (ret)
goto free_interfaces; goto free_interfaces;
@ -1421,7 +1421,7 @@ free_interfaces:
dev->actconfig = cp; dev->actconfig = cp;
if (!cp) { if (!cp) {
usb_set_device_state(dev, USB_STATE_ADDRESS); usb_set_device_state(dev, USB_STATE_ADDRESS);
usb_autosuspend_device(dev, 1); usb_autosuspend_device(dev);
goto free_interfaces; goto free_interfaces;
} }
usb_set_device_state(dev, USB_STATE_CONFIGURED); usb_set_device_state(dev, USB_STATE_CONFIGURED);
@ -1490,7 +1490,7 @@ free_interfaces:
usb_create_sysfs_intf_files (intf); usb_create_sysfs_intf_files (intf);
} }
usb_autosuspend_device(dev, 1); usb_autosuspend_device(dev);
return 0; return 0;
} }

View file

@ -200,13 +200,6 @@ static void ksuspend_usb_cleanup(void)
destroy_workqueue(ksuspend_usb_wq); destroy_workqueue(ksuspend_usb_wq);
} }
#else
#define ksuspend_usb_init() 0
#define ksuspend_usb_cleanup() do {} while (0)
#endif
#ifdef CONFIG_USB_SUSPEND #ifdef CONFIG_USB_SUSPEND
/* usb_autosuspend_work - callback routine to autosuspend a USB device */ /* usb_autosuspend_work - callback routine to autosuspend a USB device */
@ -225,7 +218,14 @@ static void usb_autosuspend_work(void *_udev)
static void usb_autosuspend_work(void *_udev) static void usb_autosuspend_work(void *_udev)
{} {}
#endif #endif /* CONFIG_USB_SUSPEND */
#else
#define ksuspend_usb_init() 0
#define ksuspend_usb_cleanup() do {} while (0)
#endif /* CONFIG_PM */
/** /**
* usb_alloc_dev - usb device constructor (usbcore-internal) * usb_alloc_dev - usb device constructor (usbcore-internal)
@ -537,138 +537,6 @@ int usb_get_current_frame_number(struct usb_device *dev)
return usb_hcd_get_frame_number (dev); return usb_hcd_get_frame_number (dev);
} }
/**
* usb_endpoint_dir_in - check if the endpoint has IN direction
* @epd: endpoint to be checked
*
* Returns true if the endpoint is of type IN, otherwise it returns false.
*/
int usb_endpoint_dir_in(const struct usb_endpoint_descriptor *epd)
{
return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN);
}
/**
* usb_endpoint_dir_out - check if the endpoint has OUT direction
* @epd: endpoint to be checked
*
* Returns true if the endpoint is of type OUT, otherwise it returns false.
*/
int usb_endpoint_dir_out(const struct usb_endpoint_descriptor *epd)
{
return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT);
}
/**
* usb_endpoint_xfer_bulk - check if the endpoint has bulk transfer type
* @epd: endpoint to be checked
*
* Returns true if the endpoint is of type bulk, otherwise it returns false.
*/
int usb_endpoint_xfer_bulk(const struct usb_endpoint_descriptor *epd)
{
return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
USB_ENDPOINT_XFER_BULK);
}
/**
* usb_endpoint_xfer_int - check if the endpoint has interrupt transfer type
* @epd: endpoint to be checked
*
* Returns true if the endpoint is of type interrupt, otherwise it returns
* false.
*/
int usb_endpoint_xfer_int(const struct usb_endpoint_descriptor *epd)
{
return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
USB_ENDPOINT_XFER_INT);
}
/**
* usb_endpoint_xfer_isoc - check if the endpoint has isochronous transfer type
* @epd: endpoint to be checked
*
* Returns true if the endpoint is of type isochronous, otherwise it returns
* false.
*/
int usb_endpoint_xfer_isoc(const struct usb_endpoint_descriptor *epd)
{
return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
USB_ENDPOINT_XFER_ISOC);
}
/**
* usb_endpoint_is_bulk_in - check if the endpoint is bulk IN
* @epd: endpoint to be checked
*
* Returns true if the endpoint has bulk transfer type and IN direction,
* otherwise it returns false.
*/
int usb_endpoint_is_bulk_in(const struct usb_endpoint_descriptor *epd)
{
return (usb_endpoint_xfer_bulk(epd) && usb_endpoint_dir_in(epd));
}
/**
* usb_endpoint_is_bulk_out - check if the endpoint is bulk OUT
* @epd: endpoint to be checked
*
* Returns true if the endpoint has bulk transfer type and OUT direction,
* otherwise it returns false.
*/
int usb_endpoint_is_bulk_out(const struct usb_endpoint_descriptor *epd)
{
return (usb_endpoint_xfer_bulk(epd) && usb_endpoint_dir_out(epd));
}
/**
* usb_endpoint_is_int_in - check if the endpoint is interrupt IN
* @epd: endpoint to be checked
*
* Returns true if the endpoint has interrupt transfer type and IN direction,
* otherwise it returns false.
*/
int usb_endpoint_is_int_in(const struct usb_endpoint_descriptor *epd)
{
return (usb_endpoint_xfer_int(epd) && usb_endpoint_dir_in(epd));
}
/**
* usb_endpoint_is_int_out - check if the endpoint is interrupt OUT
* @epd: endpoint to be checked
*
* Returns true if the endpoint has interrupt transfer type and OUT direction,
* otherwise it returns false.
*/
int usb_endpoint_is_int_out(const struct usb_endpoint_descriptor *epd)
{
return (usb_endpoint_xfer_int(epd) && usb_endpoint_dir_out(epd));
}
/**
* usb_endpoint_is_isoc_in - check if the endpoint is isochronous IN
* @epd: endpoint to be checked
*
* Returns true if the endpoint has isochronous transfer type and IN direction,
* otherwise it returns false.
*/
int usb_endpoint_is_isoc_in(const struct usb_endpoint_descriptor *epd)
{
return (usb_endpoint_xfer_isoc(epd) && usb_endpoint_dir_in(epd));
}
/**
* usb_endpoint_is_isoc_out - check if the endpoint is isochronous OUT
* @epd: endpoint to be checked
*
* Returns true if the endpoint has isochronous transfer type and OUT direction,
* otherwise it returns false.
*/
int usb_endpoint_is_isoc_out(const struct usb_endpoint_descriptor *epd)
{
return (usb_endpoint_xfer_isoc(epd) && usb_endpoint_dir_out(epd));
}
/*-------------------------------------------------------------------*/ /*-------------------------------------------------------------------*/
/* /*
* __usb_get_extra_descriptor() finds a descriptor of specific type in the * __usb_get_extra_descriptor() finds a descriptor of specific type in the
@ -1102,18 +970,6 @@ EXPORT_SYMBOL(__usb_get_extra_descriptor);
EXPORT_SYMBOL(usb_find_device); EXPORT_SYMBOL(usb_find_device);
EXPORT_SYMBOL(usb_get_current_frame_number); EXPORT_SYMBOL(usb_get_current_frame_number);
EXPORT_SYMBOL_GPL(usb_endpoint_dir_in);
EXPORT_SYMBOL_GPL(usb_endpoint_dir_out);
EXPORT_SYMBOL_GPL(usb_endpoint_xfer_bulk);
EXPORT_SYMBOL_GPL(usb_endpoint_xfer_int);
EXPORT_SYMBOL_GPL(usb_endpoint_xfer_isoc);
EXPORT_SYMBOL_GPL(usb_endpoint_is_bulk_in);
EXPORT_SYMBOL_GPL(usb_endpoint_is_bulk_out);
EXPORT_SYMBOL_GPL(usb_endpoint_is_int_in);
EXPORT_SYMBOL_GPL(usb_endpoint_is_int_out);
EXPORT_SYMBOL_GPL(usb_endpoint_is_isoc_in);
EXPORT_SYMBOL_GPL(usb_endpoint_is_isoc_out);
EXPORT_SYMBOL (usb_buffer_alloc); EXPORT_SYMBOL (usb_buffer_alloc);
EXPORT_SYMBOL (usb_buffer_free); EXPORT_SYMBOL (usb_buffer_free);

View file

@ -64,14 +64,13 @@ static inline void usb_pm_unlock(struct usb_device *udev) {}
#define USB_AUTOSUSPEND_DELAY (HZ*2) #define USB_AUTOSUSPEND_DELAY (HZ*2)
extern void usb_autosuspend_device(struct usb_device *udev, int dec_busy_cnt); extern void usb_autosuspend_device(struct usb_device *udev);
extern int usb_autoresume_device(struct usb_device *udev, int inc_busy_cnt); extern int usb_autoresume_device(struct usb_device *udev);
#else #else
#define usb_autosuspend_device(udev, dec_busy_cnt) do {} while (0) #define usb_autosuspend_device(udev) do {} while (0)
static inline int usb_autoresume_device(struct usb_device *udev, static inline int usb_autoresume_device(struct usb_device *udev)
int inc_busy_cnt)
{ {
return 0; return 0;
} }

View file

@ -1894,13 +1894,13 @@ static int eth_start_xmit (struct sk_buff *skb, struct net_device *net)
if (!eth_is_promisc (dev)) { if (!eth_is_promisc (dev)) {
u8 *dest = skb->data; u8 *dest = skb->data;
if (dest [0] & 0x01) { if (is_multicast_ether_addr(dest)) {
u16 type; u16 type;
/* ignores USB_CDC_PACKET_TYPE_MULTICAST and host /* ignores USB_CDC_PACKET_TYPE_MULTICAST and host
* SET_ETHERNET_MULTICAST_FILTERS requests * SET_ETHERNET_MULTICAST_FILTERS requests
*/ */
if (memcmp (dest, net->broadcast, ETH_ALEN) == 0) if (is_broadcast_ether_addr(dest))
type = USB_CDC_PACKET_TYPE_BROADCAST; type = USB_CDC_PACKET_TYPE_BROADCAST;
else else
type = USB_CDC_PACKET_TYPE_ALL_MULTICAST; type = USB_CDC_PACKET_TYPE_ALL_MULTICAST;

View file

@ -83,7 +83,6 @@ static int lh7a40x_queue(struct usb_ep *ep, struct usb_request *, gfp_t);
static int lh7a40x_dequeue(struct usb_ep *ep, struct usb_request *); static int lh7a40x_dequeue(struct usb_ep *ep, struct usb_request *);
static int lh7a40x_set_halt(struct usb_ep *ep, int); static int lh7a40x_set_halt(struct usb_ep *ep, int);
static int lh7a40x_fifo_status(struct usb_ep *ep); static int lh7a40x_fifo_status(struct usb_ep *ep);
static int lh7a40x_fifo_status(struct usb_ep *ep);
static void lh7a40x_fifo_flush(struct usb_ep *ep); static void lh7a40x_fifo_flush(struct usb_ep *ep);
static void lh7a40x_ep0_kick(struct lh7a40x_udc *dev, struct lh7a40x_ep *ep); static void lh7a40x_ep0_kick(struct lh7a40x_udc *dev, struct lh7a40x_ep *ep);
static void lh7a40x_handle_ep0(struct lh7a40x_udc *dev, u32 intr); static void lh7a40x_handle_ep0(struct lh7a40x_udc *dev, u32 intr);

View file

@ -1040,6 +1040,7 @@ net2280_queue (struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
} /* else the irq handler advances the queue. */ } /* else the irq handler advances the queue. */
ep->responded = 1;
if (req) if (req)
list_add_tail (&req->queue, &ep->queue); list_add_tail (&req->queue, &ep->queue);
done: done:
@ -2188,7 +2189,8 @@ static void handle_ep_small (struct net2280_ep *ep)
ep->stopped = 1; ep->stopped = 1;
set_halt (ep); set_halt (ep);
mode = 2; mode = 2;
} else if (!req && !ep->stopped) } else if (ep->responded &&
!req && !ep->stopped)
write_fifo (ep, NULL); write_fifo (ep, NULL);
} }
} else { } else {
@ -2203,7 +2205,7 @@ static void handle_ep_small (struct net2280_ep *ep)
} else if (((t & (1 << DATA_OUT_PING_TOKEN_INTERRUPT)) } else if (((t & (1 << DATA_OUT_PING_TOKEN_INTERRUPT))
&& req && req
&& req->req.actual == req->req.length) && req->req.actual == req->req.length)
|| !req) { || (ep->responded && !req)) {
ep->dev->protocol_stall = 1; ep->dev->protocol_stall = 1;
set_halt (ep); set_halt (ep);
ep->stopped = 1; ep->stopped = 1;
@ -2469,6 +2471,7 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat)
/* we made the hardware handle most lowlevel requests; /* we made the hardware handle most lowlevel requests;
* everything else goes uplevel to the gadget code. * everything else goes uplevel to the gadget code.
*/ */
ep->responded = 1;
switch (u.r.bRequest) { switch (u.r.bRequest) {
case USB_REQ_GET_STATUS: { case USB_REQ_GET_STATUS: {
struct net2280_ep *e; struct net2280_ep *e;
@ -2537,6 +2540,7 @@ delegate:
u.r.bRequestType, u.r.bRequest, u.r.bRequestType, u.r.bRequest,
w_value, w_index, w_length, w_value, w_index, w_length,
readl (&ep->regs->ep_cfg)); readl (&ep->regs->ep_cfg));
ep->responded = 0;
spin_unlock (&dev->lock); spin_unlock (&dev->lock);
tmp = dev->driver->setup (&dev->gadget, &u.r); tmp = dev->driver->setup (&dev->gadget, &u.r);
spin_lock (&dev->lock); spin_lock (&dev->lock);

View file

@ -110,7 +110,8 @@ struct net2280_ep {
out_overflow : 1, out_overflow : 1,
stopped : 1, stopped : 1,
is_in : 1, is_in : 1,
is_iso : 1; is_iso : 1,
responded : 1;
}; };
static inline void allow_status (struct net2280_ep *ep) static inline void allow_status (struct net2280_ep *ep)

View file

@ -2472,6 +2472,7 @@ static struct pxa2xx_udc memory = {
#define PXA210_B1 0x00000123 #define PXA210_B1 0x00000123
#define PXA210_B0 0x00000122 #define PXA210_B0 0x00000122
#define IXP425_A0 0x000001c1 #define IXP425_A0 0x000001c1
#define IXP425_B0 0x000001f1
#define IXP465_AD 0x00000200 #define IXP465_AD 0x00000200
/* /*
@ -2509,6 +2510,7 @@ static int __init pxa2xx_udc_probe(struct platform_device *pdev)
break; break;
#elif defined(CONFIG_ARCH_IXP4XX) #elif defined(CONFIG_ARCH_IXP4XX)
case IXP425_A0: case IXP425_A0:
case IXP425_B0:
case IXP465_AD: case IXP465_AD:
dev->has_cfr = 1; dev->has_cfr = 1;
out_dma = 0; out_dma = 0;

View file

@ -126,6 +126,11 @@ static unsigned park = 0;
module_param (park, uint, S_IRUGO); module_param (park, uint, S_IRUGO);
MODULE_PARM_DESC (park, "park setting; 1-3 back-to-back async packets"); MODULE_PARM_DESC (park, "park setting; 1-3 back-to-back async packets");
/* for flakey hardware, ignore overcurrent indicators */
static int ignore_oc = 0;
module_param (ignore_oc, bool, S_IRUGO);
MODULE_PARM_DESC (ignore_oc, "ignore bogus hardware overcurrent indications");
#define INTR_MASK (STS_IAA | STS_FATAL | STS_PCD | STS_ERR | STS_INT) #define INTR_MASK (STS_IAA | STS_FATAL | STS_PCD | STS_ERR | STS_INT)
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
@ -541,9 +546,10 @@ static int ehci_run (struct usb_hcd *hcd)
temp = HC_VERSION(readl (&ehci->caps->hc_capbase)); temp = HC_VERSION(readl (&ehci->caps->hc_capbase));
ehci_info (ehci, ehci_info (ehci,
"USB %x.%x started, EHCI %x.%02x, driver %s\n", "USB %x.%x started, EHCI %x.%02x, driver %s%s\n",
((ehci->sbrn & 0xf0)>>4), (ehci->sbrn & 0x0f), ((ehci->sbrn & 0xf0)>>4), (ehci->sbrn & 0x0f),
temp >> 8, temp & 0xff, DRIVER_VERSION); temp >> 8, temp & 0xff, DRIVER_VERSION,
ignore_oc ? ", overcurrent ignored" : "");
writel (INTR_MASK, &ehci->regs->intr_enable); /* Turn On Interrupts */ writel (INTR_MASK, &ehci->regs->intr_enable); /* Turn On Interrupts */
@ -613,9 +619,8 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
unsigned i = HCS_N_PORTS (ehci->hcs_params); unsigned i = HCS_N_PORTS (ehci->hcs_params);
/* resume root hub? */ /* resume root hub? */
status = readl (&ehci->regs->command); if (!(readl(&ehci->regs->command) & CMD_RUN))
if (!(status & CMD_RUN)) usb_hcd_resume_root_hub(hcd);
writel (status | CMD_RUN, &ehci->regs->command);
while (i--) { while (i--) {
int pstatus = readl (&ehci->regs->port_status [i]); int pstatus = readl (&ehci->regs->port_status [i]);
@ -632,7 +637,6 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
*/ */
ehci->reset_done [i] = jiffies + msecs_to_jiffies (20); ehci->reset_done [i] = jiffies + msecs_to_jiffies (20);
ehci_dbg (ehci, "port %d remote wakeup\n", i + 1); ehci_dbg (ehci, "port %d remote wakeup\n", i + 1);
usb_hcd_resume_root_hub(hcd);
} }
} }

View file

@ -34,6 +34,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
{ {
struct ehci_hcd *ehci = hcd_to_ehci (hcd); struct ehci_hcd *ehci = hcd_to_ehci (hcd);
int port; int port;
int mask;
if (time_before (jiffies, ehci->next_statechange)) if (time_before (jiffies, ehci->next_statechange))
msleep(5); msleep(5);
@ -51,14 +52,25 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
ehci->reclaim_ready = 1; ehci->reclaim_ready = 1;
ehci_work(ehci); ehci_work(ehci);
/* suspend any active/unsuspended ports, maybe allow wakeup */ /* Unlike other USB host controller types, EHCI doesn't have
* any notion of "global" or bus-wide suspend. The driver has
* to manually suspend all the active unsuspended ports, and
* then manually resume them in the bus_resume() routine.
*/
ehci->bus_suspended = 0;
while (port--) { while (port--) {
u32 __iomem *reg = &ehci->regs->port_status [port]; u32 __iomem *reg = &ehci->regs->port_status [port];
u32 t1 = readl (reg) & ~PORT_RWC_BITS; u32 t1 = readl (reg) & ~PORT_RWC_BITS;
u32 t2 = t1; u32 t2 = t1;
if ((t1 & PORT_PE) && !(t1 & PORT_OWNER)) /* keep track of which ports we suspend */
if ((t1 & PORT_PE) && !(t1 & PORT_OWNER) &&
!(t1 & PORT_SUSPEND)) {
t2 |= PORT_SUSPEND; t2 |= PORT_SUSPEND;
set_bit(port, &ehci->bus_suspended);
}
/* enable remote wakeup on all ports */
if (device_may_wakeup(&hcd->self.root_hub->dev)) if (device_may_wakeup(&hcd->self.root_hub->dev))
t2 |= PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E; t2 |= PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E;
else else
@ -76,6 +88,13 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
ehci_halt (ehci); ehci_halt (ehci);
hcd->state = HC_STATE_SUSPENDED; hcd->state = HC_STATE_SUSPENDED;
/* allow remote wakeup */
mask = INTR_MASK;
if (!device_may_wakeup(&hcd->self.root_hub->dev))
mask &= ~STS_PCD;
writel(mask, &ehci->regs->intr_enable);
readl(&ehci->regs->intr_enable);
ehci->next_statechange = jiffies + msecs_to_jiffies(10); ehci->next_statechange = jiffies + msecs_to_jiffies(10);
spin_unlock_irq (&ehci->lock); spin_unlock_irq (&ehci->lock);
return 0; return 0;
@ -88,7 +107,6 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
struct ehci_hcd *ehci = hcd_to_ehci (hcd); struct ehci_hcd *ehci = hcd_to_ehci (hcd);
u32 temp; u32 temp;
int i; int i;
int intr_enable;
if (time_before (jiffies, ehci->next_statechange)) if (time_before (jiffies, ehci->next_statechange))
msleep(5); msleep(5);
@ -100,31 +118,30 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
* the last user of the controller, not reset/pm hardware keeping * the last user of the controller, not reset/pm hardware keeping
* state we gave to it. * state we gave to it.
*/ */
temp = readl(&ehci->regs->intr_enable);
ehci_dbg(ehci, "resume root hub%s\n", temp ? "" : " after power loss");
/* re-init operational registers in case we lost power */ /* at least some APM implementations will try to deliver
if (readl (&ehci->regs->intr_enable) == 0) { * IRQs right away, so delay them until we're ready.
/* at least some APM implementations will try to deliver */
* IRQs right away, so delay them until we're ready. writel(0, &ehci->regs->intr_enable);
*/
intr_enable = 1; /* re-init operational registers */
writel (0, &ehci->regs->segment); writel(0, &ehci->regs->segment);
writel (ehci->periodic_dma, &ehci->regs->frame_list); writel(ehci->periodic_dma, &ehci->regs->frame_list);
writel ((u32)ehci->async->qh_dma, &ehci->regs->async_next); writel((u32) ehci->async->qh_dma, &ehci->regs->async_next);
} else
intr_enable = 0;
ehci_dbg(ehci, "resume root hub%s\n",
intr_enable ? " after power loss" : "");
/* restore CMD_RUN, framelist size, and irq threshold */ /* restore CMD_RUN, framelist size, and irq threshold */
writel (ehci->command, &ehci->regs->command); writel (ehci->command, &ehci->regs->command);
/* take ports out of suspend */ /* manually resume the ports we suspended during bus_suspend() */
i = HCS_N_PORTS (ehci->hcs_params); i = HCS_N_PORTS (ehci->hcs_params);
while (i--) { while (i--) {
temp = readl (&ehci->regs->port_status [i]); temp = readl (&ehci->regs->port_status [i]);
temp &= ~(PORT_RWC_BITS temp &= ~(PORT_RWC_BITS
| PORT_WKOC_E | PORT_WKDISC_E | PORT_WKCONN_E); | PORT_WKOC_E | PORT_WKDISC_E | PORT_WKCONN_E);
if (temp & PORT_SUSPEND) { if (test_bit(i, &ehci->bus_suspended) &&
(temp & PORT_SUSPEND)) {
ehci->reset_done [i] = jiffies + msecs_to_jiffies (20); ehci->reset_done [i] = jiffies + msecs_to_jiffies (20);
temp |= PORT_RESUME; temp |= PORT_RESUME;
} }
@ -134,11 +151,12 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
mdelay (20); mdelay (20);
while (i--) { while (i--) {
temp = readl (&ehci->regs->port_status [i]); temp = readl (&ehci->regs->port_status [i]);
if ((temp & PORT_SUSPEND) == 0) if (test_bit(i, &ehci->bus_suspended) &&
continue; (temp & PORT_SUSPEND)) {
temp &= ~(PORT_RWC_BITS | PORT_RESUME); temp &= ~(PORT_RWC_BITS | PORT_RESUME);
writel (temp, &ehci->regs->port_status [i]); writel (temp, &ehci->regs->port_status [i]);
ehci_vdbg (ehci, "resumed port %d\n", i + 1); ehci_vdbg (ehci, "resumed port %d\n", i + 1);
}
} }
(void) readl (&ehci->regs->command); (void) readl (&ehci->regs->command);
@ -157,8 +175,7 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
hcd->state = HC_STATE_RUNNING; hcd->state = HC_STATE_RUNNING;
/* Now we can safely re-enable irqs */ /* Now we can safely re-enable irqs */
if (intr_enable) writel(INTR_MASK, &ehci->regs->intr_enable);
writel (INTR_MASK, &ehci->regs->intr_enable);
spin_unlock_irq (&ehci->lock); spin_unlock_irq (&ehci->lock);
return 0; return 0;
@ -218,6 +235,7 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf)
{ {
struct ehci_hcd *ehci = hcd_to_ehci (hcd); struct ehci_hcd *ehci = hcd_to_ehci (hcd);
u32 temp, status = 0; u32 temp, status = 0;
u32 mask;
int ports, i, retval = 1; int ports, i, retval = 1;
unsigned long flags; unsigned long flags;
@ -233,6 +251,18 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf)
retval++; retval++;
} }
/* Some boards (mostly VIA?) report bogus overcurrent indications,
* causing massive log spam unless we completely ignore them. It
* may be relevant that VIA VT8235 controlers, where PORT_POWER is
* always set, seem to clear PORT_OCC and PORT_CSC when writing to
* PORT_POWER; that's surprising, but maybe within-spec.
*/
if (!ignore_oc)
mask = PORT_CSC | PORT_PEC | PORT_OCC;
else
mask = PORT_CSC | PORT_PEC;
// PORT_RESUME from hardware ~= PORT_STAT_C_SUSPEND
/* no hub change reports (bit 0) for now (power, ...) */ /* no hub change reports (bit 0) for now (power, ...) */
/* port N changes (bit N)? */ /* port N changes (bit N)? */
@ -250,8 +280,7 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf)
} }
if (!(temp & PORT_CONNECT)) if (!(temp & PORT_CONNECT))
ehci->reset_done [i] = 0; ehci->reset_done [i] = 0;
if ((temp & (PORT_CSC | PORT_PEC | PORT_OCC)) != 0 if ((temp & mask) != 0
// PORT_STAT_C_SUSPEND?
|| ((temp & PORT_RESUME) != 0 || ((temp & PORT_RESUME) != 0
&& time_after (jiffies, && time_after (jiffies,
ehci->reset_done [i]))) { ehci->reset_done [i]))) {
@ -319,6 +348,7 @@ static int ehci_hub_control (
u32 temp, status; u32 temp, status;
unsigned long flags; unsigned long flags;
int retval = 0; int retval = 0;
unsigned selector;
/* /*
* FIXME: support SetPortFeatures USB_PORT_FEAT_INDICATOR. * FIXME: support SetPortFeatures USB_PORT_FEAT_INDICATOR.
@ -417,7 +447,7 @@ static int ehci_hub_control (
status |= 1 << USB_PORT_FEAT_C_CONNECTION; status |= 1 << USB_PORT_FEAT_C_CONNECTION;
if (temp & PORT_PEC) if (temp & PORT_PEC)
status |= 1 << USB_PORT_FEAT_C_ENABLE; status |= 1 << USB_PORT_FEAT_C_ENABLE;
if (temp & PORT_OCC) if ((temp & PORT_OCC) && !ignore_oc)
status |= 1 << USB_PORT_FEAT_C_OVER_CURRENT; status |= 1 << USB_PORT_FEAT_C_OVER_CURRENT;
/* whoever resumes must GetPortStatus to complete it!! */ /* whoever resumes must GetPortStatus to complete it!! */
@ -506,6 +536,8 @@ static int ehci_hub_control (
} }
break; break;
case SetPortFeature: case SetPortFeature:
selector = wIndex >> 8;
wIndex &= 0xff;
if (!wIndex || wIndex > ports) if (!wIndex || wIndex > ports)
goto error; goto error;
wIndex--; wIndex--;
@ -559,6 +591,22 @@ static int ehci_hub_control (
} }
writel (temp, &ehci->regs->port_status [wIndex]); writel (temp, &ehci->regs->port_status [wIndex]);
break; break;
/* For downstream facing ports (these): one hub port is put
* into test mode according to USB2 11.24.2.13, then the hub
* must be reset (which for root hub now means rmmod+modprobe,
* or else system reboot). See EHCI 2.3.9 and 4.14 for info
* about the EHCI-specific stuff.
*/
case USB_PORT_FEAT_TEST:
if (!selector || selector > 5)
goto error;
ehci_quiesce(ehci);
ehci_halt(ehci);
temp |= selector << 16;
writel (temp, &ehci->regs->port_status [wIndex]);
break;
default: default:
goto error; goto error;
} }

View file

@ -257,9 +257,7 @@ static int ehci_pci_suspend(struct usb_hcd *hcd, pm_message_t message)
static int ehci_pci_resume(struct usb_hcd *hcd) static int ehci_pci_resume(struct usb_hcd *hcd)
{ {
struct ehci_hcd *ehci = hcd_to_ehci(hcd); struct ehci_hcd *ehci = hcd_to_ehci(hcd);
unsigned port;
struct pci_dev *pdev = to_pci_dev(hcd->self.controller); struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
int retval = -EINVAL;
// maybe restore FLADJ // maybe restore FLADJ
@ -269,27 +267,19 @@ static int ehci_pci_resume(struct usb_hcd *hcd)
/* Mark hardware accessible again as we are out of D3 state by now */ /* Mark hardware accessible again as we are out of D3 state by now */
set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
/* If CF is clear, we lost PCI Vaux power and need to restart. */ /* If CF is still set, we maintained PCI Vaux power.
if (readl(&ehci->regs->configured_flag) != FLAG_CF) * Just undo the effect of ehci_pci_suspend().
goto restart;
/* If any port is suspended (or owned by the companion),
* we know we can/must resume the HC (and mustn't reset it).
* We just defer that to the root hub code.
*/ */
for (port = HCS_N_PORTS(ehci->hcs_params); port > 0; ) { if (readl(&ehci->regs->configured_flag) == FLAG_CF) {
u32 status; int mask = INTR_MASK;
port--;
status = readl(&ehci->regs->port_status [port]); if (!device_may_wakeup(&hcd->self.root_hub->dev))
if (!(status & PORT_POWER)) mask &= ~STS_PCD;
continue; writel(mask, &ehci->regs->intr_enable);
if (status & (PORT_SUSPEND | PORT_RESUME | PORT_OWNER)) { readl(&ehci->regs->intr_enable);
usb_hcd_resume_root_hub(hcd); return 0;
return 0;
}
} }
restart:
ehci_dbg(ehci, "lost power, restarting\n"); ehci_dbg(ehci, "lost power, restarting\n");
usb_root_hub_lost_power(hcd->self.root_hub); usb_root_hub_lost_power(hcd->self.root_hub);
@ -307,13 +297,15 @@ restart:
ehci_work(ehci); ehci_work(ehci);
spin_unlock_irq(&ehci->lock); spin_unlock_irq(&ehci->lock);
/* restart; khubd will disconnect devices */
retval = ehci_run(hcd);
/* here we "know" root ports should always stay powered */ /* here we "know" root ports should always stay powered */
ehci_port_power(ehci, 1); ehci_port_power(ehci, 1);
return retval; writel(ehci->command, &ehci->regs->command);
writel(FLAG_CF, &ehci->regs->configured_flag);
readl(&ehci->regs->command); /* unblock posted writes */
hcd->state = HC_STATE_SUSPENDED;
return 0;
} }
#endif #endif

View file

@ -74,6 +74,7 @@ struct ehci_hcd { /* one per controller */
/* per root hub port */ /* per root hub port */
unsigned long reset_done [EHCI_MAX_ROOT_PORTS]; unsigned long reset_done [EHCI_MAX_ROOT_PORTS];
unsigned long bus_suspended;
/* per-HC memory pools (could be per-bus, but ...) */ /* per-HC memory pools (could be per-bus, but ...) */
struct dma_pool *qh_pool; /* qh per active urb */ struct dma_pool *qh_pool; /* qh per active urb */

View file

@ -729,6 +729,16 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd)
ohci->next_statechange = jiffies + STATECHANGE_DELAY; ohci->next_statechange = jiffies + STATECHANGE_DELAY;
ohci_writel(ohci, OHCI_INTR_RD | OHCI_INTR_RHSC, ohci_writel(ohci, OHCI_INTR_RD | OHCI_INTR_RHSC,
&regs->intrstatus); &regs->intrstatus);
/* NOTE: Vendors didn't always make the same implementation
* choices for RHSC. Many followed the spec; RHSC triggers
* on an edge, like setting and maybe clearing a port status
* change bit. With others it's level-triggered, active
* until khubd clears all the port status change bits. We'll
* always disable it here and rely on polling until khubd
* re-enables it.
*/
ohci_writel(ohci, OHCI_INTR_RHSC, &regs->intrdisable);
usb_hcd_poll_rh_status(hcd); usb_hcd_poll_rh_status(hcd);
} }

View file

@ -41,7 +41,11 @@ static void ohci_rhsc_enable (struct usb_hcd *hcd)
{ {
struct ohci_hcd *ohci = hcd_to_ohci (hcd); struct ohci_hcd *ohci = hcd_to_ohci (hcd);
ohci_writel (ohci, OHCI_INTR_RHSC, &ohci->regs->intrenable); spin_lock_irq(&ohci->lock);
if (!ohci->autostop)
del_timer(&hcd->rh_timer); /* Prevent next poll */
ohci_writel(ohci, OHCI_INTR_RHSC, &ohci->regs->intrenable);
spin_unlock_irq(&ohci->lock);
} }
#define OHCI_SCHED_ENABLES \ #define OHCI_SCHED_ENABLES \
@ -50,6 +54,9 @@ static void ohci_rhsc_enable (struct usb_hcd *hcd)
static void dl_done_list (struct ohci_hcd *); static void dl_done_list (struct ohci_hcd *);
static void finish_unlinks (struct ohci_hcd *, u16); static void finish_unlinks (struct ohci_hcd *, u16);
#ifdef CONFIG_PM
static int ohci_restart(struct ohci_hcd *ohci);
static int ohci_rh_suspend (struct ohci_hcd *ohci, int autostop) static int ohci_rh_suspend (struct ohci_hcd *ohci, int autostop)
__releases(ohci->lock) __releases(ohci->lock)
__acquires(ohci->lock) __acquires(ohci->lock)
@ -132,8 +139,6 @@ static inline struct ed *find_head (struct ed *ed)
return ed; return ed;
} }
static int ohci_restart (struct ohci_hcd *ohci);
/* caller has locked the root hub */ /* caller has locked the root hub */
static int ohci_rh_resume (struct ohci_hcd *ohci) static int ohci_rh_resume (struct ohci_hcd *ohci)
__releases(ohci->lock) __releases(ohci->lock)
@ -169,7 +174,7 @@ __acquires(ohci->lock)
break; break;
case OHCI_USB_RESUME: case OHCI_USB_RESUME:
/* HCFS changes sometime after INTR_RD */ /* HCFS changes sometime after INTR_RD */
ohci_info(ohci, "%swakeup\n", ohci_dbg(ohci, "%swakeup root hub\n",
autostopped ? "auto-" : ""); autostopped ? "auto-" : "");
break; break;
case OHCI_USB_OPER: case OHCI_USB_OPER:
@ -181,7 +186,6 @@ __acquires(ohci->lock)
ohci_dbg (ohci, "lost power\n"); ohci_dbg (ohci, "lost power\n");
status = -EBUSY; status = -EBUSY;
} }
#ifdef CONFIG_PM
if (status == -EBUSY) { if (status == -EBUSY) {
if (!autostopped) { if (!autostopped) {
spin_unlock_irq (&ohci->lock); spin_unlock_irq (&ohci->lock);
@ -191,25 +195,12 @@ __acquires(ohci->lock)
} }
return status; return status;
} }
#endif
if (status != -EINPROGRESS) if (status != -EINPROGRESS)
return status; return status;
if (autostopped) if (autostopped)
goto skip_resume; goto skip_resume;
spin_unlock_irq (&ohci->lock); spin_unlock_irq (&ohci->lock);
temp = ohci->num_ports;
while (temp--) {
u32 stat = ohci_readl (ohci,
&ohci->regs->roothub.portstatus [temp]);
/* force global, not selective, resume */
if (!(stat & RH_PS_PSS))
continue;
ohci_writel (ohci, RH_PS_POCI,
&ohci->regs->roothub.portstatus [temp]);
}
/* Some controllers (lucent erratum) need extra-long delays */ /* Some controllers (lucent erratum) need extra-long delays */
msleep (20 /* usb 11.5.1.10 */ + 12 /* 32 msec counter */ + 1); msleep (20 /* usb 11.5.1.10 */ + 12 /* 32 msec counter */ + 1);
@ -217,6 +208,7 @@ __acquires(ohci->lock)
temp &= OHCI_CTRL_HCFS; temp &= OHCI_CTRL_HCFS;
if (temp != OHCI_USB_RESUME) { if (temp != OHCI_USB_RESUME) {
ohci_err (ohci, "controller won't resume\n"); ohci_err (ohci, "controller won't resume\n");
spin_lock_irq(&ohci->lock);
return -EBUSY; return -EBUSY;
} }
@ -296,8 +288,6 @@ skip_resume:
return 0; return 0;
} }
#ifdef CONFIG_PM
static int ohci_bus_suspend (struct usb_hcd *hcd) static int ohci_bus_suspend (struct usb_hcd *hcd)
{ {
struct ohci_hcd *ohci = hcd_to_ohci (hcd); struct ohci_hcd *ohci = hcd_to_ohci (hcd);
@ -335,6 +325,83 @@ static int ohci_bus_resume (struct usb_hcd *hcd)
return rc; return rc;
} }
/* Carry out polling-, autostop-, and autoresume-related state changes */
static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed,
int any_connected)
{
int poll_rh = 1;
switch (ohci->hc_control & OHCI_CTRL_HCFS) {
case OHCI_USB_OPER:
/* keep on polling until we know a device is connected
* and RHSC is enabled */
if (!ohci->autostop) {
if (any_connected ||
!device_may_wakeup(&ohci_to_hcd(ohci)
->self.root_hub->dev)) {
if (ohci_readl(ohci, &ohci->regs->intrenable) &
OHCI_INTR_RHSC)
poll_rh = 0;
} else {
ohci->autostop = 1;
ohci->next_statechange = jiffies + HZ;
}
/* if no devices have been attached for one second, autostop */
} else {
if (changed || any_connected) {
ohci->autostop = 0;
ohci->next_statechange = jiffies +
STATECHANGE_DELAY;
} else if (time_after_eq(jiffies,
ohci->next_statechange)
&& !ohci->ed_rm_list
&& !(ohci->hc_control &
OHCI_SCHED_ENABLES)) {
ohci_rh_suspend(ohci, 1);
}
}
break;
/* if there is a port change, autostart or ask to be resumed */
case OHCI_USB_SUSPEND:
case OHCI_USB_RESUME:
if (changed) {
if (ohci->autostop)
ohci_rh_resume(ohci);
else
usb_hcd_resume_root_hub(ohci_to_hcd(ohci));
} else {
/* everything is idle, no need for polling */
poll_rh = 0;
}
break;
}
return poll_rh;
}
#else /* CONFIG_PM */
static inline int ohci_rh_resume(struct ohci_hcd *ohci)
{
return 0;
}
/* Carry out polling-related state changes.
* autostop isn't used when CONFIG_PM is turned off.
*/
static int ohci_root_hub_state_changes(struct ohci_hcd *ohci, int changed,
int any_connected)
{
int poll_rh = 1;
/* keep on polling until RHSC is enabled */
if (ohci_readl(ohci, &ohci->regs->intrenable) & OHCI_INTR_RHSC)
poll_rh = 0;
return poll_rh;
}
#endif /* CONFIG_PM */ #endif /* CONFIG_PM */
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
@ -346,7 +413,7 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
{ {
struct ohci_hcd *ohci = hcd_to_ohci (hcd); struct ohci_hcd *ohci = hcd_to_ohci (hcd);
int i, changed = 0, length = 1; int i, changed = 0, length = 1;
int any_connected = 0, rhsc_enabled = 1; int any_connected = 0;
unsigned long flags; unsigned long flags;
spin_lock_irqsave (&ohci->lock, flags); spin_lock_irqsave (&ohci->lock, flags);
@ -387,67 +454,8 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
} }
} }
/* NOTE: vendors didn't always make the same implementation hcd->poll_rh = ohci_root_hub_state_changes(ohci, changed,
* choices for RHSC. Sometimes it triggers on an edge (like any_connected);
* setting and maybe clearing a port status change bit); and
* it's level-triggered on other silicon, active until khubd
* clears all active port status change bits. If it's still
* set (level-triggered) we must disable it and rely on
* polling until khubd re-enables it.
*/
if (ohci_readl (ohci, &ohci->regs->intrstatus) & OHCI_INTR_RHSC) {
ohci_writel (ohci, OHCI_INTR_RHSC, &ohci->regs->intrdisable);
(void) ohci_readl (ohci, &ohci->regs->intrdisable);
rhsc_enabled = 0;
}
hcd->poll_rh = 1;
/* carry out appropriate state changes */
switch (ohci->hc_control & OHCI_CTRL_HCFS) {
case OHCI_USB_OPER:
/* keep on polling until we know a device is connected
* and RHSC is enabled */
if (!ohci->autostop) {
if (any_connected) {
if (rhsc_enabled)
hcd->poll_rh = 0;
} else {
ohci->autostop = 1;
ohci->next_statechange = jiffies + HZ;
}
/* if no devices have been attached for one second, autostop */
} else {
if (changed || any_connected) {
ohci->autostop = 0;
ohci->next_statechange = jiffies +
STATECHANGE_DELAY;
} else if (device_may_wakeup(&hcd->self.root_hub->dev)
&& time_after_eq(jiffies,
ohci->next_statechange)
&& !ohci->ed_rm_list
&& !(ohci->hc_control &
OHCI_SCHED_ENABLES)) {
ohci_rh_suspend (ohci, 1);
}
}
break;
/* if there is a port change, autostart or ask to be resumed */
case OHCI_USB_SUSPEND:
case OHCI_USB_RESUME:
if (changed) {
if (ohci->autostop)
ohci_rh_resume (ohci);
else
usb_hcd_resume_root_hub (hcd);
} else {
/* everything is idle, no need for polling */
hcd->poll_rh = 0;
}
break;
}
done: done:
spin_unlock_irqrestore (&ohci->lock, flags); spin_unlock_irqrestore (&ohci->lock, flags);

View file

@ -71,7 +71,7 @@ static int distrust_firmware = 1;
module_param(distrust_firmware, bool, 0); module_param(distrust_firmware, bool, 0);
MODULE_PARM_DESC(distrust_firmware, "true to distrust firmware power/overcurren" MODULE_PARM_DESC(distrust_firmware, "true to distrust firmware power/overcurren"
"t setup"); "t setup");
DECLARE_WAIT_QUEUE_HEAD(u132_hcd_wait); static DECLARE_WAIT_QUEUE_HEAD(u132_hcd_wait);
/* /*
* u132_module_lock exists to protect access to global variables * u132_module_lock exists to protect access to global variables
* *
@ -205,11 +205,7 @@ struct u132 {
struct u132_port port[MAX_U132_PORTS]; struct u132_port port[MAX_U132_PORTS];
struct u132_endp *endp[MAX_U132_ENDPS]; struct u132_endp *endp[MAX_U132_ENDPS];
}; };
int usb_ftdi_elan_read_reg(struct platform_device *pdev, u32 *data);
int usb_ftdi_elan_read_pcimem(struct platform_device *pdev, u8 addressofs,
u8 width, u32 *data);
int usb_ftdi_elan_write_pcimem(struct platform_device *pdev, u8 addressofs,
u8 width, u32 data);
/* /*
* these cannot be inlines because we need the structure offset!! * these cannot be inlines because we need the structure offset!!
* Does anyone have a better way????? * Does anyone have a better way?????

View file

@ -796,7 +796,7 @@ static int mts_usb_probe(struct usb_interface *intf,
new_desc->context.scsi_status = kmalloc(1, GFP_KERNEL); new_desc->context.scsi_status = kmalloc(1, GFP_KERNEL);
if (!new_desc->context.scsi_status) if (!new_desc->context.scsi_status)
goto out_kfree2; goto out_free_urb;
new_desc->usb_dev = dev; new_desc->usb_dev = dev;
new_desc->usb_intf = intf; new_desc->usb_intf = intf;
@ -822,18 +822,20 @@ static int mts_usb_probe(struct usb_interface *intf,
new_desc->host = scsi_host_alloc(&mts_scsi_host_template, new_desc->host = scsi_host_alloc(&mts_scsi_host_template,
sizeof(new_desc)); sizeof(new_desc));
if (!new_desc->host) if (!new_desc->host)
goto out_free_urb; goto out_kfree2;
new_desc->host->hostdata[0] = (unsigned long)new_desc; new_desc->host->hostdata[0] = (unsigned long)new_desc;
if (scsi_add_host(new_desc->host, NULL)) { if (scsi_add_host(new_desc->host, NULL)) {
err_retval = -EIO; err_retval = -EIO;
goto out_free_urb; goto out_host_put;
} }
scsi_scan_host(new_desc->host); scsi_scan_host(new_desc->host);
usb_set_intfdata(intf, new_desc); usb_set_intfdata(intf, new_desc);
return 0; return 0;
out_host_put:
scsi_host_put(new_desc->host);
out_kfree2: out_kfree2:
kfree(new_desc->context.scsi_status); kfree(new_desc->context.scsi_status);
out_free_urb: out_free_urb:

View file

@ -221,6 +221,7 @@ config USB_TOUCHSCREEN
- ITM - ITM
- some other eTurboTouch - some other eTurboTouch
- Gunze AHL61 - Gunze AHL61
- DMC TSC-10/25
Have a look at <http://linux.chapter7.ch/touchkit/> for Have a look at <http://linux.chapter7.ch/touchkit/> for
a usage description and the required user-space stuff. a usage description and the required user-space stuff.
@ -258,6 +259,11 @@ config USB_TOUCHSCREEN_GUNZE
bool "Gunze AHL61 device support" if EMBEDDED bool "Gunze AHL61 device support" if EMBEDDED
depends on USB_TOUCHSCREEN depends on USB_TOUCHSCREEN
config USB_TOUCHSCREEN_DMC_TSC10
default y
bool "DMC TSC-10/25 device support" if EMBEDDED
depends on USB_TOUCHSCREEN
config USB_YEALINK config USB_YEALINK
tristate "Yealink usb-p1k voip phone" tristate "Yealink usb-p1k voip phone"
depends on USB && INPUT && EXPERIMENTAL depends on USB && INPUT && EXPERIMENTAL

View file

@ -630,11 +630,8 @@ static int ati_remote_alloc_buffers(struct usb_device *udev,
*/ */
static void ati_remote_free_buffers(struct ati_remote *ati_remote) static void ati_remote_free_buffers(struct ati_remote *ati_remote)
{ {
if (ati_remote->irq_urb) usb_free_urb(ati_remote->irq_urb);
usb_free_urb(ati_remote->irq_urb); usb_free_urb(ati_remote->out_urb);
if (ati_remote->out_urb)
usb_free_urb(ati_remote->out_urb);
usb_buffer_free(ati_remote->udev, DATA_BUFSIZE, usb_buffer_free(ati_remote->udev, DATA_BUFSIZE,
ati_remote->inbuf, ati_remote->inbuf_dma); ati_remote->inbuf, ati_remote->inbuf_dma);

View file

@ -372,8 +372,7 @@ static void ati_remote2_urb_cleanup(struct ati_remote2 *ar2)
int i; int i;
for (i = 0; i < 2; i++) { for (i = 0; i < 2; i++) {
if (ar2->urb[i]) usb_free_urb(ar2->urb[i]);
usb_free_urb(ar2->urb[i]);
if (ar2->buf[i]) if (ar2->buf[i])
usb_buffer_free(ar2->udev, 4, ar2->buf[i], ar2->buf_dma[i]); usb_buffer_free(ar2->udev, 4, ar2->buf[i], ar2->buf_dma[i]);

View file

@ -968,20 +968,29 @@ static void hid_retry_timeout(unsigned long _hid)
hid_io_error(hid); hid_io_error(hid);
} }
/* Workqueue routine to reset the device */ /* Workqueue routine to reset the device or clear a halt */
static void hid_reset(void *_hid) static void hid_reset(void *_hid)
{ {
struct hid_device *hid = (struct hid_device *) _hid; struct hid_device *hid = (struct hid_device *) _hid;
int rc_lock, rc; int rc_lock, rc = 0;
dev_dbg(&hid->intf->dev, "resetting device\n"); if (test_bit(HID_CLEAR_HALT, &hid->iofl)) {
rc = rc_lock = usb_lock_device_for_reset(hid->dev, hid->intf); dev_dbg(&hid->intf->dev, "clear halt\n");
if (rc_lock >= 0) { rc = usb_clear_halt(hid->dev, hid->urbin->pipe);
rc = usb_reset_composite_device(hid->dev, hid->intf); clear_bit(HID_CLEAR_HALT, &hid->iofl);
if (rc_lock) hid_start_in(hid);
usb_unlock_device(hid->dev); }
else if (test_bit(HID_RESET_PENDING, &hid->iofl)) {
dev_dbg(&hid->intf->dev, "resetting device\n");
rc = rc_lock = usb_lock_device_for_reset(hid->dev, hid->intf);
if (rc_lock >= 0) {
rc = usb_reset_composite_device(hid->dev, hid->intf);
if (rc_lock)
usb_unlock_device(hid->dev);
}
clear_bit(HID_RESET_PENDING, &hid->iofl);
} }
clear_bit(HID_RESET_PENDING, &hid->iofl);
switch (rc) { switch (rc) {
case 0: case 0:
@ -1023,9 +1032,8 @@ static void hid_io_error(struct hid_device *hid)
/* Retries failed, so do a port reset */ /* Retries failed, so do a port reset */
if (!test_and_set_bit(HID_RESET_PENDING, &hid->iofl)) { if (!test_and_set_bit(HID_RESET_PENDING, &hid->iofl)) {
if (schedule_work(&hid->reset_work)) schedule_work(&hid->reset_work);
goto done; goto done;
clear_bit(HID_RESET_PENDING, &hid->iofl);
} }
} }
@ -1049,6 +1057,11 @@ static void hid_irq_in(struct urb *urb)
hid->retry_delay = 0; hid->retry_delay = 0;
hid_input_report(HID_INPUT_REPORT, urb, 1); hid_input_report(HID_INPUT_REPORT, urb, 1);
break; break;
case -EPIPE: /* stall */
clear_bit(HID_IN_RUNNING, &hid->iofl);
set_bit(HID_CLEAR_HALT, &hid->iofl);
schedule_work(&hid->reset_work);
return;
case -ECONNRESET: /* unlink */ case -ECONNRESET: /* unlink */
case -ENOENT: case -ENOENT:
case -ESHUTDOWN: /* unplug */ case -ESHUTDOWN: /* unplug */
@ -1627,6 +1640,19 @@ void hid_init_reports(struct hid_device *hid)
#define USB_VENDOR_ID_APPLE 0x05ac #define USB_VENDOR_ID_APPLE 0x05ac
#define USB_DEVICE_ID_APPLE_MIGHTYMOUSE 0x0304 #define USB_DEVICE_ID_APPLE_MIGHTYMOUSE 0x0304
#define USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI 0x020e
#define USB_DEVICE_ID_APPLE_FOUNTAIN_ISO 0x020f
#define USB_DEVICE_ID_APPLE_GEYSER_ANSI 0x0214
#define USB_DEVICE_ID_APPLE_GEYSER_ISO 0x0215
#define USB_DEVICE_ID_APPLE_GEYSER_JIS 0x0216
#define USB_DEVICE_ID_APPLE_GEYSER3_ANSI 0x0217
#define USB_DEVICE_ID_APPLE_GEYSER3_ISO 0x0218
#define USB_DEVICE_ID_APPLE_GEYSER3_JIS 0x0219
#define USB_DEVICE_ID_APPLE_GEYSER4_ANSI 0x021a
#define USB_DEVICE_ID_APPLE_GEYSER4_ISO 0x021b
#define USB_DEVICE_ID_APPLE_GEYSER4_JIS 0x021c
#define USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY 0x030a
#define USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY 0x030b
#define USB_VENDOR_ID_CHERRY 0x046a #define USB_VENDOR_ID_CHERRY 0x046a
#define USB_DEVICE_ID_CHERRY_CYMOTION 0x0023 #define USB_DEVICE_ID_CHERRY_CYMOTION 0x0023
@ -1794,17 +1820,19 @@ static const struct hid_blacklist {
{ USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION, HID_QUIRK_CYMOTION }, { USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION, HID_QUIRK_CYMOTION },
{ USB_VENDOR_ID_APPLE, 0x020E, HID_QUIRK_POWERBOOK_HAS_FN }, { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI, HID_QUIRK_POWERBOOK_HAS_FN },
{ USB_VENDOR_ID_APPLE, 0x020F, HID_QUIRK_POWERBOOK_HAS_FN }, { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ISO, HID_QUIRK_POWERBOOK_HAS_FN },
{ USB_VENDOR_ID_APPLE, 0x0214, HID_QUIRK_POWERBOOK_HAS_FN }, { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ANSI, HID_QUIRK_POWERBOOK_HAS_FN },
{ USB_VENDOR_ID_APPLE, 0x0215, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_POWERBOOK_ISO_KEYBOARD}, { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ISO, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_POWERBOOK_ISO_KEYBOARD},
{ USB_VENDOR_ID_APPLE, 0x0216, HID_QUIRK_POWERBOOK_HAS_FN }, { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_JIS, HID_QUIRK_POWERBOOK_HAS_FN },
{ USB_VENDOR_ID_APPLE, 0x0217, HID_QUIRK_POWERBOOK_HAS_FN }, { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ANSI, HID_QUIRK_POWERBOOK_HAS_FN },
{ USB_VENDOR_ID_APPLE, 0x0218, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_POWERBOOK_ISO_KEYBOARD}, { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ISO, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_POWERBOOK_ISO_KEYBOARD},
{ USB_VENDOR_ID_APPLE, 0x0219, HID_QUIRK_POWERBOOK_HAS_FN }, { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_JIS, HID_QUIRK_POWERBOOK_HAS_FN },
{ USB_VENDOR_ID_APPLE, 0x021B, HID_QUIRK_POWERBOOK_HAS_FN }, { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ANSI, HID_QUIRK_POWERBOOK_HAS_FN },
{ USB_VENDOR_ID_APPLE, 0x030A, HID_QUIRK_POWERBOOK_HAS_FN }, { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ISO, HID_QUIRK_POWERBOOK_HAS_FN },
{ USB_VENDOR_ID_APPLE, 0x030B, HID_QUIRK_POWERBOOK_HAS_FN }, { USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_JIS, HID_QUIRK_POWERBOOK_HAS_FN },
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY, HID_QUIRK_POWERBOOK_HAS_FN },
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY, HID_QUIRK_POWERBOOK_HAS_FN },
{ USB_VENDOR_ID_PANJIT, 0x0001, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_PANJIT, 0x0001, HID_QUIRK_IGNORE },
{ USB_VENDOR_ID_PANJIT, 0x0002, HID_QUIRK_IGNORE }, { USB_VENDOR_ID_PANJIT, 0x0002, HID_QUIRK_IGNORE },
@ -1985,7 +2013,7 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
if (hid->collection->usage == HID_GD_MOUSE && hid_mousepoll_interval > 0) if (hid->collection->usage == HID_GD_MOUSE && hid_mousepoll_interval > 0)
interval = hid_mousepoll_interval; interval = hid_mousepoll_interval;
if (endpoint->bEndpointAddress & USB_DIR_IN) { if (usb_endpoint_dir_in(endpoint)) {
if (hid->urbin) if (hid->urbin)
continue; continue;
if (!(hid->urbin = usb_alloc_urb(0, GFP_KERNEL))) if (!(hid->urbin = usb_alloc_urb(0, GFP_KERNEL)))
@ -2067,13 +2095,9 @@ static struct hid_device *usb_hid_configure(struct usb_interface *intf)
return hid; return hid;
fail: fail:
usb_free_urb(hid->urbin);
if (hid->urbin) usb_free_urb(hid->urbout);
usb_free_urb(hid->urbin); usb_free_urb(hid->urbctrl);
if (hid->urbout)
usb_free_urb(hid->urbout);
if (hid->urbctrl)
usb_free_urb(hid->urbctrl);
hid_free_buffers(dev, hid); hid_free_buffers(dev, hid);
hid_free_device(hid); hid_free_device(hid);
@ -2104,8 +2128,7 @@ static void hid_disconnect(struct usb_interface *intf)
usb_free_urb(hid->urbin); usb_free_urb(hid->urbin);
usb_free_urb(hid->urbctrl); usb_free_urb(hid->urbctrl);
if (hid->urbout) usb_free_urb(hid->urbout);
usb_free_urb(hid->urbout);
hid_free_buffers(hid->dev, hid); hid_free_buffers(hid->dev, hid);
hid_free_device(hid); hid_free_device(hid);

View file

@ -385,6 +385,7 @@ struct hid_control_fifo {
#define HID_IN_RUNNING 3 #define HID_IN_RUNNING 3
#define HID_RESET_PENDING 4 #define HID_RESET_PENDING 4
#define HID_SUSPENDED 5 #define HID_SUSPENDED 5
#define HID_CLEAR_HALT 6
struct hid_input { struct hid_input {
struct list_head list; struct list_head list;

View file

@ -208,10 +208,8 @@ static int usb_kbd_alloc_mem(struct usb_device *dev, struct usb_kbd *kbd)
static void usb_kbd_free_mem(struct usb_device *dev, struct usb_kbd *kbd) static void usb_kbd_free_mem(struct usb_device *dev, struct usb_kbd *kbd)
{ {
if (kbd->irq) usb_free_urb(kbd->irq);
usb_free_urb(kbd->irq); usb_free_urb(kbd->led);
if (kbd->led)
usb_free_urb(kbd->led);
if (kbd->new) if (kbd->new)
usb_buffer_free(dev, 8, kbd->new, kbd->new_dma); usb_buffer_free(dev, 8, kbd->new, kbd->new_dma);
if (kbd->cr) if (kbd->cr)
@ -236,9 +234,7 @@ static int usb_kbd_probe(struct usb_interface *iface,
return -ENODEV; return -ENODEV;
endpoint = &interface->endpoint[0].desc; endpoint = &interface->endpoint[0].desc;
if (!(endpoint->bEndpointAddress & USB_DIR_IN)) if (!usb_endpoint_is_int_in(endpoint))
return -ENODEV;
if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT)
return -ENODEV; return -ENODEV;
pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);

View file

@ -126,9 +126,7 @@ static int usb_mouse_probe(struct usb_interface *intf, const struct usb_device_i
return -ENODEV; return -ENODEV;
endpoint = &interface->endpoint[0].desc; endpoint = &interface->endpoint[0].desc;
if (!(endpoint->bEndpointAddress & USB_DIR_IN)) if (!usb_endpoint_is_int_in(endpoint))
return -ENODEV;
if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT)
return -ENODEV; return -ENODEV;
pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress); pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);

View file

@ -8,6 +8,7 @@
* - PanJit TouchSet * - PanJit TouchSet
* - eTurboTouch * - eTurboTouch
* - Gunze AHL61 * - Gunze AHL61
* - DMC TSC-10/25
* *
* Copyright (C) 2004-2006 by Daniel Ritz <daniel.ritz@gmx.ch> * Copyright (C) 2004-2006 by Daniel Ritz <daniel.ritz@gmx.ch>
* Copyright (C) by Todd E. Johnson (mtouchusb.c) * Copyright (C) by Todd E. Johnson (mtouchusb.c)
@ -30,6 +31,8 @@
* - ITM parts are from itmtouch.c * - ITM parts are from itmtouch.c
* - 3M parts are from mtouchusb.c * - 3M parts are from mtouchusb.c
* - PanJit parts are from an unmerged driver by Lanslott Gish * - PanJit parts are from an unmerged driver by Lanslott Gish
* - DMC TSC 10/25 are from Holger Schurig, with ideas from an unmerged
* driver from Marius Vollmer
* *
*****************************************************************************/ *****************************************************************************/
@ -44,7 +47,7 @@
#include <linux/usb/input.h> #include <linux/usb/input.h>
#define DRIVER_VERSION "v0.4" #define DRIVER_VERSION "v0.5"
#define DRIVER_AUTHOR "Daniel Ritz <daniel.ritz@gmx.ch>" #define DRIVER_AUTHOR "Daniel Ritz <daniel.ritz@gmx.ch>"
#define DRIVER_DESC "USB Touchscreen Driver" #define DRIVER_DESC "USB Touchscreen Driver"
@ -103,6 +106,7 @@ enum {
DEVTYPE_ITM, DEVTYPE_ITM,
DEVTYPE_ETURBO, DEVTYPE_ETURBO,
DEVTYPE_GUNZE, DEVTYPE_GUNZE,
DEVTYPE_DMC_TSC10,
}; };
static struct usb_device_id usbtouch_devices[] = { static struct usb_device_id usbtouch_devices[] = {
@ -139,6 +143,10 @@ static struct usb_device_id usbtouch_devices[] = {
{USB_DEVICE(0x0637, 0x0001), .driver_info = DEVTYPE_GUNZE}, {USB_DEVICE(0x0637, 0x0001), .driver_info = DEVTYPE_GUNZE},
#endif #endif
#ifdef CONFIG_USB_TOUCHSCREEN_DMC_TSC10
{USB_DEVICE(0x0afa, 0x03e8), .driver_info = DEVTYPE_DMC_TSC10},
#endif
{} {}
}; };
@ -312,6 +320,80 @@ static int gunze_read_data(unsigned char *pkt, int *x, int *y, int *touch, int *
} }
#endif #endif
/*****************************************************************************
* DMC TSC-10/25 Part
*
* Documentation about the controller and it's protocol can be found at
* http://www.dmccoltd.com/files/controler/tsc10usb_pi_e.pdf
* http://www.dmccoltd.com/files/controler/tsc25_usb_e.pdf
*/
#ifdef CONFIG_USB_TOUCHSCREEN_DMC_TSC10
/* supported data rates. currently using 130 */
#define TSC10_RATE_POINT 0x50
#define TSC10_RATE_30 0x40
#define TSC10_RATE_50 0x41
#define TSC10_RATE_80 0x42
#define TSC10_RATE_100 0x43
#define TSC10_RATE_130 0x44
#define TSC10_RATE_150 0x45
/* commands */
#define TSC10_CMD_RESET 0x55
#define TSC10_CMD_RATE 0x05
#define TSC10_CMD_DATA1 0x01
static int dmc_tsc10_init(struct usbtouch_usb *usbtouch)
{
struct usb_device *dev = usbtouch->udev;
int ret;
unsigned char buf[2];
/* reset */
buf[0] = buf[1] = 0xFF;
ret = usb_control_msg(dev, usb_rcvctrlpipe (dev, 0),
TSC10_CMD_RESET,
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
0, 0, buf, 2, USB_CTRL_SET_TIMEOUT);
if (ret < 0)
return ret;
if (buf[0] != 0x06 || buf[1] != 0x00)
return -ENODEV;
/* set coordinate output rate */
buf[0] = buf[1] = 0xFF;
ret = usb_control_msg(dev, usb_rcvctrlpipe (dev, 0),
TSC10_CMD_RATE,
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
TSC10_RATE_150, 0, buf, 2, USB_CTRL_SET_TIMEOUT);
if (ret < 0)
return ret;
if (buf[0] != 0x06 || buf[1] != 0x00)
return -ENODEV;
/* start sending data */
ret = usb_control_msg(dev, usb_rcvctrlpipe (dev, 0),
TSC10_CMD_DATA1,
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
0, 0, NULL, 0, USB_CTRL_SET_TIMEOUT);
if (ret < 0)
return ret;
return 0;
}
static int dmc_tsc10_read_data(unsigned char *pkt, int *x, int *y, int *touch, int *press)
{
*x = ((pkt[2] & 0x03) << 8) | pkt[1];
*y = ((pkt[4] & 0x03) << 8) | pkt[3];
*touch = pkt[0] & 0x01;
return 1;
}
#endif
/***************************************************************************** /*****************************************************************************
* the different device descriptors * the different device descriptors
*/ */
@ -389,6 +471,18 @@ static struct usbtouch_device_info usbtouch_dev_info[] = {
.read_data = gunze_read_data, .read_data = gunze_read_data,
}, },
#endif #endif
#ifdef CONFIG_USB_TOUCHSCREEN_DMC_TSC10
[DEVTYPE_DMC_TSC10] = {
.min_xc = 0x0,
.max_xc = 0x03ff,
.min_yc = 0x0,
.max_yc = 0x03ff,
.rept_size = 5,
.init = dmc_tsc10_init,
.read_data = dmc_tsc10_read_data,
},
#endif
}; };

View file

@ -110,7 +110,6 @@ struct wacom_combo {
}; };
extern int wacom_wac_irq(struct wacom_wac * wacom_wac, void * wcombo); extern int wacom_wac_irq(struct wacom_wac * wacom_wac, void * wcombo);
extern void wacom_sys_irq(struct urb *urb);
extern void wacom_report_abs(void *wcombo, unsigned int abs_type, int abs_data); extern void wacom_report_abs(void *wcombo, unsigned int abs_type, int abs_data);
extern void wacom_report_rel(void *wcombo, unsigned int rel_type, int rel_data); extern void wacom_report_rel(void *wcombo, unsigned int rel_type, int rel_data);
extern void wacom_report_key(void *wcombo, unsigned int key_type, int key_data); extern void wacom_report_key(void *wcombo, unsigned int key_type, int key_data);

View file

@ -42,7 +42,7 @@ static struct input_dev * get_input_dev(struct wacom_combo *wcombo)
return wcombo->wacom->dev; return wcombo->wacom->dev;
} }
void wacom_sys_irq(struct urb *urb) static void wacom_sys_irq(struct urb *urb)
{ {
struct wacom *wacom = urb->context; struct wacom *wacom = urb->context;
struct wacom_combo wcombo; struct wacom_combo wcombo;

View file

@ -859,10 +859,8 @@ static int usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
interface = intf->cur_altsetting; interface = intf->cur_altsetting;
endpoint = &interface->endpoint[0].desc; endpoint = &interface->endpoint[0].desc;
if (!(endpoint->bEndpointAddress & USB_DIR_IN)) if (!usb_endpoint_is_int_in(endpoint))
return -EIO; return -ENODEV;
if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT)
return -EIO;
yld = kzalloc(sizeof(struct yealink_dev), GFP_KERNEL); yld = kzalloc(sizeof(struct yealink_dev), GFP_KERNEL);
if (!yld) if (!yld)

View file

@ -4,6 +4,7 @@
# #
obj-$(CONFIG_USB_ADUTUX) += adutux.o obj-$(CONFIG_USB_ADUTUX) += adutux.o
obj-$(CONFIG_USB_APPLEDISPLAY) += appledisplay.o
obj-$(CONFIG_USB_AUERSWALD) += auerswald.o obj-$(CONFIG_USB_AUERSWALD) += auerswald.o
obj-$(CONFIG_USB_CYPRESS_CY7C63)+= cypress_cy7c63.o obj-$(CONFIG_USB_CYPRESS_CY7C63)+= cypress_cy7c63.o
obj-$(CONFIG_USB_CYTHERM) += cytherm.o obj-$(CONFIG_USB_CYTHERM) += cytherm.o

View file

@ -216,10 +216,7 @@ static int appledisplay_probe(struct usb_interface *iface,
iface_desc = iface->cur_altsetting; iface_desc = iface->cur_altsetting;
for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) { for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) {
endpoint = &iface_desc->endpoint[i].desc; endpoint = &iface_desc->endpoint[i].desc;
if (!int_in_endpointAddr && if (!int_in_endpointAddr && usb_endpoint_is_int_in(endpoint)) {
(endpoint->bEndpointAddress & USB_DIR_IN) &&
((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
USB_ENDPOINT_XFER_INT)) {
/* we found an interrupt in endpoint */ /* we found an interrupt in endpoint */
int_in_endpointAddr = endpoint->bEndpointAddress; int_in_endpointAddr = endpoint->bEndpointAddress;
break; break;

View file

@ -704,9 +704,7 @@ static void auerbuf_free (pauerbuf_t bp)
{ {
kfree(bp->bufp); kfree(bp->bufp);
kfree(bp->dr); kfree(bp->dr);
if (bp->urbp) { usb_free_urb(bp->urbp);
usb_free_urb(bp->urbp);
}
kfree(bp); kfree(bp);
} }
@ -1155,8 +1153,7 @@ static void auerswald_int_release (pauerswald_t cp)
dbg ("auerswald_int_release"); dbg ("auerswald_int_release");
/* stop the int endpoint */ /* stop the int endpoint */
if (cp->inturbp) usb_kill_urb (cp->inturbp);
usb_kill_urb (cp->inturbp);
/* deallocate memory */ /* deallocate memory */
auerswald_int_free (cp); auerswald_int_free (cp);

View file

@ -53,13 +53,12 @@ static void __exit emi26_exit (void);
static int emi26_writememory (struct usb_device *dev, int address, unsigned char *data, int length, __u8 request) static int emi26_writememory (struct usb_device *dev, int address, unsigned char *data, int length, __u8 request)
{ {
int result; int result;
unsigned char *buffer = kmalloc (length, GFP_KERNEL); unsigned char *buffer = kmemdup(data, length, GFP_KERNEL);
if (!buffer) { if (!buffer) {
err("emi26: kmalloc(%d) failed.", length); err("emi26: kmalloc(%d) failed.", length);
return -ENOMEM; return -ENOMEM;
} }
memcpy (buffer, data, length);
/* Note: usb_control_msg returns negative value on error or length of the /* Note: usb_control_msg returns negative value on error or length of the
* data that was written! */ * data that was written! */
result = usb_control_msg (dev, usb_sndctrlpipe(dev, 0), request, 0x40, address, 0, buffer, length, 300); result = usb_control_msg (dev, usb_sndctrlpipe(dev, 0), request, 0x40, address, 0, buffer, length, 300);

View file

@ -61,13 +61,12 @@ static void __exit emi62_exit (void);
static int emi62_writememory (struct usb_device *dev, int address, unsigned char *data, int length, __u8 request) static int emi62_writememory (struct usb_device *dev, int address, unsigned char *data, int length, __u8 request)
{ {
int result; int result;
unsigned char *buffer = kmalloc (length, GFP_KERNEL); unsigned char *buffer = kmemdup(data, length, GFP_KERNEL);
if (!buffer) { if (!buffer) {
err("emi62: kmalloc(%d) failed.", length); err("emi62: kmalloc(%d) failed.", length);
return -ENOMEM; return -ENOMEM;
} }
memcpy (buffer, data, length);
/* Note: usb_control_msg returns negative value on error or length of the /* Note: usb_control_msg returns negative value on error or length of the
* data that was written! */ * data that was written! */
result = usb_control_msg (dev, usb_sndctrlpipe(dev, 0), request, 0x40, address, 0, buffer, length, 300); result = usb_control_msg (dev, usb_sndctrlpipe(dev, 0), request, 0x40, address, 0, buffer, length, 300);

View file

@ -303,7 +303,7 @@ void ftdi_elan_gone_away(struct platform_device *pdev)
EXPORT_SYMBOL_GPL(ftdi_elan_gone_away); EXPORT_SYMBOL_GPL(ftdi_elan_gone_away);
void ftdi_release_platform_dev(struct device *dev) static void ftdi_release_platform_dev(struct device *dev)
{ {
dev->parent = NULL; dev->parent = NULL;
} }
@ -1426,14 +1426,6 @@ static int ftdi_elan_read_reg(struct usb_ftdi *ftdi, u32 *data)
} }
} }
int usb_ftdi_elan_read_reg(struct platform_device *pdev, u32 *data)
{
struct usb_ftdi *ftdi = platform_device_to_usb_ftdi(pdev);
return ftdi_elan_read_reg(ftdi, data);
}
EXPORT_SYMBOL_GPL(usb_ftdi_elan_read_reg);
static int ftdi_elan_read_config(struct usb_ftdi *ftdi, int config_offset, static int ftdi_elan_read_config(struct usb_ftdi *ftdi, int config_offset,
u8 width, u32 *data) u8 width, u32 *data)
{ {
@ -2633,10 +2625,7 @@ static int ftdi_elan_probe(struct usb_interface *interface,
for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
endpoint = &iface_desc->endpoint[i].desc; endpoint = &iface_desc->endpoint[i].desc;
if (!ftdi->bulk_in_endpointAddr && if (!ftdi->bulk_in_endpointAddr &&
((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) usb_endpoint_is_bulk_in(endpoint)) {
== USB_DIR_IN) && ((endpoint->bmAttributes &
USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK))
{
buffer_size = le16_to_cpu(endpoint->wMaxPacketSize); buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
ftdi->bulk_in_size = buffer_size; ftdi->bulk_in_size = buffer_size;
ftdi->bulk_in_endpointAddr = endpoint->bEndpointAddress; ftdi->bulk_in_endpointAddr = endpoint->bEndpointAddress;
@ -2649,10 +2638,7 @@ static int ftdi_elan_probe(struct usb_interface *interface,
} }
} }
if (!ftdi->bulk_out_endpointAddr && if (!ftdi->bulk_out_endpointAddr &&
((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) usb_endpoint_is_bulk_out(endpoint)) {
== USB_DIR_OUT) && ((endpoint->bmAttributes &
USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK))
{
ftdi->bulk_out_endpointAddr = ftdi->bulk_out_endpointAddr =
endpoint->bEndpointAddress; endpoint->bEndpointAddress;
} }

View file

@ -125,12 +125,12 @@ static DEFINE_MUTEX(disconnect_mutex);
static int idmouse_create_image(struct usb_idmouse *dev) static int idmouse_create_image(struct usb_idmouse *dev)
{ {
int bytes_read = 0; int bytes_read;
int bulk_read = 0; int bulk_read;
int result = 0; int result;
memcpy(dev->bulk_in_buffer, HEADER, sizeof(HEADER)-1); memcpy(dev->bulk_in_buffer, HEADER, sizeof(HEADER)-1);
bytes_read += sizeof(HEADER)-1; bytes_read = sizeof(HEADER)-1;
/* reset the device and set a fast blink rate */ /* reset the device and set a fast blink rate */
result = ftip_command(dev, FTIP_RELEASE, 0, 0); result = ftip_command(dev, FTIP_RELEASE, 0, 0);
@ -208,9 +208,9 @@ static inline void idmouse_delete(struct usb_idmouse *dev)
static int idmouse_open(struct inode *inode, struct file *file) static int idmouse_open(struct inode *inode, struct file *file)
{ {
struct usb_idmouse *dev = NULL; struct usb_idmouse *dev;
struct usb_interface *interface; struct usb_interface *interface;
int result = 0; int result;
/* prevent disconnects */ /* prevent disconnects */
mutex_lock(&disconnect_mutex); mutex_lock(&disconnect_mutex);
@ -305,7 +305,7 @@ static ssize_t idmouse_read(struct file *file, char __user *buffer, size_t count
loff_t * ppos) loff_t * ppos)
{ {
struct usb_idmouse *dev; struct usb_idmouse *dev;
int result = 0; int result;
dev = (struct usb_idmouse *) file->private_data; dev = (struct usb_idmouse *) file->private_data;
@ -329,7 +329,7 @@ static int idmouse_probe(struct usb_interface *interface,
const struct usb_device_id *id) const struct usb_device_id *id)
{ {
struct usb_device *udev = interface_to_usbdev(interface); struct usb_device *udev = interface_to_usbdev(interface);
struct usb_idmouse *dev = NULL; struct usb_idmouse *dev;
struct usb_host_interface *iface_desc; struct usb_host_interface *iface_desc;
struct usb_endpoint_descriptor *endpoint; struct usb_endpoint_descriptor *endpoint;
int result; int result;
@ -350,11 +350,7 @@ static int idmouse_probe(struct usb_interface *interface,
/* set up the endpoint information - use only the first bulk-in endpoint */ /* set up the endpoint information - use only the first bulk-in endpoint */
endpoint = &iface_desc->endpoint[0].desc; endpoint = &iface_desc->endpoint[0].desc;
if (!dev->bulk_in_endpointAddr if (!dev->bulk_in_endpointAddr && usb_endpoint_is_bulk_in(endpoint)) {
&& (endpoint->bEndpointAddress & USB_DIR_IN)
&& ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
USB_ENDPOINT_XFER_BULK)) {
/* we found a bulk in endpoint */ /* we found a bulk in endpoint */
dev->orig_bi_size = le16_to_cpu(endpoint->wMaxPacketSize); dev->orig_bi_size = le16_to_cpu(endpoint->wMaxPacketSize);
dev->bulk_in_size = 0x200; /* works _much_ faster */ dev->bulk_in_size = 0x200; /* works _much_ faster */

View file

@ -317,12 +317,8 @@ static inline void tower_delete (struct lego_usb_tower *dev)
tower_abort_transfers (dev); tower_abort_transfers (dev);
/* free data structures */ /* free data structures */
if (dev->interrupt_in_urb != NULL) { usb_free_urb(dev->interrupt_in_urb);
usb_free_urb (dev->interrupt_in_urb); usb_free_urb(dev->interrupt_out_urb);
}
if (dev->interrupt_out_urb != NULL) {
usb_free_urb (dev->interrupt_out_urb);
}
kfree (dev->read_buffer); kfree (dev->read_buffer);
kfree (dev->interrupt_in_buffer); kfree (dev->interrupt_in_buffer);
kfree (dev->interrupt_out_buffer); kfree (dev->interrupt_out_buffer);
@ -502,15 +498,11 @@ static void tower_abort_transfers (struct lego_usb_tower *dev)
if (dev->interrupt_in_running) { if (dev->interrupt_in_running) {
dev->interrupt_in_running = 0; dev->interrupt_in_running = 0;
mb(); mb();
if (dev->interrupt_in_urb != NULL && dev->udev) { if (dev->udev)
usb_kill_urb (dev->interrupt_in_urb); usb_kill_urb (dev->interrupt_in_urb);
}
}
if (dev->interrupt_out_busy) {
if (dev->interrupt_out_urb != NULL && dev->udev) {
usb_kill_urb (dev->interrupt_out_urb);
}
} }
if (dev->interrupt_out_busy && dev->udev)
usb_kill_urb(dev->interrupt_out_urb);
exit: exit:
dbg(2, "%s: leave", __FUNCTION__); dbg(2, "%s: leave", __FUNCTION__);
@ -898,14 +890,11 @@ static int tower_probe (struct usb_interface *interface, const struct usb_device
for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
endpoint = &iface_desc->endpoint[i].desc; endpoint = &iface_desc->endpoint[i].desc;
if (((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) && if (usb_endpoint_xfer_int(endpoint)) {
((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)) { if (usb_endpoint_dir_in(endpoint))
dev->interrupt_in_endpoint = endpoint; dev->interrupt_in_endpoint = endpoint;
} else
dev->interrupt_out_endpoint = endpoint;
if (((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) &&
((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)) {
dev->interrupt_out_endpoint = endpoint;
} }
} }
if(dev->interrupt_in_endpoint == NULL) { if(dev->interrupt_in_endpoint == NULL) {

View file

@ -551,7 +551,7 @@ static int interfacekit_probe(struct usb_interface *intf, const struct usb_devic
return -ENODEV; return -ENODEV;
endpoint = &interface->endpoint[0].desc; endpoint = &interface->endpoint[0].desc;
if (!(endpoint->bEndpointAddress & 0x80)) if (!usb_endpoint_dir_in(endpoint))
return -ENODEV; return -ENODEV;
/* /*
* bmAttributes * bmAttributes
@ -650,8 +650,7 @@ out2:
device_remove_file(kit->dev, &dev_output_attrs[i]); device_remove_file(kit->dev, &dev_output_attrs[i]);
out: out:
if (kit) { if (kit) {
if (kit->irq) usb_free_urb(kit->irq);
usb_free_urb(kit->irq);
if (kit->data) if (kit->data)
usb_buffer_free(dev, URB_INT_SIZE, kit->data, kit->data_dma); usb_buffer_free(dev, URB_INT_SIZE, kit->data, kit->data_dma);
if (kit->dev) if (kit->dev)

View file

@ -323,7 +323,7 @@ static int motorcontrol_probe(struct usb_interface *intf, const struct usb_devic
return -ENODEV; return -ENODEV;
endpoint = &interface->endpoint[0].desc; endpoint = &interface->endpoint[0].desc;
if (!(endpoint->bEndpointAddress & 0x80)) if (!usb_endpoint_dir_in(endpoint))
return -ENODEV; return -ENODEV;
/* /*
@ -392,8 +392,7 @@ out2:
device_remove_file(mc->dev, &dev_attrs[i]); device_remove_file(mc->dev, &dev_attrs[i]);
out: out:
if (mc) { if (mc) {
if (mc->irq) usb_free_urb(mc->irq);
usb_free_urb(mc->irq);
if (mc->data) if (mc->data)
usb_buffer_free(dev, URB_INT_SIZE, mc->data, mc->data_dma); usb_buffer_free(dev, URB_INT_SIZE, mc->data, mc->data_dma);
if (mc->dev) if (mc->dev)

View file

@ -95,3 +95,7 @@ int usb_ftdi_elan_edset_setup(struct platform_device *pdev, u8 ed_number,
int halted, int skipped, int actual, int non_null)); int halted, int skipped, int actual, int non_null));
int usb_ftdi_elan_edset_flush(struct platform_device *pdev, u8 ed_number, int usb_ftdi_elan_edset_flush(struct platform_device *pdev, u8 ed_number,
void *endp); void *endp);
int usb_ftdi_elan_read_pcimem(struct platform_device *pdev, int mem_offset,
u8 width, u32 *data);
int usb_ftdi_elan_write_pcimem(struct platform_device *pdev, int mem_offset,
u8 width, u32 data);

View file

@ -138,7 +138,7 @@ get_endpoints (struct usbtest_dev *dev, struct usb_interface *intf)
default: default:
continue; continue;
} }
if (e->desc.bEndpointAddress & USB_DIR_IN) { if (usb_endpoint_dir_in(&e->desc)) {
if (!in) if (!in)
in = e; in = e;
} else { } else {
@ -147,7 +147,7 @@ get_endpoints (struct usbtest_dev *dev, struct usb_interface *intf)
} }
continue; continue;
try_iso: try_iso:
if (e->desc.bEndpointAddress & USB_DIR_IN) { if (usb_endpoint_dir_in(&e->desc)) {
if (!iso_in) if (!iso_in)
iso_in = e; iso_in = e;
} else { } else {

View file

@ -249,9 +249,9 @@ asix_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value, u16 index,
req->bRequestType = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE; req->bRequestType = USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE;
req->bRequest = cmd; req->bRequest = cmd;
req->wValue = value; req->wValue = cpu_to_le16(value);
req->wIndex = index; req->wIndex = cpu_to_le16(index);
req->wLength = size; req->wLength = cpu_to_le16(size);
usb_fill_control_urb(urb, dev->udev, usb_fill_control_urb(urb, dev->udev,
usb_sndctrlpipe(dev->udev, 0), usb_sndctrlpipe(dev->udev, 0),

View file

@ -786,14 +786,10 @@ static int catc_probe(struct usb_interface *intf, const struct usb_device_id *id
if ((!catc->ctrl_urb) || (!catc->tx_urb) || if ((!catc->ctrl_urb) || (!catc->tx_urb) ||
(!catc->rx_urb) || (!catc->irq_urb)) { (!catc->rx_urb) || (!catc->irq_urb)) {
err("No free urbs available."); err("No free urbs available.");
if (catc->ctrl_urb) usb_free_urb(catc->ctrl_urb);
usb_free_urb(catc->ctrl_urb); usb_free_urb(catc->tx_urb);
if (catc->tx_urb) usb_free_urb(catc->rx_urb);
usb_free_urb(catc->tx_urb); usb_free_urb(catc->irq_urb);
if (catc->rx_urb)
usb_free_urb(catc->rx_urb);
if (catc->irq_urb)
usb_free_urb(catc->irq_urb);
free_netdev(netdev); free_netdev(netdev);
return -ENOMEM; return -ENOMEM;
} }

View file

@ -200,8 +200,7 @@ next_desc:
dev->status = &info->control->cur_altsetting->endpoint [0]; dev->status = &info->control->cur_altsetting->endpoint [0];
desc = &dev->status->desc; desc = &dev->status->desc;
if (desc->bmAttributes != USB_ENDPOINT_XFER_INT if (!usb_endpoint_is_int_in(desc)
|| !(desc->bEndpointAddress & USB_DIR_IN)
|| (le16_to_cpu(desc->wMaxPacketSize) || (le16_to_cpu(desc->wMaxPacketSize)
< sizeof(struct usb_cdc_notification)) < sizeof(struct usb_cdc_notification))
|| !desc->bInterval) { || !desc->bInterval) {

View file

@ -237,12 +237,12 @@ static inline void nc_dump_usbctl(struct usbnet *dev, u16 usbctl)
#define STATUS_CONN_OTHER (1 << 14) #define STATUS_CONN_OTHER (1 << 14)
#define STATUS_SUSPEND_OTHER (1 << 13) #define STATUS_SUSPEND_OTHER (1 << 13)
#define STATUS_MAILBOX_OTHER (1 << 12) #define STATUS_MAILBOX_OTHER (1 << 12)
#define STATUS_PACKETS_OTHER(n) (((n) >> 8) && 0x03) #define STATUS_PACKETS_OTHER(n) (((n) >> 8) & 0x03)
#define STATUS_CONN_THIS (1 << 6) #define STATUS_CONN_THIS (1 << 6)
#define STATUS_SUSPEND_THIS (1 << 5) #define STATUS_SUSPEND_THIS (1 << 5)
#define STATUS_MAILBOX_THIS (1 << 4) #define STATUS_MAILBOX_THIS (1 << 4)
#define STATUS_PACKETS_THIS(n) (((n) >> 0) && 0x03) #define STATUS_PACKETS_THIS(n) (((n) >> 0) & 0x03)
#define STATUS_UNSPEC_MASK 0x0c8c #define STATUS_UNSPEC_MASK 0x0c8c
#define STATUS_NOISE_MASK ((u16)~(0x0303|STATUS_UNSPEC_MASK)) #define STATUS_NOISE_MASK ((u16)~(0x0303|STATUS_UNSPEC_MASK))

View file

@ -163,6 +163,7 @@ static int get_registers(pegasus_t * pegasus, __u16 indx, __u16 size,
/* using ATOMIC, we'd never wake up if we slept */ /* using ATOMIC, we'd never wake up if we slept */
if ((ret = usb_submit_urb(pegasus->ctrl_urb, GFP_ATOMIC))) { if ((ret = usb_submit_urb(pegasus->ctrl_urb, GFP_ATOMIC))) {
set_current_state(TASK_RUNNING);
if (ret == -ENODEV) if (ret == -ENODEV)
netif_device_detach(pegasus->net); netif_device_detach(pegasus->net);
if (netif_msg_drv(pegasus)) if (netif_msg_drv(pegasus))

View file

@ -116,7 +116,7 @@ int usbnet_get_endpoints(struct usbnet *dev, struct usb_interface *intf)
e = alt->endpoint + ep; e = alt->endpoint + ep;
switch (e->desc.bmAttributes) { switch (e->desc.bmAttributes) {
case USB_ENDPOINT_XFER_INT: case USB_ENDPOINT_XFER_INT:
if (!(e->desc.bEndpointAddress & USB_DIR_IN)) if (!usb_endpoint_dir_in(&e->desc))
continue; continue;
intr = 1; intr = 1;
/* FALLTHROUGH */ /* FALLTHROUGH */
@ -125,7 +125,7 @@ int usbnet_get_endpoints(struct usbnet *dev, struct usb_interface *intf)
default: default:
continue; continue;
} }
if (e->desc.bEndpointAddress & USB_DIR_IN) { if (usb_endpoint_dir_in(&e->desc)) {
if (!intr && !in) if (!intr && !in)
in = e; in = e;
else if (intr && !status) else if (intr && !status)

View file

@ -554,6 +554,17 @@ config USB_SERIAL_OMNINET
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
module will be called omninet. module will be called omninet.
config USB_SERIAL_DEBUG
tristate "USB Debugging Device"
depends on USB_SERIAL
help
Say Y here if you have a USB debugging device used to recieve
debugging data from another machine. The most common of these
devices is the NetChip TurboCONNECT device.
To compile this driver as a module, choose M here: the
module will be called usb-debug.
config USB_EZUSB config USB_EZUSB
bool bool
depends on USB_SERIAL_KEYSPAN_PDA || USB_SERIAL_XIRCOM || USB_SERIAL_KEYSPAN || USB_SERIAL_WHITEHEAT depends on USB_SERIAL_KEYSPAN_PDA || USB_SERIAL_XIRCOM || USB_SERIAL_KEYSPAN || USB_SERIAL_WHITEHEAT

View file

@ -18,6 +18,7 @@ obj-$(CONFIG_USB_SERIAL_BELKIN) += belkin_sa.o
obj-$(CONFIG_USB_SERIAL_CP2101) += cp2101.o obj-$(CONFIG_USB_SERIAL_CP2101) += cp2101.o
obj-$(CONFIG_USB_SERIAL_CYBERJACK) += cyberjack.o obj-$(CONFIG_USB_SERIAL_CYBERJACK) += cyberjack.o
obj-$(CONFIG_USB_SERIAL_CYPRESS_M8) += cypress_m8.o obj-$(CONFIG_USB_SERIAL_CYPRESS_M8) += cypress_m8.o
obj-$(CONFIG_USB_SERIAL_DEBUG) += usb_debug.o
obj-$(CONFIG_USB_SERIAL_DIGI_ACCELEPORT) += digi_acceleport.o obj-$(CONFIG_USB_SERIAL_DIGI_ACCELEPORT) += digi_acceleport.o
obj-$(CONFIG_USB_SERIAL_EDGEPORT) += io_edgeport.o obj-$(CONFIG_USB_SERIAL_EDGEPORT) += io_edgeport.o
obj-$(CONFIG_USB_SERIAL_EDGEPORT_TI) += io_ti.o obj-$(CONFIG_USB_SERIAL_EDGEPORT_TI) += io_ti.o

View file

@ -270,8 +270,11 @@ static void aircable_read(void *params)
*/ */
tty = port->tty; tty = port->tty;
if (!tty) if (!tty) {
schedule_work(&priv->rx_work); schedule_work(&priv->rx_work);
err("%s - No tty available", __FUNCTION__);
return ;
}
count = min(64, serial_buf_data_avail(priv->rx_buf)); count = min(64, serial_buf_data_avail(priv->rx_buf));
@ -305,9 +308,7 @@ static int aircable_probe(struct usb_serial *serial,
for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) { for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) {
endpoint = &iface_desc->endpoint[i].desc; endpoint = &iface_desc->endpoint[i].desc;
if (((endpoint->bEndpointAddress & 0x80) == 0x00) && if (usb_endpoint_is_bulk_out(endpoint)) {
((endpoint->bmAttributes & 3) == 0x02)) {
/* we found our bulk out endpoint */
dbg("found bulk out on endpoint %d", i); dbg("found bulk out on endpoint %d", i);
++num_bulk_out; ++num_bulk_out;
} }

View file

@ -19,6 +19,7 @@
static struct usb_device_id id_table [] = { static struct usb_device_id id_table [] = {
{ USB_DEVICE(0x0c88, 0x17da) }, /* Kyocera Wireless KPC650/Passport */ { USB_DEVICE(0x0c88, 0x17da) }, /* Kyocera Wireless KPC650/Passport */
{ USB_DEVICE(0x1410, 0x1110) }, /* Novatel Wireless Merlin CDMA */ { USB_DEVICE(0x1410, 0x1110) }, /* Novatel Wireless Merlin CDMA */
{ USB_DEVICE(0x1410, 0x1430) }, /* Novatel Merlin XU870 HSDPA/3G */
{ USB_DEVICE(0x1410, 0x1100) }, /* ExpressCard34 Qualcomm 3G CDMA */ { USB_DEVICE(0x1410, 0x1100) }, /* ExpressCard34 Qualcomm 3G CDMA */
{ }, { },
}; };

View file

@ -85,10 +85,9 @@ static int ark3116_attach(struct usb_serial *serial)
int i; int i;
for (i = 0; i < serial->num_ports; ++i) { for (i = 0; i < serial->num_ports; ++i) {
priv = kmalloc(sizeof (struct ark3116_private), GFP_KERNEL); priv = kzalloc(sizeof(struct ark3116_private), GFP_KERNEL);
if (!priv) if (!priv)
goto cleanup; goto cleanup;
memset(priv, 0x00, sizeof (struct ark3116_private));
spin_lock_init(&priv->lock); spin_lock_init(&priv->lock);
usb_set_serial_port_data(serial->port[i], priv); usb_set_serial_port_data(serial->port[i], priv);

View file

@ -166,19 +166,17 @@ static int usb_console_setup(struct console *co, char *options)
if (serial->type->set_termios) { if (serial->type->set_termios) {
/* build up a fake tty structure so that the open call has something /* build up a fake tty structure so that the open call has something
* to look at to get the cflag value */ * to look at to get the cflag value */
tty = kmalloc (sizeof (*tty), GFP_KERNEL); tty = kzalloc(sizeof(*tty), GFP_KERNEL);
if (!tty) { if (!tty) {
err ("no more memory"); err ("no more memory");
return -ENOMEM; return -ENOMEM;
} }
termios = kmalloc (sizeof (*termios), GFP_KERNEL); termios = kzalloc(sizeof(*termios), GFP_KERNEL);
if (!termios) { if (!termios) {
err ("no more memory"); err ("no more memory");
kfree (tty); kfree (tty);
return -ENOMEM; return -ENOMEM;
} }
memset (tty, 0x00, sizeof(*tty));
memset (termios, 0x00, sizeof(*termios));
termios->c_cflag = cflag; termios->c_cflag = cflag;
tty->termios = termios; tty->termios = termios;
port->tty = tty; port->tty = tty;

View file

@ -1684,15 +1684,14 @@ static int __init cypress_init(void)
info(DRIVER_DESC " " DRIVER_VERSION); info(DRIVER_DESC " " DRIVER_VERSION);
return 0; return 0;
failed_usb_register:
usb_deregister(&cypress_driver);
failed_ca42v2_register:
usb_serial_deregister(&cypress_ca42v2_device);
failed_hidcom_register:
usb_serial_deregister(&cypress_hidcom_device);
failed_em_register:
usb_serial_deregister(&cypress_earthmate_device);
failed_usb_register:
usb_serial_deregister(&cypress_ca42v2_device);
failed_ca42v2_register:
usb_serial_deregister(&cypress_hidcom_device);
failed_hidcom_register:
usb_serial_deregister(&cypress_earthmate_device);
failed_em_register:
return retval; return retval;
} }

View file

@ -31,12 +31,11 @@ int ezusb_writememory (struct usb_serial *serial, int address, unsigned char *da
return -ENODEV; return -ENODEV;
} }
transfer_buffer = kmalloc (length, GFP_KERNEL); transfer_buffer = kmemdup(data, length, GFP_KERNEL);
if (!transfer_buffer) { if (!transfer_buffer) {
dev_err(&serial->dev->dev, "%s - kmalloc(%d) failed.\n", __FUNCTION__, length); dev_err(&serial->dev->dev, "%s - kmalloc(%d) failed.\n", __FUNCTION__, length);
return -ENOMEM; return -ENOMEM;
} }
memcpy (transfer_buffer, data, length);
result = usb_control_msg (serial->dev, usb_sndctrlpipe(serial->dev, 0), bRequest, 0x40, address, 0, transfer_buffer, length, 3000); result = usb_control_msg (serial->dev, usb_sndctrlpipe(serial->dev, 0), bRequest, 0x40, address, 0, transfer_buffer, length, 3000);
kfree (transfer_buffer); kfree (transfer_buffer);
return result; return result;

View file

@ -1388,8 +1388,7 @@ static void ftdi_close (struct usb_serial_port *port, struct file *filp)
flush_scheduled_work(); flush_scheduled_work();
/* shutdown our bulk read */ /* shutdown our bulk read */
if (port->read_urb) usb_kill_urb(port->read_urb);
usb_kill_urb(port->read_urb);
} /* ftdi_close */ } /* ftdi_close */

View file

@ -1523,12 +1523,11 @@ static int garmin_attach (struct usb_serial *serial)
dbg("%s", __FUNCTION__); dbg("%s", __FUNCTION__);
garmin_data_p = kmalloc (sizeof(struct garmin_data), GFP_KERNEL); garmin_data_p = kzalloc(sizeof(struct garmin_data), GFP_KERNEL);
if (garmin_data_p == NULL) { if (garmin_data_p == NULL) {
dev_err(&port->dev, "%s - Out of memory\n", __FUNCTION__); dev_err(&port->dev, "%s - Out of memory\n", __FUNCTION__);
return -ENOMEM; return -ENOMEM;
} }
memset (garmin_data_p, 0, sizeof(struct garmin_data));
init_timer(&garmin_data_p->timer); init_timer(&garmin_data_p->timer);
spin_lock_init(&garmin_data_p->lock); spin_lock_init(&garmin_data_p->lock);
INIT_LIST_HEAD(&garmin_data_p->pktlist); INIT_LIST_HEAD(&garmin_data_p->pktlist);

View file

@ -1038,9 +1038,7 @@ static void edge_close (struct usb_serial_port *port, struct file * filp)
edge_port->open = FALSE; edge_port->open = FALSE;
edge_port->openPending = FALSE; edge_port->openPending = FALSE;
if (edge_port->write_urb) { usb_kill_urb(edge_port->write_urb);
usb_kill_urb(edge_port->write_urb);
}
if (edge_port->write_urb) { if (edge_port->write_urb) {
/* if this urb had a transfer buffer already (old transfer) free it */ /* if this urb had a transfer buffer already (old transfer) free it */

View file

@ -206,10 +206,9 @@ static int ipw_open(struct usb_serial_port *port, struct file *filp)
dbg("%s", __FUNCTION__); dbg("%s", __FUNCTION__);
buf_flow_init = kmalloc(16, GFP_KERNEL); buf_flow_init = kmemdup(buf_flow_static, 16, GFP_KERNEL);
if (!buf_flow_init) if (!buf_flow_init)
return -ENOMEM; return -ENOMEM;
memcpy(buf_flow_init, buf_flow_static, 16);
if (port->tty) if (port->tty)
port->tty->low_latency = 1; port->tty->low_latency = 1;

View file

@ -2306,22 +2306,16 @@ static void keyspan_shutdown (struct usb_serial *serial)
} }
/* Now free them */ /* Now free them */
if (s_priv->instat_urb) usb_free_urb(s_priv->instat_urb);
usb_free_urb(s_priv->instat_urb); usb_free_urb(s_priv->glocont_urb);
if (s_priv->glocont_urb)
usb_free_urb(s_priv->glocont_urb);
for (i = 0; i < serial->num_ports; ++i) { for (i = 0; i < serial->num_ports; ++i) {
port = serial->port[i]; port = serial->port[i];
p_priv = usb_get_serial_port_data(port); p_priv = usb_get_serial_port_data(port);
if (p_priv->inack_urb) usb_free_urb(p_priv->inack_urb);
usb_free_urb(p_priv->inack_urb); usb_free_urb(p_priv->outcont_urb);
if (p_priv->outcont_urb)
usb_free_urb(p_priv->outcont_urb);
for (j = 0; j < 2; j++) { for (j = 0; j < 2; j++) {
if (p_priv->in_urbs[j]) usb_free_urb(p_priv->in_urbs[j]);
usb_free_urb(p_priv->in_urbs[j]); usb_free_urb(p_priv->out_urbs[j]);
if (p_priv->out_urbs[j])
usb_free_urb(p_priv->out_urbs[j]);
} }
} }

View file

@ -185,13 +185,11 @@ static int kobil_startup (struct usb_serial *serial)
for (i = 0; i < altsetting->desc.bNumEndpoints; i++) { for (i = 0; i < altsetting->desc.bNumEndpoints; i++) {
endpoint = &altsetting->endpoint[i]; endpoint = &altsetting->endpoint[i];
if (((endpoint->desc.bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) && if (usb_endpoint_is_int_out(&endpoint->desc)) {
((endpoint->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)) {
dbg("%s Found interrupt out endpoint. Address: %d", __FUNCTION__, endpoint->desc.bEndpointAddress); dbg("%s Found interrupt out endpoint. Address: %d", __FUNCTION__, endpoint->desc.bEndpointAddress);
priv->write_int_endpoint_address = endpoint->desc.bEndpointAddress; priv->write_int_endpoint_address = endpoint->desc.bEndpointAddress;
} }
if (((endpoint->desc.bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) && if (usb_endpoint_is_int_in(&endpoint->desc)) {
((endpoint->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)) {
dbg("%s Found interrupt in endpoint. Address: %d", __FUNCTION__, endpoint->desc.bEndpointAddress); dbg("%s Found interrupt in endpoint. Address: %d", __FUNCTION__, endpoint->desc.bEndpointAddress);
priv->read_int_endpoint_address = endpoint->desc.bEndpointAddress; priv->read_int_endpoint_address = endpoint->desc.bEndpointAddress;
} }
@ -355,8 +353,7 @@ static void kobil_close (struct usb_serial_port *port, struct file *filp)
usb_free_urb( port->write_urb ); usb_free_urb( port->write_urb );
port->write_urb = NULL; port->write_urb = NULL;
} }
if (port->interrupt_in_urb) usb_kill_urb(port->interrupt_in_urb);
usb_kill_urb(port->interrupt_in_urb);
} }

View file

@ -358,10 +358,8 @@ static int mct_u232_startup (struct usb_serial *serial)
/* Puh, that's dirty */ /* Puh, that's dirty */
port = serial->port[0]; port = serial->port[0];
rport = serial->port[1]; rport = serial->port[1];
if (port->read_urb) { /* No unlinking, it wasn't submitted yet. */
/* No unlinking, it wasn't submitted yet. */ usb_free_urb(port->read_urb);
usb_free_urb(port->read_urb);
}
port->read_urb = rport->interrupt_in_urb; port->read_urb = rport->interrupt_in_urb;
rport->interrupt_in_urb = NULL; rport->interrupt_in_urb = NULL;
port->read_urb->context = port; port->read_urb->context = port;

View file

@ -2596,12 +2596,11 @@ static int mos7840_startup(struct usb_serial *serial)
/* set up port private structures */ /* set up port private structures */
for (i = 0; i < serial->num_ports; ++i) { for (i = 0; i < serial->num_ports; ++i) {
mos7840_port = kmalloc(sizeof(struct moschip_port), GFP_KERNEL); mos7840_port = kzalloc(sizeof(struct moschip_port), GFP_KERNEL);
if (mos7840_port == NULL) { if (mos7840_port == NULL) {
err("%s - Out of memory", __FUNCTION__); err("%s - Out of memory", __FUNCTION__);
return -ENOMEM; return -ENOMEM;
} }
memset(mos7840_port, 0, sizeof(struct moschip_port));
/* Initialize all port interrupt end point to port 0 int endpoint * /* Initialize all port interrupt end point to port 0 int endpoint *
* Our device has only one interrupt end point comman to all port */ * Our device has only one interrupt end point comman to all port */

View file

@ -95,8 +95,7 @@ static void navman_close(struct usb_serial_port *port, struct file *filp)
{ {
dbg("%s - port %d", __FUNCTION__, port->number); dbg("%s - port %d", __FUNCTION__, port->number);
if (port->interrupt_in_urb) usb_kill_urb(port->interrupt_in_urb);
usb_kill_urb(port->interrupt_in_urb);
} }
static int navman_write(struct usb_serial_port *port, static int navman_write(struct usb_serial_port *port,

View file

@ -228,6 +228,7 @@ static int product_5052_count;
/* null entry */ /* null entry */
static struct usb_device_id ti_id_table_3410[1+TI_EXTRA_VID_PID_COUNT+1] = { static struct usb_device_id ti_id_table_3410[1+TI_EXTRA_VID_PID_COUNT+1] = {
{ USB_DEVICE(TI_VENDOR_ID, TI_3410_PRODUCT_ID) }, { USB_DEVICE(TI_VENDOR_ID, TI_3410_PRODUCT_ID) },
{ USB_DEVICE(TI_VENDOR_ID, TI_3410_EZ430_ID) },
}; };
static struct usb_device_id ti_id_table_5052[4+TI_EXTRA_VID_PID_COUNT+1] = { static struct usb_device_id ti_id_table_5052[4+TI_EXTRA_VID_PID_COUNT+1] = {
@ -239,6 +240,7 @@ static struct usb_device_id ti_id_table_5052[4+TI_EXTRA_VID_PID_COUNT+1] = {
static struct usb_device_id ti_id_table_combined[] = { static struct usb_device_id ti_id_table_combined[] = {
{ USB_DEVICE(TI_VENDOR_ID, TI_3410_PRODUCT_ID) }, { USB_DEVICE(TI_VENDOR_ID, TI_3410_PRODUCT_ID) },
{ USB_DEVICE(TI_VENDOR_ID, TI_3410_EZ430_ID) },
{ USB_DEVICE(TI_VENDOR_ID, TI_5052_BOOT_PRODUCT_ID) }, { USB_DEVICE(TI_VENDOR_ID, TI_5052_BOOT_PRODUCT_ID) },
{ USB_DEVICE(TI_VENDOR_ID, TI_5152_BOOT_PRODUCT_ID) }, { USB_DEVICE(TI_VENDOR_ID, TI_5152_BOOT_PRODUCT_ID) },
{ USB_DEVICE(TI_VENDOR_ID, TI_5052_EEPROM_PRODUCT_ID) }, { USB_DEVICE(TI_VENDOR_ID, TI_5052_EEPROM_PRODUCT_ID) },
@ -459,13 +461,12 @@ static int ti_startup(struct usb_serial *serial)
/* set up port structures */ /* set up port structures */
for (i = 0; i < serial->num_ports; ++i) { for (i = 0; i < serial->num_ports; ++i) {
tport = kmalloc(sizeof(struct ti_port), GFP_KERNEL); tport = kzalloc(sizeof(struct ti_port), GFP_KERNEL);
if (tport == NULL) { if (tport == NULL) {
dev_err(&dev->dev, "%s - out of memory\n", __FUNCTION__); dev_err(&dev->dev, "%s - out of memory\n", __FUNCTION__);
status = -ENOMEM; status = -ENOMEM;
goto free_tports; goto free_tports;
} }
memset(tport, 0, sizeof(struct ti_port));
spin_lock_init(&tport->tp_lock); spin_lock_init(&tport->tp_lock);
tport->tp_uart_base_addr = (i == 0 ? TI_UART1_BASE_ADDR : TI_UART2_BASE_ADDR); tport->tp_uart_base_addr = (i == 0 ? TI_UART1_BASE_ADDR : TI_UART2_BASE_ADDR);
tport->tp_flags = low_latency ? ASYNC_LOW_LATENCY : 0; tport->tp_flags = low_latency ? ASYNC_LOW_LATENCY : 0;

View file

@ -28,6 +28,7 @@
/* Vendor and product ids */ /* Vendor and product ids */
#define TI_VENDOR_ID 0x0451 #define TI_VENDOR_ID 0x0451
#define TI_3410_PRODUCT_ID 0x3410 #define TI_3410_PRODUCT_ID 0x3410
#define TI_3410_EZ430_ID 0xF430 /* TI ez430 development tool */
#define TI_5052_BOOT_PRODUCT_ID 0x5052 /* no EEPROM, no firmware */ #define TI_5052_BOOT_PRODUCT_ID 0x5052 /* no EEPROM, no firmware */
#define TI_5152_BOOT_PRODUCT_ID 0x5152 /* no EEPROM, no firmware */ #define TI_5152_BOOT_PRODUCT_ID 0x5152 /* no EEPROM, no firmware */
#define TI_5052_EEPROM_PRODUCT_ID 0x505A /* EEPROM, no firmware */ #define TI_5052_EEPROM_PRODUCT_ID 0x505A /* EEPROM, no firmware */

View file

@ -952,32 +952,28 @@ probe_error:
port = serial->port[i]; port = serial->port[i];
if (!port) if (!port)
continue; continue;
if (port->read_urb) usb_free_urb(port->read_urb);
usb_free_urb (port->read_urb);
kfree(port->bulk_in_buffer); kfree(port->bulk_in_buffer);
} }
for (i = 0; i < num_bulk_out; ++i) { for (i = 0; i < num_bulk_out; ++i) {
port = serial->port[i]; port = serial->port[i];
if (!port) if (!port)
continue; continue;
if (port->write_urb) usb_free_urb(port->write_urb);
usb_free_urb (port->write_urb);
kfree(port->bulk_out_buffer); kfree(port->bulk_out_buffer);
} }
for (i = 0; i < num_interrupt_in; ++i) { for (i = 0; i < num_interrupt_in; ++i) {
port = serial->port[i]; port = serial->port[i];
if (!port) if (!port)
continue; continue;
if (port->interrupt_in_urb) usb_free_urb(port->interrupt_in_urb);
usb_free_urb (port->interrupt_in_urb);
kfree(port->interrupt_in_buffer); kfree(port->interrupt_in_buffer);
} }
for (i = 0; i < num_interrupt_out; ++i) { for (i = 0; i < num_interrupt_out; ++i) {
port = serial->port[i]; port = serial->port[i];
if (!port) if (!port)
continue; continue;
if (port->interrupt_out_urb) usb_free_urb(port->interrupt_out_urb);
usb_free_urb (port->interrupt_out_urb);
kfree(port->interrupt_out_buffer); kfree(port->interrupt_out_buffer);
} }

View file

@ -0,0 +1,65 @@
/*
* USB Debug cable driver
*
* Copyright (C) 2006 Greg Kroah-Hartman <greg@kroah.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License version
* 2 as published by the Free Software Foundation.
*/
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/tty.h>
#include <linux/module.h>
#include <linux/usb.h>
#include <linux/usb/serial.h>
static struct usb_device_id id_table [] = {
{ USB_DEVICE(0x0525, 0x127a) },
{ },
};
MODULE_DEVICE_TABLE(usb, id_table);
static struct usb_driver debug_driver = {
.name = "debug",
.probe = usb_serial_probe,
.disconnect = usb_serial_disconnect,
.id_table = id_table,
.no_dynamic_id = 1,
};
static struct usb_serial_driver debug_device = {
.driver = {
.owner = THIS_MODULE,
.name = "debug",
},
.id_table = id_table,
.num_interrupt_in = NUM_DONT_CARE,
.num_bulk_in = NUM_DONT_CARE,
.num_bulk_out = NUM_DONT_CARE,
.num_ports = 1,
};
static int __init debug_init(void)
{
int retval;
retval = usb_serial_register(&debug_device);
if (retval)
return retval;
retval = usb_register(&debug_driver);
if (retval)
usb_serial_deregister(&debug_device);
return retval;
}
static void __exit debug_exit(void)
{
usb_deregister(&debug_driver);
usb_serial_deregister(&debug_device);
}
module_init(debug_init);
module_exit(debug_exit);
MODULE_LICENSE("GPL");

View file

@ -348,8 +348,7 @@ static void visor_close (struct usb_serial_port *port, struct file * filp)
/* shutdown our urbs */ /* shutdown our urbs */
usb_kill_urb(port->read_urb); usb_kill_urb(port->read_urb);
if (port->interrupt_in_urb) usb_kill_urb(port->interrupt_in_urb);
usb_kill_urb(port->interrupt_in_urb);
/* Try to send shutdown message, if the device is gone, this will just fail. */ /* Try to send shutdown message, if the device is gone, this will just fail. */
transfer_buffer = kmalloc (0x12, GFP_KERNEL); transfer_buffer = kmalloc (0x12, GFP_KERNEL);

View file

@ -142,10 +142,7 @@ int onetouch_connect_input(struct us_data *ss)
return -ENODEV; return -ENODEV;
endpoint = &interface->endpoint[2].desc; endpoint = &interface->endpoint[2].desc;
if (!(endpoint->bEndpointAddress & USB_DIR_IN)) if (!usb_endpoint_is_int_in(endpoint))
return -ENODEV;
if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
!= USB_ENDPOINT_XFER_INT)
return -ENODEV; return -ENODEV;
pipe = usb_rcvintpipe(udev, endpoint->bEndpointAddress); pipe = usb_rcvintpipe(udev, endpoint->bEndpointAddress);

View file

@ -1318,6 +1318,16 @@ UNUSUAL_DEV( 0x1019, 0x0c55, 0x0000, 0x0110,
US_SC_DEVICE, US_PR_DEVICE, usb_stor_ucr61s2b_init, US_SC_DEVICE, US_PR_DEVICE, usb_stor_ucr61s2b_init,
0 ), 0 ),
/* Reported by Jaco Kroon <jaco@kroon.co.za>
* The usb-storage module found on the Digitech GNX4 (and supposedly other
* devices) misbehaves and causes a bunch of invalid I/O errors.
*/
UNUSUAL_DEV( 0x1210, 0x0003, 0x0100, 0x0100,
"Digitech HMG",
"DigiTech Mass Storage",
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_IGNORE_RESIDUE ),
/* Reported by Vilius Bilinkevicius <vilisas AT xxx DOT lt) */ /* Reported by Vilius Bilinkevicius <vilisas AT xxx DOT lt) */
UNUSUAL_DEV( 0x132b, 0x000b, 0x0001, 0x0001, UNUSUAL_DEV( 0x132b, 0x000b, 0x0001, 0x0001,
"Minolta", "Minolta",

View file

@ -740,18 +740,16 @@ static int get_pipes(struct us_data *us)
ep = &altsetting->endpoint[i].desc; ep = &altsetting->endpoint[i].desc;
/* Is it a BULK endpoint? */ /* Is it a BULK endpoint? */
if ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) if (usb_endpoint_xfer_bulk(ep)) {
== USB_ENDPOINT_XFER_BULK) {
/* BULK in or out? */ /* BULK in or out? */
if (ep->bEndpointAddress & USB_DIR_IN) if (usb_endpoint_dir_in(ep))
ep_in = ep; ep_in = ep;
else else
ep_out = ep; ep_out = ep;
} }
/* Is it an interrupt endpoint? */ /* Is it an interrupt endpoint? */
else if ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) else if (usb_endpoint_xfer_int(ep)) {
== USB_ENDPOINT_XFER_INT) {
ep_int = ep; ep_int = ep;
} }
} }

View file

@ -313,8 +313,13 @@ struct usb_bus {
/* This is arbitrary. /* This is arbitrary.
* From USB 2.0 spec Table 11-13, offset 7, a hub can * From USB 2.0 spec Table 11-13, offset 7, a hub can
* have up to 255 ports. The most yet reported is 10. * have up to 255 ports. The most yet reported is 10.
*
* Current Wireless USB host hardware (Intel i1480 for example) allows
* up to 22 devices to connect. Upcoming hardware might raise that
* limit. Because the arrays need to add a bit for hub status data, we
* do 31, so plus one evens out to four bytes.
*/ */
#define USB_MAXCHILDREN (16) #define USB_MAXCHILDREN (31)
struct usb_tt; struct usb_tt;
@ -357,7 +362,8 @@ struct usb_device {
u8 portnum; /* Parent port number (origin 1) */ u8 portnum; /* Parent port number (origin 1) */
u8 level; /* Number of USB hub ancestors */ u8 level; /* Number of USB hub ancestors */
int have_langid; /* whether string_langid is valid */ unsigned discon_suspended:1; /* Disconnected while suspended */
unsigned have_langid:1; /* whether string_langid is valid */
int string_langid; /* language ID for strings */ int string_langid; /* language ID for strings */
/* static strings from the device */ /* static strings from the device */
@ -410,14 +416,37 @@ extern struct usb_device *usb_find_device(u16 vendor_id, u16 product_id);
/* USB autosuspend and autoresume */ /* USB autosuspend and autoresume */
#ifdef CONFIG_USB_SUSPEND #ifdef CONFIG_USB_SUSPEND
extern int usb_autopm_set_interface(struct usb_interface *intf);
extern int usb_autopm_get_interface(struct usb_interface *intf); extern int usb_autopm_get_interface(struct usb_interface *intf);
extern void usb_autopm_put_interface(struct usb_interface *intf); extern void usb_autopm_put_interface(struct usb_interface *intf);
#else static inline void usb_autopm_enable(struct usb_interface *intf)
#define usb_autopm_get_interface(intf) 0 {
#define usb_autopm_put_interface(intf) do {} while (0) intf->pm_usage_cnt = 0;
#endif usb_autopm_set_interface(intf);
}
static inline void usb_autopm_disable(struct usb_interface *intf)
{
intf->pm_usage_cnt = 1;
usb_autopm_set_interface(intf);
}
#else
static inline int usb_autopm_set_interface(struct usb_interface *intf)
{ return 0; }
static inline int usb_autopm_get_interface(struct usb_interface *intf)
{ return 0; }
static inline void usb_autopm_put_interface(struct usb_interface *intf)
{ }
static inline void usb_autopm_enable(struct usb_interface *intf)
{ }
static inline void usb_autopm_disable(struct usb_interface *intf)
{ }
#endif
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
@ -490,17 +519,137 @@ static inline int usb_make_path (struct usb_device *dev, char *buf,
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
extern int usb_endpoint_dir_in(const struct usb_endpoint_descriptor *epd); /**
extern int usb_endpoint_dir_out(const struct usb_endpoint_descriptor *epd); * usb_endpoint_dir_in - check if the endpoint has IN direction
extern int usb_endpoint_xfer_bulk(const struct usb_endpoint_descriptor *epd); * @epd: endpoint to be checked
extern int usb_endpoint_xfer_int(const struct usb_endpoint_descriptor *epd); *
extern int usb_endpoint_xfer_isoc(const struct usb_endpoint_descriptor *epd); * Returns true if the endpoint is of type IN, otherwise it returns false.
extern int usb_endpoint_is_bulk_in(const struct usb_endpoint_descriptor *epd); */
extern int usb_endpoint_is_bulk_out(const struct usb_endpoint_descriptor *epd); static inline int usb_endpoint_dir_in(const struct usb_endpoint_descriptor *epd)
extern int usb_endpoint_is_int_in(const struct usb_endpoint_descriptor *epd); {
extern int usb_endpoint_is_int_out(const struct usb_endpoint_descriptor *epd); return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN);
extern int usb_endpoint_is_isoc_in(const struct usb_endpoint_descriptor *epd); }
extern int usb_endpoint_is_isoc_out(const struct usb_endpoint_descriptor *epd);
/**
* usb_endpoint_dir_out - check if the endpoint has OUT direction
* @epd: endpoint to be checked
*
* Returns true if the endpoint is of type OUT, otherwise it returns false.
*/
static inline int usb_endpoint_dir_out(const struct usb_endpoint_descriptor *epd)
{
return ((epd->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT);
}
/**
* usb_endpoint_xfer_bulk - check if the endpoint has bulk transfer type
* @epd: endpoint to be checked
*
* Returns true if the endpoint is of type bulk, otherwise it returns false.
*/
static inline int usb_endpoint_xfer_bulk(const struct usb_endpoint_descriptor *epd)
{
return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
USB_ENDPOINT_XFER_BULK);
}
/**
* usb_endpoint_xfer_int - check if the endpoint has interrupt transfer type
* @epd: endpoint to be checked
*
* Returns true if the endpoint is of type interrupt, otherwise it returns
* false.
*/
static inline int usb_endpoint_xfer_int(const struct usb_endpoint_descriptor *epd)
{
return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
USB_ENDPOINT_XFER_INT);
}
/**
* usb_endpoint_xfer_isoc - check if the endpoint has isochronous transfer type
* @epd: endpoint to be checked
*
* Returns true if the endpoint is of type isochronous, otherwise it returns
* false.
*/
static inline int usb_endpoint_xfer_isoc(const struct usb_endpoint_descriptor *epd)
{
return ((epd->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
USB_ENDPOINT_XFER_ISOC);
}
/**
* usb_endpoint_is_bulk_in - check if the endpoint is bulk IN
* @epd: endpoint to be checked
*
* Returns true if the endpoint has bulk transfer type and IN direction,
* otherwise it returns false.
*/
static inline int usb_endpoint_is_bulk_in(const struct usb_endpoint_descriptor *epd)
{
return (usb_endpoint_xfer_bulk(epd) && usb_endpoint_dir_in(epd));
}
/**
* usb_endpoint_is_bulk_out - check if the endpoint is bulk OUT
* @epd: endpoint to be checked
*
* Returns true if the endpoint has bulk transfer type and OUT direction,
* otherwise it returns false.
*/
static inline int usb_endpoint_is_bulk_out(const struct usb_endpoint_descriptor *epd)
{
return (usb_endpoint_xfer_bulk(epd) && usb_endpoint_dir_out(epd));
}
/**
* usb_endpoint_is_int_in - check if the endpoint is interrupt IN
* @epd: endpoint to be checked
*
* Returns true if the endpoint has interrupt transfer type and IN direction,
* otherwise it returns false.
*/
static inline int usb_endpoint_is_int_in(const struct usb_endpoint_descriptor *epd)
{
return (usb_endpoint_xfer_int(epd) && usb_endpoint_dir_in(epd));
}
/**
* usb_endpoint_is_int_out - check if the endpoint is interrupt OUT
* @epd: endpoint to be checked
*
* Returns true if the endpoint has interrupt transfer type and OUT direction,
* otherwise it returns false.
*/
static inline int usb_endpoint_is_int_out(const struct usb_endpoint_descriptor *epd)
{
return (usb_endpoint_xfer_int(epd) && usb_endpoint_dir_out(epd));
}
/**
* usb_endpoint_is_isoc_in - check if the endpoint is isochronous IN
* @epd: endpoint to be checked
*
* Returns true if the endpoint has isochronous transfer type and IN direction,
* otherwise it returns false.
*/
static inline int usb_endpoint_is_isoc_in(const struct usb_endpoint_descriptor *epd)
{
return (usb_endpoint_xfer_isoc(epd) && usb_endpoint_dir_in(epd));
}
/**
* usb_endpoint_is_isoc_out - check if the endpoint is isochronous OUT
* @epd: endpoint to be checked
*
* Returns true if the endpoint has isochronous transfer type and OUT direction,
* otherwise it returns false.
*/
static inline int usb_endpoint_is_isoc_out(const struct usb_endpoint_descriptor *epd)
{
return (usb_endpoint_xfer_isoc(epd) && usb_endpoint_dir_out(epd));
}
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/

View file

@ -981,7 +981,7 @@ void snd_usbmidi_disconnect(struct list_head* p)
if (umidi->usb_protocol_ops->finish_out_endpoint) if (umidi->usb_protocol_ops->finish_out_endpoint)
umidi->usb_protocol_ops->finish_out_endpoint(ep->out); umidi->usb_protocol_ops->finish_out_endpoint(ep->out);
} }
if (ep->in && ep->in->urb) if (ep->in)
usb_kill_urb(ep->in->urb); usb_kill_urb(ep->in->urb);
} }
} }

View file

@ -1620,8 +1620,7 @@ static void snd_usb_mixer_free(struct usb_mixer_interface *mixer)
kfree(mixer->urb->transfer_buffer); kfree(mixer->urb->transfer_buffer);
usb_free_urb(mixer->urb); usb_free_urb(mixer->urb);
} }
if (mixer->rc_urb) usb_free_urb(mixer->rc_urb);
usb_free_urb(mixer->rc_urb);
kfree(mixer->rc_setup_packet); kfree(mixer->rc_setup_packet);
kfree(mixer); kfree(mixer);
} }
@ -2056,8 +2055,6 @@ void snd_usb_mixer_disconnect(struct list_head *p)
struct usb_mixer_interface *mixer; struct usb_mixer_interface *mixer;
mixer = list_entry(p, struct usb_mixer_interface, list); mixer = list_entry(p, struct usb_mixer_interface, list);
if (mixer->urb) usb_kill_urb(mixer->urb);
usb_kill_urb(mixer->urb); usb_kill_urb(mixer->rc_urb);
if (mixer->rc_urb)
usb_kill_urb(mixer->rc_urb);
} }