CTC++ Coverage Report - Execution Profile    #753/1532

Files Summary | Functions Summary | Execution Profile | Index | No Index
First | Previous | Next | Last


File: drivers/usb/serial/cyberjack.c
Instrumentation mode: function-decision-multicondition
TER: 0 % ( 0/316)

Start/ End/    
True False - Line Source

  1 /*
  2  *  REINER SCT cyberJack pinpad/e-com USB Chipcard Reader Driver
  3  *
  4  *  Copyright (C) 2001  REINER SCT
  5  *  Author: Matthias Bruestle
  6  *
  7  *  Contact: support@reiner-sct.com (see MAINTAINERS)
  8  *
  9  *  This program is largely derived from work by the linux-usb group
  10  *  and associated source files.  Please see the usb/serial files for
  11  *  individual credits and copyrights.
  12  *
  13  *  This program is free software; you can redistribute it and/or modify
  14  *  it under the terms of the GNU General Public License as published by
  15  *  the Free Software Foundation; either version 2 of the License, or
  16  *  (at your option) any later version.
  17  *
  18  *  Thanks to Greg Kroah-Hartman (greg@kroah.com) for his help and
  19  *  patience.
  20  *
  21  *  In case of problems, please write to the contact e-mail address
  22  *  mentioned above.
  23  *
  24  *  Please note that later models of the cyberjack reader family are
  25  *  supported by a libusb-based userspace device driver.
  26  *
  27  *  Homepage: http://www.reiner-sct.de/support/treiber_cyberjack.php#linux
  28  */
  29 
  30 
  31 #include <linux/config.h>
  32 #include <linux/kernel.h>
  33 #include <linux/errno.h>
  34 #include <linux/init.h>
  35 #include <linux/slab.h>
  36 #include <linux/tty.h>
  37 #include <linux/tty_driver.h>
  38 #include <linux/tty_flip.h>
  39 #include <linux/module.h>
  40 #include <linux/spinlock.h>
  41 #include <asm/uaccess.h>
  42 #include <linux/usb.h>
  43 #include "usb-serial.h"
  44 
  45 #define CYBERJACK_LOCAL_BUF_SIZE 32
  46 
  47 static int debug;
  48 
  49 /*
  50  * Version Information
  51  */
  52 #define DRIVER_VERSION "v1.01"
  53 #define DRIVER_AUTHOR "Matthias Bruestle"
  54 #define DRIVER_DESC "REINER SCT cyberJack pinpad/e-com USB Chipcard Reader Driver"
  55 
  56 
  57 #define CYBERJACK_VENDOR_ID   0x0C4B
  58 #define CYBERJACK_PRODUCT_ID   0x0100
  59 
  60 /* Function prototypes */
  61 static int cyberjack_startup (struct usb_serial *serial);
  62 static void cyberjack_shutdown (struct usb_serial *serial);
  63 static int  cyberjack_open (struct usb_serial_port *port, struct file *filp);
  64 static void cyberjack_close (struct usb_serial_port *port, struct file *filp);
  65 static int cyberjack_write (struct usb_serial_port *port, const unsigned char *buf, int count);
  66 static int cyberjack_write_room( struct usb_serial_port *port );
  67 static void cyberjack_read_int_callback (struct urb *urb, struct pt_regs *regs);
  68 static void cyberjack_read_bulk_callback (struct urb *urb, struct pt_regs *regs);
  69 static void cyberjack_write_bulk_callback (struct urb *urb, struct pt_regs *regs);
  70 
  71 static struct usb_device_id id_table [] = {
  72    { USB_DEVICE(CYBERJACK_VENDOR_ID, CYBERJACK_PRODUCT_ID) },
  73    { }         /* Terminating entry */
  74 };
  75 
  76 MODULE_DEVICE_TABLE (usb, id_table);
  77 
  78 static struct usb_driver cyberjack_driver = {
  79    .name =      "cyberjack",
  80    .probe =   usb_serial_probe,
  81    .disconnect =   usb_serial_disconnect,
  82    .id_table =   id_table,
  83    .no_dynamic_id =    1,
  84 };
  85 
  86 static struct usb_serial_driver cyberjack_device = {
  87    .driver = {
  88       .owner =   THIS_MODULE,
  89       .name =      "cyberjack",
  90    },
  91    .description =      "Reiner SCT Cyberjack USB card reader",
  92    .id_table =      id_table,
  93    .num_interrupt_in =   1,
  94    .num_bulk_in =      1,
  95    .num_bulk_out =      1,
  96    .num_ports =      1,
  97    .attach =      cyberjack_startup,
  98    .shutdown =      cyberjack_shutdown,
  99    .open =         cyberjack_open,
  100    .close =      cyberjack_close,
  101    .write =      cyberjack_write,
  102    .write_room =   cyberjack_write_room,
  103    .read_int_callback =   cyberjack_read_int_callback,
  104    .read_bulk_callback =   cyberjack_read_bulk_callback,
  105    .write_bulk_callback =   cyberjack_write_bulk_callback,
  106 };
  107 
  108 struct cyberjack_private {
  109    spinlock_t   lock;      /* Lock for SMP */
  110    short      rdtodo;      /* Bytes still to read */
  111    unsigned char   wrbuf[5*64];   /* Buffer for collecting data to write */
  112    short      wrfilled;   /* Overall data size we already got */
  113    short      wrsent;      /* Data already sent */
  114 };
  115 
  116 /* do some startup allocations not currently performed by usb_serial_probe() */
 
- 117 static int cyberjack_startup (struct usb_serial *serial)
  118 {
  119    struct cyberjack_private *priv;
  120    int i;
  121 
    122    dbg("%s", __FUNCTION__);
- 122   if (debug)
- 122 do-while (0)
  123 
  124    /* allocate the private data structure */
  125    priv = kmalloc(sizeof(struct cyberjack_private), GFP_KERNEL);
- 126    if (!priv)
 - 127       return -ENOMEM;
  128 
  129    /* set initial values */
    130    spin_lock_init(&priv->lock);
- 130 do-while (0)
  131    priv->rdtodo = 0;
  132    priv->wrfilled = 0;
  133    priv->wrsent = 0;
  134    usb_set_serial_port_data(serial->port[0], priv);
  135 
  136    init_waitqueue_head(&serial->port[0]->write_wait);
  137 
- 138    for (i = 0; i < serial->num_ports; ++i) {
  139       int result;
  140       serial->port[i]->interrupt_in_urb->dev = serial->dev;
  141       result = usb_submit_urb(serial->port[i]->interrupt_in_urb, 
  142                GFP_KERNEL);
- 143       if (result)
  144          err(" usb_submit_urb(read int) failed");
    145       dbg("%s - usb_submit_urb(int urb)", __FUNCTION__);
- 145     if (debug)
- 145   do-while (0)
  146    }
  147 
 - 148    return( 0 );
  149 }
  150 
 
- 151 static void cyberjack_shutdown (struct usb_serial *serial)
  152 {
  153    int i;
  154    
    155    dbg("%s", __FUNCTION__);
- 155   if (debug)
- 155 do-while (0)
  156 
- 157    for (i=0; i < serial->num_ports; ++i) {
  158       usb_kill_urb(serial->port[i]->interrupt_in_urb);
  159       /* My special items, the standard routines free my urbs */
  160       kfree(usb_get_serial_port_data(serial->port[i]));
  161       usb_set_serial_port_data(serial->port[i], NULL);
  162    }
  163 }
  164    
 
- 165 static int  cyberjack_open (struct usb_serial_port *port, struct file *filp)
  166 {
  167    struct cyberjack_private *priv;
  168    unsigned long flags;
  169    int result = 0;
  170 
    171    dbg("%s - port %d", __FUNCTION__, port->number);
- 171   if (debug)
- 171 do-while (0)
  172 
    173    dbg("%s - usb_clear_halt", __FUNCTION__ );
- 173   if (debug)
- 173 do-while (0)
  174    usb_clear_halt(port->serial->dev, port->write_urb->pipe);
  175 
  176    /* force low_latency on so that our tty_push actually forces
  177     * the data through, otherwise it is scheduled, and with high
  178     * data rates (like with OHCI) data can get lost.
  179     */
  180    port->tty->low_latency = 1;
  181 
  182    priv = usb_get_serial_port_data(port);
    183    spin_lock_irqsave(&priv->lock, flags);
    183   do
    183     do
- 183     do-while (0)
- 183   do-while (0)
    183   do
    183     do
- 183     do-while (0)
- 183   do-while (0)
- 183 do-while (0)
  184    priv->rdtodo = 0;
  185    priv->wrfilled = 0;
  186    priv->wrsent = 0;
    187    spin_unlock_irqrestore(&priv->lock, flags);
    187   do
    187     do
- 187     do-while (0)
- 187   do-while (0)
- 187 do-while (0)
  188 
 - 189    return result;
  190 }
  191 
 
- 192 static void cyberjack_close (struct usb_serial_port *port, struct file *filp)
  193 {
    194    dbg("%s - port %d", __FUNCTION__, port->number);
- 194   if (debug)
- 194 do-while (0)
  195 
- 196    if (port->serial->dev) {
  197       /* shutdown any bulk reads that might be going on */
  198       usb_kill_urb(port->write_urb);
  199       usb_kill_urb(port->read_urb);
  200    }
  201 }
  202 
 
- 203 static int cyberjack_write (struct usb_serial_port *port, const unsigned char *buf, int count)
  204 {
  205    struct usb_serial *serial = port->serial;
  206    struct cyberjack_private *priv = usb_get_serial_port_data(port);
  207    unsigned long flags;
  208    int result;
  209    int wrexpected;
  210 
    211    dbg("%s - port %d", __FUNCTION__, port->number);
- 211   if (debug)
- 211 do-while (0)
  212 
- 213    if (count == 0) {
    214       dbg("%s - write request of 0 bytes", __FUNCTION__);
- 214     if (debug)
- 214   do-while (0)
 - 215       return (0);
  216    }
  217 
    218    spin_lock(&port->lock);
    218   do
- 218   do-while (0)
- 218 do-while (0)
- 219    if (port->write_urb_busy) {
    220       spin_unlock(&port->lock);
    220     do
- 220     do-while (0)
- 220   do-while (0)
    221       dbg("%s - already writing", __FUNCTION__);
- 221     if (debug)
- 221   do-while (0)
 - 222       return 0;
  223    }
  224    port->write_urb_busy = 1;
    225    spin_unlock(&port->lock);
    225   do
- 225   do-while (0)
- 225 do-while (0)
  226 
    227    spin_lock_irqsave(&priv->lock, flags);
    227   do
    227     do
- 227     do-while (0)
- 227   do-while (0)
    227   do
    227     do
- 227     do-while (0)
- 227   do-while (0)
- 227 do-while (0)
  228 
- 229    if( (count+priv->wrfilled)>sizeof(priv->wrbuf) ) {
  230       /* To much data for buffer. Reset buffer. */
  231       priv->wrfilled=0;
    232       spin_unlock_irqrestore(&priv->lock, flags);
    232     do
    232       do
- 232       do-while (0)
- 232     do-while (0)
- 232   do-while (0)
  233       port->write_urb_busy = 0;
 - 234       return (0);
  235    }
  236 
  237    /* Copy data */
  238    memcpy (priv->wrbuf+priv->wrfilled, buf, count);
  239 
  240    usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count,
  241       priv->wrbuf+priv->wrfilled);
  242    priv->wrfilled += count;
  243 
- 244    if( priv->wrfilled >= 3 ) {
  245       wrexpected = ((int)priv->wrbuf[2]<<8)+priv->wrbuf[1]+3;
    246       dbg("%s - expected data: %d", __FUNCTION__, wrexpected);
- 246     if (debug)
- 246   do-while (0)
    247    } else {
  248       wrexpected = sizeof(priv->wrbuf);
  249    }
  250 
- 251    if( priv->wrfilled >= wrexpected ) {
  252       /* We have enough data to begin transmission */
  253       int length;
  254 
    255       dbg("%s - transmitting data (frame 1)", __FUNCTION__);
- 255     if (debug)
- 255   do-while (0)
    256       length = (wrexpected > port->bulk_out_size) ? port->bulk_out_size : wrexpected;
- 256   ternary-?: ( wrexpected > port -> bulk_out_s..
  257 
  258       memcpy (port->write_urb->transfer_buffer, priv->wrbuf, length );
  259       priv->wrsent=length;
  260 
  261       /* set up our urb */
  262       usb_fill_bulk_urb(port->write_urb, serial->dev, 
  263                usb_sndbulkpipe(serial->dev, port->bulk_out_endpointAddress),
  264                port->write_urb->transfer_buffer, length,
    265                ((serial->type->write_bulk_callback) ? 
- 265   ternary-?: ( serial -> type -> write_bulk_ca..
  266                 serial->type->write_bulk_callback : 
  267                 cyberjack_write_bulk_callback), 
  268                port);
  269 
  270       /* send the data out the bulk port */
  271       result = usb_submit_urb(port->write_urb, GFP_ATOMIC);
- 272       if (result) {
  273          err("%s - failed submitting write urb, error %d", __FUNCTION__, result);
  274          /* Throw away data. No better idea what to do with it. */
  275          priv->wrfilled=0;
  276          priv->wrsent=0;
    277          spin_unlock_irqrestore(&priv->lock, flags);
    277       do
    277         do
- 277         do-while (0)
- 277       do-while (0)
- 277     do-while (0)
  278          port->write_urb_busy = 0;
 - 279          return 0;
  280       }
  281 
    282       dbg("%s - priv->wrsent=%d", __FUNCTION__,priv->wrsent);
- 282     if (debug)
- 282   do-while (0)
    283       dbg("%s - priv->wrfilled=%d", __FUNCTION__,priv->wrfilled);
- 283     if (debug)
- 283   do-while (0)
  284 
- 285       if( priv->wrsent>=priv->wrfilled ) {
    286          dbg("%s - buffer cleaned", __FUNCTION__);
- 286       if (debug)
- 286     do-while (0)
  287          memset( priv->wrbuf, 0, sizeof(priv->wrbuf) );
  288          priv->wrfilled=0;
  289          priv->wrsent=0;
  290       }
  291    }
  292 
    293    spin_unlock_irqrestore(&priv->lock, flags);
    293   do
    293     do
- 293     do-while (0)
- 293   do-while (0)
- 293 do-while (0)
  294 
 - 295    return (count);
  296 
  297 
 
- 298 static int cyberjack_write_room( struct usb_serial_port *port )
  299 {
 - 300    return CYBERJACK_LOCAL_BUF_SIZE;
  301 }
  302 
 
- 303 static void cyberjack_read_int_callback( struct urb *urb, struct pt_regs *regs )
  304 {
  305    struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
  306    struct cyberjack_private *priv = usb_get_serial_port_data(port);
  307    unsigned char *data = urb->transfer_buffer;
  308    int result;
  309 
    310    dbg("%s - port %d", __FUNCTION__, port->number);
- 310   if (debug)
- 310 do-while (0)
  311 
  312    /* the urb might have been killed. */
- 313    if (urb->status)
 - 314       return;
  315 
  316    usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
  317 
  318    /* React only to interrupts signaling a bulk_in transfer */
- 319    if( (urb->actual_length==4) && (data[0]==0x01) ) {
 - 319   (T) && (T)
 - 319   (T) && (F)
 - 319   (F) && (_)
  320       short old_rdtodo;
  321       int result;
  322 
  323       /* This is a announcement of coming bulk_ins. */
  324       unsigned short size = ((unsigned short)data[3]<<8)+data[2]+3;
  325 
    326       spin_lock(&priv->lock);
    326     do
- 326     do-while (0)
- 326   do-while (0)
  327 
  328       old_rdtodo = priv->rdtodo;
  329 
- 330       if( (old_rdtodo+size)<(old_rdtodo) ) {
    331          dbg( "To many bulk_in urbs to do." );
- 331       if (debug)
- 331     do-while (0)
    332          spin_unlock(&priv->lock);
    332       do
- 332       do-while (0)
- 332     do-while (0)
 - 333          goto resubmit;
  334       }
  335 
  336       /* "+=" is probably more fault tollerant than "=" */
  337       priv->rdtodo += size;
  338 
    339       dbg("%s - rdtodo: %d", __FUNCTION__, priv->rdtodo);
- 339     if (debug)
- 339   do-while (0)
  340 
    341       spin_unlock(&priv->lock);
    341     do
- 341     do-while (0)
- 341   do-while (0)
  342 
- 343       if( !old_rdtodo ) {
  344          port->read_urb->dev = port->serial->dev;
  345          result = usb_submit_urb(port->read_urb, GFP_ATOMIC);
- 346          if( result )
  347             err("%s - failed resubmitting read urb, error %d", __FUNCTION__, result);
    348          dbg("%s - usb_submit_urb(read urb)", __FUNCTION__);
- 348       if (debug)
- 348     do-while (0)
  349       }
  350    }
  351 
  352 resubmit:
  353    port->interrupt_in_urb->dev = port->serial->dev;
  354    result = usb_submit_urb(port->interrupt_in_urb, GFP_ATOMIC);
- 355    if (result)
  356       err(" usb_submit_urb(read int) failed");
    357    dbg("%s - usb_submit_urb(int urb)", __FUNCTION__);
- 357   if (debug)
- 357 do-while (0)
  358 }
  359 
 
- 360 static void cyberjack_read_bulk_callback (struct urb *urb, struct pt_regs *regs)
  361 {
  362    struct usb_serial_port *port = (struct usb_serial_port *)urb->context;
  363    struct cyberjack_private *priv = usb_get_serial_port_data(port);
  364    struct tty_struct *tty;
  365    unsigned char *data = urb->transfer_buffer;
  366    short todo;
  367    int result;
  368 
    369    dbg("%s - port %d", __FUNCTION__, port->number);
- 369   if (debug)
- 369 do-while (0)
  370    
  371    usb_serial_debug_data(debug, &port->dev, __FUNCTION__, urb->actual_length, data);
- 372    if (urb->status) {
    373       dbg("%s - nonzero read bulk status received: %d", __FUNCTION__, urb->status);
- 373     if (debug)
- 373   do-while (0)
 - 374       return;
  375    }
  376 
  377    tty = port->tty;
- 378    if (!tty) {
    379       dbg("%s - ignoring since device not open\n", __FUNCTION__);
- 379     if (debug)
- 379   do-while (0)
 - 380       return;
  381    }
- 382    if (urb->actual_length) {
  383       tty_buffer_request_room(tty, urb->actual_length);
  384       tty_insert_flip_string(tty, data, urb->actual_length);
  385         tty_flip_buffer_push(tty);
  386    }
  387 
    388    spin_lock(&priv->lock);
    388   do
- 388   do-while (0)
- 388 do-while (0)
  389 
  390    /* Reduce urbs to do by one. */
  391    priv->rdtodo-=urb->actual_length;
  392    /* Just to be sure */
- 393    if ( priv->rdtodo<0 ) priv->rdtodo = 0;
  394    todo = priv->rdtodo;
  395 
    396    spin_unlock(&priv->lock);
    396   do
- 396   do-while (0)
- 396 do-while (0)
  397 
    398    dbg("%s - rdtodo: %d", __FUNCTION__, todo);
- 398