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