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
_______________________________________________
[email protected]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel