Commit 2824bd250f0be1551747cc3ed5ae07facc285b57

Authored by Michael Hund
Committed by Greg Kroah-Hartman
1 parent 83ef344a75

[PATCH] USB: add ldusb driver

The following driver provides complete interrupt-in and interrupt-out
reports (raw data) to a user program. Until now it uses the
HIDIOCGDEVINFO ioctl call, because I don't know better :-(. Perhaps, it
will be ok for you - and I will be happy, if you assign 8 minor numbers.

I have tested it in several environments and it works very well for me.
However, it has a problem with two or more devices at the same hub, if
the two or more devices need 1 ms interrupt-in transfers. Unfortunately
more than one interrupt-in transfer every ms isn't possible (ehci
driver?). This is why the min_interrupt_in_interval and
min_interrupt_out_interval are increased to 2 ms (see the corresponding
module parameters). This way, I can use two devices simultaneously at
the same hub.

Signed-off-by: Michael Hund <mhund@ld-didactic.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

Showing 4 changed files with 806 additions and 0 deletions Side-by-side Diff

drivers/usb/Makefile
... ... @@ -65,6 +65,7 @@
65 65 obj-$(CONFIG_USB_EMI62) += misc/
66 66 obj-$(CONFIG_USB_IDMOUSE) += misc/
67 67 obj-$(CONFIG_USB_LCD) += misc/
  68 +obj-$(CONFIG_USB_LD) += misc/
68 69 obj-$(CONFIG_USB_LED) += misc/
69 70 obj-$(CONFIG_USB_LEGOTOWER) += misc/
70 71 obj-$(CONFIG_USB_RIO500) += misc/
drivers/usb/misc/Kconfig
... ... @@ -139,6 +139,16 @@
139 139  
140 140 source "drivers/usb/misc/sisusbvga/Kconfig"
141 141  
  142 +config USB_LD
  143 + tristate "USB LD driver"
  144 + depends on USB && EXPERIMENTAL
  145 + help
  146 + This driver is for generic USB devices that use interrupt transfers,
  147 + like LD Didactic's USB devices.
  148 +
  149 + To compile this driver as a module, choose M here: the
  150 + module will be called ldusb.
  151 +
142 152 config USB_TEST
143 153 tristate "USB testing driver (DEVELOPMENT)"
144 154 depends on USB && USB_DEVICEFS && EXPERIMENTAL
drivers/usb/misc/Makefile
... ... @@ -9,6 +9,7 @@
9 9 obj-$(CONFIG_USB_EMI62) += emi62.o
10 10 obj-$(CONFIG_USB_IDMOUSE) += idmouse.o
11 11 obj-$(CONFIG_USB_LCD) += usblcd.o
  12 +obj-$(CONFIG_USB_LD) += ldusb.o
12 13 obj-$(CONFIG_USB_LED) += usbled.o
13 14 obj-$(CONFIG_USB_LEGOTOWER) += legousbtower.o
14 15 obj-$(CONFIG_USB_PHIDGETKIT) += phidgetkit.o
drivers/usb/misc/ldusb.c
  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 + */
  27 +
  28 +#include <linux/config.h>
  29 +#include <linux/kernel.h>
  30 +#include <linux/errno.h>
  31 +#include <linux/init.h>
  32 +#include <linux/slab.h>
  33 +#include <linux/module.h>
  34 +
  35 +#include <asm/uaccess.h>
  36 +#include <linux/input.h>
  37 +#include <linux/usb.h>
  38 +#include <linux/poll.h>
  39 +
  40 +/* Define these values to match your devices */
  41 +#define USB_VENDOR_ID_LD 0x0f11 /* USB Vendor ID of LD Didactic GmbH */
  42 +#define USB_DEVICE_ID_CASSY 0x1000 /* USB Product ID for all CASSY-S modules */
  43 +#define USB_DEVICE_ID_POCKETCASSY 0x1010 /* USB Product ID for Pocket-CASSY */
  44 +#define USB_DEVICE_ID_MOBILECASSY 0x1020 /* USB Product ID for Mobile-CASSY */
  45 +#define USB_DEVICE_ID_JWM 0x1080 /* USB Product ID for Joule and Wattmeter */
  46 +#define USB_DEVICE_ID_DMMP 0x1081 /* USB Product ID for Digital Multimeter P (reserved) */
  47 +#define USB_DEVICE_ID_UMIP 0x1090 /* USB Product ID for UMI P */
  48 +#define USB_DEVICE_ID_VIDEOCOM 0x1200 /* USB Product ID for VideoCom */
  49 +#define USB_DEVICE_ID_COM3LAB 0x2000 /* USB Product ID for COM3LAB */
  50 +#define USB_DEVICE_ID_TELEPORT 0x2010 /* USB Product ID for Terminal Adapter */
  51 +#define USB_DEVICE_ID_NETWORKANALYSER 0x2020 /* USB Product ID for Network Analyser */
  52 +#define USB_DEVICE_ID_POWERCONTROL 0x2030 /* USB Product ID for Controlling device for Power Electronics */
  53 +
  54 +#define USB_VENDOR_ID_VERNIER 0x08f7
  55 +#define USB_DEVICE_ID_VERNIER_LABPRO 0x0001
  56 +#define USB_DEVICE_ID_VERNIER_GOTEMP 0x0002
  57 +#define USB_DEVICE_ID_VERNIER_SKIP 0x0003
  58 +#define USB_DEVICE_ID_VERNIER_CYCLOPS 0x0004
  59 +
  60 +
  61 +#ifdef CONFIG_USB_DYNAMIC_MINORS
  62 +#define USB_LD_MINOR_BASE 0
  63 +#else
  64 +#define USB_LD_MINOR_BASE 176
  65 +#endif
  66 +
  67 +/* table of devices that work with this driver */
  68 +static struct usb_device_id ld_usb_table [] = {
  69 + { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_CASSY) },
  70 + { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_POCKETCASSY) },
  71 + { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_MOBILECASSY) },
  72 + { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_JWM) },
  73 + { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_DMMP) },
  74 + { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_UMIP) },
  75 + { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_VIDEOCOM) },
  76 + { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_COM3LAB) },
  77 + { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_TELEPORT) },
  78 + { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_NETWORKANALYSER) },
  79 + { USB_DEVICE(USB_VENDOR_ID_LD, USB_DEVICE_ID_POWERCONTROL) },
  80 + { USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_LABPRO) },
  81 + { USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_GOTEMP) },
  82 + { USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_SKIP) },
  83 + { USB_DEVICE(USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_CYCLOPS) },
  84 + { } /* Terminating entry */
  85 +};
  86 +MODULE_DEVICE_TABLE(usb, ld_usb_table);
  87 +MODULE_VERSION("V0.11");
  88 +MODULE_AUTHOR("Michael Hund <mhund@ld-didactic.de>");
  89 +MODULE_DESCRIPTION("LD USB Driver");
  90 +MODULE_LICENSE("GPL");
  91 +MODULE_SUPPORTED_DEVICE("LD USB Devices");
  92 +
  93 +#ifdef CONFIG_USB_DEBUG
  94 + static int debug = 1;
  95 +#else
  96 + static int debug = 0;
  97 +#endif
  98 +
  99 +/* Use our own dbg macro */
  100 +#define dbg_info(dev, format, arg...) do { if (debug) dev_info(dev , format , ## arg); } while (0)
  101 +
  102 +/* Module parameters */
  103 +module_param(debug, int, S_IRUGO | S_IWUSR);
  104 +MODULE_PARM_DESC(debug, "Debug enabled or not");
  105 +
  106 +/* All interrupt in transfers are collected in a ring buffer to
  107 + * avoid racing conditions and get better performance of the driver.
  108 + */
  109 +static int ring_buffer_size = 128;
  110 +module_param(ring_buffer_size, int, 0);
  111 +MODULE_PARM_DESC(ring_buffer_size, "Read ring buffer size in reports");
  112 +
  113 +/* The write_buffer can contain more than one interrupt out transfer.
  114 + */
  115 +static int write_buffer_size = 10;
  116 +module_param(write_buffer_size, int, 0);
  117 +MODULE_PARM_DESC(write_buffer_size, "Write buffer size in reports");
  118 +
  119 +/* As of kernel version 2.6.4 ehci-hcd uses an
  120 + * "only one interrupt transfer per frame" shortcut
  121 + * to simplify the scheduling of periodic transfers.
  122 + * This conflicts with our standard 1ms intervals for in and out URBs.
  123 + * We use default intervals of 2ms for in and 2ms for out transfers,
  124 + * which should be fast enough.
  125 + * Increase the interval to allow more devices that do interrupt transfers,
  126 + * or set to 1 to use the standard interval from the endpoint descriptors.
  127 + */
  128 +static int min_interrupt_in_interval = 2;
  129 +module_param(min_interrupt_in_interval, int, 0);
  130 +MODULE_PARM_DESC(min_interrupt_in_interval, "Minimum interrupt in interval in ms");
  131 +
  132 +static int min_interrupt_out_interval = 2;
  133 +module_param(min_interrupt_out_interval, int, 0);
  134 +MODULE_PARM_DESC(min_interrupt_out_interval, "Minimum interrupt out interval in ms");
  135 +
  136 +/* Structure to hold all of our device specific stuff */
  137 +struct ld_usb {
  138 + struct semaphore sem; /* locks this structure */
  139 + struct usb_interface* intf; /* save off the usb interface pointer */
  140 +
  141 + int open_count; /* number of times this port has been opened */
  142 +
  143 + char* ring_buffer;
  144 + unsigned int ring_head;
  145 + unsigned int ring_tail;
  146 +
  147 + wait_queue_head_t read_wait;
  148 + wait_queue_head_t write_wait;
  149 +
  150 + char* interrupt_in_buffer;
  151 + struct usb_endpoint_descriptor* interrupt_in_endpoint;
  152 + struct urb* interrupt_in_urb;
  153 + int interrupt_in_interval;
  154 + size_t interrupt_in_endpoint_size;
  155 + int interrupt_in_running;
  156 + int interrupt_in_done;
  157 +
  158 + char* interrupt_out_buffer;
  159 + struct usb_endpoint_descriptor* interrupt_out_endpoint;
  160 + struct urb* interrupt_out_urb;
  161 + int interrupt_out_interval;
  162 + size_t interrupt_out_endpoint_size;
  163 + int interrupt_out_busy;
  164 +};
  165 +
  166 +/* prevent races between open() and disconnect() */
  167 +static DECLARE_MUTEX(disconnect_sem);
  168 +
  169 +static struct usb_driver ld_usb_driver;
  170 +
  171 +/**
  172 + * ld_usb_abort_transfers
  173 + * aborts transfers and frees associated data structures
  174 + */
  175 +static void ld_usb_abort_transfers(struct ld_usb *dev)
  176 +{
  177 + /* shutdown transfer */
  178 + if (dev->interrupt_in_running) {
  179 + dev->interrupt_in_running = 0;
  180 + if (dev->intf)
  181 + usb_kill_urb(dev->interrupt_in_urb);
  182 + }
  183 + if (dev->interrupt_out_busy)
  184 + if (dev->intf)
  185 + usb_kill_urb(dev->interrupt_out_urb);
  186 +}
  187 +
  188 +/**
  189 + * ld_usb_delete
  190 + */
  191 +static void ld_usb_delete(struct ld_usb *dev)
  192 +{
  193 + ld_usb_abort_transfers(dev);
  194 +
  195 + /* free data structures */
  196 + usb_free_urb(dev->interrupt_in_urb);
  197 + usb_free_urb(dev->interrupt_out_urb);
  198 + kfree(dev->ring_buffer);
  199 + kfree(dev->interrupt_in_buffer);
  200 + kfree(dev->interrupt_out_buffer);
  201 + kfree(dev);
  202 +}
  203 +
  204 +/**
  205 + * ld_usb_interrupt_in_callback
  206 + */
  207 +static void ld_usb_interrupt_in_callback(struct urb *urb, struct pt_regs *regs)
  208 +{
  209 + struct ld_usb *dev = urb->context;
  210 + size_t *actual_buffer;
  211 + unsigned int next_ring_head;
  212 + int retval;
  213 +
  214 + if (urb->status) {
  215 + if (urb->status == -ENOENT ||
  216 + urb->status == -ECONNRESET ||
  217 + urb->status == -ESHUTDOWN) {
  218 + goto exit;
  219 + } else {
  220 + dbg_info(&dev->intf->dev, "%s: nonzero status received: %d\n",
  221 + __FUNCTION__, urb->status);
  222 + goto resubmit; /* maybe we can recover */
  223 + }
  224 + }
  225 +
  226 + if (urb->actual_length > 0) {
  227 + next_ring_head = (dev->ring_head+1) % ring_buffer_size;
  228 + if (next_ring_head != dev->ring_tail) {
  229 + actual_buffer = (size_t*)(dev->ring_buffer + dev->ring_head*(sizeof(size_t)+dev->interrupt_in_endpoint_size));
  230 + /* actual_buffer gets urb->actual_length + interrupt_in_buffer */
  231 + *actual_buffer = urb->actual_length;
  232 + memcpy(actual_buffer+1, dev->interrupt_in_buffer, urb->actual_length);
  233 + dev->ring_head = next_ring_head;
  234 + dbg_info(&dev->intf->dev, "%s: received %d bytes\n",
  235 + __FUNCTION__, urb->actual_length);
  236 + } else
  237 + dev_warn(&dev->intf->dev,
  238 + "Ring buffer overflow, %d bytes dropped\n",
  239 + urb->actual_length);
  240 + }
  241 +
  242 +resubmit:
  243 + /* resubmit if we're still running */
  244 + if (dev->interrupt_in_running && dev->intf) {
  245 + retval = usb_submit_urb(dev->interrupt_in_urb, GFP_ATOMIC);
  246 + if (retval)
  247 + dev_err(&dev->intf->dev,
  248 + "usb_submit_urb failed (%d)\n", retval);
  249 + }
  250 +
  251 +exit:
  252 + dev->interrupt_in_done = 1;
  253 + wake_up_interruptible(&dev->read_wait);
  254 +}
  255 +
  256 +/**
  257 + * ld_usb_interrupt_out_callback
  258 + */
  259 +static void ld_usb_interrupt_out_callback(struct urb *urb, struct pt_regs *regs)
  260 +{
  261 + struct ld_usb *dev = urb->context;
  262 +
  263 + /* sync/async unlink faults aren't errors */
  264 + if (urb->status && !(urb->status == -ENOENT ||
  265 + urb->status == -ECONNRESET ||
  266 + urb->status == -ESHUTDOWN))
  267 + dbg_info(&dev->intf->dev,
  268 + "%s - nonzero write interrupt status received: %d\n",
  269 + __FUNCTION__, urb->status);
  270 +
  271 + dev->interrupt_out_busy = 0;
  272 + wake_up_interruptible(&dev->write_wait);
  273 +}
  274 +
  275 +/**
  276 + * ld_usb_open
  277 + */
  278 +static int ld_usb_open(struct inode *inode, struct file *file)
  279 +{
  280 + struct ld_usb *dev;
  281 + int subminor;
  282 + int retval = 0;
  283 + struct usb_interface *interface;
  284 +
  285 + nonseekable_open(inode, file);
  286 + subminor = iminor(inode);
  287 +
  288 + down(&disconnect_sem);
  289 +
  290 + interface = usb_find_interface(&ld_usb_driver, subminor);
  291 +
  292 + if (!interface) {
  293 + err("%s - error, can't find device for minor %d\n",
  294 + __FUNCTION__, subminor);
  295 + retval = -ENODEV;
  296 + goto unlock_disconnect_exit;
  297 + }
  298 +
  299 + dev = usb_get_intfdata(interface);
  300 +
  301 + if (!dev) {
  302 + retval = -ENODEV;
  303 + goto unlock_disconnect_exit;
  304 + }
  305 +
  306 + /* lock this device */
  307 + if (down_interruptible(&dev->sem)) {
  308 + retval = -ERESTARTSYS;
  309 + goto unlock_disconnect_exit;
  310 + }
  311 +
  312 + /* allow opening only once */
  313 + if (dev->open_count) {
  314 + retval = -EBUSY;
  315 + goto unlock_exit;
  316 + }
  317 + dev->open_count = 1;
  318 +
  319 + /* initialize in direction */
  320 + dev->ring_head = 0;
  321 + dev->ring_tail = 0;
  322 + usb_fill_int_urb(dev->interrupt_in_urb,
  323 + interface_to_usbdev(interface),
  324 + usb_rcvintpipe(interface_to_usbdev(interface),
  325 + dev->interrupt_in_endpoint->bEndpointAddress),
  326 + dev->interrupt_in_buffer,
  327 + dev->interrupt_in_endpoint_size,
  328 + ld_usb_interrupt_in_callback,
  329 + dev,
  330 + dev->interrupt_in_interval);
  331 +
  332 + dev->interrupt_in_running = 1;
  333 + dev->interrupt_in_done = 0;
  334 +
  335 + retval = usb_submit_urb(dev->interrupt_in_urb, GFP_KERNEL);
  336 + if (retval) {
  337 + dev_err(&interface->dev, "Couldn't submit interrupt_in_urb %d\n", retval);
  338 + dev->interrupt_in_running = 0;
  339 + dev->open_count = 0;
  340 + goto unlock_exit;
  341 + }
  342 +
  343 + /* save device in the file's private structure */
  344 + file->private_data = dev;
  345 +
  346 +unlock_exit:
  347 + up(&dev->sem);
  348 +
  349 +unlock_disconnect_exit:
  350 + up(&disconnect_sem);
  351 +
  352 + return retval;
  353 +}
  354 +
  355 +/**
  356 + * ld_usb_release
  357 + */
  358 +static int ld_usb_release(struct inode *inode, struct file *file)
  359 +{
  360 + struct ld_usb *dev;
  361 + int retval = 0;
  362 +
  363 + dev = file->private_data;
  364 +
  365 + if (dev == NULL) {
  366 + retval = -ENODEV;
  367 + goto exit;
  368 + }
  369 +
  370 + if (down_interruptible(&dev->sem)) {
  371 + retval = -ERESTARTSYS;
  372 + goto exit;
  373 + }
  374 +
  375 + if (dev->open_count != 1) {
  376 + retval = -ENODEV;
  377 + goto unlock_exit;
  378 + }
  379 + if (dev->intf == NULL) {
  380 + /* the device was unplugged before the file was released */
  381 + up(&dev->sem);
  382 + /* unlock here as ld_usb_delete frees dev */
  383 + ld_usb_delete(dev);
  384 + goto exit;
  385 + }
  386 +
  387 + /* wait until write transfer is finished */
  388 + if (dev->interrupt_out_busy)
  389 + wait_event_interruptible_timeout(dev->write_wait, !dev->interrupt_out_busy, 2 * HZ);
  390 + ld_usb_abort_transfers(dev);
  391 + dev->open_count = 0;
  392 +
  393 +unlock_exit:
  394 + up(&dev->sem);
  395 +
  396 +exit:
  397 + return retval;
  398 +}
  399 +
  400 +/**
  401 + * ld_usb_poll
  402 + */
  403 +static unsigned int ld_usb_poll(struct file *file, poll_table *wait)
  404 +{
  405 + struct ld_usb *dev;
  406 + unsigned int mask = 0;
  407 +
  408 + dev = file->private_data;
  409 +
  410 + poll_wait(file, &dev->read_wait, wait);
  411 + poll_wait(file, &dev->write_wait, wait);
  412 +
  413 + if (dev->ring_head != dev->ring_tail)
  414 + mask |= POLLIN | POLLRDNORM;
  415 + if (!dev->interrupt_out_busy)
  416 + mask |= POLLOUT | POLLWRNORM;
  417 +
  418 + return mask;
  419 +}
  420 +
  421 +/**
  422 + * ld_usb_read
  423 + */
  424 +static ssize_t ld_usb_read(struct file *file, char __user *buffer, size_t count,
  425 + loff_t *ppos)
  426 +{
  427 + struct ld_usb *dev;
  428 + size_t *actual_buffer;
  429 + size_t bytes_to_read;
  430 + int retval = 0;
  431 +
  432 + dev = file->private_data;
  433 +
  434 + /* verify that we actually have some data to read */
  435 + if (count == 0)
  436 + goto exit;
  437 +
  438 + /* lock this object */
  439 + if (down_interruptible(&dev->sem)) {
  440 + retval = -ERESTARTSYS;
  441 + goto exit;
  442 + }
  443 +
  444 + /* verify that the device wasn't unplugged */
  445 + if (dev->intf == NULL) {
  446 + retval = -ENODEV;
  447 + err("No device or device unplugged %d\n", retval);
  448 + goto unlock_exit;
  449 + }
  450 +
  451 + /* wait for data */
  452 + if (dev->ring_head == dev->ring_tail) {
  453 + if (file->f_flags & O_NONBLOCK) {
  454 + retval = -EAGAIN;
  455 + goto unlock_exit;
  456 + }
  457 + retval = wait_event_interruptible(dev->read_wait, dev->interrupt_in_done);
  458 + if (retval < 0)
  459 + goto unlock_exit;
  460 + }
  461 +
  462 + /* actual_buffer contains actual_length + interrupt_in_buffer */
  463 + actual_buffer = (size_t*)(dev->ring_buffer + dev->ring_tail*(sizeof(size_t)+dev->interrupt_in_endpoint_size));
  464 + bytes_to_read = min(count, *actual_buffer);
  465 + if (bytes_to_read < *actual_buffer)
  466 + dev_warn(&dev->intf->dev, "Read buffer overflow, %d bytes dropped\n",
  467 + *actual_buffer-bytes_to_read);
  468 +
  469 + /* copy one interrupt_in_buffer from ring_buffer into userspace */
  470 + if (copy_to_user(buffer, actual_buffer+1, bytes_to_read)) {
  471 + retval = -EFAULT;
  472 + goto unlock_exit;
  473 + }
  474 + dev->ring_tail = (dev->ring_tail+1) % ring_buffer_size;
  475 +
  476 + retval = bytes_to_read;
  477 +
  478 +unlock_exit:
  479 + /* unlock the device */
  480 + up(&dev->sem);
  481 +
  482 +exit:
  483 + return retval;
  484 +}
  485 +
  486 +/**
  487 + * ld_usb_write
  488 + */
  489 +static ssize_t ld_usb_write(struct file *file, const char __user *buffer,
  490 + size_t count, loff_t *ppos)
  491 +{
  492 + struct ld_usb *dev;
  493 + size_t bytes_to_write;
  494 + int retval = 0;
  495 +
  496 + dev = file->private_data;
  497 +
  498 + /* verify that we actually have some data to write */
  499 + if (count == 0)
  500 + goto exit;
  501 +
  502 + /* lock this object */
  503 + if (down_interruptible(&dev->sem)) {
  504 + retval = -ERESTARTSYS;
  505 + goto exit;
  506 + }
  507 +
  508 + /* verify that the device wasn't unplugged */
  509 + if (dev->intf == NULL) {
  510 + retval = -ENODEV;
  511 + err("No device or device unplugged %d\n", retval);
  512 + goto unlock_exit;
  513 + }
  514 +
  515 + /* wait until previous transfer is finished */
  516 + if (dev->interrupt_out_busy) {
  517 + if (file->f_flags & O_NONBLOCK) {
  518 + retval = -EAGAIN;
  519 + goto unlock_exit;
  520 + }
  521 + retval = wait_event_interruptible(dev->write_wait, !dev->interrupt_out_busy);
  522 + if (retval < 0) {
  523 + goto unlock_exit;
  524 + }
  525 + }
  526 +
  527 + /* write the data into interrupt_out_buffer from userspace */
  528 + bytes_to_write = min(count, write_buffer_size*dev->interrupt_out_endpoint_size);
  529 + if (bytes_to_write < count)
  530 + dev_warn(&dev->intf->dev, "Write buffer overflow, %d bytes dropped\n",count-bytes_to_write);
  531 + dbg_info(&dev->intf->dev, "%s: count = %d, bytes_to_write = %d\n", __FUNCTION__, count, bytes_to_write);
  532 +
  533 + if (copy_from_user(dev->interrupt_out_buffer, buffer, bytes_to_write)) {
  534 + retval = -EFAULT;
  535 + goto unlock_exit;
  536 + }
  537 +
  538 + if (dev->interrupt_out_endpoint == NULL) {
  539 + /* try HID_REQ_SET_REPORT=9 on control_endpoint instead of interrupt_out_endpoint */
  540 + retval = usb_control_msg(interface_to_usbdev(dev->intf),
  541 + usb_sndctrlpipe(interface_to_usbdev(dev->intf), 0),
  542 + 9,
  543 + USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,
  544 + 1 << 8, 0,
  545 + dev->interrupt_out_buffer,
  546 + bytes_to_write,
  547 + USB_CTRL_SET_TIMEOUT * HZ);
  548 + if (retval < 0)
  549 + err("Couldn't submit HID_REQ_SET_REPORT %d\n", retval);
  550 + goto unlock_exit;
  551 + }
  552 +
  553 + /* send off the urb */
  554 + usb_fill_int_urb(dev->interrupt_out_urb,
  555 + interface_to_usbdev(dev->intf),
  556 + usb_sndintpipe(interface_to_usbdev(dev->intf),
  557 + dev->interrupt_out_endpoint->bEndpointAddress),
  558 + dev->interrupt_out_buffer,
  559 + bytes_to_write,
  560 + ld_usb_interrupt_out_callback,
  561 + dev,
  562 + dev->interrupt_out_interval);
  563 +
  564 + dev->interrupt_out_busy = 1;
  565 + wmb();
  566 +
  567 + retval = usb_submit_urb(dev->interrupt_out_urb, GFP_KERNEL);
  568 + if (retval) {
  569 + dev->interrupt_out_busy = 0;
  570 + err("Couldn't submit interrupt_out_urb %d\n", retval);
  571 + goto unlock_exit;
  572 + }
  573 + retval = bytes_to_write;
  574 +
  575 +unlock_exit:
  576 + /* unlock the device */
  577 + up(&dev->sem);
  578 +
  579 +exit:
  580 + return retval;
  581 +}
  582 +
  583 +/* file operations needed when we register this driver */
  584 +static struct file_operations ld_usb_fops = {
  585 + .owner = THIS_MODULE,
  586 + .read = ld_usb_read,
  587 + .write = ld_usb_write,
  588 + .open = ld_usb_open,
  589 + .release = ld_usb_release,
  590 + .poll = ld_usb_poll,
  591 +};
  592 +
  593 +/*
  594 + * usb class driver info in order to get a minor number from the usb core,
  595 + * and to have the device registered with devfs and the driver core
  596 + */
  597 +static struct usb_class_driver ld_usb_class = {
  598 + .name = "ldusb%d",
  599 + .fops = &ld_usb_fops,
  600 + .minor_base = USB_LD_MINOR_BASE,
  601 +};
  602 +
  603 +/**
  604 + * ld_usb_probe
  605 + *
  606 + * Called by the usb core when a new device is connected that it thinks
  607 + * this driver might be interested in.
  608 + */
  609 +static int ld_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
  610 +{
  611 + struct usb_device *udev = interface_to_usbdev(intf);
  612 + struct ld_usb *dev = NULL;
  613 + struct usb_host_interface *iface_desc;
  614 + struct usb_endpoint_descriptor *endpoint;
  615 + char *buffer;
  616 + int i;
  617 + int retval = -ENOMEM;
  618 +
  619 + /* allocate memory for our device state and intialize it */
  620 +
  621 + dev = kmalloc(sizeof(*dev), GFP_KERNEL);
  622 + if (dev == NULL) {
  623 + dev_err(&intf->dev, "Out of memory\n");
  624 + goto exit;
  625 + }
  626 + memset(dev, 0x00, sizeof(*dev));
  627 + init_MUTEX(&dev->sem);
  628 + dev->intf = intf;
  629 + init_waitqueue_head(&dev->read_wait);
  630 + init_waitqueue_head(&dev->write_wait);
  631 +
  632 + /* workaround for early firmware versions on fast computers */
  633 + if ((le16_to_cpu(udev->descriptor.idVendor) == USB_VENDOR_ID_LD) &&
  634 + ((le16_to_cpu(udev->descriptor.idProduct) == USB_DEVICE_ID_CASSY) ||
  635 + (le16_to_cpu(udev->descriptor.idProduct) == USB_DEVICE_ID_COM3LAB)) &&
  636 + (le16_to_cpu(udev->descriptor.bcdDevice) <= 0x103)) {
  637 + buffer = kmalloc(256, GFP_KERNEL);
  638 + /* usb_string makes SETUP+STALL to leave always ControlReadLoop */
  639 + usb_string(udev, 255, buffer, 256);
  640 + kfree(buffer);
  641 + }
  642 +
  643 + iface_desc = intf->cur_altsetting;
  644 +
  645 + /* set up the endpoint information */
  646 + for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
  647 + endpoint = &iface_desc->endpoint[i].desc;
  648 +
  649 + if (((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN) &&
  650 + ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)) {
  651 + dev->interrupt_in_endpoint = endpoint;
  652 + }
  653 +
  654 + if (((endpoint->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT) &&
  655 + ((endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT)) {
  656 + dev->interrupt_out_endpoint = endpoint;
  657 + }
  658 + }
  659 + if (dev->interrupt_in_endpoint == NULL) {
  660 + dev_err(&intf->dev, "Interrupt in endpoint not found\n");
  661 + goto error;
  662 + }
  663 + if (dev->interrupt_out_endpoint == NULL)
  664 + dev_warn(&intf->dev, "Interrupt out endpoint not found (using control endpoint instead)\n");
  665 +
  666 + dev->interrupt_in_endpoint_size = le16_to_cpu(dev->interrupt_in_endpoint->wMaxPacketSize);
  667 + dev->ring_buffer = kmalloc(ring_buffer_size*(sizeof(size_t)+dev->interrupt_in_endpoint_size), GFP_KERNEL);
  668 + if (!dev->ring_buffer) {
  669 + dev_err(&intf->dev, "Couldn't allocate ring_buffer\n");
  670 + goto error;
  671 + }
  672 + dev->interrupt_in_buffer = kmalloc(dev->interrupt_in_endpoint_size, GFP_KERNEL);
  673 + if (!dev->interrupt_in_buffer) {
  674 + dev_err(&intf->dev, "Couldn't allocate interrupt_in_buffer\n");
  675 + goto error;
  676 + }
  677 + dev->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL);
  678 + if (!dev->interrupt_in_urb) {
  679 + dev_err(&intf->dev, "Couldn't allocate interrupt_in_urb\n");
  680 + goto error;
  681 + }
  682 + dev->interrupt_out_endpoint_size = dev->interrupt_out_endpoint ? le16_to_cpu(dev->interrupt_out_endpoint->wMaxPacketSize) :
  683 + udev->descriptor.bMaxPacketSize0;
  684 + dev->interrupt_out_buffer = kmalloc(write_buffer_size*dev->interrupt_out_endpoint_size, GFP_KERNEL);
  685 + if (!dev->interrupt_out_buffer) {
  686 + dev_err(&intf->dev, "Couldn't allocate interrupt_out_buffer\n");
  687 + goto error;
  688 + }
  689 + dev->interrupt_out_urb = usb_alloc_urb(0, GFP_KERNEL);
  690 + if (!dev->interrupt_out_urb) {
  691 + dev_err(&intf->dev, "Couldn't allocate interrupt_out_urb\n");
  692 + goto error;
  693 + }
  694 + dev->interrupt_in_interval = min_interrupt_in_interval > dev->interrupt_in_endpoint->bInterval ? min_interrupt_in_interval : dev->interrupt_in_endpoint->bInterval;
  695 + if (dev->interrupt_out_endpoint)
  696 + dev->interrupt_out_interval = min_interrupt_out_interval > dev->interrupt_out_endpoint->bInterval ? min_interrupt_out_interval : dev->interrupt_out_endpoint->bInterval;
  697 +
  698 + /* we can register the device now, as it is ready */
  699 + usb_set_intfdata(intf, dev);
  700 +
  701 + retval = usb_register_dev(intf, &ld_usb_class);
  702 + if (retval) {
  703 + /* something prevented us from registering this driver */
  704 + dev_err(&intf->dev, "Not able to get a minor for this device.\n");
  705 + usb_set_intfdata(intf, NULL);
  706 + goto error;
  707 + }
  708 +
  709 + /* let the user know what node this device is now attached to */
  710 + dev_info(&intf->dev, "LD USB Device #%d now attached to major %d minor %d\n",
  711 + (intf->minor - USB_LD_MINOR_BASE), USB_MAJOR, intf->minor);
  712 +
  713 +exit:
  714 + return retval;
  715 +
  716 +error:
  717 + ld_usb_delete(dev);
  718 +
  719 + return retval;
  720 +}
  721 +
  722 +/**
  723 + * ld_usb_disconnect
  724 + *
  725 + * Called by the usb core when the device is removed from the system.
  726 + */
  727 +static void ld_usb_disconnect(struct usb_interface *intf)
  728 +{
  729 + struct ld_usb *dev;
  730 + int minor;
  731 +
  732 + down(&disconnect_sem);
  733 +
  734 + dev = usb_get_intfdata(intf);
  735 + usb_set_intfdata(intf, NULL);
  736 +
  737 + down(&dev->sem);
  738 +
  739 + minor = intf->minor;
  740 +
  741 + /* give back our minor */
  742 + usb_deregister_dev(intf, &ld_usb_class);
  743 +
  744 + /* if the device is not opened, then we clean up right now */
  745 + if (!dev->open_count) {
  746 + up(&dev->sem);
  747 + ld_usb_delete(dev);
  748 + } else {
  749 + dev->intf = NULL;
  750 + up(&dev->sem);
  751 + }
  752 +
  753 + up(&disconnect_sem);
  754 +
  755 + dev_info(&intf->dev, "LD USB Device #%d now disconnected\n",
  756 + (minor - USB_LD_MINOR_BASE));
  757 +}
  758 +
  759 +/* usb specific object needed to register this driver with the usb subsystem */
  760 +static struct usb_driver ld_usb_driver = {
  761 + .owner = THIS_MODULE,
  762 + .name = "ldusb",
  763 + .probe = ld_usb_probe,
  764 + .disconnect = ld_usb_disconnect,
  765 + .id_table = ld_usb_table,
  766 +};
  767 +
  768 +/**
  769 + * ld_usb_init
  770 + */
  771 +static int __init ld_usb_init(void)
  772 +{
  773 + int retval;
  774 +
  775 + /* register this driver with the USB subsystem */
  776 + retval = usb_register(&ld_usb_driver);
  777 + if (retval)
  778 + err("usb_register failed for the "__FILE__" driver. Error number %d\n", retval);
  779 +
  780 + return retval;
  781 +}
  782 +
  783 +/**
  784 + * ld_usb_exit
  785 + */
  786 +static void __exit ld_usb_exit(void)
  787 +{
  788 + /* deregister this driver with the USB subsystem */
  789 + usb_deregister(&ld_usb_driver);
  790 +}
  791 +
  792 +module_init(ld_usb_init);
  793 +module_exit(ld_usb_exit);