USB: kobil_sct: Rework driver
authorAlan Cox <alan@lxorguk.ukuu.org.uk>
Wed, 22 Aug 2007 22:09:16 +0000 (23:09 +0100)
committerGreg Kroah-Hartman <gregkh@suse.de>
Fri, 12 Oct 2007 21:55:20 +0000 (14:55 -0700)
No hardware but this driver is currently totally broken so we can't make
it much worse. Remove all tbe broken invalid termios handling and replace
it with a proper set_termios method.

Signed-off-by: Alan Cox <alan@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/usb/serial/kobil_sct.c

index 02a86dbc0e9759673000eeb4521a8d0bafabc5ed..6f224195bd25a6048efc65cc26f9b197d6f87a70 100644 (file)
@@ -82,6 +82,7 @@ static int  kobil_tiocmset(struct usb_serial_port *port, struct file *file,
                           unsigned int set, unsigned int clear);
 static void kobil_read_int_callback( struct urb *urb );
 static void kobil_write_callback( struct urb *purb );
+static void kobil_set_termios(struct usb_serial_port *port, struct ktermios *old);
 
 
 static struct usb_device_id id_table [] = {
@@ -119,6 +120,7 @@ static struct usb_serial_driver kobil_device = {
        .attach =               kobil_startup,
        .shutdown =             kobil_shutdown,
        .ioctl =                kobil_ioctl,
+       .set_termios =          kobil_set_termios,
        .tiocmget =             kobil_tiocmget,
        .tiocmset =             kobil_tiocmset,
        .open =                 kobil_open,
@@ -137,7 +139,6 @@ struct kobil_private {
        int cur_pos; // index of the next char to send in buf
        __u16 device_type;
        int line_state;
-       struct ktermios internal_termios;
 };
 
 
@@ -216,7 +217,7 @@ static void kobil_shutdown (struct usb_serial *serial)
 
 static int kobil_open (struct usb_serial_port *port, struct file *filp)
 {
-       int i, result = 0;
+       int result = 0;
        struct kobil_private *priv;
        unsigned char *transfer_buffer;
        int transfer_buffer_length = 8;
@@ -242,16 +243,6 @@ static int kobil_open (struct usb_serial_port *port, struct file *filp)
        port->tty->termios->c_iflag = IGNBRK | IGNPAR | IXOFF;
        port->tty->termios->c_oflag &= ~ONLCR; // do NOT translate CR to CR-NL (0x0A -> 0x0A 0x0D)
        
-       // set up internal termios structure 
-       priv->internal_termios.c_iflag = port->tty->termios->c_iflag;
-       priv->internal_termios.c_oflag = port->tty->termios->c_oflag;
-       priv->internal_termios.c_cflag = port->tty->termios->c_cflag;
-       priv->internal_termios.c_lflag = port->tty->termios->c_lflag;
-
-       for (i=0; i<NCCS; i++) {
-               priv->internal_termios.c_cc[i] = port->tty->termios->c_cc[i];
-       }
-       
        // allocate memory for transfer buffer
        transfer_buffer = kzalloc(transfer_buffer_length, GFP_KERNEL);
        if (! transfer_buffer) {
@@ -607,102 +598,79 @@ static int  kobil_tiocmset(struct usb_serial_port *port, struct file *file,
        return (result < 0) ? result : 0;
 }
 
-
-static int  kobil_ioctl(struct usb_serial_port *port, struct file *file,
-                       unsigned int cmd, unsigned long arg)
+static void kobil_set_termios(struct usb_serial_port *port, struct ktermios *old)
 {
        struct kobil_private * priv;
        int result;
        unsigned short urb_val = 0;
-       unsigned char *transfer_buffer;
-       int transfer_buffer_length = 8;
-       char *settings;
-       void __user *user_arg = (void __user *)arg;
+       int c_cflag = port->tty->termios->c_cflag;
+       speed_t speed;
+       void * settings;
 
        priv = usb_get_serial_port_data(port);
-       if ((priv->device_type == KOBIL_USBTWIN_PRODUCT_ID) || (priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID)) {
+       if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID || priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID)
                // This device doesn't support ioctl calls
-               return 0;
-       }
-
-       switch (cmd) {
-       case TCGETS:   // 0x5401
-               if (!access_ok(VERIFY_WRITE, user_arg, sizeof(struct ktermios))) {
-                       dbg("%s - port %d Error in access_ok", __FUNCTION__, port->number);
-                       return -EFAULT;
-               }
-               if (kernel_termios_to_user_termios((struct ktermios __user *)arg,
-                                                  &priv->internal_termios))
-                       return -EFAULT;
-               return 0;
-
-       case TCSETS:   // 0x5402
-               if (!(port->tty->termios)) {
-                       dbg("%s - port %d Error: port->tty->termios is NULL", __FUNCTION__, port->number);
-                       return -ENOTTY;
-               }
-               if (!access_ok(VERIFY_READ, user_arg, sizeof(struct ktermios))) {
-                       dbg("%s - port %d Error in access_ok", __FUNCTION__, port->number);
-                       return -EFAULT;
-               }
-               if (user_termios_to_kernel_termios(&priv->internal_termios,
-                                                  (struct ktermios __user *)arg))
-                       return -EFAULT;
-               
-               settings = kzalloc(50, GFP_KERNEL);
-               if (! settings) {
-                       return -ENOBUFS;
-               }
+               return;
 
-               switch (priv->internal_termios.c_cflag & CBAUD) {
-               case B1200:
+       switch (speed = tty_get_baud_rate(port->tty)) {
+               case 1200:
                        urb_val = SUSBCR_SBR_1200;
-                       strcat(settings, "1200 ");
                        break;
-               case B9600:
+               case 9600:
                default:
                        urb_val = SUSBCR_SBR_9600;
-                       strcat(settings, "9600 ");
                        break;
-               }
+       }
+       urb_val |= (c_cflag & CSTOPB) ? SUSBCR_SPASB_2StopBits : SUSBCR_SPASB_1StopBit;
+
+       settings = kzalloc(50, GFP_KERNEL);
+       if (! settings)
+               return;
 
-               urb_val |= (priv->internal_termios.c_cflag & CSTOPB) ? SUSBCR_SPASB_2StopBits : SUSBCR_SPASB_1StopBit;
-               strcat(settings, (priv->internal_termios.c_cflag & CSTOPB) ? "2 StopBits " : "1 StopBit ");
+       sprintf(settings, "%d ", speed);
 
-               if (priv->internal_termios.c_cflag & PARENB) {
-                       if  (priv->internal_termios.c_cflag & PARODD) {
-                               urb_val |= SUSBCR_SPASB_OddParity;
-                               strcat(settings, "Odd Parity");
-                       } else {
-                               urb_val |= SUSBCR_SPASB_EvenParity;
-                               strcat(settings, "Even Parity");
-                       }
+       if (c_cflag & PARENB) {
+               if  (c_cflag & PARODD) {
+                       urb_val |= SUSBCR_SPASB_OddParity;
+                       strcat(settings, "Odd Parity");
                } else {
-                       urb_val |= SUSBCR_SPASB_NoParity;
-                       strcat(settings, "No Parity");
+                       urb_val |= SUSBCR_SPASB_EvenParity;
+                       strcat(settings, "Even Parity");
                }
-               dbg("%s - port %d setting port to: %s", __FUNCTION__, port->number, settings );
+       } else {
+               urb_val |= SUSBCR_SPASB_NoParity;
+               strcat(settings, "No Parity");
+       }
 
-               result = usb_control_msg( port->serial->dev, 
-                                         usb_rcvctrlpipe(port->serial->dev, 0 ), 
-                                         SUSBCRequest_SetBaudRateParityAndStopBits,
-                                         USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT,
-                                         urb_val,
-                                         0,
-                                         settings,
-                                         0,
-                                         KOBIL_TIMEOUT
-                       );
+       result = usb_control_msg( port->serial->dev,
+                                 usb_rcvctrlpipe(port->serial->dev, 0 ),
+                                 SUSBCRequest_SetBaudRateParityAndStopBits,
+                                 USB_TYPE_VENDOR | USB_RECIP_ENDPOINT | USB_DIR_OUT,
+                                 urb_val,
+                                 0,
+                                 settings,
+                                 0,
+                                 KOBIL_TIMEOUT
+               );
+       kfree(settings);
+}
 
-               dbg("%s - port %d Send set_baudrate URB returns: %i", __FUNCTION__, port->number, result);
-               kfree(settings);
+static int kobil_ioctl(struct usb_serial_port *port, struct file * file, unsigned int cmd, unsigned long arg)
+{
+       struct kobil_private * priv = usb_get_serial_port_data(port);
+       unsigned char *transfer_buffer;
+       int transfer_buffer_length = 8;
+       int result;
+
+       if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID || priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID)
+               // This device doesn't support ioctl calls
                return 0;
 
+       switch (cmd) {
        case TCFLSH:   // 0x540B
                transfer_buffer = kmalloc(transfer_buffer_length, GFP_KERNEL);
-               if (! transfer_buffer) {
+               if (! transfer_buffer)
                        return -ENOBUFS;
-               }
 
                result = usb_control_msg( port->serial->dev, 
                                          usb_rcvctrlpipe(port->serial->dev, 0 ), 
@@ -716,15 +684,13 @@ static int  kobil_ioctl(struct usb_serial_port *port, struct file *file,
                        );
                
                dbg("%s - port %d Send reset_all_queues (FLUSH) URB returns: %i", __FUNCTION__, port->number, result);
-
                kfree(transfer_buffer);
-               return ((result < 0) ? -EFAULT : 0);
-
+               return (result < 0) ? -EFAULT : 0;
+       default:
+               return -ENOIOCTLCMD;
        }
-       return -ENOIOCTLCMD;
 }
 
-
 static int __init kobil_init (void)
 {
        int retval;