]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/usb/serial/kobil_sct.c
Merge branch 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/aegl/linux-2.6
[linux-2.6-omap-h63xx.git] / drivers / usb / serial / kobil_sct.c
index 02a86dbc0e9759673000eeb4521a8d0bafabc5ed..693f00da7c038b0072d360b031479c0f1a30bea5 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 [] = {
@@ -112,13 +113,11 @@ static struct usb_serial_driver kobil_device = {
        .description =          "KOBIL USB smart card terminal",
        .usb_driver =           &kobil_driver,
        .id_table =             id_table,
-       .num_interrupt_in =     NUM_DONT_CARE,
-       .num_bulk_in =          0,
-       .num_bulk_out =         0,
        .num_ports =            1,
        .attach =               kobil_startup,
        .shutdown =             kobil_shutdown,
        .ioctl =                kobil_ioctl,
+       .set_termios =          kobil_set_termios,
        .tiocmget =             kobil_tiocmget,
        .tiocmset =             kobil_tiocmset,
        .open =                 kobil_open,
@@ -136,8 +135,6 @@ struct kobil_private {
        int filled;  // index of the last char in buf
        int cur_pos; // index of the next char to send in buf
        __u16 device_type;
-       int line_state;
-       struct ktermios internal_termios;
 };
 
 
@@ -159,7 +156,6 @@ static int kobil_startup (struct usb_serial *serial)
        priv->filled = 0;
        priv->cur_pos = 0;
        priv->device_type = le16_to_cpu(serial->dev->descriptor.idProduct);
-       priv->line_state = 0;
 
        switch (priv->device_type){
        case KOBIL_ADAPTER_B_PRODUCT_ID:
@@ -187,11 +183,11 @@ static int kobil_startup (struct usb_serial *serial)
        for (i = 0; i < altsetting->desc.bNumEndpoints; i++) {
                endpoint = &altsetting->endpoint[i];
                if (usb_endpoint_is_int_out(&endpoint->desc)) {
-                       dbg("%s Found interrupt out endpoint. Address: %d", __FUNCTION__, endpoint->desc.bEndpointAddress);
+                       dbg("%s Found interrupt out endpoint. Address: %d", __func__, endpoint->desc.bEndpointAddress);
                        priv->write_int_endpoint_address = endpoint->desc.bEndpointAddress;
                }
                if (usb_endpoint_is_int_in(&endpoint->desc)) {
-                       dbg("%s Found interrupt in  endpoint. Address: %d", __FUNCTION__, endpoint->desc.bEndpointAddress);
+                       dbg("%s Found interrupt in  endpoint. Address: %d", __func__, endpoint->desc.bEndpointAddress);
                        priv->read_int_endpoint_address = endpoint->desc.bEndpointAddress;
                }
        }
@@ -202,7 +198,7 @@ static int kobil_startup (struct usb_serial *serial)
 static void kobil_shutdown (struct usb_serial *serial)
 {
        int i;
-       dbg("%s - port %d", __FUNCTION__, serial->port[0]->number);
+       dbg("%s - port %d", __func__, serial->port[0]->number);
 
        for (i=0; i < serial->num_ports; ++i) {
                while (serial->port[i]->open_count > 0) {
@@ -216,15 +212,14 @@ 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;
        int write_urb_transfer_buffer_length = 8;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
        priv = usb_get_serial_port_data(port);
-       priv->line_state = 0;
 
        // someone sets the dev to 0 if the close method has been called
        port->interrupt_in_urb->dev = port->serial->dev;
@@ -242,16 +237,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) {
@@ -260,10 +245,10 @@ static int kobil_open (struct usb_serial_port *port, struct file *filp)
        
        // allocate write_urb
        if (!port->write_urb) { 
-               dbg("%s - port %d  Allocating port->write_urb", __FUNCTION__, port->number);
+               dbg("%s - port %d  Allocating port->write_urb", __func__, port->number);
                port->write_urb = usb_alloc_urb(0, GFP_KERNEL);  
                if (!port->write_urb) {
-                       dbg("%s - port %d usb_alloc_urb failed", __FUNCTION__, port->number);
+                       dbg("%s - port %d usb_alloc_urb failed", __func__, port->number);
                        kfree(transfer_buffer);
                        return -ENOMEM;
                }
@@ -289,7 +274,7 @@ static int kobil_open (struct usb_serial_port *port, struct file *filp)
                                  transfer_buffer_length,
                                  KOBIL_TIMEOUT
                );
-       dbg("%s - port %d Send get_HW_version URB returns: %i", __FUNCTION__, port->number, result);
+       dbg("%s - port %d Send get_HW_version URB returns: %i", __func__, port->number, result);
        dbg("Harware version: %i.%i.%i", transfer_buffer[0], transfer_buffer[1], transfer_buffer[2] );
        
        // get firmware version
@@ -303,7 +288,7 @@ static int kobil_open (struct usb_serial_port *port, struct file *filp)
                                  transfer_buffer_length,
                                  KOBIL_TIMEOUT
                );
-       dbg("%s - port %d Send get_FW_version URB returns: %i", __FUNCTION__, port->number, result);
+       dbg("%s - port %d Send get_FW_version URB returns: %i", __func__, port->number, result);
        dbg("Firmware version: %i.%i.%i", transfer_buffer[0], transfer_buffer[1], transfer_buffer[2] );
 
        if (priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID || priv->device_type == KOBIL_ADAPTER_K_PRODUCT_ID) {
@@ -318,7 +303,7 @@ static int kobil_open (struct usb_serial_port *port, struct file *filp)
                                          0,
                                          KOBIL_TIMEOUT
                        );
-               dbg("%s - port %d Send set_baudrate URB returns: %i", __FUNCTION__, port->number, result);
+               dbg("%s - port %d Send set_baudrate URB returns: %i", __func__, port->number, result);
                
                // reset all queues
                result = usb_control_msg( port->serial->dev, 
@@ -331,13 +316,13 @@ static int kobil_open (struct usb_serial_port *port, struct file *filp)
                                          0,
                                          KOBIL_TIMEOUT
                        );
-               dbg("%s - port %d Send reset_all_queues URB returns: %i", __FUNCTION__, port->number, result);
+               dbg("%s - port %d Send reset_all_queues URB returns: %i", __func__, port->number, result);
        }
        if (priv->device_type == KOBIL_USBTWIN_PRODUCT_ID || priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID ||
            priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID) {
                // start reading (Adapter B 'cause PNP string)
                result = usb_submit_urb( port->interrupt_in_urb, GFP_ATOMIC  ); 
-               dbg("%s - port %d Send read URB returns: %i", __FUNCTION__, port->number, result);
+               dbg("%s - port %d Send read URB returns: %i", __func__, port->number, result);
        }
 
        kfree(transfer_buffer);
@@ -347,7 +332,7 @@ static int kobil_open (struct usb_serial_port *port, struct file *filp)
 
 static void kobil_close (struct usb_serial_port *port, struct file *filp)
 {
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        if (port->write_urb) {
                usb_kill_urb(port->write_urb);
@@ -367,11 +352,11 @@ static void kobil_read_int_callback(struct urb *urb)
        int status = urb->status;
 //     char *dbg_data;
 
-       dbg("%s - port %d", __FUNCTION__, port->number);
+       dbg("%s - port %d", __func__, port->number);
 
        if (status) {
                dbg("%s - port %d Read int status not zero: %d",
-                   __FUNCTION__, port->number, status);
+                   __func__, port->number, status);
                return;
        }
 
@@ -401,7 +386,7 @@ static void kobil_read_int_callback(struct urb *urb)
        port->interrupt_in_urb->dev = port->serial->dev;
 
        result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
-       dbg("%s - port %d Send read URB returns: %i", __FUNCTION__, port->number, result);
+       dbg("%s - port %d Send read URB returns: %i", __func__, port->number, result);
 }
 
 
@@ -419,21 +404,21 @@ static int kobil_write (struct usb_serial_port *port,
        struct kobil_private * priv;
 
        if (count == 0) {
-               dbg("%s - port %d write request of 0 bytes", __FUNCTION__, port->number);
+               dbg("%s - port %d write request of 0 bytes", __func__, port->number);
                return 0;
        }
 
        priv = usb_get_serial_port_data(port);
 
        if (count > (KOBIL_BUF_LENGTH - priv->filled)) {
-               dbg("%s - port %d Error: write request bigger than buffer size", __FUNCTION__, port->number);
+               dbg("%s - port %d Error: write request bigger than buffer size", __func__, port->number);
                return -ENOMEM;
        }
 
        // Copy data to buffer
        memcpy (priv->buf + priv->filled, buf, count);
 
-       usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, priv->buf + priv->filled);
+       usb_serial_debug_data(debug, &port->dev, __func__, count, priv->buf + priv->filled);
 
        priv->filled = priv->filled + count;
 
@@ -465,7 +450,7 @@ static int kobil_write (struct usb_serial_port *port,
 
                        priv->cur_pos = priv->cur_pos + length;
                        result = usb_submit_urb( port->write_urb, GFP_NOIO );
-                       dbg("%s - port %d Send write URB returns: %i", __FUNCTION__, port->number, result);
+                       dbg("%s - port %d Send write URB returns: %i", __func__, port->number, result);
                        todo = priv->filled - priv->cur_pos;
 
                        if (todo > 0) {
@@ -486,7 +471,7 @@ static int kobil_write (struct usb_serial_port *port,
                        port->interrupt_in_urb->dev = port->serial->dev;
                        
                        result = usb_submit_urb( port->interrupt_in_urb, GFP_NOIO ); 
-                       dbg("%s - port %d Send read URB returns: %i", __FUNCTION__, port->number, result);
+                       dbg("%s - port %d Send read URB returns: %i", __func__, port->number, result);
                }
        }
        return count;
@@ -495,7 +480,7 @@ static int kobil_write (struct usb_serial_port *port,
 
 static int kobil_write_room (struct usb_serial_port *port)
 {
-       //dbg("%s - port %d", __FUNCTION__, port->number);
+       //dbg("%s - port %d", __func__, port->number);
        return 8;
 }
 
@@ -530,16 +515,13 @@ static int kobil_tiocmget(struct usb_serial_port *port, struct file *file)
                                  KOBIL_TIMEOUT);
 
        dbg("%s - port %d Send get_status_line_state URB returns: %i. Statusline: %02x", 
-           __FUNCTION__, port->number, result, transfer_buffer[0]);
-
-       if ((transfer_buffer[0] & SUSBCR_GSL_DSR) != 0) {
-               priv->line_state |= TIOCM_DSR;
-       } else {
-               priv->line_state &= ~TIOCM_DSR; 
-       }
+           __func__, port->number, result, transfer_buffer[0]);
 
+       result = 0;
+       if ((transfer_buffer[0] & SUSBCR_GSL_DSR) != 0)
+               result = TIOCM_DSR;
        kfree(transfer_buffer);
-       return priv->line_state;
+       return result;
 }
 
 static int  kobil_tiocmset(struct usb_serial_port *port, struct file *file,
@@ -552,6 +534,7 @@ static int  kobil_tiocmset(struct usb_serial_port *port, struct file *file,
        unsigned char *transfer_buffer;
        int transfer_buffer_length = 8;
 
+       /* FIXME: locking ? */
        priv = usb_get_serial_port_data(port);
        if ((priv->device_type == KOBIL_USBTWIN_PRODUCT_ID) || (priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID)) {
                // This device doesn't support ioctl calls
@@ -575,9 +558,9 @@ static int  kobil_tiocmset(struct usb_serial_port *port, struct file *file,
 
        if (priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID) {
                if (dtr != 0)
-                       dbg("%s - port %d Setting DTR", __FUNCTION__, port->number);
+                       dbg("%s - port %d Setting DTR", __func__, port->number);
                else
-                       dbg("%s - port %d Clearing DTR", __FUNCTION__, port->number);
+                       dbg("%s - port %d Clearing DTR", __func__, port->number);
                result = usb_control_msg( port->serial->dev, 
                                          usb_rcvctrlpipe(port->serial->dev, 0 ), 
                                          SUSBCRequest_SetStatusLinesOrQueues,
@@ -589,9 +572,9 @@ static int  kobil_tiocmset(struct usb_serial_port *port, struct file *file,
                                          KOBIL_TIMEOUT);
        } else {
                if (rts != 0)
-                       dbg("%s - port %d Setting RTS", __FUNCTION__, port->number);
+                       dbg("%s - port %d Setting RTS", __func__, port->number);
                else
-                       dbg("%s - port %d Clearing RTS", __FUNCTION__, port->number);
+                       dbg("%s - port %d Clearing RTS", __func__, port->number);
                result = usb_control_msg( port->serial->dev, 
                                          usb_rcvctrlpipe(port->serial->dev, 0 ), 
                                          SUSBCRequest_SetStatusLinesOrQueues,
@@ -602,107 +585,87 @@ static int  kobil_tiocmset(struct usb_serial_port *port, struct file *file,
                                          0,
                                          KOBIL_TIMEOUT);
        }
-       dbg("%s - port %d Send set_status_line URB returns: %i", __FUNCTION__, port->number, result);
+       dbg("%s - port %d Send set_status_line URB returns: %i", __func__, port->number, result);
        kfree(transfer_buffer);
        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:
                default:
+                       speed = 9600;
+               case 9600:
                        urb_val = SUSBCR_SBR_9600;
-                       strcat(settings, "9600 ");
                        break;
-               }
+       }
+       urb_val |= (c_cflag & CSTOPB) ? SUSBCR_SPASB_2StopBits : SUSBCR_SPASB_1StopBit;
 
-               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 ");
+       settings = kzalloc(50, GFP_KERNEL);
+       if (! settings)
+               return;
 
-               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");
-                       }
+       sprintf(settings, "%d ", speed);
+
+       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");
+       }
+       port->tty->termios->c_cflag &= ~CMSPAR;
+       tty_encode_baud_rate(port->tty, speed, speed);
+
+       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);
+}
 
-               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
-                       );
+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;
 
-               dbg("%s - port %d Send set_baudrate URB returns: %i", __FUNCTION__, port->number, result);
-               kfree(settings);
+       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 ), 
@@ -715,16 +678,14 @@ static int  kobil_ioctl(struct usb_serial_port *port, struct file *file,
                                          KOBIL_TIMEOUT
                        );
                
-               dbg("%s - port %d Send reset_all_queues (FLUSH) URB returns: %i", __FUNCTION__, port->number, result);
-
+               dbg("%s - port %d Send reset_all_queues (FLUSH) URB returns: %i", __func__, 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;