tty: Bring the usb tty port structure into more use
authorAlan Cox <alan@lxorguk.ukuu.org.uk>
Thu, 11 Jun 2009 11:26:29 +0000 (12:26 +0100)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 11 Jun 2009 15:50:56 +0000 (08:50 -0700)
This allows us to clean stuff up, but is probably also going to cause
some app breakage with buggy apps as we now implement proper POSIX behaviour
for USB ports matching all the other ports. This does also mean other apps
that break on USB will now work properly.

Signed-off-by: Alan Cox <alan@lxorguk.ukuu.org.uk>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
39 files changed:
drivers/usb/serial/belkin_sa.c
drivers/usb/serial/ch341.c
drivers/usb/serial/console.c
drivers/usb/serial/cp210x.c
drivers/usb/serial/cyberjack.c
drivers/usb/serial/cypress_m8.c
drivers/usb/serial/digi_acceleport.c
drivers/usb/serial/empeg.c
drivers/usb/serial/ftdi_sio.c
drivers/usb/serial/garmin_gps.c
drivers/usb/serial/generic.c
drivers/usb/serial/io_edgeport.c
drivers/usb/serial/io_ti.c
drivers/usb/serial/ipaq.c
drivers/usb/serial/ipw.c
drivers/usb/serial/ir-usb.c
drivers/usb/serial/iuu_phoenix.c
drivers/usb/serial/keyspan.c
drivers/usb/serial/keyspan.h
drivers/usb/serial/keyspan_pda.c
drivers/usb/serial/kl5kusb105.c
drivers/usb/serial/kobil_sct.c
drivers/usb/serial/mct_u232.c
drivers/usb/serial/mos7720.c
drivers/usb/serial/mos7840.c
drivers/usb/serial/navman.c
drivers/usb/serial/omninet.c
drivers/usb/serial/opticon.c
drivers/usb/serial/option.c
drivers/usb/serial/oti6858.c
drivers/usb/serial/pl2303.c
drivers/usb/serial/sierra.c
drivers/usb/serial/spcp8x5.c
drivers/usb/serial/symbolserial.c
drivers/usb/serial/ti_usb_3410_5052.c
drivers/usb/serial/usb-serial.c
drivers/usb/serial/visor.c
drivers/usb/serial/whiteheat.c
include/linux/usb/serial.h

index b7eacad4d48cb4ae34097c8d2ebbe7cb0ad0a363..2bfd6dd85b5ad23624cef600a2e8e5f76de5fa18 100644 (file)
@@ -93,8 +93,7 @@ static int  belkin_sa_startup(struct usb_serial *serial);
 static void belkin_sa_shutdown(struct usb_serial *serial);
 static int  belkin_sa_open(struct tty_struct *tty,
                        struct usb_serial_port *port, struct file *filp);
-static void belkin_sa_close(struct tty_struct *tty,
-                       struct usb_serial_port *port, struct file *filp);
+static void belkin_sa_close(struct usb_serial_port *port);
 static void belkin_sa_read_int_callback(struct urb *urb);
 static void belkin_sa_set_termios(struct tty_struct *tty,
                        struct usb_serial_port *port, struct ktermios * old);
@@ -244,8 +243,7 @@ exit:
 } /* belkin_sa_open */
 
 
-static void belkin_sa_close(struct tty_struct *tty,
-                       struct usb_serial_port *port, struct file *filp)
+static void belkin_sa_close(struct usb_serial_port *port)
 {
        dbg("%s port %d", __func__, port->number);
 
index ab4cc277aa659be685a154c6a5024cf02f14eba9..2830766f5b391cc7d177c82e49a058ba28b1be73 100644 (file)
@@ -262,13 +262,33 @@ error:    kfree(priv);
        return r;
 }
 
-static void ch341_close(struct tty_struct *tty, struct usb_serial_port *port,
-                               struct file *filp)
+static int ch341_carrier_raised(struct usb_serial_port *port)
+{
+       struct ch341_private *priv = usb_get_serial_port_data(port);
+       if (priv->line_status & CH341_BIT_DCD)
+               return 1;
+       return 0;
+}
+
+static void ch341_dtr_rts(struct usb_serial_port *port, int on)
 {
        struct ch341_private *priv = usb_get_serial_port_data(port);
        unsigned long flags;
-       unsigned int c_cflag;
 
+       dbg("%s - port %d", __func__, port->number);
+       /* drop DTR and RTS */
+       spin_lock_irqsave(&priv->lock, flags);
+       if (on)
+               priv->line_control |= CH341_BIT_RTS | CH341_BIT_DTR;
+       else
+               priv->line_control &= ~(CH341_BIT_RTS | CH341_BIT_DTR);
+       spin_unlock_irqrestore(&priv->lock, flags);
+       ch341_set_handshake(port->serial->dev, priv->line_control);
+       wake_up_interruptible(&priv->delta_msr_wait);
+}
+
+static void ch341_close(struct usb_serial_port *port)
+{
        dbg("%s - port %d", __func__, port->number);
 
        /* shutdown our urbs */
@@ -276,18 +296,6 @@ static void ch341_close(struct tty_struct *tty, struct usb_serial_port *port,
        usb_kill_urb(port->write_urb);
        usb_kill_urb(port->read_urb);
        usb_kill_urb(port->interrupt_in_urb);
-
-       if (tty) {
-               c_cflag = tty->termios->c_cflag;
-               if (c_cflag & HUPCL) {
-                       /* drop DTR and RTS */
-                       spin_lock_irqsave(&priv->lock, flags);
-                       priv->line_control = 0;
-                       spin_unlock_irqrestore(&priv->lock, flags);
-                       ch341_set_handshake(port->serial->dev, 0);
-               }
-       }
-       wake_up_interruptible(&priv->delta_msr_wait);
 }
 
 
@@ -302,7 +310,6 @@ static int ch341_open(struct tty_struct *tty, struct usb_serial_port *port,
        dbg("ch341_open()");
 
        priv->baud_rate = DEFAULT_BAUD_RATE;
-       priv->line_control = CH341_BIT_RTS | CH341_BIT_DTR;
 
        r = ch341_configure(serial->dev, priv);
        if (r)
@@ -322,7 +329,7 @@ static int ch341_open(struct tty_struct *tty, struct usb_serial_port *port,
        if (r) {
                dev_err(&port->dev, "%s - failed submitting interrupt urb,"
                        " error %d\n", __func__, r);
-               ch341_close(tty, port, NULL);
+               ch341_close(port);
                return -EPROTO;
        }
 
@@ -343,9 +350,6 @@ static void ch341_set_termios(struct tty_struct *tty,
 
        dbg("ch341_set_termios()");
 
-       if (!tty || !tty->termios)
-               return;
-
        baud_rate = tty_get_baud_rate(tty);
 
        priv->baud_rate = baud_rate;
@@ -568,6 +572,8 @@ static struct usb_serial_driver ch341_device = {
        .usb_driver        = &ch341_driver,
        .num_ports         = 1,
        .open              = ch341_open,
+       .dtr_rts           = ch341_dtr_rts,
+       .carrier_raised    = ch341_carrier_raised,
        .close             = ch341_close,
        .ioctl             = ch341_ioctl,
        .set_termios       = ch341_set_termios,
index 19e24045b137a2964b450afbf94cc930de3cd427..247b61bfb7f45f4d179abd6ef36f9611eea046da 100644 (file)
@@ -169,7 +169,9 @@ static int usb_console_setup(struct console *co, char *options)
                        kfree(tty);
                }
        }
-
+       /* So we know not to kill the hardware on a hangup on this
+          port. We have also bumped the use count by one so it won't go
+          idle */
        port->console = 1;
        retval = 0;
 
@@ -182,7 +184,7 @@ free_tty:
        kfree(tty);
 reset_open_count:
        port->port.count = 0;
-goto out;
+       goto out;
 }
 
 static void usb_console_write(struct console *co,
index e8d5133ce9c84f911d210a374f5af40821c7f6b4..d9f586dc6eccdefd64688122bda9fe268fab9419 100644 (file)
@@ -36,8 +36,7 @@
 static int cp2101_open(struct tty_struct *, struct usb_serial_port *,
                                                        struct file *);
 static void cp2101_cleanup(struct usb_serial_port *);
-static void cp2101_close(struct tty_struct *, struct usb_serial_port *,
-                                                       struct file*);
+static void cp2101_close(struct usb_serial_port *);
 static void cp2101_get_termios(struct tty_struct *,
        struct usb_serial_port *port);
 static void cp2101_get_termios_port(struct usb_serial_port *port,
@@ -398,8 +397,7 @@ static void cp2101_cleanup(struct usb_serial_port *port)
        }
 }
 
-static void cp2101_close(struct tty_struct *tty, struct usb_serial_port *port,
-                                       struct file *filp)
+static void cp2101_close(struct usb_serial_port *port)
 {
        dbg("%s - port %d", __func__, port->number);
 
index dd501bb63ed6173b2b1f31a35f93d3a7d202db0a..933ba913e66c5fc21950a3ccc2e5b8229f8c9d63 100644 (file)
@@ -61,8 +61,7 @@ static int cyberjack_startup(struct usb_serial *serial);
 static void cyberjack_shutdown(struct usb_serial *serial);
 static int  cyberjack_open(struct tty_struct *tty,
                        struct usb_serial_port *port, struct file *filp);
-static void cyberjack_close(struct tty_struct *tty,
-                       struct usb_serial_port *port, struct file *filp);
+static void cyberjack_close(struct usb_serial_port *port);
 static int cyberjack_write(struct tty_struct *tty,
        struct usb_serial_port *port, const unsigned char *buf, int count);
 static int cyberjack_write_room(struct tty_struct *tty);
@@ -185,8 +184,7 @@ static int  cyberjack_open(struct tty_struct *tty,
        return result;
 }
 
-static void cyberjack_close(struct tty_struct *tty,
-                       struct usb_serial_port *port, struct file *filp)
+static void cyberjack_close(struct usb_serial_port *port)
 {
        dbg("%s - port %d", __func__, port->number);
 
index e568710b263fa9dc6a6e258c6898c70254180d59..669f93848539560182b589131cc18788487477dc 100644 (file)
@@ -174,8 +174,8 @@ static int  cypress_ca42v2_startup(struct usb_serial *serial);
 static void cypress_shutdown(struct usb_serial *serial);
 static int  cypress_open(struct tty_struct *tty,
                        struct usb_serial_port *port, struct file *filp);
-static void cypress_close(struct tty_struct *tty,
-                       struct usb_serial_port *port, struct file *filp);
+static void cypress_close(struct usb_serial_port *port);
+static void cypress_dtr_rts(struct usb_serial_port *port, int on);
 static int  cypress_write(struct tty_struct *tty, struct usb_serial_port *port,
                        const unsigned char *buf, int count);
 static void cypress_send(struct usb_serial_port *port);
@@ -218,6 +218,7 @@ static struct usb_serial_driver cypress_earthmate_device = {
        .shutdown =                     cypress_shutdown,
        .open =                         cypress_open,
        .close =                        cypress_close,
+       .dtr_rts =                      cypress_dtr_rts,
        .write =                        cypress_write,
        .write_room =                   cypress_write_room,
        .ioctl =                        cypress_ioctl,
@@ -244,6 +245,7 @@ static struct usb_serial_driver cypress_hidcom_device = {
        .shutdown =                     cypress_shutdown,
        .open =                         cypress_open,
        .close =                        cypress_close,
+       .dtr_rts =                      cypress_dtr_rts,
        .write =                        cypress_write,
        .write_room =                   cypress_write_room,
        .ioctl =                        cypress_ioctl,
@@ -270,6 +272,7 @@ static struct usb_serial_driver cypress_ca42v2_device = {
        .shutdown =                     cypress_shutdown,
        .open =                         cypress_open,
        .close =                        cypress_close,
+       .dtr_rts =                      cypress_dtr_rts,
        .write =                        cypress_write,
        .write_room =                   cypress_write_room,
        .ioctl =                        cypress_ioctl,
@@ -656,11 +659,7 @@ static int cypress_open(struct tty_struct *tty,
        priv->rx_flags = 0;
        spin_unlock_irqrestore(&priv->lock, flags);
 
-       /* raise both lines and set termios */
-       spin_lock_irqsave(&priv->lock, flags);
-       priv->line_control = CONTROL_DTR | CONTROL_RTS;
-       priv->cmd_ctrl = 1;
-       spin_unlock_irqrestore(&priv->lock, flags);
+       /* Set termios */
        result = cypress_write(tty, port, NULL, 0);
 
        if (result) {
@@ -694,76 +693,42 @@ static int cypress_open(struct tty_struct *tty,
                                                        __func__, result);
                cypress_set_dead(port);
        }
-
+       port->port.drain_delay = 256;
        return result;
 } /* cypress_open */
 
+static void cypress_dtr_rts(struct usb_serial_port *port, int on)
+{
+       struct cypress_private *priv = usb_get_serial_port_data(port);
+       /* drop dtr and rts */
+       priv = usb_get_serial_port_data(port);
+       spin_lock_irq(&priv->lock);
+       if (on == 0)
+               priv->line_control = 0;
+       else 
+               priv->line_control = CONTROL_DTR | CONTROL_RTS;
+       priv->cmd_ctrl = 1;
+       spin_unlock_irq(&priv->lock);
+       cypress_write(NULL, port, NULL, 0);
+}
 
-static void cypress_close(struct tty_struct *tty,
-                       struct usb_serial_port *port, struct file *filp)
+static void cypress_close(struct usb_serial_port *port)
 {
        struct cypress_private *priv = usb_get_serial_port_data(port);
-       unsigned int c_cflag;
-       int bps;
-       long timeout;
-       wait_queue_t wait;
 
        dbg("%s - port %d", __func__, port->number);
 
-       /* wait for data to drain from buffer */
-       spin_lock_irq(&priv->lock);
-       timeout = CYPRESS_CLOSING_WAIT;
-       init_waitqueue_entry(&wait, current);
-       add_wait_queue(&tty->write_wait, &wait);
-       for (;;) {
-               set_current_state(TASK_INTERRUPTIBLE);
-               if (cypress_buf_data_avail(priv->buf) == 0
-               || timeout == 0 || signal_pending(current)
-               /* without mutex, allowed due to harmless failure mode */
-               || port->serial->disconnected)
-                       break;
-               spin_unlock_irq(&priv->lock);
-               timeout = schedule_timeout(timeout);
-               spin_lock_irq(&priv->lock);
-       }
-       set_current_state(TASK_RUNNING);
-       remove_wait_queue(&tty->write_wait, &wait);
-       /* clear out any remaining data in the buffer */
-       cypress_buf_clear(priv->buf);
-       spin_unlock_irq(&priv->lock);
-
        /* writing is potentially harmful, lock must be taken */
        mutex_lock(&port->serial->disc_mutex);
        if (port->serial->disconnected) {
                mutex_unlock(&port->serial->disc_mutex);
                return;
        }
-       /* wait for characters to drain from device */
-       if (tty) {
-               bps = tty_get_baud_rate(tty);
-               if (bps > 1200)
-                       timeout = max((HZ * 2560) / bps, HZ / 10);
-               else
-                       timeout = 2 * HZ;
-               schedule_timeout_interruptible(timeout);
-       }
-
+       cypress_buf_clear(priv->buf);
        dbg("%s - stopping urbs", __func__);
        usb_kill_urb(port->interrupt_in_urb);
        usb_kill_urb(port->interrupt_out_urb);
 
-       if (tty) {
-               c_cflag = tty->termios->c_cflag;
-               if (c_cflag & HUPCL) {
-                       /* drop dtr and rts */
-                       priv = usb_get_serial_port_data(port);
-                       spin_lock_irq(&priv->lock);
-                       priv->line_control = 0;
-                       priv->cmd_ctrl = 1;
-                       spin_unlock_irq(&priv->lock);
-                       cypress_write(tty, port, NULL, 0);
-               }
-       }
 
        if (stats)
                dev_info(&port->dev, "Statistics: %d Bytes In | %d Bytes Out | %d Commands Issued\n",
index 38ba4ea8b6bfdf1b84b69d9338cd9c3154d60e51..30f5140eff03a3bbeef50e90f28c942223c99e0e 100644 (file)
@@ -422,7 +422,6 @@ struct digi_port {
        int dp_throttled;
        int dp_throttle_restart;
        wait_queue_head_t dp_flush_wait;
-       int dp_in_close;                        /* close in progress */
        wait_queue_head_t dp_close_wait;        /* wait queue for close */
        struct work_struct dp_wakeup_work;
        struct usb_serial_port *dp_port;
@@ -456,8 +455,9 @@ static int digi_write_room(struct tty_struct *tty);
 static int digi_chars_in_buffer(struct tty_struct *tty);
 static int digi_open(struct tty_struct *tty, struct usb_serial_port *port,
        struct file *filp);
-static void digi_close(struct tty_struct *tty, struct usb_serial_port *port,
-       struct file *filp);
+static void digi_close(struct usb_serial_port *port);
+static int digi_carrier_raised(struct usb_serial_port *port);
+static void digi_dtr_rts(struct usb_serial_port *port, int on);
 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);
@@ -510,6 +510,8 @@ static struct usb_serial_driver digi_acceleport_2_device = {
        .num_ports =                    3,
        .open =                         digi_open,
        .close =                        digi_close,
+       .dtr_rts =                      digi_dtr_rts,
+       .carrier_raised =               digi_carrier_raised,
        .write =                        digi_write,
        .write_room =                   digi_write_room,
        .write_bulk_callback =          digi_write_bulk_callback,
@@ -1328,6 +1330,19 @@ static int digi_chars_in_buffer(struct tty_struct *tty)
 
 }
 
+static void digi_dtr_rts(struct usb_serial_port *port, int on)
+{
+       /* Adjust DTR and RTS */
+       digi_set_modem_signals(port, on * (TIOCM_DTR|TIOCM_RTS), 1);
+}
+
+static int digi_carrier_raised(struct usb_serial_port *port)
+{
+       struct digi_port *priv = usb_get_serial_port_data(port);
+       if (priv->dp_modem_signals & TIOCM_CD)
+               return 1;
+       return 0;
+}
 
 static int digi_open(struct tty_struct *tty, struct usb_serial_port *port,
                                struct file *filp)
@@ -1336,7 +1351,6 @@ static int digi_open(struct tty_struct *tty, struct usb_serial_port *port,
        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->port.count);
@@ -1345,26 +1359,6 @@ static int digi_open(struct tty_struct *tty, struct usb_serial_port *port,
        if (digi_startup_device(port->serial) != 0)
                return -ENXIO;
 
-       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;
-       }
-
-       /* wait for a close in progress to finish */
-       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);
-       }
-
-       spin_unlock_irqrestore(&priv->dp_port_lock, flags);
-
        /* read modem signals automatically whenever they change */
        buf[0] = DIGI_CMD_READ_INPUT_SIGNALS;
        buf[1] = priv->dp_port_num;
@@ -1387,16 +1381,11 @@ static int digi_open(struct tty_struct *tty, struct usb_serial_port *port,
                not_termios.c_iflag = ~tty->termios->c_iflag;
                digi_set_termios(tty, port, &not_termios);
        }
-
-       /* set DTR and RTS */
-       digi_set_modem_signals(port, TIOCM_DTR|TIOCM_RTS, 1);
-
        return 0;
 }
 
 
-static void digi_close(struct tty_struct *tty, struct usb_serial_port *port,
-                               struct file *filp)
+static void digi_close(struct usb_serial_port *port)
 {
        DEFINE_WAIT(wait);
        int ret;
@@ -1411,28 +1400,9 @@ static void digi_close(struct tty_struct *tty, struct usb_serial_port *port,
        if (port->serial->disconnected)
                goto exit;
 
-       /* do cleanup only after final close on this port */
-       spin_lock_irq(&priv->dp_port_lock);
-       priv->dp_in_close = 1;
-       spin_unlock_irq(&priv->dp_port_lock);
-
-       /* 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);
-
-       /* flush driver and line discipline buffers */
-       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);
-               /* drop DTR and RTS */
-               digi_set_modem_signals(port, 0, 0);
+               /* FIXME: Transmit idle belongs in the wait_unti_sent path */
+               digi_transmit_idle(port, DIGI_CLOSE_TIMEOUT);
 
                /* disable input flow control */
                buf[0] = DIGI_CMD_SET_INPUT_FLOW_CONTROL;
@@ -1477,11 +1447,9 @@ static void digi_close(struct tty_struct *tty, struct usb_serial_port *port,
                /* shutdown any outstanding bulk writes */
                usb_kill_urb(port->write_urb);
        }
-       tty->closing = 0;
 exit:
        spin_lock_irq(&priv->dp_port_lock);
        priv->dp_write_urb_in_use = 0;
-       priv->dp_in_close = 0;
        wake_up_interruptible(&priv->dp_close_wait);
        spin_unlock_irq(&priv->dp_port_lock);
        mutex_unlock(&port->serial->disc_mutex);
@@ -1560,7 +1528,6 @@ static int digi_startup(struct usb_serial *serial)
                priv->dp_throttled = 0;
                priv->dp_throttle_restart = 0;
                init_waitqueue_head(&priv->dp_flush_wait);
-               priv->dp_in_close = 0;
                init_waitqueue_head(&priv->dp_close_wait);
                INIT_WORK(&priv->dp_wakeup_work, digi_wakeup_write_lock);
                priv->dp_port = serial->port[i];
index c709ec474a80b8540e91d5ae6e25fde2690f6b09..2b141ccb0cd958ca56d51c476075dc621e0a5a4a 100644 (file)
@@ -81,8 +81,7 @@ static int debug;
 /* function prototypes for an empeg-car player */
 static int  empeg_open(struct tty_struct *tty, struct usb_serial_port *port,
                                                struct file *filp);
-static void empeg_close(struct tty_struct *tty, struct usb_serial_port *port,
-                                               struct file *filp);
+static void empeg_close(struct usb_serial_port *port);
 static int  empeg_write(struct tty_struct *tty, struct usb_serial_port *port,
                                                const unsigned char *buf,
                                                int count);
@@ -181,8 +180,7 @@ static int empeg_open(struct tty_struct *tty, struct usb_serial_port *port,
 }
 
 
-static void empeg_close(struct tty_struct *tty, struct usb_serial_port *port,
-                               struct file *filp)
+static void empeg_close(struct usb_serial_port *port)
 {
        dbg("%s - port %d", __func__, port->number);
 
index d9fcdaedf389d9c670b57847004939c44a25dc32..d9d87111f9a9c25ddbc483016fc0a2dc5456d835 100644 (file)
@@ -719,8 +719,8 @@ static int  ftdi_sio_port_probe(struct usb_serial_port *port);
 static int  ftdi_sio_port_remove(struct usb_serial_port *port);
 static int  ftdi_open(struct tty_struct *tty,
                        struct usb_serial_port *port, struct file *filp);
-static void ftdi_close(struct tty_struct *tty,
-                       struct usb_serial_port *port, struct file *filp);
+static void ftdi_close(struct usb_serial_port *port);
+static void ftdi_dtr_rts(struct usb_serial_port *port, int on);
 static int  ftdi_write(struct tty_struct *tty, struct usb_serial_port *port,
                        const unsigned char *buf, int count);
 static int  ftdi_write_room(struct tty_struct *tty);
@@ -758,6 +758,7 @@ static struct usb_serial_driver ftdi_sio_device = {
        .port_remove =          ftdi_sio_port_remove,
        .open =                 ftdi_open,
        .close =                ftdi_close,
+       .dtr_rts =              ftdi_dtr_rts,
        .throttle =             ftdi_throttle,
        .unthrottle =           ftdi_unthrottle,
        .write =                ftdi_write,
@@ -1558,6 +1559,30 @@ static int ftdi_open(struct tty_struct *tty,
 } /* ftdi_open */
 
 
+static void ftdi_dtr_rts(struct usb_serial_port *port, int on)
+{
+       struct ftdi_private *priv = usb_get_serial_port_data(port);
+       char buf[1];
+
+       mutex_lock(&port->serial->disc_mutex);
+       if (!port->serial->disconnected) {
+               /* Disable flow control */
+               if (!on && usb_control_msg(port->serial->dev,
+                           usb_sndctrlpipe(port->serial->dev, 0),
+                           FTDI_SIO_SET_FLOW_CTRL_REQUEST,
+                           FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE,
+                           0, priv->interface, buf, 0,
+                           WDR_TIMEOUT) < 0) {
+                           dev_err(&port->dev, "error from flowcontrol urb\n");
+               }
+               /* drop RTS and DTR */
+               if (on)
+                       set_mctrl(port, TIOCM_DTR | TIOCM_RTS);
+               else
+                       clear_mctrl(port, TIOCM_DTR | TIOCM_RTS);
+       }
+       mutex_unlock(&port->serial->disc_mutex);
+}
 
 /*
  * usbserial:__serial_close  only calls ftdi_close if the point is open
@@ -1567,31 +1592,12 @@ static int ftdi_open(struct tty_struct *tty,
  *
  */
 
-static void ftdi_close(struct tty_struct *tty,
-                       struct usb_serial_port *port, struct file *filp)
+static void ftdi_close(struct usb_serial_port *port)
 { /* ftdi_close */
-       unsigned int c_cflag = tty->termios->c_cflag;
        struct ftdi_private *priv = usb_get_serial_port_data(port);
-       char buf[1];
 
        dbg("%s", __func__);
 
-       mutex_lock(&port->serial->disc_mutex);
-       if (c_cflag & HUPCL && !port->serial->disconnected) {
-               /* Disable flow control */
-               if (usb_control_msg(port->serial->dev,
-                                   usb_sndctrlpipe(port->serial->dev, 0),
-                                   FTDI_SIO_SET_FLOW_CTRL_REQUEST,
-                                   FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE,
-                                   0, priv->interface, buf, 0,
-                                   WDR_TIMEOUT) < 0) {
-                       dev_err(&port->dev, "error from flowcontrol urb\n");
-               }
-
-               /* drop RTS and DTR */
-               clear_mctrl(port, TIOCM_DTR | TIOCM_RTS);
-       } /* Note change no line if hupcl is off */
-       mutex_unlock(&port->serial->disc_mutex);
 
        /* cancel any scheduled reading */
        cancel_delayed_work_sync(&priv->rx_work);
index 586d30ff450b2eb9cc8346bd26ea3697056661ac..ee25a3fe3b09c317b0ecbb86f8dde60301bbc9b9 100644 (file)
@@ -993,8 +993,7 @@ static int garmin_open(struct tty_struct *tty,
 }
 
 
-static void garmin_close(struct tty_struct *tty,
-                       struct usb_serial_port *port, struct file *filp)
+static void garmin_close(struct usb_serial_port *port)
 {
        struct usb_serial *serial = port->serial;
        struct garmin_data *garmin_data_p = usb_get_serial_port_data(port);
index 4cec9906ccf394ef312f07d152bbc64785f2cce0..be82ea956720184d545a0c43bce6f684c032fb7e 100644 (file)
@@ -184,8 +184,7 @@ int usb_serial_generic_resume(struct usb_serial *serial)
 }
 EXPORT_SYMBOL_GPL(usb_serial_generic_resume);
 
-void usb_serial_generic_close(struct tty_struct *tty,
-                       struct usb_serial_port *port, struct file *filp)
+void usb_serial_generic_close(struct usb_serial_port *port)
 {
        dbg("%s - port %d", __func__, port->number);
        generic_cleanup(port);
index fb4a73d090f6b9137daa847301a37545c48edc9b..53ef5996e33de377b6290c84e4183f2669ef646e 100644 (file)
@@ -207,8 +207,7 @@ static void edge_bulk_out_cmd_callback(struct urb *urb);
 /* function prototypes for the usbserial callbacks */
 static int edge_open(struct tty_struct *tty, struct usb_serial_port *port,
                                        struct file *filp);
-static void edge_close(struct tty_struct *tty, struct usb_serial_port *port,
-                                       struct file *filp);
+static void edge_close(struct usb_serial_port *port);
 static int edge_write(struct tty_struct *tty, struct usb_serial_port *port,
                                        const unsigned char *buf, int count);
 static int edge_write_room(struct tty_struct *tty);
@@ -965,7 +964,7 @@ static int edge_open(struct tty_struct *tty,
 
        if (!edge_port->txfifo.fifo) {
                dbg("%s - no memory", __func__);
-               edge_close(tty, port, filp);
+               edge_close(port);
                return -ENOMEM;
        }
 
@@ -975,7 +974,7 @@ static int edge_open(struct tty_struct *tty,
 
        if (!edge_port->write_urb) {
                dbg("%s - no memory", __func__);
-               edge_close(tty, port, filp);
+               edge_close(port);
                return -ENOMEM;
        }
 
@@ -1099,8 +1098,7 @@ static void block_until_tx_empty(struct edgeport_port *edge_port)
  * edge_close
  *     this function is called by the tty driver when a port is closed
  *****************************************************************************/
-static void edge_close(struct tty_struct *tty,
-                       struct usb_serial_port *port, struct file *filp)
+static void edge_close(struct usb_serial_port *port)
 {
        struct edgeport_serial *edge_serial;
        struct edgeport_port *edge_port;
index 513b25e044c166749f062843d246350bd2ea8ea3..eabf20eeb370ee4ce578c831b36003a7837d2bd9 100644 (file)
@@ -2009,8 +2009,7 @@ release_es_lock:
        return status;
 }
 
-static void edge_close(struct tty_struct *tty,
-                       struct usb_serial_port *port, struct file *filp)
+static void edge_close(struct usb_serial_port *port)
 {
        struct edgeport_serial *edge_serial;
        struct edgeport_port *edge_port;
index cd62825a9ac325e520d6cf0ba93f6e7cab763d66..c610a99fa47741c51d2b9312150f9ffc05868e23 100644 (file)
@@ -76,8 +76,7 @@ static int initial_wait;
 /* Function prototypes for an ipaq */
 static int  ipaq_open(struct tty_struct *tty,
                        struct usb_serial_port *port, struct file *filp);
-static void ipaq_close(struct tty_struct *tty,
-                       struct usb_serial_port *port, struct file *filp);
+static void ipaq_close(struct usb_serial_port *port);
 static int  ipaq_calc_num_ports(struct usb_serial *serial);
 static int  ipaq_startup(struct usb_serial *serial);
 static void ipaq_shutdown(struct usb_serial *serial);
@@ -714,8 +713,7 @@ error:
 }
 
 
-static void ipaq_close(struct tty_struct *tty,
-                       struct usb_serial_port *port, struct file *filp)
+static void ipaq_close(struct usb_serial_port *port)
 {
        struct ipaq_private     *priv = usb_get_serial_port_data(port);
 
index da2a2b46644a5ddada6bd79abf71504df4148fb7..29ad038b9c8de2536a9373bb60b28f9ad7354044 100644 (file)
@@ -302,23 +302,17 @@ static int ipw_open(struct tty_struct *tty,
        return 0;
 }
 
-static void ipw_close(struct tty_struct *tty,
-                       struct usb_serial_port *port, struct file *filp)
+static void ipw_dtr_rts(struct usb_serial_port *port, int on)
 {
        struct usb_device *dev = port->serial->dev;
        int result;
 
-       if (tty_hung_up_p(filp)) {
-               dbg("%s: tty_hung_up_p ...", __func__);
-               return;
-       }
-
        /*--1: drop the dtr */
        dbg("%s:dropping dtr", __func__);
        result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
                         IPW_SIO_SET_PIN,
                         USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT,
-                        IPW_PIN_CLRDTR,
+                        on ? IPW_PIN_SETDTR : IPW_PIN_CLRDTR,
                         0,
                         NULL,
                         0,
@@ -332,7 +326,7 @@ static void ipw_close(struct tty_struct *tty,
        result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
                         IPW_SIO_SET_PIN, USB_TYPE_VENDOR |
                                        USB_RECIP_INTERFACE | USB_DIR_OUT,
-                        IPW_PIN_CLRRTS,
+                        on ? IPW_PIN_SETRTS : IPW_PIN_CLRRTS,
                         0,
                         NULL,
                         0,
@@ -340,7 +334,12 @@ static void ipw_close(struct tty_struct *tty,
        if (result < 0)
                dev_err(&port->dev,
                                "dropping rts failed (error = %d)\n", result);
+}
 
+static void ipw_close(struct usb_serial_port *port)
+{
+       struct usb_device *dev = port->serial->dev;
+       int result;
 
        /*--3: purge */
        dbg("%s:sending purge", __func__);
@@ -461,6 +460,7 @@ static struct usb_serial_driver ipw_device = {
        .num_ports =            1,
        .open =                 ipw_open,
        .close =                ipw_close,
+       .dtr_rts =              ipw_dtr_rts,
        .port_probe =           ipw_probe,
        .port_remove =          ipw_disconnect,
        .write =                ipw_write,
index 4e2cda93da596f7d5b98db2ae9a60b001418b392..66009b6b763a29a511551a9600d50802de63d3c9 100644 (file)
@@ -88,8 +88,7 @@ static int xbof = -1;
 static int  ir_startup (struct usb_serial *serial);
 static int  ir_open(struct tty_struct *tty, struct usb_serial_port *port,
                                        struct file *filep);
-static void ir_close(struct tty_struct *tty, struct usb_serial_port *port,
-                                       struct file *filep);
+static void ir_close(struct usb_serial_port *port);
 static int  ir_write(struct tty_struct *tty, struct usb_serial_port *port,
                                        const unsigned char *buf, int count);
 static void ir_write_bulk_callback (struct urb *urb);
@@ -346,8 +345,7 @@ static int ir_open(struct tty_struct *tty,
        return result;
 }
 
-static void ir_close(struct tty_struct *tty,
-                       struct usb_serial_port *port, struct file * filp)
+static void ir_close(struct usb_serial_port *port)
 {
        dbg("%s - port %d", __func__, port->number);
 
index 4473d442b2aa45357f7bfcea14aac39445de87da..bb572cee6ecdd78be4b1e3127eb58cfe2df04a59 100644 (file)
@@ -70,7 +70,6 @@ static void read_rxcmd_callback(struct urb *urb);
 struct iuu_private {
        spinlock_t lock;        /* store irq state */
        wait_queue_head_t delta_msr_wait;
-       u8 line_control;
        u8 line_status;
        u8 termios_initialized;
        int tiostatus;          /* store IUART SIGNAL for tiocmget call */
@@ -946,19 +945,10 @@ static int iuu_uart_baud(struct usb_serial_port *port, u32 baud,
        return status;
 }
 
-static int set_control_lines(struct usb_device *dev, u8 value)
-{
-       return 0;
-}
-
-static void iuu_close(struct tty_struct *tty,
-                       struct usb_serial_port *port, struct file *filp)
+static void iuu_close(struct usb_serial_port *port)
 {
        /* iuu_led (port,255,0,0,0); */
        struct usb_serial *serial;
-       struct iuu_private *priv = usb_get_serial_port_data(port);
-       unsigned long flags;
-       unsigned int c_cflag;
 
        serial = port->serial;
        if (!serial)
@@ -968,17 +958,6 @@ static void iuu_close(struct tty_struct *tty,
 
        iuu_uart_off(port);
        if (serial->dev) {
-               if (tty) {
-                       c_cflag = tty->termios->c_cflag;
-                       if (c_cflag & HUPCL) {
-                               /* drop DTR and RTS */
-                               priv = usb_get_serial_port_data(port);
-                               spin_lock_irqsave(&priv->lock, flags);
-                               priv->line_control = 0;
-                               spin_unlock_irqrestore(&priv->lock, flags);
-                               set_control_lines(port->serial->dev, 0);
-                       }
-               }
                /* free writebuf */
                /* shutdown our urbs */
                dbg("%s - shutting down urbs", __func__);
@@ -1154,7 +1133,7 @@ static int iuu_open(struct tty_struct *tty,
        if (result) {
                dev_err(&port->dev, "%s - failed submitting read urb,"
                        " error %d\n", __func__, result);
-               iuu_close(tty, port, NULL);
+               iuu_close(port);
                return -EPROTO;
        } else {
                dbg("%s - rxcmd OK", __func__);
index 00daa8f7759a99946fc3a902dc1e46c9a2bf55af..f1195a98f316df62f0d465b144b32fc3f6f9da66 100644 (file)
@@ -1298,8 +1298,16 @@ static inline void stop_urb(struct urb *urb)
                usb_kill_urb(urb);
 }
 
-static void keyspan_close(struct tty_struct *tty,
-                       struct usb_serial_port *port, struct file *filp)
+static void keyspan_dtr_rts(struct usb_serial_port *port, int on)
+{
+       struct keyspan_port_private *p_priv = usb_get_serial_port_data(port);
+
+       p_priv->rts_state = on;
+       p_priv->dtr_state = on;
+       keyspan_send_setup(port, 0);
+}
+
+static void keyspan_close(struct usb_serial_port *port)
 {
        int                     i;
        struct usb_serial       *serial = port->serial;
@@ -1336,7 +1344,6 @@ static void keyspan_close(struct tty_struct *tty,
                        stop_urb(p_priv->out_urbs[i]);
                }
        }
-       tty_port_tty_set(&port->port, NULL);
 }
 
 /* download the firmware to a pre-renumeration device */
index 38b4582e073446ad6513b7ed11145ccc6a26e61c..0d4569b60768a736a1e180db3621aa9053f22e72 100644 (file)
@@ -38,9 +38,8 @@
 static int  keyspan_open               (struct tty_struct *tty,
                                         struct usb_serial_port *port,
                                         struct file *filp);
-static void keyspan_close              (struct tty_struct *tty,
-                                        struct usb_serial_port *port,
-                                        struct file *filp);
+static void keyspan_close              (struct usb_serial_port *port);
+static void keyspan_dtr_rts            (struct usb_serial_port *port, int on);
 static int  keyspan_startup            (struct usb_serial *serial);
 static void keyspan_shutdown           (struct usb_serial *serial);
 static int  keyspan_write_room         (struct tty_struct *tty);
@@ -562,6 +561,7 @@ static struct usb_serial_driver keyspan_1port_device = {
        .num_ports              = 1,
        .open                   = keyspan_open,
        .close                  = keyspan_close,
+       .dtr_rts                = keyspan_dtr_rts,
        .write                  = keyspan_write,
        .write_room             = keyspan_write_room,
        .set_termios            = keyspan_set_termios,
@@ -582,6 +582,7 @@ static struct usb_serial_driver keyspan_2port_device = {
        .num_ports              = 2,
        .open                   = keyspan_open,
        .close                  = keyspan_close,
+       .dtr_rts                = keyspan_dtr_rts,
        .write                  = keyspan_write,
        .write_room             = keyspan_write_room,
        .set_termios            = keyspan_set_termios,
@@ -602,6 +603,7 @@ static struct usb_serial_driver keyspan_4port_device = {
        .num_ports              = 4,
        .open                   = keyspan_open,
        .close                  = keyspan_close,
+       .dtr_rts                = keyspan_dtr_rts,
        .write                  = keyspan_write,
        .write_room             = keyspan_write_room,
        .set_termios            = keyspan_set_termios,
index bf1ae247da66133f64ee79d57f15ef6619f82aa2..ab769dbea1b3e6f66d4df15ce6166caca8a17a50 100644 (file)
@@ -651,6 +651,35 @@ static int keyspan_pda_chars_in_buffer(struct tty_struct *tty)
 }
 
 
+static void keyspan_pda_dtr_rts(struct usb_serial_port *port, int on)
+{
+       struct usb_serial *serial = port->serial;
+
+       if (serial->dev) {
+               if (on)
+                       keyspan_pda_set_modem_info(serial, (1<<7) | (1<< 2));
+               else
+                       keyspan_pda_set_modem_info(serial, 0);
+       }
+}
+
+static int keyspan_pda_carrier_raised(struct usb_serial_port *port)
+{
+       struct usb_serial *serial = port->serial;
+       unsigned char modembits;
+
+       /* If we can read the modem status and the DCD is low then
+          carrier is not raised yet */
+       if (keyspan_pda_get_modem_info(serial, &modembits) >= 0) {
+               if (!(modembits & (1>>6)))
+                       return 0;
+       }
+       /* Carrier raised, or we failed (eg disconnected) so
+          progress accordingly */
+       return 1;
+}
+
+
 static int keyspan_pda_open(struct tty_struct *tty,
                        struct usb_serial_port *port, struct file *filp)
 {
@@ -682,13 +711,6 @@ static int keyspan_pda_open(struct tty_struct *tty,
        priv->tx_room = room;
        priv->tx_throttled = room ? 0 : 1;
 
-       /* the normal serial device seems to always turn on DTR and RTS here,
-          so do the same */
-       if (tty && (tty->termios->c_cflag & CBAUD))
-               keyspan_pda_set_modem_info(serial, (1<<7) | (1<<2));
-       else
-               keyspan_pda_set_modem_info(serial, 0);
-
        /*Start reading from the device*/
        port->interrupt_in_urb->dev = serial->dev;
        rc = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL);
@@ -700,19 +722,11 @@ static int keyspan_pda_open(struct tty_struct *tty,
 error:
        return rc;
 }
-
-
-static void keyspan_pda_close(struct tty_struct *tty,
-                       struct usb_serial_port *port, struct file *filp)
+static void keyspan_pda_close(struct usb_serial_port *port)
 {
        struct usb_serial *serial = port->serial;
 
        if (serial->dev) {
-               /* the normal serial device seems to always shut
-                  off DTR and RTS now */
-               if (tty->termios->c_cflag & HUPCL)
-                       keyspan_pda_set_modem_info(serial, 0);
-
                /* shutdown our bulk reads and writes */
                usb_kill_urb(port->write_urb);
                usb_kill_urb(port->interrupt_in_urb);
@@ -839,6 +853,8 @@ static struct usb_serial_driver keyspan_pda_device = {
        .usb_driver =           &keyspan_pda_driver,
        .id_table =             id_table_std,
        .num_ports =            1,
+       .dtr_rts =              keyspan_pda_dtr_rts,
+       .carrier_raised =       keyspan_pda_carrier_raised,
        .open =                 keyspan_pda_open,
        .close =                keyspan_pda_close,
        .write =                keyspan_pda_write,
index fcd9082f3e7f05d93fedc3073e3f6a87c318a6a8..fa817c66b3e8c827bb6ce0837591f2406dd73f70 100644 (file)
@@ -76,8 +76,7 @@ static int  klsi_105_startup(struct usb_serial *serial);
 static void klsi_105_shutdown(struct usb_serial *serial);
 static int  klsi_105_open(struct tty_struct *tty,
                        struct usb_serial_port *port, struct file *filp);
-static void klsi_105_close(struct tty_struct *tty,
-                       struct usb_serial_port *port, struct file *filp);
+static void klsi_105_close(struct usb_serial_port *port);
 static int  klsi_105_write(struct tty_struct *tty,
        struct usb_serial_port *port, const unsigned char *buf, int count);
 static void klsi_105_write_bulk_callback(struct urb *urb);
@@ -447,8 +446,7 @@ exit:
 } /* klsi_105_open */
 
 
-static void klsi_105_close(struct tty_struct *tty,
-                       struct usb_serial_port *port, struct file *filp)
+static void klsi_105_close(struct usb_serial_port *port)
 {
        struct klsi_105_private *priv = usb_get_serial_port_data(port);
        int rc;
index c148544953b37df33a00fc9873377a31168de993..6b570498287f3f5d62d337e6a347945101b638c3 100644 (file)
@@ -72,8 +72,7 @@ static int  kobil_startup(struct usb_serial *serial);
 static void kobil_shutdown(struct usb_serial *serial);
 static int  kobil_open(struct tty_struct *tty,
                        struct usb_serial_port *port, struct file *filp);
-static void kobil_close(struct tty_struct *tty, struct usb_serial_port *port,
-                       struct file *filp);
+static void kobil_close(struct usb_serial_port *port);
 static int  kobil_write(struct tty_struct *tty, struct usb_serial_port *port,
                         const unsigned char *buf, int count);
 static int  kobil_write_room(struct tty_struct *tty);
@@ -209,7 +208,7 @@ static void kobil_shutdown(struct usb_serial *serial)
 
        for (i = 0; i < serial->num_ports; ++i) {
                while (serial->port[i]->port.count > 0)
-                       kobil_close(NULL, serial->port[i], NULL);
+                       kobil_close(serial->port[i]);
                kfree(usb_get_serial_port_data(serial->port[i]));
                usb_set_serial_port_data(serial->port[i], NULL);
        }
@@ -346,11 +345,11 @@ static int kobil_open(struct tty_struct *tty,
 }
 
 
-static void kobil_close(struct tty_struct *tty,
-                       struct usb_serial_port *port, struct file *filp)
+static void kobil_close(struct usb_serial_port *port)
 {
        dbg("%s - port %d", __func__, port->number);
 
+       /* FIXME: Add rts/dtr methods */
        if (port->write_urb) {
                usb_kill_urb(port->write_urb);
                usb_free_urb(port->write_urb);
index 82930a7d509327c2797ef474042e0a3d2a4106ac..873795548fc0a976a5bd129e3316933c9eda069b 100644 (file)
@@ -95,8 +95,8 @@ static int  mct_u232_startup(struct usb_serial *serial);
 static void mct_u232_shutdown(struct usb_serial *serial);
 static int  mct_u232_open(struct tty_struct *tty,
                        struct usb_serial_port *port, struct file *filp);
-static void mct_u232_close(struct tty_struct *tty,
-                       struct usb_serial_port *port, struct file *filp);
+static void mct_u232_close(struct usb_serial_port *port);
+static void mct_u232_dtr_rts(struct usb_serial_port *port, int on);
 static void mct_u232_read_int_callback(struct urb *urb);
 static void mct_u232_set_termios(struct tty_struct *tty,
                        struct usb_serial_port *port, struct ktermios *old);
@@ -140,6 +140,7 @@ static struct usb_serial_driver mct_u232_device = {
        .num_ports =         1,
        .open =              mct_u232_open,
        .close =             mct_u232_close,
+       .dtr_rts =           mct_u232_dtr_rts,
        .throttle =          mct_u232_throttle,
        .unthrottle =        mct_u232_unthrottle,
        .read_int_callback = mct_u232_read_int_callback,
@@ -496,29 +497,29 @@ error:
        return retval;
 } /* mct_u232_open */
 
-
-static void mct_u232_close(struct tty_struct *tty,
-                       struct usb_serial_port *port, struct file *filp)
+static void mct_u232_dtr_rts(struct usb_serial_port *port, int on)
 {
-       unsigned int c_cflag;
        unsigned int control_state;
        struct mct_u232_private *priv = usb_get_serial_port_data(port);
-       dbg("%s port %d", __func__, port->number);
 
-       if (tty) {
-               c_cflag = tty->termios->c_cflag;
-               mutex_lock(&port->serial->disc_mutex);
-               if (c_cflag & HUPCL && !port->serial->disconnected) {
-                       /* drop DTR and RTS */
-                       spin_lock_irq(&priv->lock);
+       mutex_lock(&port->serial->disc_mutex);
+       if (!port->serial->disconnected) {
+               /* drop DTR and RTS */
+               spin_lock_irq(&priv->lock);
+               if (on)
+                       priv->control_state |= TIOCM_DTR | TIOCM_RTS;
+               else
                        priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS);
-                       control_state = priv->control_state;
-                       spin_unlock_irq(&priv->lock);
-                       mct_u232_set_modem_ctrl(port->serial, control_state);
-               }
-               mutex_unlock(&port->serial->disc_mutex);
+               control_state = priv->control_state;
+               spin_unlock_irq(&priv->lock);
+               mct_u232_set_modem_ctrl(port->serial, control_state);
        }
+       mutex_unlock(&port->serial->disc_mutex);
+}
 
+static void mct_u232_close(struct usb_serial_port *port)
+{
+       dbg("%s port %d", __func__, port->number);
 
        if (port->serial->dev) {
                /* shutdown our urbs */
index 24e3b5d4b4d49f088a9891718bc36c815c4a409c..9e1a013ee7f679177e7b588aabbb2b6534d4cda3 100644 (file)
@@ -533,8 +533,7 @@ static int mos7720_chars_in_buffer(struct tty_struct *tty)
        return chars;
 }
 
-static void mos7720_close(struct tty_struct *tty,
-                       struct usb_serial_port *port, struct file *filp)
+static void mos7720_close(struct usb_serial_port *port)
 {
        struct usb_serial *serial;
        struct moschip_port *mos7720_port;
index 84fb1dcd30dc3eacdf186c3666375775ff9b1fad..10b78a37214f6c337b1ac1bb3cb93219a9bbd3ba 100644 (file)
@@ -1135,54 +1135,12 @@ static int mos7840_chars_in_buffer(struct tty_struct *tty)
 
 }
 
-/************************************************************************
- *
- * mos7840_block_until_tx_empty
- *
- *     This function will block the close until one of the following:
- *             1. TX count are 0
- *             2. The mos7840 has stopped
- *             3. A timeout of 3 seconds without activity has expired
- *
- ************************************************************************/
-static void mos7840_block_until_tx_empty(struct tty_struct *tty,
-                               struct moschip_port *mos7840_port)
-{
-       int timeout = HZ / 10;
-       int wait = 30;
-       int count;
-
-       while (1) {
-
-               count = mos7840_chars_in_buffer(tty);
-
-               /* Check for Buffer status */
-               if (count <= 0)
-                       return;
-
-               /* Block the thread for a while */
-               interruptible_sleep_on_timeout(&mos7840_port->wait_chase,
-                                              timeout);
-
-               /* No activity.. count down section */
-               wait--;
-               if (wait == 0) {
-                       dbg("%s - TIMEOUT", __func__);
-                       return;
-               } else {
-                       /* Reset timeout value back to seconds */
-                       wait = 30;
-               }
-       }
-}
-
 /*****************************************************************************
  * mos7840_close
  *     this function is called by the tty driver when a port is closed
  *****************************************************************************/
 
-static void mos7840_close(struct tty_struct *tty,
-                       struct usb_serial_port *port, struct file *filp)
+static void mos7840_close(struct usb_serial_port *port)
 {
        struct usb_serial *serial;
        struct moschip_port *mos7840_port;
@@ -1223,10 +1181,6 @@ static void mos7840_close(struct tty_struct *tty,
                }
        }
 
-       if (serial->dev)
-               /* flush and block until tx is empty */
-               mos7840_block_until_tx_empty(tty, mos7840_port);
-
        /* While closing port, shutdown all bulk read, write  *
         * and interrupt read if they exists                  */
        if (serial->dev) {
index bcdcbb822705fd952863dcd5d041abef4d8daad3..f5f3751a888ced2547abf459d63e99a6cafe3a7e 100644 (file)
@@ -98,8 +98,7 @@ static int navman_open(struct tty_struct *tty,
        return result;
 }
 
-static void navman_close(struct tty_struct *tty,
-                       struct usb_serial_port *port, struct file *filp)
+static void navman_close(struct usb_serial_port *port)
 {
        dbg("%s - port %d", __func__, port->number);
 
index df6539712726b93b8c007ecea018a5ed9ea4cb50..1104617334f50d9ff4e9afbbe3d3b21934f92cc3 100644 (file)
@@ -66,8 +66,7 @@ static int debug;
 /* function prototypes */
 static int  omninet_open(struct tty_struct *tty, struct usb_serial_port *port,
                                                        struct file *filp);
-static void omninet_close(struct tty_struct *tty, struct usb_serial_port *port,
-                                                       struct file *filp);
+static void omninet_close(struct usb_serial_port *port);
 static void omninet_read_bulk_callback(struct urb *urb);
 static void omninet_write_bulk_callback(struct urb *urb);
 static int  omninet_write(struct tty_struct *tty, struct usb_serial_port *port,
@@ -189,8 +188,7 @@ static int omninet_open(struct tty_struct *tty,
        return result;
 }
 
-static void omninet_close(struct tty_struct *tty,
-                       struct usb_serial_port *port, struct file *filp)
+static void omninet_close(struct usb_serial_port *port)
 {
        dbg("%s - port %d", __func__, port->number);
        usb_kill_urb(port->read_urb);
index b500ad10b7589185087bbcb64cc0e4ba97fbfd3b..c20480aa975558c9fdac755fe0323991e6c1b4f6 100644 (file)
@@ -173,8 +173,7 @@ static int opticon_open(struct tty_struct *tty, struct usb_serial_port *port,
        return result;
 }
 
-static void opticon_close(struct tty_struct *tty, struct usb_serial_port *port,
-                         struct file *filp)
+static void opticon_close(struct usb_serial_port *port)
 {
        struct opticon_private *priv = usb_get_serial_data(port->serial);
 
index 7817b82889ca5e56eeb0c63a01c9351cf1a02612..a16d69fadba1cd9fa7088b9baa3a598b6402c2d9 100644 (file)
@@ -45,8 +45,9 @@
 /* Function prototypes */
 static int  option_open(struct tty_struct *tty, struct usb_serial_port *port,
                                                        struct file *filp);
-static void option_close(struct tty_struct *tty, struct usb_serial_port *port,
-                                                       struct file *filp);
+static void option_close(struct usb_serial_port *port);
+static void option_dtr_rts(struct usb_serial_port *port, int on);
+
 static int  option_startup(struct usb_serial *serial);
 static void option_shutdown(struct usb_serial *serial);
 static int  option_write_room(struct tty_struct *tty);
@@ -61,7 +62,7 @@ static void option_set_termios(struct tty_struct *tty,
 static int  option_tiocmget(struct tty_struct *tty, struct file *file);
 static int  option_tiocmset(struct tty_struct *tty, struct file *file,
                                unsigned int set, unsigned int clear);
-static int  option_send_setup(struct tty_struct *tty, struct usb_serial_port *port);
+static int  option_send_setup(struct usb_serial_port *port);
 static int  option_suspend(struct usb_serial *serial, pm_message_t message);
 static int  option_resume(struct usb_serial *serial);
 
@@ -551,6 +552,7 @@ static struct usb_serial_driver option_1port_device = {
        .num_ports         = 1,
        .open              = option_open,
        .close             = option_close,
+       .dtr_rts           = option_dtr_rts,
        .write             = option_write,
        .write_room        = option_write_room,
        .chars_in_buffer   = option_chars_in_buffer,
@@ -630,7 +632,7 @@ static void option_set_termios(struct tty_struct *tty,
        dbg("%s", __func__);
        /* Doesn't support option setting */
        tty_termios_copy_hw(tty->termios, old_termios);
-       option_send_setup(tty, port);
+       option_send_setup(port);
 }
 
 static int option_tiocmget(struct tty_struct *tty, struct file *file)
@@ -669,7 +671,7 @@ static int option_tiocmset(struct tty_struct *tty, struct file *file,
                portdata->rts_state = 0;
        if (clear & TIOCM_DTR)
                portdata->dtr_state = 0;
-       return option_send_setup(tty, port);
+       return option_send_setup(port);
 }
 
 /* Write */
@@ -897,10 +899,6 @@ static int option_open(struct tty_struct *tty,
 
        dbg("%s", __func__);
 
-       /* Set some sane defaults */
-       portdata->rts_state = 1;
-       portdata->dtr_state = 1;
-
        /* Reset low level data toggle and start reading from endpoints */
        for (i = 0; i < N_IN_URB; i++) {
                urb = portdata->in_urbs[i];
@@ -936,37 +934,43 @@ static int option_open(struct tty_struct *tty,
                                usb_pipeout(urb->pipe), 0); */
        }
 
-       option_send_setup(tty, port);
+       option_send_setup(port);
 
        return 0;
 }
 
-static void option_close(struct tty_struct *tty,
-                       struct usb_serial_port *port, struct file *filp)
+static void option_dtr_rts(struct usb_serial_port *port, int on)
 {
-       int i;
        struct usb_serial *serial = port->serial;
        struct option_port_private *portdata;
 
        dbg("%s", __func__);
        portdata = usb_get_serial_port_data(port);
+       mutex_lock(&serial->disc_mutex);
+       portdata->rts_state = on;
+       portdata->dtr_state = on;
+       if (serial->dev)
+               option_send_setup(port);
+       mutex_unlock(&serial->disc_mutex);
+}
 
-       portdata->rts_state = 0;
-       portdata->dtr_state = 0;
 
-       if (serial->dev) {
-               mutex_lock(&serial->disc_mutex);
-               if (!serial->disconnected)
-                       option_send_setup(tty, port);
-               mutex_unlock(&serial->disc_mutex);
+static void option_close(struct usb_serial_port *port)
+{
+       int i;
+       struct usb_serial *serial = port->serial;
+       struct option_port_private *portdata;
+
+       dbg("%s", __func__);
+       portdata = usb_get_serial_port_data(port);
 
+       if (serial->dev) {
                /* Stop reading/writing urbs */
                for (i = 0; i < N_IN_URB; i++)
                        usb_kill_urb(portdata->in_urbs[i]);
                for (i = 0; i < N_OUT_URB; i++)
                        usb_kill_urb(portdata->out_urbs[i]);
        }
-       tty_port_tty_set(&port->port, NULL);
 }
 
 /* Helper functions used by option_setup_urbs */
@@ -1032,28 +1036,24 @@ static void option_setup_urbs(struct usb_serial *serial)
  * This is exactly the same as SET_CONTROL_LINE_STATE from the PSTN
  * CDC.
 */
-static int option_send_setup(struct tty_struct *tty,
-                                               struct usb_serial_port *port)
+static int option_send_setup(struct usb_serial_port *port)
 {
        struct usb_serial *serial = port->serial;
        struct option_port_private *portdata;
        int ifNum = serial->interface->cur_altsetting->desc.bInterfaceNumber;
+       int val = 0;
        dbg("%s", __func__);
 
        portdata = usb_get_serial_port_data(port);
 
-       if (tty) {
-               int val = 0;
-               if (portdata->dtr_state)
-                       val |= 0x01;
-               if (portdata->rts_state)
-                       val |= 0x02;
+       if (portdata->dtr_state)
+               val |= 0x01;
+       if (portdata->rts_state)
+               val |= 0x02;
 
-               return usb_control_msg(serial->dev,
-                       usb_rcvctrlpipe(serial->dev, 0),
-                       0x22, 0x21, val, ifNum, NULL, 0, USB_CTRL_SET_TIMEOUT);
-       }
-       return 0;
+       return usb_control_msg(serial->dev,
+               usb_rcvctrlpipe(serial->dev, 0),
+               0x22, 0x21, val, ifNum, NULL, 0, USB_CTRL_SET_TIMEOUT);
 }
 
 static int option_startup(struct usb_serial *serial)
index ba551f00f16ff1ec30fbcd90422f1e1112e8c00a..7de54781fe614e96d32ee69327822f02416c3801 100644 (file)
@@ -143,8 +143,7 @@ struct oti6858_control_pkt {
 /* function prototypes */
 static int oti6858_open(struct tty_struct *tty,
                        struct usb_serial_port *port, struct file *filp);
-static void oti6858_close(struct tty_struct *tty,
-                       struct usb_serial_port *port, struct file *filp);
+static void oti6858_close(struct usb_serial_port *port);
 static void oti6858_set_termios(struct tty_struct *tty,
                        struct usb_serial_port *port, struct ktermios *old);
 static int oti6858_ioctl(struct tty_struct *tty, struct file *file,
@@ -622,67 +621,30 @@ static int oti6858_open(struct tty_struct *tty,
        if (result != 0) {
                dev_err(&port->dev, "%s(): usb_submit_urb() failed"
                               " with error %d\n", __func__, result);
-               oti6858_close(tty, port, NULL);
+               oti6858_close(port);
                return -EPROTO;
        }
 
        /* setup termios */
        if (tty)
                oti6858_set_termios(tty, port, &tmp_termios);
-
+       port->port.drain_delay = 256;   /* FIXME: check the FIFO length */
        return 0;
 }
 
-static void oti6858_close(struct tty_struct *tty,
-                       struct usb_serial_port *port, struct file *filp)
+static void oti6858_close(struct usb_serial_port *port)
 {
        struct oti6858_private *priv = usb_get_serial_port_data(port);
        unsigned long flags;
-       long timeout;
-       wait_queue_t wait;
 
        dbg("%s(port = %d)", __func__, port->number);
 
-       /* wait for data to drain from the buffer */
        spin_lock_irqsave(&priv->lock, flags);
-       timeout = 30 * HZ;      /* PL2303_CLOSING_WAIT */
-       init_waitqueue_entry(&wait, current);
-       add_wait_queue(&tty->write_wait, &wait);
-       dbg("%s(): entering wait loop", __func__);
-       for (;;) {
-               set_current_state(TASK_INTERRUPTIBLE);
-               if (oti6858_buf_data_avail(priv->buf) == 0
-               || timeout == 0 || signal_pending(current)
-               || port->serial->disconnected)
-                       break;
-               spin_unlock_irqrestore(&priv->lock, flags);
-               timeout = schedule_timeout(timeout);
-               spin_lock_irqsave(&priv->lock, flags);
-       }
-       set_current_state(TASK_RUNNING);
-       remove_wait_queue(&tty->write_wait, &wait);
-       dbg("%s(): after wait loop", __func__);
-
        /* clear out any remaining data in the buffer */
        oti6858_buf_clear(priv->buf);
        spin_unlock_irqrestore(&priv->lock, flags);
 
-       /* wait for characters to drain from the device */
-       /* (this is long enough for the entire 256 byte */
-       /* pl2303 hardware buffer to drain with no flow */
-       /* control for data rates of 1200 bps or more, */
-       /* for lower rates we should really know how much */
-       /* data is in the buffer to compute a delay */
-       /* that is not unnecessarily long) */
-       /* FIXME
-       bps = tty_get_baud_rate(tty);
-       if (bps > 1200)
-               timeout = max((HZ*2560)/bps,HZ/10);
-       else
-       */
-               timeout = 2*HZ;
-       schedule_timeout_interruptible(timeout);
-       dbg("%s(): after schedule_timeout_interruptible()", __func__);
+       dbg("%s(): after buf_clear()", __func__);
 
        /* cancel scheduled setup */
        cancel_delayed_work(&priv->delayed_setup_work);
@@ -694,15 +656,6 @@ static void oti6858_close(struct tty_struct *tty,
        usb_kill_urb(port->write_urb);
        usb_kill_urb(port->read_urb);
        usb_kill_urb(port->interrupt_in_urb);
-
-       /*
-       if (tty && (tty->termios->c_cflag) & HUPCL) {
-               // drop DTR and RTS
-               spin_lock_irqsave(&priv->lock, flags);
-               priv->pending_setup.control &= ~CONTROL_MASK;
-               spin_unlock_irqrestore(&priv->lock, flags);
-       }
-       */
 }
 
 static int oti6858_tiocmset(struct tty_struct *tty, struct file *file,
index 751a533a4347e7324725afb8948b75fcb2437bbd..e02dc3d643c7ae1279f467b21584e2899a82dfb7 100644 (file)
@@ -652,69 +652,41 @@ static void pl2303_set_termios(struct tty_struct *tty,
        kfree(buf);
 }
 
-static void pl2303_close(struct tty_struct *tty,
-                       struct usb_serial_port *port, struct file *filp)
+static void pl2303_dtr_rts(struct usb_serial_port *port, int on)
+{
+       struct pl2303_private *priv = usb_get_serial_port_data(port);
+       unsigned long flags;
+       u8 control;
+
+       spin_lock_irqsave(&priv->lock, flags);
+       /* Change DTR and RTS */
+       if (on)
+               priv->line_control |= (CONTROL_DTR | CONTROL_RTS);
+       else
+               priv->line_control &= ~(CONTROL_DTR | CONTROL_RTS);
+       control = priv->line_control;
+       spin_unlock_irqrestore(&priv->lock, flags);
+       set_control_lines(port->serial->dev, control);
+}
+
+static void pl2303_close(struct usb_serial_port *port)
 {
        struct pl2303_private *priv = usb_get_serial_port_data(port);
        unsigned long flags;
-       unsigned int c_cflag;
-       int bps;
-       long timeout;
-       wait_queue_t wait;
 
        dbg("%s - port %d", __func__, port->number);
 
-       /* wait for data to drain from the buffer */
        spin_lock_irqsave(&priv->lock, flags);
-       timeout = PL2303_CLOSING_WAIT;
-       init_waitqueue_entry(&wait, current);
-       add_wait_queue(&tty->write_wait, &wait);
-       for (;;) {
-               set_current_state(TASK_INTERRUPTIBLE);
-               if (pl2303_buf_data_avail(priv->buf) == 0 ||
-                   timeout == 0 || signal_pending(current) ||
-                   port->serial->disconnected)
-                       break;
-               spin_unlock_irqrestore(&priv->lock, flags);
-               timeout = schedule_timeout(timeout);
-               spin_lock_irqsave(&priv->lock, flags);
-       }
-       set_current_state(TASK_RUNNING);
-       remove_wait_queue(&tty->write_wait, &wait);
        /* clear out any remaining data in the buffer */
        pl2303_buf_clear(priv->buf);
        spin_unlock_irqrestore(&priv->lock, flags);
 
-       /* wait for characters to drain from the device */
-       /* (this is long enough for the entire 256 byte */
-       /* pl2303 hardware buffer to drain with no flow */
-       /* control for data rates of 1200 bps or more, */
-       /* for lower rates we should really know how much */
-       /* data is in the buffer to compute a delay */
-       /* that is not unnecessarily long) */
-       bps = tty_get_baud_rate(tty);
-       if (bps > 1200)
-               timeout = max((HZ*2560)/bps, HZ/10);
-       else
-               timeout = 2*HZ;
-       schedule_timeout_interruptible(timeout);
-
        /* shutdown our urbs */
        dbg("%s - shutting down urbs", __func__);
        usb_kill_urb(port->write_urb);
        usb_kill_urb(port->read_urb);
        usb_kill_urb(port->interrupt_in_urb);
 
-       if (tty) {
-               c_cflag = tty->termios->c_cflag;
-               if (c_cflag & HUPCL) {
-                       /* drop DTR and RTS */
-                       spin_lock_irqsave(&priv->lock, flags);
-                       priv->line_control = 0;
-                       spin_unlock_irqrestore(&priv->lock, flags);
-                       set_control_lines(port->serial->dev, 0);
-               }
-       }
 }
 
 static int pl2303_open(struct tty_struct *tty,
@@ -748,7 +720,7 @@ static int pl2303_open(struct tty_struct *tty,
        if (result) {
                dev_err(&port->dev, "%s - failed submitting read urb,"
                        " error %d\n", __func__, result);
-               pl2303_close(tty, port, NULL);
+               pl2303_close(port);
                return -EPROTO;
        }
 
@@ -758,9 +730,10 @@ static int pl2303_open(struct tty_struct *tty,
        if (result) {
                dev_err(&port->dev, "%s - failed submitting interrupt urb,"
                        " error %d\n", __func__, result);
-               pl2303_close(tty, port, NULL);
+               pl2303_close(port);
                return -EPROTO;
        }
+       port->port.drain_delay = 256;
        return 0;
 }
 
@@ -821,6 +794,14 @@ static int pl2303_tiocmget(struct tty_struct *tty, struct file *file)
        return result;
 }
 
+static int pl2303_carrier_raised(struct usb_serial_port *port)
+{
+       struct pl2303_private *priv = usb_get_serial_port_data(port);
+       if (priv->line_status & UART_DCD)
+               return 1;
+       return 0;
+}
+
 static int wait_modem_info(struct usb_serial_port *port, unsigned int arg)
 {
        struct pl2303_private *priv = usb_get_serial_port_data(port);
@@ -1125,6 +1106,8 @@ static struct usb_serial_driver pl2303_device = {
        .num_ports =            1,
        .open =                 pl2303_open,
        .close =                pl2303_close,
+       .dtr_rts =              pl2303_dtr_rts,
+       .carrier_raised =       pl2303_carrier_raised,
        .write =                pl2303_write,
        .ioctl =                pl2303_ioctl,
        .break_ctl =            pl2303_break_ctl,
index 913225c6161037ad78596f5ba68b9fa078f510b5..1319b8968d82e6034d8541a3fb07e51077826d4c 100644 (file)
@@ -240,57 +240,39 @@ struct sierra_port_private {
        int ri_state;
 };
 
-static int sierra_send_setup(struct tty_struct *tty,
-                                               struct usb_serial_port *port)
+static int sierra_send_setup(struct usb_serial_port *port)
 {
        struct usb_serial *serial = port->serial;
        struct sierra_port_private *portdata;
        __u16 interface = 0;
+       int val = 0;
 
        dev_dbg(&port->dev, "%s", __func__);
 
        portdata = usb_get_serial_port_data(port);
 
-       if (tty) {
-               int val = 0;
-               if (portdata->dtr_state)
-                       val |= 0x01;
-               if (portdata->rts_state)
-                       val |= 0x02;
-
-               /* If composite device then properly report interface */
-               if (serial->num_ports == 1) {
-                       interface = sierra_calc_interface(serial);
-
-                       /* Control message is sent only to interfaces with
-                        * interrupt_in endpoints
-                        */
-                       if (port->interrupt_in_urb) {
-                               /* send control message */
-                               return usb_control_msg(serial->dev,
-                                       usb_rcvctrlpipe(serial->dev, 0),
-                                       0x22, 0x21, val, interface,
-                                       NULL, 0, USB_CTRL_SET_TIMEOUT);
-                       }
-               }
-
-               /* Otherwise the need to do non-composite mapping */
-               else {
-                       if (port->bulk_out_endpointAddress == 2)
-                               interface = 0;
-                       else if (port->bulk_out_endpointAddress == 4)
-                               interface = 1;
-                       else if (port->bulk_out_endpointAddress == 5)
-                               interface = 2;
-
-                       return usb_control_msg(serial->dev,
-                               usb_rcvctrlpipe(serial->dev, 0),
-                               0x22, 0x21, val, interface,
-                               NULL, 0, USB_CTRL_SET_TIMEOUT);
-
-               }
+       if (portdata->dtr_state)
+               val |= 0x01;
+       if (portdata->rts_state)
+               val |= 0x02;
+
+       /* If composite device then properly report interface */
+       if (serial->num_ports == 1)
+               interface = sierra_calc_interface(serial);
+
+       /* Otherwise the need to do non-composite mapping */
+       else {
+               if (port->bulk_out_endpointAddress == 2)
+                       interface = 0;
+               else if (port->bulk_out_endpointAddress == 4)
+                       interface = 1;
+               else if (port->bulk_out_endpointAddress == 5)
+                       interface = 2;
        }
-
+       return usb_control_msg(serial->dev,
+                       usb_rcvctrlpipe(serial->dev, 0),
+                       0x22, 0x21, val, interface,
+                       NULL, 0, USB_CTRL_SET_TIMEOUT);
        return 0;
 }
 
@@ -299,7 +281,7 @@ static void sierra_set_termios(struct tty_struct *tty,
 {
        dev_dbg(&port->dev, "%s", __func__);
        tty_termios_copy_hw(tty->termios, old_termios);
-       sierra_send_setup(tty, port);
+       sierra_send_setup(port);
 }
 
 static int sierra_tiocmget(struct tty_struct *tty, struct file *file)
@@ -338,7 +320,7 @@ static int sierra_tiocmset(struct tty_struct *tty, struct file *file,
                portdata->rts_state = 0;
        if (clear & TIOCM_DTR)
                portdata->dtr_state = 0;
-       return sierra_send_setup(tty, port);
+       return sierra_send_setup(port);
 }
 
 static void sierra_outdat_callback(struct urb *urb)
@@ -598,7 +580,7 @@ static int sierra_open(struct tty_struct *tty,
                }
        }
 
-       sierra_send_setup(tty, port);
+       sierra_send_setup(port);
 
        /* start up the interrupt endpoint if we have one */
        if (port->interrupt_in_urb) {
@@ -610,32 +592,38 @@ static int sierra_open(struct tty_struct *tty,
        return 0;
 }
 
-static void sierra_close(struct tty_struct *tty,
-                       struct usb_serial_port *port, struct file *filp)
+static void sierra_dtr_rts(struct usb_serial_port *port, int on)
 {
-       int i;
        struct usb_serial *serial = port->serial;
        struct sierra_port_private *portdata;
 
-       dev_dbg(&port->dev, "%s", __func__);
        portdata = usb_get_serial_port_data(port);
-
-       portdata->rts_state = 0;
-       portdata->dtr_state = 0;
+       portdata->rts_state = on;
+       portdata->dtr_state = on;
 
        if (serial->dev) {
                mutex_lock(&serial->disc_mutex);
                if (!serial->disconnected)
-                       sierra_send_setup(tty, port);
+                       sierra_send_setup(port);
                mutex_unlock(&serial->disc_mutex);
+       }
+}
+
+static void sierra_close(struct usb_serial_port *port)
+{
+       int i;
+       struct usb_serial *serial = port->serial;
+       struct sierra_port_private *portdata;
 
+       dev_dbg(&port->dev, "%s", __func__);
+       portdata = usb_get_serial_port_data(port);
+
+       if (serial->dev) {
                /* Stop reading/writing urbs */
                for (i = 0; i < N_IN_URB; i++)
                        usb_kill_urb(portdata->in_urbs[i]);
        }
-
        usb_kill_urb(port->interrupt_in_urb);
-       tty_port_tty_set(&port->port, NULL);
 }
 
 static int sierra_startup(struct usb_serial *serial)
@@ -737,6 +725,7 @@ static struct usb_serial_driver sierra_device = {
        .probe             = sierra_probe,
        .open              = sierra_open,
        .close             = sierra_close,
+       .dtr_rts           = sierra_dtr_rts,
        .write             = sierra_write,
        .write_room        = sierra_write_room,
        .set_termios       = sierra_set_termios,
index 5e7528cc81a8e624f8ef64a869eca06b18918126..8f7ed8f13996185857021d7d2f730c08f60b2403 100644 (file)
@@ -446,66 +446,47 @@ static void spcp8x5_set_workMode(struct usb_device *dev, u16 value,
                        "RTSCTS usb_control_msg(enable flowctrl) = %d\n", ret);
 }
 
+static int spcp8x5_carrier_raised(struct usb_serial_port *port)
+{
+       struct spcp8x5_private *priv = usb_get_serial_port_data(port);
+       if (priv->line_status & MSR_STATUS_LINE_DCD)
+               return 1;
+       return 0;
+}
+
+static void spcp8x5_dtr_rts(struct usb_serial_port *port, int on)
+{
+       struct spcp8x5_private *priv = usb_get_serial_port_data(port);
+       unsigned long flags;
+       u8 control;
+
+       spin_lock_irqsave(&priv->lock, flags);
+       if (on)
+               priv->line_control = MCR_CONTROL_LINE_DTR
+                                               | MCR_CONTROL_LINE_RTS;
+       else
+               priv->line_control &= ~ (MCR_CONTROL_LINE_DTR
+                                               | MCR_CONTROL_LINE_RTS);
+       control = priv->line_control;
+       spin_unlock_irqrestore(&priv->lock, flags);
+       spcp8x5_set_ctrlLine(port->serial->dev, control , priv->type);
+}
+
 /* close the serial port. We should wait for data sending to device 1st and
  * then kill all urb. */
-static void spcp8x5_close(struct tty_struct *tty,
-                       struct usb_serial_port *port, struct file *filp)
+static void spcp8x5_close(struct usb_serial_port *port)
 {
        struct spcp8x5_private *priv = usb_get_serial_port_data(port);
        unsigned long flags;
-       unsigned int c_cflag;
-       int bps;
-       long timeout;
-       wait_queue_t wait;
        int result;
 
        dbg("%s - port %d", __func__, port->number);
 
-       /* wait for data to drain from the buffer */
        spin_lock_irqsave(&priv->lock, flags);
-       timeout = SPCP8x5_CLOSING_WAIT;
-       init_waitqueue_entry(&wait, current);
-       add_wait_queue(&tty->write_wait, &wait);
-       for (;;) {
-               set_current_state(TASK_INTERRUPTIBLE);
-               if (ringbuf_avail_data(priv->buf) == 0 ||
-                   timeout == 0 || signal_pending(current))
-                       break;
-               spin_unlock_irqrestore(&priv->lock, flags);
-               timeout = schedule_timeout(timeout);
-               spin_lock_irqsave(&priv->lock, flags);
-       }
-       set_current_state(TASK_RUNNING);
-       remove_wait_queue(&tty->write_wait, &wait);
-
        /* clear out any remaining data in the buffer */
        clear_ringbuf(priv->buf);
        spin_unlock_irqrestore(&priv->lock, flags);
 
-       /* wait for characters to drain from the device (this is long enough
-        * for the entire all byte spcp8x5 hardware buffer to drain with no
-        * flow control for data rates of 1200 bps or more, for lower rates we
-        * should really know how much data is in the buffer to compute a delay
-        * that is not unnecessarily long) */
-       bps = tty_get_baud_rate(tty);
-       if (bps > 1200)
-               timeout = max((HZ*2560) / bps, HZ/10);
-       else
-               timeout = 2*HZ;
-       set_current_state(TASK_INTERRUPTIBLE);
-       schedule_timeout(timeout);
-
-       /* clear control lines */
-       if (tty) {
-               c_cflag = tty->termios->c_cflag;
-               if (c_cflag & HUPCL) {
-                       spin_lock_irqsave(&priv->lock, flags);
-                       priv->line_control = 0;
-                       spin_unlock_irqrestore(&priv->lock, flags);
-                       spcp8x5_set_ctrlLine(port->serial->dev, 0 , priv->type);
-               }
-       }
-
        /* kill urb */
        if (port->write_urb != NULL) {
                result = usb_unlink_urb(port->write_urb);
@@ -665,13 +646,6 @@ static int spcp8x5_open(struct tty_struct *tty,
        if (ret)
                return ret;
 
-       spin_lock_irqsave(&priv->lock, flags);
-       if (tty && (tty->termios->c_cflag & CBAUD))
-               priv->line_control = MCR_DTR | MCR_RTS;
-       else
-               priv->line_control = 0;
-       spin_unlock_irqrestore(&priv->lock, flags);
-
        spcp8x5_set_ctrlLine(serial->dev, priv->line_control , priv->type);
 
        /* Setup termios */
@@ -691,9 +665,10 @@ static int spcp8x5_open(struct tty_struct *tty,
        port->read_urb->dev = serial->dev;
        ret = usb_submit_urb(port->read_urb, GFP_KERNEL);
        if (ret) {
-               spcp8x5_close(tty, port, NULL);
+               spcp8x5_close(port);
                return -EPROTO;
        }
+       port->port.drain_delay = 256;
        return 0;
 }
 
@@ -1033,6 +1008,8 @@ static struct usb_serial_driver spcp8x5_device = {
        .num_ports              = 1,
        .open                   = spcp8x5_open,
        .close                  = spcp8x5_close,
+       .dtr_rts                = spcp8x5_dtr_rts,
+       .carrier_raised         = spcp8x5_carrier_raised,
        .write                  = spcp8x5_write,
        .set_termios            = spcp8x5_set_termios,
        .ioctl                  = spcp8x5_ioctl,
index 69879e4379402f63ad53579c6a1184d762322260..8b07ebc6baeb4e40ba036e07cacee5414b508628 100644 (file)
@@ -152,8 +152,7 @@ static int symbol_open(struct tty_struct *tty, struct usb_serial_port *port,
        return result;
 }
 
-static void symbol_close(struct tty_struct *tty, struct usb_serial_port *port,
-                         struct file *filp)
+static void symbol_close(struct usb_serial_port *port)
 {
        struct symbol_private *priv = usb_get_serial_data(port->serial);
 
index 0a64bac306ee693f02e9b11ce20a2a70cf452965..42cb04c403beee3900e6fa33451913d0e0a3b29e 100644 (file)
@@ -100,8 +100,7 @@ static int ti_startup(struct usb_serial *serial);
 static void ti_shutdown(struct usb_serial *serial);
 static int ti_open(struct tty_struct *tty, struct usb_serial_port *port,
                struct file *file);
-static void ti_close(struct tty_struct *tty, struct usb_serial_port *port,
-               struct file *file);
+static void ti_close(struct usb_serial_port *port);
 static int ti_write(struct tty_struct *tty, struct usb_serial_port *port,
                const unsigned char *data, int count);
 static int ti_write_room(struct tty_struct *tty);
@@ -647,8 +646,7 @@ release_lock:
 }
 
 
-static void ti_close(struct tty_struct *tty, struct usb_serial_port *port,
-                                                       struct file *file)
+static void ti_close(struct usb_serial_port *port)
 {
        struct ti_device *tdev;
        struct ti_port *tport;
index f331e2bde88acbb0c2b4e36fee01eff68ffc9b5c..1967a7edc10c51fab8263aafc43a425a2b28e686 100644 (file)
@@ -238,9 +238,11 @@ static int serial_open (struct tty_struct *tty, struct file *filp)
                        goto bailout_interface_put;
                mutex_unlock(&serial->disc_mutex);
        }
-
        mutex_unlock(&port->mutex);
-       return 0;
+       /* Now do the correct tty layer semantics */
+       retval = tty_port_block_til_ready(&port->port, tty, filp);
+       if (retval == 0)
+               return 0;
 
 bailout_interface_put:
        usb_autopm_put_interface(serial->interface);
@@ -259,64 +261,89 @@ bailout_serial_put:
        return retval;
 }
 
-static void serial_close(struct tty_struct *tty, struct file *filp)
+/**
+ *     serial_do_down          -       shut down hardware
+ *     @port: port to shut down
+ *
+ *     Shut down a USB port unless it is the console. We never shut down the
+ *     console hardware as it will always be in use.
+ *
+ *     Don't free any resources at this point
+ */
+static void serial_do_down(struct usb_serial_port *port)
 {
-       struct usb_serial_port *port = tty->driver_data;
+       struct usb_serial_driver *drv = port->serial->type;
        struct usb_serial *serial;
        struct module *owner;
-       int count;
 
-       if (!port)
+       /* The console is magical, do not hang up the console hardware
+          or there will be tears */
+       if (port->console)
                return;
 
-       dbg("%s - port %d", __func__, port->number);
-
        mutex_lock(&port->mutex);
        serial = port->serial;
        owner = serial->type->driver.owner;
 
-       if (port->port.count == 0) {
-               mutex_unlock(&port->mutex);
-               return;
-       }
-
-       if (port->port.count == 1)
-               /* only call the device specific close if this
-                * port is being closed by the last owner. Ensure we do
-                * this before we drop the port count. The call is protected
-                * by the port mutex
-                */
-               serial->type->close(tty, port, filp);
-
-       if (port->port.count == (port->console ? 2 : 1)) {
-               struct tty_struct *tty = tty_port_tty_get(&port->port);
-               if (tty) {
-                       /* We must do this before we drop the port count to
-                          zero. */
-                       if (tty->driver_data)
-                               tty->driver_data = NULL;
-                       tty_port_tty_set(&port->port, NULL);
-                       tty_kref_put(tty);
-               }
-       }
+       if (drv->close)
+               drv->close(port);
 
-       --port->port.count;
-       count = port->port.count;
        mutex_unlock(&port->mutex);
-       put_device(&port->dev);
+}
+
+/**
+ *     serial_do_free          -       free resources post close/hangup
+ *     @port: port to free up
+ *
+ *     Do the resource freeing and refcount dropping for the port. We must
+ *     be careful about ordering and we must avoid freeing up the console.
+ */
 
+static void serial_do_free(struct usb_serial_port *port)
+{
+       struct usb_serial *serial;
+       struct module *owner;
+
+       /* The console is magical, do not hang up the console hardware
+          or there will be tears */
+       if (port->console)
+               return;
+
+       serial = port->serial;
+       owner = serial->type->driver.owner;
+       put_device(&port->dev);
        /* Mustn't dereference port any more */
-       if (count == 0) {
-               mutex_lock(&serial->disc_mutex);
-               if (!serial->disconnected)
-                       usb_autopm_put_interface(serial->interface);
-               mutex_unlock(&serial->disc_mutex);
-       }
+       mutex_lock(&serial->disc_mutex);
+       if (!serial->disconnected)
+               usb_autopm_put_interface(serial->interface);
+       mutex_unlock(&serial->disc_mutex);
        usb_serial_put(serial);
-
        /* Mustn't dereference serial any more */
-       if (count == 0)
-               module_put(owner);
+       module_put(owner);
+}
+
+static void serial_close(struct tty_struct *tty, struct file *filp)
+{
+       struct usb_serial_port *port = tty->driver_data;
+
+       dbg("%s - port %d", __func__, port->number);
+
+
+       if (tty_port_close_start(&port->port, tty, filp) == 0)
+               return;
+
+       serial_do_down(port);           
+       tty_port_close_end(&port->port, tty);
+       tty_port_tty_set(&port->port, NULL);
+       serial_do_free(port);
+}
+
+static void serial_hangup(struct tty_struct *tty)
+{
+       struct usb_serial_port *port = tty->driver_data;
+       serial_do_down(port);
+       tty_port_hangup(&port->port);
+       serial_do_free(port);
 }
 
 static int serial_write(struct tty_struct *tty, const unsigned char *buf,
@@ -648,6 +675,29 @@ static struct usb_serial_driver *search_serial_device(
        return NULL;
 }
 
+static int serial_carrier_raised(struct tty_port *port)
+{
+       struct usb_serial_port *p = container_of(port, struct usb_serial_port, port);
+       struct usb_serial_driver *drv = p->serial->type;
+       if (drv->carrier_raised)
+               return drv->carrier_raised(p);
+       /* No carrier control - don't block */
+       return 1;       
+}
+
+static void serial_dtr_rts(struct tty_port *port, int on)
+{
+       struct usb_serial_port *p = container_of(port, struct usb_serial_port, port);
+       struct usb_serial_driver *drv = p->serial->type;
+       if (drv->dtr_rts)
+               drv->dtr_rts(p, on);
+}
+
+static const struct tty_port_operations serial_port_ops = {
+       .carrier_raised = serial_carrier_raised,
+       .dtr_rts = serial_dtr_rts,
+};
+
 int usb_serial_probe(struct usb_interface *interface,
                               const struct usb_device_id *id)
 {
@@ -841,6 +891,7 @@ int usb_serial_probe(struct usb_interface *interface,
                if (!port)
                        goto probe_error;
                tty_port_init(&port->port);
+               port->port.ops = &serial_port_ops;
                port->serial = serial;
                spin_lock_init(&port->lock);
                mutex_init(&port->mutex);
@@ -1071,6 +1122,9 @@ void usb_serial_disconnect(struct usb_interface *interface)
                if (port) {
                        struct tty_struct *tty = tty_port_tty_get(&port->port);
                        if (tty) {
+                               /* The hangup will occur asynchronously but
+                                  the object refcounts will sort out all the
+                                  cleanup */
                                tty_hangup(tty);
                                tty_kref_put(tty);
                        }
@@ -1135,6 +1189,7 @@ static const struct tty_operations serial_ops = {
        .open =                 serial_open,
        .close =                serial_close,
        .write =                serial_write,
+       .hangup =               serial_hangup,
        .write_room =           serial_write_room,
        .ioctl =                serial_ioctl,
        .set_termios =          serial_set_termios,
@@ -1147,6 +1202,7 @@ static const struct tty_operations serial_ops = {
        .proc_fops =            &serial_proc_fops,
 };
 
+
 struct tty_driver *usb_serial_tty_driver;
 
 static int __init usb_serial_init(void)
index 5ac414bda718103191d6489f613e3d5d3c361dd6..b15f1c0e1d4acba4adcbadf66ac98a9870e8c994 100644 (file)
@@ -38,8 +38,7 @@
 /* function prototypes for a handspring visor */
 static int  visor_open(struct tty_struct *tty, struct usb_serial_port *port,
                                        struct file *filp);
-static void visor_close(struct tty_struct *tty, struct usb_serial_port *port,
-                                       struct file *filp);
+static void visor_close(struct usb_serial_port *port);
 static int  visor_write(struct tty_struct *tty, struct usb_serial_port *port,
                                        const unsigned char *buf, int count);
 static int  visor_write_room(struct tty_struct *tty);
@@ -324,8 +323,7 @@ exit:
 }
 
 
-static void visor_close(struct tty_struct *tty,
-                       struct usb_serial_port *port, struct file *filp)
+static void visor_close(struct usb_serial_port *port)
 {
        struct visor_private *priv = usb_get_serial_port_data(port);
        unsigned char *transfer_buffer;
index 5335d3211c073c1c661d895aeaa0488fa0196ba1..7c7295d09f344cf7b4b167346e140e75d6394207 100644 (file)
@@ -147,8 +147,7 @@ static int  whiteheat_attach(struct usb_serial *serial);
 static void whiteheat_shutdown(struct usb_serial *serial);
 static int  whiteheat_open(struct tty_struct *tty,
                        struct usb_serial_port *port, struct file *filp);
-static void whiteheat_close(struct tty_struct *tty,
-                       struct usb_serial_port *port, struct file *filp);
+static void whiteheat_close(struct usb_serial_port *port);
 static int  whiteheat_write(struct tty_struct *tty,
                        struct usb_serial_port *port,
                        const unsigned char *buf, int count);
@@ -712,8 +711,7 @@ exit:
 }
 
 
-static void whiteheat_close(struct tty_struct *tty,
-                       struct usb_serial_port *port, struct file *filp)
+static void whiteheat_close(struct usb_serial_port *port)
 {
        struct whiteheat_private *info = usb_get_serial_port_data(port);
        struct whiteheat_urb_wrap *wrap;
@@ -723,31 +721,7 @@ static void whiteheat_close(struct tty_struct *tty,
 
        dbg("%s - port %d", __func__, port->number);
 
-       mutex_lock(&port->serial->disc_mutex);
-       /* filp is NULL when called from usb_serial_disconnect */
-       if ((filp && (tty_hung_up_p(filp))) || port->serial->disconnected) {
-               mutex_unlock(&port->serial->disc_mutex);
-               return;
-       }
-       mutex_unlock(&port->serial->disc_mutex);
-
-       tty->closing = 1;
-
-/*
- * Not currently in use; tty_wait_until_sent() calls
- * serial_chars_in_buffer() which deadlocks on the second semaphore
- * acquisition. This should be fixed at some point. Greg's been
- * notified.
-       if ((filp->f_flags & (O_NDELAY | O_NONBLOCK)) == 0) {
-               tty_wait_until_sent(tty, CLOSING_DELAY);
-       }
-*/
-
-       tty_driver_flush_buffer(tty);
-       tty_ldisc_flush(tty);
-
        firm_report_tx_done(port);
-
        firm_close(port);
 
        /* shutdown our bulk reads and writes */
@@ -775,10 +749,7 @@ static void whiteheat_close(struct tty_struct *tty,
        }
        spin_unlock_irq(&info->lock);
        mutex_unlock(&info->deathwarrant);
-
        stop_command_port(port->serial);
-
-       tty->closing = 0;
 }
 
 
index 625e9e4639c68f3e9fc2b6b1d3ce4a734fa2113b..8cdfed738fe4b8b28d0f7208c8553f0cf2eaee03 100644 (file)
@@ -224,8 +224,7 @@ struct usb_serial_driver {
        /* Called by console with tty = NULL and by tty */
        int  (*open)(struct tty_struct *tty,
                        struct usb_serial_port *port, struct file *filp);
-       void (*close)(struct tty_struct *tty,
-                       struct usb_serial_port *port, struct file *filp);
+       void (*close)(struct usb_serial_port *port);
        int  (*write)(struct tty_struct *tty, struct usb_serial_port *port,
                        const unsigned char *buf, int count);
        /* Called only by the tty layer */
@@ -241,6 +240,10 @@ struct usb_serial_driver {
        int  (*tiocmget)(struct tty_struct *tty, struct file *file);
        int  (*tiocmset)(struct tty_struct *tty, struct file *file,
                         unsigned int set, unsigned int clear);
+       /* Called by the tty layer for port level work. There may or may not
+          be an attached tty at this point */
+       void (*dtr_rts)(struct usb_serial_port *port, int on);
+       int  (*carrier_raised)(struct usb_serial_port *port);
        /* USB events */
        void (*read_int_callback)(struct urb *urb);
        void (*write_int_callback)(struct urb *urb);
@@ -283,8 +286,7 @@ extern int usb_serial_generic_open(struct tty_struct *tty,
                struct usb_serial_port *port, struct file *filp);
 extern int usb_serial_generic_write(struct tty_struct *tty,
        struct usb_serial_port *port, const unsigned char *buf, int count);
-extern void usb_serial_generic_close(struct tty_struct *tty,
-                       struct usb_serial_port *port, struct file *filp);
+extern void usb_serial_generic_close(struct usb_serial_port *port);
 extern int usb_serial_generic_resume(struct usb_serial *serial);
 extern int usb_serial_generic_write_room(struct tty_struct *tty);
 extern int usb_serial_generic_chars_in_buffer(struct tty_struct *tty);