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

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


File: drivers/usb/misc/ldusb.c
Instrumentation mode: function-decision-multicondition
TER: 1 % ( 3/271)

Start/ End/    
True False - Line Source

  1 /**
  2  * Generic USB driver for report based interrupt in/out devices
  3  * like LD Didactic's USB devices. LD Didactic's USB devices are
  4  * HID devices which do not use HID report definitons (they use
  5  * raw interrupt in and our reports only for communication).
  6  *
  7  * This driver uses a ring buffer for time critical reading of
  8  * interrupt in reports and provides read and write methods for
  9  * raw interrupt reports (similar to the Windows HID driver).
  10  * Devices based on the book USB COMPLETE by Jan Axelson may need
  11  * such a compatibility to the Windows HID driver.
  12  *
  13  * Copyright (C) 2005 Michael Hund <mhund@ld-didactic.de>
  14  *
  15  *   This program is free software; you can redistribute it and/or
  16  *   modify it under the terms of the GNU General Public License as
  17  *   published by the Free Software Foundation; either version 2 of
  18  *   the License, or (at your option) any later version.
  19  *
  20  * Derived from Lego USB Tower driver
  21  * Copyright (C) 2003 David Glance <advidgsf@sourceforge.net>
  22  *       2001-2004 Juergen Stuber <starblue@users.sourceforge.net>
  23  *
  24  * V0.1  (mh) Initial version
  25  * V0.11 (mh) Added raw support for HID 1.0 devices (no interrupt out endpoint)
  26  * V0.12 (mh) Added kmalloc check for string buffer
  27  * V0.13 (mh) Added support for LD X-Ray and Machine Test System
  28  */
  29 
  30 #include <linux/config.h>
  31 #include <linux/kernel.h>
  32 #include <linux/errno.h>
  33 #include <linux/init.h>
  34 #include <linux/slab.h>
  35 #include <linux/module.h>
  36 
  37 #include <asm/uaccess.h>
  38 #include <linux/input.h>
  39 #include <linux/usb.h>
  40 #include <linux/poll.h>
  41 
  42 /* Define these values to match your devices */
  43 #define USB_VENDOR_ID_LD      0x0f11   /* USB Vendor ID of LD Didactic GmbH */
  44 #define USB_DEVICE_ID_LD_CASSY      0x1000   /* USB Product ID of CASSY-S */
  45 #define USB_DEVICE_ID_LD_POCKETCASSY   0x1010   /* USB Product ID of Pocket-CASSY */
  46 #define USB_DEVICE_ID_LD_MOBILECASSY   0x1020   /* USB Product ID of Mobile-CASSY */
  47 #define USB_DEVICE_ID_LD_JWM      0x1080   /* USB Product ID of Joule and Wattmeter */
  48 #define USB_DEVICE_ID_LD_DMMP      0x1081   /* USB Product ID of Digital Multimeter P (reserved) */
  49 #define USB_DEVICE_ID_LD_UMIP      0x1090   /* USB Product ID of UMI P */
  50 #define USB_DEVICE_ID_LD_XRAY1      0x1100   /* USB Product ID of X-Ray Apparatus */
  51 #define USB_DEVICE_ID_LD_XRAY2      0x1101   /* USB Product ID of X-Ray Apparatus */
  52 #define USB_DEVICE_ID_LD_VIDEOCOM   0x1200   /* USB Product ID of VideoCom */
  53 #define USB_DEVICE_ID_LD_COM3LAB   0x2000   /* USB Product ID of COM3LAB */
  54 #define USB_DEVICE_ID_LD_TELEPORT   0x2010   /* USB Product ID of Terminal Adapter */
  55 #define USB_DEVICE_ID_LD_NETWORKANALYSER 0x2020   /* USB Product ID of Network Analyser */
  56 #define USB_DEVICE_ID_LD_POWERCONTROL   0x2030   /* USB Product ID of Converter Control Unit */
  57 #define USB_DEVICE_ID_LD_MACHINETEST   0x2040   /* USB Product ID of Machine Test System */
  58 
  59 #define USB_VENDOR_ID_VERNIER      0x08f7
  60 #define USB_DEVICE_ID_VERNIER_LABPRO   0x0001
  61 #define USB_DEVICE_ID_VERNIER_GOTEMP   0x0002
  62 #define USB_DEVICE_ID_VERNIER_SKIP   0x0003
  63 #define USB_DEVICE_ID_VERNIER_CYCLOPS   0x0004
  64 
  65 
  66 #ifdef CONFIG_USB_DYNAMIC_MINORS
  67 #define USB_LD_MINOR_BASE   0
  68 #else
  69 #define USB_LD_MINOR_BASE   176
  70 #endif
  71 
  72 /* table of devices that work with this driver */
  73 static struct usb_device_id ld_usb_table [] = {
  74    { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_CASSY) },
  75    { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_POCKETCASSY) },
  76    { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MOBILECASSY) },
  77    { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_JWM) },
  78    { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_DMMP) },
  79    { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_UMIP) },
  80    { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_XRAY1) },
  81    { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_XRAY2) },
  82    { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_VIDEOCOM) },
  83    { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_COM3LAB) },
  84    { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_TELEPORT) },
  85    { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_NETWORKANALYSER) },
  86    { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_POWERCONTROL) },
  87    { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_LD_MACHINETEST) },
  88    { USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_LABPRO) },
  89    { USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_GOTEMP) },
  90    { USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_SKIP) },
  91    { USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_CYCLOPS) },
  92    { }               /* Terminating entry */
  93 };
  94 MODULE_DEVICE_TABLE(usb, ld_usb_table);
  95 MODULE_VERSION("V0.13");
  96 MODULE_AUTHOR("Michael Hund <mhund@ld-didactic.de>");
  97 MODULE_DESCRIPTION("LD USB Driver");
  98 MODULE_LICENSE("GPL");
  99 MODULE_SUPPORTED_DEVICE("LD USB Devices");
  100 
  101 #ifdef CONFIG_USB_DEBUG
  102    static int debug = 1;
  103 #else
  104    static int debug = 0;
  105 #endif
  106 
  107 /* Use our own dbg macro */
  108 #define dbg_info(dev, format, arg...) do { if (debug) dev_info(dev , format , ## arg); } while (0)
  109 
  110 /* Module parameters */
 
- 111 module_param(debug, int, S_IRUGO | S_IWUSR);
 - 111 return ( & ( debug ) )
  112 MODULE_PARM_DESC(debug, "Debug enabled or not");
  113 
  114 /* All interrupt in transfers are collected in a ring buffer to
  115  * avoid racing conditions and get better performance of the driver.
  116  */
  117 static int ring_buffer_size = 128;
 
- 118 module_param(ring_buffer_size, int, 0);
 - 118 return ( & ( ring_buffer_size ) )
  119 MODULE_PARM_DESC(ring_buffer_size, "Read ring buffer size in reports");
  120 
  121 /* The write_buffer can contain more than one interrupt out transfer.
  122  */
  123 static int write_buffer_size = 10;
 
- 124 module_param(write_buffer_size, int, 0);
 - 124 return ( & ( write_buffer_size ) )
  125 MODULE_PARM_DESC(write_buffer_size, "Write buffer size in reports");
  126 
  127 /* As of kernel version 2.6.4 ehci-hcd uses an
  128  * "only one interrupt transfer per frame" shortcut
  129  * to simplify the scheduling of periodic transfers.
  130  * This conflicts with our standard 1ms intervals for in and out URBs.
  131  * We use default intervals of 2ms for in and 2ms for out transfers,
  132  * which should be fast enough.
  133  * Increase the interval to allow more devices that do interrupt transfers,
  134  * or set to 1 to use the standard interval from the endpoint descriptors.
  135  */
  136 static int min_interrupt_in_interval = 2;
 
- 137 module_param(min_interrupt_in_interval, int, 0);
 - 137 return ( & ( min_interrupt_in_interval ) )
  138 MODULE_PARM_DESC(min_interrupt_in_interval, "Minimum interrupt in interval in ms");
  139 
  140 static int min_interrupt_out_interval = 2;
 
- 141 module_param(min_interrupt_out_interval, int, 0);
 - 141 return ( & ( min_interrupt_out_interval ) )
  142 MODULE_PARM_DESC(min_interrupt_out_interval, "Minimum interrupt out interval in ms");
  143 
  144 /* Structure to hold all of our device specific stuff */
  145 struct ld_usb {
  146    struct semaphore   sem;      /* locks this structure */
  147    struct usb_interface*   intf;      /* save off the usb interface pointer */
  148 
  149    int         open_count;   /* number of times this port has been opened */
  150 
  151    char*         ring_buffer;
  152    unsigned int      ring_head;
  153    unsigned int      ring_tail;
  154 
  155    wait_queue_head_t   read_wait;
  156    wait_queue_head_t   write_wait;
  157 
  158    char*         interrupt_in_buffer;
  159    struct usb_endpoint_descriptor* interrupt_in_endpoint;
  160    struct urb*      interrupt_in_urb;
  161    int         interrupt_in_interval;
  162    size_t         interrupt_in_endpoint_size;
  163    int         interrupt_in_running;
  164    int         interrupt_in_done;
  165 
  166    char*         interrupt_out_buffer;
  167    struct usb_endpoint_descriptor* interrupt_out_endpoint;
  168    struct urb*      interrupt_out_urb;
  169    int         interrupt_out_interval;
  170    size_t         interrupt_out_endpoint_size;
  171    int         interrupt_out_busy;
  172 };
  173 
  174 /* prevent races between open() and disconnect() */
  175 static DECLARE_MUTEX(disconnect_sem);
  176 
  177 static struct usb_driver ld_usb_driver;
  178 
  179 /**
  180  *   ld_usb_abort_transfers
  181  *      aborts transfers and frees associated data structures
  182  */
 
- 183 static void ld_usb_abort_transfers(struct ld_usb *dev)
  184 {
  185    /* shutdown transfer */
- 186    if (dev->interrupt_in_running) {
  187       dev->interrupt_in_running = 0;
- 188       if (dev->intf)
  189          usb_kill_urb(dev->interrupt_in_urb);
  190    }
- 191    if (dev->interrupt_out_busy)
- 192       if (dev->intf)
  193          usb_kill_urb(dev->interrupt_out_urb);
  194 }
  195 
  196 /**
  197  *   ld_usb_delete
  198  */
 
- 199 static void ld_usb_delete(struct ld_usb *dev)
  200 {
  201    ld_usb_abort_transfers(dev);
  202 
  203    /* free data structures */
  204    usb_free_urb(dev->interrupt_in_urb);
  205    usb_free_urb(dev->interrupt_out_urb);
  206    kfree(dev->ring_buffer);
  207    kfree(dev->interrupt_in_buffer);
  208    kfree(dev->interrupt_out_buffer);
  209    kfree(dev);
  210 }
  211 
  212 /**
  213  *   ld_usb_interrupt_in_callback
  214  */
 
- 215 static void ld_usb_interrupt_in_callback(struct urb *urb, struct pt_regs *regs)
  216 {
  217    struct ld_usb *dev = urb->context;
  218    size_t *actual_buffer;
  219    unsigned int next_ring_head;
  220    int retval;
  221 
- 222    if (urb->status) {
  223       if (urb->status == -ENOENT ||
  224           urb->status == -ECONNRESET ||
- 225           urb->status == -ESHUTDOWN) {
 - 225     T || _ || _
 - 225     F || T || _
 - 225     F || F || T
 - 225     F || F || F
 - 226          goto exit;
    227       } else {
    228          dbg_info(&dev->intf->dev, "%s: nonzero status received: %d\n",
- 228       if (debug)
- 228         ternary-?: ( & dev -> intf -> dev ) ->..
- 228     do-while (0)
  229              __FUNCTION__, urb->status);
 - 230          goto resubmit; /* maybe we can recover */
  231       }
  232    }
  233 
- 234    if (urb->actual_length > 0) {
  235       next_ring_head = (dev->ring_head+1) % ring_buffer_size;
- 236       if (next_ring_head != dev->ring_tail) {
  237          actual_buffer = (size_t*)(dev->ring_buffer + dev->ring_head*(sizeof(size_t)+dev->interrupt_in_endpoint_size));
  238          /* actual_buffer gets urb->actual_length + interrupt_in_buffer */
  239          *actual_buffer = urb->actual_length;
  240          memcpy(actual_buffer+1, dev->interrupt_in_buffer, urb->actual_length);
  241          dev->ring_head = next_ring_head;
    242          dbg_info(&dev->intf->dev, "%s: received %d bytes\n",
- 242       if (debug)
- 242         ternary-?: ( & dev -> intf -> dev ) ->..
- 242     do-while (0)
  243              __FUNCTION__, urb->actual_length);
    244       } else
    245          dev_warn(&dev->intf->dev,
- 245     ternary-?: ( & dev -> intf -> dev ) -> dri..
  246              "Ring buffer overflow, %d bytes dropped\n",
  247              urb->actual_length);
  248    }
  249 
  250 resubmit:
  251    /* resubmit if we're still running */
- 252    if (dev->interrupt_in_running && dev->intf) {
 - 252   T && T
 - 252   T && F
 - 252   F && _
  253       retval = usb_submit_urb(dev->interrupt_in_urb, GFP_ATOMIC);
- 254       if (retval)
    255          dev_err(&dev->intf->dev,
- 255     ternary-?: ( & dev -> intf -> dev ) -> dri..
  256             "usb_submit_urb failed (%d)\n", retval);
  257    }
  258 
  259 exit:
  260    dev->interrupt_in_done = 1;
  261    wake_up_interruptible(&dev->read_wait);
  262 }
  263 
  264 /**
  265  *   ld_usb_interrupt_out_callback
  266  */
 
- 267 static void ld_usb_interrupt_out_callback(struct urb *urb, struct pt_regs *regs)
  268 {
  269    struct ld_usb *dev = urb->context;
  270 
  271    /* sync/async unlink faults aren't errors */
  272    if (urb->status && !(urb->status == -ENOENT ||
  273               urb->status == -ECONNRESET ||
- 274               urb->status == -ESHUTDOWN))
 - 274   T && !(F || F || F)
 - 274   T && !(T || _ || _)
 - 274   T && !(F || T || _)
 - 274   T && !(F || F || T)
 - 274   F && !(_ || _ || _)
    275       dbg_info(&dev->intf->dev,
- 275     if (debug)
- 275       ternary-?: ( & dev -> intf -> dev ) -> d..
- 275   do-while (0)
  276           "%s - nonzero write interrupt status received: %d\n",
  277           __FUNCTION__, urb->status);
  278 
  279    dev->interrupt_out_busy = 0;
  280    wake_up_interruptible(&dev->write_wait);
  281 }
  282 
  283 /**
  284  *   ld_usb_open
  285  */
 
- 286 static int ld_usb_open(struct inode *inode, struct file *file)
  287 {
  288    struct ld_usb *dev;
  289    int subminor;
  290    int retval = 0;
  291    struct usb_interface *interface;
  292 
  293    nonseekable_open(inode, file);
  294    subminor = iminor(inode);
  295 
  296    down(&disconnect_sem);
  297 
  298    interface = usb_find_interface(&ld_usb_driver, subminor);
  299 
- 300    if (!interface) {
  301       err("%s - error, can't find device for minor %d\n",
  302            __FUNCTION__, subminor);
  303       retval = -ENODEV;
 - 304       goto unlock_disconnect_exit;
  305    }
  306 
  307    dev = usb_get_intfdata(interface);
  308 
- 309    if (!dev) {
  310       retval = -ENODEV;
 - 311       goto unlock_disconnect_exit;
  312    }
  313 
  314    /* lock this device */
- 315    if (down_interruptible(&dev->sem)) {
  316       retval = -ERESTARTSYS;
 - 317       goto unlock_disconnect_exit;
  318    }
  319 
  320    /* allow opening only once */
- 321    if (dev->open_count) {
  322       retval = -EBUSY;
 - 323       goto unlock_exit;
  324    }
  325    dev->open_count = 1;
  326 
  327    /* initialize in direction */
  328    dev->ring_head = 0;
  329    dev->ring_tail = 0;
  330    usb_fill_int_urb(dev->interrupt_in_urb,
  331           interface_to_usbdev(interface),
  332           usb_rcvintpipe(interface_to_usbdev(interface),
  333                dev->interrupt_in_endpoint->bEndpointAddress),
  334           dev->interrupt_in_buffer,
  335           dev->interrupt_in_endpoint_size,
  336           ld_usb_interrupt_in_callback,
  337           dev,
  338           dev->interrupt_in_interval);
  339 
  340    dev->interrupt_in_running = 1;
  341    dev->interrupt_in_done = 0;
  342 
  343    retval = usb_submit_urb(dev->interrupt_in_urb, GFP_KERNEL);
- 344    if (retval) {
    345       dev_err(&interface->dev, "Couldn't submit interrupt_in_urb %d\n", retval);
- 345   ternary-?: ( & interface -> dev ) -> driver
  346       dev->interrupt_in_running = 0;
  347       dev->open_count = 0;
 - 348       goto unlock_exit;
  349    }
  350 
  351    /* save device in the file's private structure */
  352    file->private_data = dev;
  353 
  354 unlock_exit:
  355    up(&dev->sem);
  356 
  357 unlock_disconnect_exit:
  358    up(&disconnect_sem);
  359 
 - 360    return retval;
  361 }
  362 
  363 /**
  364  *   ld_usb_release
  365  */
 
- 366 static int ld_usb_release(struct inode *inode, struct file *file)
  367 {
  368    struct ld_usb *dev;
  369    int retval = 0;
  370 
  371    dev = file->private_data;
  372 
- 373    if (dev == NULL) {
  374       retval = -ENODEV;
 - 375       goto exit;
  376    }
  377 
- 378    if (down_interruptible(&dev->sem)) {
  379       retval = -ERESTARTSYS;
 - 380       goto exit;
  381    }
  382 
- 383    if (dev->open_count != 1) {
  384       retval = -ENODEV;
 - 385       goto unlock_exit;
  386    }
- 387    if (dev->intf == NULL) {
  388       /* the device was unplugged before the file was released */
  389       up(&dev->sem);
  390       /* unlock here as ld_usb_delete frees dev */
  391       ld_usb_delete(dev);
 - 392       goto exit;
  393    }
  394 
  395    /* wait until write transfer is finished */
- 396    if (dev->interrupt_out_busy)
  397       wait_event_interruptible_timeout(dev->write_wait, !dev->interrupt_out_busy, 2 * HZ);
  398    ld_usb_abort_transfers(dev);
  399    dev->open_count = 0;
  400 
  401 unlock_exit:
  402    up(&dev->sem);
  403 
  404 exit:
 - 405    return retval;
  406 }
  407 
  408 /**
  409  *   ld_usb_poll
  410  */
 
- 411 static unsigned int ld_usb_poll(struct file *file, poll_table *wait)
  412 {
  413    struct ld_usb *dev;
  414    unsigned int mask = 0;
  415 
  416    dev = file->private_data;
  417 
  418    poll_wait(file, &dev->read_wait, wait);
  419    poll_wait(file, &dev->write_wait, wait);
  420 
- 421    if (dev->ring_head != dev->ring_tail)
  422       mask |= POLLIN | POLLRDNORM;
- 423    if (!dev->interrupt_out_busy)
  424       mask |= POLLOUT | POLLWRNORM;
  425 
 - 426    return mask;
  427 }
  428 
  429 /**
  430  *   ld_usb_read
  431  */
 
- 432 static ssize_t ld_usb_read(struct file *file, char __user *buffer, size_t count,
  433             loff_t *ppos)
  434 {
  435    struct ld_usb *dev;
  436    size_t *actual_buffer;
  437    size_t bytes_to_read;
  438    int retval = 0;
  439 
  440    dev = file->private_data;
  441 
  442    /* verify that we actually have some data to read */
- 443    if (count == 0)
 - 444       goto exit;
  445 
  446    /* lock this object */
- 447    if (down_interruptible(&dev->sem)) {
  448       retval = -ERESTARTSYS;
 - 449       goto exit;
  450    }
  451 
  452    /* verify that the device wasn't unplugged */
- 453    if (dev->intf == NULL) {
  454       retval = -ENODEV;
  455       err("No device or device unplugged %d\n", retval);
 - 456       goto unlock_exit;
  457    }
  458 
  459    /* wait for data */
- 460    if (dev->ring_head == dev->ring_tail) {
- 461       if (file->f_flags & O_NONBLOCK) {
  462          retval = -EAGAIN;
 - 463          goto unlock_exit;
  464       }
  465       retval = wait_event_interruptible(dev->read_wait, dev->interrupt_in_done);
- 466       if (retval < 0)
 - 467          goto unlock_exit;
  468    }
  469 
  470    /* actual_buffer contains actual_length + interrupt_in_buffer */
  471    actual_buffer = (size_t*)(dev->ring_buffer + dev->ring_tail*(sizeof(size_t)+dev->interrupt_in_endpoint_size));
  472    bytes_to_read = min(count, *actual_buffer);
- 473    if (bytes_to_read < *actual_buffer)
    474       dev_warn(&dev->intf->dev, "Read buffer overflow, %zd bytes dropped\n",
- 474   ternary-?: ( & dev -> intf -> dev ) -> driver
  475           *actual_buffer-bytes_to_read);
  476 
  477    /* copy one interrupt_in_buffer from ring_buffer into userspace */
- 478    if (copy_to_user(buffer, actual_buffer+1, bytes_to_read)) {
  479       retval = -EFAULT;
 - 480       goto unlock_exit;
  481    }
  482    dev->ring_tail = (dev->ring_tail+1) % ring_buffer_size;
  483 
  484    retval = bytes_to_read;
  485 
  486 unlock_exit:
  487    /* unlock the device */
  488    up(&dev->sem);
  489 
  490 exit:
 - 491    return retval;
  492 }
  493 
  494 /**
  495  *   ld_usb_write
  496  */
 
- 497 static ssize_t ld_usb_write(struct file *file, const char __user *buffer,
  498              size_t count, loff_t *ppos)
  499 {
  500    struct ld_usb *dev;
  501    size_t bytes_to_write;
  502    int retval = 0;
  503 
  504    dev = file->private_data;
  505 
  506    /* verify that we actually have some data to write */
- 507    if (count == 0)
 - 508       goto exit;
  509 
  510    /* lock this object */
- 511    if (down_interruptible(&dev->sem)) {
  512       retval = -ERESTARTSYS;
 - 513       goto exit;