X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fusb%2Fserial%2Fkobil_sct.c;h=87dfcd89ffabf44316fefa86d18cf4ecb1f077ce;hb=43bc926fffd92024b46cafaf7350d669ba9ca884;hp=82319a9d1bee94238203df2f9bf31a04bde0b278;hpb=5273a3df6485dc2ad6aa7ddd441b9a21970f003b;p=linux-2.6.git diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c index 82319a9d1..87dfcd89f 100644 --- a/drivers/usb/serial/kobil_sct.c +++ b/drivers/usb/serial/kobil_sct.c @@ -21,6 +21,9 @@ * Supported readers: USB TWIN, KAAN Standard Plus and SecOVID Reader Plus * (Adapter K), B1 Professional and KAAN Professional (Adapter B) * + * (21/05/2004) tw + * Fix bug with P'n'P readers + * * (28/05/2003) tw * Add support for KAAN SIM * @@ -45,21 +48,13 @@ #include #include #include - - +#include "usb-serial.h" #include "kobil_sct.h" -//#include "../core/usb-debug.c" -#ifdef CONFIG_USB_SERIAL_DEBUG - static int debug = 1; -#else - static int debug; -#endif - -#include "usb-serial.h" +static int debug; /* Version Information */ -#define DRIVER_VERSION "28/05/2003" +#define DRIVER_VERSION "21/05/2004" #define DRIVER_AUTHOR "KOBIL Systems GmbH - http://www.kobil.com" #define DRIVER_DESC "KOBIL USB Smart Card Terminal Driver (experimental)" @@ -78,7 +73,7 @@ static int kobil_startup (struct usb_serial *serial); static void kobil_shutdown (struct usb_serial *serial); static int kobil_open (struct usb_serial_port *port, struct file *filp); static void kobil_close (struct usb_serial_port *port, struct file *filp); -static int kobil_write (struct usb_serial_port *port, int from_user, +static int kobil_write (struct usb_serial_port *port, const unsigned char *buf, int count); static int kobil_write_room(struct usb_serial_port *port); static int kobil_ioctl(struct usb_serial_port *port, struct file *file, @@ -102,17 +97,20 @@ static struct usb_device_id id_table [] = { MODULE_DEVICE_TABLE (usb, id_table); static struct usb_driver kobil_driver = { - .owner = THIS_MODULE, .name = "kobil", .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, .id_table = id_table, + .no_dynamic_id = 1, }; -struct usb_serial_device_type kobil_device = { - .owner = THIS_MODULE, - .name = "KOBIL USB smart card terminal", +static struct usb_serial_driver kobil_device = { + .driver = { + .owner = THIS_MODULE, + .name = "kobil", + }, + .description = "KOBIL USB smart card terminal", .id_table = id_table, .num_interrupt_in = NUM_DONT_CARE, .num_bulk_in = 0, @@ -160,7 +158,7 @@ static int kobil_startup (struct usb_serial *serial) priv->filled = 0; priv->cur_pos = 0; - priv->device_type = serial->product; + priv->device_type = le16_to_cpu(serial->dev->descriptor.idProduct); priv->line_state = 0; switch (priv->device_type){ @@ -183,7 +181,7 @@ static int kobil_startup (struct usb_serial *serial) pdev = serial->dev; actconfig = pdev->actconfig; interface = actconfig->interface[0]; - altsetting = interface->altsetting; + altsetting = interface->cur_altsetting; endpoint = altsetting->endpoint; for (i = 0; i < altsetting->desc.bNumEndpoints; i++) { @@ -230,9 +228,6 @@ static int kobil_open (struct usb_serial_port *port, struct file *filp) priv = usb_get_serial_port_data(port); priv->line_state = 0; - if (port_paranoia_check (port, __FUNCTION__)) - return -ENODEV; - // someone sets the dev to 0 if the close method has been called port->interrupt_in_urb->dev = port->serial->dev; @@ -260,11 +255,9 @@ static int kobil_open (struct usb_serial_port *port, struct file *filp) } // allocate memory for transfer buffer - transfer_buffer = (unsigned char *) kmalloc(transfer_buffer_length, GFP_KERNEL); + transfer_buffer = kzalloc(transfer_buffer_length, GFP_KERNEL); if (! transfer_buffer) { return -ENOMEM; - } else { - memset(transfer_buffer, 0, transfer_buffer_length); } // allocate write_urb @@ -342,6 +335,12 @@ static int kobil_open (struct usb_serial_port *port, struct file *filp) ); dbg("%s - port %d Send reset_all_queues URB returns: %i", __FUNCTION__, 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); + } kfree(transfer_buffer); return 0; @@ -352,20 +351,18 @@ static void kobil_close (struct usb_serial_port *port, struct file *filp) { dbg("%s - port %d", __FUNCTION__, port->number); - if (port->write_urb){ - usb_unlink_urb( port->write_urb ); + if (port->write_urb) { + usb_kill_urb(port->write_urb); usb_free_urb( port->write_urb ); - port->write_urb = 0; - } - if (port->interrupt_in_urb){ - usb_unlink_urb (port->interrupt_in_urb); + port->write_urb = NULL; } + if (port->interrupt_in_urb) + usb_kill_urb(port->interrupt_in_urb); } static void kobil_read_int_callback( struct urb *purb, struct pt_regs *regs) { - int i; int result; struct usb_serial_port *port = (struct usb_serial_port *) purb->context; struct tty_struct *tty; @@ -384,11 +381,10 @@ static void kobil_read_int_callback( struct urb *purb, struct pt_regs *regs) // BEGIN DEBUG /* - dbg_data = (unsigned char *) kmalloc((3 * purb->actual_length + 10) * sizeof(char), GFP_KERNEL); + dbg_data = kzalloc((3 * purb->actual_length + 10) * sizeof(char), GFP_KERNEL); if (! dbg_data) { return; } - memset(dbg_data, 0, (3 * purb->actual_length + 10)); for (i = 0; i < purb->actual_length; i++) { sprintf(dbg_data +3*i, "%02X ", data[i]); } @@ -397,14 +393,8 @@ static void kobil_read_int_callback( struct urb *purb, struct pt_regs *regs) */ // END DEBUG - for (i = 0; i < purb->actual_length; ++i) { - // if we insert more than TTY_FLIPBUF_SIZE characters, we drop them. - if(tty->flip.count >= TTY_FLIPBUF_SIZE) { - tty_flip_buffer_push(tty); - } - // this doesn't actually push the data through unless tty->low_latency is set - tty_insert_flip_char(tty, data[i], 0); - } + tty_buffer_request_room(tty, purb->actual_length); + tty_insert_flip_string(tty, data, purb->actual_length); tty_flip_buffer_push(tty); } @@ -421,7 +411,7 @@ static void kobil_write_callback( struct urb *purb, struct pt_regs *regs ) } -static int kobil_write (struct usb_serial_port *port, int from_user, +static int kobil_write (struct usb_serial_port *port, const unsigned char *buf, int count) { int length = 0; @@ -442,15 +432,9 @@ static int kobil_write (struct usb_serial_port *port, int from_user, } // Copy data to buffer - if (from_user) { - if (copy_from_user(priv->buf + priv->filled, buf, count)) { - return -EFAULT; - } - } else { - memcpy (priv->buf + priv->filled, buf, count); - } + memcpy (priv->buf + priv->filled, buf, count); - usb_serial_debug_data (__FILE__, __FUNCTION__, count, priv->buf + priv->filled); + usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, priv->buf + priv->filled); priv->filled = priv->filled + count; @@ -459,6 +443,10 @@ static int kobil_write (struct usb_serial_port *port, int from_user, if ( ((priv->device_type != KOBIL_ADAPTER_B_PRODUCT_ID) && (priv->filled > 2) && (priv->filled >= (priv->buf[1] + 3))) || ((priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID) && (priv->filled > 3) && (priv->filled >= (priv->buf[2] + 4))) ) { + // stop reading (except TWIN and KAAN SIM) + if ( (priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID) || (priv->device_type == KOBIL_ADAPTER_K_PRODUCT_ID) ) + usb_kill_urb(port->interrupt_in_urb); + todo = priv->filled - priv->cur_pos; while(todo > 0) { @@ -466,25 +454,23 @@ static int kobil_write (struct usb_serial_port *port, int from_user, length = (todo < 8) ? todo : 8; // copy data to transfer buffer memcpy(port->write_urb->transfer_buffer, priv->buf + priv->cur_pos, length ); - - usb_fill_bulk_urb( port->write_urb, - port->serial->dev, - usb_sndbulkpipe( port->serial->dev, priv->write_int_endpoint_address), - port->write_urb->transfer_buffer, - length, - kobil_write_callback, - port + usb_fill_int_urb( port->write_urb, + port->serial->dev, + usb_sndintpipe(port->serial->dev, priv->write_int_endpoint_address), + port->write_urb->transfer_buffer, + length, + kobil_write_callback, + port, + 8 ); priv->cur_pos = priv->cur_pos + length; - result = usb_submit_urb( port->write_urb, GFP_ATOMIC ); + result = usb_submit_urb( port->write_urb, GFP_NOIO ); dbg("%s - port %d Send write URB returns: %i", __FUNCTION__, port->number, result); todo = priv->filled - priv->cur_pos; if (todo > 0) { - //mdelay(16); - set_current_state(TASK_UNINTERRUPTIBLE); - schedule_timeout(24 * HZ / 1000); + msleep(24); } } // end while @@ -495,9 +481,14 @@ static int kobil_write (struct usb_serial_port *port, int from_user, // someone sets the dev to 0 if the close method has been called port->interrupt_in_urb->dev = port->serial->dev; - // start reading - result = usb_submit_urb( port->interrupt_in_urb, GFP_ATOMIC ); - dbg("%s - port %d Send read URB returns: %i", __FUNCTION__, port->number, result); + // start reading (except TWIN and KAAN SIM) + if ( (priv->device_type == KOBIL_ADAPTER_B_PRODUCT_ID) || (priv->device_type == KOBIL_ADAPTER_K_PRODUCT_ID) ) { + // someone sets the dev to 0 if the close method has been called + 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); + } } return count; } @@ -524,11 +515,10 @@ static int kobil_tiocmget(struct usb_serial_port *port, struct file *file) } // allocate memory for transfer buffer - transfer_buffer = (unsigned char *) kmalloc(transfer_buffer_length, GFP_KERNEL); + transfer_buffer = kzalloc(transfer_buffer_length, GFP_KERNEL); if (!transfer_buffer) { return -ENOMEM; } - memset(transfer_buffer, 0, transfer_buffer_length); result = usb_control_msg( port->serial->dev, usb_rcvctrlpipe(port->serial->dev, 0 ), @@ -570,11 +560,10 @@ static int kobil_tiocmset(struct usb_serial_port *port, struct file *file, } // allocate memory for transfer buffer - transfer_buffer = (unsigned char *) kmalloc(transfer_buffer_length, GFP_KERNEL); + transfer_buffer = kzalloc(transfer_buffer_length, GFP_KERNEL); if (! transfer_buffer) { return -ENOMEM; } - memset(transfer_buffer, 0, transfer_buffer_length); if (set & TIOCM_RTS) rts = 1; @@ -629,6 +618,7 @@ static int kobil_ioctl(struct usb_serial_port *port, struct file *file, unsigned char *transfer_buffer; int transfer_buffer_length = 8; char *settings; + void __user *user_arg = (void __user *)arg; priv = usb_get_serial_port_data(port); if ((priv->device_type == KOBIL_USBTWIN_PRODUCT_ID) || (priv->device_type == KOBIL_KAAN_SIM_PRODUCT_ID)) { @@ -638,12 +628,11 @@ static int kobil_ioctl(struct usb_serial_port *port, struct file *file, switch (cmd) { case TCGETS: // 0x5401 - result = verify_area(VERIFY_WRITE, (void *)arg, sizeof(struct termios)); - if (result) { - dbg("%s - port %d Error in verify_area", __FUNCTION__, port->number); - return(result); + if (!access_ok(VERIFY_WRITE, user_arg, sizeof(struct termios))) { + dbg("%s - port %d Error in access_ok", __FUNCTION__, port->number); + return -EFAULT; } - if (kernel_termios_to_user_termios((struct termios *)arg, + if (kernel_termios_to_user_termios((struct termios __user *)arg, &priv->internal_termios)) return -EFAULT; return 0; @@ -653,20 +642,18 @@ static int kobil_ioctl(struct usb_serial_port *port, struct file *file, dbg("%s - port %d Error: port->tty->termios is NULL", __FUNCTION__, port->number); return -ENOTTY; } - result = verify_area(VERIFY_READ, (void *)arg, sizeof(struct termios)); - if (result) { - dbg("%s - port %d Error in verify_area", __FUNCTION__, port->number); - return result; + if (!access_ok(VERIFY_READ, user_arg, sizeof(struct termios))) { + dbg("%s - port %d Error in access_ok", __FUNCTION__, port->number); + return -EFAULT; } if (user_termios_to_kernel_termios(&priv->internal_termios, - (struct termios *)arg)) + (struct termios __user *)arg)) return -EFAULT; - settings = (unsigned char *) kmalloc(50, GFP_KERNEL); + settings = kzalloc(50, GFP_KERNEL); if (! settings) { return -ENOBUFS; } - memset(settings, 0, 50); switch (priv->internal_termios.c_cflag & CBAUD) { case B1200: @@ -773,5 +760,5 @@ MODULE_AUTHOR( DRIVER_AUTHOR ); MODULE_DESCRIPTION( DRIVER_DESC ); MODULE_LICENSE( "GPL" ); -MODULE_PARM(debug, "i"); +module_param(debug, bool, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(debug, "Debug enabled or not");