buf = kmalloc(1, GFP_KERNEL);
        if (!buf) {
                dbg("error kmalloc");
+               *port->tty->termios = *old_termios;
                return;
        }
 
 
        
        dbg("%s", __func__);
 
-       for (i=0; i < serial->num_ports; ++i) {
+       for (i = 0; i < serial->num_ports; ++i) {
                usb_kill_urb(serial->port[i]->interrupt_in_urb);
                /* My special items, the standard routines free my urbs */
                kfree(usb_get_serial_port_data(serial->port[i]));
 
        if (count == 0) {
                dbg("%s - write request of 0 bytes", __func__);
-               return (0);
+               return 0;
        }
 
        spin_lock_bh(&port->lock);
 
        spin_lock_irqsave(&priv->lock, flags);
 
-       if( (count+priv->wrfilled)>sizeof(priv->wrbuf) ) {
+       if( (count+priv->wrfilled) > sizeof(priv->wrbuf) ) {
                /* To much data for buffer. Reset buffer. */
-               priv->wrfilled=0;
-               spin_unlock_irqrestore(&priv->lock, flags);
+               priv->wrfilled = 0;
                port->write_urb_busy = 0;
-               return (0);
+               spin_unlock_irqrestore(&priv->lock, flags);
+               return 0;
        }
 
        /* Copy data */
                if (result) {
                        err("%s - failed submitting write urb, error %d", __func__, result);
                        /* Throw away data. No better idea what to do with it. */
-                       priv->wrfilled=0;
-                       priv->wrsent=0;
+                       priv->wrfilled = 0;
+                       priv->wrsent = 0;
                        spin_unlock_irqrestore(&priv->lock, flags);
                        port->write_urb_busy = 0;
                        return 0;
                if( priv->wrsent>=priv->wrfilled ) {
                        dbg("%s - buffer cleaned", __func__);
                        memset( priv->wrbuf, 0, sizeof(priv->wrbuf) );
-                       priv->wrfilled=0;
-                       priv->wrsent=0;
+                       priv->wrfilled = 0;
+                       priv->wrsent = 0;
                }
        }
 
 
 static int cyberjack_write_room( struct usb_serial_port *port )
 {
+       /* FIXME: .... */
        return CYBERJACK_LOCAL_BUF_SIZE;
 }
 
        usb_serial_debug_data(debug, &port->dev, __func__, urb->actual_length, data);
 
        /* React only to interrupts signaling a bulk_in transfer */
-       if( (urb->actual_length==4) && (data[0]==0x01) ) {
+       if( (urb->actual_length == 4) && (data[0] == 0x01) ) {
                short old_rdtodo;
 
                /* This is a announcement of coming bulk_ins. */
                if (result) {
                        err("%s - failed submitting write urb, error %d", __func__, result);
                        /* Throw away data. No better idea what to do with it. */
-                       priv->wrfilled=0;
-                       priv->wrsent=0;
+                       priv->wrfilled = 0;
+                       priv->wrsent = 0;
                        goto exit;
                }
 
                if( (priv->wrsent>=priv->wrfilled) || (priv->wrsent>=blksize) ) {
                        dbg("%s - buffer cleaned", __func__);
                        memset( priv->wrbuf, 0, sizeof(priv->wrbuf) );
-                       priv->wrfilled=0;
-                       priv->wrsent=0;
+                       priv->wrfilled = 0;
+                       priv->wrsent = 0;
                }
        }
 
 
 
        dbg("%s - port %d", __func__, port->number);
 
+       /* FIXME: Locking */
        if (serial->num_bulk_out) {
                if (!(port->write_urb_busy))
                        room = port->bulk_out_size;
        }
 
        dbg("%s - returns %d", __func__, room);
-       return (room);
+       return room;
 }
 
 int usb_serial_generic_chars_in_buffer (struct usb_serial_port *port)
 
        dbg("%s - port %d", __func__, port->number);
 
+       /* FIXME: Locking */
        if (serial->num_bulk_out) {
                if (port->write_urb_busy)
                        chars = port->write_urb->transfer_buffer_length;
                    __func__, status);
                return;
        }
-
        usb_serial_port_softint(port);
 }
 EXPORT_SYMBOL_GPL(usb_serial_generic_write_bulk_callback);
 
        p_priv = usb_get_serial_port_data(port);
        d_details = p_priv->device_details;
 
+       /* FIXME: locking */
        if (d_details->msg_format == msg_usa90)
                data_len = 64;
        else
                        if (this_urb->status != -EINPROGRESS)
                                return (data_len);
        }
-       return (0);
+       return 0;
 }
 
 
 static int keyspan_chars_in_buffer (struct usb_serial_port *port)
 {
-       return (0);
+       return 0;
 }
 
 
        //mdelay(100);
        //keyspan_set_termios(port, NULL);
 
-       return (0);
+       return 0;
 }
 
 static inline void stop_urb(struct urb *urb)
        }
 #endif
 
-       return (0);
+       return 0;
 }
 
 static int keyspan_usa28_send_setup(struct usb_serial *serial,
        }
 #endif
 
-       return (0);
+       return 0;
 }
 
 static int keyspan_usa49_send_setup(struct usb_serial *serial,
        }
 #endif
 
-       return (0);
+       return 0;
 }
 
 static int keyspan_usa90_send_setup(struct usb_serial *serial,
        if ((err = usb_submit_urb(this_urb, GFP_ATOMIC)) != 0) {
                dbg("%s - usb_submit_urb(setup) failed (%d)", __func__, err);
        }
-       return (0);
+       return 0;
 }
 
 static int keyspan_usa67_send_setup(struct usb_serial *serial,
        if (err != 0)
                dbg("%s - usb_submit_urb(setup) failed (%d)", __func__,
                                err);
-       return (0);
+       return 0;
 }
 
 static void keyspan_send_setup(struct usb_serial_port *port, int reset_port)
                                err);
        }
                        
-       return (0);
+       return 0;
 }
 
 static void keyspan_shutdown (struct usb_serial *serial)
 
 static int keyspan_pda_chars_in_buffer (struct usb_serial_port *port)
 {
        struct keyspan_pda_private *priv;
+       unsigned long flags;
+       int ret = 0;
 
        priv = usb_get_serial_port_data(port);
 
        /* when throttled, return at least WAKEUP_CHARS to tell select() (via
           n_tty.c:normal_poll() ) that we're not writeable. */
+
+       spin_lock_irqsave(&port->lock, flags);
        if (port->write_urb_busy || priv->tx_throttled)
-               return 256;
-       return 0;
+               ret = 256;
+       spin_unlock_irqrestore(&port->lock, flags);
+       return ret;
 }
 
 
 
                                  struct ktermios *old_termios)
 {
        struct klsi_105_private *priv = usb_get_serial_port_data(port);
-       unsigned int iflag = port->tty->termios->c_iflag;
+       struct tty_struct *tty = port->tty;
+       unsigned int iflag = tty->termios->c_iflag;
        unsigned int old_iflag = old_termios->c_iflag;
-       unsigned int cflag = port->tty->termios->c_cflag;
+       unsigned int cflag = tty->termios->c_cflag;
        unsigned int old_cflag = old_termios->c_cflag;
        struct klsi_105_port_settings cfg;
        unsigned long flags;
+       speed_t baud;
        
        /* lock while we are modifying the settings */
        spin_lock_irqsave (&priv->lock, flags);
        /*
         * Update baud rate
         */
+       baud = tty_get_baud_rate(tty);
+
        if( (cflag & CBAUD) != (old_cflag & CBAUD) ) {
                /* reassert DTR and (maybe) RTS on transition from B0 */
                if( (old_cflag & CBAUD) == B0 ) {
                        mct_u232_set_modem_ctrl(serial, priv->control_state);
 #endif
                }
-               
-               switch(tty_get_baud_rate(port->tty)) {
+       }
+       switch(baud) {
                case 0: /* handled below */
                        break;
                case 1200:
                        priv->cfg.baudrate = kl5kusb105a_sio_b115200;
                        break;
                default:
-                       err("KLSI USB->Serial converter:"
+                       dbg("KLSI USB->Serial converter:"
                            " unsupported baudrate request, using default"
                            " of 9600");
                        priv->cfg.baudrate = kl5kusb105a_sio_b9600;
+                       baud = 9600;
                        break;
-               }
-               if ((cflag & CBAUD) == B0 ) {
-                       dbg("%s: baud is B0", __func__);
-                       /* Drop RTS and DTR */
-                       /* maybe this should be simulated by sending read
-                        * disable and read enable messages?
-                        */
-                       ;
+       }
+       if ((cflag & CBAUD) == B0 ) {
+               dbg("%s: baud is B0", __func__);
+               /* Drop RTS and DTR */
+               /* maybe this should be simulated by sending read
+                * disable and read enable messages?
+                */
+               ;
 #if 0
-                       priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS);
-                       mct_u232_set_modem_ctrl(serial, priv->control_state);
+               priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS);
+                       mct_u232_set_modem_ctrl(serial, priv->control_state);
 #endif
-               }
        }
+       tty_encode_baud_rate(tty, baud, baud);
 
        if ((cflag & CSIZE) != (old_cflag & CSIZE)) {
                /* set the number of data bits */
        if ((cflag & (PARENB|PARODD)) != (old_cflag & (PARENB|PARODD))
            || (cflag & CSTOPB) != (old_cflag & CSTOPB) ) {
                
+               /* Not currently supported */
+               tty->termios->c_cflag &= ~(PARENB|PARODD|CSTOPB);
 #if 0
                priv->last_lcr = 0;
 
            || (iflag & IXON) != (old_iflag & IXON)
            ||  (cflag & CRTSCTS) != (old_cflag & CRTSCTS) ) {
                
+               /* Not currently supported */
+               tty->termios->c_cflag &= ~CRTSCTS;
                /* Drop DTR/RTS if no flow control otherwise assert */
 #if 0
                if ((iflag & IXOFF) || (iflag & IXON) || (cflag & CRTSCTS) )
 
                return -ENODEV;
        }
 
+       /* FIXME: Locking */
        for (i = 0; i < NUM_URBS; ++i) {
                if (mos7720_port->write_urb_pool[i] && mos7720_port->write_urb_pool[i]->status != -EINPROGRESS)
                        room += URB_TRANSFER_BUFFER_SIZE;
 
  *     This program is free software; you can redistribute it and/or
  *     modify it under the terms of the GNU General Public License
  *     version 2 as published by the Free Software Foundation.
+ *
+ * TODO:
+ *     Add termios method that uses copy_hw but also kills all echo
+ *     flags as the navman is rx only so cannot echo.
  */
 
 #include <linux/kernel.h>
 
        /*
         * This device can't write any data, only read from the device
-        * so we just silently eat all data sent to us and say it was
-        * successfully sent.
-        * Evil, I know, but do you have a better idea?
         */
-
-       return count;
+       return -EOPNOTSUPP;
 }
 
 static struct usb_serial_driver navman_device = {
 
        struct usb_serial       *serial = port->serial;
        struct usb_serial_port  *wport  = serial->port[1];
 
-       int room = 0; // Default: no room
+       int room = 0; /* Default: no room */
 
+       /* FIXME: no consistent locking for write_urb_busy */
        if (wport->write_urb_busy)
                room = wport->bulk_out_size - OMNINET_HEADERLEN;
 
 
 
        portdata = usb_get_serial_port_data(port);
 
+
        for (i=0; i < N_OUT_URB; i++) {
                this_urb = portdata->out_urbs[i];
                if (this_urb && !test_bit(i, &portdata->out_busy))
 
        for (i=0; i < N_OUT_URB; i++) {
                this_urb = portdata->out_urbs[i];
+               /* FIXME: This locking is insufficient as this_urb may
+                  go unused during the test */
                if (this_urb && test_bit(i, &portdata->out_busy))
                        data_len += this_urb->transfer_buffer_length;
        }
 
        buf = kzalloc(7, GFP_KERNEL);
        if (!buf) {
                dev_err(&port->dev, "%s - out of memory.\n", __func__);
+               /* Report back no change occurred */
+               *port->tty->termios = *old_termios;
                return;
        }
 
 
        struct usb_serial_port *port = (struct usb_serial_port *) urb->context;
        unsigned char *data = urb->transfer_buffer;
        unsigned char length = urb->actual_length;
-       int i;
        int result;
        int status = urb->status;
 
        if (safe) {
                __u16 fcs;
                if (!(fcs = fcs_compute10 (data, length, CRC10_INITFCS))) {
-
                        int actual_length = data[length - 2] >> 2;
-
                        if (actual_length <= (length - 2)) {
-
                                info ("%s - actual: %d", __func__, actual_length);
-
-                               for (i = 0; i < actual_length; i++) {
-                                       tty_insert_flip_char (port->tty, data[i], 0);
-                               }
+                               tty_insert_flip_string(port->tty, data, actual_length);
                                tty_flip_buffer_push (port->tty);
                        } else {
                                err ("%s - inconsistent lengths %d:%d", __func__,
                        err ("%s - bad CRC %x", __func__, fcs);
                }
        } else {
-               for (i = 0; i < length; i++) {
-                       tty_insert_flip_char (port->tty, data[i], 0);
-               }
+               tty_insert_flip_string(port->tty, data, length);
                tty_flip_buffer_push (port->tty);
        }
 
 
        if ((result = usb_submit_urb (urb, GFP_ATOMIC))) {
                err ("%s - failed resubmitting read urb, error %d", __func__, result);
+               /* FIXME: Need a mechanism to retry later if this happens */
        }
 }
 
 
        if (!port->write_urb) {
                dbg ("%s - write urb NULL", __func__);
-               return (0);
+               return 0;
        }
 
        dbg ("safe_write write_urb: %d transfer_buffer_length",
 
        if (!port->write_urb->transfer_buffer_length) {
                dbg ("%s - write urb transfer_buffer_length zero", __func__);
-               return (0);
+               return 0;
        }
        if (count == 0) {
                dbg ("%s - write request of 0 bytes", __func__);
-               return (0);
+               return 0;
        }
        spin_lock_bh(&port->lock);
        if (port->write_urb_busy) {
 
 static int safe_write_room (struct usb_serial_port *port)
 {
-       int room = 0;           // Default: no room
+       int room = 0;           /* Default: no room */
+       unsigned long flags;
 
        dbg ("%s", __func__);
 
+       spin_lock_irqsave(&port->lock, flags);
        if (port->write_urb_busy)
                room = port->bulk_out_size - (safe ? 2 : 0);
+       spin_unlock_irqrestore(&port->lock, flags);
 
        if (room) {
                dbg ("safe_write_room returns %d", room);
        }
 
-       return (room);
+       return room;
 }
 
 static int safe_startup (struct usb_serial *serial)
 
         * have sent out, but hasn't made it through to the
         * device as we can't see the backend here, so just
         * tell the tty layer that everything is flushed.
+        *
+        * FIXME: should walk the outstanding urbs info
         */
        return 0;
 }
 
        usb_serial_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
        usb_serial_tty_driver->init_termios = tty_std_termios;
        usb_serial_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
+       usb_serial_tty_driver->init_termios.c_ispeed = 9600;
+       usb_serial_tty_driver->init_termios.c_ospeed = 9600;
        tty_set_operations(usb_serial_tty_driver, &serial_ops);
        result = tty_register_driver(usb_serial_tty_driver);
        if (result) {
 
         * have sent out, but hasn't made it through to the
         * device, so just tell the tty layer that everything
         * is flushed.
+        *
+        * FIXME: Should walk outstanding_urbs
         */
        return 0;
 }
 
 struct whiteheat_private {
        spinlock_t              lock;
        __u8                    flags;
-       __u8                    mcr;
+       __u8                    mcr;            /* FIXME: no locking on mcr */
        struct list_head        rx_urbs_free;
        struct list_head        rx_urbs_submitted;
        struct list_head        rx_urb_q;