This is the uncertain part. It also addresses several problems, so, could 
also be further splitted, but this is just a draft anyway... I am not even 
signing-off for it.

Problem 1. Oops with ftdi_sio and "console=ttyUSB0." This is caused by 2 
NULL-pointer dereferences - port->tty in ftdi_open() and old_termios in 
ftdi_set_termios(). This is fixed by checking respective values, although 
Paul thinks, that the proper fix would be to supply dummy objects (at 
least the ->tty to ->open()), however, for some reason this doesn't work.

Problem 2. Missing carriage-returns on line-feeds in 
/drivers/usb/serial/console.c, this fix is completely from Paul.

Problem 3. Recursive error-messages on dongle-unplug, which render the 
system unusable. Here again, the proper solution would be to implement 
some usb_serial_console_disconnect() which would prevent sending output to 
a disconnected port. A possible implementation is also included below. 
Paul had a different version, whereby he was calling unregister_console(), 
which I was not sure about. Anyway, none of these disconnect() 
implementations alone suffice to fix the problem. What indeed fixes it is 
a check for (port->serial->dev->state == USB_STATE_NOTATTACHED) in 
usb_console_write(). Just in case the same check was added to 
serial_write() in drivers/usb/serial/usb-serial.c.

Now you see why - comments are welcome:-)

Thanks
Guennadi
P.S. Thanks to Paul Fulghum for the fixes, which did help me make my setup 
working stably (until I run into new bugs:-)).
---
Guennadi Liakhovetski

diff -u a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c
--- a/drivers/usb/serial/console.c      13 Jan 2005 21:09:08 -0000
+++ b/drivers/usb/serial/console.c      11 Apr 2006 18:03:29 -0000
@@ -202,7 +202,7 @@
        struct usb_serial *serial;
        int retval = -ENODEV;
 
-       if (!port)
+       if (!port || port->serial->dev->state == USB_STATE_NOTATTACHED)
                return;
        serial = port->serial;
 
@@ -213,17 +213,38 @@
 
        if (!port->open_count) {
                dbg ("%s - port not opened", __FUNCTION__);
-               goto exit;
+               return;
        }
 
-       /* pass on to the driver specific version of this function if it is 
available */
-       if (serial->type->write)
-               retval = serial->type->write(port, buf, count);
-       else
-               retval = usb_serial_generic_write(port, buf, count);
-
-exit:
-       dbg("%s - return value (if we had one): %d", __FUNCTION__, retval);
+       while (count) {
+               unsigned int i;
+               unsigned int lf;
+               /* search for LF so we can insert CR if necessary */
+               for (i=0, lf=0 ; i < count ; i++) {
+                       if (*(buf + i) == 10) {
+                               lf = 1;
+                               i++;
+                               break;
+                       }
+               }
+               /* pass on to the driver specific version of this function if 
it is available */
+               if (serial->type->write)
+                       retval = serial->type->write(port, buf, i);
+               else
+                       retval = usb_serial_generic_write(port, buf, i);
+               dbg("%s - return value : %d", __FUNCTION__, retval);
+               if (lf) {
+                       /* append CR after LF */
+                       unsigned char cr = 13;
+                       if (serial->type->write)
+                               retval = serial->type->write(port, &cr, 1);
+                       else
+                               retval = usb_serial_generic_write(port, &cr, 1);
+                       dbg("%s - return value : %d", __FUNCTION__, retval);
+               }
+               buf += i;
+               count -= i;
+       }
 }
 
 static struct console usbcons = {
@@ -234,6 +255,14 @@
        .index =        -1,
 };
 
+void usb_serial_console_disconnect(struct usb_serial *serial)
+{
+       if (serial && serial->port && serial->port[0] && serial->port[0] == 
usbcons_info.port) {
+               usbcons_info.port->open_count--;
+               usbcons_info.port = NULL;
+       }
+}
+
 void usb_serial_console_init (int serial_debug, int minor)
 {
        debug = serial_debug;
diff -u a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
--- a/drivers/usb/serial/ftdi_sio.c     30 Mar 2006 19:18:07 -0000
+++ b/drivers/usb/serial/ftdi_sio.c     11 Apr 2006 18:12:53 -0000
@@ -1254,7 +1254,6 @@
 
 static int  ftdi_open (struct usb_serial_port *port, struct file *filp)
 { /* ftdi_open */
-       struct termios tmp_termios;
        struct usb_device *dev = port->serial->dev;
        struct ftdi_private *priv = usb_get_serial_port_data(port);
        unsigned long flags;
@@ -1264,8 +1263,8 @@
 
        dbg("%s", __FUNCTION__);
 
-
-       port->tty->low_latency = (priv->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
+       if (port->tty)
+               port->tty->low_latency = (priv->flags & ASYNC_LOW_LATENCY) ? 1 
: 0;
 
        /* No error checking for this (will get errors later anyway) */
        /* See ftdi_sio.h for description of what is reset */
@@ -1279,7 +1278,8 @@
           This is same behaviour as serial.c/rs_open() - Kuba */
 
        /* ftdi_set_termios  will send usb control messages */
-       ftdi_set_termios(port, &tmp_termios);
+       if (port->tty)
+               ftdi_set_termios(port, NULL);
 
        /* FIXME: Flow control might be enabled, so it should be checked -
           we have no control of defaults! */
@@ -1860,7 +1860,7 @@
                        err("%s urb failed to set baudrate", __FUNCTION__);
                }
                /* Ensure RTS and DTR are raised when baudrate changed from 0 */
-               if ((old_termios->c_cflag & CBAUD) == B0) {
+               if (!old_termios || (old_termios->c_cflag & CBAUD) == B0) {
                        set_mctrl(port, TIOCM_DTR | TIOCM_RTS);
                }
        }
diff -u a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
--- a/drivers/usb/serial/usb-serial.c   30 Mar 2006 19:18:07 -0000
+++ b/drivers/usb/serial/usb-serial.c   11 Apr 2006 18:02:12 -0000
@@ -197,12 +197,12 @@
         
        ++port->open_count;
 
-       if (port->open_count == 1) {
+       /* set up our port structure making the tty driver
+        * remember our port object, and us it */
+       tty->driver_data = port;
+       port->tty = tty;
 
-               /* set up our port structure making the tty driver
-                * remember our port object, and us it */
-               tty->driver_data = port;
-               port->tty = tty;
+       if (port->open_count == 1) {
 
                /* lock this module before we call it
                 * this may fail, which means we must bail out,
@@ -271,7 +271,7 @@
        struct usb_serial_port *port = tty->driver_data;
        int retval = -EINVAL;
 
-       if (!port)
+       if (!port || port->serial->dev->state == USB_STATE_NOTATTACHED)
                goto exit;
 
        dbg("%s - port %d, %d byte(s)", __FUNCTION__, port->number, count);
@@ -982,6 +982,7 @@
        struct device *dev = &interface->dev;
        struct usb_serial_port *port;
 
+       usb_serial_console_disconnect(serial);
        dbg ("%s", __FUNCTION__);
 
        usb_set_intfdata (interface, NULL);
diff -u a/drivers/usb/serial/usb-serial.h b/drivers/usb/serial/usb-serial.h
--- a/drivers/usb/serial/usb-serial.h   30 Mar 2006 19:18:07 -0000
+++ b/drivers/usb/serial/usb-serial.h   11 Apr 2006 18:02:12 -0000
@@ -248,9 +248,11 @@
 #ifdef CONFIG_USB_SERIAL_CONSOLE
 extern void usb_serial_console_init (int debug, int minor);
 extern void usb_serial_console_exit (void);
+extern void usb_serial_console_disconnect(struct usb_serial *serial);
 #else
 static inline void usb_serial_console_init (int debug, int minor) { }
 static inline void usb_serial_console_exit (void) { }
+static inline void usb_serial_console_disconnect(struct usb_serial *serial) {}
 #endif
 
 /* Functions needed by other parts of the usbserial core */


-------------------------------------------------------
This SF.Net email is sponsored by xPML, a groundbreaking scripting language
that extends applications into web and mobile media. Attend the live webcast
and join the prime developer group breaking into this new coding territory!
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=110944&bid=241720&dat=121642
_______________________________________________
linux-usb-devel@lists.sourceforge.net
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to