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:
commit
9641219825
@ -345,8 +345,7 @@ static inline void skel_delete (struct usb_skel *dev)
|
||||
usb_buffer_free (dev->udev, dev->bulk_out_size,
|
||||
dev->bulk_out_buffer,
|
||||
dev->write_urb->transfer_dma);
|
||||
if (dev->write_urb != NULL)
|
||||
usb_free_urb (dev->write_urb);
|
||||
usb_free_urb (dev->write_urb);
|
||||
kfree (dev);
|
||||
}
|
||||
</programlisting>
|
||||
|
@ -561,8 +561,7 @@ static struct notifier_block usb_pcwd_notifier = {
|
||||
*/
|
||||
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)
|
||||
usb_buffer_free(usb_pcwd->udev, usb_pcwd->intr_size,
|
||||
usb_pcwd->intr_buffer, usb_pcwd->intr_dma);
|
||||
|
@ -178,9 +178,9 @@ static int iforce_usb_probe(struct usb_interface *intf,
|
||||
|
||||
fail:
|
||||
if (iforce) {
|
||||
if (iforce->irq) usb_free_urb(iforce->irq);
|
||||
if (iforce->out) usb_free_urb(iforce->out);
|
||||
if (iforce->ctrl) usb_free_urb(iforce->ctrl);
|
||||
usb_free_urb(iforce->irq);
|
||||
usb_free_urb(iforce->out);
|
||||
usb_free_urb(iforce->ctrl);
|
||||
kfree(iforce);
|
||||
}
|
||||
|
||||
|
@ -815,14 +815,11 @@ static int gigaset_probe(struct usb_interface *interface,
|
||||
return 0;
|
||||
|
||||
error:
|
||||
if (ucs->read_urb)
|
||||
usb_kill_urb(ucs->read_urb);
|
||||
usb_kill_urb(ucs->read_urb);
|
||||
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);
|
||||
if (ucs->read_urb != NULL)
|
||||
usb_free_urb(ucs->read_urb);
|
||||
usb_free_urb(ucs->read_urb);
|
||||
usb_set_intfdata(interface, NULL);
|
||||
ucs->read_urb = ucs->bulk_out_urb = 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? */
|
||||
|
||||
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);
|
||||
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;
|
||||
cs->inbuf[0].rcvbuf = ucs->bulk_out_buffer = NULL;
|
||||
|
||||
|
@ -275,8 +275,7 @@ static void cinergyt2_free_stream_urbs (struct cinergyt2 *cinergyt2)
|
||||
int 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,
|
||||
cinergyt2->streambuf, cinergyt2->streambuf_dmahandle);
|
||||
@ -320,8 +319,7 @@ static void cinergyt2_stop_stream_xfer (struct cinergyt2 *cinergyt2)
|
||||
cinergyt2_control_stream_transfer(cinergyt2, 0);
|
||||
|
||||
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)
|
||||
|
@ -1135,8 +1135,7 @@ static void ttusb_dec_free_iso_urbs(struct ttusb_dec *dec)
|
||||
dprintk("%s\n", __FUNCTION__);
|
||||
|
||||
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,
|
||||
ISO_FRAME_SIZE * (FRAMES_PER_ISO_BUF *
|
||||
|
@ -1953,8 +1953,8 @@ struct pvr2_hdw *pvr2_hdw_create(struct usb_interface *intf,
|
||||
return hdw;
|
||||
fail:
|
||||
if (hdw) {
|
||||
if (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_read_urb);
|
||||
usb_free_urb(hdw->ctl_write_urb);
|
||||
if (hdw->ctl_read_buffer) kfree(hdw->ctl_read_buffer);
|
||||
if (hdw->ctl_write_buffer) kfree(hdw->ctl_write_buffer);
|
||||
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;
|
||||
if (hdw->ctl_write_pend_flag || hdw->ctl_read_pend_flag) {
|
||||
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);
|
||||
}
|
||||
if (hdw->ctl_read_pend_flag && hdw->ctl_read_urb) {
|
||||
if (hdw->ctl_read_pend_flag)
|
||||
usb_unlink_urb(hdw->ctl_read_urb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -289,7 +289,7 @@ static void pvr2_buffer_done(struct pvr2_buffer *bp)
|
||||
pvr2_buffer_set_none(bp);
|
||||
bp->signature = 0;
|
||||
bp->stream = NULL;
|
||||
if (bp->purb) usb_free_urb(bp->purb);
|
||||
usb_free_urb(bp->purb);
|
||||
pvr2_trace(PVR2_TRACE_BUF_POOL,"/*---TRACE_FLOW---*/"
|
||||
" bufferDone %p",bp);
|
||||
}
|
||||
|
@ -866,11 +866,9 @@ int pwc_isoc_init(struct pwc_device *pdev)
|
||||
}
|
||||
if (ret) {
|
||||
/* De-allocate in reverse order */
|
||||
while (i >= 0) {
|
||||
if (pdev->sbuf[i].urb != NULL)
|
||||
usb_free_urb(pdev->sbuf[i].urb);
|
||||
while (i--) {
|
||||
usb_free_urb(pdev->sbuf[i].urb);
|
||||
pdev->sbuf[i].urb = NULL;
|
||||
i--;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
@ -775,7 +775,7 @@ static int sn9c102_start_transfer(struct sn9c102_device* cam)
|
||||
return 0;
|
||||
|
||||
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]);
|
||||
|
||||
free_buffers:
|
||||
|
@ -190,8 +190,7 @@ static int qcm_alloc_int_urb(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 */
|
||||
|
||||
|
@ -489,7 +489,7 @@ static int zc0301_start_transfer(struct zc0301_device* cam)
|
||||
return 0;
|
||||
|
||||
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]);
|
||||
|
||||
free_buffers:
|
||||
|
@ -1793,10 +1793,8 @@ err_out_3:
|
||||
err_out_2:
|
||||
usb_free_urb(self->tx_urb);
|
||||
err_out_1:
|
||||
for (i = 0; i < self->max_rx_urb; i++) {
|
||||
if (self->rx_urb[i])
|
||||
usb_free_urb(self->rx_urb[i]);
|
||||
}
|
||||
for (i = 0; i < self->max_rx_urb; i++)
|
||||
usb_free_urb(self->rx_urb[i]);
|
||||
free_netdev(net);
|
||||
err_out:
|
||||
return ret;
|
||||
|
@ -1828,10 +1828,8 @@ err_start:
|
||||
/* Leave the device in reset state */
|
||||
zd1201_docmd(zd, ZD1201_CMDCODE_INIT, 0, 0, 0);
|
||||
err_zd:
|
||||
if (zd->tx_urb)
|
||||
usb_free_urb(zd->tx_urb);
|
||||
if (zd->rx_urb)
|
||||
usb_free_urb(zd->rx_urb);
|
||||
usb_free_urb(zd->tx_urb);
|
||||
usb_free_urb(zd->rx_urb);
|
||||
kfree(zd);
|
||||
return err;
|
||||
}
|
||||
|
@ -834,8 +834,8 @@ static int speedtch_bind(struct usbatm_data *usbatm,
|
||||
const struct usb_endpoint_descriptor *endpoint_desc = &desc->endpoint[i].desc;
|
||||
|
||||
if ((endpoint_desc->bEndpointAddress == target_address)) {
|
||||
use_isoc = (endpoint_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
|
||||
USB_ENDPOINT_XFER_ISOC;
|
||||
use_isoc =
|
||||
usb_endpoint_xfer_isoc(endpoint_desc);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -401,9 +401,8 @@ static int uea_send_modem_cmd(struct usb_device *usb,
|
||||
int ret = -ENOMEM;
|
||||
u8 *xfer_buff;
|
||||
|
||||
xfer_buff = kmalloc(size, GFP_KERNEL);
|
||||
xfer_buff = kmemdup(buff, size, GFP_KERNEL);
|
||||
if (xfer_buff) {
|
||||
memcpy(xfer_buff, buff, size);
|
||||
ret = usb_control_msg(usb,
|
||||
usb_sndctrlpipe(usb, 0),
|
||||
LOAD_INTERNAL,
|
||||
@ -595,14 +594,12 @@ static int uea_idma_write(struct uea_softc *sc, void *data, u32 size)
|
||||
u8 *xfer_buff;
|
||||
int bytes_read;
|
||||
|
||||
xfer_buff = kmalloc(size, GFP_KERNEL);
|
||||
xfer_buff = kmemdup(data, size, GFP_KERNEL);
|
||||
if (!xfer_buff) {
|
||||
uea_err(INS_TO_USBDEV(sc), "can't allocate xfer_buff\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
memcpy(xfer_buff, data, size);
|
||||
|
||||
ret = usb_bulk_msg(sc->usb_dev,
|
||||
usb_sndbulkpipe(sc->usb_dev, UEA_IDMA_PIPE),
|
||||
xfer_buff, size, &bytes_read, BULK_TIMEOUT);
|
||||
@ -765,12 +762,11 @@ static int uea_request(struct uea_softc *sc,
|
||||
u8 *xfer_buff;
|
||||
int ret = -ENOMEM;
|
||||
|
||||
xfer_buff = kmalloc(size, GFP_KERNEL);
|
||||
xfer_buff = kmemdup(data, size, GFP_KERNEL);
|
||||
if (!xfer_buff) {
|
||||
uea_err(INS_TO_USBDEV(sc), "can't allocate xfer_buff\n");
|
||||
return ret;
|
||||
}
|
||||
memcpy(xfer_buff, data, size);
|
||||
|
||||
ret = usb_control_msg(sc->usb_dev, usb_sndctrlpipe(sc->usb_dev, 0),
|
||||
UCDC_SEND_ENCAPSULATED_COMMAND,
|
||||
|
@ -892,7 +892,7 @@ skip_normal_probe:
|
||||
|
||||
|
||||
/* workaround for switched endpoints */
|
||||
if ((epread->bEndpointAddress & USB_DIR_IN) != USB_DIR_IN) {
|
||||
if (!usb_endpoint_dir_in(epread)) {
|
||||
/* descriptors are swapped */
|
||||
struct usb_endpoint_descriptor *t;
|
||||
dev_dbg(&intf->dev,"The data interface has switched endpoints");
|
||||
|
@ -72,6 +72,21 @@ config USB_SUSPEND
|
||||
|
||||
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
|
||||
bool
|
||||
|
@ -175,12 +175,13 @@ static char *usb_dump_endpoint_descriptor (
|
||||
)
|
||||
{
|
||||
char dir, unit, *type;
|
||||
unsigned interval, in, bandwidth = 1;
|
||||
unsigned interval, bandwidth = 1;
|
||||
|
||||
if (start > end)
|
||||
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) {
|
||||
switch (le16_to_cpu(desc->wMaxPacketSize) & (0x03 << 11)) {
|
||||
case 1 << 11: bandwidth = 2; break;
|
||||
@ -204,7 +205,7 @@ static char *usb_dump_endpoint_descriptor (
|
||||
break;
|
||||
case USB_ENDPOINT_XFER_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;
|
||||
else
|
||||
interval = 0;
|
||||
|
@ -561,7 +561,7 @@ static int usbdev_open(struct inode *inode, struct file *file)
|
||||
dev = inode->i_private;
|
||||
if (!dev)
|
||||
goto out;
|
||||
ret = usb_autoresume_device(dev, 1);
|
||||
ret = usb_autoresume_device(dev);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
@ -609,7 +609,7 @@ static int usbdev_release(struct inode *inode, struct file *file)
|
||||
releaseintf(ps, ifnum);
|
||||
}
|
||||
destroy_all_async(ps);
|
||||
usb_autosuspend_device(dev, 1);
|
||||
usb_autosuspend_device(dev);
|
||||
usb_unlock_device(dev);
|
||||
usb_put_dev(dev);
|
||||
put_pid(ps->disc_pid);
|
||||
|
@ -205,7 +205,7 @@ static int usb_probe_interface(struct device *dev)
|
||||
if (id) {
|
||||
dev_dbg(dev, "%s - got id\n", __FUNCTION__);
|
||||
|
||||
error = usb_autoresume_device(udev, 1);
|
||||
error = usb_autoresume_device(udev);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
@ -229,7 +229,7 @@ static int usb_probe_interface(struct device *dev)
|
||||
} else
|
||||
intf->condition = USB_INTERFACE_BOUND;
|
||||
|
||||
usb_autosuspend_device(udev, 1);
|
||||
usb_autosuspend_device(udev);
|
||||
}
|
||||
|
||||
return error;
|
||||
@ -247,7 +247,7 @@ static int usb_unbind_interface(struct device *dev)
|
||||
|
||||
/* Autoresume for set_interface call below */
|
||||
udev = interface_to_usbdev(intf);
|
||||
error = usb_autoresume_device(udev, 1);
|
||||
error = usb_autoresume_device(udev);
|
||||
|
||||
/* release all urbs for this interface */
|
||||
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;
|
||||
|
||||
if (!error)
|
||||
usb_autosuspend_device(udev, 1);
|
||||
usb_autosuspend_device(udev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -408,6 +408,16 @@ static int usb_match_one_id(struct usb_interface *interface,
|
||||
(id->bDeviceProtocol != dev->descriptor.bDeviceProtocol))
|
||||
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) &&
|
||||
(id->bInterfaceClass != intf->desc.bInterfaceClass))
|
||||
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
|
||||
* multiple-function device. Use the USB_INTERFACE_INFO
|
||||
* 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
|
||||
* 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);
|
||||
|
||||
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 */
|
||||
if (is_usb_device(dev)) {
|
||||
@ -790,7 +810,7 @@ EXPORT_SYMBOL_GPL_FUTURE(usb_deregister);
|
||||
#ifdef CONFIG_PM
|
||||
|
||||
/* 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;
|
||||
int status = 0;
|
||||
@ -817,7 +837,7 @@ done:
|
||||
}
|
||||
|
||||
/* 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;
|
||||
int status = 0;
|
||||
@ -843,7 +863,7 @@ done:
|
||||
}
|
||||
|
||||
/* 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;
|
||||
int status = 0;
|
||||
@ -880,7 +900,7 @@ done:
|
||||
}
|
||||
|
||||
/* 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;
|
||||
int status = 0;
|
||||
@ -920,6 +940,44 @@ done:
|
||||
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
|
||||
* @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);
|
||||
|
||||
/* 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->pm_usage_cnt > 0)
|
||||
return -EBUSY;
|
||||
if (udev->actconfig) {
|
||||
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;
|
||||
}
|
||||
status = autosuspend_check(udev);
|
||||
if (status < 0)
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Suspend all the interfaces and then udev itself */
|
||||
if (udev->actconfig) {
|
||||
for (; i < udev->actconfig->desc.bNumInterfaces; i++) {
|
||||
intf = udev->actconfig->interface[i];
|
||||
status = suspend_interface(intf, msg);
|
||||
status = usb_suspend_interface(intf, msg);
|
||||
if (status != 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
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 (status != 0) {
|
||||
while (--i >= 0) {
|
||||
intf = udev->actconfig->interface[i];
|
||||
resume_interface(intf);
|
||||
usb_resume_interface(intf);
|
||||
}
|
||||
|
||||
/* If the suspend succeeded, propagate it up the tree */
|
||||
} else if (parent)
|
||||
usb_autosuspend_device(parent, 0);
|
||||
usb_autosuspend_device(parent);
|
||||
|
||||
// dev_dbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status);
|
||||
return status;
|
||||
@ -1064,9 +1104,25 @@ int usb_resume_both(struct usb_device *udev)
|
||||
/* Propagate the resume up the tree, if necessary */
|
||||
if (udev->state == USB_STATE_SUSPENDED) {
|
||||
if (parent) {
|
||||
usb_pm_lock(parent);
|
||||
parent->auto_pm = 1;
|
||||
status = usb_resume_both(parent);
|
||||
status = usb_autoresume_device(parent);
|
||||
if (status == 0) {
|
||||
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 {
|
||||
|
||||
/* 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 !=
|
||||
PM_EVENT_ON)
|
||||
status = -EHOSTUNREACH;
|
||||
}
|
||||
if (status == 0)
|
||||
status = resume_device(udev);
|
||||
if (parent)
|
||||
usb_pm_unlock(parent);
|
||||
else
|
||||
status = usb_resume_device(udev);
|
||||
}
|
||||
} else {
|
||||
|
||||
/* Needed only for setting udev->dev.power.power_state.event
|
||||
* 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) {
|
||||
for (i = 0; i < udev->actconfig->desc.bNumInterfaces; 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
|
||||
|
||||
/* 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
|
||||
* @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
|
||||
* @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.
|
||||
*
|
||||
* @dec_usage_cnt should be 1 if the subsystem previously incremented
|
||||
* @udev's usage counter (such as by passing 1 to usb_autoresume_device);
|
||||
* otherwise it should be 0.
|
||||
*
|
||||
* If the usage counter for @udev or any of its active interfaces is greater
|
||||
* than 0, the autosuspend request will not be queued. (If an interface
|
||||
* 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.
|
||||
* @udev's usage counter is decremented. If it or any of the usage counters
|
||||
* for an active interface is greater than 0, no autosuspend request will be
|
||||
* queued. (If an interface driver does not support autosuspend then its
|
||||
* usage counter is permanently positive.) Furthermore, 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
|
||||
* necessary.
|
||||
*
|
||||
* 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);
|
||||
udev->pm_usage_cnt -= dec_usage_cnt;
|
||||
if (udev->pm_usage_cnt <= 0)
|
||||
queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend,
|
||||
USB_AUTOSUSPEND_DELAY);
|
||||
usb_pm_unlock(udev);
|
||||
int status;
|
||||
|
||||
status = usb_autopm_do_device(udev, -1);
|
||||
// dev_dbg(&udev->dev, "%s: cnt %d\n",
|
||||
// __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
|
||||
* @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
|
||||
* and needs to guarantee that it is not suspended. In addition, the
|
||||
* caller can prevent @udev from being autosuspended subsequently. (Note
|
||||
* that this will not prevent suspend events originating in the PM core.)
|
||||
* Examples would be when @udev's device file in usbfs is opened (autosuspend
|
||||
* should be prevented until the file is closed) or when a remote-wakeup
|
||||
* request is received (later autosuspends should not be prevented).
|
||||
* and needs to guarantee that it is not suspended. No autosuspend will
|
||||
* occur until usb_autosuspend_device is called. (Note that this will not
|
||||
* prevent suspend events originating in the PM core.) Examples would be
|
||||
* when @udev's device file in usbfs is opened or when a remote-wakeup
|
||||
* request is received.
|
||||
*
|
||||
* @inc_usage_cnt should be 1 to increment @udev's usage counter and prevent
|
||||
* autosuspends. This prevention will persist until the usage counter is
|
||||
* 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.
|
||||
* @udev's usage counter is incremented to prevent subsequent autosuspends.
|
||||
* However if the autoresume fails then the usage counter is re-decremented.
|
||||
*
|
||||
* Often the caller will hold @udev's device lock, but this is not
|
||||
* necessary (and attempting it might cause deadlock).
|
||||
*
|
||||
* 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;
|
||||
|
||||
usb_pm_lock(udev);
|
||||
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);
|
||||
status = usb_autopm_do_device(udev, 1);
|
||||
// dev_dbg(&udev->dev, "%s: status %d cnt %d\n",
|
||||
// __FUNCTION__, status, udev->pm_usage_cnt);
|
||||
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
|
||||
* @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)
|
||||
{
|
||||
struct usb_device *udev = interface_to_usbdev(intf);
|
||||
int status;
|
||||
|
||||
usb_pm_lock(udev);
|
||||
if (intf->condition != USB_INTERFACE_UNBOUND &&
|
||||
--intf->pm_usage_cnt <= 0) {
|
||||
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);
|
||||
status = usb_autopm_do_interface(intf, -1);
|
||||
// dev_dbg(&intf->dev, "%s: status %d cnt %d\n",
|
||||
// __FUNCTION__, status, intf->pm_usage_cnt);
|
||||
}
|
||||
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)
|
||||
{
|
||||
struct usb_device *udev = interface_to_usbdev(intf);
|
||||
int status;
|
||||
int status;
|
||||
|
||||
usb_pm_lock(udev);
|
||||
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);
|
||||
status = usb_autopm_do_interface(intf, 1);
|
||||
// dev_dbg(&intf->dev, "%s: status %d cnt %d\n",
|
||||
// __FUNCTION__, status, intf->pm_usage_cnt);
|
||||
return status;
|
||||
}
|
||||
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 */
|
||||
|
||||
static int usb_suspend(struct device *dev, pm_message_t message)
|
||||
|
@ -10,15 +10,20 @@
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/idr.h>
|
||||
#include <linux/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 usb_endpoint_descriptor *desc;
|
||||
struct usb_device *udev;
|
||||
struct device dev;
|
||||
int minor;
|
||||
};
|
||||
#define to_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,
|
||||
};
|
||||
|
||||
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 {
|
||||
struct kref kref;
|
||||
struct class *class;
|
||||
@ -176,11 +230,20 @@ static int init_endpoint_class(void)
|
||||
ep_class->class = class_create(THIS_MODULE, "usb_endpoint");
|
||||
if (IS_ERR(ep_class->class)) {
|
||||
result = IS_ERR(ep_class->class);
|
||||
kfree(ep_class);
|
||||
ep_class = NULL;
|
||||
goto exit;
|
||||
goto class_create_error;
|
||||
}
|
||||
|
||||
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:
|
||||
return result;
|
||||
}
|
||||
@ -191,6 +254,7 @@ static void release_endpoint_class(struct kref *kref)
|
||||
class_destroy(ep_class->class);
|
||||
kfree(ep_class);
|
||||
ep_class = NULL;
|
||||
usb_endpoint_major_cleanup();
|
||||
}
|
||||
|
||||
static void destroy_endpoint_class(void)
|
||||
@ -213,7 +277,6 @@ int usb_create_ep_files(struct device *parent,
|
||||
{
|
||||
char name[8];
|
||||
struct ep_device *ep_dev;
|
||||
int minor;
|
||||
int retval;
|
||||
|
||||
retval = init_endpoint_class();
|
||||
@ -226,12 +289,16 @@ int usb_create_ep_files(struct device *parent,
|
||||
goto error_alloc;
|
||||
}
|
||||
|
||||
/* fun calculation to determine the minor of this endpoint */
|
||||
minor = (((udev->bus->busnum - 1) * 128) * 16) + (udev->devnum - 1);
|
||||
retval = endpoint_get_minor(ep_dev);
|
||||
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->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.parent = parent;
|
||||
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);
|
||||
if (retval)
|
||||
goto error_register;
|
||||
goto error_chrdev;
|
||||
retval = sysfs_create_group(&ep_dev->dev.kobj, &ep_dev_attr_grp);
|
||||
if (retval)
|
||||
goto error_group;
|
||||
@ -261,6 +328,9 @@ error_group:
|
||||
destroy_endpoint_class();
|
||||
return retval;
|
||||
|
||||
error_chrdev:
|
||||
endpoint_free_minor(ep_dev);
|
||||
|
||||
error_register:
|
||||
kfree(ep_dev);
|
||||
error_alloc:
|
||||
@ -271,14 +341,16 @@ exit:
|
||||
|
||||
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];
|
||||
|
||||
sprintf(name, "ep_%02x", endpoint->desc.bEndpointAddress);
|
||||
sysfs_remove_link(&endpoint->ep_dev->dev.parent->kobj, name);
|
||||
sysfs_remove_group(&endpoint->ep_dev->dev.kobj, &ep_dev_attr_grp);
|
||||
device_unregister(&endpoint->ep_dev->dev);
|
||||
sysfs_remove_link(&ep_dev->dev.parent->kobj, name);
|
||||
sysfs_remove_group(&ep_dev->dev.kobj, &ep_dev_attr_grp);
|
||||
endpoint_free_minor(ep_dev);
|
||||
device_unregister(&ep_dev->dev);
|
||||
endpoint->ep_dev = NULL;
|
||||
destroy_endpoint_class();
|
||||
}
|
||||
|
@ -256,7 +256,9 @@ static const u8 hs_rh_config_descriptor [] = {
|
||||
0x05, /* __u8 ep_bDescriptorType; Endpoint */
|
||||
0x81, /* __u8 ep_bEndpointAddress; IN Endpoint 1 */
|
||||
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) */
|
||||
};
|
||||
|
||||
|
@ -31,6 +31,47 @@
|
||||
#include "hcd.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
|
||||
* Note: Both are also protected by ->dev.sem, except that ->state can
|
||||
* 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;
|
||||
|
||||
/* 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 */
|
||||
static int blinkenlights = 0;
|
||||
module_param (blinkenlights, bool, S_IRUGO);
|
||||
@ -276,6 +327,9 @@ static void kick_khubd(struct usb_hub *hub)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
/* Suppress autosuspend until khubd runs */
|
||||
to_usb_interface(hub->intfdev)->pm_usage_cnt = 1;
|
||||
|
||||
spin_lock_irqsave(&hub_event_lock, flags);
|
||||
if (list_empty(&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 */
|
||||
hub->quiescing = 1;
|
||||
hub->activating = 0;
|
||||
hub->resume_root_hub = 0;
|
||||
|
||||
/* (blocking) stop khubd and related activity */
|
||||
usb_kill_urb(hub->urb);
|
||||
@ -473,7 +526,7 @@ static void hub_activate(struct usb_hub *hub)
|
||||
|
||||
hub->quiescing = 0;
|
||||
hub->activating = 1;
|
||||
hub->resume_root_hub = 0;
|
||||
|
||||
status = usb_submit_urb(hub->urb, GFP_NOIO);
|
||||
if (status < 0)
|
||||
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",
|
||||
(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);
|
||||
maxp = usb_maxpacket(hdev, pipe, usb_pipeout(pipe));
|
||||
|
||||
@ -883,6 +941,7 @@ descriptor_error:
|
||||
INIT_WORK(&hub->leds, led_work, hub);
|
||||
|
||||
usb_set_intfdata (intf, hub);
|
||||
intf->needs_remote_wakeup = 1;
|
||||
|
||||
if (hdev->speed == USB_SPEED_HIGH)
|
||||
highspeed_hubs++;
|
||||
@ -980,6 +1039,8 @@ static void recursively_mark_NOTATTACHED(struct usb_device *udev)
|
||||
if (udev->children[i])
|
||||
recursively_mark_NOTATTACHED(udev->children[i]);
|
||||
}
|
||||
if (udev->state == USB_STATE_SUSPENDED)
|
||||
udev->discon_suspended = 1;
|
||||
udev->state = USB_STATE_NOTATTACHED;
|
||||
}
|
||||
|
||||
@ -1169,6 +1230,14 @@ void usb_disconnect(struct usb_device **pdev)
|
||||
*pdev = NULL;
|
||||
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);
|
||||
}
|
||||
|
||||
@ -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);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* 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)
|
||||
static int __usb_new_device(void *void_data)
|
||||
{
|
||||
struct usb_device *udev = void_data;
|
||||
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);
|
||||
if (err < 0) {
|
||||
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;
|
||||
}
|
||||
|
||||
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:
|
||||
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,
|
||||
u16 *status, u16 *change)
|
||||
@ -1323,10 +1423,12 @@ static int hub_port_status(struct usb_hub *hub, int port1,
|
||||
int ret;
|
||||
|
||||
ret = get_port_status(hub->hdev, port1, &hub->status->port);
|
||||
if (ret < 0)
|
||||
if (ret < 4) {
|
||||
dev_err (hub->intfdev,
|
||||
"%s failed (err = %d)\n", __FUNCTION__, ret);
|
||||
else {
|
||||
if (ret >= 0)
|
||||
ret = -EIO;
|
||||
} else {
|
||||
*status = le16_to_cpu(hub->status->port.wPortStatus);
|
||||
*change = le16_to_cpu(hub->status->port.wPortChange);
|
||||
ret = 0;
|
||||
@ -1674,6 +1776,12 @@ static int
|
||||
hub_port_resume(struct usb_hub *hub, int port1, struct usb_device *udev)
|
||||
{
|
||||
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);
|
||||
|
||||
@ -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",
|
||||
port1, status);
|
||||
} else {
|
||||
u16 devstatus;
|
||||
u16 portchange;
|
||||
|
||||
/* drive resume for at least 20 msec */
|
||||
if (udev)
|
||||
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
|
||||
* sequence.
|
||||
*/
|
||||
devstatus = portchange = 0;
|
||||
status = hub_port_status(hub, port1,
|
||||
&devstatus, &portchange);
|
||||
status = hub_port_status(hub, port1, &portstatus, &portchange);
|
||||
SuspendCleared:
|
||||
if (status < 0
|
||||
|| (devstatus & LIVE_FLAGS) != LIVE_FLAGS
|
||||
|| (devstatus & USB_PORT_STAT_SUSPEND) != 0
|
||||
|| (portstatus & LIVE_FLAGS) != LIVE_FLAGS
|
||||
|| (portstatus & USB_PORT_STAT_SUSPEND) != 0
|
||||
) {
|
||||
dev_dbg(hub->intfdev,
|
||||
"port %d status %04x.%04x after resume, %d\n",
|
||||
port1, portchange, devstatus, status);
|
||||
port1, portchange, portstatus, status);
|
||||
if (status >= 0)
|
||||
status = -ENODEV;
|
||||
} else {
|
||||
@ -1774,23 +1878,16 @@ static int remote_wakeup(struct usb_device *udev)
|
||||
{
|
||||
int status = 0;
|
||||
|
||||
/* All this just to avoid sending a port-resume message
|
||||
* to the parent hub! */
|
||||
|
||||
usb_lock_device(udev);
|
||||
usb_pm_lock(udev);
|
||||
if (udev->state == USB_STATE_SUSPENDED) {
|
||||
dev_dbg(&udev->dev, "usb %sresume\n", "wakeup-");
|
||||
/* TRSMRCY = 10 msec */
|
||||
msleep(10);
|
||||
status = finish_port_resume(udev);
|
||||
if (status == 0)
|
||||
udev->dev.power.power_state.event = PM_EVENT_ON;
|
||||
}
|
||||
usb_pm_unlock(udev);
|
||||
status = usb_autoresume_device(udev);
|
||||
|
||||
if (status == 0)
|
||||
usb_autoresume_device(udev, 0);
|
||||
/* Give the interface drivers a chance to do something,
|
||||
* then autosuspend the device again. */
|
||||
if (status == 0)
|
||||
usb_autosuspend_device(udev);
|
||||
}
|
||||
usb_unlock_device(udev);
|
||||
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 */
|
||||
if (!hdev->parent) {
|
||||
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)
|
||||
{
|
||||
struct usb_device *hdev = interface_to_usbdev(intf);
|
||||
struct usb_hub *hub = usb_get_intfdata (intf);
|
||||
struct usb_device *hdev = hub->hdev;
|
||||
int status;
|
||||
|
||||
dev_dbg(&intf->dev, "%s\n", __FUNCTION__);
|
||||
|
||||
/* "global resume" of the downstream HC-to-USB interface */
|
||||
if (!hdev->parent) {
|
||||
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);
|
||||
|
||||
hub->resume_root_hub = 1;
|
||||
kick_khubd(hub);
|
||||
}
|
||||
|
||||
@ -2555,16 +2655,13 @@ static void hub_events(void)
|
||||
intf = to_usb_interface(hub->intfdev);
|
||||
hub_dev = &intf->dev;
|
||||
|
||||
i = hub->resume_root_hub;
|
||||
|
||||
dev_dbg(hub_dev, "state %d ports %d chg %04x evt %04x%s\n",
|
||||
dev_dbg(hub_dev, "state %d ports %d chg %04x evt %04x\n",
|
||||
hdev->state, hub->descriptor
|
||||
? hub->descriptor->bNbrPorts
|
||||
: 0,
|
||||
/* NOTE: expects max 15 ports... */
|
||||
(u16) hub->change_bits[0],
|
||||
(u16) hub->event_bits[0],
|
||||
i ? ", resume root" : "");
|
||||
(u16) hub->event_bits[0]);
|
||||
|
||||
usb_get_intf(intf);
|
||||
spin_unlock_irq(&hub_event_lock);
|
||||
@ -2585,16 +2682,16 @@ static void hub_events(void)
|
||||
goto loop;
|
||||
}
|
||||
|
||||
/* Is this is a root hub wanting to reactivate the downstream
|
||||
* ports? If so, be sure the interface resumes even if its
|
||||
* stub "device" node was never suspended.
|
||||
*/
|
||||
if (i)
|
||||
usb_autoresume_device(hdev, 0);
|
||||
|
||||
/* If this is an inactive or suspended hub, do nothing */
|
||||
if (hub->quiescing)
|
||||
/* Autoresume */
|
||||
ret = usb_autopm_get_interface(intf);
|
||||
if (ret) {
|
||||
dev_dbg(hub_dev, "Can't autoresume: %d\n", ret);
|
||||
goto loop;
|
||||
}
|
||||
|
||||
/* If this is an inactive hub, do nothing */
|
||||
if (hub->quiescing)
|
||||
goto loop_autopm;
|
||||
|
||||
if (hub->error) {
|
||||
dev_dbg (hub_dev, "resetting for error %d\n",
|
||||
@ -2604,7 +2701,7 @@ static void hub_events(void)
|
||||
if (ret) {
|
||||
dev_dbg (hub_dev,
|
||||
"error resetting hub: %d\n", ret);
|
||||
goto loop;
|
||||
goto loop_autopm;
|
||||
}
|
||||
|
||||
hub->nerrors = 0;
|
||||
@ -2732,6 +2829,10 @@ static void hub_events(void)
|
||||
if (!hdev->parent && !hub->busy_bits[0])
|
||||
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:
|
||||
usb_unlock_device(hdev);
|
||||
usb_put_intf(intf);
|
||||
@ -2773,6 +2874,7 @@ static struct usb_driver hub_driver = {
|
||||
.post_reset = hub_post_reset,
|
||||
.ioctl = hub_ioctl,
|
||||
.id_table = hub_id_table,
|
||||
.supports_autosuspend = 1,
|
||||
};
|
||||
|
||||
int usb_hub_init(void)
|
||||
@ -2997,7 +3099,7 @@ int usb_reset_composite_device(struct usb_device *udev,
|
||||
}
|
||||
|
||||
/* Prevent autosuspend during the reset */
|
||||
usb_autoresume_device(udev, 1);
|
||||
usb_autoresume_device(udev);
|
||||
|
||||
if (iface && iface->condition != USB_INTERFACE_BINDING)
|
||||
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;
|
||||
}
|
||||
EXPORT_SYMBOL(usb_reset_composite_device);
|
||||
|
@ -192,45 +192,4 @@ struct usb_tt_clear {
|
||||
|
||||
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 */
|
||||
|
@ -764,7 +764,7 @@ int usb_string(struct usb_device *dev, int index, char *buf, size_t size)
|
||||
err = -EINVAL;
|
||||
goto errout;
|
||||
} else {
|
||||
dev->have_langid = -1;
|
||||
dev->have_langid = 1;
|
||||
dev->string_langid = tbuf[2] | (tbuf[3]<< 8);
|
||||
/* always use the first langid listed */
|
||||
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 */
|
||||
ret = usb_autoresume_device(dev, 1);
|
||||
ret = usb_autoresume_device(dev);
|
||||
if (ret)
|
||||
goto free_interfaces;
|
||||
|
||||
@ -1421,7 +1421,7 @@ free_interfaces:
|
||||
dev->actconfig = cp;
|
||||
if (!cp) {
|
||||
usb_set_device_state(dev, USB_STATE_ADDRESS);
|
||||
usb_autosuspend_device(dev, 1);
|
||||
usb_autosuspend_device(dev);
|
||||
goto free_interfaces;
|
||||
}
|
||||
usb_set_device_state(dev, USB_STATE_CONFIGURED);
|
||||
@ -1490,7 +1490,7 @@ free_interfaces:
|
||||
usb_create_sysfs_intf_files (intf);
|
||||
}
|
||||
|
||||
usb_autosuspend_device(dev, 1);
|
||||
usb_autosuspend_device(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -200,13 +200,6 @@ static void ksuspend_usb_cleanup(void)
|
||||
destroy_workqueue(ksuspend_usb_wq);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#define ksuspend_usb_init() 0
|
||||
#define ksuspend_usb_cleanup() do {} while (0)
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_USB_SUSPEND
|
||||
|
||||
/* 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)
|
||||
{}
|
||||
|
||||
#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)
|
||||
@ -537,138 +537,6 @@ int usb_get_current_frame_number(struct usb_device *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
|
||||
@ -1102,18 +970,6 @@ EXPORT_SYMBOL(__usb_get_extra_descriptor);
|
||||
EXPORT_SYMBOL(usb_find_device);
|
||||
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_free);
|
||||
|
||||
|
@ -64,14 +64,13 @@ static inline void usb_pm_unlock(struct usb_device *udev) {}
|
||||
|
||||
#define USB_AUTOSUSPEND_DELAY (HZ*2)
|
||||
|
||||
extern void usb_autosuspend_device(struct usb_device *udev, int dec_busy_cnt);
|
||||
extern int usb_autoresume_device(struct usb_device *udev, int inc_busy_cnt);
|
||||
extern void usb_autosuspend_device(struct usb_device *udev);
|
||||
extern int usb_autoresume_device(struct usb_device *udev);
|
||||
|
||||
#else
|
||||
|
||||
#define usb_autosuspend_device(udev, dec_busy_cnt) do {} while (0)
|
||||
static inline int usb_autoresume_device(struct usb_device *udev,
|
||||
int inc_busy_cnt)
|
||||
#define usb_autosuspend_device(udev) do {} while (0)
|
||||
static inline int usb_autoresume_device(struct usb_device *udev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
@ -1894,13 +1894,13 @@ static int eth_start_xmit (struct sk_buff *skb, struct net_device *net)
|
||||
if (!eth_is_promisc (dev)) {
|
||||
u8 *dest = skb->data;
|
||||
|
||||
if (dest [0] & 0x01) {
|
||||
if (is_multicast_ether_addr(dest)) {
|
||||
u16 type;
|
||||
|
||||
/* ignores USB_CDC_PACKET_TYPE_MULTICAST and host
|
||||
* 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;
|
||||
else
|
||||
type = USB_CDC_PACKET_TYPE_ALL_MULTICAST;
|
||||
|
@ -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_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 void lh7a40x_fifo_flush(struct usb_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);
|
||||
|
@ -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. */
|
||||
|
||||
ep->responded = 1;
|
||||
if (req)
|
||||
list_add_tail (&req->queue, &ep->queue);
|
||||
done:
|
||||
@ -2188,7 +2189,8 @@ static void handle_ep_small (struct net2280_ep *ep)
|
||||
ep->stopped = 1;
|
||||
set_halt (ep);
|
||||
mode = 2;
|
||||
} else if (!req && !ep->stopped)
|
||||
} else if (ep->responded &&
|
||||
!req && !ep->stopped)
|
||||
write_fifo (ep, NULL);
|
||||
}
|
||||
} else {
|
||||
@ -2203,7 +2205,7 @@ static void handle_ep_small (struct net2280_ep *ep)
|
||||
} else if (((t & (1 << DATA_OUT_PING_TOKEN_INTERRUPT))
|
||||
&& req
|
||||
&& req->req.actual == req->req.length)
|
||||
|| !req) {
|
||||
|| (ep->responded && !req)) {
|
||||
ep->dev->protocol_stall = 1;
|
||||
set_halt (ep);
|
||||
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;
|
||||
* everything else goes uplevel to the gadget code.
|
||||
*/
|
||||
ep->responded = 1;
|
||||
switch (u.r.bRequest) {
|
||||
case USB_REQ_GET_STATUS: {
|
||||
struct net2280_ep *e;
|
||||
@ -2537,6 +2540,7 @@ delegate:
|
||||
u.r.bRequestType, u.r.bRequest,
|
||||
w_value, w_index, w_length,
|
||||
readl (&ep->regs->ep_cfg));
|
||||
ep->responded = 0;
|
||||
spin_unlock (&dev->lock);
|
||||
tmp = dev->driver->setup (&dev->gadget, &u.r);
|
||||
spin_lock (&dev->lock);
|
||||
|
@ -110,7 +110,8 @@ struct net2280_ep {
|
||||
out_overflow : 1,
|
||||
stopped : 1,
|
||||
is_in : 1,
|
||||
is_iso : 1;
|
||||
is_iso : 1,
|
||||
responded : 1;
|
||||
};
|
||||
|
||||
static inline void allow_status (struct net2280_ep *ep)
|
||||
|
@ -2472,6 +2472,7 @@ static struct pxa2xx_udc memory = {
|
||||
#define PXA210_B1 0x00000123
|
||||
#define PXA210_B0 0x00000122
|
||||
#define IXP425_A0 0x000001c1
|
||||
#define IXP425_B0 0x000001f1
|
||||
#define IXP465_AD 0x00000200
|
||||
|
||||
/*
|
||||
@ -2509,6 +2510,7 @@ static int __init pxa2xx_udc_probe(struct platform_device *pdev)
|
||||
break;
|
||||
#elif defined(CONFIG_ARCH_IXP4XX)
|
||||
case IXP425_A0:
|
||||
case IXP425_B0:
|
||||
case IXP465_AD:
|
||||
dev->has_cfr = 1;
|
||||
out_dma = 0;
|
||||
|
@ -126,6 +126,11 @@ static unsigned park = 0;
|
||||
module_param (park, uint, S_IRUGO);
|
||||
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)
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
@ -541,9 +546,10 @@ static int ehci_run (struct usb_hcd *hcd)
|
||||
|
||||
temp = HC_VERSION(readl (&ehci->caps->hc_capbase));
|
||||
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),
|
||||
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 */
|
||||
|
||||
@ -613,9 +619,8 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd)
|
||||
unsigned i = HCS_N_PORTS (ehci->hcs_params);
|
||||
|
||||
/* resume root hub? */
|
||||
status = readl (&ehci->regs->command);
|
||||
if (!(status & CMD_RUN))
|
||||
writel (status | CMD_RUN, &ehci->regs->command);
|
||||
if (!(readl(&ehci->regs->command) & CMD_RUN))
|
||||
usb_hcd_resume_root_hub(hcd);
|
||||
|
||||
while (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_dbg (ehci, "port %d remote wakeup\n", i + 1);
|
||||
usb_hcd_resume_root_hub(hcd);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -34,6 +34,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
|
||||
{
|
||||
struct ehci_hcd *ehci = hcd_to_ehci (hcd);
|
||||
int port;
|
||||
int mask;
|
||||
|
||||
if (time_before (jiffies, ehci->next_statechange))
|
||||
msleep(5);
|
||||
@ -51,14 +52,25 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
|
||||
ehci->reclaim_ready = 1;
|
||||
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--) {
|
||||
u32 __iomem *reg = &ehci->regs->port_status [port];
|
||||
u32 t1 = readl (reg) & ~PORT_RWC_BITS;
|
||||
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;
|
||||
set_bit(port, &ehci->bus_suspended);
|
||||
}
|
||||
|
||||
/* enable remote wakeup on all ports */
|
||||
if (device_may_wakeup(&hcd->self.root_hub->dev))
|
||||
t2 |= PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E;
|
||||
else
|
||||
@ -76,6 +88,13 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
|
||||
ehci_halt (ehci);
|
||||
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);
|
||||
spin_unlock_irq (&ehci->lock);
|
||||
return 0;
|
||||
@ -88,7 +107,6 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
|
||||
struct ehci_hcd *ehci = hcd_to_ehci (hcd);
|
||||
u32 temp;
|
||||
int i;
|
||||
int intr_enable;
|
||||
|
||||
if (time_before (jiffies, ehci->next_statechange))
|
||||
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
|
||||
* 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 */
|
||||
if (readl (&ehci->regs->intr_enable) == 0) {
|
||||
/* at least some APM implementations will try to deliver
|
||||
* IRQs right away, so delay them until we're ready.
|
||||
*/
|
||||
intr_enable = 1;
|
||||
writel (0, &ehci->regs->segment);
|
||||
writel (ehci->periodic_dma, &ehci->regs->frame_list);
|
||||
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" : "");
|
||||
/* 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);
|
||||
|
||||
/* re-init operational registers */
|
||||
writel(0, &ehci->regs->segment);
|
||||
writel(ehci->periodic_dma, &ehci->regs->frame_list);
|
||||
writel((u32) ehci->async->qh_dma, &ehci->regs->async_next);
|
||||
|
||||
/* restore CMD_RUN, framelist size, and irq threshold */
|
||||
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);
|
||||
while (i--) {
|
||||
temp = readl (&ehci->regs->port_status [i]);
|
||||
temp &= ~(PORT_RWC_BITS
|
||||
| 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);
|
||||
temp |= PORT_RESUME;
|
||||
}
|
||||
@ -134,11 +151,12 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
|
||||
mdelay (20);
|
||||
while (i--) {
|
||||
temp = readl (&ehci->regs->port_status [i]);
|
||||
if ((temp & PORT_SUSPEND) == 0)
|
||||
continue;
|
||||
temp &= ~(PORT_RWC_BITS | PORT_RESUME);
|
||||
writel (temp, &ehci->regs->port_status [i]);
|
||||
ehci_vdbg (ehci, "resumed port %d\n", i + 1);
|
||||
if (test_bit(i, &ehci->bus_suspended) &&
|
||||
(temp & PORT_SUSPEND)) {
|
||||
temp &= ~(PORT_RWC_BITS | PORT_RESUME);
|
||||
writel (temp, &ehci->regs->port_status [i]);
|
||||
ehci_vdbg (ehci, "resumed port %d\n", i + 1);
|
||||
}
|
||||
}
|
||||
(void) readl (&ehci->regs->command);
|
||||
|
||||
@ -157,8 +175,7 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
|
||||
hcd->state = HC_STATE_RUNNING;
|
||||
|
||||
/* 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);
|
||||
return 0;
|
||||
@ -218,6 +235,7 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf)
|
||||
{
|
||||
struct ehci_hcd *ehci = hcd_to_ehci (hcd);
|
||||
u32 temp, status = 0;
|
||||
u32 mask;
|
||||
int ports, i, retval = 1;
|
||||
unsigned long flags;
|
||||
|
||||
@ -233,6 +251,18 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf)
|
||||
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, ...) */
|
||||
|
||||
/* port N changes (bit N)? */
|
||||
@ -250,8 +280,7 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf)
|
||||
}
|
||||
if (!(temp & PORT_CONNECT))
|
||||
ehci->reset_done [i] = 0;
|
||||
if ((temp & (PORT_CSC | PORT_PEC | PORT_OCC)) != 0
|
||||
// PORT_STAT_C_SUSPEND?
|
||||
if ((temp & mask) != 0
|
||||
|| ((temp & PORT_RESUME) != 0
|
||||
&& time_after (jiffies,
|
||||
ehci->reset_done [i]))) {
|
||||
@ -319,6 +348,7 @@ static int ehci_hub_control (
|
||||
u32 temp, status;
|
||||
unsigned long flags;
|
||||
int retval = 0;
|
||||
unsigned selector;
|
||||
|
||||
/*
|
||||
* FIXME: support SetPortFeatures USB_PORT_FEAT_INDICATOR.
|
||||
@ -417,7 +447,7 @@ static int ehci_hub_control (
|
||||
status |= 1 << USB_PORT_FEAT_C_CONNECTION;
|
||||
if (temp & PORT_PEC)
|
||||
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;
|
||||
|
||||
/* whoever resumes must GetPortStatus to complete it!! */
|
||||
@ -506,6 +536,8 @@ static int ehci_hub_control (
|
||||
}
|
||||
break;
|
||||
case SetPortFeature:
|
||||
selector = wIndex >> 8;
|
||||
wIndex &= 0xff;
|
||||
if (!wIndex || wIndex > ports)
|
||||
goto error;
|
||||
wIndex--;
|
||||
@ -559,6 +591,22 @@ static int ehci_hub_control (
|
||||
}
|
||||
writel (temp, &ehci->regs->port_status [wIndex]);
|
||||
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:
|
||||
goto error;
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
|
||||
unsigned port;
|
||||
struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
|
||||
int retval = -EINVAL;
|
||||
|
||||
// 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 */
|
||||
set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
|
||||
|
||||
/* If CF is clear, we lost PCI Vaux power and need to restart. */
|
||||
if (readl(&ehci->regs->configured_flag) != FLAG_CF)
|
||||
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.
|
||||
/* If CF is still set, we maintained PCI Vaux power.
|
||||
* Just undo the effect of ehci_pci_suspend().
|
||||
*/
|
||||
for (port = HCS_N_PORTS(ehci->hcs_params); port > 0; ) {
|
||||
u32 status;
|
||||
port--;
|
||||
status = readl(&ehci->regs->port_status [port]);
|
||||
if (!(status & PORT_POWER))
|
||||
continue;
|
||||
if (status & (PORT_SUSPEND | PORT_RESUME | PORT_OWNER)) {
|
||||
usb_hcd_resume_root_hub(hcd);
|
||||
return 0;
|
||||
}
|
||||
if (readl(&ehci->regs->configured_flag) == FLAG_CF) {
|
||||
int 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);
|
||||
return 0;
|
||||
}
|
||||
|
||||
restart:
|
||||
ehci_dbg(ehci, "lost power, restarting\n");
|
||||
usb_root_hub_lost_power(hcd->self.root_hub);
|
||||
|
||||
@ -307,13 +297,15 @@ restart:
|
||||
ehci_work(ehci);
|
||||
spin_unlock_irq(&ehci->lock);
|
||||
|
||||
/* restart; khubd will disconnect devices */
|
||||
retval = ehci_run(hcd);
|
||||
|
||||
/* here we "know" root ports should always stay powered */
|
||||
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
|
||||
|
||||
|
@ -74,6 +74,7 @@ struct ehci_hcd { /* one per controller */
|
||||
|
||||
/* per root hub port */
|
||||
unsigned long reset_done [EHCI_MAX_ROOT_PORTS];
|
||||
unsigned long bus_suspended;
|
||||
|
||||
/* per-HC memory pools (could be per-bus, but ...) */
|
||||
struct dma_pool *qh_pool; /* qh per active urb */
|
||||
|
@ -729,6 +729,16 @@ static irqreturn_t ohci_irq (struct usb_hcd *hcd)
|
||||
ohci->next_statechange = jiffies + STATECHANGE_DELAY;
|
||||
ohci_writel(ohci, OHCI_INTR_RD | OHCI_INTR_RHSC,
|
||||
®s->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, ®s->intrdisable);
|
||||
usb_hcd_poll_rh_status(hcd);
|
||||
}
|
||||
|
||||
|
@ -41,7 +41,11 @@ static void ohci_rhsc_enable (struct usb_hcd *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 \
|
||||
@ -50,6 +54,9 @@ static void ohci_rhsc_enable (struct usb_hcd *hcd)
|
||||
static void dl_done_list (struct ohci_hcd *);
|
||||
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)
|
||||
__releases(ohci->lock)
|
||||
__acquires(ohci->lock)
|
||||
@ -132,8 +139,6 @@ static inline struct ed *find_head (struct ed *ed)
|
||||
return ed;
|
||||
}
|
||||
|
||||
static int ohci_restart (struct ohci_hcd *ohci);
|
||||
|
||||
/* caller has locked the root hub */
|
||||
static int ohci_rh_resume (struct ohci_hcd *ohci)
|
||||
__releases(ohci->lock)
|
||||
@ -169,7 +174,7 @@ __acquires(ohci->lock)
|
||||
break;
|
||||
case OHCI_USB_RESUME:
|
||||
/* HCFS changes sometime after INTR_RD */
|
||||
ohci_info(ohci, "%swakeup\n",
|
||||
ohci_dbg(ohci, "%swakeup root hub\n",
|
||||
autostopped ? "auto-" : "");
|
||||
break;
|
||||
case OHCI_USB_OPER:
|
||||
@ -181,7 +186,6 @@ __acquires(ohci->lock)
|
||||
ohci_dbg (ohci, "lost power\n");
|
||||
status = -EBUSY;
|
||||
}
|
||||
#ifdef CONFIG_PM
|
||||
if (status == -EBUSY) {
|
||||
if (!autostopped) {
|
||||
spin_unlock_irq (&ohci->lock);
|
||||
@ -191,25 +195,12 @@ __acquires(ohci->lock)
|
||||
}
|
||||
return status;
|
||||
}
|
||||
#endif
|
||||
if (status != -EINPROGRESS)
|
||||
return status;
|
||||
if (autostopped)
|
||||
goto skip_resume;
|
||||
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 */
|
||||
msleep (20 /* usb 11.5.1.10 */ + 12 /* 32 msec counter */ + 1);
|
||||
|
||||
@ -217,6 +208,7 @@ __acquires(ohci->lock)
|
||||
temp &= OHCI_CTRL_HCFS;
|
||||
if (temp != OHCI_USB_RESUME) {
|
||||
ohci_err (ohci, "controller won't resume\n");
|
||||
spin_lock_irq(&ohci->lock);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
@ -296,8 +288,6 @@ skip_resume:
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
||||
static int ohci_bus_suspend (struct usb_hcd *hcd)
|
||||
{
|
||||
struct ohci_hcd *ohci = hcd_to_ohci (hcd);
|
||||
@ -335,6 +325,83 @@ static int ohci_bus_resume (struct usb_hcd *hcd)
|
||||
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 */
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
@ -346,7 +413,7 @@ ohci_hub_status_data (struct usb_hcd *hcd, char *buf)
|
||||
{
|
||||
struct ohci_hcd *ohci = hcd_to_ohci (hcd);
|
||||
int i, changed = 0, length = 1;
|
||||
int any_connected = 0, rhsc_enabled = 1;
|
||||
int any_connected = 0;
|
||||
unsigned long 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
|
||||
* choices for RHSC. Sometimes it triggers on an edge (like
|
||||
* 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;
|
||||
}
|
||||
hcd->poll_rh = ohci_root_hub_state_changes(ohci, changed,
|
||||
any_connected);
|
||||
|
||||
done:
|
||||
spin_unlock_irqrestore (&ohci->lock, flags);
|
||||
|
@ -71,7 +71,7 @@ static int distrust_firmware = 1;
|
||||
module_param(distrust_firmware, bool, 0);
|
||||
MODULE_PARM_DESC(distrust_firmware, "true to distrust firmware power/overcurren"
|
||||
"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
|
||||
*
|
||||
@ -205,11 +205,7 @@ struct u132 {
|
||||
struct u132_port port[MAX_U132_PORTS];
|
||||
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!!
|
||||
* Does anyone have a better way?????
|
||||
|
@ -796,7 +796,7 @@ static int mts_usb_probe(struct usb_interface *intf,
|
||||
|
||||
new_desc->context.scsi_status = kmalloc(1, GFP_KERNEL);
|
||||
if (!new_desc->context.scsi_status)
|
||||
goto out_kfree2;
|
||||
goto out_free_urb;
|
||||
|
||||
new_desc->usb_dev = dev;
|
||||
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,
|
||||
sizeof(new_desc));
|
||||
if (!new_desc->host)
|
||||
goto out_free_urb;
|
||||
goto out_kfree2;
|
||||
|
||||
new_desc->host->hostdata[0] = (unsigned long)new_desc;
|
||||
if (scsi_add_host(new_desc->host, NULL)) {
|
||||
err_retval = -EIO;
|
||||
goto out_free_urb;
|
||||
goto out_host_put;
|
||||
}
|
||||
scsi_scan_host(new_desc->host);
|
||||
|
||||
usb_set_intfdata(intf, new_desc);
|
||||
return 0;
|
||||
|
||||
out_host_put:
|
||||
scsi_host_put(new_desc->host);
|
||||
out_kfree2:
|
||||
kfree(new_desc->context.scsi_status);
|
||||
out_free_urb:
|
||||
|
@ -221,6 +221,7 @@ config USB_TOUCHSCREEN
|
||||
- ITM
|
||||
- some other eTurboTouch
|
||||
- Gunze AHL61
|
||||
- DMC TSC-10/25
|
||||
|
||||
Have a look at <http://linux.chapter7.ch/touchkit/> for
|
||||
a usage description and the required user-space stuff.
|
||||
@ -258,6 +259,11 @@ config USB_TOUCHSCREEN_GUNZE
|
||||
bool "Gunze AHL61 device support" if EMBEDDED
|
||||
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
|
||||
tristate "Yealink usb-p1k voip phone"
|
||||
depends on USB && INPUT && EXPERIMENTAL
|
||||
|
@ -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)
|
||||
{
|
||||
if (ati_remote->irq_urb)
|
||||
usb_free_urb(ati_remote->irq_urb);
|
||||
|
||||
if (ati_remote->out_urb)
|
||||
usb_free_urb(ati_remote->out_urb);
|
||||
usb_free_urb(ati_remote->irq_urb);
|
||||
usb_free_urb(ati_remote->out_urb);
|
||||
|
||||
usb_buffer_free(ati_remote->udev, DATA_BUFSIZE,
|
||||
ati_remote->inbuf, ati_remote->inbuf_dma);
|
||||
|
@ -372,8 +372,7 @@ static void ati_remote2_urb_cleanup(struct ati_remote2 *ar2)
|
||||
int 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])
|
||||
usb_buffer_free(ar2->udev, 4, ar2->buf[i], ar2->buf_dma[i]);
|
||||
|
@ -968,20 +968,29 @@ static void hid_retry_timeout(unsigned long _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)
|
||||
{
|
||||
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");
|
||||
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);
|
||||
if (test_bit(HID_CLEAR_HALT, &hid->iofl)) {
|
||||
dev_dbg(&hid->intf->dev, "clear halt\n");
|
||||
rc = usb_clear_halt(hid->dev, hid->urbin->pipe);
|
||||
clear_bit(HID_CLEAR_HALT, &hid->iofl);
|
||||
hid_start_in(hid);
|
||||
}
|
||||
|
||||
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) {
|
||||
case 0:
|
||||
@ -1023,9 +1032,8 @@ static void hid_io_error(struct hid_device *hid)
|
||||
|
||||
/* Retries failed, so do a port reset */
|
||||
if (!test_and_set_bit(HID_RESET_PENDING, &hid->iofl)) {
|
||||
if (schedule_work(&hid->reset_work))
|
||||
goto done;
|
||||
clear_bit(HID_RESET_PENDING, &hid->iofl);
|
||||
schedule_work(&hid->reset_work);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1049,6 +1057,11 @@ static void hid_irq_in(struct urb *urb)
|
||||
hid->retry_delay = 0;
|
||||
hid_input_report(HID_INPUT_REPORT, urb, 1);
|
||||
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 -ENOENT:
|
||||
case -ESHUTDOWN: /* unplug */
|
||||
@ -1627,6 +1640,19 @@ void hid_init_reports(struct hid_device *hid)
|
||||
|
||||
#define USB_VENDOR_ID_APPLE 0x05ac
|
||||
#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_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_APPLE, 0x020E, HID_QUIRK_POWERBOOK_HAS_FN },
|
||||
{ USB_VENDOR_ID_APPLE, 0x020F, HID_QUIRK_POWERBOOK_HAS_FN },
|
||||
{ USB_VENDOR_ID_APPLE, 0x0214, HID_QUIRK_POWERBOOK_HAS_FN },
|
||||
{ USB_VENDOR_ID_APPLE, 0x0215, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_POWERBOOK_ISO_KEYBOARD},
|
||||
{ USB_VENDOR_ID_APPLE, 0x0216, HID_QUIRK_POWERBOOK_HAS_FN },
|
||||
{ USB_VENDOR_ID_APPLE, 0x0217, HID_QUIRK_POWERBOOK_HAS_FN },
|
||||
{ USB_VENDOR_ID_APPLE, 0x0218, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_POWERBOOK_ISO_KEYBOARD},
|
||||
{ USB_VENDOR_ID_APPLE, 0x0219, HID_QUIRK_POWERBOOK_HAS_FN },
|
||||
{ USB_VENDOR_ID_APPLE, 0x021B, HID_QUIRK_POWERBOOK_HAS_FN },
|
||||
{ USB_VENDOR_ID_APPLE, 0x030A, HID_QUIRK_POWERBOOK_HAS_FN },
|
||||
{ USB_VENDOR_ID_APPLE, 0x030B, HID_QUIRK_POWERBOOK_HAS_FN },
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI, HID_QUIRK_POWERBOOK_HAS_FN },
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ISO, HID_QUIRK_POWERBOOK_HAS_FN },
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ANSI, HID_QUIRK_POWERBOOK_HAS_FN },
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ISO, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_POWERBOOK_ISO_KEYBOARD},
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_JIS, HID_QUIRK_POWERBOOK_HAS_FN },
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ANSI, HID_QUIRK_POWERBOOK_HAS_FN },
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ISO, HID_QUIRK_POWERBOOK_HAS_FN | HID_QUIRK_POWERBOOK_ISO_KEYBOARD},
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_JIS, HID_QUIRK_POWERBOOK_HAS_FN },
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ANSI, HID_QUIRK_POWERBOOK_HAS_FN },
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ISO, 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, 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)
|
||||
interval = hid_mousepoll_interval;
|
||||
|
||||
if (endpoint->bEndpointAddress & USB_DIR_IN) {
|
||||
if (usb_endpoint_dir_in(endpoint)) {
|
||||
if (hid->urbin)
|
||||
continue;
|
||||
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;
|
||||
|
||||
fail:
|
||||
|
||||
if (hid->urbin)
|
||||
usb_free_urb(hid->urbin);
|
||||
if (hid->urbout)
|
||||
usb_free_urb(hid->urbout);
|
||||
if (hid->urbctrl)
|
||||
usb_free_urb(hid->urbctrl);
|
||||
usb_free_urb(hid->urbin);
|
||||
usb_free_urb(hid->urbout);
|
||||
usb_free_urb(hid->urbctrl);
|
||||
hid_free_buffers(dev, 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->urbctrl);
|
||||
if (hid->urbout)
|
||||
usb_free_urb(hid->urbout);
|
||||
usb_free_urb(hid->urbout);
|
||||
|
||||
hid_free_buffers(hid->dev, hid);
|
||||
hid_free_device(hid);
|
||||
|
@ -385,6 +385,7 @@ struct hid_control_fifo {
|
||||
#define HID_IN_RUNNING 3
|
||||
#define HID_RESET_PENDING 4
|
||||
#define HID_SUSPENDED 5
|
||||
#define HID_CLEAR_HALT 6
|
||||
|
||||
struct hid_input {
|
||||
struct list_head list;
|
||||
|
@ -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)
|
||||
{
|
||||
if (kbd->irq)
|
||||
usb_free_urb(kbd->irq);
|
||||
if (kbd->led)
|
||||
usb_free_urb(kbd->led);
|
||||
usb_free_urb(kbd->irq);
|
||||
usb_free_urb(kbd->led);
|
||||
if (kbd->new)
|
||||
usb_buffer_free(dev, 8, kbd->new, kbd->new_dma);
|
||||
if (kbd->cr)
|
||||
@ -236,9 +234,7 @@ static int usb_kbd_probe(struct usb_interface *iface,
|
||||
return -ENODEV;
|
||||
|
||||
endpoint = &interface->endpoint[0].desc;
|
||||
if (!(endpoint->bEndpointAddress & USB_DIR_IN))
|
||||
return -ENODEV;
|
||||
if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT)
|
||||
if (!usb_endpoint_is_int_in(endpoint))
|
||||
return -ENODEV;
|
||||
|
||||
pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
|
||||
|
@ -126,9 +126,7 @@ static int usb_mouse_probe(struct usb_interface *intf, const struct usb_device_i
|
||||
return -ENODEV;
|
||||
|
||||
endpoint = &interface->endpoint[0].desc;
|
||||
if (!(endpoint->bEndpointAddress & USB_DIR_IN))
|
||||
return -ENODEV;
|
||||
if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT)
|
||||
if (!usb_endpoint_is_int_in(endpoint))
|
||||
return -ENODEV;
|
||||
|
||||
pipe = usb_rcvintpipe(dev, endpoint->bEndpointAddress);
|
||||
|
@ -8,6 +8,7 @@
|
||||
* - PanJit TouchSet
|
||||
* - eTurboTouch
|
||||
* - Gunze AHL61
|
||||
* - DMC TSC-10/25
|
||||
*
|
||||
* Copyright (C) 2004-2006 by Daniel Ritz <daniel.ritz@gmx.ch>
|
||||
* Copyright (C) by Todd E. Johnson (mtouchusb.c)
|
||||
@ -30,6 +31,8 @@
|
||||
* - ITM parts are from itmtouch.c
|
||||
* - 3M parts are from mtouchusb.c
|
||||
* - 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>
|
||||
|
||||
|
||||
#define DRIVER_VERSION "v0.4"
|
||||
#define DRIVER_VERSION "v0.5"
|
||||
#define DRIVER_AUTHOR "Daniel Ritz <daniel.ritz@gmx.ch>"
|
||||
#define DRIVER_DESC "USB Touchscreen Driver"
|
||||
|
||||
@ -103,6 +106,7 @@ enum {
|
||||
DEVTYPE_ITM,
|
||||
DEVTYPE_ETURBO,
|
||||
DEVTYPE_GUNZE,
|
||||
DEVTYPE_DMC_TSC10,
|
||||
};
|
||||
|
||||
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},
|
||||
#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
|
||||
|
||||
/*****************************************************************************
|
||||
* 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
|
||||
*/
|
||||
@ -389,6 +471,18 @@ static struct usbtouch_device_info usbtouch_dev_info[] = {
|
||||
.read_data = gunze_read_data,
|
||||
},
|
||||
#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
|
||||
};
|
||||
|
||||
|
||||
|
@ -110,7 +110,6 @@ struct wacom_combo {
|
||||
};
|
||||
|
||||
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_rel(void *wcombo, unsigned int rel_type, int rel_data);
|
||||
extern void wacom_report_key(void *wcombo, unsigned int key_type, int key_data);
|
||||
|
@ -42,7 +42,7 @@ static struct input_dev * get_input_dev(struct wacom_combo *wcombo)
|
||||
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_combo wcombo;
|
||||
|
@ -859,10 +859,8 @@ static int usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
|
||||
|
||||
interface = intf->cur_altsetting;
|
||||
endpoint = &interface->endpoint[0].desc;
|
||||
if (!(endpoint->bEndpointAddress & USB_DIR_IN))
|
||||
return -EIO;
|
||||
if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) != USB_ENDPOINT_XFER_INT)
|
||||
return -EIO;
|
||||
if (!usb_endpoint_is_int_in(endpoint))
|
||||
return -ENODEV;
|
||||
|
||||
yld = kzalloc(sizeof(struct yealink_dev), GFP_KERNEL);
|
||||
if (!yld)
|
||||
|
@ -4,6 +4,7 @@
|
||||
#
|
||||
|
||||
obj-$(CONFIG_USB_ADUTUX) += adutux.o
|
||||
obj-$(CONFIG_USB_APPLEDISPLAY) += appledisplay.o
|
||||
obj-$(CONFIG_USB_AUERSWALD) += auerswald.o
|
||||
obj-$(CONFIG_USB_CYPRESS_CY7C63)+= cypress_cy7c63.o
|
||||
obj-$(CONFIG_USB_CYTHERM) += cytherm.o
|
||||
|
@ -216,10 +216,7 @@ static int appledisplay_probe(struct usb_interface *iface,
|
||||
iface_desc = iface->cur_altsetting;
|
||||
for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) {
|
||||
endpoint = &iface_desc->endpoint[i].desc;
|
||||
if (!int_in_endpointAddr &&
|
||||
(endpoint->bEndpointAddress & USB_DIR_IN) &&
|
||||
((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
|
||||
USB_ENDPOINT_XFER_INT)) {
|
||||
if (!int_in_endpointAddr && usb_endpoint_is_int_in(endpoint)) {
|
||||
/* we found an interrupt in endpoint */
|
||||
int_in_endpointAddr = endpoint->bEndpointAddress;
|
||||
break;
|
||||
|
@ -704,9 +704,7 @@ static void auerbuf_free (pauerbuf_t bp)
|
||||
{
|
||||
kfree(bp->bufp);
|
||||
kfree(bp->dr);
|
||||
if (bp->urbp) {
|
||||
usb_free_urb(bp->urbp);
|
||||
}
|
||||
usb_free_urb(bp->urbp);
|
||||
kfree(bp);
|
||||
}
|
||||
|
||||
@ -1155,8 +1153,7 @@ static void auerswald_int_release (pauerswald_t cp)
|
||||
dbg ("auerswald_int_release");
|
||||
|
||||
/* stop the int endpoint */
|
||||
if (cp->inturbp)
|
||||
usb_kill_urb (cp->inturbp);
|
||||
usb_kill_urb (cp->inturbp);
|
||||
|
||||
/* deallocate memory */
|
||||
auerswald_int_free (cp);
|
||||
|
@ -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)
|
||||
{
|
||||
int result;
|
||||
unsigned char *buffer = kmalloc (length, GFP_KERNEL);
|
||||
unsigned char *buffer = kmemdup(data, length, GFP_KERNEL);
|
||||
|
||||
if (!buffer) {
|
||||
err("emi26: kmalloc(%d) failed.", length);
|
||||
return -ENOMEM;
|
||||
}
|
||||
memcpy (buffer, data, length);
|
||||
/* Note: usb_control_msg returns negative value on error or length of the
|
||||
* data that was written! */
|
||||
result = usb_control_msg (dev, usb_sndctrlpipe(dev, 0), request, 0x40, address, 0, buffer, length, 300);
|
||||
|
@ -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)
|
||||
{
|
||||
int result;
|
||||
unsigned char *buffer = kmalloc (length, GFP_KERNEL);
|
||||
unsigned char *buffer = kmemdup(data, length, GFP_KERNEL);
|
||||
|
||||
if (!buffer) {
|
||||
err("emi62: kmalloc(%d) failed.", length);
|
||||
return -ENOMEM;
|
||||
}
|
||||
memcpy (buffer, data, length);
|
||||
/* Note: usb_control_msg returns negative value on error or length of the
|
||||
* data that was written! */
|
||||
result = usb_control_msg (dev, usb_sndctrlpipe(dev, 0), request, 0x40, address, 0, buffer, length, 300);
|
||||
|
@ -303,7 +303,7 @@ void ftdi_elan_gone_away(struct platform_device *pdev)
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
@ -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,
|
||||
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) {
|
||||
endpoint = &iface_desc->endpoint[i].desc;
|
||||
if (!ftdi->bulk_in_endpointAddr &&
|
||||
((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
|
||||
== USB_DIR_IN) && ((endpoint->bmAttributes &
|
||||
USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK))
|
||||
{
|
||||
usb_endpoint_is_bulk_in(endpoint)) {
|
||||
buffer_size = le16_to_cpu(endpoint->wMaxPacketSize);
|
||||
ftdi->bulk_in_size = buffer_size;
|
||||
ftdi->bulk_in_endpointAddr = endpoint->bEndpointAddress;
|
||||
@ -2649,10 +2638,7 @@ static int ftdi_elan_probe(struct usb_interface *interface,
|
||||
}
|
||||
}
|
||||
if (!ftdi->bulk_out_endpointAddr &&
|
||||
((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK)
|
||||
== USB_DIR_OUT) && ((endpoint->bmAttributes &
|
||||
USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK))
|
||||
{
|
||||
usb_endpoint_is_bulk_out(endpoint)) {
|
||||
ftdi->bulk_out_endpointAddr =
|
||||
endpoint->bEndpointAddress;
|
||||
}
|
||||
|
@ -125,12 +125,12 @@ static DEFINE_MUTEX(disconnect_mutex);
|
||||
|
||||
static int idmouse_create_image(struct usb_idmouse *dev)
|
||||
{
|
||||
int bytes_read = 0;
|
||||
int bulk_read = 0;
|
||||
int result = 0;
|
||||
int bytes_read;
|
||||
int bulk_read;
|
||||
int result;
|
||||
|
||||
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 */
|
||||
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)
|
||||
{
|
||||
struct usb_idmouse *dev = NULL;
|
||||
struct usb_idmouse *dev;
|
||||
struct usb_interface *interface;
|
||||
int result = 0;
|
||||
int result;
|
||||
|
||||
/* prevent disconnects */
|
||||
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)
|
||||
{
|
||||
struct usb_idmouse *dev;
|
||||
int result = 0;
|
||||
int result;
|
||||
|
||||
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)
|
||||
{
|
||||
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_endpoint_descriptor *endpoint;
|
||||
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 */
|
||||
endpoint = &iface_desc->endpoint[0].desc;
|
||||
if (!dev->bulk_in_endpointAddr
|
||||
&& (endpoint->bEndpointAddress & USB_DIR_IN)
|
||||
&& ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) ==
|
||||
USB_ENDPOINT_XFER_BULK)) {
|
||||
|
||||
if (!dev->bulk_in_endpointAddr && usb_endpoint_is_bulk_in(endpoint)) {
|
||||
/* we found a bulk in endpoint */
|
||||
dev->orig_bi_size = le16_to_cpu(endpoint->wMaxPacketSize);
|
||||
dev->bulk_in_size = 0x200; /* works _much_ faster */
|
||||
|
@ -317,12 +317,8 @@ static inline void tower_delete (struct lego_usb_tower *dev)
|
||||
tower_abort_transfers (dev);
|
||||
|
||||
/* free data structures */
|
||||
if (dev->interrupt_in_urb != NULL) {
|
||||
usb_free_urb (dev->interrupt_in_urb);
|
||||
}
|
||||
if (dev->interrupt_out_urb != NULL) {
|
||||
usb_free_urb (dev->interrupt_out_urb);
|
||||
}
|
||||
usb_free_urb(dev->interrupt_in_urb);
|
||||
usb_free_urb(dev->interrupt_out_urb);
|
||||
kfree (dev->read_buffer);
|
||||
kfree (dev->interrupt_in_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) {
|
||||
dev->interrupt_in_running = 0;
|
||||
mb();
|
||||
if (dev->interrupt_in_urb != NULL && dev->udev) {
|
||||
if (dev->udev)
|
||||
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:
|
||||
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) {
|
||||
endpoint = &iface_desc->endpoint[i].desc;
|
||||
|
||||
if (((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) &&
|
||||
((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)) {
|
||||
dev->interrupt_in_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 (usb_endpoint_xfer_int(endpoint)) {
|
||||
if (usb_endpoint_dir_in(endpoint))
|
||||
dev->interrupt_in_endpoint = endpoint;
|
||||
else
|
||||
dev->interrupt_out_endpoint = endpoint;
|
||||
}
|
||||
}
|
||||
if(dev->interrupt_in_endpoint == NULL) {
|
||||
|
@ -551,7 +551,7 @@ static int interfacekit_probe(struct usb_interface *intf, const struct usb_devic
|
||||
return -ENODEV;
|
||||
|
||||
endpoint = &interface->endpoint[0].desc;
|
||||
if (!(endpoint->bEndpointAddress & 0x80))
|
||||
if (!usb_endpoint_dir_in(endpoint))
|
||||
return -ENODEV;
|
||||
/*
|
||||
* bmAttributes
|
||||
@ -650,8 +650,7 @@ out2:
|
||||
device_remove_file(kit->dev, &dev_output_attrs[i]);
|
||||
out:
|
||||
if (kit) {
|
||||
if (kit->irq)
|
||||
usb_free_urb(kit->irq);
|
||||
usb_free_urb(kit->irq);
|
||||
if (kit->data)
|
||||
usb_buffer_free(dev, URB_INT_SIZE, kit->data, kit->data_dma);
|
||||
if (kit->dev)
|
||||
|
@ -323,7 +323,7 @@ static int motorcontrol_probe(struct usb_interface *intf, const struct usb_devic
|
||||
return -ENODEV;
|
||||
|
||||
endpoint = &interface->endpoint[0].desc;
|
||||
if (!(endpoint->bEndpointAddress & 0x80))
|
||||
if (!usb_endpoint_dir_in(endpoint))
|
||||
return -ENODEV;
|
||||
|
||||
/*
|
||||
@ -392,8 +392,7 @@ out2:
|
||||
device_remove_file(mc->dev, &dev_attrs[i]);
|
||||
out:
|
||||
if (mc) {
|
||||
if (mc->irq)
|
||||
usb_free_urb(mc->irq);
|
||||
usb_free_urb(mc->irq);
|
||||
if (mc->data)
|
||||
usb_buffer_free(dev, URB_INT_SIZE, mc->data, mc->data_dma);
|
||||
if (mc->dev)
|
||||
|
@ -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 usb_ftdi_elan_edset_flush(struct platform_device *pdev, u8 ed_number,
|
||||
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);
|
||||
|
@ -138,7 +138,7 @@ get_endpoints (struct usbtest_dev *dev, struct usb_interface *intf)
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
if (e->desc.bEndpointAddress & USB_DIR_IN) {
|
||||
if (usb_endpoint_dir_in(&e->desc)) {
|
||||
if (!in)
|
||||
in = e;
|
||||
} else {
|
||||
@ -147,7 +147,7 @@ get_endpoints (struct usbtest_dev *dev, struct usb_interface *intf)
|
||||
}
|
||||
continue;
|
||||
try_iso:
|
||||
if (e->desc.bEndpointAddress & USB_DIR_IN) {
|
||||
if (usb_endpoint_dir_in(&e->desc)) {
|
||||
if (!iso_in)
|
||||
iso_in = e;
|
||||
} else {
|
||||
|
@ -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->bRequest = cmd;
|
||||
req->wValue = value;
|
||||
req->wIndex = index;
|
||||
req->wLength = size;
|
||||
req->wValue = cpu_to_le16(value);
|
||||
req->wIndex = cpu_to_le16(index);
|
||||
req->wLength = cpu_to_le16(size);
|
||||
|
||||
usb_fill_control_urb(urb, dev->udev,
|
||||
usb_sndctrlpipe(dev->udev, 0),
|
||||
|
@ -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) ||
|
||||
(!catc->rx_urb) || (!catc->irq_urb)) {
|
||||
err("No free urbs available.");
|
||||
if (catc->ctrl_urb)
|
||||
usb_free_urb(catc->ctrl_urb);
|
||||
if (catc->tx_urb)
|
||||
usb_free_urb(catc->tx_urb);
|
||||
if (catc->rx_urb)
|
||||
usb_free_urb(catc->rx_urb);
|
||||
if (catc->irq_urb)
|
||||
usb_free_urb(catc->irq_urb);
|
||||
usb_free_urb(catc->ctrl_urb);
|
||||
usb_free_urb(catc->tx_urb);
|
||||
usb_free_urb(catc->rx_urb);
|
||||
usb_free_urb(catc->irq_urb);
|
||||
free_netdev(netdev);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
@ -200,8 +200,7 @@ next_desc:
|
||||
|
||||
dev->status = &info->control->cur_altsetting->endpoint [0];
|
||||
desc = &dev->status->desc;
|
||||
if (desc->bmAttributes != USB_ENDPOINT_XFER_INT
|
||||
|| !(desc->bEndpointAddress & USB_DIR_IN)
|
||||
if (!usb_endpoint_is_int_in(desc)
|
||||
|| (le16_to_cpu(desc->wMaxPacketSize)
|
||||
< sizeof(struct usb_cdc_notification))
|
||||
|| !desc->bInterval) {
|
||||
|
@ -237,12 +237,12 @@ static inline void nc_dump_usbctl(struct usbnet *dev, u16 usbctl)
|
||||
#define STATUS_CONN_OTHER (1 << 14)
|
||||
#define STATUS_SUSPEND_OTHER (1 << 13)
|
||||
#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_SUSPEND_THIS (1 << 5)
|
||||
#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_NOISE_MASK ((u16)~(0x0303|STATUS_UNSPEC_MASK))
|
||||
|
@ -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 */
|
||||
if ((ret = usb_submit_urb(pegasus->ctrl_urb, GFP_ATOMIC))) {
|
||||
set_current_state(TASK_RUNNING);
|
||||
if (ret == -ENODEV)
|
||||
netif_device_detach(pegasus->net);
|
||||
if (netif_msg_drv(pegasus))
|
||||
|
@ -116,7 +116,7 @@ int usbnet_get_endpoints(struct usbnet *dev, struct usb_interface *intf)
|
||||
e = alt->endpoint + ep;
|
||||
switch (e->desc.bmAttributes) {
|
||||
case USB_ENDPOINT_XFER_INT:
|
||||
if (!(e->desc.bEndpointAddress & USB_DIR_IN))
|
||||
if (!usb_endpoint_dir_in(&e->desc))
|
||||
continue;
|
||||
intr = 1;
|
||||
/* FALLTHROUGH */
|
||||
@ -125,7 +125,7 @@ int usbnet_get_endpoints(struct usbnet *dev, struct usb_interface *intf)
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
if (e->desc.bEndpointAddress & USB_DIR_IN) {
|
||||
if (usb_endpoint_dir_in(&e->desc)) {
|
||||
if (!intr && !in)
|
||||
in = e;
|
||||
else if (intr && !status)
|
||||
|
@ -554,6 +554,17 @@ config USB_SERIAL_OMNINET
|
||||
To compile this driver as a module, choose M here: the
|
||||
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
|
||||
bool
|
||||
depends on USB_SERIAL_KEYSPAN_PDA || USB_SERIAL_XIRCOM || USB_SERIAL_KEYSPAN || USB_SERIAL_WHITEHEAT
|
||||
|
@ -18,6 +18,7 @@ obj-$(CONFIG_USB_SERIAL_BELKIN) += belkin_sa.o
|
||||
obj-$(CONFIG_USB_SERIAL_CP2101) += cp2101.o
|
||||
obj-$(CONFIG_USB_SERIAL_CYBERJACK) += cyberjack.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_EDGEPORT) += io_edgeport.o
|
||||
obj-$(CONFIG_USB_SERIAL_EDGEPORT_TI) += io_ti.o
|
||||
|
@ -270,8 +270,11 @@ static void aircable_read(void *params)
|
||||
*/
|
||||
tty = port->tty;
|
||||
|
||||
if (!tty)
|
||||
if (!tty) {
|
||||
schedule_work(&priv->rx_work);
|
||||
err("%s - No tty available", __FUNCTION__);
|
||||
return ;
|
||||
}
|
||||
|
||||
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++) {
|
||||
endpoint = &iface_desc->endpoint[i].desc;
|
||||
if (((endpoint->bEndpointAddress & 0x80) == 0x00) &&
|
||||
((endpoint->bmAttributes & 3) == 0x02)) {
|
||||
/* we found our bulk out endpoint */
|
||||
if (usb_endpoint_is_bulk_out(endpoint)) {
|
||||
dbg("found bulk out on endpoint %d", i);
|
||||
++num_bulk_out;
|
||||
}
|
||||
|
@ -19,6 +19,7 @@
|
||||
static struct usb_device_id id_table [] = {
|
||||
{ USB_DEVICE(0x0c88, 0x17da) }, /* Kyocera Wireless KPC650/Passport */
|
||||
{ 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 */
|
||||
{ },
|
||||
};
|
||||
|
@ -85,10 +85,9 @@ static int ark3116_attach(struct usb_serial *serial)
|
||||
int 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)
|
||||
goto cleanup;
|
||||
memset(priv, 0x00, sizeof (struct ark3116_private));
|
||||
spin_lock_init(&priv->lock);
|
||||
|
||||
usb_set_serial_port_data(serial->port[i], priv);
|
||||
|
@ -166,19 +166,17 @@ static int usb_console_setup(struct console *co, char *options)
|
||||
if (serial->type->set_termios) {
|
||||
/* build up a fake tty structure so that the open call has something
|
||||
* to look at to get the cflag value */
|
||||
tty = kmalloc (sizeof (*tty), GFP_KERNEL);
|
||||
tty = kzalloc(sizeof(*tty), GFP_KERNEL);
|
||||
if (!tty) {
|
||||
err ("no more memory");
|
||||
return -ENOMEM;
|
||||
}
|
||||
termios = kmalloc (sizeof (*termios), GFP_KERNEL);
|
||||
termios = kzalloc(sizeof(*termios), GFP_KERNEL);
|
||||
if (!termios) {
|
||||
err ("no more memory");
|
||||
kfree (tty);
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset (tty, 0x00, sizeof(*tty));
|
||||
memset (termios, 0x00, sizeof(*termios));
|
||||
termios->c_cflag = cflag;
|
||||
tty->termios = termios;
|
||||
port->tty = tty;
|
||||
|
@ -1684,15 +1684,14 @@ static int __init cypress_init(void)
|
||||
|
||||
info(DRIVER_DESC " " DRIVER_VERSION);
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -31,12 +31,11 @@ int ezusb_writememory (struct usb_serial *serial, int address, unsigned char *da
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
transfer_buffer = kmalloc (length, GFP_KERNEL);
|
||||
transfer_buffer = kmemdup(data, length, GFP_KERNEL);
|
||||
if (!transfer_buffer) {
|
||||
dev_err(&serial->dev->dev, "%s - kmalloc(%d) failed.\n", __FUNCTION__, length);
|
||||
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);
|
||||
kfree (transfer_buffer);
|
||||
return result;
|
||||
|
@ -1388,8 +1388,7 @@ static void ftdi_close (struct usb_serial_port *port, struct file *filp)
|
||||
flush_scheduled_work();
|
||||
|
||||
/* shutdown our bulk read */
|
||||
if (port->read_urb)
|
||||
usb_kill_urb(port->read_urb);
|
||||
usb_kill_urb(port->read_urb);
|
||||
} /* ftdi_close */
|
||||
|
||||
|
||||
|
@ -1523,12 +1523,11 @@ static int garmin_attach (struct usb_serial *serial)
|
||||
|
||||
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) {
|
||||
dev_err(&port->dev, "%s - Out of memory\n", __FUNCTION__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset (garmin_data_p, 0, sizeof(struct garmin_data));
|
||||
init_timer(&garmin_data_p->timer);
|
||||
spin_lock_init(&garmin_data_p->lock);
|
||||
INIT_LIST_HEAD(&garmin_data_p->pktlist);
|
||||
|
@ -1038,9 +1038,7 @@ static void edge_close (struct usb_serial_port *port, struct file * filp)
|
||||
edge_port->open = 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 this urb had a transfer buffer already (old transfer) free it */
|
||||
|
@ -206,10 +206,9 @@ static int ipw_open(struct usb_serial_port *port, struct file *filp)
|
||||
|
||||
dbg("%s", __FUNCTION__);
|
||||
|
||||
buf_flow_init = kmalloc(16, GFP_KERNEL);
|
||||
buf_flow_init = kmemdup(buf_flow_static, 16, GFP_KERNEL);
|
||||
if (!buf_flow_init)
|
||||
return -ENOMEM;
|
||||
memcpy(buf_flow_init, buf_flow_static, 16);
|
||||
|
||||
if (port->tty)
|
||||
port->tty->low_latency = 1;
|
||||
|
@ -2306,22 +2306,16 @@ static void keyspan_shutdown (struct usb_serial *serial)
|
||||
}
|
||||
|
||||
/* Now free them */
|
||||
if (s_priv->instat_urb)
|
||||
usb_free_urb(s_priv->instat_urb);
|
||||
if (s_priv->glocont_urb)
|
||||
usb_free_urb(s_priv->glocont_urb);
|
||||
usb_free_urb(s_priv->instat_urb);
|
||||
usb_free_urb(s_priv->glocont_urb);
|
||||
for (i = 0; i < serial->num_ports; ++i) {
|
||||
port = serial->port[i];
|
||||
p_priv = usb_get_serial_port_data(port);
|
||||
if (p_priv->inack_urb)
|
||||
usb_free_urb(p_priv->inack_urb);
|
||||
if (p_priv->outcont_urb)
|
||||
usb_free_urb(p_priv->outcont_urb);
|
||||
usb_free_urb(p_priv->inack_urb);
|
||||
usb_free_urb(p_priv->outcont_urb);
|
||||
for (j = 0; j < 2; j++) {
|
||||
if (p_priv->in_urbs[j])
|
||||
usb_free_urb(p_priv->in_urbs[j]);
|
||||
if (p_priv->out_urbs[j])
|
||||
usb_free_urb(p_priv->out_urbs[j]);
|
||||
usb_free_urb(p_priv->in_urbs[j]);
|
||||
usb_free_urb(p_priv->out_urbs[j]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -185,13 +185,11 @@ static int kobil_startup (struct usb_serial *serial)
|
||||
|
||||
for (i = 0; i < altsetting->desc.bNumEndpoints; i++) {
|
||||
endpoint = &altsetting->endpoint[i];
|
||||
if (((endpoint->desc.bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) &&
|
||||
((endpoint->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)) {
|
||||
if (usb_endpoint_is_int_out(&endpoint->desc)) {
|
||||
dbg("%s Found interrupt out endpoint. Address: %d", __FUNCTION__, endpoint->desc.bEndpointAddress);
|
||||
priv->write_int_endpoint_address = endpoint->desc.bEndpointAddress;
|
||||
}
|
||||
if (((endpoint->desc.bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) &&
|
||||
((endpoint->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)) {
|
||||
if (usb_endpoint_is_int_in(&endpoint->desc)) {
|
||||
dbg("%s Found interrupt in endpoint. Address: %d", __FUNCTION__, 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 );
|
||||
port->write_urb = NULL;
|
||||
}
|
||||
if (port->interrupt_in_urb)
|
||||
usb_kill_urb(port->interrupt_in_urb);
|
||||
usb_kill_urb(port->interrupt_in_urb);
|
||||
}
|
||||
|
||||
|
||||
|
@ -358,10 +358,8 @@ static int mct_u232_startup (struct usb_serial *serial)
|
||||
/* Puh, that's dirty */
|
||||
port = serial->port[0];
|
||||
rport = serial->port[1];
|
||||
if (port->read_urb) {
|
||||
/* No unlinking, it wasn't submitted yet. */
|
||||
usb_free_urb(port->read_urb);
|
||||
}
|
||||
/* No unlinking, it wasn't submitted yet. */
|
||||
usb_free_urb(port->read_urb);
|
||||
port->read_urb = rport->interrupt_in_urb;
|
||||
rport->interrupt_in_urb = NULL;
|
||||
port->read_urb->context = port;
|
||||
|
@ -2596,12 +2596,11 @@ static int mos7840_startup(struct usb_serial *serial)
|
||||
|
||||
/* set up port private structures */
|
||||
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) {
|
||||
err("%s - Out of memory", __FUNCTION__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset(mos7840_port, 0, sizeof(struct moschip_port));
|
||||
|
||||
/* Initialize all port interrupt end point to port 0 int endpoint *
|
||||
* Our device has only one interrupt end point comman to all port */
|
||||
|
@ -95,8 +95,7 @@ static void navman_close(struct usb_serial_port *port, struct file *filp)
|
||||
{
|
||||
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,
|
||||
|
@ -228,6 +228,7 @@ static int product_5052_count;
|
||||
/* null entry */
|
||||
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_EZ430_ID) },
|
||||
};
|
||||
|
||||
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[] = {
|
||||
{ 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_5152_BOOT_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 */
|
||||
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) {
|
||||
dev_err(&dev->dev, "%s - out of memory\n", __FUNCTION__);
|
||||
status = -ENOMEM;
|
||||
goto free_tports;
|
||||
}
|
||||
memset(tport, 0, sizeof(struct ti_port));
|
||||
spin_lock_init(&tport->tp_lock);
|
||||
tport->tp_uart_base_addr = (i == 0 ? TI_UART1_BASE_ADDR : TI_UART2_BASE_ADDR);
|
||||
tport->tp_flags = low_latency ? ASYNC_LOW_LATENCY : 0;
|
||||
|
@ -28,6 +28,7 @@
|
||||
/* Vendor and product ids */
|
||||
#define TI_VENDOR_ID 0x0451
|
||||
#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_5152_BOOT_PRODUCT_ID 0x5152 /* no EEPROM, no firmware */
|
||||
#define TI_5052_EEPROM_PRODUCT_ID 0x505A /* EEPROM, no firmware */
|
||||
|
@ -952,32 +952,28 @@ probe_error:
|
||||
port = serial->port[i];
|
||||
if (!port)
|
||||
continue;
|
||||
if (port->read_urb)
|
||||
usb_free_urb (port->read_urb);
|
||||
usb_free_urb(port->read_urb);
|
||||
kfree(port->bulk_in_buffer);
|
||||
}
|
||||
for (i = 0; i < num_bulk_out; ++i) {
|
||||
port = serial->port[i];
|
||||
if (!port)
|
||||
continue;
|
||||
if (port->write_urb)
|
||||
usb_free_urb (port->write_urb);
|
||||
usb_free_urb(port->write_urb);
|
||||
kfree(port->bulk_out_buffer);
|
||||
}
|
||||
for (i = 0; i < num_interrupt_in; ++i) {
|
||||
port = serial->port[i];
|
||||
if (!port)
|
||||
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);
|
||||
}
|
||||
for (i = 0; i < num_interrupt_out; ++i) {
|
||||
port = serial->port[i];
|
||||
if (!port)
|
||||
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);
|
||||
}
|
||||
|
||||
|
65
drivers/usb/serial/usb_debug.c
Normal file
65
drivers/usb/serial/usb_debug.c
Normal 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");
|
@ -348,8 +348,7 @@ static void visor_close (struct usb_serial_port *port, struct file * filp)
|
||||
|
||||
/* shutdown our urbs */
|
||||
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. */
|
||||
transfer_buffer = kmalloc (0x12, GFP_KERNEL);
|
||||
|
@ -142,10 +142,7 @@ int onetouch_connect_input(struct us_data *ss)
|
||||
return -ENODEV;
|
||||
|
||||
endpoint = &interface->endpoint[2].desc;
|
||||
if (!(endpoint->bEndpointAddress & USB_DIR_IN))
|
||||
return -ENODEV;
|
||||
if ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
|
||||
!= USB_ENDPOINT_XFER_INT)
|
||||
if (!usb_endpoint_is_int_in(endpoint))
|
||||
return -ENODEV;
|
||||
|
||||
pipe = usb_rcvintpipe(udev, endpoint->bEndpointAddress);
|
||||
|
@ -1318,6 +1318,16 @@ UNUSUAL_DEV( 0x1019, 0x0c55, 0x0000, 0x0110,
|
||||
US_SC_DEVICE, US_PR_DEVICE, usb_stor_ucr61s2b_init,
|
||||
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) */
|
||||
UNUSUAL_DEV( 0x132b, 0x000b, 0x0001, 0x0001,
|
||||
"Minolta",
|
||||
|
@ -740,18 +740,16 @@ static int get_pipes(struct us_data *us)
|
||||
ep = &altsetting->endpoint[i].desc;
|
||||
|
||||
/* Is it a BULK endpoint? */
|
||||
if ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
|
||||
== USB_ENDPOINT_XFER_BULK) {
|
||||
if (usb_endpoint_xfer_bulk(ep)) {
|
||||
/* BULK in or out? */
|
||||
if (ep->bEndpointAddress & USB_DIR_IN)
|
||||
if (usb_endpoint_dir_in(ep))
|
||||
ep_in = ep;
|
||||
else
|
||||
ep_out = ep;
|
||||
}
|
||||
|
||||
/* Is it an interrupt endpoint? */
|
||||
else if ((ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
|
||||
== USB_ENDPOINT_XFER_INT) {
|
||||
else if (usb_endpoint_xfer_int(ep)) {
|
||||
ep_int = ep;
|
||||
}
|
||||
}
|
||||
|
@ -313,8 +313,13 @@ struct usb_bus {
|
||||
/* This is arbitrary.
|
||||
* From USB 2.0 spec Table 11-13, offset 7, a hub can
|
||||
* 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;
|
||||
|
||||
@ -357,7 +362,8 @@ struct usb_device {
|
||||
u8 portnum; /* Parent port number (origin 1) */
|
||||
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 */
|
||||
|
||||
/* 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 */
|
||||
#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 void usb_autopm_put_interface(struct usb_interface *intf);
|
||||
|
||||
#else
|
||||
#define usb_autopm_get_interface(intf) 0
|
||||
#define usb_autopm_put_interface(intf) do {} while (0)
|
||||
#endif
|
||||
static inline void usb_autopm_enable(struct usb_interface *intf)
|
||||
{
|
||||
intf->pm_usage_cnt = 0;
|
||||
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);
|
||||
extern int usb_endpoint_xfer_bulk(const struct usb_endpoint_descriptor *epd);
|
||||
extern int usb_endpoint_xfer_int(const struct usb_endpoint_descriptor *epd);
|
||||
extern int usb_endpoint_xfer_isoc(const struct usb_endpoint_descriptor *epd);
|
||||
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);
|
||||
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);
|
||||
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_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.
|
||||
*/
|
||||
static inline 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.
|
||||
*/
|
||||
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));
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
|
@ -981,7 +981,7 @@ void snd_usbmidi_disconnect(struct list_head* p)
|
||||
if (umidi->usb_protocol_ops->finish_out_endpoint)
|
||||
umidi->usb_protocol_ops->finish_out_endpoint(ep->out);
|
||||
}
|
||||
if (ep->in && ep->in->urb)
|
||||
if (ep->in)
|
||||
usb_kill_urb(ep->in->urb);
|
||||
}
|
||||
}
|
||||
|
@ -1620,8 +1620,7 @@ static void snd_usb_mixer_free(struct usb_mixer_interface *mixer)
|
||||
kfree(mixer->urb->transfer_buffer);
|
||||
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);
|
||||
}
|
||||
@ -2056,8 +2055,6 @@ void snd_usb_mixer_disconnect(struct list_head *p)
|
||||
struct usb_mixer_interface *mixer;
|
||||
|
||||
mixer = list_entry(p, struct usb_mixer_interface, list);
|
||||
if (mixer->urb)
|
||||
usb_kill_urb(mixer->urb);
|
||||
if (mixer->rc_urb)
|
||||
usb_kill_urb(mixer->rc_urb);
|
||||
usb_kill_urb(mixer->urb);
|
||||
usb_kill_urb(mixer->rc_urb);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user