Commit 9f8e35fc authored by Linus Torvalds's avatar Linus Torvalds

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

* master.kernel.org:/pub/scm/linux/kernel/git/gregkh/usb-2.6:
  USB: "sparse" cleanups for usb gadgets
  usb-serial: Fix edgeport regression on non-EPiC devices
  USB: more pxa2xx_udc dead code removal
  USB: NIKON D50 is an unusual device
  USB: drivers/usb/serial/sierra.c: make 3 functions static
  USB: fix BUG: sleeping function called from invalid context at /home/jeremy/hg/xen/paravirt/linux/drivers/usb/core/urb.c:524, in_atomic():1, irqs_disabled():0
  USB: mct_u232: Convert to proper speed handling API
  digi_acceleport: Drag the driver kicking and screaming into coding style
  cp2101: Remove broken termios optimisation, use proper speed API
  USB: Fix a bug in usb_start_wait_urb
  USB: fix scatterlist PIO case (IOMMU)
  USB: fix usb_serial_suspend(): buggy code
  USB: yet another quirky device
  USB: Add CanonScan LiDE30 to the quirk list
  USB: even more quirks
  USB: usb.h kernel-doc additions
  USB: more quirky devices
  USB: Don't let usb-storage steal Blackberry Pearl
  USB: devices misc: Trivial patch to build the IOWARRIOR when it is selected in Kconfig
parents 970e2dfa a9475226
...@@ -48,6 +48,7 @@ obj-$(CONFIG_USB_SISUSBVGA) += misc/ ...@@ -48,6 +48,7 @@ obj-$(CONFIG_USB_SISUSBVGA) += misc/
obj-$(CONFIG_USB_TEST) += misc/ obj-$(CONFIG_USB_TEST) += misc/
obj-$(CONFIG_USB_TRANCEVIBRATOR)+= misc/ obj-$(CONFIG_USB_TRANCEVIBRATOR)+= misc/
obj-$(CONFIG_USB_USS720) += misc/ obj-$(CONFIG_USB_USS720) += misc/
obj-$(CONFIG_USB_IOWARRIOR) += misc/
obj-$(CONFIG_USB_ATM) += atm/ obj-$(CONFIG_USB_ATM) += atm/
obj-$(CONFIG_USB_SPEEDTOUCH) += atm/ obj-$(CONFIG_USB_SPEEDTOUCH) += atm/
...@@ -18,9 +18,17 @@ ...@@ -18,9 +18,17 @@
#include "hcd.h" /* for usbcore internals */ #include "hcd.h" /* for usbcore internals */
#include "usb.h" #include "usb.h"
struct api_context {
struct completion done;
int status;
};
static void usb_api_blocking_completion(struct urb *urb) static void usb_api_blocking_completion(struct urb *urb)
{ {
complete((struct completion *)urb->context); struct api_context *ctx = urb->context;
ctx->status = urb->status;
complete(&ctx->done);
} }
...@@ -32,20 +40,21 @@ static void usb_api_blocking_completion(struct urb *urb) ...@@ -32,20 +40,21 @@ static void usb_api_blocking_completion(struct urb *urb)
*/ */
static int usb_start_wait_urb(struct urb *urb, int timeout, int *actual_length) static int usb_start_wait_urb(struct urb *urb, int timeout, int *actual_length)
{ {
struct completion done; struct api_context ctx;
unsigned long expire; unsigned long expire;
int retval; int retval;
int status = urb->status;
init_completion(&done); init_completion(&ctx.done);
urb->context = &done; urb->context = &ctx;
urb->actual_length = 0; urb->actual_length = 0;
retval = usb_submit_urb(urb, GFP_NOIO); retval = usb_submit_urb(urb, GFP_NOIO);
if (unlikely(retval)) if (unlikely(retval))
goto out; goto out;
expire = timeout ? msecs_to_jiffies(timeout) : MAX_SCHEDULE_TIMEOUT; expire = timeout ? msecs_to_jiffies(timeout) : MAX_SCHEDULE_TIMEOUT;
if (!wait_for_completion_timeout(&done, expire)) { if (!wait_for_completion_timeout(&ctx.done, expire)) {
usb_kill_urb(urb);
retval = (ctx.status == -ENOENT ? -ETIMEDOUT : ctx.status);
dev_dbg(&urb->dev->dev, dev_dbg(&urb->dev->dev,
"%s timed out on ep%d%s len=%d/%d\n", "%s timed out on ep%d%s len=%d/%d\n",
...@@ -54,11 +63,8 @@ static int usb_start_wait_urb(struct urb *urb, int timeout, int *actual_length) ...@@ -54,11 +63,8 @@ static int usb_start_wait_urb(struct urb *urb, int timeout, int *actual_length)
usb_pipein(urb->pipe) ? "in" : "out", usb_pipein(urb->pipe) ? "in" : "out",
urb->actual_length, urb->actual_length,
urb->transfer_buffer_length); urb->transfer_buffer_length);
usb_kill_urb(urb);
retval = status == -ENOENT ? -ETIMEDOUT : status;
} else } else
retval = status; retval = ctx.status;
out: out:
if (actual_length) if (actual_length)
*actual_length = urb->actual_length; *actual_length = urb->actual_length;
...@@ -411,15 +417,22 @@ int usb_sg_init ( ...@@ -411,15 +417,22 @@ int usb_sg_init (
* Some systems need to revert to PIO when DMA is temporarily * Some systems need to revert to PIO when DMA is temporarily
* unavailable. For their sakes, both transfer_buffer and * unavailable. For their sakes, both transfer_buffer and
* transfer_dma are set when possible. However this can only * transfer_dma are set when possible. However this can only
* work on systems without HIGHMEM, since DMA buffers located * work on systems without:
* in high memory are not directly addressable by the CPU for *
* PIO ... so when HIGHMEM is in use, transfer_buffer is NULL * - HIGHMEM, since DMA buffers located in high memory are
* not directly addressable by the CPU for PIO;
*
* - IOMMU, since dma_map_sg() is allowed to use an IOMMU to
* make virtually discontiguous buffers be "dma-contiguous"
* so that PIO and DMA need diferent numbers of URBs.
*
* So when HIGHMEM or IOMMU are in use, transfer_buffer is NULL
* to prevent stale pointers and to help spot bugs. * to prevent stale pointers and to help spot bugs.
*/ */
if (dma) { if (dma) {
io->urbs [i]->transfer_dma = sg_dma_address (sg + i); io->urbs [i]->transfer_dma = sg_dma_address (sg + i);
len = sg_dma_len (sg + i); len = sg_dma_len (sg + i);
#ifdef CONFIG_HIGHMEM #if defined(CONFIG_HIGHMEM) || defined(CONFIG_IOMMU)
io->urbs[i]->transfer_buffer = NULL; io->urbs[i]->transfer_buffer = NULL;
#else #else
io->urbs[i]->transfer_buffer = io->urbs[i]->transfer_buffer =
......
...@@ -30,18 +30,40 @@ ...@@ -30,18 +30,40 @@
static const struct usb_device_id usb_quirk_list[] = { static const struct usb_device_id usb_quirk_list[] = {
/* HP 5300/5370C scanner */ /* HP 5300/5370C scanner */
{ USB_DEVICE(0x03f0, 0x0701), .driver_info = USB_QUIRK_STRING_FETCH_255 }, { USB_DEVICE(0x03f0, 0x0701), .driver_info = USB_QUIRK_STRING_FETCH_255 },
/* Acer Peripherals Inc. (now BenQ Corp.) Prisa 640BU */
{ USB_DEVICE(0x04a5, 0x207e), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
/* Benq S2W 3300U */ /* Benq S2W 3300U */
{ USB_DEVICE(0x04a5, 0x20b0), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, { USB_DEVICE(0x04a5, 0x20b0), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
/* Canon, Inc. CanoScan N1240U/LiDE30 */
{ USB_DEVICE(0x04a9, 0x220e), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
/* Canon, Inc. CanoScan N650U/N656U */
{ USB_DEVICE(0x04a9, 0x2206), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
/* Canon, Inc. CanoScan 1220U */
{ USB_DEVICE(0x04a9, 0x2207), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
/* Canon, Inc. CanoScan N670U/N676U/LiDE 20 */
{ USB_DEVICE(0x04a9, 0x220d), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
/* old Cannon scanner */
{ USB_DEVICE(0x04a9, 0x2220), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
/* Seiko Epson Corp. Perfection 1200 */ /* Seiko Epson Corp. Perfection 1200 */
{ USB_DEVICE(0x04b8, 0x0104), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, { USB_DEVICE(0x04b8, 0x0104), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
/* Seiko Epson Corp. Perfection 660 */
{ USB_DEVICE(0x04b8, 0x0114), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
/* Epson Perfection 1260 Photo */
{ USB_DEVICE(0x04b8, 0x011d), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
/* Seiko Epson Corp - Perfection 1670 */ /* Seiko Epson Corp - Perfection 1670 */
{ USB_DEVICE(0x04b8, 0x011f), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, { USB_DEVICE(0x04b8, 0x011f), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
/* EPSON Perfection 2480 */
{ USB_DEVICE(0x04b8, 0x0121), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
/* Seiko Epson Corp.*/
{ USB_DEVICE(0x04b8, 0x0122), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
/* Samsung ML-2510 Series printer */ /* Samsung ML-2510 Series printer */
{ USB_DEVICE(0x04e8, 0x327e), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, { USB_DEVICE(0x04e8, 0x327e), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
/* Elsa MicroLink 56k (V.250) */ /* Elsa MicroLink 56k (V.250) */
{ USB_DEVICE(0x05cc, 0x2267), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, { USB_DEVICE(0x05cc, 0x2267), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
/* Ultima Electronics Corp.*/ /* Ultima Electronics Corp.*/
{ USB_DEVICE(0x05d8, 0x4005), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, { USB_DEVICE(0x05d8, 0x4005), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
/* Agfa Snapscan1212u */
{ USB_DEVICE(0x06bd, 0x2061), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
/* Umax [hex] Astra 3400U */ /* Umax [hex] Astra 3400U */
{ USB_DEVICE(0x1606, 0x0060), .driver_info = USB_QUIRK_NO_AUTOSUSPEND }, { USB_DEVICE(0x1606, 0x0060), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
......
...@@ -50,7 +50,7 @@ usb_descriptor_fillbuf(void *buf, unsigned buflen, ...@@ -50,7 +50,7 @@ usb_descriptor_fillbuf(void *buf, unsigned buflen,
return -EINVAL; return -EINVAL;
/* fill buffer from src[] until null descriptor ptr */ /* fill buffer from src[] until null descriptor ptr */
for (; 0 != *src; src++) { for (; NULL != *src; src++) {
unsigned len = (*src)->bLength; unsigned len = (*src)->bLength;
if (len > buflen) if (len > buflen)
......
...@@ -71,7 +71,7 @@ ep_matches ( ...@@ -71,7 +71,7 @@ ep_matches (
u16 max; u16 max;
/* endpoint already claimed? */ /* endpoint already claimed? */
if (0 != ep->driver_data) if (NULL != ep->driver_data)
return 0; return 0;
/* only support ep0 for portable CONTROL traffic */ /* only support ep0 for portable CONTROL traffic */
......
...@@ -1723,7 +1723,8 @@ rx_submit (struct eth_dev *dev, struct usb_request *req, gfp_t gfp_flags) ...@@ -1723,7 +1723,8 @@ rx_submit (struct eth_dev *dev, struct usb_request *req, gfp_t gfp_flags)
size += sizeof (struct rndis_packet_msg_type); size += sizeof (struct rndis_packet_msg_type);
size -= size % dev->out_ep->maxpacket; size -= size % dev->out_ep->maxpacket;
if ((skb = alloc_skb (size + NET_IP_ALIGN, gfp_flags)) == 0) { skb = alloc_skb(size + NET_IP_ALIGN, gfp_flags);
if (skb == NULL) {
DEBUG (dev, "no rx skb\n"); DEBUG (dev, "no rx skb\n");
goto enomem; goto enomem;
} }
......
...@@ -964,7 +964,7 @@ static int setup_req (struct usb_ep *ep, struct usb_request *req, u16 len) ...@@ -964,7 +964,7 @@ static int setup_req (struct usb_ep *ep, struct usb_request *req, u16 len)
} }
if (len > sizeof (dev->rbuf)) if (len > sizeof (dev->rbuf))
req->buf = kmalloc(len, GFP_ATOMIC); req->buf = kmalloc(len, GFP_ATOMIC);
if (req->buf == 0) { if (req->buf == NULL) {
req->buf = dev->rbuf; req->buf = dev->rbuf;
return -ENOMEM; return -ENOMEM;
} }
...@@ -1394,7 +1394,7 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) ...@@ -1394,7 +1394,7 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
dev->setup_abort = 0; dev->setup_abort = 0;
if (dev->state == STATE_DEV_UNCONNECTED) { if (dev->state == STATE_DEV_UNCONNECTED) {
#ifdef CONFIG_USB_GADGET_DUALSPEED #ifdef CONFIG_USB_GADGET_DUALSPEED
if (gadget->speed == USB_SPEED_HIGH && dev->hs_config == 0) { if (gadget->speed == USB_SPEED_HIGH && dev->hs_config == NULL) {
spin_unlock(&dev->lock); spin_unlock(&dev->lock);
ERROR (dev, "no high speed config??\n"); ERROR (dev, "no high speed config??\n");
return -EINVAL; return -EINVAL;
......
...@@ -1299,7 +1299,7 @@ static int m66592_queue(struct usb_ep *_ep, struct usb_request *_req, ...@@ -1299,7 +1299,7 @@ static int m66592_queue(struct usb_ep *_ep, struct usb_request *_req,
req->req.actual = 0; req->req.actual = 0;
req->req.status = -EINPROGRESS; req->req.status = -EINPROGRESS;
if (ep->desc == 0) /* control */ if (ep->desc == NULL) /* control */
start_ep0(ep, req); start_ep0(ep, req);
else { else {
if (request && !ep->busy) if (request && !ep->busy)
......
...@@ -93,8 +93,6 @@ static const char driver_name [] = "pxa2xx_udc"; ...@@ -93,8 +93,6 @@ static const char driver_name [] = "pxa2xx_udc";
static const char ep0name [] = "ep0"; static const char ep0name [] = "ep0";
// #define DISABLE_TEST_MODE
#ifdef CONFIG_ARCH_IXP4XX #ifdef CONFIG_ARCH_IXP4XX
/* cpu-specific register addresses are compiled in to this code */ /* cpu-specific register addresses are compiled in to this code */
...@@ -113,17 +111,6 @@ static const char ep0name [] = "ep0"; ...@@ -113,17 +111,6 @@ static const char ep0name [] = "ep0";
#define SIZE_STR "" #define SIZE_STR ""
#endif #endif
#ifdef DISABLE_TEST_MODE
/* (mode == 0) == no undocumented chip tweaks
* (mode & 1) == double buffer bulk IN
* (mode & 2) == double buffer bulk OUT
* ... so mode = 3 (or 7, 15, etc) does it for both
*/
static ushort fifo_mode = 0;
module_param(fifo_mode, ushort, 0);
MODULE_PARM_DESC (fifo_mode, "pxa2xx udc fifo mode");
#endif
/* --------------------------------------------------------------------------- /* ---------------------------------------------------------------------------
* endpoint related parts of the api to the usb controller hardware, * endpoint related parts of the api to the usb controller hardware,
* used by gadget driver; and the inner talker-to-hardware core. * used by gadget driver; and the inner talker-to-hardware core.
...@@ -1252,23 +1239,6 @@ static void udc_enable (struct pxa2xx_udc *dev) ...@@ -1252,23 +1239,6 @@ static void udc_enable (struct pxa2xx_udc *dev)
UDC_RES2 = 0x00; UDC_RES2 = 0x00;
} }
#ifdef DISABLE_TEST_MODE
/* "test mode" seems to have become the default in later chip
* revs, preventing double buffering (and invalidating docs).
* this EXPERIMENT enables it for bulk endpoints by tweaking
* undefined/reserved register bits (that other drivers clear).
* Belcarra code comments noted this usage.
*/
if (fifo_mode & 1) { /* IN endpoints */
UDC_RES1 |= USIR0_IR1|USIR0_IR6;
UDC_RES2 |= USIR1_IR11;
}
if (fifo_mode & 2) { /* OUT endpoints */
UDC_RES1 |= USIR0_IR2|USIR0_IR7;
UDC_RES2 |= USIR1_IR12;
}
#endif
/* enable suspend/resume and reset irqs */ /* enable suspend/resume and reset irqs */
udc_clear_mask_UDCCR(UDCCR_SRM | UDCCR_REM); udc_clear_mask_UDCCR(UDCCR_SRM | UDCCR_REM);
......
...@@ -653,7 +653,8 @@ set_source_sink_config (struct zero_dev *dev, gfp_t gfp_flags) ...@@ -653,7 +653,8 @@ set_source_sink_config (struct zero_dev *dev, gfp_t gfp_flags)
result = usb_ep_enable (ep, d); result = usb_ep_enable (ep, d);
if (result == 0) { if (result == 0) {
ep->driver_data = dev; ep->driver_data = dev;
if (source_sink_start_ep (ep, gfp_flags) != 0) { if (source_sink_start_ep(ep, gfp_flags)
!= NULL) {
dev->in_ep = ep; dev->in_ep = ep;
continue; continue;
} }
...@@ -667,7 +668,8 @@ set_source_sink_config (struct zero_dev *dev, gfp_t gfp_flags) ...@@ -667,7 +668,8 @@ set_source_sink_config (struct zero_dev *dev, gfp_t gfp_flags)
result = usb_ep_enable (ep, d); result = usb_ep_enable (ep, d);
if (result == 0) { if (result == 0) {
ep->driver_data = dev; ep->driver_data = dev;
if (source_sink_start_ep (ep, gfp_flags) != 0) { if (source_sink_start_ep(ep, gfp_flags)
!= NULL) {
dev->out_ep = ep; dev->out_ep = ep;
continue; continue;
} }
......
...@@ -356,7 +356,7 @@ static void cp2101_get_termios (struct usb_serial_port *port) ...@@ -356,7 +356,7 @@ static void cp2101_get_termios (struct usb_serial_port *port)
dbg("%s - port %d", __FUNCTION__, port->number); dbg("%s - port %d", __FUNCTION__, port->number);
if ((!port->tty) || (!port->tty->termios)) { if (!port->tty || !port->tty->termios) {
dbg("%s - no tty structures", __FUNCTION__); dbg("%s - no tty structures", __FUNCTION__);
return; return;
} }
...@@ -526,50 +526,35 @@ static void cp2101_set_termios (struct usb_serial_port *port, ...@@ -526,50 +526,35 @@ static void cp2101_set_termios (struct usb_serial_port *port,
return; return;
} }
cflag = port->tty->termios->c_cflag; cflag = port->tty->termios->c_cflag;
old_cflag = old_termios->c_cflag;
/* Check that they really want us to change something */ baud = tty_get_baud_rate(port->tty);
if (old_termios) {
if ((cflag == old_termios->c_cflag) &&
(RELEVANT_IFLAG(port->tty->termios->c_iflag)
== RELEVANT_IFLAG(old_termios->c_iflag))) {
dbg("%s - nothing to change...", __FUNCTION__);
return;
}
old_cflag = old_termios->c_cflag;
}
/* If the baud rate is to be updated*/ /* If the baud rate is to be updated*/
if ((cflag & CBAUD) != (old_cflag & CBAUD)) { if (baud != tty_termios_baud_rate(old_termios)) {
switch (cflag & CBAUD) { switch (baud) {
/* case 0:
* The baud rates which are commented out below case 600:
* appear to be supported by the device case 1200:
* but are non-standard case 1800:
*/ case 2400:
case B0: baud = 0; break; case 4800:
case B600: baud = 600; break; case 7200:
case B1200: baud = 1200; break; case 9600:
case B1800: baud = 1800; break; case 14400:
case B2400: baud = 2400; break; case 19200:
case B4800: baud = 4800; break; case 28800:
/*case B7200: baud = 7200; break;*/ case 38400:
case B9600: baud = 9600; break; case 55854:
/*ase B14400: baud = 14400; break;*/ case 57600:
case B19200: baud = 19200; break; case 115200:
/*case B28800: baud = 28800; break;*/ case 127117:
case B38400: baud = 38400; break; case 230400:
/*case B55854: baud = 55054; break;*/ case 460800:
case B57600: baud = 57600; break; case 921600:
case B115200: baud = 115200; break; case 3686400:
/*case B127117: baud = 127117; break;*/ break;
case B230400: baud = 230400; break;
case B460800: baud = 460800; break;
case B921600: baud = 921600; break;
/*case B3686400: baud = 3686400; break;*/
default: default:
dev_err(&port->dev, "cp2101 driver does not " baud = 9600;
"support the baudrate requested\n");
break; break;
} }
......
...@@ -433,38 +433,38 @@ struct digi_port { ...@@ -433,38 +433,38 @@ struct digi_port {
/* Local Function Declarations */ /* Local Function Declarations */
static void digi_wakeup_write( struct usb_serial_port *port ); static void digi_wakeup_write(struct usb_serial_port *port);
static void digi_wakeup_write_lock(struct work_struct *work); static void digi_wakeup_write_lock(struct work_struct *work);
static int digi_write_oob_command( struct usb_serial_port *port, static int digi_write_oob_command(struct usb_serial_port *port,
unsigned char *buf, int count, int interruptible ); unsigned char *buf, int count, int interruptible);
static int digi_write_inb_command( struct usb_serial_port *port, static int digi_write_inb_command(struct usb_serial_port *port,
unsigned char *buf, int count, unsigned long timeout ); unsigned char *buf, int count, unsigned long timeout);
static int digi_set_modem_signals( struct usb_serial_port *port, static int digi_set_modem_signals(struct usb_serial_port *port,
unsigned int modem_signals, int interruptible ); unsigned int modem_signals, int interruptible);
static int digi_transmit_idle( struct usb_serial_port *port, static int digi_transmit_idle(struct usb_serial_port *port,
unsigned long timeout ); unsigned long timeout);
static void digi_rx_throttle (struct usb_serial_port *port); static void digi_rx_throttle (struct usb_serial_port *port);
static void digi_rx_unthrottle (struct usb_serial_port *port); static void digi_rx_unthrottle (struct usb_serial_port *port);
static void digi_set_termios( struct usb_serial_port *port, static void digi_set_termios(struct usb_serial_port *port,
struct ktermios *old_termios ); struct ktermios *old_termios);
static void digi_break_ctl( struct usb_serial_port *port, int break_state ); static void digi_break_ctl(struct usb_serial_port *port, int break_state);
static int digi_ioctl( struct usb_serial_port *port, struct file *file, static int digi_ioctl(struct usb_serial_port *port, struct file *file,
unsigned int cmd, unsigned long arg ); unsigned int cmd, unsigned long arg);
static int digi_tiocmget( struct usb_serial_port *port, struct file *file ); static int digi_tiocmget(struct usb_serial_port *port, struct file *file);
static int digi_tiocmset( struct usb_serial_port *port, struct file *file, static int digi_tiocmset(struct usb_serial_port *port, struct file *file,
unsigned int set, unsigned int clear ); unsigned int set, unsigned int clear);
static int digi_write( struct usb_serial_port *port, const unsigned char *buf, int count ); static int digi_write(struct usb_serial_port *port, const unsigned char *buf, int count);
static void digi_write_bulk_callback( struct urb *urb ); static void digi_write_bulk_callback(struct urb *urb);
static int digi_write_room( struct usb_serial_port *port ); static int digi_write_room(struct usb_serial_port *port);
static int digi_chars_in_buffer( struct usb_serial_port *port ); static int digi_chars_in_buffer(struct usb_serial_port *port);
static int digi_open( struct usb_serial_port *port, struct file *filp ); static int digi_open(struct usb_serial_port *port, struct file *filp);
static void digi_close( struct usb_serial_port *port, struct file *filp ); static void digi_close(struct usb_serial_port *port, struct file *filp);
static int digi_startup_device( struct usb_serial *serial ); static int digi_startup_device(struct usb_serial *serial);
static int digi_startup( struct usb_serial *serial ); static int digi_startup(struct usb_serial *serial);
static void digi_shutdown( struct usb_serial *serial ); static void digi_shutdown(struct usb_serial *serial);
static void digi_read_bulk_callback( struct urb *urb ); static void digi_read_bulk_callback(struct urb *urb);
static int digi_read_inb_callback( struct urb *urb ); static int digi_read_inb_callback(struct urb *urb);
static int digi_read_oob_callback( struct urb *urb ); static int digi_read_oob_callback(struct urb *urb);
/* Statics */ /* Statics */
...@@ -576,9 +576,9 @@ static struct usb_serial_driver digi_acceleport_4_device = { ...@@ -576,9 +576,9 @@ static struct usb_serial_driver digi_acceleport_4_device = {
* with the equivalent code. * with the equivalent code.
*/ */
static inline long cond_wait_interruptible_timeout_irqrestore( static long cond_wait_interruptible_timeout_irqrestore(
wait_queue_head_t *q, long timeout, wait_queue_head_t *q, long timeout,
spinlock_t *lock, unsigned long flags ) spinlock_t *lock, unsigned long flags)
{ {
DEFINE_WAIT(wait); DEFINE_WAIT(wait);
...@@ -600,18 +600,16 @@ static inline long cond_wait_interruptible_timeout_irqrestore( ...@@ -600,18 +600,16 @@ static inline long cond_wait_interruptible_timeout_irqrestore(
static void digi_wakeup_write_lock(struct work_struct *work) static void digi_wakeup_write_lock(struct work_struct *work)
{ {
struct digi_port *priv = struct digi_port *priv = container_of(work, struct digi_port, dp_wakeup_work);
container_of(work, struct digi_port, dp_wakeup_work);
struct usb_serial_port *port = priv->dp_port; struct usb_serial_port *port = priv->dp_port;
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&priv->dp_port_lock, flags);
spin_lock_irqsave( &priv->dp_port_lock, flags ); digi_wakeup_write(port);
digi_wakeup_write( port ); spin_unlock_irqrestore(&priv->dp_port_lock, flags);
spin_unlock_irqrestore( &priv->dp_port_lock, flags );
} }
static void digi_wakeup_write( struct usb_serial_port *port ) static void digi_wakeup_write(struct usb_serial_port *port)
{ {
tty_wakeup(port->tty); tty_wakeup(port->tty);
} }
...@@ -628,8 +626,8 @@ static void digi_wakeup_write( struct usb_serial_port *port ) ...@@ -628,8 +626,8 @@ static void digi_wakeup_write( struct usb_serial_port *port )
* returned by usb_submit_urb. * returned by usb_submit_urb.
*/ */
static int digi_write_oob_command( struct usb_serial_port *port, static int digi_write_oob_command(struct usb_serial_port *port,
unsigned char *buf, int count, int interruptible ) unsigned char *buf, int count, int interruptible)
{ {
int ret = 0; int ret = 0;
...@@ -638,49 +636,37 @@ static int digi_write_oob_command( struct usb_serial_port *port, ...@@ -638,49 +636,37 @@ static int digi_write_oob_command( struct usb_serial_port *port,
struct digi_port *oob_priv = usb_get_serial_port_data(oob_port); struct digi_port *oob_priv = usb_get_serial_port_data(oob_port);
unsigned long flags = 0; unsigned long flags = 0;
dbg("digi_write_oob_command: TOP: port=%d, count=%d", oob_priv->dp_port_num, count);
dbg( "digi_write_oob_command: TOP: port=%d, count=%d", oob_priv->dp_port_num, count ); spin_lock_irqsave(&oob_priv->dp_port_lock, flags);
while(count > 0) {
spin_lock_irqsave( &oob_priv->dp_port_lock, flags ); while(oob_port->write_urb->status == -EINPROGRESS
|| oob_priv->dp_write_urb_in_use) {
while( count > 0 ) {
while( oob_port->write_urb->status == -EINPROGRESS
|| oob_priv->dp_write_urb_in_use ) {
cond_wait_interruptible_timeout_irqrestore( cond_wait_interruptible_timeout_irqrestore(
&oob_port->write_wait, DIGI_RETRY_TIMEOUT, &oob_port->write_wait, DIGI_RETRY_TIMEOUT,
&oob_priv->dp_port_lock, flags ); &oob_priv->dp_port_lock, flags);
if( interruptible && signal_pending(current) ) { if (interruptible && signal_pending(current))
return( -EINTR ); return -EINTR;
} spin_lock_irqsave(&oob_priv->dp_port_lock, flags);
spin_lock_irqsave( &oob_priv->dp_port_lock, flags );
} }
/* len must be a multiple of 4, so commands are not split */ /* len must be a multiple of 4, so commands are not split */
len = min(count, oob_port->bulk_out_size ); len = min(count, oob_port->bulk_out_size);
if( len > 4 ) if (len > 4)
len &= ~3; len &= ~3;
memcpy(oob_port->write_urb->transfer_buffer, buf, len);
memcpy( oob_port->write_urb->transfer_buffer, buf, len );
oob_port->write_urb->transfer_buffer_length = len; oob_port->write_urb->transfer_buffer_length = len;
oob_port->write_urb->dev = port->serial->dev; oob_port->write_urb->dev = port->serial->dev;
if ((ret = usb_submit_urb(oob_port->write_urb, GFP_ATOMIC)) == 0) {
if( (ret=usb_submit_urb(oob_port->write_urb, GFP_ATOMIC)) == 0 ) {
oob_priv->dp_write_urb_in_use = 1; oob_priv->dp_write_urb_in_use = 1;
count -= len; count -= len;
buf += len; buf += len;
} }
}
spin_unlock_irqrestore( &oob_priv->dp_port_lock, flags );
if( ret ) {
err("%s: usb_submit_urb failed, ret=%d", __FUNCTION__,
ret );
} }
spin_unlock_irqrestore(&oob_priv->dp_port_lock, flags);
return( ret ); if (ret)
err("%s: usb_submit_urb failed, ret=%d", __FUNCTION__, ret);
return ret;
} }
...@@ -697,63 +683,58 @@ dbg( "digi_write_oob_command: TOP: port=%d, count=%d", oob_priv->dp_port_num, co ...@@ -697,63 +683,58 @@ dbg( "digi_write_oob_command: TOP: port=%d, count=%d", oob_priv->dp_port_num, co
* error returned by digi_write. * error returned by digi_write.
*/ */
static int digi_write_inb_command( struct usb_serial_port *port, static int digi_write_inb_command(struct usb_serial_port *port,
unsigned char *buf, int count, unsigned long timeout ) unsigned char *buf, int count, unsigned long timeout)
{ {
int ret = 0; int ret = 0;
int len; int len;
struct digi_port *priv = usb_get_serial_port_data(port); struct digi_port *priv = usb_get_serial_port_data(port);
unsigned char *data = port->write_urb->transfer_buffer; unsigned char *data = port->write_urb->transfer_buffer;
unsigned long flags = 0; unsigned long flags = 0;
dbg("digi_write_inb_command: TOP: port=%d, count=%d",
priv->dp_port_num, count);
dbg( "digi_write_inb_command: TOP: port=%d, count=%d", priv->dp_port_num, if (timeout)
count );
if( timeout )
timeout += jiffies; timeout += jiffies;
else else
timeout = ULONG_MAX; timeout = ULONG_MAX;
spin_lock_irqsave( &priv->dp_port_lock, flags ); spin_lock_irqsave(&priv->dp_port_lock, flags);
while(count > 0 && ret == 0) {
while( count > 0 && ret == 0 ) { while((port->write_urb->status == -EINPROGRESS
|| priv->dp_write_urb_in_use) && time_before(jiffies, timeout)) {
while( (port->write_urb->status == -EINPROGRESS
|| priv->dp_write_urb_in_use) && time_before(jiffies, timeout)) {
cond_wait_interruptible_timeout_irqrestore( cond_wait_interruptible_timeout_irqrestore(
&port->write_wait, DIGI_RETRY_TIMEOUT, &port->write_wait, DIGI_RETRY_TIMEOUT,
&priv->dp_port_lock, flags ); &priv->dp_port_lock, flags);
if( signal_pending(current) ) { if (signal_pending(current))
return( -EINTR ); return -EINTR;
} spin_lock_irqsave(&priv->dp_port_lock, flags);
spin_lock_irqsave( &priv->dp_port_lock, flags );
} }
/* len must be a multiple of 4 and small enough to */ /* len must be a multiple of 4 and small enough to */
/* guarantee the write will send buffered data first, */ /* guarantee the write will send buffered data first, */
/* so commands are in order with data and not split */ /* so commands are in order with data and not split */
len = min(count, port->bulk_out_size-2-priv->dp_out_buf_len ); len = min(count, port->bulk_out_size-2-priv->dp_out_buf_len);
if( len > 4 ) if (len > 4)
len &= ~3; len &= ~3;
/* write any buffered data first */ /* write any buffered data first */
if( priv->dp_out_buf_len > 0 ) { if (priv->dp_out_buf_len > 0) {
data[0] = DIGI_CMD_SEND_DATA; data[0] = DIGI_CMD_SEND_DATA;
data[1] = priv->dp_out_buf_len; data[1] = priv->dp_out_buf_len;
memcpy( data+2, priv->dp_out_buf, memcpy(data + 2, priv->dp_out_buf,
priv->dp_out_buf_len ); priv->dp_out_buf_len);
memcpy( data+2+priv->dp_out_buf_len, buf, len ); memcpy(data + 2 + priv->dp_out_buf_len, buf, len);
port->write_urb->transfer_buffer_length port->write_urb->transfer_buffer_length
= priv->dp_out_buf_len+2+len; = priv->dp_out_buf_len + 2 + len;
} else { } else {
memcpy( data, buf, len ); memcpy(data, buf, len);
port->write_urb->transfer_buffer_length = len; port->write_urb->transfer_buffer_length = len;
} }
port->write_urb->dev = port->serial->dev; port->write_urb->dev = port->serial->dev;
if( (ret=usb_submit_urb(port->write_urb, GFP_ATOMIC)) == 0 ) { if ((ret = usb_submit_urb(port->write_urb, GFP_ATOMIC)) == 0) {
priv->dp_write_urb_in_use = 1; priv->dp_write_urb_in_use = 1;
priv->dp_out_buf_len = 0; priv->dp_out_buf_len = 0;
count -= len; count -= len;
...@@ -761,16 +742,12 @@ count ); ...@@ -761,16 +742,12 @@ count );
} }
} }
spin_unlock_irqrestore(&priv->dp_port_lock, flags);
spin_unlock_irqrestore( &priv->dp_port_lock, flags ); if (ret)
err("%s: usb_submit_urb failed, ret=%d, port=%d",
if( ret ) { __FUNCTION__, ret, priv->dp_port_num);
err("%s: usb_submit_urb failed, ret=%d, port=%d", __FUNCTION__, return ret;
ret, priv->dp_port_num );
}
return( ret );
} }
...@@ -784,8 +761,8 @@ count ); ...@@ -784,8 +761,8 @@ count );
* returned by usb_submit_urb. * returned by usb_submit_urb.
*/ */
static int digi_set_modem_signals( struct usb_serial_port *port, static int digi_set_modem_signals(struct usb_serial_port *port,
unsigned int modem_signals, int interruptible ) unsigned int modem_signals, int interruptible)
{ {
int ret; int ret;
...@@ -796,60 +773,47 @@ static int digi_set_modem_signals( struct usb_serial_port *port, ...@@ -796,60 +773,47 @@ static int digi_set_modem_signals( struct usb_serial_port *port,
unsigned long flags = 0; unsigned long flags = 0;
dbg( "digi_set_modem_signals: TOP: port=%d, modem_signals=0x%x", dbg("digi_set_modem_signals: TOP: port=%d, modem_signals=0x%x",
port_priv->dp_port_num, modem_signals ); port_priv->dp_port_num, modem_signals);
spin_lock_irqsave( &oob_priv->dp_port_lock, flags ); spin_lock_irqsave(&oob_priv->dp_port_lock, flags);
spin_lock( &port_priv->dp_port_lock ); spin_lock(&port_priv->dp_port_lock);
while( oob_port->write_urb->status == -EINPROGRESS while(oob_port->write_urb->status == -EINPROGRESS || oob_priv->dp_write_urb_in_use) {
|| oob_priv->dp_write_urb_in_use ) { spin_unlock(&port_priv->dp_port_lock);
spin_unlock( &port_priv->dp_port_lock );
cond_wait_interruptible_timeout_irqrestore( cond_wait_interruptible_timeout_irqrestore(
&oob_port->write_wait, DIGI_RETRY_TIMEOUT, &oob_port->write_wait, DIGI_RETRY_TIMEOUT,
&oob_priv->dp_port_lock, flags ); &oob_priv->dp_port_lock, flags);
if( interruptible && signal_pending(current) ) { if (interruptible && signal_pending(current))
return( -EINTR ); return -EINTR;
} spin_lock_irqsave(&oob_priv->dp_port_lock, flags);
spin_lock_irqsave( &oob_priv->dp_port_lock, flags ); spin_lock(&port_priv->dp_port_lock);
spin_lock( &port_priv->dp_port_lock );
} }
data[0] = DIGI_CMD_SET_DTR_SIGNAL; data[0] = DIGI_CMD_SET_DTR_SIGNAL;
data[1] = port_priv->dp_port_num; data[1] = port_priv->dp_port_num;
data[2] = (modem_signals&TIOCM_DTR) ? data[2] = (modem_signals&TIOCM_DTR) ? DIGI_DTR_ACTIVE : DIGI_DTR_INACTIVE;
DIGI_DTR_ACTIVE : DIGI_DTR_INACTIVE;
data[3] = 0; data[3] = 0;
data[4] = DIGI_CMD_SET_RTS_SIGNAL; data[4] = DIGI_CMD_SET_RTS_SIGNAL;
data[5] = port_priv->dp_port_num; data[5] = port_priv->dp_port_num;
data[6] = (modem_signals&TIOCM_RTS) ? data[6] = (modem_signals&TIOCM_RTS) ? DIGI_RTS_ACTIVE : DIGI_RTS_INACTIVE;
DIGI_RTS_ACTIVE : DIGI_RTS_INACTIVE;
data[7] = 0; data[7] = 0;
oob_port->write_urb->transfer_buffer_length = 8; oob_port->write_urb->transfer_buffer_length = 8;
oob_port->write_urb->dev = port->serial->dev; oob_port->write_urb->dev = port->serial->dev;
if( (ret=usb_submit_urb(oob_port->write_urb, GFP_ATOMIC)) == 0 ) { if ((ret = usb_submit_urb(oob_port->write_urb, GFP_ATOMIC)) == 0) {
oob_priv->dp_write_urb_in_use = 1; oob_priv->dp_write_urb_in_use = 1;
port_priv->dp_modem_signals = port_priv->dp_modem_signals =
(port_priv->dp_modem_signals&~(TIOCM_DTR|TIOCM_RTS)) (port_priv->dp_modem_signals&~(TIOCM_DTR|TIOCM_RTS))
| (modem_signals&(TIOCM_DTR|TIOCM_RTS)); | (modem_signals&(TIOCM_DTR|TIOCM_RTS));
} }
spin_unlock(&port_priv->dp_port_lock);
spin_unlock( &port_priv->dp_port_lock ); spin_unlock_irqrestore(&oob_priv->dp_port_lock, flags);
spin_unlock_irqrestore( &oob_priv->dp_port_lock, flags ); if (ret)
err("%s: usb_submit_urb failed, ret=%d", __FUNCTION__, ret);
if( ret ) { return ret;
err("%s: usb_submit_urb failed, ret=%d", __FUNCTION__,
ret );
}
return( ret );
} }
/* /*
* Digi Transmit Idle * Digi Transmit Idle
* *
...@@ -862,203 +826,182 @@ port_priv->dp_port_num, modem_signals ); ...@@ -862,203 +826,182 @@ port_priv->dp_port_num, modem_signals );
* port at a time, so its ok. * port at a time, so its ok.
*/ */
static int digi_transmit_idle( struct usb_serial_port *port, static int digi_transmit_idle(struct usb_serial_port *port,
unsigned long timeout ) unsigned long timeout)
{ {
int ret; int ret;
unsigned char buf[2]; unsigned char buf[2];
struct digi_port *priv = usb_get_serial_port_data(port); struct digi_port *priv = usb_get_serial_port_data(port);
unsigned long flags = 0; unsigned long flags = 0;
spin_lock_irqsave(&priv->dp_port_lock, flags);
spin_lock_irqsave( &priv->dp_port_lock, flags );
priv->dp_transmit_idle = 0; priv->dp_transmit_idle = 0;
spin_unlock_irqrestore( &priv->dp_port_lock, flags ); spin_unlock_irqrestore(&priv->dp_port_lock, flags);
buf[0] = DIGI_CMD_TRANSMIT_IDLE; buf[0] = DIGI_CMD_TRANSMIT_IDLE;
buf[1] = 0; buf[1] = 0;
timeout += jiffies; timeout += jiffies;
if( (ret=digi_write_inb_command( port, buf, 2, timeout-jiffies )) != 0 ) if ((ret = digi_write_inb_command(port, buf, 2, timeout - jiffies)) != 0)
return( ret ); return ret;
spin_lock_irqsave( &priv->dp_port_lock, flags ); spin_lock_irqsave(&priv->dp_port_lock, flags);
while( time_before(jiffies, timeout) && !priv->dp_transmit_idle ) { while(time_before(jiffies, timeout) && !priv->dp_transmit_idle) {
cond_wait_interruptible_timeout_irqrestore( cond_wait_interruptible_timeout_irqrestore(
&priv->dp_transmit_idle_wait, DIGI_RETRY_TIMEOUT, &priv->dp_transmit_idle_wait, DIGI_RETRY_TIMEOUT,
&priv->dp_port_lock, flags ); &priv->dp_port_lock, flags);
if( signal_pending(current) ) { if (signal_pending(current))
return( -EINTR ); return -EINTR;
} spin_lock_irqsave(&priv->dp_port_lock, flags);
spin_lock_irqsave( &priv->dp_port_lock, flags );
} }
priv->dp_transmit_idle = 0; priv->dp_transmit_idle = 0;
spin_unlock_irqrestore( &priv->dp_port_lock, flags ); spin_unlock_irqrestore(&priv->dp_port_lock, flags);
return 0;
return( 0 );
} }
static void digi_rx_throttle( struct usb_serial_port *port ) static void digi_rx_throttle(struct usb_serial_port *port)
{ {
unsigned long flags; unsigned long flags;
struct digi_port *priv = usb_get_serial_port_data(port); struct digi_port *priv = usb_get_serial_port_data(port);
dbg( "digi_rx_throttle: TOP: port=%d", priv->dp_port_num ); dbg("digi_rx_throttle: TOP: port=%d", priv->dp_port_num);
/* stop receiving characters by not resubmitting the read urb */ /* stop receiving characters by not resubmitting the read urb */
spin_lock_irqsave( &priv->dp_port_lock, flags ); spin_lock_irqsave(&priv->dp_port_lock, flags);
priv->dp_throttled = 1; priv->dp_throttled = 1;
priv->dp_throttle_restart = 0; priv->dp_throttle_restart = 0;
spin_unlock_irqrestore( &priv->dp_port_lock, flags ); spin_unlock_irqrestore(&priv->dp_port_lock, flags);
} }
static void digi_rx_unthrottle( struct usb_serial_port *port ) static void digi_rx_unthrottle(struct usb_serial_port *port)
{ {
int ret = 0; int ret = 0;
unsigned long flags; unsigned long flags;
struct digi_port *priv = usb_get_serial_port_data(port); struct digi_port *priv = usb_get_serial_port_data(port);
dbg( "digi_rx_unthrottle: TOP: port=%d", priv->dp_port_num ); dbg("digi_rx_unthrottle: TOP: port=%d", priv->dp_port_num);
spin_lock_irqsave( &priv->dp_port_lock, flags ); spin_lock_irqsave(&priv->dp_port_lock, flags);
/* turn throttle off */ /* turn throttle off */
priv->dp_throttled = 0; priv->dp_throttled = 0;
priv->dp_throttle_restart = 0; priv->dp_throttle_restart = 0;
/* restart read chain */ /* restart read chain */
if( priv->dp_throttle_restart ) { if (priv->dp_throttle_restart) {
port->read_urb->dev = port->serial->dev; port->read_urb->dev = port->serial->dev;
ret = usb_submit_urb( port->read_urb, GFP_ATOMIC ); ret = usb_submit_urb(port->read_urb, GFP_ATOMIC);
} }
spin_unlock_irqrestore( &priv->dp_port_lock, flags ); spin_unlock_irqrestore(&priv->dp_port_lock, flags);
if( ret ) {
err("%s: usb_submit_urb failed, ret=%d, port=%d", __FUNCTION__,
ret, priv->dp_port_num );
}
if (ret)
err("%s: usb_submit_urb failed, ret=%d, port=%d",
__FUNCTION__, ret, priv->dp_port_num);
} }
static void digi_set_termios( struct usb_serial_port *port, static void digi_set_termios(struct usb_serial_port *port,
struct ktermios *old_termios ) struct ktermios *old_termios)
{ {
struct digi_port *priv = usb_get_serial_port_data(port); struct digi_port *priv = usb_get_serial_port_data(port);
unsigned int iflag = port->tty->termios->c_iflag; struct tty_struct *tty = port->tty;
unsigned int cflag = port->tty->termios->c_cflag; unsigned int iflag = tty->termios->c_iflag;
unsigned int cflag = tty->termios->c_cflag;
unsigned int old_iflag = old_termios->c_iflag; unsigned int old_iflag = old_termios->c_iflag;
unsigned int old_cflag = old_termios->c_cflag; unsigned int old_cflag = old_termios->c_cflag;
unsigned char buf[32]; unsigned char buf[32];
unsigned int modem_signals; unsigned int modem_signals;
int arg,ret; int arg,ret;
int i = 0; int i = 0;
speed_t baud;
dbg("digi_set_termios: TOP: port=%d, iflag=0x%x, old_iflag=0x%x, cflag=0x%x, old_cflag=0x%x", priv->dp_port_num, iflag, old_iflag, cflag, old_cflag);
dbg( "digi_set_termios: TOP: port=%d, iflag=0x%x, old_iflag=0x%x, cflag=0x%x, old_cflag=0x%x", priv->dp_port_num, iflag, old_iflag, cflag, old_cflag );
/* set baud rate */ /* set baud rate */
if( (cflag&CBAUD) != (old_cflag&CBAUD) ) { if ((baud = tty_get_baud_rate(tty)) != tty_termios_baud_rate(old_termios)) {
arg = -1; arg = -1;
/* reassert DTR and (maybe) RTS on transition from B0 */ /* reassert DTR and (maybe) RTS on transition from B0 */
if( (old_cflag&CBAUD) == B0 ) { if ((old_cflag&CBAUD) == B0) {
/* don't set RTS if using hardware flow control */ /* don't set RTS if using hardware flow control */
/* and throttling input */ /* and throttling input */
modem_signals = TIOCM_DTR; modem_signals = TIOCM_DTR;
if( !(port->tty->termios->c_cflag & CRTSCTS) || if (!(tty->termios->c_cflag & CRTSCTS) ||
!test_bit(TTY_THROTTLED, &port->tty->flags) ) { !test_bit(TTY_THROTTLED, &tty->flags))
modem_signals |= TIOCM_RTS; modem_signals |= TIOCM_RTS;
} digi_set_modem_signals(port, modem_signals, 1);
digi_set_modem_signals( port, modem_signals, 1 );
} }
switch (baud) {
switch( (cflag&CBAUD) ) {
/* drop DTR and RTS on transition to B0 */ /* drop DTR and RTS on transition to B0 */
case B0: digi_set_modem_signals( port, 0, 1 ); break; case 0: digi_set_modem_signals(port, 0, 1); break;
case B50: arg = DIGI_BAUD_50; break; case 50: arg = DIGI_BAUD_50; break;
case B75: arg = DIGI_BAUD_75; break; case 75: arg = DIGI_BAUD_75; break;
case B110: arg = DIGI_BAUD_110; break; case 110: arg = DIGI_BAUD_110; break;
case B150: arg = DIGI_BAUD_150; break; case 150: arg = DIGI_BAUD_150; break;
case B200: arg = DIGI_BAUD_200; break; case 200: arg = DIGI_BAUD_200; break;
case B300: arg = DIGI_BAUD_300; break; case 300: arg = DIGI_BAUD_300; break;
case B600: arg = DIGI_BAUD_600; break; case 600: arg = DIGI_BAUD_600; break;
case B1200: arg = DIGI_BAUD_1200; break; case 1200: arg = DIGI_BAUD_1200; break;
case B1800: arg = DIGI_BAUD_1800; break; case 1800: arg = DIGI_BAUD_1800; break;
case B2400: arg = DIGI_BAUD_2400; break; case 2400: arg = DIGI_BAUD_2400; break;
case B4800: arg = DIGI_BAUD_4800; break; case 4800: arg = DIGI_BAUD_4800; break;
case B9600: arg = DIGI_BAUD_9600; break; case 9600: arg = DIGI_BAUD_9600; break;
case B19200: arg = DIGI_BAUD_19200; break; case 19200: arg = DIGI_BAUD_19200; break;
case B38400: arg = DIGI_BAUD_38400; break; case 38400: arg = DIGI_BAUD_38400; break;
case B57600: arg = DIGI_BAUD_57600; break; case 57600: arg = DIGI_BAUD_57600; break;
case B115200: arg = DIGI_BAUD_115200; break; case 115200: arg = DIGI_BAUD_115200; break;
case B230400: arg = DIGI_BAUD_230400; break; case 230400: arg = DIGI_BAUD_230400; break;
case B460800: arg = DIGI_BAUD_460800; break; case 460800: arg = DIGI_BAUD_460800; break;
default: default:
dbg( "digi_set_termios: can't handle baud rate 0x%x", arg = DIGI_BAUD_9600;
(cflag&CBAUD) ); baud = 9600;
break; break;
} }
if (arg != -1) {
if( arg != -1 ) {
buf[i++] = DIGI_CMD_SET_BAUD_RATE; buf[i++] = DIGI_CMD_SET_BAUD_RATE;
buf[i++] = priv->dp_port_num; buf[i++] = priv->dp_port_num;
buf[i++] = arg; buf[i++] = arg;
buf[i++] = 0; buf[i++] = 0;
} }
} }
/* set parity */ /* set parity */
if( (cflag&(PARENB|PARODD)) != (old_cflag&(PARENB|PARODD)) ) { if ((cflag&(PARENB|PARODD)) != (old_cflag&(PARENB|PARODD))) {
if (cflag&PARENB) {
if( (cflag&PARENB) ) { if (cflag&PARODD)
if( (cflag&PARODD) )
arg = DIGI_PARITY_ODD; arg = DIGI_PARITY_ODD;
else else
arg = DIGI_PARITY_EVEN; arg = DIGI_PARITY_EVEN;
} else { } else {
arg = DIGI_PARITY_NONE; arg = DIGI_PARITY_NONE;
} }
buf[i++] = DIGI_CMD_SET_PARITY; buf[i++] = DIGI_CMD_SET_PARITY;
buf[i++] = priv->dp_port_num; buf[i++] = priv->dp_port_num;
buf[i++] = arg; buf[i++] = arg;
buf[i++] = 0; buf[i++] = 0;
} }
/* set word size */ /* set word size */
if( (cflag&CSIZE) != (old_cflag&CSIZE) ) { if ((cflag&CSIZE) != (old_cflag&CSIZE)) {
arg = -1; arg = -1;
switch (cflag&CSIZE) {
switch( (cflag&CSIZE) ) {
case CS5: arg = DIGI_WORD_SIZE_5; break; case CS5: arg = DIGI_WORD_SIZE_5; break;
case CS6: arg = DIGI_WORD_SIZE_6; break; case CS6: arg = DIGI_WORD_SIZE_6; break;
case CS7: arg = DIGI_WORD_SIZE_7; break; case CS7: arg = DIGI_WORD_SIZE_7; break;
case CS8: arg = DIGI_WORD_SIZE_8; break; case CS8: arg = DIGI_WORD_SIZE_8; break;
default: default:
dbg( "digi_set_termios: can't handle word size %d", dbg("digi_set_termios: can't handle word size %d",
(cflag&CSIZE) ); (cflag&CSIZE));
break; break;
} }
if( arg != -1 ) { if (arg != -1) {
buf[i++] = DIGI_CMD_SET_WORD_SIZE; buf[i++] = DIGI_CMD_SET_WORD_SIZE;
buf[i++] = priv->dp_port_num; buf[i++] = priv->dp_port_num;
buf[i++] = arg; buf[i++] = arg;
...@@ -1068,9 +1011,9 @@ dbg( "digi_set_termios: TOP: port=%d, iflag=0x%x, old_iflag=0x%x, cflag=0x%x, ol ...@@ -1068,9 +1011,9 @@ dbg( "digi_set_termios: TOP: port=%d, iflag=0x%x, old_iflag=0x%x, cflag=0x%x, ol
} }
/* set stop bits */ /* set stop bits */
if( (cflag&CSTOPB) != (old_cflag&CSTOPB) ) { if ((cflag&CSTOPB) != (old_cflag&CSTOPB)) {
if( (cflag&CSTOPB) ) if ((cflag&CSTOPB))
arg = DIGI_STOP_BITS_2; arg = DIGI_STOP_BITS_2;
else else
arg = DIGI_STOP_BITS_1; arg = DIGI_STOP_BITS_1;
...@@ -1083,18 +1026,15 @@ dbg( "digi_set_termios: TOP: port=%d, iflag=0x%x, old_iflag=0x%x, cflag=0x%x, ol ...@@ -1083,18 +1026,15 @@ dbg( "digi_set_termios: TOP: port=%d, iflag=0x%x, old_iflag=0x%x, cflag=0x%x, ol
} }
/* set input flow control */ /* set input flow control */
if( (iflag&IXOFF) != (old_iflag&IXOFF) if ((iflag&IXOFF) != (old_iflag&IXOFF)
|| (cflag&CRTSCTS) != (old_cflag&CRTSCTS) ) { || (cflag&CRTSCTS) != (old_cflag&CRTSCTS)) {
arg = 0; arg = 0;
if (iflag&IXOFF)
if( (iflag&IXOFF) )
arg |= DIGI_INPUT_FLOW_CONTROL_XON_XOFF; arg |= DIGI_INPUT_FLOW_CONTROL_XON_XOFF;
else else
arg &= ~DIGI_INPUT_FLOW_CONTROL_XON_XOFF; arg &= ~DIGI_INPUT_FLOW_CONTROL_XON_XOFF;
if( (cflag&CRTSCTS) ) { if (cflag&CRTSCTS) {
arg |= DIGI_INPUT_FLOW_CONTROL_RTS; arg |= DIGI_INPUT_FLOW_CONTROL_RTS;
/* On USB-4 it is necessary to assert RTS prior */ /* On USB-4 it is necessary to assert RTS prior */
...@@ -1107,43 +1047,37 @@ dbg( "digi_set_termios: TOP: port=%d, iflag=0x%x, old_iflag=0x%x, cflag=0x%x, ol ...@@ -1107,43 +1047,37 @@ dbg( "digi_set_termios: TOP: port=%d, iflag=0x%x, old_iflag=0x%x, cflag=0x%x, ol
} else { } else {
arg &= ~DIGI_INPUT_FLOW_CONTROL_RTS; arg &= ~DIGI_INPUT_FLOW_CONTROL_RTS;
} }
buf[i++] = DIGI_CMD_SET_INPUT_FLOW_CONTROL; buf[i++] = DIGI_CMD_SET_INPUT_FLOW_CONTROL;
buf[i++] = priv->dp_port_num; buf[i++] = priv->dp_port_num;
buf[i++] = arg; buf[i++] = arg;
buf[i++] = 0; buf[i++] = 0;
} }
/* set output flow control */ /* set output flow control */
if( (iflag&IXON) != (old_iflag&IXON) if ((iflag&IXON) != (old_iflag&IXON)
|| (cflag&CRTSCTS) != (old_cflag&CRTSCTS) ) { || (cflag&CRTSCTS) != (old_cflag&CRTSCTS)) {
arg = 0; arg = 0;
if (iflag&IXON)
if( (iflag&IXON) )
arg |= DIGI_OUTPUT_FLOW_CONTROL_XON_XOFF; arg |= DIGI_OUTPUT_FLOW_CONTROL_XON_XOFF;
else else
arg &= ~DIGI_OUTPUT_FLOW_CONTROL_XON_XOFF; arg &= ~DIGI_OUTPUT_FLOW_CONTROL_XON_XOFF;
if( (cflag&CRTSCTS) ) { if (cflag&CRTSCTS) {
arg |= DIGI_OUTPUT_FLOW_CONTROL_CTS; arg |= DIGI_OUTPUT_FLOW_CONTROL_CTS;
} else { } else {
arg &= ~DIGI_OUTPUT_FLOW_CONTROL_CTS; arg &= ~DIGI_OUTPUT_FLOW_CONTROL_CTS;
port->tty->hw_stopped = 0; tty->hw_stopped = 0;
} }
buf[i++] = DIGI_CMD_SET_OUTPUT_FLOW_CONTROL; buf[i++] = DIGI_CMD_SET_OUTPUT_FLOW_CONTROL;
buf[i++] = priv->dp_port_num; buf[i++] = priv->dp_port_num;
buf[i++] = arg; buf[i++] = arg;
buf[i++] = 0; buf[i++] = 0;
} }
/* set receive enable/disable */ /* set receive enable/disable */
if( (cflag&CREAD) != (old_cflag&CREAD) ) { if ((cflag&CREAD) != (old_cflag&CREAD)) {
if (cflag&CREAD)
if( (cflag&CREAD) )
arg = DIGI_ENABLE; arg = DIGI_ENABLE;
else else
arg = DIGI_DISABLE; arg = DIGI_DISABLE;
...@@ -1152,32 +1086,26 @@ dbg( "digi_set_termios: TOP: port=%d, iflag=0x%x, old_iflag=0x%x, cflag=0x%x, ol ...@@ -1152,32 +1086,26 @@ dbg( "digi_set_termios: TOP: port=%d, iflag=0x%x, old_iflag=0x%x, cflag=0x%x, ol
buf[i++] = priv->dp_port_num; buf[i++] = priv->dp_port_num;
buf[i++] = arg; buf[i++] = arg;
buf[i++] = 0; buf[i++] = 0;
} }
if ((ret = digi_write_oob_command(port, buf, i, 1)) != 0)
if( (ret=digi_write_oob_command( port, buf, i, 1 )) != 0 ) dbg("digi_set_termios: write oob failed, ret=%d", ret);
dbg( "digi_set_termios: write oob failed, ret=%d", ret );
} }
static void digi_break_ctl( struct usb_serial_port *port, int break_state ) static void digi_break_ctl(struct usb_serial_port *port, int break_state)
{ {
unsigned char buf[4]; unsigned char buf[4];
buf[0] = DIGI_CMD_BREAK_CONTROL; buf[0] = DIGI_CMD_BREAK_CONTROL;
buf[1] = 2; /* length */ buf[1] = 2; /* length */
buf[2] = break_state ? 1 : 0; buf[2] = break_state ? 1 : 0;
buf[3] = 0; /* pad */ buf[3] = 0; /* pad */
digi_write_inb_command(port, buf, 4, 0);
digi_write_inb_command( port, buf, 4, 0 );
} }
static int digi_tiocmget( struct usb_serial_port *port, struct file *file ) static int digi_tiocmget(struct usb_serial_port *port, struct file *file)
{ {
struct digi_port *priv = usb_get_serial_port_data(port); struct digi_port *priv = usb_get_serial_port_data(port);
unsigned int val; unsigned int val;
...@@ -1185,15 +1113,15 @@ static int digi_tiocmget( struct usb_serial_port *port, struct file *file ) ...@@ -1185,15 +1113,15 @@ static int digi_tiocmget( struct usb_serial_port *port, struct file *file )
dbg("%s: TOP: port=%d", __FUNCTION__, priv->dp_port_num); dbg("%s: TOP: port=%d", __FUNCTION__, priv->dp_port_num);
spin_lock_irqsave( &priv->dp_port_lock, flags ); spin_lock_irqsave(&priv->dp_port_lock, flags);
val = priv->dp_modem_signals; val = priv->dp_modem_signals;
spin_unlock_irqrestore( &priv->dp_port_lock, flags ); spin_unlock_irqrestore(&priv->dp_port_lock, flags);
return val; return val;
} }
static int digi_tiocmset( struct usb_serial_port *port, struct file *file, static int digi_tiocmset(struct usb_serial_port *port, struct file *file,
unsigned int set, unsigned int clear ) unsigned int set, unsigned int clear)
{ {
struct digi_port *priv = usb_get_serial_port_data(port); struct digi_port *priv = usb_get_serial_port_data(port);
unsigned int val; unsigned int val;
...@@ -1201,41 +1129,34 @@ static int digi_tiocmset( struct usb_serial_port *port, struct file *file, ...@@ -1201,41 +1129,34 @@ static int digi_tiocmset( struct usb_serial_port *port, struct file *file,
dbg("%s: TOP: port=%d", __FUNCTION__, priv->dp_port_num); dbg("%s: TOP: port=%d", __FUNCTION__, priv->dp_port_num);
spin_lock_irqsave( &priv->dp_port_lock, flags ); spin_lock_irqsave(&priv->dp_port_lock, flags);
val = (priv->dp_modem_signals & ~clear) | set; val = (priv->dp_modem_signals & ~clear) | set;
spin_unlock_irqrestore( &priv->dp_port_lock, flags ); spin_unlock_irqrestore(&priv->dp_port_lock, flags);
return digi_set_modem_signals( port, val, 1 ); return digi_set_modem_signals(port, val, 1);
} }
static int digi_ioctl( struct usb_serial_port *port, struct file *file, static int digi_ioctl(struct usb_serial_port *port, struct file *file,
unsigned int cmd, unsigned long arg ) unsigned int cmd, unsigned long arg)
{ {
struct digi_port *priv = usb_get_serial_port_data(port); struct digi_port *priv = usb_get_serial_port_data(port);
dbg("digi_ioctl: TOP: port=%d, cmd=0x%x", priv->dp_port_num, cmd);
dbg( "digi_ioctl: TOP: port=%d, cmd=0x%x", priv->dp_port_num, cmd );
switch (cmd) { switch (cmd) {
case TIOCMIWAIT: case TIOCMIWAIT:
/* wait for any of the 4 modem inputs (DCD,RI,DSR,CTS)*/ /* wait for any of the 4 modem inputs (DCD,RI,DSR,CTS)*/
/* TODO */ /* TODO */
return( 0 ); return 0;
case TIOCGICOUNT: case TIOCGICOUNT:
/* return count of modemline transitions */ /* return count of modemline transitions */
/* TODO */ /* TODO */
return 0; return 0;
} }
return -ENOIOCTLCMD;
return( -ENOIOCTLCMD );
} }
static int digi_write(struct usb_serial_port *port, const unsigned char *buf, int count)
static int digi_write( struct usb_serial_port *port, const unsigned char *buf, int count )
{ {
int ret,data_len,new_len; int ret,data_len,new_len;
...@@ -1243,35 +1164,29 @@ static int digi_write( struct usb_serial_port *port, const unsigned char *buf, i ...@@ -1243,35 +1164,29 @@ static int digi_write( struct usb_serial_port *port, const unsigned char *buf, i
unsigned char *data = port->write_urb->transfer_buffer; unsigned char *data = port->write_urb->transfer_buffer;
unsigned long flags = 0; unsigned long flags = 0;
dbg("digi_write: TOP: port=%d, count=%d, in_interrupt=%ld",
dbg( "digi_write: TOP: port=%d, count=%d, in_interrupt=%ld", priv->dp_port_num, count, in_interrupt());
priv->dp_port_num, count, in_interrupt() );
/* copy user data (which can sleep) before getting spin lock */ /* copy user data (which can sleep) before getting spin lock */
count = min( count, port->bulk_out_size-2 ); count = min(count, port->bulk_out_size-2);
count = min( 64, count); count = min(64, count);
/* be sure only one write proceeds at a time */ /* be sure only one write proceeds at a time */
/* there are races on the port private buffer */ /* there are races on the port private buffer */
/* and races to check write_urb->status */ /* and races to check write_urb->status */
spin_lock_irqsave( &priv->dp_port_lock, flags ); spin_lock_irqsave(&priv->dp_port_lock, flags);
/* wait for urb status clear to submit another urb */ /* wait for urb status clear to submit another urb */
if( port->write_urb->status == -EINPROGRESS if (port->write_urb->status == -EINPROGRESS || priv->dp_write_urb_in_use) {
|| priv->dp_write_urb_in_use ) {
/* buffer data if count is 1 (probably put_char) if possible */ /* buffer data if count is 1 (probably put_char) if possible */
if( count == 1 && priv->dp_out_buf_len < DIGI_OUT_BUF_SIZE ) { if (count == 1 && priv->dp_out_buf_len < DIGI_OUT_BUF_SIZE) {
priv->dp_out_buf[priv->dp_out_buf_len++] = *buf; priv->dp_out_buf[priv->dp_out_buf_len++] = *buf;
new_len = 1; new_len = 1;
} else { } else {
new_len = 0; new_len = 0;
} }
spin_unlock_irqrestore(&priv->dp_port_lock, flags);
spin_unlock_irqrestore( &priv->dp_port_lock, flags ); return new_len;
return( new_len );
} }
/* allow space for any buffered data and for new data, up to */ /* allow space for any buffered data and for new data, up to */
...@@ -1279,9 +1194,9 @@ priv->dp_port_num, count, in_interrupt() ); ...@@ -1279,9 +1194,9 @@ priv->dp_port_num, count, in_interrupt() );
new_len = min(count, port->bulk_out_size-2-priv->dp_out_buf_len); new_len = min(count, port->bulk_out_size-2-priv->dp_out_buf_len);
data_len = new_len + priv->dp_out_buf_len; data_len = new_len + priv->dp_out_buf_len;
if( data_len == 0 ) { if (data_len == 0) {
spin_unlock_irqrestore( &priv->dp_port_lock, flags ); spin_unlock_irqrestore(&priv->dp_port_lock, flags);
return( 0 ); return 0;
} }
port->write_urb->transfer_buffer_length = data_len+2; port->write_urb->transfer_buffer_length = data_len+2;
...@@ -1291,32 +1206,29 @@ priv->dp_port_num, count, in_interrupt() ); ...@@ -1291,32 +1206,29 @@ priv->dp_port_num, count, in_interrupt() );
*data++ = data_len; *data++ = data_len;
/* copy in buffered data first */ /* copy in buffered data first */
memcpy( data, priv->dp_out_buf, priv->dp_out_buf_len ); memcpy(data, priv->dp_out_buf, priv->dp_out_buf_len);
data += priv->dp_out_buf_len; data += priv->dp_out_buf_len;
/* copy in new data */ /* copy in new data */
memcpy( data, buf, new_len ); memcpy(data, buf, new_len);
if( (ret=usb_submit_urb(port->write_urb, GFP_ATOMIC)) == 0 ) { if ((ret = usb_submit_urb(port->write_urb, GFP_ATOMIC)) == 0) {
priv->dp_write_urb_in_use = 1; priv->dp_write_urb_in_use = 1;
ret = new_len; ret = new_len;
priv->dp_out_buf_len = 0; priv->dp_out_buf_len = 0;
} }
/* return length of new data written, or error */ /* return length of new data written, or error */
spin_unlock_irqrestore( &priv->dp_port_lock, flags ); spin_unlock_irqrestore(&priv->dp_port_lock, flags);
if( ret < 0 ) { if (ret < 0)
err("%s: usb_submit_urb failed, ret=%d, port=%d", __FUNCTION__, err("%s: usb_submit_urb failed, ret=%d, port=%d",
ret, priv->dp_port_num ); __FUNCTION__, ret, priv->dp_port_num);
} dbg("digi_write: returning %d", ret);
return ret;
dbg( "digi_write: returning %d", ret );
return( ret );
} }
static void digi_write_bulk_callback(struct urb *urb)
static void digi_write_bulk_callback( struct urb *urb )
{ {
struct usb_serial_port *port = (struct usb_serial_port *)urb->context; struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
...@@ -1326,153 +1238,136 @@ static void digi_write_bulk_callback( struct urb *urb ) ...@@ -1326,153 +1238,136 @@ static void digi_write_bulk_callback( struct urb *urb )
int ret = 0; int ret = 0;
int status = urb->status; int status = urb->status;
dbg("digi_write_bulk_callback: TOP, urb->status=%d", status);
dbg("digi_write_bulk_callback: TOP, urb status=%d", status);
/* port and serial sanity check */ /* port and serial sanity check */
if( port == NULL || (priv=usb_get_serial_port_data(port)) == NULL ) { if (port == NULL || (priv=usb_get_serial_port_data(port)) == NULL) {
err("%s: port or port->private is NULL, status=%d", err("%s: port or port->private is NULL, status=%d",
__FUNCTION__, status); __FUNCTION__, status);
return; return;
} }
serial = port->serial; serial = port->serial;
if( serial == NULL || (serial_priv=usb_get_serial_data(serial)) == NULL ) { if (serial == NULL || (serial_priv=usb_get_serial_data(serial)) == NULL) {
err("%s: serial or serial->private is NULL, status=%d", err("%s: serial or serial->private is NULL, status=%d",
__FUNCTION__, status); __FUNCTION__, status);
return; return;
} }
/* handle oob callback */ /* handle oob callback */
if( priv->dp_port_num == serial_priv->ds_oob_port_num ) { if (priv->dp_port_num == serial_priv->ds_oob_port_num) {
dbg( "digi_write_bulk_callback: oob callback" ); dbg("digi_write_bulk_callback: oob callback");
spin_lock( &priv->dp_port_lock ); spin_lock(&priv->dp_port_lock);
priv->dp_write_urb_in_use = 0; priv->dp_write_urb_in_use = 0;
wake_up_interruptible( &port->write_wait ); wake_up_interruptible(&port->write_wait);
spin_unlock( &priv->dp_port_lock ); spin_unlock(&priv->dp_port_lock);
return; return;
} }
/* try to send any buffered data on this port, if it is open */ /* try to send any buffered data on this port, if it is open */
spin_lock( &priv->dp_port_lock ); spin_lock(&priv->dp_port_lock);
priv->dp_write_urb_in_use = 0; priv->dp_write_urb_in_use = 0;
if( port->open_count && port->write_urb->status != -EINPROGRESS if (port->open_count && port->write_urb->status != -EINPROGRESS
&& priv->dp_out_buf_len > 0 ) { && priv->dp_out_buf_len > 0) {
*((unsigned char *)(port->write_urb->transfer_buffer)) *((unsigned char *)(port->write_urb->transfer_buffer))
= (unsigned char)DIGI_CMD_SEND_DATA; = (unsigned char)DIGI_CMD_SEND_DATA;
*((unsigned char *)(port->write_urb->transfer_buffer)+1) *((unsigned char *)(port->write_urb->transfer_buffer)+1)
= (unsigned char)priv->dp_out_buf_len; = (unsigned char)priv->dp_out_buf_len;
port->write_urb->transfer_buffer_length = priv->dp_out_buf_len+2;
port->write_urb->transfer_buffer_length
= priv->dp_out_buf_len+2;
port->write_urb->dev = serial->dev; port->write_urb->dev = serial->dev;
memcpy(port->write_urb->transfer_buffer+2, priv->dp_out_buf,
memcpy( port->write_urb->transfer_buffer+2, priv->dp_out_buf, priv->dp_out_buf_len);
priv->dp_out_buf_len ); if ((ret = usb_submit_urb(port->write_urb, GFP_ATOMIC)) == 0) {
if( (ret=usb_submit_urb(port->write_urb, GFP_ATOMIC)) == 0 ) {
priv->dp_write_urb_in_use = 1; priv->dp_write_urb_in_use = 1;
priv->dp_out_buf_len = 0; priv->dp_out_buf_len = 0;
} }
} }
/* wake up processes sleeping on writes immediately */ /* wake up processes sleeping on writes immediately */
digi_wakeup_write( port ); digi_wakeup_write(port);
/* also queue up a wakeup at scheduler time, in case we */ /* also queue up a wakeup at scheduler time, in case we */
/* lost the race in write_chan(). */ /* lost the race in write_chan(). */
schedule_work(&priv->dp_wakeup_work); schedule_work(&priv->dp_wakeup_work);
spin_unlock( &priv->dp_port_lock ); spin_unlock(&priv->dp_port_lock);
if (ret)
if( ret ) { err("%s: usb_submit_urb failed, ret=%d, port=%d",
err("%s: usb_submit_urb failed, ret=%d, port=%d", __FUNCTION__, __FUNCTION__, ret, priv->dp_port_num);
ret, priv->dp_port_num );
}
} }
static int digi_write_room(struct usb_serial_port *port)
static int digi_write_room( struct usb_serial_port *port )
{ {
int room; int room;
struct digi_port *priv = usb_get_serial_port_data(port); struct digi_port *priv = usb_get_serial_port_data(port);
unsigned long flags = 0; unsigned long flags = 0;
spin_lock_irqsave(&priv->dp_port_lock, flags);
spin_lock_irqsave( &priv->dp_port_lock, flags ); if (port->write_urb->status == -EINPROGRESS || priv->dp_write_urb_in_use)
if( port->write_urb->status == -EINPROGRESS
|| priv->dp_write_urb_in_use )
room = 0; room = 0;
else else
room = port->bulk_out_size - 2 - priv->dp_out_buf_len; room = port->bulk_out_size - 2 - priv->dp_out_buf_len;
spin_unlock_irqrestore( &priv->dp_port_lock, flags ); spin_unlock_irqrestore(&priv->dp_port_lock, flags);
dbg("digi_write_room: port=%d, room=%d", priv->dp_port_num, room);
dbg( "digi_write_room: port=%d, room=%d", priv->dp_port_num, room ); return room;
return( room );
} }
static int digi_chars_in_buffer(struct usb_serial_port *port)
static int digi_chars_in_buffer( struct usb_serial_port *port )
{ {
struct digi_port *priv = usb_get_serial_port_data(port); struct digi_port *priv = usb_get_serial_port_data(port);
if( port->write_urb->status == -EINPROGRESS if (port->write_urb->status == -EINPROGRESS
|| priv->dp_write_urb_in_use ) { || priv->dp_write_urb_in_use) {
dbg( "digi_chars_in_buffer: port=%d, chars=%d", priv->dp_port_num, port->bulk_out_size - 2 ); dbg("digi_chars_in_buffer: port=%d, chars=%d",
/* return( port->bulk_out_size - 2 ); */ priv->dp_port_num, port->bulk_out_size - 2);
return( 256 ); /* return(port->bulk_out_size - 2); */
return 256;
} else { } else {
dbg( "digi_chars_in_buffer: port=%d, chars=%d", priv->dp_port_num, priv->dp_out_buf_len ); dbg("digi_chars_in_buffer: port=%d, chars=%d",
return( priv->dp_out_buf_len ); priv->dp_port_num, priv->dp_out_buf_len);
return priv->dp_out_buf_len;
} }
} }
static int digi_open( struct usb_serial_port *port, struct file *filp ) static int digi_open(struct usb_serial_port *port, struct file *filp)
{ {
int ret; int ret;
unsigned char buf[32]; unsigned char buf[32];
struct digi_port *priv = usb_get_serial_port_data(port); struct digi_port *priv = usb_get_serial_port_data(port);
struct ktermios not_termios; struct ktermios not_termios;
unsigned long flags = 0; unsigned long flags = 0;
dbg("digi_open: TOP: port=%d, open_count=%d",
dbg( "digi_open: TOP: port=%d, open_count=%d", priv->dp_port_num, port->open_count ); priv->dp_port_num, port->open_count);
/* be sure the device is started up */ /* be sure the device is started up */
if( digi_startup_device( port->serial ) != 0 ) if (digi_startup_device(port->serial) != 0)
return( -ENXIO ); return -ENXIO;
spin_lock_irqsave( &priv->dp_port_lock, flags ); spin_lock_irqsave(&priv->dp_port_lock, flags);
/* don't wait on a close in progress for non-blocking opens */ /* don't wait on a close in progress for non-blocking opens */
if( priv->dp_in_close && (filp->f_flags&(O_NDELAY|O_NONBLOCK)) == 0 ) { if (priv->dp_in_close && (filp->f_flags&(O_NDELAY|O_NONBLOCK)) == 0) {
spin_unlock_irqrestore( &priv->dp_port_lock, flags ); spin_unlock_irqrestore(&priv->dp_port_lock, flags);
return( -EAGAIN ); return -EAGAIN;
} }
/* wait for a close in progress to finish */ /* wait for a close in progress to finish */
while( priv->dp_in_close ) { while(priv->dp_in_close) {
cond_wait_interruptible_timeout_irqrestore( cond_wait_interruptible_timeout_irqrestore(
&priv->dp_close_wait, DIGI_RETRY_TIMEOUT, &priv->dp_close_wait, DIGI_RETRY_TIMEOUT,
&priv->dp_port_lock, flags ); &priv->dp_port_lock, flags);
if( signal_pending(current) ) { if (signal_pending(current))
return( -EINTR ); return -EINTR;
} spin_lock_irqsave(&priv->dp_port_lock, flags);
spin_lock_irqsave( &priv->dp_port_lock, flags );
} }
spin_unlock_irqrestore( &priv->dp_port_lock, flags ); spin_unlock_irqrestore(&priv->dp_port_lock, flags);
/* read modem signals automatically whenever they change */ /* read modem signals automatically whenever they change */
buf[0] = DIGI_CMD_READ_INPUT_SIGNALS; buf[0] = DIGI_CMD_READ_INPUT_SIGNALS;
...@@ -1486,23 +1381,22 @@ dbg( "digi_open: TOP: port=%d, open_count=%d", priv->dp_port_num, port->open_cou ...@@ -1486,23 +1381,22 @@ dbg( "digi_open: TOP: port=%d, open_count=%d", priv->dp_port_num, port->open_cou
buf[6] = DIGI_FLUSH_TX | DIGI_FLUSH_RX; buf[6] = DIGI_FLUSH_TX | DIGI_FLUSH_RX;
buf[7] = 0; buf[7] = 0;
if( (ret=digi_write_oob_command( port, buf, 8, 1 )) != 0 ) if ((ret = digi_write_oob_command(port, buf, 8, 1)) != 0)
dbg( "digi_open: write oob failed, ret=%d", ret ); dbg("digi_open: write oob failed, ret=%d", ret);
/* set termios settings */ /* set termios settings */
not_termios.c_cflag = ~port->tty->termios->c_cflag; not_termios.c_cflag = ~port->tty->termios->c_cflag;
not_termios.c_iflag = ~port->tty->termios->c_iflag; not_termios.c_iflag = ~port->tty->termios->c_iflag;
digi_set_termios( port, &not_termios ); digi_set_termios(port, &not_termios);
/* set DTR and RTS */ /* set DTR and RTS */
digi_set_modem_signals( port, TIOCM_DTR|TIOCM_RTS, 1 ); digi_set_modem_signals(port, TIOCM_DTR|TIOCM_RTS, 1);
return( 0 );
return 0;
} }
static void digi_close( struct usb_serial_port *port, struct file *filp ) static void digi_close(struct usb_serial_port *port, struct file *filp)
{ {
DEFINE_WAIT(wait); DEFINE_WAIT(wait);
int ret; int ret;
...@@ -1511,40 +1405,37 @@ static void digi_close( struct usb_serial_port *port, struct file *filp ) ...@@ -1511,40 +1405,37 @@ static void digi_close( struct usb_serial_port *port, struct file *filp )
struct digi_port *priv = usb_get_serial_port_data(port); struct digi_port *priv = usb_get_serial_port_data(port);
unsigned long flags = 0; unsigned long flags = 0;
dbg("digi_close: TOP: port=%d, open_count=%d",
dbg( "digi_close: TOP: port=%d, open_count=%d", priv->dp_port_num, port->open_count ); priv->dp_port_num, port->open_count);
/* if disconnected, just clear flags */ /* if disconnected, just clear flags */
if (!usb_get_intfdata(port->serial->interface)) if (!usb_get_intfdata(port->serial->interface))
goto exit; goto exit;
/* do cleanup only after final close on this port */ /* do cleanup only after final close on this port */
spin_lock_irqsave( &priv->dp_port_lock, flags ); spin_lock_irqsave(&priv->dp_port_lock, flags);
priv->dp_in_close = 1; priv->dp_in_close = 1;
spin_unlock_irqrestore( &priv->dp_port_lock, flags ); spin_unlock_irqrestore(&priv->dp_port_lock, flags);
/* tell line discipline to process only XON/XOFF */ /* tell line discipline to process only XON/XOFF */
tty->closing = 1; tty->closing = 1;
/* wait for output to drain */ /* wait for output to drain */
if( (filp->f_flags&(O_NDELAY|O_NONBLOCK)) == 0 ) { if ((filp->f_flags&(O_NDELAY|O_NONBLOCK)) == 0)
tty_wait_until_sent( tty, DIGI_CLOSE_TIMEOUT ); tty_wait_until_sent(tty, DIGI_CLOSE_TIMEOUT);
}
/* flush driver and line discipline buffers */ /* flush driver and line discipline buffers */
if( tty->driver->flush_buffer ) if (tty->driver->flush_buffer)
tty->driver->flush_buffer( tty ); tty->driver->flush_buffer(tty);
tty_ldisc_flush(tty); tty_ldisc_flush(tty);
if (port->serial->dev) { if (port->serial->dev) {
/* wait for transmit idle */ /* wait for transmit idle */
if( (filp->f_flags&(O_NDELAY|O_NONBLOCK)) == 0 ) { if ((filp->f_flags&(O_NDELAY|O_NONBLOCK)) == 0) {
digi_transmit_idle( port, DIGI_CLOSE_TIMEOUT ); digi_transmit_idle(port, DIGI_CLOSE_TIMEOUT);
} }
/* drop DTR and RTS */ /* drop DTR and RTS */
digi_set_modem_signals( port, 0, 0 ); digi_set_modem_signals(port, 0, 0);
/* disable input flow control */ /* disable input flow control */
buf[0] = DIGI_CMD_SET_INPUT_FLOW_CONTROL; buf[0] = DIGI_CMD_SET_INPUT_FLOW_CONTROL;
...@@ -1576,8 +1467,8 @@ dbg( "digi_close: TOP: port=%d, open_count=%d", priv->dp_port_num, port->open_co ...@@ -1576,8 +1467,8 @@ dbg( "digi_close: TOP: port=%d, open_count=%d", priv->dp_port_num, port->open_co
buf[18] = DIGI_FLUSH_TX | DIGI_FLUSH_RX; buf[18] = DIGI_FLUSH_TX | DIGI_FLUSH_RX;
buf[19] = 0; buf[19] = 0;
if( (ret=digi_write_oob_command( port, buf, 20, 0 )) != 0 ) if ((ret = digi_write_oob_command(port, buf, 20, 0)) != 0)
dbg( "digi_close: write oob failed, ret=%d", ret ); dbg("digi_close: write oob failed, ret=%d", ret);
/* wait for final commands on oob port to complete */ /* wait for final commands on oob port to complete */
prepare_to_wait(&priv->dp_flush_wait, &wait, TASK_INTERRUPTIBLE); prepare_to_wait(&priv->dp_flush_wait, &wait, TASK_INTERRUPTIBLE);
...@@ -1587,17 +1478,14 @@ dbg( "digi_close: TOP: port=%d, open_count=%d", priv->dp_port_num, port->open_co ...@@ -1587,17 +1478,14 @@ dbg( "digi_close: TOP: port=%d, open_count=%d", priv->dp_port_num, port->open_co
/* shutdown any outstanding bulk writes */ /* shutdown any outstanding bulk writes */
usb_kill_urb(port->write_urb); usb_kill_urb(port->write_urb);
} }
tty->closing = 0; tty->closing = 0;
exit: exit:
spin_lock_irqsave( &priv->dp_port_lock, flags ); spin_lock_irqsave(&priv->dp_port_lock, flags);
priv->dp_write_urb_in_use = 0; priv->dp_write_urb_in_use = 0;
priv->dp_in_close = 0; priv->dp_in_close = 0;
wake_up_interruptible( &priv->dp_close_wait ); wake_up_interruptible(&priv->dp_close_wait);
spin_unlock_irqrestore( &priv->dp_port_lock, flags ); spin_unlock_irqrestore(&priv->dp_port_lock, flags);
dbg("digi_close: done");
dbg( "digi_close: done" );
} }
...@@ -1608,155 +1496,136 @@ dbg( "digi_close: done" ); ...@@ -1608,155 +1496,136 @@ dbg( "digi_close: done" );
* urbs initialized. Returns 0 if successful, non-zero error otherwise. * urbs initialized. Returns 0 if successful, non-zero error otherwise.
*/ */
static int digi_startup_device( struct usb_serial *serial ) static int digi_startup_device(struct usb_serial *serial)
{ {
int i,ret = 0; int i,ret = 0;
struct digi_serial *serial_priv = usb_get_serial_data(serial); struct digi_serial *serial_priv = usb_get_serial_data(serial);
struct usb_serial_port *port; struct usb_serial_port *port;
/* be sure this happens exactly once */ /* be sure this happens exactly once */
spin_lock( &serial_priv->ds_serial_lock ); spin_lock(&serial_priv->ds_serial_lock);
if( serial_priv->ds_device_started ) { if (serial_priv->ds_device_started) {
spin_unlock( &serial_priv->ds_serial_lock ); spin_unlock(&serial_priv->ds_serial_lock);
return( 0 ); return 0;
} }
serial_priv->ds_device_started = 1; serial_priv->ds_device_started = 1;
spin_unlock( &serial_priv->ds_serial_lock ); spin_unlock(&serial_priv->ds_serial_lock);
/* start reading from each bulk in endpoint for the device */ /* start reading from each bulk in endpoint for the device */
/* set USB_DISABLE_SPD flag for write bulk urbs */ /* set USB_DISABLE_SPD flag for write bulk urbs */
for( i=0; i<serial->type->num_ports+1; i++ ) { for (i = 0; i < serial->type->num_ports + 1; i++) {
port = serial->port[i]; port = serial->port[i];
port->write_urb->dev = port->serial->dev; port->write_urb->dev = port->serial->dev;
if ((ret = usb_submit_urb(port->read_urb, GFP_KERNEL)) != 0) {
if( (ret=usb_submit_urb(port->read_urb, GFP_KERNEL)) != 0 ) { err("%s: usb_submit_urb failed, ret=%d, port=%d",
err("%s: usb_submit_urb failed, ret=%d, port=%d", __FUNCTION__, __FUNCTION__, ret, i);
ret, i );
break; break;
} }
} }
return ret;
return( ret );
} }
static int digi_startup( struct usb_serial *serial ) static int digi_startup(struct usb_serial *serial)
{ {
int i; int i;
struct digi_port *priv; struct digi_port *priv;
struct digi_serial *serial_priv; struct digi_serial *serial_priv;
dbg("digi_startup: TOP");
dbg( "digi_startup: TOP" );
/* allocate the private data structures for all ports */ /* allocate the private data structures for all ports */
/* number of regular ports + 1 for the out-of-band port */ /* number of regular ports + 1 for the out-of-band port */
for( i=0; i<serial->type->num_ports+1; i++ ) { for(i = 0; i < serial->type->num_ports + 1; i++) {
/* allocate port private structure */ /* allocate port private structure */
priv = kmalloc( sizeof(struct digi_port), priv = kmalloc(sizeof(struct digi_port), GFP_KERNEL);
GFP_KERNEL ); if (priv == NULL) {
if( priv == (struct digi_port *)0 ) { while (--i >= 0)
while( --i >= 0 ) kfree(usb_get_serial_port_data(serial->port[i]));
kfree( usb_get_serial_port_data(serial->port[i]) ); return 1; /* error */
return( 1 ); /* error */
} }
/* initialize port private structure */ /* initialize port private structure */
spin_lock_init( &priv->dp_port_lock ); spin_lock_init(&priv->dp_port_lock);
priv->dp_port_num = i; priv->dp_port_num = i;
priv->dp_out_buf_len = 0; priv->dp_out_buf_len = 0;
priv->dp_write_urb_in_use = 0; priv->dp_write_urb_in_use = 0;
priv->dp_modem_signals = 0; priv->dp_modem_signals = 0;
init_waitqueue_head( &priv->dp_modem_change_wait ); init_waitqueue_head(&priv->dp_modem_change_wait);
priv->dp_transmit_idle = 0; priv->dp_transmit_idle = 0;
init_waitqueue_head( &priv->dp_transmit_idle_wait ); init_waitqueue_head(&priv->dp_transmit_idle_wait);
priv->dp_throttled = 0; priv->dp_throttled = 0;
priv->dp_throttle_restart = 0; priv->dp_throttle_restart = 0;
init_waitqueue_head( &priv->dp_flush_wait ); init_waitqueue_head(&priv->dp_flush_wait);
priv->dp_in_close = 0; priv->dp_in_close = 0;
init_waitqueue_head( &priv->dp_close_wait ); init_waitqueue_head(&priv->dp_close_wait);
INIT_WORK(&priv->dp_wakeup_work, digi_wakeup_write_lock); INIT_WORK(&priv->dp_wakeup_work, digi_wakeup_write_lock);
priv->dp_port = serial->port[i]; priv->dp_port = serial->port[i];
/* initialize write wait queue for this port */ /* initialize write wait queue for this port */
init_waitqueue_head( &serial->port[i]->write_wait ); init_waitqueue_head(&serial->port[i]->write_wait);
usb_set_serial_port_data(serial->port[i], priv); usb_set_serial_port_data(serial->port[i], priv);
} }
/* allocate serial private structure */ /* allocate serial private structure */
serial_priv = kmalloc( sizeof(struct digi_serial), serial_priv = kmalloc(sizeof(struct digi_serial), GFP_KERNEL);
GFP_KERNEL ); if (serial_priv == NULL) {
if( serial_priv == (struct digi_serial *)0 ) { for (i = 0; i < serial->type->num_ports + 1; i++)
for( i=0; i<serial->type->num_ports+1; i++ ) kfree(usb_get_serial_port_data(serial->port[i]));
kfree( usb_get_serial_port_data(serial->port[i]) ); return 1; /* error */
return( 1 ); /* error */
} }
/* initialize serial private structure */ /* initialize serial private structure */
spin_lock_init( &serial_priv->ds_serial_lock ); spin_lock_init(&serial_priv->ds_serial_lock);
serial_priv->ds_oob_port_num = serial->type->num_ports; serial_priv->ds_oob_port_num = serial->type->num_ports;
serial_priv->ds_oob_port = serial->port[serial_priv->ds_oob_port_num]; serial_priv->ds_oob_port = serial->port[serial_priv->ds_oob_port_num];
serial_priv->ds_device_started = 0; serial_priv->ds_device_started = 0;
usb_set_serial_data(serial, serial_priv); usb_set_serial_data(serial, serial_priv);
return( 0 ); return 0;
} }
static void digi_shutdown( struct usb_serial *serial ) static void digi_shutdown(struct usb_serial *serial)
{ {
int i; int i;
dbg("digi_shutdown: TOP, in_interrupt()=%ld", in_interrupt());
dbg( "digi_shutdown: TOP, in_interrupt()=%ld", in_interrupt() );
/* stop reads and writes on all ports */ /* stop reads and writes on all ports */
for( i=0; i<serial->type->num_ports+1; i++ ) { for (i = 0; i < serial->type->num_ports + 1; i++) {
usb_kill_urb(serial->port[i]->read_urb); usb_kill_urb(serial->port[i]->read_urb);
usb_kill_urb(serial->port[i]->write_urb); usb_kill_urb(serial->port[i]->write_urb);
} }
/* free the private data structures for all ports */ /* free the private data structures for all ports */
/* number of regular ports + 1 for the out-of-band port */ /* number of regular ports + 1 for the out-of-band port */
for( i=0; i<serial->type->num_ports+1; i++ ) for(i = 0; i < serial->type->num_ports + 1; i++)
kfree( usb_get_serial_port_data(serial->port[i]) ); kfree(usb_get_serial_port_data(serial->port[i]));
kfree( usb_get_serial_data(serial) ); kfree(usb_get_serial_data(serial));
} }
static void digi_read_bulk_callback( struct urb *urb ) static void digi_read_bulk_callback(struct urb *urb)
{ {
struct usb_serial_port *port = (struct usb_serial_port *)urb->context; struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
struct digi_port *priv; struct digi_port *priv;
struct digi_serial *serial_priv; struct digi_serial *serial_priv;
int ret; int ret;
int status = urb->status; int status = urb->status;
dbg("digi_read_bulk_callback: TOP");
dbg( "digi_read_bulk_callback: TOP" );
/* port sanity check, do not resubmit if port is not valid */ /* port sanity check, do not resubmit if port is not valid */
if( port == NULL || (priv=usb_get_serial_port_data(port)) == NULL ) { if (port == NULL || (priv = usb_get_serial_port_data(port)) == NULL) {
err("%s: port or port->private is NULL, status=%d", err("%s: port or port->private is NULL, status=%d",
__FUNCTION__, status); __FUNCTION__, status);
return; return;
} }
if( port->serial == NULL if (port->serial == NULL ||
|| (serial_priv=usb_get_serial_data(port->serial)) == NULL ) { (serial_priv=usb_get_serial_data(port->serial)) == NULL) {
err("%s: serial is bad or serial->private is NULL, status=%d", err("%s: serial is bad or serial->private is NULL, status=%d",
__FUNCTION__, status); __FUNCTION__, status);
return; return;
} }
...@@ -1768,24 +1637,23 @@ dbg( "digi_read_bulk_callback: TOP" ); ...@@ -1768,24 +1637,23 @@ dbg( "digi_read_bulk_callback: TOP" );
} }
/* handle oob or inb callback, do not resubmit if error */ /* handle oob or inb callback, do not resubmit if error */
if( priv->dp_port_num == serial_priv->ds_oob_port_num ) { if (priv->dp_port_num == serial_priv->ds_oob_port_num) {
if( digi_read_oob_callback( urb ) != 0 ) if (digi_read_oob_callback(urb) != 0)
return; return;
} else { } else {
if( digi_read_inb_callback( urb ) != 0 ) if (digi_read_inb_callback(urb) != 0)
return; return;
} }
/* continue read */ /* continue read */
urb->dev = port->serial->dev; urb->dev = port->serial->dev;
if( (ret=usb_submit_urb(urb, GFP_ATOMIC)) != 0 ) { if ((ret = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
err("%s: failed resubmitting urb, ret=%d, port=%d", __FUNCTION__, err("%s: failed resubmitting urb, ret=%d, port=%d",
ret, priv->dp_port_num ); __FUNCTION__, ret, priv->dp_port_num);
} }
} }
/* /*
* Digi Read INB Callback * Digi Read INB Callback
* *
...@@ -1796,7 +1664,7 @@ dbg( "digi_read_bulk_callback: TOP" ); ...@@ -1796,7 +1664,7 @@ dbg( "digi_read_bulk_callback: TOP" );
* throttled, and -1 if the sanity checks failed. * throttled, and -1 if the sanity checks failed.
*/ */
static int digi_read_inb_callback( struct urb *urb ) static int digi_read_inb_callback(struct urb *urb)
{ {
struct usb_serial_port *port = (struct usb_serial_port *)urb->context; struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
...@@ -1812,72 +1680,67 @@ static int digi_read_inb_callback( struct urb *urb ) ...@@ -1812,72 +1680,67 @@ static int digi_read_inb_callback( struct urb *urb )
/* do not process callbacks on closed ports */ /* do not process callbacks on closed ports */
/* but do continue the read chain */ /* but do continue the read chain */
if( port->open_count == 0 ) if (port->open_count == 0)
return( 0 ); return 0;
/* short/multiple packet check */ /* short/multiple packet check */
if( urb->actual_length != len + 2 ) { if (urb->actual_length != len + 2) {
err("%s: INCOMPLETE OR MULTIPLE PACKET, urb status=%d, " err("%s: INCOMPLETE OR MULTIPLE PACKET, urb->status=%d, "
"port=%d, opcode=%d, len=%d, actual_length=%d, " "port=%d, opcode=%d, len=%d, actual_length=%d, "
"port_status=%d", __FUNCTION__, status, priv->dp_port_num, "status=%d", __FUNCTION__, status, priv->dp_port_num,
opcode, len, urb->actual_length, port_status); opcode, len, urb->actual_length, port_status);
return( -1 ); return -1;
} }
spin_lock( &priv->dp_port_lock ); spin_lock(&priv->dp_port_lock);
/* check for throttle; if set, do not resubmit read urb */ /* check for throttle; if set, do not resubmit read urb */
/* indicate the read chain needs to be restarted on unthrottle */ /* indicate the read chain needs to be restarted on unthrottle */
throttled = priv->dp_throttled; throttled = priv->dp_throttled;
if( throttled ) if (throttled)
priv->dp_throttle_restart = 1; priv->dp_throttle_restart = 1;
/* receive data */ /* receive data */
if( opcode == DIGI_CMD_RECEIVE_DATA ) { if (opcode == DIGI_CMD_RECEIVE_DATA) {
/* get flag from port_status */ /* get flag from port_status */
flag = 0; flag = 0;
/* overrun is special, not associated with a char */ /* overrun is special, not associated with a char */
if (port_status & DIGI_OVERRUN_ERROR) { if (port_status & DIGI_OVERRUN_ERROR)
tty_insert_flip_char( tty, 0, TTY_OVERRUN ); tty_insert_flip_char(tty, 0, TTY_OVERRUN);
}
/* break takes precedence over parity, */ /* break takes precedence over parity, */
/* which takes precedence over framing errors */ /* which takes precedence over framing errors */
if (port_status & DIGI_BREAK_ERROR) { if (port_status & DIGI_BREAK_ERROR)
flag = TTY_BREAK; flag = TTY_BREAK;
} else if (port_status & DIGI_PARITY_ERROR) { else if (port_status & DIGI_PARITY_ERROR)
flag = TTY_PARITY; flag = TTY_PARITY;
} else if (port_status & DIGI_FRAMING_ERROR) { else if (port_status & DIGI_FRAMING_ERROR)
flag = TTY_FRAME; flag = TTY_FRAME;
}
/* data length is len-1 (one byte of len is port_status) */ /* data length is len-1 (one byte of len is port_status) */
--len; --len;
len = tty_buffer_request_room(tty, len); len = tty_buffer_request_room(tty, len);
if( len > 0 ) { if (len > 0) {
/* Hot path */ /* Hot path */
if(flag == TTY_NORMAL) if (flag == TTY_NORMAL)
tty_insert_flip_string(tty, data, len); tty_insert_flip_string(tty, data, len);
else { else {
for(i = 0; i < len; i++) for(i = 0; i < len; i++)
tty_insert_flip_char(tty, data[i], flag); tty_insert_flip_char(tty, data[i], flag);
} }
tty_flip_buffer_push( tty ); tty_flip_buffer_push(tty);
} }
} }
spin_unlock(&priv->dp_port_lock);
spin_unlock( &priv->dp_port_lock ); if (opcode == DIGI_CMD_RECEIVE_DISABLE)
dbg("%s: got RECEIVE_DISABLE", __FUNCTION__);
if( opcode == DIGI_CMD_RECEIVE_DISABLE ) { else if (opcode != DIGI_CMD_RECEIVE_DATA)
dbg("%s: got RECEIVE_DISABLE", __FUNCTION__ ); dbg("%s: unknown opcode: %d", __FUNCTION__, opcode);
} else if( opcode != DIGI_CMD_RECEIVE_DATA ) {
dbg("%s: unknown opcode: %d", __FUNCTION__, opcode );
}
return( throttled ? 1 : 0 ); return(throttled ? 1 : 0);
} }
...@@ -1891,7 +1754,7 @@ static int digi_read_inb_callback( struct urb *urb ) ...@@ -1891,7 +1754,7 @@ static int digi_read_inb_callback( struct urb *urb )
* -1 if the sanity checks failed. * -1 if the sanity checks failed.
*/ */
static int digi_read_oob_callback( struct urb *urb ) static int digi_read_oob_callback(struct urb *urb)
{ {
struct usb_serial_port *port = (struct usb_serial_port *)urb->context; struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
...@@ -1900,87 +1763,75 @@ static int digi_read_oob_callback( struct urb *urb ) ...@@ -1900,87 +1763,75 @@ static int digi_read_oob_callback( struct urb *urb )
int opcode, line, status, val; int opcode, line, status, val;
int i; int i;
dbg("digi_read_oob_callback: port=%d, len=%d",
dbg( "digi_read_oob_callback: port=%d, len=%d", priv->dp_port_num, priv->dp_port_num, urb->actual_length);
urb->actual_length );
/* handle each oob command */ /* handle each oob command */
for( i=0; i<urb->actual_length-3; ) { for(i = 0; i < urb->actual_length - 3;) {
opcode = ((unsigned char *)urb->transfer_buffer)[i++]; opcode = ((unsigned char *)urb->transfer_buffer)[i++];
line = ((unsigned char *)urb->transfer_buffer)[i++]; line = ((unsigned char *)urb->transfer_buffer)[i++];
status = ((unsigned char *)urb->transfer_buffer)[i++]; status = ((unsigned char *)urb->transfer_buffer)[i++];
val = ((unsigned char *)urb->transfer_buffer)[i++]; val = ((unsigned char *)urb->transfer_buffer)[i++];
dbg( "digi_read_oob_callback: opcode=%d, line=%d, status=%d, val=%d", dbg("digi_read_oob_callback: opcode=%d, line=%d, status=%d, val=%d",
opcode, line, status, val ); opcode, line, status, val);
if( status != 0 || line >= serial->type->num_ports ) if (status != 0 || line >= serial->type->num_ports)
continue; continue;
port = serial->port[line]; port = serial->port[line];
if ((priv=usb_get_serial_port_data(port)) == NULL ) if ((priv=usb_get_serial_port_data(port)) == NULL)
return -1; return -1;
if( opcode == DIGI_CMD_READ_INPUT_SIGNALS ) { if (opcode == DIGI_CMD_READ_INPUT_SIGNALS) {
spin_lock(&priv->dp_port_lock);
spin_lock( &priv->dp_port_lock );
/* convert from digi flags to termiox flags */ /* convert from digi flags to termiox flags */
if( val & DIGI_READ_INPUT_SIGNALS_CTS ) { if (val & DIGI_READ_INPUT_SIGNALS_CTS) {
priv->dp_modem_signals |= TIOCM_CTS; priv->dp_modem_signals |= TIOCM_CTS;
/* port must be open to use tty struct */ /* port must be open to use tty struct */
if( port->open_count if (port->open_count
&& port->tty->termios->c_cflag & CRTSCTS ) { && port->tty->termios->c_cflag & CRTSCTS) {
port->tty->hw_stopped = 0; port->tty->hw_stopped = 0;
digi_wakeup_write( port ); digi_wakeup_write(port);
} }
} else { } else {
priv->dp_modem_signals &= ~TIOCM_CTS; priv->dp_modem_signals &= ~TIOCM_CTS;
/* port must be open to use tty struct */ /* port must be open to use tty struct */
if( port->open_count if (port->open_count
&& port->tty->termios->c_cflag & CRTSCTS ) { && port->tty->termios->c_cflag & CRTSCTS) {
port->tty->hw_stopped = 1; port->tty->hw_stopped = 1;
} }
} }
if( val & DIGI_READ_INPUT_SIGNALS_DSR ) if (val & DIGI_READ_INPUT_SIGNALS_DSR)
priv->dp_modem_signals |= TIOCM_DSR; priv->dp_modem_signals |= TIOCM_DSR;
else else
priv->dp_modem_signals &= ~TIOCM_DSR; priv->dp_modem_signals &= ~TIOCM_DSR;
if( val & DIGI_READ_INPUT_SIGNALS_RI ) if (val & DIGI_READ_INPUT_SIGNALS_RI)
priv->dp_modem_signals |= TIOCM_RI; priv->dp_modem_signals |= TIOCM_RI;
else else
priv->dp_modem_signals &= ~TIOCM_RI; priv->dp_modem_signals &= ~TIOCM_RI;
if( val & DIGI_READ_INPUT_SIGNALS_DCD ) if (val & DIGI_READ_INPUT_SIGNALS_DCD)
priv->dp_modem_signals |= TIOCM_CD; priv->dp_modem_signals |= TIOCM_CD;
else else
priv->dp_modem_signals &= ~TIOCM_CD; priv->dp_modem_signals &= ~TIOCM_CD;
wake_up_interruptible( &priv->dp_modem_change_wait ); wake_up_interruptible(&priv->dp_modem_change_wait);
spin_unlock( &priv->dp_port_lock ); spin_unlock(&priv->dp_port_lock);
} else if (opcode == DIGI_CMD_TRANSMIT_IDLE) {
} else if( opcode == DIGI_CMD_TRANSMIT_IDLE ) { spin_lock(&priv->dp_port_lock);
spin_lock( &priv->dp_port_lock );
priv->dp_transmit_idle = 1; priv->dp_transmit_idle = 1;
wake_up_interruptible( &priv->dp_transmit_idle_wait ); wake_up_interruptible(&priv->dp_transmit_idle_wait);
spin_unlock( &priv->dp_port_lock ); spin_unlock(&priv->dp_port_lock);
} else if (opcode == DIGI_CMD_IFLUSH_FIFO) {
} else if( opcode == DIGI_CMD_IFLUSH_FIFO ) { wake_up_interruptible(&priv->dp_flush_wait);
wake_up_interruptible( &priv->dp_flush_wait );
} }
} }
return 0;
return( 0 );
} }
static int __init digi_init(void)
static int __init digi_init (void)
{ {
int retval; int retval;
retval = usb_serial_register(&digi_acceleport_2_device); retval = usb_serial_register(&digi_acceleport_2_device);
...@@ -2002,12 +1853,11 @@ static int __init digi_init (void) ...@@ -2002,12 +1853,11 @@ static int __init digi_init (void)
return retval; return retval;
} }
static void __exit digi_exit (void) static void __exit digi_exit (void)
{ {
usb_deregister (&digi_driver); usb_deregister(&digi_driver);
usb_serial_deregister (&digi_acceleport_2_device); usb_serial_deregister(&digi_acceleport_2_device);
usb_serial_deregister (&digi_acceleport_4_device); usb_serial_deregister(&digi_acceleport_4_device);
} }
...@@ -2015,8 +1865,8 @@ module_init(digi_init); ...@@ -2015,8 +1865,8 @@ module_init(digi_init);
module_exit(digi_exit); module_exit(digi_exit);
MODULE_AUTHOR( DRIVER_AUTHOR ); MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION( DRIVER_DESC ); MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL"); MODULE_LICENSE("GPL");
module_param(debug, bool, S_IRUGO | S_IWUSR); module_param(debug, bool, S_IRUGO | S_IWUSR);
......
...@@ -2366,9 +2366,8 @@ static int send_cmd_write_baud_rate (struct edgeport_port *edge_port, int baudRa ...@@ -2366,9 +2366,8 @@ static int send_cmd_write_baud_rate (struct edgeport_port *edge_port, int baudRa
int status; int status;
unsigned char number = edge_port->port->number - edge_port->port->serial->minor; unsigned char number = edge_port->port->number - edge_port->port->serial->minor;
if ((!edge_serial->is_epic) || if (edge_serial->is_epic &&
((edge_serial->is_epic) && !edge_serial->epic_descriptor.Supports.IOSPSetBaudRate) {
(!edge_serial->epic_descriptor.Supports.IOSPSetBaudRate))) {
dbg("SendCmdWriteBaudRate - NOT Setting baud rate for port = %d, baud = %d", dbg("SendCmdWriteBaudRate - NOT Setting baud rate for port = %d, baud = %d",
edge_port->port->number, baudRate); edge_port->port->number, baudRate);
return 0; return 0;
...@@ -2461,18 +2460,16 @@ static int send_cmd_write_uart_register (struct edgeport_port *edge_port, __u8 r ...@@ -2461,18 +2460,16 @@ static int send_cmd_write_uart_register (struct edgeport_port *edge_port, __u8 r
dbg("%s - write to %s register 0x%02x", (regNum == MCR) ? "MCR" : "LCR", __FUNCTION__, regValue); dbg("%s - write to %s register 0x%02x", (regNum == MCR) ? "MCR" : "LCR", __FUNCTION__, regValue);
if ((!edge_serial->is_epic) || if (edge_serial->is_epic &&
((edge_serial->is_epic) && !edge_serial->epic_descriptor.Supports.IOSPWriteMCR &&
(!edge_serial->epic_descriptor.Supports.IOSPWriteMCR) && regNum == MCR) {
(regNum == MCR))) {
dbg("SendCmdWriteUartReg - Not writing to MCR Register"); dbg("SendCmdWriteUartReg - Not writing to MCR Register");
return 0; return 0;
} }
if ((!edge_serial->is_epic) || if (edge_serial->is_epic &&
((edge_serial->is_epic) && !edge_serial->epic_descriptor.Supports.IOSPWriteLCR &&
(!edge_serial->epic_descriptor.Supports.IOSPWriteLCR) && regNum == LCR) {
(regNum == LCR))) {
dbg ("SendCmdWriteUartReg - Not writing to LCR Register"); dbg ("SendCmdWriteUartReg - Not writing to LCR Register");
return 0; return 0;
} }
......
...@@ -184,21 +184,21 @@ struct mct_u232_private { ...@@ -184,21 +184,21 @@ struct mct_u232_private {
* we do not know how to support. We ignore them for the moment. * we do not know how to support. We ignore them for the moment.
* XXX Rate-limit the error message, it's user triggerable. * XXX Rate-limit the error message, it's user triggerable.
*/ */
static int mct_u232_calculate_baud_rate(struct usb_serial *serial, int value) static int mct_u232_calculate_baud_rate(struct usb_serial *serial, speed_t value)
{ {
if (le16_to_cpu(serial->dev->descriptor.idProduct) == MCT_U232_SITECOM_PID if (le16_to_cpu(serial->dev->descriptor.idProduct) == MCT_U232_SITECOM_PID
|| le16_to_cpu(serial->dev->descriptor.idProduct) == MCT_U232_BELKIN_F5U109_PID) { || le16_to_cpu(serial->dev->descriptor.idProduct) == MCT_U232_BELKIN_F5U109_PID) {
switch (value) { switch (value) {
case B300: return 0x01; case 300: return 0x01;
case B600: return 0x02; /* this one not tested */ case 600: return 0x02; /* this one not tested */
case B1200: return 0x03; case 1200: return 0x03;
case B2400: return 0x04; case 2400: return 0x04;
case B4800: return 0x06; case 4800: return 0x06;
case B9600: return 0x08; case 9600: return 0x08;
case B19200: return 0x09; case 19200: return 0x09;
case B38400: return 0x0a; case 38400: return 0x0a;
case B57600: return 0x0b; case 57600: return 0x0b;
case B115200: return 0x0c; case 115200: return 0x0c;
default: default:
err("MCT USB-RS232: unsupported baudrate request 0x%x," err("MCT USB-RS232: unsupported baudrate request 0x%x,"
" using default of B9600", value); " using default of B9600", value);
...@@ -206,27 +206,27 @@ static int mct_u232_calculate_baud_rate(struct usb_serial *serial, int value) ...@@ -206,27 +206,27 @@ static int mct_u232_calculate_baud_rate(struct usb_serial *serial, int value)
} }
} else { } else {
switch (value) { switch (value) {
case B300: value = 300; break; case 300: break;
case B600: value = 600; break; case 600: break;
case B1200: value = 1200; break; case 1200: break;
case B2400: value = 2400; break; case 2400: break;
case B4800: value = 4800; break; case 4800: break;
case B9600: value = 9600; break; case 9600: break;
case B19200: value = 19200; break; case 19200: break;
case B38400: value = 38400; break; case 38400: break;
case B57600: value = 57600; break; case 57600: break;
case B115200: value = 115200; break; case 115200: break;
default: default:
err("MCT USB-RS232: unsupported baudrate request 0x%x," err("MCT USB-RS232: unsupported baudrate request 0x%x,"
" using default of B9600", value); " using default of B9600", value);
value = 9600; value = 9600;
} }
return 115200/value; return 115200/value;
} }
} }
static int mct_u232_set_baud_rate(struct usb_serial *serial, struct usb_serial_port *port, static int mct_u232_set_baud_rate(struct usb_serial *serial, struct usb_serial_port *port,
int value) speed_t value)
{ {
__le32 divisor; __le32 divisor;
int rc; int rc;
...@@ -634,7 +634,7 @@ static void mct_u232_set_termios (struct usb_serial_port *port, ...@@ -634,7 +634,7 @@ static void mct_u232_set_termios (struct usb_serial_port *port,
mct_u232_set_modem_ctrl(serial, control_state); mct_u232_set_modem_ctrl(serial, control_state);
} }
mct_u232_set_baud_rate(serial, port, cflag & CBAUD); mct_u232_set_baud_rate(serial, port, tty_get_baud_rate(port->tty));
if ((cflag & CBAUD) == B0 ) { if ((cflag & CBAUD) == B0 ) {
dbg("%s: baud is B0", __FUNCTION__); dbg("%s: baud is B0", __FUNCTION__);
......
...@@ -79,7 +79,7 @@ ...@@ -79,7 +79,7 @@
* and "Intel solution". They are the regular MCT and "Sitecom" for us. * and "Intel solution". They are the regular MCT and "Sitecom" for us.
* This is pointless to document in the header, see the code for the bits. * This is pointless to document in the header, see the code for the bits.
*/ */
static int mct_u232_calculate_baud_rate(struct usb_serial *serial, int value); static int mct_u232_calculate_baud_rate(struct usb_serial *serial, speed_t value);
/* /*
* Line Control Register (LCR) * Line Control Register (LCR)
......
...@@ -45,7 +45,7 @@ enum devicetype { ...@@ -45,7 +45,7 @@ enum devicetype {
DEVICE_INSTALLER = 2, DEVICE_INSTALLER = 2,
}; };
int sierra_set_power_state(struct usb_device *udev, __u16 swiState) static int sierra_set_power_state(struct usb_device *udev, __u16 swiState)
{ {
int result; int result;
dev_dbg(&udev->dev, "%s", "SET POWER STATE"); dev_dbg(&udev->dev, "%s", "SET POWER STATE");
...@@ -60,7 +60,7 @@ int sierra_set_power_state(struct usb_device *udev, __u16 swiState) ...@@ -60,7 +60,7 @@ int sierra_set_power_state(struct usb_device *udev, __u16 swiState)
return result; return result;
} }
int sierra_set_ms_mode(struct usb_device *udev, __u16 eSocMode) static int sierra_set_ms_mode(struct usb_device *udev, __u16 eSocMode)
{ {
int result; int result;
dev_dbg(&udev->dev, "%s", "DEVICE MODE SWITCH"); dev_dbg(&udev->dev, "%s", "DEVICE MODE SWITCH");
...@@ -75,7 +75,8 @@ int sierra_set_ms_mode(struct usb_device *udev, __u16 eSocMode) ...@@ -75,7 +75,8 @@ int sierra_set_ms_mode(struct usb_device *udev, __u16 eSocMode)
return result; return result;
} }
int sierra_probe(struct usb_interface *iface, const struct usb_device_id *id) static int sierra_probe(struct usb_interface *iface,
const struct usb_device_id *id)
{ {
int result; int result;
struct usb_device *udev; struct usb_device *udev;
......
...@@ -60,19 +60,19 @@ static struct usb_driver usb_serial_driver = { ...@@ -60,19 +60,19 @@ static struct usb_driver usb_serial_driver = {
static int debug; static int debug;
static struct usb_serial *serial_table[SERIAL_TTY_MINORS]; /* initially all NULL */ static struct usb_serial *serial_table[SERIAL_TTY_MINORS]; /* initially all NULL */
static spinlock_t table_lock; static DEFINE_MUTEX(table_lock);
static LIST_HEAD(usb_serial_driver_list); static LIST_HEAD(usb_serial_driver_list);
struct usb_serial *usb_serial_get_by_index(unsigned index) struct usb_serial *usb_serial_get_by_index(unsigned index)
{ {
struct usb_serial *serial; struct usb_serial *serial;
spin_lock(&table_lock); mutex_lock(&table_lock);
serial = serial_table[index]; serial = serial_table[index];
if (serial) if (serial)
kref_get(&serial->kref); kref_get(&serial->kref);
spin_unlock(&table_lock); mutex_unlock(&table_lock);
return serial; return serial;
} }
...@@ -84,7 +84,7 @@ static struct usb_serial *get_free_serial (struct usb_serial *serial, int num_po ...@@ -84,7 +84,7 @@ static struct usb_serial *get_free_serial (struct usb_serial *serial, int num_po
dbg("%s %d", __FUNCTION__, num_ports); dbg("%s %d", __FUNCTION__, num_ports);
*minor = 0; *minor = 0;
spin_lock(&table_lock); mutex_lock(&table_lock);
for (i = 0; i < SERIAL_TTY_MINORS; ++i) { for (i = 0; i < SERIAL_TTY_MINORS; ++i) {
if (serial_table[i]) if (serial_table[i])
continue; continue;
...@@ -106,10 +106,10 @@ static struct usb_serial *get_free_serial (struct usb_serial *serial, int num_po ...@@ -106,10 +106,10 @@ static struct usb_serial *get_free_serial (struct usb_serial *serial, int num_po
serial_table[i] = serial; serial_table[i] = serial;
serial->port[j++]->number = i; serial->port[j++]->number = i;
} }
spin_unlock(&table_lock); mutex_unlock(&table_lock);
return serial; return serial;
} }
spin_unlock(&table_lock); mutex_unlock(&table_lock);
return NULL; return NULL;
} }
...@@ -172,9 +172,9 @@ static void destroy_serial(struct kref *kref) ...@@ -172,9 +172,9 @@ static void destroy_serial(struct kref *kref)
void usb_serial_put(struct usb_serial *serial) void usb_serial_put(struct usb_serial *serial)
{ {
spin_lock(&table_lock); mutex_lock(&table_lock);
kref_put(&serial->kref, destroy_serial); kref_put(&serial->kref, destroy_serial);
spin_unlock(&table_lock); mutex_unlock(&table_lock);
} }
/***************************************************************************** /*****************************************************************************
...@@ -1077,16 +1077,17 @@ int usb_serial_suspend(struct usb_interface *intf, pm_message_t message) ...@@ -1077,16 +1077,17 @@ int usb_serial_suspend(struct usb_interface *intf, pm_message_t message)
struct usb_serial_port *port; struct usb_serial_port *port;
int i, r = 0; int i, r = 0;
if (serial) { if (!serial) /* device has been disconnected */
for (i = 0; i < serial->num_ports; ++i) { return 0;
port = serial->port[i];
if (port) for (i = 0; i < serial->num_ports; ++i) {
kill_traffic(port); port = serial->port[i];
} if (port)
kill_traffic(port);
} }
if (serial->type->suspend) if (serial->type->suspend)
serial->type->suspend(serial, message); r = serial->type->suspend(serial, message);
return r; return r;
} }
...@@ -1128,7 +1129,6 @@ static int __init usb_serial_init(void) ...@@ -1128,7 +1129,6 @@ static int __init usb_serial_init(void)
return -ENOMEM; return -ENOMEM;
/* Initialize our global data */ /* Initialize our global data */
spin_lock_init(&table_lock);
for (i = 0; i < SERIAL_TTY_MINORS; ++i) { for (i = 0; i < SERIAL_TTY_MINORS; ++i) {
serial_table[i] = NULL; serial_table[i] = NULL;
} }
......
...@@ -320,6 +320,13 @@ UNUSUAL_DEV( 0x04b0, 0x0401, 0x0200, 0x0200, ...@@ -320,6 +320,13 @@ UNUSUAL_DEV( 0x04b0, 0x0401, 0x0200, 0x0200,
US_SC_DEVICE, US_PR_DEVICE, NULL, US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_FIX_CAPACITY), US_FL_FIX_CAPACITY),
/* Reported by Milinevsky Dmitry <niam.niam@gmail.com> */
UNUSUAL_DEV( 0x04b0, 0x0409, 0x0100, 0x0100,
"NIKON",
"NIKON DSC D50",
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_FIX_CAPACITY),
/* Reported by Andreas Bockhold <andreas@bockionline.de> */ /* Reported by Andreas Bockhold <andreas@bockionline.de> */
UNUSUAL_DEV( 0x04b0, 0x0405, 0x0100, 0x0100, UNUSUAL_DEV( 0x04b0, 0x0405, 0x0100, 0x0100,
"NIKON", "NIKON",
...@@ -1357,6 +1364,20 @@ UNUSUAL_DEV( 0x0f19, 0x0105, 0x0100, 0x0100, ...@@ -1357,6 +1364,20 @@ UNUSUAL_DEV( 0x0f19, 0x0105, 0x0100, 0x0100,
US_SC_DEVICE, US_PR_DEVICE, NULL, US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_IGNORE_RESIDUE ), US_FL_IGNORE_RESIDUE ),
/* Jeremy Katz <katzj@redhat.com>:
* The Blackberry Pearl can run in two modes; a usb-storage only mode
* and a mode that allows access via mass storage and to its database.
* The berry_charge module will set the device to dual mode and thus we
* should ignore its native mode if that module is built
*/
#ifdef CONFIG_USB_BERRY_CHARGE
UNUSUAL_DEV( 0x0fca, 0x0006, 0x0001, 0x0001,
"RIM",
"Blackberry Pearl",
US_SC_DEVICE, US_PR_DEVICE, NULL,
US_FL_IGNORE_DEVICE ),
#endif
/* Reported by Michael Stattmann <michael@stattmann.com> */ /* Reported by Michael Stattmann <michael@stattmann.com> */
UNUSUAL_DEV( 0x0fce, 0xd008, 0x0000, 0x0000, UNUSUAL_DEV( 0x0fce, 0xd008, 0x0000, 0x0000,
"Sony Ericsson", "Sony Ericsson",
......
...@@ -94,6 +94,7 @@ enum usb_interface_condition { ...@@ -94,6 +94,7 @@ enum usb_interface_condition {
* endpoint configurations. They will be in no particular order. * endpoint configurations. They will be in no particular order.
* @num_altsetting: number of altsettings defined. * @num_altsetting: number of altsettings defined.
* @cur_altsetting: the current altsetting. * @cur_altsetting: the current altsetting.
* @intf_assoc: interface association descriptor
* @driver: the USB driver that is bound to this interface. * @driver: the USB driver that is bound to this interface.
* @minor: the minor number assigned to this interface, if this * @minor: the minor number assigned to this interface, if this
* interface is bound to a driver that uses the USB major number. * interface is bound to a driver that uses the USB major number.
...@@ -213,6 +214,7 @@ struct usb_interface_cache { ...@@ -213,6 +214,7 @@ struct usb_interface_cache {
* @desc: the device's configuration descriptor. * @desc: the device's configuration descriptor.
* @string: pointer to the cached version of the iConfiguration string, if * @string: pointer to the cached version of the iConfiguration string, if
* present for this configuration. * present for this configuration.
* @intf_assoc: list of any interface association descriptors in this config
* @interface: array of pointers to usb_interface structures, one for each * @interface: array of pointers to usb_interface structures, one for each
* interface in the configuration. The number of interfaces is stored * interface in the configuration. The number of interfaces is stored
* in desc.bNumInterfaces. These pointers are valid only while the * in desc.bNumInterfaces. These pointers are valid only while the
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment