diff options
Diffstat (limited to 'drivers/usb/serial/cyberjack.c')
| -rw-r--r-- | drivers/usb/serial/cyberjack.c | 379 |
1 files changed, 143 insertions, 236 deletions
diff --git a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c index 8d9b045aa7e..2916dea3ede 100644 --- a/drivers/usb/serial/cyberjack.c +++ b/drivers/usb/serial/cyberjack.c @@ -30,25 +30,18 @@ #include <linux/kernel.h> #include <linux/errno.h> -#include <linux/init.h> #include <linux/slab.h> #include <linux/tty.h> #include <linux/tty_driver.h> #include <linux/tty_flip.h> #include <linux/module.h> #include <linux/spinlock.h> -#include <asm/uaccess.h> +#include <linux/uaccess.h> #include <linux/usb.h> #include <linux/usb/serial.h> #define CYBERJACK_LOCAL_BUF_SIZE 32 -static int debug; - -/* - * Version Information - */ -#define DRIVER_VERSION "v1.01" #define DRIVER_AUTHOR "Matthias Bruestle" #define DRIVER_DESC "REINER SCT cyberJack pinpad/e-com USB Chipcard Reader Driver" @@ -57,30 +50,24 @@ static int debug; #define CYBERJACK_PRODUCT_ID 0x0100 /* Function prototypes */ -static int cyberjack_startup (struct usb_serial *serial); -static void cyberjack_shutdown (struct usb_serial *serial); -static int cyberjack_open (struct usb_serial_port *port, struct file *filp); -static void cyberjack_close (struct usb_serial_port *port, struct file *filp); -static int cyberjack_write (struct usb_serial_port *port, const unsigned char *buf, int count); -static int cyberjack_write_room( struct usb_serial_port *port ); -static void cyberjack_read_int_callback (struct urb *urb); -static void cyberjack_read_bulk_callback (struct urb *urb); -static void cyberjack_write_bulk_callback (struct urb *urb); - -static struct usb_device_id id_table [] = { +static int cyberjack_port_probe(struct usb_serial_port *port); +static int cyberjack_port_remove(struct usb_serial_port *port); +static int cyberjack_open(struct tty_struct *tty, + struct usb_serial_port *port); +static void cyberjack_close(struct usb_serial_port *port); +static int cyberjack_write(struct tty_struct *tty, + struct usb_serial_port *port, const unsigned char *buf, int count); +static int cyberjack_write_room(struct tty_struct *tty); +static void cyberjack_read_int_callback(struct urb *urb); +static void cyberjack_read_bulk_callback(struct urb *urb); +static void cyberjack_write_bulk_callback(struct urb *urb); + +static const struct usb_device_id id_table[] = { { USB_DEVICE(CYBERJACK_VENDOR_ID, CYBERJACK_PRODUCT_ID) }, { } /* Terminating entry */ }; -MODULE_DEVICE_TABLE (usb, id_table); - -static struct usb_driver cyberjack_driver = { - .name = "cyberjack", - .probe = usb_serial_probe, - .disconnect = usb_serial_disconnect, - .id_table = id_table, - .no_dynamic_id = 1, -}; +MODULE_DEVICE_TABLE(usb, id_table); static struct usb_serial_driver cyberjack_device = { .driver = { @@ -88,14 +75,10 @@ static struct usb_serial_driver cyberjack_device = { .name = "cyberjack", }, .description = "Reiner SCT Cyberjack USB card reader", - .usb_driver = &cyberjack_driver, .id_table = id_table, - .num_interrupt_in = 1, - .num_bulk_in = 1, - .num_bulk_out = 1, .num_ports = 1, - .attach = cyberjack_startup, - .shutdown = cyberjack_shutdown, + .port_probe = cyberjack_port_probe, + .port_remove = cyberjack_port_remove, .open = cyberjack_open, .close = cyberjack_close, .write = cyberjack_write, @@ -105,6 +88,10 @@ static struct usb_serial_driver cyberjack_device = { .write_bulk_callback = cyberjack_write_bulk_callback, }; +static struct usb_serial_driver * const serial_drivers[] = { + &cyberjack_device, NULL +}; + struct cyberjack_private { spinlock_t lock; /* Lock for SMP */ short rdtodo; /* Bytes still to read */ @@ -113,72 +100,51 @@ struct cyberjack_private { short wrsent; /* Data already sent */ }; -/* do some startup allocations not currently performed by usb_serial_probe() */ -static int cyberjack_startup (struct usb_serial *serial) +static int cyberjack_port_probe(struct usb_serial_port *port) { struct cyberjack_private *priv; - int i; - - dbg("%s", __FUNCTION__); + int result; - /* allocate the private data structure */ priv = kmalloc(sizeof(struct cyberjack_private), GFP_KERNEL); if (!priv) return -ENOMEM; - /* set initial values */ spin_lock_init(&priv->lock); priv->rdtodo = 0; priv->wrfilled = 0; priv->wrsent = 0; - usb_set_serial_port_data(serial->port[0], priv); - init_waitqueue_head(&serial->port[0]->write_wait); + usb_set_serial_port_data(port, priv); - for (i = 0; i < serial->num_ports; ++i) { - int result; - serial->port[i]->interrupt_in_urb->dev = serial->dev; - result = usb_submit_urb(serial->port[i]->interrupt_in_urb, - GFP_KERNEL); - if (result) - err(" usb_submit_urb(read int) failed"); - dbg("%s - usb_submit_urb(int urb)", __FUNCTION__); - } + result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); + if (result) + dev_err(&port->dev, "usb_submit_urb(read int) failed\n"); - return( 0 ); + return 0; } -static void cyberjack_shutdown (struct usb_serial *serial) +static int cyberjack_port_remove(struct usb_serial_port *port) { - int i; - - dbg("%s", __FUNCTION__); - - 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])); - usb_set_serial_port_data(serial->port[i], NULL); - } + struct cyberjack_private *priv; + + usb_kill_urb(port->interrupt_in_urb); + + priv = usb_get_serial_port_data(port); + kfree(priv); + + return 0; } - -static int cyberjack_open (struct usb_serial_port *port, struct file *filp) + +static int cyberjack_open(struct tty_struct *tty, + struct usb_serial_port *port) { struct cyberjack_private *priv; unsigned long flags; int result = 0; - dbg("%s - port %d", __FUNCTION__, port->number); - - dbg("%s - usb_clear_halt", __FUNCTION__ ); + dev_dbg(&port->dev, "%s - usb_clear_halt\n", __func__); usb_clear_halt(port->serial->dev, port->write_urb->pipe); - /* force low_latency on so that our tty_push actually forces - * the data through, otherwise it is scheduled, and with high - * data rates (like with OHCI) data can get lost. - */ - port->tty->low_latency = 1; - priv = usb_get_serial_port_data(port); spin_lock_irqsave(&priv->lock, flags); priv->rdtodo = 0; @@ -189,135 +155,120 @@ static int cyberjack_open (struct usb_serial_port *port, struct file *filp) return result; } -static void cyberjack_close (struct usb_serial_port *port, struct file *filp) +static void cyberjack_close(struct usb_serial_port *port) { - dbg("%s - port %d", __FUNCTION__, port->number); - - if (port->serial->dev) { - /* shutdown any bulk reads that might be going on */ - usb_kill_urb(port->write_urb); - usb_kill_urb(port->read_urb); - } + usb_kill_urb(port->write_urb); + usb_kill_urb(port->read_urb); } -static int cyberjack_write (struct usb_serial_port *port, const unsigned char *buf, int count) +static int cyberjack_write(struct tty_struct *tty, + struct usb_serial_port *port, const unsigned char *buf, int count) { - struct usb_serial *serial = port->serial; + struct device *dev = &port->dev; struct cyberjack_private *priv = usb_get_serial_port_data(port); unsigned long flags; int result; int wrexpected; - dbg("%s - port %d", __FUNCTION__, port->number); - if (count == 0) { - dbg("%s - write request of 0 bytes", __FUNCTION__); - return (0); + dev_dbg(dev, "%s - write request of 0 bytes\n", __func__); + return 0; } - spin_lock_bh(&port->lock); - if (port->write_urb_busy) { - spin_unlock_bh(&port->lock); - dbg("%s - already writing", __FUNCTION__); + if (!test_and_clear_bit(0, &port->write_urbs_free)) { + dev_dbg(dev, "%s - already writing\n", __func__); return 0; } - port->write_urb_busy = 1; - spin_unlock_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; + priv->wrfilled = 0; spin_unlock_irqrestore(&priv->lock, flags); - port->write_urb_busy = 0; - return (0); + set_bit(0, &port->write_urbs_free); + return 0; } /* Copy data */ - memcpy (priv->wrbuf+priv->wrfilled, buf, count); + memcpy(priv->wrbuf + priv->wrfilled, buf, count); - usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, - priv->wrbuf+priv->wrfilled); + usb_serial_debug_data(dev, __func__, count, priv->wrbuf + priv->wrfilled); priv->wrfilled += count; - if( priv->wrfilled >= 3 ) { + if (priv->wrfilled >= 3) { wrexpected = ((int)priv->wrbuf[2]<<8)+priv->wrbuf[1]+3; - dbg("%s - expected data: %d", __FUNCTION__, wrexpected); - } else { + dev_dbg(dev, "%s - expected data: %d\n", __func__, wrexpected); + } else wrexpected = sizeof(priv->wrbuf); - } - if( priv->wrfilled >= wrexpected ) { + if (priv->wrfilled >= wrexpected) { /* We have enough data to begin transmission */ int length; - dbg("%s - transmitting data (frame 1)", __FUNCTION__); - length = (wrexpected > port->bulk_out_size) ? port->bulk_out_size : wrexpected; + dev_dbg(dev, "%s - transmitting data (frame 1)\n", __func__); + length = (wrexpected > port->bulk_out_size) ? + port->bulk_out_size : wrexpected; - memcpy (port->write_urb->transfer_buffer, priv->wrbuf, length ); - priv->wrsent=length; + memcpy(port->write_urb->transfer_buffer, priv->wrbuf, length); + priv->wrsent = length; /* set up our urb */ - usb_fill_bulk_urb(port->write_urb, serial->dev, - usb_sndbulkpipe(serial->dev, port->bulk_out_endpointAddress), - port->write_urb->transfer_buffer, length, - ((serial->type->write_bulk_callback) ? - serial->type->write_bulk_callback : - cyberjack_write_bulk_callback), - port); + port->write_urb->transfer_buffer_length = length; /* send the data out the bulk port */ result = usb_submit_urb(port->write_urb, GFP_ATOMIC); if (result) { - err("%s - failed submitting write urb, error %d", __FUNCTION__, result); + dev_err(&port->dev, + "%s - failed submitting write urb, error %d\n", + __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; + set_bit(0, &port->write_urbs_free); return 0; } - dbg("%s - priv->wrsent=%d", __FUNCTION__,priv->wrsent); - dbg("%s - priv->wrfilled=%d", __FUNCTION__,priv->wrfilled); + dev_dbg(dev, "%s - priv->wrsent=%d\n", __func__, priv->wrsent); + dev_dbg(dev, "%s - priv->wrfilled=%d\n", __func__, priv->wrfilled); - if( priv->wrsent>=priv->wrfilled ) { - dbg("%s - buffer cleaned", __FUNCTION__); - memset( priv->wrbuf, 0, sizeof(priv->wrbuf) ); - priv->wrfilled=0; - priv->wrsent=0; + if (priv->wrsent >= priv->wrfilled) { + dev_dbg(dev, "%s - buffer cleaned\n", __func__); + memset(priv->wrbuf, 0, sizeof(priv->wrbuf)); + priv->wrfilled = 0; + priv->wrsent = 0; } } spin_unlock_irqrestore(&priv->lock, flags); - return (count); -} + return count; +} -static int cyberjack_write_room( struct usb_serial_port *port ) +static int cyberjack_write_room(struct tty_struct *tty) { + /* FIXME: .... */ return CYBERJACK_LOCAL_BUF_SIZE; } -static void cyberjack_read_int_callback( struct urb *urb ) +static void cyberjack_read_int_callback(struct urb *urb) { - struct usb_serial_port *port = (struct usb_serial_port *)urb->context; + struct usb_serial_port *port = urb->context; struct cyberjack_private *priv = usb_get_serial_port_data(port); + struct device *dev = &port->dev; unsigned char *data = urb->transfer_buffer; int status = urb->status; int result; - dbg("%s - port %d", __FUNCTION__, port->number); - /* the urb might have been killed. */ if (status) return; - usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data); + usb_serial_debug_data(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. */ @@ -327,147 +278,134 @@ static void cyberjack_read_int_callback( struct urb *urb ) old_rdtodo = priv->rdtodo; - if( (old_rdtodo+size)<(old_rdtodo) ) { - dbg( "To many bulk_in urbs to do." ); + if (old_rdtodo > SHRT_MAX - size) { + dev_dbg(dev, "To many bulk_in urbs to do.\n"); spin_unlock(&priv->lock); goto resubmit; } - /* "+=" is probably more fault tollerant than "=" */ + /* "+=" is probably more fault tolerant than "=" */ priv->rdtodo += size; - dbg("%s - rdtodo: %d", __FUNCTION__, priv->rdtodo); + dev_dbg(dev, "%s - rdtodo: %d\n", __func__, priv->rdtodo); spin_unlock(&priv->lock); - if( !old_rdtodo ) { - port->read_urb->dev = port->serial->dev; + if (!old_rdtodo) { result = usb_submit_urb(port->read_urb, GFP_ATOMIC); - if( result ) - err("%s - failed resubmitting read urb, error %d", __FUNCTION__, result); - dbg("%s - usb_submit_urb(read urb)", __FUNCTION__); + if (result) + dev_err(dev, "%s - failed resubmitting read urb, error %d\n", + __func__, result); + dev_dbg(dev, "%s - usb_submit_urb(read urb)\n", __func__); } } resubmit: - port->interrupt_in_urb->dev = port->serial->dev; result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC); if (result) - err(" usb_submit_urb(read int) failed"); - dbg("%s - usb_submit_urb(int urb)", __FUNCTION__); + dev_err(&port->dev, "usb_submit_urb(read int) failed\n"); + dev_dbg(dev, "%s - usb_submit_urb(int urb)\n", __func__); } -static void cyberjack_read_bulk_callback (struct urb *urb) +static void cyberjack_read_bulk_callback(struct urb *urb) { - struct usb_serial_port *port = (struct usb_serial_port *)urb->context; + struct usb_serial_port *port = urb->context; struct cyberjack_private *priv = usb_get_serial_port_data(port); - struct tty_struct *tty; + struct device *dev = &port->dev; unsigned char *data = urb->transfer_buffer; short todo; int result; int status = urb->status; - dbg("%s - port %d", __FUNCTION__, port->number); - - usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data); + usb_serial_debug_data(dev, __func__, urb->actual_length, data); if (status) { - dbg("%s - nonzero read bulk status received: %d", - __FUNCTION__, status); + dev_dbg(dev, "%s - nonzero read bulk status received: %d\n", + __func__, status); return; } - tty = port->tty; - if (!tty) { - dbg("%s - ignoring since device not open\n", __FUNCTION__); - return; - } if (urb->actual_length) { - tty_buffer_request_room(tty, urb->actual_length); - tty_insert_flip_string(tty, data, urb->actual_length); - tty_flip_buffer_push(tty); + tty_insert_flip_string(&port->port, data, urb->actual_length); + tty_flip_buffer_push(&port->port); } spin_lock(&priv->lock); /* Reduce urbs to do by one. */ - priv->rdtodo-=urb->actual_length; + priv->rdtodo -= urb->actual_length; /* Just to be sure */ - if ( priv->rdtodo<0 ) priv->rdtodo = 0; + if (priv->rdtodo < 0) + priv->rdtodo = 0; todo = priv->rdtodo; spin_unlock(&priv->lock); - dbg("%s - rdtodo: %d", __FUNCTION__, todo); + dev_dbg(dev, "%s - rdtodo: %d\n", __func__, todo); /* Continue to read if we have still urbs to do. */ - if( todo /* || (urb->actual_length==port->bulk_in_endpointAddress)*/ ) { - port->read_urb->dev = port->serial->dev; + if (todo /* || (urb->actual_length==port->bulk_in_endpointAddress)*/) { result = usb_submit_urb(port->read_urb, GFP_ATOMIC); if (result) - err("%s - failed resubmitting read urb, error %d", __FUNCTION__, result); - dbg("%s - usb_submit_urb(read urb)", __FUNCTION__); + dev_err(dev, "%s - failed resubmitting read urb, error %d\n", + __func__, result); + dev_dbg(dev, "%s - usb_submit_urb(read urb)\n", __func__); } } -static void cyberjack_write_bulk_callback (struct urb *urb) +static void cyberjack_write_bulk_callback(struct urb *urb) { - struct usb_serial_port *port = (struct usb_serial_port *)urb->context; + struct usb_serial_port *port = urb->context; struct cyberjack_private *priv = usb_get_serial_port_data(port); + struct device *dev = &port->dev; int status = urb->status; - dbg("%s - port %d", __FUNCTION__, port->number); - - port->write_urb_busy = 0; + set_bit(0, &port->write_urbs_free); if (status) { - dbg("%s - nonzero write bulk status received: %d", - __FUNCTION__, status); + dev_dbg(dev, "%s - nonzero write bulk status received: %d\n", + __func__, status); return; } spin_lock(&priv->lock); /* only do something if we have more data to send */ - if( priv->wrfilled ) { + if (priv->wrfilled) { int length, blksize, result; - dbg("%s - transmitting data (frame n)", __FUNCTION__); + dev_dbg(dev, "%s - transmitting data (frame n)\n", __func__); length = ((priv->wrfilled - priv->wrsent) > port->bulk_out_size) ? port->bulk_out_size : (priv->wrfilled - priv->wrsent); - memcpy (port->write_urb->transfer_buffer, priv->wrbuf + priv->wrsent, - length ); - priv->wrsent+=length; + memcpy(port->write_urb->transfer_buffer, + priv->wrbuf + priv->wrsent, length); + priv->wrsent += length; /* set up our urb */ - usb_fill_bulk_urb(port->write_urb, port->serial->dev, - usb_sndbulkpipe(port->serial->dev, port->bulk_out_endpointAddress), - port->write_urb->transfer_buffer, length, - ((port->serial->type->write_bulk_callback) ? - port->serial->type->write_bulk_callback : - cyberjack_write_bulk_callback), - port); + port->write_urb->transfer_buffer_length = length; /* send the data out the bulk port */ result = usb_submit_urb(port->write_urb, GFP_ATOMIC); if (result) { - err("%s - failed submitting write urb, error %d", __FUNCTION__, result); + dev_err(dev, "%s - failed submitting write urb, error %d\n", + __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; } - dbg("%s - priv->wrsent=%d", __FUNCTION__,priv->wrsent); - dbg("%s - priv->wrfilled=%d", __FUNCTION__,priv->wrfilled); + dev_dbg(dev, "%s - priv->wrsent=%d\n", __func__, priv->wrsent); + dev_dbg(dev, "%s - priv->wrfilled=%d\n", __func__, priv->wrfilled); blksize = ((int)priv->wrbuf[2]<<8)+priv->wrbuf[1]+3; - if( (priv->wrsent>=priv->wrfilled) || (priv->wrsent>=blksize) ) { - dbg("%s - buffer cleaned", __FUNCTION__); - memset( priv->wrbuf, 0, sizeof(priv->wrbuf) ); - priv->wrfilled=0; - priv->wrsent=0; + if (priv->wrsent >= priv->wrfilled || + priv->wrsent >= blksize) { + dev_dbg(dev, "%s - buffer cleaned\n", __func__); + memset(priv->wrbuf, 0, sizeof(priv->wrbuf)); + priv->wrfilled = 0; + priv->wrsent = 0; } } @@ -476,39 +414,8 @@ exit: usb_serial_port_softint(port); } -static int __init cyberjack_init (void) -{ - int retval; - retval = usb_serial_register(&cyberjack_device); - if (retval) - goto failed_usb_serial_register; - retval = usb_register(&cyberjack_driver); - if (retval) - goto failed_usb_register; - - info(DRIVER_VERSION " " DRIVER_AUTHOR); - info(DRIVER_DESC); - - return 0; -failed_usb_register: - usb_serial_deregister(&cyberjack_device); -failed_usb_serial_register: - return retval; -} +module_usb_serial_driver(serial_drivers, id_table); -static void __exit cyberjack_exit (void) -{ - usb_deregister (&cyberjack_driver); - usb_serial_deregister (&cyberjack_device); -} - -module_init(cyberjack_init); -module_exit(cyberjack_exit); - -MODULE_AUTHOR( DRIVER_AUTHOR ); -MODULE_DESCRIPTION( DRIVER_DESC ); -MODULE_VERSION( DRIVER_VERSION ); +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); MODULE_LICENSE("GPL"); - -module_param(debug, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(debug, "Debug enabled or not"); |
