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/
obj-$(CONFIG_USB_TEST) += misc/
obj-$(CONFIG_USB_TRANCEVIBRATOR)+= misc/
obj-$(CONFIG_USB_USS720) += misc/
obj-$(CONFIG_USB_IOWARRIOR) += misc/
obj-$(CONFIG_USB_ATM) += atm/
obj-$(CONFIG_USB_SPEEDTOUCH) += atm/
......@@ -18,9 +18,17 @@
#include "hcd.h" /* for usbcore internals */
#include "usb.h"
struct api_context {
struct completion done;
int status;
};
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)
*/
static int usb_start_wait_urb(struct urb *urb, int timeout, int *actual_length)
{
struct completion done;
struct api_context ctx;
unsigned long expire;
int retval;
int status = urb->status;
init_completion(&done);
urb->context = &done;
init_completion(&ctx.done);
urb->context = &ctx;
urb->actual_length = 0;
retval = usb_submit_urb(urb, GFP_NOIO);
if (unlikely(retval))
goto out;
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,
"%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)
usb_pipein(urb->pipe) ? "in" : "out",
urb->actual_length,
urb->transfer_buffer_length);
usb_kill_urb(urb);
retval = status == -ENOENT ? -ETIMEDOUT : status;
} else
retval = status;
retval = ctx.status;
out:
if (actual_length)
*actual_length = urb->actual_length;
......@@ -411,15 +417,22 @@ int usb_sg_init (
* Some systems need to revert to PIO when DMA is temporarily
* unavailable. For their sakes, both transfer_buffer and
* transfer_dma are set when possible. However this can only
* work on systems without HIGHMEM, since DMA buffers located
* in high memory are not directly addressable by the CPU for
* PIO ... so when HIGHMEM is in use, transfer_buffer is NULL
* work on systems without:
*
* - 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.
*/
if (dma) {
io->urbs [i]->transfer_dma = sg_dma_address (sg + i);
len = sg_dma_len (sg + i);
#ifdef CONFIG_HIGHMEM
#if defined(CONFIG_HIGHMEM) || defined(CONFIG_IOMMU)
io->urbs[i]->transfer_buffer = NULL;
#else
io->urbs[i]->transfer_buffer =
......
......@@ -30,18 +30,40 @@
static const struct usb_device_id usb_quirk_list[] = {
/* HP 5300/5370C scanner */
{ 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 */
{ 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 */
{ 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 */
{ 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 */
{ USB_DEVICE(0x04e8, 0x327e), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
/* Elsa MicroLink 56k (V.250) */
{ USB_DEVICE(0x05cc, 0x2267), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
/* Ultima Electronics Corp.*/
{ 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 */
{ USB_DEVICE(0x1606, 0x0060), .driver_info = USB_QUIRK_NO_AUTOSUSPEND },
......
......@@ -50,7 +50,7 @@ usb_descriptor_fillbuf(void *buf, unsigned buflen,
return -EINVAL;
/* fill buffer from src[] until null descriptor ptr */
for (; 0 != *src; src++) {
for (; NULL != *src; src++) {
unsigned len = (*src)->bLength;
if (len > buflen)
......
......@@ -71,7 +71,7 @@ ep_matches (
u16 max;
/* endpoint already claimed? */
if (0 != ep->driver_data)
if (NULL != ep->driver_data)
return 0;
/* 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)
size += sizeof (struct rndis_packet_msg_type);
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");
goto enomem;
}
......
......@@ -964,7 +964,7 @@ static int setup_req (struct usb_ep *ep, struct usb_request *req, u16 len)
}
if (len > sizeof (dev->rbuf))
req->buf = kmalloc(len, GFP_ATOMIC);
if (req->buf == 0) {
if (req->buf == NULL) {
req->buf = dev->rbuf;
return -ENOMEM;
}
......@@ -1394,7 +1394,7 @@ gadgetfs_setup (struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
dev->setup_abort = 0;
if (dev->state == STATE_DEV_UNCONNECTED) {
#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);
ERROR (dev, "no high speed config??\n");
return -EINVAL;
......
......@@ -1299,7 +1299,7 @@ static int m66592_queue(struct usb_ep *_ep, struct usb_request *_req,
req->req.actual = 0;
req->req.status = -EINPROGRESS;
if (ep->desc == 0) /* control */
if (ep->desc == NULL) /* control */
start_ep0(ep, req);
else {
if (request && !ep->busy)
......
......@@ -93,8 +93,6 @@ static const char driver_name [] = "pxa2xx_udc";
static const char ep0name [] = "ep0";
// #define DISABLE_TEST_MODE
#ifdef CONFIG_ARCH_IXP4XX
/* cpu-specific register addresses are compiled in to this code */
......@@ -113,17 +111,6 @@ static const char ep0name [] = "ep0";
#define SIZE_STR ""
#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,
* used by gadget driver; and the inner talker-to-hardware core.
......@@ -1252,23 +1239,6 @@ static void udc_enable (struct pxa2xx_udc *dev)
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 */
udc_clear_mask_UDCCR(UDCCR_SRM | UDCCR_REM);
......
......@@ -653,7 +653,8 @@ set_source_sink_config (struct zero_dev *dev, gfp_t gfp_flags)
result = usb_ep_enable (ep, d);
if (result == 0) {
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;
continue;
}
......@@ -667,7 +668,8 @@ set_source_sink_config (struct zero_dev *dev, gfp_t gfp_flags)
result = usb_ep_enable (ep, d);
if (result == 0) {
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;
continue;
}
......
......@@ -356,7 +356,7 @@ static void cp2101_get_termios (struct usb_serial_port *port)
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__);
return;
}
......@@ -526,50 +526,35 @@ static void cp2101_set_termios (struct usb_serial_port *port,
return;
}
cflag = port->tty->termios->c_cflag;
/* Check that they really want us to change something */
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;
}
old_cflag = old_termios->c_cflag;
baud = tty_get_baud_rate(port->tty);
/* If the baud rate is to be updated*/
if ((cflag & CBAUD) != (old_cflag & CBAUD)) {
switch (cflag & CBAUD) {
/*
* The baud rates which are commented out below
* appear to be supported by the device
* but are non-standard
*/
case B0: baud = 0; break;
case B600: baud = 600; break;
case B1200: baud = 1200; break;
case B1800: baud = 1800; break;
case B2400: baud = 2400; break;
case B4800: baud = 4800; break;
/*case B7200: baud = 7200; break;*/
case B9600: baud = 9600; break;
/*ase B14400: baud = 14400; break;*/
case B19200: baud = 19200; break;
/*case B28800: baud = 28800; break;*/
case B38400: baud = 38400; break;
/*case B55854: baud = 55054; break;*/
case B57600: baud = 57600; break;
case B115200: baud = 115200; break;
/*case B127117: baud = 127117; break;*/
case B230400: baud = 230400; break;
case B460800: baud = 460800; break;
case B921600: baud = 921600; break;
/*case B3686400: baud = 3686400; break;*/
if (baud != tty_termios_baud_rate(old_termios)) {
switch (baud) {
case 0:
case 600:
case 1200:
case 1800:
case 2400:
case 4800:
case 7200:
case 9600:
case 14400:
case 19200:
case 28800:
case 38400:
case 55854:
case 57600:
case 115200:
case 127117:
case 230400:
case 460800:
case 921600:
case 3686400:
break;
default:
dev_err(&port->dev, "cp2101 driver does not "
"support the baudrate requested\n");
baud = 9600;
break;
}
......
......@@ -433,38 +433,38 @@ struct digi_port {
/* 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 int digi_write_oob_command( struct usb_serial_port *port,
unsigned char *buf, int count, int interruptible );
static int digi_write_inb_command( struct usb_serial_port *port,
unsigned char *buf, int count, unsigned long timeout );
static int digi_set_modem_signals( struct usb_serial_port *port,
unsigned int modem_signals, int interruptible );
static int digi_transmit_idle( struct usb_serial_port *port,
unsigned long timeout );
static int digi_write_oob_command(struct usb_serial_port *port,
unsigned char *buf, int count, int interruptible);
static int digi_write_inb_command(struct usb_serial_port *port,
unsigned char *buf, int count, unsigned long timeout);
static int digi_set_modem_signals(struct usb_serial_port *port,
unsigned int modem_signals, int interruptible);
static int digi_transmit_idle(struct usb_serial_port *port,
unsigned long timeout);
static void digi_rx_throttle (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,
struct ktermios *old_termios );
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,
unsigned int cmd, unsigned long arg );
static int digi_tiocmget( 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 );
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 int digi_write_room( 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 void digi_close( struct usb_serial_port *port, struct file *filp );
static int digi_startup_device( struct usb_serial *serial );
static int digi_startup( struct usb_serial *serial );
static void digi_shutdown( struct usb_serial *serial );
static void digi_read_bulk_callback( struct urb *urb );
static int digi_read_inb_callback( struct urb *urb );
static int digi_read_oob_callback( struct urb *urb );
static void digi_set_termios(struct usb_serial_port *port,
struct ktermios *old_termios);
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,
unsigned int cmd, unsigned long arg);
static int digi_tiocmget(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);
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 int digi_write_room(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 void digi_close(struct usb_serial_port *port, struct file *filp);
static int digi_startup_device(struct usb_serial *serial);
static int digi_startup(struct usb_serial *serial);
static void digi_shutdown(struct usb_serial *serial);
static void digi_read_bulk_callback(struct urb *urb);
static int digi_read_inb_callback(struct urb *urb);
static int digi_read_oob_callback(struct urb *urb);
/* Statics */
......@@ -576,9 +576,9 @@ static struct usb_serial_driver digi_acceleport_4_device = {
* 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,
spinlock_t *lock, unsigned long flags )
spinlock_t *lock, unsigned long flags)
{
DEFINE_WAIT(wait);
......@@ -600,18 +600,16 @@ static inline long cond_wait_interruptible_timeout_irqrestore(
static void digi_wakeup_write_lock(struct work_struct *work)
{
struct digi_port *priv =
container_of(work, struct digi_port, dp_wakeup_work);
struct digi_port *priv = container_of(work, struct digi_port, dp_wakeup_work);
struct usb_serial_port *port = priv->dp_port;
unsigned long flags;
spin_lock_irqsave( &priv->dp_port_lock, flags );
digi_wakeup_write( port );
spin_unlock_irqrestore( &priv->dp_port_lock, flags );
spin_lock_irqsave(&priv->dp_port_lock, flags);
digi_wakeup_write(port);
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);
}
......@@ -628,8 +626,8 @@ static void digi_wakeup_write( struct usb_serial_port *port )
* returned by usb_submit_urb.
*/
static int digi_write_oob_command( struct usb_serial_port *port,
unsigned char *buf, int count, int interruptible )
static int digi_write_oob_command(struct usb_serial_port *port,
unsigned char *buf, int count, int interruptible)
{
int ret = 0;
......@@ -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);
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 ) {
while( oob_port->write_urb->status == -EINPROGRESS
|| oob_priv->dp_write_urb_in_use ) {
spin_lock_irqsave(&oob_priv->dp_port_lock, flags);
while(count > 0) {
while(oob_port->write_urb->status == -EINPROGRESS
|| oob_priv->dp_write_urb_in_use) {
cond_wait_interruptible_timeout_irqrestore(
&oob_port->write_wait, DIGI_RETRY_TIMEOUT,
&oob_priv->dp_port_lock, flags );
if( interruptible && signal_pending(current) ) {
return( -EINTR );
}
spin_lock_irqsave( &oob_priv->dp_port_lock, flags );
&oob_priv->dp_port_lock, flags);
if (interruptible && signal_pending(current))
return -EINTR;
spin_lock_irqsave(&oob_priv->dp_port_lock, flags);
}
/* len must be a multiple of 4, so commands are not split */
len = min(count, oob_port->bulk_out_size );
if( len > 4 )
len = min(count, oob_port->bulk_out_size);
if (len > 4)
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->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;
count -= len;
buf += len;
}
}
spin_unlock_irqrestore( &oob_priv->dp_port_lock, flags );
if( ret ) {
err("%s: usb_submit_urb failed, ret=%d", __FUNCTION__,
ret );
}
return( ret );
spin_unlock_irqrestore(&oob_priv->dp_port_lock, flags);
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
* error returned by digi_write.
*/
static int digi_write_inb_command( struct usb_serial_port *port,
unsigned char *buf, int count, unsigned long timeout )
static int digi_write_inb_command(struct usb_serial_port *port,
unsigned char *buf, int count, unsigned long timeout)
{
int ret = 0;
int len;
struct digi_port *priv = usb_get_serial_port_data(port);
unsigned char *data = port->write_urb->transfer_buffer;
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,
count );
if( timeout )
if (timeout)
timeout += jiffies;
else
timeout = ULONG_MAX;
spin_lock_irqsave( &priv->dp_port_lock, flags );
while( count > 0 && ret == 0 ) {
while( (port->write_urb->status == -EINPROGRESS
|| priv->dp_write_urb_in_use) && time_before(jiffies, timeout)) {
spin_lock_irqsave(&priv->dp_port_lock, flags);
while(count > 0 && ret == 0) {
while((port->write_urb->status == -EINPROGRESS
|| priv->dp_write_urb_in_use) && time_before(jiffies, timeout)) {
cond_wait_interruptible_timeout_irqrestore(
&port->write_wait, DIGI_RETRY_TIMEOUT,
&priv->dp_port_lock, flags );
if( signal_pending(current) ) {
return( -EINTR );
}
spin_lock_irqsave( &priv->dp_port_lock, flags );
&priv->dp_port_lock, flags);
if (signal_pending(current))
return -EINTR;
spin_lock_irqsave(&priv->dp_port_lock, flags);
}
/* len must be a multiple of 4 and small enough to */
/* guarantee the write will send buffered data first, */
/* so commands are in order with data and not split */
len = min(count, port->bulk_out_size-2-priv->dp_out_buf_len );
if( len > 4 )
len = min(count, port->bulk_out_size-2-priv->dp_out_buf_len);
if (len > 4)
len &= ~3;
/* 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[1] = priv->dp_out_buf_len;
memcpy( data+2, priv->dp_out_buf,
priv->dp_out_buf_len );
memcpy( data+2+priv->dp_out_buf_len, buf, len );
memcpy(data + 2, priv->dp_out_buf,
priv->dp_out_buf_len);
memcpy(data + 2 + priv->dp_out_buf_len, buf, len);
port->write_urb->transfer_buffer_length
= priv->dp_out_buf_len+2+len;
= priv->dp_out_buf_len + 2 + len;
} else {
memcpy( data, buf, len );
memcpy(data, buf, len);
port->write_urb->transfer_buffer_length = len;
}
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_out_buf_len = 0;
count -= len;
......@@ -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", __FUNCTION__,
ret, priv->dp_port_num );
}
return( ret );
if (ret)
err("%s: usb_submit_urb failed, ret=%d, port=%d",
__FUNCTION__, ret, priv->dp_port_num);
return ret;
}
......@@ -784,8 +761,8 @@ count );
* returned by usb_submit_urb.
*/
static int digi_set_modem_signals( struct usb_serial_port *port,
unsigned int modem_signals, int interruptible )
static int digi_set_modem_signals(struct usb_serial_port *port,
unsigned int modem_signals, int interruptible)
{
int ret;
......@@ -796,60 +773,47 @@ static int digi_set_modem_signals( struct usb_serial_port *port,
unsigned long flags = 0;
dbg( "digi_set_modem_signals: TOP: port=%d, modem_signals=0x%x",
port_priv->dp_port_num, modem_signals );
dbg("digi_set_modem_signals: TOP: port=%d, modem_signals=0x%x",
port_priv->dp_port_num, modem_signals);
spin_lock_irqsave( &oob_priv->dp_port_lock, flags );
spin_lock( &port_priv->dp_port_lock );
spin_lock_irqsave(&oob_priv->dp_port_lock, flags);
spin_lock(&port_priv->dp_port_lock);
while( oob_port->write_urb->status == -EINPROGRESS
|| oob_priv->dp_write_urb_in_use ) {
spin_unlock( &port_priv->dp_port_lock );
while(oob_port->write_urb->status == -EINPROGRESS || oob_priv->dp_write_urb_in_use) {
spin_unlock(&port_priv->dp_port_lock);
cond_wait_interruptible_timeout_irqrestore(
&oob_port->write_wait, DIGI_RETRY_TIMEOUT,
&oob_priv->dp_port_lock, flags );
if( interruptible && signal_pending(current) ) {
return( -EINTR );
}
spin_lock_irqsave( &oob_priv->dp_port_lock, flags );
spin_lock( &port_priv->dp_port_lock );
&oob_priv->dp_port_lock, flags);
if (interruptible && signal_pending(current))
return -EINTR;
spin_lock_irqsave(&oob_priv->dp_port_lock, flags);
spin_lock(&port_priv->dp_port_lock);
}
data[0] = DIGI_CMD_SET_DTR_SIGNAL;
data[1] = port_priv->dp_port_num;
data[2] = (modem_signals&TIOCM_DTR) ?
DIGI_DTR_ACTIVE : DIGI_DTR_INACTIVE;
data[2] = (modem_signals&TIOCM_DTR) ? DIGI_DTR_ACTIVE : DIGI_DTR_INACTIVE;
data[3] = 0;
data[4] = DIGI_CMD_SET_RTS_SIGNAL;
data[5] = port_priv->dp_port_num;
data[6] = (modem_signals&TIOCM_RTS) ?
DIGI_RTS_ACTIVE : DIGI_RTS_INACTIVE;
data[6] = (modem_signals&TIOCM_RTS) ? DIGI_RTS_ACTIVE : DIGI_RTS_INACTIVE;
data[7] = 0;
oob_port->write_urb->transfer_buffer_length = 8;
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;
port_priv->dp_modem_signals =
(port_priv->dp_modem_signals&~(TIOCM_DTR|TIOCM_RTS))
| (modem_signals&(TIOCM_DTR|TIOCM_RTS));
}
spin_unlock( &port_priv->dp_port_lock );
spin_unlock_irqrestore( &oob_priv->dp_port_lock, flags );
if( ret ) {
err("%s: usb_submit_urb failed, ret=%d", __FUNCTION__,
ret );
}
return( ret );
spin_unlock(&port_priv->dp_port_lock);
spin_unlock_irqrestore(&oob_priv->dp_port_lock, flags);
if (ret)
err("%s: usb_submit_urb failed, ret=%d", __FUNCTION__, ret);
return ret;
}
/*
* Digi Transmit Idle
*
......@@ -862,203 +826,182 @@ port_priv->dp_port_num, modem_signals );
* port at a time, so its ok.
*/
static int digi_transmit_idle( struct usb_serial_port *port,
unsigned long timeout )
static int digi_transmit_idle(struct usb_serial_port *port,
unsigned long timeout)
{
int ret;
unsigned char buf[2];
struct digi_port *priv = usb_get_serial_port_data(port);
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;
spin_unlock_irqrestore( &priv->dp_port_lock, flags );
spin_unlock_irqrestore(&priv->dp_port_lock, flags);
buf[0] = DIGI_CMD_TRANSMIT_IDLE;
buf[1] = 0;
timeout += jiffies;
if( (ret=digi_write_inb_command( port, buf, 2, timeout-jiffies )) != 0 )
return( ret );
if ((ret = digi_write_inb_command(port, buf, 2, timeout - jiffies)) != 0)
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(
&priv->dp_transmit_idle_wait, DIGI_RETRY_TIMEOUT,
&priv->dp_port_lock, flags );
if( signal_pending(current) ) {
return( -EINTR );
}
spin_lock_irqsave( &priv->dp_port_lock, flags );
&priv->dp_port_lock, flags);
if (signal_pending(current))
return -EINTR;
spin_lock_irqsave(&priv->dp_port_lock, flags);
}
priv->dp_transmit_idle = 0;
spin_unlock_irqrestore( &priv->dp_port_lock, flags );
return( 0 );
spin_unlock_irqrestore(&priv->dp_port_lock, flags);
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;
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 */
spin_lock_irqsave( &priv->dp_port_lock, flags );
spin_lock_irqsave(&priv->dp_port_lock, flags);
priv->dp_throttled = 1;
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;
unsigned long flags;
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 */
priv->dp_throttled = 0;
priv->dp_throttle_restart = 0;
/* restart read chain */
if( priv->dp_throttle_restart ) {
if (priv->dp_throttle_restart) {
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 );
if( ret ) {
err("%s: usb_submit_urb failed, ret=%d, port=%d", __FUNCTION__,
ret, priv->dp_port_num );
}
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);
}
static void digi_set_termios( struct usb_serial_port *port,
struct ktermios *old_termios )
static void digi_set_termios(struct usb_serial_port *port,
struct ktermios *old_termios)
{
struct digi_port *priv = usb_get_serial_port_data(port);
unsigned int iflag = port->tty->termios->c_iflag;
unsigned int cflag = port->tty->termios->c_cflag;
struct tty_struct *tty = port->tty;
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_cflag = old_termios->c_cflag;
unsigned char buf[32];
unsigned int modem_signals;
int arg,ret;
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 */
if( (cflag&CBAUD) != (old_cflag&CBAUD) ) {
if ((baud = tty_get_baud_rate(tty)) != tty_termios_baud_rate(old_termios)) {
arg = -1;
/* 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 */
/* and throttling input */
modem_signals = TIOCM_DTR;
if( !(port->tty->termios->c_cflag & CRTSCTS) ||
!test_bit(TTY_THROTTLED, &port->tty->flags) ) {
if (!(tty->termios->c_cflag & CRTSCTS) ||
!test_bit(TTY_THROTTLED, &tty->flags))
modem_signals |= TIOCM_RTS;
}
digi_set_modem_signals( port, modem_signals, 1 );
digi_set_modem_signals(port, modem_signals, 1);
}
switch( (cflag&CBAUD) ) {
switch (baud) {
/* drop DTR and RTS on transition to B0 */
case B0: digi_set_modem_signals( port, 0, 1 ); break;
case B50: arg = DIGI_BAUD_50; break;
case B75: arg = DIGI_BAUD_75; break;
case B110: arg = DIGI_BAUD_110; break;
case B150: arg = DIGI_BAUD_150; break;
case B200: arg = DIGI_BAUD_200; break;
case B300: arg = DIGI_BAUD_300; break;
case B600: arg = DIGI_BAUD_600; break;
case B1200: arg = DIGI_BAUD_1200; break;
case B1800: arg = DIGI_BAUD_1800; break;
case B2400: arg = DIGI_BAUD_2400; break;
case B4800: arg = DIGI_BAUD_4800; break;
case B9600: arg = DIGI_BAUD_9600; break;
case B19200: arg = DIGI_BAUD_19200; break;
case B38400: arg = DIGI_BAUD_38400; break;
case B57600: arg = DIGI_BAUD_57600; break;
case B115200: arg = DIGI_BAUD_115200; break;
case B230400: arg = DIGI_BAUD_230400; break;
case B460800: arg = DIGI_BAUD_460800; break;
default:
dbg( "digi_set_termios: can't handle baud rate 0x%x",
(cflag&CBAUD) );
break;
case 0: digi_set_modem_signals(port, 0, 1); break;
case 50: arg = DIGI_BAUD_50; break;
case 75: arg = DIGI_BAUD_75; break;
case 110: arg = DIGI_BAUD_110; break;
case 150: arg = DIGI_BAUD_150; break;
case 200: arg = DIGI_BAUD_200; break;
case 300: arg = DIGI_BAUD_300; break;
case 600: arg = DIGI_BAUD_600; break;
case 1200: arg = DIGI_BAUD_1200; break;
case 1800: arg = DIGI_BAUD_1800; break;
case 2400: arg = DIGI_BAUD_2400; break;
case 4800: arg = DIGI_BAUD_4800; break;
case 9600: arg = DIGI_BAUD_9600; break;
case 19200: arg = DIGI_BAUD_19200; break;
case 38400: arg = DIGI_BAUD_38400; break;
case 57600: arg = DIGI_BAUD_57600; break;
case 115200: arg = DIGI_BAUD_115200; break;
case 230400: arg = DIGI_BAUD_230400; break;
case 460800: arg = DIGI_BAUD_460800; break;
default:
arg = DIGI_BAUD_9600;
baud = 9600;
break;
}
if( arg != -1 ) {
if (arg != -1) {
buf[i++] = DIGI_CMD_SET_BAUD_RATE;
buf[i++] = priv->dp_port_num;
buf[i++] = arg;
buf[i++] = 0;
}
}
/* set parity */
if( (cflag&(PARENB|PARODD)) != (old_cflag&(PARENB|PARODD)) ) {
if( (cflag&PARENB) ) {
if( (cflag&PARODD) )
if ((cflag&(PARENB|PARODD)) != (old_cflag&(PARENB|PARODD))) {
if (cflag&PARENB) {
if (cflag&PARODD)
arg = DIGI_PARITY_ODD;
else
arg = DIGI_PARITY_EVEN;
} else {
arg = DIGI_PARITY_NONE;
}
buf[i++] = DIGI_CMD_SET_PARITY;
buf[i++] = priv->dp_port_num;
buf[i++] = arg;
buf[i++] = 0;
}
/* set word size */
if( (cflag&CSIZE) != (old_cflag&CSIZE) ) {
if ((cflag&CSIZE) != (old_cflag&CSIZE)) {
arg = -1;
switch( (cflag&CSIZE) ) {
switch (cflag&CSIZE) {
case CS5: arg = DIGI_WORD_SIZE_5; break;
case CS6: arg = DIGI_WORD_SIZE_6; break;
case CS7: arg = DIGI_WORD_SIZE_7; break;
case CS8: arg = DIGI_WORD_SIZE_8; break;
default:
dbg( "digi_set_termios: can't handle word size %d",
(cflag&CSIZE) );
dbg("digi_set_termios: can't handle word size %d",
(cflag&CSIZE));
break;
}
if( arg != -1 ) {
if (arg != -1) {
buf[i++] = DIGI_CMD_SET_WORD_SIZE;
buf[i++] = priv->dp_port_num;
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
}
/* 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;
else
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
}
/* set input flow control */
if( (iflag&IXOFF) != (old_iflag&IXOFF)
|| (cflag&CRTSCTS) != (old_cflag&CRTSCTS) ) {
if ((iflag&IXOFF) != (old_iflag&IXOFF)
|| (cflag&CRTSCTS) != (old_cflag&CRTSCTS)) {
arg = 0;
if( (iflag&IXOFF) )
if (iflag&IXOFF)
arg |= DIGI_INPUT_FLOW_CONTROL_XON_XOFF;
else
arg &= ~DIGI_INPUT_FLOW_CONTROL_XON_XOFF;
if( (cflag&CRTSCTS) ) {
if (cflag&CRTSCTS) {
arg |= DIGI_INPUT_FLOW_CONTROL_RTS;
/* 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
} else {
arg &= ~DIGI_INPUT_FLOW_CONTROL_RTS;
}
buf[i++] = DIGI_CMD_SET_INPUT_FLOW_CONTROL;
buf[i++] = priv->dp_port_num;
buf[i++] = arg;
buf[i++] = 0;
}
/* set output flow control */
if( (iflag&IXON) != (old_iflag&IXON)
|| (cflag&CRTSCTS) != (old_cflag&CRTSCTS) ) {
if ((iflag&IXON) != (old_iflag&IXON)
|| (cflag&CRTSCTS) != (old_cflag&CRTSCTS)) {
arg = 0;
if( (iflag&IXON) )
if (iflag&IXON)
arg |= DIGI_OUTPUT_FLOW_CONTROL_XON_XOFF;
else
arg &= ~DIGI_OUTPUT_FLOW_CONTROL_XON_XOFF;
if( (cflag&CRTSCTS) ) {
if (cflag&CRTSCTS) {
arg |= DIGI_OUTPUT_FLOW_CONTROL_CTS;
} else {
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++] = priv->dp_port_num;
buf[i++] = arg;
buf[i++] = 0;
}
/* set receive enable/disable */
if( (cflag&CREAD) != (old_cflag&CREAD) ) {
if( (cflag&CREAD) )
if ((cflag&CREAD) != (old_cflag&CREAD)) {
if (cflag&CREAD)
arg = DIGI_ENABLE;
else
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
buf[i++] = priv->dp_port_num;
buf[i++] = arg;
buf[i++] = 0;
}
if( (ret=digi_write_oob_command( port, buf, i, 1 )) != 0 )
dbg( "digi_set_termios: write oob failed, ret=%d", ret );
if ((ret = digi_write_oob_command(port, buf, i, 1)) != 0)
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];
buf[0] = DIGI_CMD_BREAK_CONTROL;
buf[1] = 2; /* length */
buf[2] = break_state ? 1 : 0;
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);
unsigned int val;
......@@ -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);
spin_lock_irqsave( &priv->dp_port_lock, flags );
spin_lock_irqsave(&priv->dp_port_lock, flags);
val = priv->dp_modem_signals;
spin_unlock_irqrestore( &priv->dp_port_lock, flags );
spin_unlock_irqrestore(&priv->dp_port_lock, flags);
return val;
}
static int digi_tiocmset( struct usb_serial_port *port, struct file *file,
unsigned int set, unsigned int clear )
static int digi_tiocmset(struct usb_serial_port *port, struct file *file,
unsigned int set, unsigned int clear)
{
struct digi_port *priv = usb_get_serial_port_data(port);
unsigned int val;
......@@ -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);
spin_lock_irqsave( &priv->dp_port_lock, flags );
spin_lock_irqsave(&priv->dp_port_lock, flags);
val = (priv->dp_modem_signals & ~clear) | set;
spin_unlock_irqrestore( &priv->dp_port_lock, flags );
return digi_set_modem_signals( port, val, 1 );
spin_unlock_irqrestore(&priv->dp_port_lock, flags);
return digi_set_modem_signals(port, val, 1);
}
static int digi_ioctl( struct usb_serial_port *port, struct file *file,
unsigned int cmd, unsigned long arg )
static int digi_ioctl(struct usb_serial_port *port, struct file *file,
unsigned int cmd, unsigned long arg)
{
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) {
case TIOCMIWAIT:
/* wait for any of the 4 modem inputs (DCD,RI,DSR,CTS)*/
/* TODO */
return( 0 );
return 0;
case TIOCGICOUNT:
/* return count of modemline transitions */
/* TODO */
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;
......@@ -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 long flags = 0;
dbg( "digi_write: TOP: port=%d, count=%d, in_interrupt=%ld",
priv->dp_port_num, count, in_interrupt() );
dbg("digi_write: TOP: port=%d, count=%d, in_interrupt=%ld",
priv->dp_port_num, count, in_interrupt());
/* copy user data (which can sleep) before getting spin lock */
count = min( count, port->bulk_out_size-2 );
count = min( 64, count);
count = min(count, port->bulk_out_size-2);
count = min(64, count);
/* be sure only one write proceeds at a time */
/* there are races on the port private buffer */
/* 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 */
if( port->write_urb->status == -EINPROGRESS
|| priv->dp_write_urb_in_use ) {
if (port->write_urb->status == -EINPROGRESS || priv->dp_write_urb_in_use) {
/* 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;
new_len = 1;
} else {
new_len = 0;
}
spin_unlock_irqrestore( &priv->dp_port_lock, flags );
return( new_len );
spin_unlock_irqrestore(&priv->dp_port_lock, flags);
return new_len;
}
/* allow space for any buffered data and for new data, up to */
......@@ -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);
data_len = new_len + priv->dp_out_buf_len;
if( data_len == 0 ) {
spin_unlock_irqrestore( &priv->dp_port_lock, flags );
return( 0 );
if (data_len == 0) {
spin_unlock_irqrestore(&priv->dp_port_lock, flags);
return 0;
}
port->write_urb->transfer_buffer_length = data_len+2;
......@@ -1291,32 +1206,29 @@ priv->dp_port_num, count, in_interrupt() );
*data++ = data_len;
/* 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;
/* 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;
ret = new_len;
priv->dp_out_buf_len = 0;
}
/* return length of new data written, or error */
spin_unlock_irqrestore( &priv->dp_port_lock, flags );
if( ret < 0 ) {
err("%s: usb_submit_urb failed, ret=%d, port=%d", __FUNCTION__,
ret, priv->dp_port_num );
}
dbg( "digi_write: returning %d", ret );
return( ret );
spin_unlock_irqrestore(&priv->dp_port_lock, flags);
if (ret < 0)
err("%s: usb_submit_urb failed, ret=%d, port=%d",
__FUNCTION__, ret, priv->dp_port_num);
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;
......@@ -1326,153 +1238,136 @@ static void digi_write_bulk_callback( struct urb *urb )
int ret = 0;
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 */
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",
__FUNCTION__, status);
return;
}
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",
__FUNCTION__, status);
return;
}
/* handle oob callback */
if( priv->dp_port_num == serial_priv->ds_oob_port_num ) {
dbg( "digi_write_bulk_callback: oob callback" );
spin_lock( &priv->dp_port_lock );
if (priv->dp_port_num == serial_priv->ds_oob_port_num) {
dbg("digi_write_bulk_callback: oob callback");
spin_lock(&priv->dp_port_lock);
priv->dp_write_urb_in_use = 0;
wake_up_interruptible( &port->write_wait );
spin_unlock( &priv->dp_port_lock );
wake_up_interruptible(&port->write_wait);
spin_unlock(&priv->dp_port_lock);
return;
}
/* 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;
if( port->open_count && port->write_urb->status != -EINPROGRESS
&& priv->dp_out_buf_len > 0 ) {
if (port->open_count && port->write_urb->status != -EINPROGRESS
&& priv->dp_out_buf_len > 0) {
*((unsigned char *)(port->write_urb->transfer_buffer))
= (unsigned char)DIGI_CMD_SEND_DATA;
*((unsigned char *)(port->write_urb->transfer_buffer)+1)
= (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;
memcpy( port->write_urb->transfer_buffer+2, priv->dp_out_buf,
priv->dp_out_buf_len );
if( (ret=usb_submit_urb(port->write_urb, GFP_ATOMIC)) == 0 ) {
memcpy(port->write_urb->transfer_buffer+2, priv->dp_out_buf,
priv->dp_out_buf_len);
if ((ret = usb_submit_urb(port->write_urb, GFP_ATOMIC)) == 0) {
priv->dp_write_urb_in_use = 1;
priv->dp_out_buf_len = 0;
}
}
/* 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 */
/* lost the race in write_chan(). */
schedule_work(&priv->dp_wakeup_work);
spin_unlock( &priv->dp_port_lock );
if( ret ) {
err("%s: usb_submit_urb failed, ret=%d, port=%d", __FUNCTION__,
ret, priv->dp_port_num );
}
spin_unlock(&priv->dp_port_lock);
if (ret)
err("%s: usb_submit_urb failed, ret=%d, port=%d",
__FUNCTION__, 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;
struct digi_port *priv = usb_get_serial_port_data(port);
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;
else
room = port->bulk_out_size - 2 - priv->dp_out_buf_len;
spin_unlock_irqrestore( &priv->dp_port_lock, flags );
dbg( "digi_write_room: port=%d, room=%d", priv->dp_port_num, room );
return( room );
spin_unlock_irqrestore(&priv->dp_port_lock, flags);
dbg("digi_write_room: port=%d, room=%d", priv->dp_port_num, 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);
if( port->write_urb->status == -EINPROGRESS
|| priv->dp_write_urb_in_use ) {
dbg( "digi_chars_in_buffer: port=%d, chars=%d", priv->dp_port_num, port->bulk_out_size - 2 );
/* return( port->bulk_out_size - 2 ); */
return( 256 );
if (port->write_urb->status == -EINPROGRESS
|| priv->dp_write_urb_in_use) {
dbg("digi_chars_in_buffer: port=%d, chars=%d",
priv->dp_port_num, port->bulk_out_size - 2);
/* return(port->bulk_out_size - 2); */
return 256;
} else {
dbg( "digi_chars_in_buffer: port=%d, chars=%d", priv->dp_port_num, priv->dp_out_buf_len );
return( priv->dp_out_buf_len );
dbg("digi_chars_in_buffer: port=%d, chars=%d",
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;
unsigned char buf[32];
struct digi_port *priv = usb_get_serial_port_data(port);
struct ktermios not_termios;
unsigned long flags = 0;
dbg( "digi_open: TOP: port=%d, open_count=%d", priv->dp_port_num, port->open_count );
dbg("digi_open: TOP: port=%d, open_count=%d",
priv->dp_port_num, port->open_count);
/* be sure the device is started up */
if( digi_startup_device( port->serial ) != 0 )
return( -ENXIO );
if (digi_startup_device(port->serial) != 0)
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 */
if( priv->dp_in_close && (filp->f_flags&(O_NDELAY|O_NONBLOCK)) == 0 ) {
spin_unlock_irqrestore( &priv->dp_port_lock, flags );
return( -EAGAIN );
if (priv->dp_in_close && (filp->f_flags&(O_NDELAY|O_NONBLOCK)) == 0) {
spin_unlock_irqrestore(&priv->dp_port_lock, flags);
return -EAGAIN;
}
/* wait for a close in progress to finish */
while( priv->dp_in_close ) {
while(priv->dp_in_close) {
cond_wait_interruptible_timeout_irqrestore(
&priv->dp_close_wait, DIGI_RETRY_TIMEOUT,
&priv->dp_port_lock, flags );
if( signal_pending(current) ) {
return( -EINTR );
}
spin_lock_irqsave( &priv->dp_port_lock, flags );
&priv->dp_port_lock, flags);
if (signal_pending(current))
return -EINTR;
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 */
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
buf[6] = DIGI_FLUSH_TX | DIGI_FLUSH_RX;
buf[7] = 0;
if( (ret=digi_write_oob_command( port, buf, 8, 1 )) != 0 )
dbg( "digi_open: write oob failed, ret=%d", ret );
if ((ret = digi_write_oob_command(port, buf, 8, 1)) != 0)
dbg("digi_open: write oob failed, ret=%d", ret);
/* set termios settings */
not_termios.c_cflag = ~port->tty->termios->c_cflag;
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 */
digi_set_modem_signals( port, TIOCM_DTR|TIOCM_RTS, 1 );
return( 0 );
digi_set_modem_signals(port, TIOCM_DTR|TIOCM_RTS, 1);
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);
int ret;
......@@ -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);
unsigned long flags = 0;
dbg( "digi_close: TOP: port=%d, open_count=%d", priv->dp_port_num, port->open_count );
dbg("digi_close: TOP: port=%d, open_count=%d",
priv->dp_port_num, port->open_count);
/* if disconnected, just clear flags */
if (!usb_get_intfdata(port->serial->interface))
goto exit;
/* 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;
spin_unlock_irqrestore( &priv->dp_port_lock, flags );
spin_unlock_irqrestore(&priv->dp_port_lock, flags);
/* tell line discipline to process only XON/XOFF */
tty->closing = 1;
/* wait for output to drain */
if( (filp->f_flags&(O_NDELAY|O_NONBLOCK)) == 0 ) {
tty_wait_until_sent( tty, DIGI_CLOSE_TIMEOUT );
}
if ((filp->f_flags&(O_NDELAY|O_NONBLOCK)) == 0)
tty_wait_until_sent(tty, DIGI_CLOSE_TIMEOUT);
/* flush driver and line discipline buffers */
if( tty->driver->flush_buffer )
tty->driver->flush_buffer( tty );
if (tty->driver->flush_buffer)
tty->driver->flush_buffer(tty);
tty_ldisc_flush(tty);
if (port->serial->dev) {
/* wait for transmit idle */
if( (filp->f_flags&(O_NDELAY|O_NONBLOCK)) == 0 ) {
digi_transmit_idle( port, DIGI_CLOSE_TIMEOUT );
if ((filp->f_flags&(O_NDELAY|O_NONBLOCK)) == 0) {
digi_transmit_idle(port, DIGI_CLOSE_TIMEOUT);
}
/* drop DTR and RTS */
digi_set_modem_signals( port, 0, 0 );
digi_set_modem_signals(port, 0, 0);
/* disable 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
buf[18] = DIGI_FLUSH_TX | DIGI_FLUSH_RX;
buf[19] = 0;
if( (ret=digi_write_oob_command( port, buf, 20, 0 )) != 0 )
dbg( "digi_close: write oob failed, ret=%d", ret );
if ((ret = digi_write_oob_command(port, buf, 20, 0)) != 0)
dbg("digi_close: write oob failed, ret=%d", ret);
/* wait for final commands on oob port to complete */
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
/* shutdown any outstanding bulk writes */
usb_kill_urb(port->write_urb);
}
tty->closing = 0;
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_in_close = 0;
wake_up_interruptible( &priv->dp_close_wait );
spin_unlock_irqrestore( &priv->dp_port_lock, flags );
dbg( "digi_close: done" );
wake_up_interruptible(&priv->dp_close_wait);
spin_unlock_irqrestore(&priv->dp_port_lock, flags);
dbg("digi_close: done");
}
......@@ -1608,155 +1496,136 @@ dbg( "digi_close: done" );
* 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;
struct digi_serial *serial_priv = usb_get_serial_data(serial);
struct usb_serial_port *port;
/* be sure this happens exactly once */
spin_lock( &serial_priv->ds_serial_lock );
if( serial_priv->ds_device_started ) {
spin_unlock( &serial_priv->ds_serial_lock );
return( 0 );
spin_lock(&serial_priv->ds_serial_lock);
if (serial_priv->ds_device_started) {
spin_unlock(&serial_priv->ds_serial_lock);
return 0;
}
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 */
/* 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->write_urb->dev = port->serial->dev;
if( (ret=usb_submit_urb(port->read_urb, GFP_KERNEL)) != 0 ) {
err("%s: usb_submit_urb failed, ret=%d, port=%d", __FUNCTION__,
ret, i );
if ((ret = usb_submit_urb(port->read_urb, GFP_KERNEL)) != 0) {
err("%s: usb_submit_urb failed, ret=%d, port=%d",
__FUNCTION__, ret, i);
break;
}
}
return( ret );
return ret;
}
static int digi_startup( struct usb_serial *serial )
static int digi_startup(struct usb_serial *serial)
{
int i;
struct digi_port *priv;
struct digi_serial *serial_priv;
dbg( "digi_startup: TOP" );
dbg("digi_startup: TOP");
/* allocate the private data structures for all ports */
/* 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 */
priv = kmalloc( sizeof(struct digi_port),
GFP_KERNEL );
if( priv == (struct digi_port *)0 ) {
while( --i >= 0 )
kfree( usb_get_serial_port_data(serial->port[i]) );
return( 1 ); /* error */
priv = kmalloc(sizeof(struct digi_port), GFP_KERNEL);
if (priv == NULL) {
while (--i >= 0)
kfree(usb_get_serial_port_data(serial->port[i]));
return 1; /* error */
}
/* 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_out_buf_len = 0;
priv->dp_write_urb_in_use = 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;
init_waitqueue_head( &priv->dp_transmit_idle_wait );
init_waitqueue_head(&priv->dp_transmit_idle_wait);
priv->dp_throttled = 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;
init_waitqueue_head( &priv->dp_close_wait );
init_waitqueue_head(&priv->dp_close_wait);
INIT_WORK(&priv->dp_wakeup_work, digi_wakeup_write_lock);
priv->dp_port = serial->port[i];
/* 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);
}
/* allocate serial private structure */
serial_priv = kmalloc( sizeof(struct digi_serial),
GFP_KERNEL );
if( serial_priv == (struct digi_serial *)0 ) {
for( i=0; i<serial->type->num_ports+1; i++ )
kfree( usb_get_serial_port_data(serial->port[i]) );
return( 1 ); /* error */
serial_priv = kmalloc(sizeof(struct digi_serial), GFP_KERNEL);
if (serial_priv == NULL) {
for (i = 0; i < serial->type->num_ports + 1; i++)
kfree(usb_get_serial_port_data(serial->port[i]));
return 1; /* error */
}
/* 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 = serial->port[serial_priv->ds_oob_port_num];
serial_priv->ds_device_started = 0;
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;
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 */
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]->write_urb);
}
/* free the private data structures for all ports */
/* number of regular ports + 1 for the out-of-band port */
for( i=0; i<serial->type->num_ports+1; i++ )
kfree( usb_get_serial_port_data(serial->port[i]) );
kfree( usb_get_serial_data(serial) );
for(i = 0; i < serial->type->num_ports + 1; i++)
kfree(usb_get_serial_port_data(serial->port[i]));
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 digi_port *priv;
struct digi_serial *serial_priv;
int ret;
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 */
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",
__FUNCTION__, status);
return;
}
if( port->serial == NULL
|| (serial_priv=usb_get_serial_data(port->serial)) == NULL ) {
if (port->serial == NULL ||
(serial_priv=usb_get_serial_data(port->serial)) == NULL) {
err("%s: serial is bad or serial->private is NULL, status=%d",
__FUNCTION__, status);
__FUNCTION__, status);
return;
}
......@@ -1768,24 +1637,23 @@ dbg( "digi_read_bulk_callback: TOP" );
}
/* handle oob or inb callback, do not resubmit if error */
if( priv->dp_port_num == serial_priv->ds_oob_port_num ) {
if( digi_read_oob_callback( urb ) != 0 )
if (priv->dp_port_num == serial_priv->ds_oob_port_num) {
if (digi_read_oob_callback(urb) != 0)
return;
} else {
if( digi_read_inb_callback( urb ) != 0 )
if (digi_read_inb_callback(urb) != 0)
return;
}
/* continue read */
urb->dev = port->serial->dev;
if( (ret=usb_submit_urb(urb, GFP_ATOMIC)) != 0 ) {
err("%s: failed resubmitting urb, ret=%d, port=%d", __FUNCTION__,
ret, priv->dp_port_num );
if ((ret = usb_submit_urb(urb, GFP_ATOMIC)) != 0) {
err("%s: failed resubmitting urb, ret=%d, port=%d",
__FUNCTION__, ret, priv->dp_port_num);
}
}
/*
* Digi Read INB Callback
*
......@@ -1796,7 +1664,7 @@ dbg( "digi_read_bulk_callback: TOP" );
* 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;
......@@ -1812,72 +1680,67 @@ static int digi_read_inb_callback( struct urb *urb )
/* do not process callbacks on closed ports */
/* but do continue the read chain */
if( port->open_count == 0 )
return( 0 );
if (port->open_count == 0)
return 0;
/* short/multiple packet check */
if( urb->actual_length != len + 2 ) {
err("%s: INCOMPLETE OR MULTIPLE PACKET, urb status=%d, "
if (urb->actual_length != len + 2) {
err("%s: INCOMPLETE OR MULTIPLE PACKET, urb->status=%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);
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 */
/* indicate the read chain needs to be restarted on unthrottle */
throttled = priv->dp_throttled;
if( throttled )
if (throttled)
priv->dp_throttle_restart = 1;
/* receive data */
if( opcode == DIGI_CMD_RECEIVE_DATA ) {
if (opcode == DIGI_CMD_RECEIVE_DATA) {
/* get flag from port_status */
flag = 0;
/* overrun is special, not associated with a char */
if (port_status & DIGI_OVERRUN_ERROR) {
tty_insert_flip_char( tty, 0, TTY_OVERRUN );
}
if (port_status & DIGI_OVERRUN_ERROR)
tty_insert_flip_char(tty, 0, TTY_OVERRUN);
/* break takes precedence over parity, */
/* which takes precedence over framing errors */
if (port_status & DIGI_BREAK_ERROR) {
if (port_status & DIGI_BREAK_ERROR)
flag = TTY_BREAK;
} else if (port_status & DIGI_PARITY_ERROR) {
else if (port_status & DIGI_PARITY_ERROR)
flag = TTY_PARITY;
} else if (port_status & DIGI_FRAMING_ERROR) {
else if (port_status & DIGI_FRAMING_ERROR)
flag = TTY_FRAME;
}
/* data length is len-1 (one byte of len is port_status) */
--len;
len = tty_buffer_request_room(tty, len);
if( len > 0 ) {
if (len > 0) {
/* Hot path */
if(flag == TTY_NORMAL)
if (flag == TTY_NORMAL)
tty_insert_flip_string(tty, data, len);
else {
for(i = 0; i < len; i++)
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__ );
} else if( opcode != DIGI_CMD_RECEIVE_DATA ) {
dbg("%s: unknown opcode: %d", __FUNCTION__, opcode );
}
if (opcode == DIGI_CMD_RECEIVE_DISABLE)
dbg("%s: got RECEIVE_DISABLE", __FUNCTION__);
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 )
* -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;
......@@ -1900,87 +1763,75 @@ static int digi_read_oob_callback( struct urb *urb )
int opcode, line, status, val;
int i;
dbg( "digi_read_oob_callback: port=%d, len=%d", priv->dp_port_num,
urb->actual_length );
dbg("digi_read_oob_callback: port=%d, len=%d",
priv->dp_port_num, urb->actual_length);
/* 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++];
line = ((unsigned char *)urb->transfer_buffer)[i++];
status = ((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",
opcode, line, status, val );
dbg("digi_read_oob_callback: opcode=%d, line=%d, status=%d, val=%d",
opcode, line, status, val);
if( status != 0 || line >= serial->type->num_ports )
if (status != 0 || line >= serial->type->num_ports)
continue;
port = serial->port[line];
if ((priv=usb_get_serial_port_data(port)) == NULL )
if ((priv=usb_get_serial_port_data(port)) == NULL)
return -1;
if( opcode == DIGI_CMD_READ_INPUT_SIGNALS ) {
spin_lock( &priv->dp_port_lock );
if (opcode == DIGI_CMD_READ_INPUT_SIGNALS) {
spin_lock(&priv->dp_port_lock);
/* 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;
/* port must be open to use tty struct */
if( port->open_count
&& port->tty->termios->c_cflag & CRTSCTS ) {
if (port->open_count
&& port->tty->termios->c_cflag & CRTSCTS) {
port->tty->hw_stopped = 0;
digi_wakeup_write( port );
digi_wakeup_write(port);
}
} else {
priv->dp_modem_signals &= ~TIOCM_CTS;
/* port must be open to use tty struct */
if( port->open_count
&& port->tty->termios->c_cflag & CRTSCTS ) {
if (port->open_count
&& port->tty->termios->c_cflag & CRTSCTS) {
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;
else
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;
else
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;
else
priv->dp_modem_signals &= ~TIOCM_CD;
wake_up_interruptible( &priv->dp_modem_change_wait );
spin_unlock( &priv->dp_port_lock );
} else if( opcode == DIGI_CMD_TRANSMIT_IDLE ) {
spin_lock( &priv->dp_port_lock );
wake_up_interruptible(&priv->dp_modem_change_wait);
spin_unlock(&priv->dp_port_lock);
} else if (opcode == DIGI_CMD_TRANSMIT_IDLE) {
spin_lock(&priv->dp_port_lock);
priv->dp_transmit_idle = 1;
wake_up_interruptible( &priv->dp_transmit_idle_wait );
spin_unlock( &priv->dp_port_lock );
} else if( opcode == DIGI_CMD_IFLUSH_FIFO ) {
wake_up_interruptible( &priv->dp_flush_wait );
wake_up_interruptible(&priv->dp_transmit_idle_wait);
spin_unlock(&priv->dp_port_lock);
} else if (opcode == DIGI_CMD_IFLUSH_FIFO) {
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;
retval = usb_serial_register(&digi_acceleport_2_device);
......@@ -2002,12 +1853,11 @@ static int __init digi_init (void)
return retval;
}
static void __exit digi_exit (void)
{
usb_deregister (&digi_driver);
usb_serial_deregister (&digi_acceleport_2_device);
usb_serial_deregister (&digi_acceleport_4_device);
usb_deregister(&digi_driver);
usb_serial_deregister(&digi_acceleport_2_device);
usb_serial_deregister(&digi_acceleport_4_device);
}
......@@ -2015,8 +1865,8 @@ module_init(digi_init);
module_exit(digi_exit);
MODULE_AUTHOR( DRIVER_AUTHOR );
MODULE_DESCRIPTION( DRIVER_DESC );
MODULE_AUTHOR(DRIVER_AUTHOR);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_LICENSE("GPL");
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
int status;
unsigned char number = edge_port->port->number - edge_port->port->serial->minor;
if ((!edge_serial->is_epic) ||
((edge_serial->is_epic) &&
(!edge_serial->epic_descriptor.Supports.IOSPSetBaudRate))) {
if (edge_serial->is_epic &&
!edge_serial->epic_descriptor.Supports.IOSPSetBaudRate) {
dbg("SendCmdWriteBaudRate - NOT Setting baud rate for port = %d, baud = %d",
edge_port->port->number, baudRate);
return 0;
......@@ -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);
if ((!edge_serial->is_epic) ||
((edge_serial->is_epic) &&
(!edge_serial->epic_descriptor.Supports.IOSPWriteMCR) &&
(regNum == MCR))) {
if (edge_serial->is_epic &&
!edge_serial->epic_descriptor.Supports.IOSPWriteMCR &&
regNum == MCR) {
dbg("SendCmdWriteUartReg - Not writing to MCR Register");
return 0;
}
if ((!edge_serial->is_epic) ||
((edge_serial->is_epic) &&
(!edge_serial->epic_descriptor.Supports.IOSPWriteLCR) &&
(regNum == LCR))) {
if (edge_serial->is_epic &&
!edge_serial->epic_descriptor.Supports.IOSPWriteLCR &&
regNum == LCR) {
dbg ("SendCmdWriteUartReg - Not writing to LCR Register");
return 0;
}
......
......@@ -184,21 +184,21 @@ struct mct_u232_private {
* we do not know how to support. We ignore them for the moment.
* 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
|| le16_to_cpu(serial->dev->descriptor.idProduct) == MCT_U232_BELKIN_F5U109_PID) {
switch (value) {
case B300: return 0x01;
case B600: return 0x02; /* this one not tested */
case B1200: return 0x03;
case B2400: return 0x04;
case B4800: return 0x06;
case B9600: return 0x08;
case B19200: return 0x09;
case B38400: return 0x0a;
case B57600: return 0x0b;
case B115200: return 0x0c;
case 300: return 0x01;
case 600: return 0x02; /* this one not tested */
case 1200: return 0x03;
case 2400: return 0x04;
case 4800: return 0x06;
case 9600: return 0x08;
case 19200: return 0x09;
case 38400: return 0x0a;
case 57600: return 0x0b;
case 115200: return 0x0c;
default:
err("MCT USB-RS232: unsupported baudrate request 0x%x,"
" using default of B9600", value);
......@@ -206,27 +206,27 @@ static int mct_u232_calculate_baud_rate(struct usb_serial *serial, int value)
}
} else {
switch (value) {
case B300: value = 300; break;
case B600: value = 600; break;
case B1200: value = 1200; break;
case B2400: value = 2400; break;
case B4800: value = 4800; break;
case B9600: value = 9600; break;
case B19200: value = 19200; break;
case B38400: value = 38400; break;
case B57600: value = 57600; break;
case B115200: value = 115200; break;
default:
err("MCT USB-RS232: unsupported baudrate request 0x%x,"
" using default of B9600", value);
value = 9600;
case 300: break;
case 600: break;
case 1200: break;
case 2400: break;
case 4800: break;
case 9600: break;
case 19200: break;
case 38400: break;
case 57600: break;
case 115200: break;
default:
err("MCT USB-RS232: unsupported baudrate request 0x%x,"
" using default of B9600", value);
value = 9600;
}
return 115200/value;
}
}
static int mct_u232_set_baud_rate(struct usb_serial *serial, struct usb_serial_port *port,
int value)
speed_t value)
{
__le32 divisor;
int rc;
......@@ -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_baud_rate(serial, port, cflag & CBAUD);
mct_u232_set_baud_rate(serial, port, tty_get_baud_rate(port->tty));
if ((cflag & CBAUD) == B0 ) {
dbg("%s: baud is B0", __FUNCTION__);
......
......@@ -79,7 +79,7 @@
* 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.
*/
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)
......
......@@ -45,7 +45,7 @@ enum devicetype {
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;
dev_dbg(&udev->dev, "%s", "SET POWER STATE");
......@@ -60,7 +60,7 @@ int sierra_set_power_state(struct usb_device *udev, __u16 swiState)
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;
dev_dbg(&udev->dev, "%s", "DEVICE MODE SWITCH");
......@@ -75,7 +75,8 @@ int sierra_set_ms_mode(struct usb_device *udev, __u16 eSocMode)
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;
struct usb_device *udev;
......
......@@ -60,19 +60,19 @@ static struct usb_driver usb_serial_driver = {
static int debug;
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);
struct usb_serial *usb_serial_get_by_index(unsigned index)
{
struct usb_serial *serial;
spin_lock(&table_lock);
mutex_lock(&table_lock);
serial = serial_table[index];
if (serial)
kref_get(&serial->kref);
spin_unlock(&table_lock);
mutex_unlock(&table_lock);
return serial;
}
......@@ -84,7 +84,7 @@ static struct usb_serial *get_free_serial (struct usb_serial *serial, int num_po
dbg("%s %d", __FUNCTION__, num_ports);
*minor = 0;
spin_lock(&table_lock);
mutex_lock(&table_lock);
for (i = 0; i < SERIAL_TTY_MINORS; ++i) {
if (serial_table[i])
continue;
......@@ -106,10 +106,10 @@ static struct usb_serial *get_free_serial (struct usb_serial *serial, int num_po
serial_table[i] = serial;
serial->port[j++]->number = i;
}
spin_unlock(&table_lock);
mutex_unlock(&table_lock);
return serial;
}
spin_unlock(&table_lock);
mutex_unlock(&table_lock);
return NULL;
}
......@@ -172,9 +172,9 @@ static void destroy_serial(struct kref *kref)
void usb_serial_put(struct usb_serial *serial)
{
spin_lock(&table_lock);
mutex_lock(&table_lock);
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)
struct usb_serial_port *port;
int i, r = 0;
if (serial) {
for (i = 0; i < serial->num_ports; ++i) {
port = serial->port[i];
if (port)
kill_traffic(port);
}
if (!serial) /* device has been disconnected */
return 0;
for (i = 0; i < serial->num_ports; ++i) {
port = serial->port[i];
if (port)
kill_traffic(port);
}
if (serial->type->suspend)
serial->type->suspend(serial, message);
r = serial->type->suspend(serial, message);
return r;
}
......@@ -1128,7 +1129,6 @@ static int __init usb_serial_init(void)
return -ENOMEM;
/* Initialize our global data */
spin_lock_init(&table_lock);
for (i = 0; i < SERIAL_TTY_MINORS; ++i) {
serial_table[i] = NULL;
}
......
......@@ -320,6 +320,13 @@ UNUSUAL_DEV( 0x04b0, 0x0401, 0x0200, 0x0200,
US_SC_DEVICE, US_PR_DEVICE, NULL,
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> */
UNUSUAL_DEV( 0x04b0, 0x0405, 0x0100, 0x0100,
"NIKON",
......@@ -1357,6 +1364,20 @@ UNUSUAL_DEV( 0x0f19, 0x0105, 0x0100, 0x0100,
US_SC_DEVICE, US_PR_DEVICE, NULL,
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> */
UNUSUAL_DEV( 0x0fce, 0xd008, 0x0000, 0x0000,
"Sony Ericsson",
......
......@@ -94,6 +94,7 @@ enum usb_interface_condition {
* endpoint configurations. They will be in no particular order.
* @num_altsetting: number of altsettings defined.
* @cur_altsetting: the current altsetting.
* @intf_assoc: interface association descriptor
* @driver: the USB driver that is bound to this interface.
* @minor: the minor number assigned to this interface, if this
* interface is bound to a driver that uses the USB major number.
......@@ -213,6 +214,7 @@ struct usb_interface_cache {
* @desc: the device's configuration descriptor.
* @string: pointer to the cached version of the iConfiguration string, if
* 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 in the configuration. The number of interfaces is stored
* 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