On Fri, 2006-04-07 at 22:10 +0200, Guennadi Liakhovetski wrote: > Yep, that would work, I first didn't look at that code too attentively as > I didn't want to do any such "intrusive" changes. Would you then remove > the call to serial->type->set_termios(port, NULL);? Do all usb-serial > drivers call their set_termios methods inside ->open()? If this is the > case, one wouldn't need to check for NULL second parameter in > ->set_termios().
I don't think you can count on all device specific drivers calling set_termios in open, so I would leave it. > BTW, just noticed - there's another bug in ftdi_sio: they > call ftdi_set_termios() in ftdi_open() with a __uninitialised__ temporary > struct termios tmp_termios; and then test it: (old_termios->c_cflag & > CBAUD) == B0... So, you might fix that as well with your new patch. Yes, that is a bug. console.c calls it with old_termios set to NULL so I guess all usb serial set_termios implementations must deal with NULL Maybe the best solution is to remove tmp_termios from ftdi_open and replace that with NULL, and put the check for old_termios == NULL in ftdi_set_termios like you had in your patch. Try this patch: --- linux-2.6.16/drivers/usb/serial/usb-serial.c 2006-03-19 23:53:29.000000000 -0600 +++ b/drivers/usb/serial/usb-serial.c 2006-04-07 14:42:48.000000000 -0500 @@ -197,12 +197,12 @@ static int serial_open (struct tty_struc ++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, --- linux-2.6.16/drivers/usb/serial/console.c 2006-03-19 23:53:29.000000000 -0600 +++ b/drivers/usb/serial/console.c 2006-04-07 15:28:23.000000000 -0500 @@ -148,6 +148,25 @@ static int __init usb_console_setup(stru info->port = port; + /* build up a fake tty structure so that the open call has something + * to look at to get the cflag value */ + tty = kmalloc (sizeof (*tty), GFP_KERNEL); + if (!tty) { + err ("no more memory"); + return -ENOMEM; + } + termios = kmalloc (sizeof (*termios), GFP_KERNEL); + if (!termios) { + err ("no more memory"); + kfree (tty); + return -ENOMEM; + } + memset (tty, 0x00, sizeof(*tty)); + memset (termios, 0x00, sizeof(*termios)); + termios->c_cflag = cflag; + tty->termios = termios; + port->tty = tty; + ++port->open_count; if (port->open_count == 1) { /* only call the device specific open if this @@ -156,42 +175,22 @@ static int __init usb_console_setup(stru retval = serial->type->open(port, NULL); else retval = usb_serial_generic_open(port, NULL); - if (retval) + if (retval) { port->open_count = 0; - } - - if (retval) { - err ("could not open USB console port"); - return retval; + err ("could not open USB console port"); + goto exit; + } } if (serial->type->set_termios) { - /* build up a fake tty structure so that the open call has something - * to look at to get the cflag value */ - tty = kmalloc (sizeof (*tty), GFP_KERNEL); - if (!tty) { - err ("no more memory"); - return -ENOMEM; - } - termios = kmalloc (sizeof (*termios), GFP_KERNEL); - if (!termios) { - err ("no more memory"); - kfree (tty); - return -ENOMEM; - } - memset (tty, 0x00, sizeof(*tty)); - memset (termios, 0x00, sizeof(*termios)); - termios->c_cflag = cflag; - tty->termios = termios; - port->tty = tty; /* set up the initial termios settings */ serial->type->set_termios(port, NULL); - port->tty = NULL; - kfree (termios); - kfree (tty); } - +exit: + port->tty = NULL; + kfree (termios); + kfree (tty); return retval; } @@ -200,7 +199,6 @@ static void usb_console_write(struct con static struct usbcons_info *info = &usbcons_info; struct usb_serial_port *port = info->port; struct usb_serial *serial; - int retval = -ENODEV; if (!port) return; @@ -216,11 +214,33 @@ static void usb_console_write(struct con goto exit; } - /* 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); + 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) + serial->type->write(port, buf, i); + else + usb_serial_generic_write(port, buf, i); + if (lf) { + /* append CR after LF */ + unsigned char cr = 13; + if (serial->type->write) + serial->type->write(port, &cr, 1); + else + usb_serial_generic_write(port, &cr, 1); + } + buf += i; + count -= i; + } exit: dbg("%s - return value (if we had one): %d", __FUNCTION__, retval); --- linux-2.6.16/drivers/usb/serial/ftdi_sio.c 2006-03-19 23:53:29.000000000 -0600 +++ b/drivers/usb/serial/ftdi_sio.c 2006-04-07 16:04:16.000000000 -0500 @@ -1254,7 +1254,6 @@ static void ftdi_shutdown (struct usb_se 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; @@ -1279,7 +1278,7 @@ static int ftdi_open (struct usb_serial This is same behaviour as serial.c/rs_open() - Kuba */ /* ftdi_set_termios will send usb control messages */ - ftdi_set_termios(port, &tmp_termios); + ftdi_set_termios(port, NULL); /* FIXME: Flow control might be enabled, so it should be checked - we have no control of defaults! */ @@ -1860,7 +1859,7 @@ static void ftdi_set_termios (struct usb 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); } } ------------------------------------------------------- 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