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

Reply via email to