linux/drivers/staging/frontier/alphatrack.c
<<
>>
Prefs
   1/*
   2 * Frontier Designs Alphatrack driver
   3 *
   4 * Copyright (C) 2007 Michael Taht (m@taht.net)
   5 *
   6 * Based on the usbled driver and ldusb drivers by
   7 *
   8 * Copyright (C) 2004 Greg Kroah-Hartman (greg@kroah.com)
   9 * Copyright (C) 2005 Michael Hund <mhund@ld-didactic.de>
  10 *
  11 * The ldusb driver was, in turn, derived from Lego USB Tower driver
  12 * Copyright (C) 2003 David Glance <advidgsf@sourceforge.net>
  13 *               2001-2004 Juergen Stuber <starblue@users.sourceforge.net>
  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, version 2.
  18 *
  19 */
  20
  21/**
  22 * This driver uses a ring buffer for time critical reading of
  23 * interrupt in reports and provides read and write methods for
  24 * raw interrupt reports.
  25 */
  26
  27/* Note: this currently uses a dumb ringbuffer for reads and writes.
  28 * A more optimal driver would cache and kill off outstanding urbs that are
  29 * now invalid, and ignore ones that already were in the queue but valid
  30 * as we only have 30 commands for the alphatrack. In particular this is
  31 * key for getting lights to flash in time as otherwise many commands
  32 * can be buffered up before the light change makes it to the interface.
  33*/
  34
  35#include <linux/kernel.h>
  36#include <linux/errno.h>
  37#include <linux/init.h>
  38#include <linux/slab.h>
  39#include <linux/module.h>
  40#include <linux/kobject.h>
  41#include <linux/mutex.h>
  42
  43#include <linux/uaccess.h>
  44#include <linux/input.h>
  45#include <linux/usb.h>
  46#include <linux/poll.h>
  47
  48#include "alphatrack.h"
  49
  50#define VENDOR_ID       0x165b
  51#define PRODUCT_ID      0xfad1
  52
  53#ifdef CONFIG_USB_DYNAMIC_MINORS
  54#define USB_ALPHATRACK_MINOR_BASE       0
  55#else
  56/* FIXME 176 - is another driver's minor - apply for that */
  57#define USB_ALPHATRACK_MINOR_BASE       176
  58#endif
  59
  60/* table of devices that work with this driver */
  61static const struct usb_device_id usb_alphatrack_table[] = {
  62        {USB_DEVICE(VENDOR_ID, PRODUCT_ID)},
  63        {}                      /* Terminating entry */
  64};
  65
  66MODULE_DEVICE_TABLE(usb, usb_alphatrack_table);
  67MODULE_VERSION("0.41");
  68MODULE_AUTHOR("Mike Taht <m@taht.net>");
  69MODULE_DESCRIPTION("Alphatrack USB Driver");
  70MODULE_LICENSE("GPL");
  71MODULE_SUPPORTED_DEVICE("Frontier Designs Alphatrack Control Surface");
  72
  73/* These aren't done yet */
  74
  75#define SUPPRESS_EXTRA_ONLINE_EVENTS 0
  76#define BUFFERED_WRITES 0
  77#define SUPPRESS_EXTRA_OFFLINE_EVENTS 0
  78#define COMPRESS_FADER_EVENTS 0
  79
  80#define BUFFERED_READS 1
  81#define RING_BUFFER_SIZE 512
  82#define WRITE_BUFFER_SIZE 34
  83#define ALPHATRACK_USB_TIMEOUT 10
  84#define OUTPUT_CMD_SIZE 8
  85#define INPUT_CMD_SIZE 12
  86#define ALPHATRACK_DEBUG 0
  87
  88static int debug = ALPHATRACK_DEBUG;
  89
  90/* Use our own dbg macro */
  91#define dbg_info(dev, format, arg...) do \
  92        { if (debug) dev_info(dev , format , ## arg); } while (0)
  93
  94#define alphatrack_ocmd_info(dev, cmd, format, arg...)
  95
  96#define alphatrack_icmd_info(dev, cmd, format, arg...)
  97
  98/* Module parameters */
  99
 100module_param(debug, int, S_IRUGO | S_IWUSR);
 101MODULE_PARM_DESC(debug, "Debug enabled or not");
 102
 103/* All interrupt in transfers are collected in a ring buffer to
 104 * avoid racing conditions and get better performance of the driver.
 105 */
 106
 107static int ring_buffer_size = RING_BUFFER_SIZE;
 108
 109module_param(ring_buffer_size, int, S_IRUGO);
 110MODULE_PARM_DESC(ring_buffer_size, "Read ring buffer size");
 111
 112/* The write_buffer can one day contain more than one interrupt out transfer.
 113 */
 114
 115static int write_buffer_size = WRITE_BUFFER_SIZE;
 116module_param(write_buffer_size, int, S_IRUGO);
 117MODULE_PARM_DESC(write_buffer_size, "Write buffer size");
 118
 119/*
 120 * Increase the interval for debugging purposes.
 121 * or set to 1 to use the standard interval from the endpoint descriptors.
 122 */
 123
 124static int min_interrupt_in_interval = ALPHATRACK_USB_TIMEOUT;
 125module_param(min_interrupt_in_interval, int, 0);
 126MODULE_PARM_DESC(min_interrupt_in_interval,
 127                 "Minimum interrupt in interval in ms");
 128
 129static int min_interrupt_out_interval = ALPHATRACK_USB_TIMEOUT;
 130module_param(min_interrupt_out_interval, int, 0);
 131MODULE_PARM_DESC(min_interrupt_out_interval,
 132                 "Minimum interrupt out interval in ms");
 133
 134/* Structure to hold all of our device specific stuff */
 135
 136struct usb_alphatrack {
 137        struct mutex mtx;       /* locks this structure */
 138        struct usb_interface *intf;     /* save off the usb interface pointer */
 139        int open_count;         /* number of times this port has been opened */
 140
 141        /* make gcc happy */
 142        struct alphatrack_icmd (*ring_buffer)[RING_BUFFER_SIZE];
 143        struct alphatrack_ocmd (*write_buffer)[WRITE_BUFFER_SIZE];
 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        unsigned char *interrupt_in_buffer;
 151        unsigned char *oldi_buffer;
 152        struct usb_endpoint_descriptor *interrupt_in_endpoint;
 153        struct urb *interrupt_in_urb;
 154        int interrupt_in_interval;
 155        size_t interrupt_in_endpoint_size;
 156        int interrupt_in_running;
 157        int interrupt_in_done;
 158
 159        char *interrupt_out_buffer;
 160        struct usb_endpoint_descriptor *interrupt_out_endpoint;
 161        struct urb *interrupt_out_urb;
 162        int interrupt_out_interval;
 163        size_t interrupt_out_endpoint_size;
 164        int interrupt_out_busy;
 165
 166        atomic_t writes_pending;
 167        int event;              /* alternate interface to events */
 168        int fader;              /* 10 bits */
 169        int lights;             /* 23 bits */
 170        unsigned char dump_state;       /* 0 if disabled 1 if enabled */
 171        unsigned char enable;   /* 0 if disabled 1 if enabled */
 172        unsigned char offline;  /* if the device is out of range or asleep */
 173        unsigned char verbose;  /* be verbose in error reporting */
 174        unsigned char last_cmd[OUTPUT_CMD_SIZE];
 175        unsigned char screen[32];
 176};
 177
 178/* prevent races between open() and disconnect() */
 179static DEFINE_MUTEX(disconnect_mutex);
 180
 181/* forward declaration */
 182
 183static struct usb_driver usb_alphatrack_driver;
 184
 185/**
 186 *      usb_alphatrack_abort_transfers
 187 *      aborts transfers and frees associated data structures
 188 */
 189static void usb_alphatrack_abort_transfers(struct usb_alphatrack *dev)
 190{
 191        /* shutdown transfer */
 192        if (dev->interrupt_in_running) {
 193                dev->interrupt_in_running = 0;
 194                if (dev->intf)
 195                        usb_kill_urb(dev->interrupt_in_urb);
 196        }
 197        if (dev->interrupt_out_busy)
 198                if (dev->intf)
 199                        usb_kill_urb(dev->interrupt_out_urb);
 200}
 201
 202/**
 203 *      usb_alphatrack_delete
 204 */
 205static void usb_alphatrack_delete(struct usb_alphatrack *dev)
 206{
 207        usb_alphatrack_abort_transfers(dev);
 208        usb_free_urb(dev->interrupt_in_urb);
 209        usb_free_urb(dev->interrupt_out_urb);
 210        kfree(dev->ring_buffer);
 211        kfree(dev->interrupt_in_buffer);
 212        kfree(dev->interrupt_out_buffer);
 213        kfree(dev);             /* fixme oldi_buffer */
 214}
 215
 216/**
 217 *      usb_alphatrack_interrupt_in_callback
 218 */
 219
 220static void usb_alphatrack_interrupt_in_callback(struct urb *urb)
 221{
 222        struct usb_alphatrack *dev = urb->context;
 223        unsigned int next_ring_head;
 224        int retval = -1;
 225
 226        if (urb->status) {
 227                if (urb->status == -ENOENT ||
 228                    urb->status == -ECONNRESET || urb->status == -ESHUTDOWN) {
 229                        goto exit;
 230                } else {
 231                        dbg_info(&dev->intf->dev,
 232                                 "%s: nonzero status received: %d\n", __func__,
 233                                 urb->status);
 234                        goto resubmit;  /* maybe we can recover */
 235                }
 236        }
 237
 238        if (urb->actual_length != INPUT_CMD_SIZE) {
 239                dev_warn(&dev->intf->dev,
 240                         "Urb length was %d bytes!!"
 241                         "Do something intelligent\n", urb->actual_length);
 242        } else {
 243                alphatrack_ocmd_info(&dev->intf->dev,
 244                                     &(*dev->ring_buffer)[dev->ring_tail].cmd,
 245                                     "%s", "bla");
 246                if (memcmp
 247                    (dev->interrupt_in_buffer, dev->oldi_buffer,
 248                     INPUT_CMD_SIZE) == 0) {
 249                        goto resubmit;
 250                }
 251                memcpy(dev->oldi_buffer, dev->interrupt_in_buffer,
 252                       INPUT_CMD_SIZE);
 253
 254#if SUPPRESS_EXTRA_OFFLINE_EVENTS
 255                if (dev->offline == 2 && dev->interrupt_in_buffer[1] == 0xff)
 256                        goto resubmit;
 257                if (dev->offline == 1 && dev->interrupt_in_buffer[1] == 0xff) {
 258                        dev->offline = 2;
 259                        goto resubmit;
 260                }
 261/* Always pass one offline event up the stack */
 262                if (dev->offline > 0 && dev->interrupt_in_buffer[1] != 0xff)
 263                        dev->offline = 0;
 264                if (dev->offline == 0 && dev->interrupt_in_buffer[1] == 0xff)
 265                        dev->offline = 1;
 266#endif
 267                dbg_info(&dev->intf->dev, "%s: head, tail are %x, %x\n",
 268                         __func__, dev->ring_head, dev->ring_tail);
 269                next_ring_head = (dev->ring_head + 1) % ring_buffer_size;
 270
 271                if (next_ring_head != dev->ring_tail) {
 272                        memcpy(&((*dev->ring_buffer)[dev->ring_head]),
 273                               dev->interrupt_in_buffer, urb->actual_length);
 274                        dev->ring_head = next_ring_head;
 275                        retval = 0;
 276                        memset(dev->interrupt_in_buffer, 0, urb->actual_length);
 277                } else {
 278                        dev_warn(&dev->intf->dev,
 279                                 "Ring buffer overflow, %d bytes dropped\n",
 280                                 urb->actual_length);
 281                        memset(dev->interrupt_in_buffer, 0, urb->actual_length);
 282                }
 283        }
 284
 285resubmit:
 286        /* resubmit if we're still running */
 287        if (dev->interrupt_in_running && dev->intf) {
 288                retval = usb_submit_urb(dev->interrupt_in_urb, GFP_ATOMIC);
 289                if (retval)
 290                        dev_err(&dev->intf->dev,
 291                                "usb_submit_urb failed (%d)\n", retval);
 292        }
 293
 294exit:
 295        dev->interrupt_in_done = 1;
 296        wake_up_interruptible(&dev->read_wait);
 297}
 298
 299/**
 300 *      usb_alphatrack_interrupt_out_callback
 301 */
 302static void usb_alphatrack_interrupt_out_callback(struct urb *urb)
 303{
 304        struct usb_alphatrack *dev = urb->context;
 305
 306        /* sync/async unlink faults aren't errors */
 307        if (urb->status && !(urb->status == -ENOENT ||
 308                             urb->status == -ECONNRESET ||
 309                             urb->status == -ESHUTDOWN))
 310                dbg_info(&dev->intf->dev,
 311                         "%s - nonzero write interrupt status received: %d\n",
 312                         __func__, urb->status);
 313        atomic_dec(&dev->writes_pending);
 314        dev->interrupt_out_busy = 0;
 315        wake_up_interruptible(&dev->write_wait);
 316}
 317
 318/**
 319 *      usb_alphatrack_open
 320 */
 321static int usb_alphatrack_open(struct inode *inode, struct file *file)
 322{
 323        struct usb_alphatrack *dev;
 324        int subminor;
 325        int retval = 0;
 326        struct usb_interface *interface;
 327
 328        nonseekable_open(inode, file);
 329        subminor = iminor(inode);
 330
 331        mutex_lock(&disconnect_mutex);
 332
 333        interface = usb_find_interface(&usb_alphatrack_driver, subminor);
 334
 335        if (!interface) {
 336                pr_err("%s - error, can't find device for minor %d\n",
 337                       __func__, subminor);
 338                retval = -ENODEV;
 339                goto unlock_disconnect_exit;
 340        }
 341
 342        dev = usb_get_intfdata(interface);
 343
 344        if (!dev) {
 345                retval = -ENODEV;
 346                goto unlock_disconnect_exit;
 347        }
 348
 349        /* lock this device */
 350        if (mutex_lock_interruptible(&dev->mtx)) {
 351                retval = -ERESTARTSYS;
 352                goto unlock_disconnect_exit;
 353        }
 354
 355        /* allow opening only once */
 356        if (dev->open_count) {
 357                retval = -EBUSY;
 358                goto unlock_exit;
 359        }
 360        dev->open_count = 1;
 361
 362        /* initialize in direction */
 363        dev->ring_head = 0;
 364        dev->ring_tail = 0;
 365        usb_fill_int_urb(dev->interrupt_in_urb,
 366                         interface_to_usbdev(interface),
 367                         usb_rcvintpipe(interface_to_usbdev(interface),
 368                                        dev->interrupt_in_endpoint->
 369                                        bEndpointAddress),
 370                         dev->interrupt_in_buffer,
 371                         dev->interrupt_in_endpoint_size,
 372                         usb_alphatrack_interrupt_in_callback, dev,
 373                         dev->interrupt_in_interval);
 374
 375        dev->interrupt_in_running = 1;
 376        dev->interrupt_in_done = 0;
 377        dev->enable = 1;
 378        dev->offline = 0;
 379
 380        retval = usb_submit_urb(dev->interrupt_in_urb, GFP_KERNEL);
 381        if (retval) {
 382                dev_err(&interface->dev,
 383                        "Couldn't submit interrupt_in_urb %d\n", retval);
 384                dev->interrupt_in_running = 0;
 385                dev->open_count = 0;
 386                goto unlock_exit;
 387        }
 388
 389        /* save device in the file's private structure */
 390        file->private_data = dev;
 391
 392unlock_exit:
 393        mutex_unlock(&dev->mtx);
 394
 395unlock_disconnect_exit:
 396        mutex_unlock(&disconnect_mutex);
 397
 398        return retval;
 399}
 400
 401/**
 402 *      usb_alphatrack_release
 403 */
 404static int usb_alphatrack_release(struct inode *inode, struct file *file)
 405{
 406        struct usb_alphatrack *dev;
 407        int retval = 0;
 408
 409        dev = file->private_data;
 410
 411        if (dev == NULL) {
 412                retval = -ENODEV;
 413                goto exit;
 414        }
 415
 416        if (mutex_lock_interruptible(&dev->mtx)) {
 417                retval = -ERESTARTSYS;
 418                goto exit;
 419        }
 420
 421        if (dev->open_count != 1) {
 422                retval = -ENODEV;
 423                goto unlock_exit;
 424        }
 425
 426        if (dev->intf == NULL) {
 427                /* the device was unplugged before the file was released */
 428                mutex_unlock(&dev->mtx);
 429                /* unlock here as usb_alphatrack_delete frees dev */
 430                usb_alphatrack_delete(dev);
 431                retval = -ENODEV;
 432                goto exit;
 433        }
 434
 435        /* wait until write transfer is finished */
 436        if (dev->interrupt_out_busy)
 437                wait_event_interruptible_timeout(dev->write_wait,
 438                                                 !dev->interrupt_out_busy,
 439                                                 2 * HZ);
 440        usb_alphatrack_abort_transfers(dev);
 441        dev->open_count = 0;
 442
 443unlock_exit:
 444        mutex_unlock(&dev->mtx);
 445
 446exit:
 447        return retval;
 448}
 449
 450/**
 451 *      usb_alphatrack_poll
 452 */
 453static unsigned int usb_alphatrack_poll(struct file *file, poll_table *wait)
 454{
 455        struct usb_alphatrack *dev;
 456        unsigned int mask = 0;
 457
 458        dev = file->private_data;
 459
 460        poll_wait(file, &dev->read_wait, wait);
 461        poll_wait(file, &dev->write_wait, wait);
 462
 463        if (dev->ring_head != dev->ring_tail)
 464                mask |= POLLIN | POLLRDNORM;
 465        if (!dev->interrupt_out_busy)
 466                mask |= POLLOUT | POLLWRNORM;
 467
 468        return mask;
 469}
 470
 471/**
 472 *      usb_alphatrack_read
 473 */
 474static ssize_t usb_alphatrack_read(struct file *file, char __user *buffer,
 475                                   size_t count, loff_t *ppos)
 476{
 477        struct usb_alphatrack *dev;
 478        int retval = 0;
 479
 480        int c = 0;
 481
 482        dev = file->private_data;
 483
 484        /* verify that we actually have some data to read */
 485        if (count == 0)
 486                goto exit;
 487
 488        /* lock this object */
 489        if (mutex_lock_interruptible(&dev->mtx)) {
 490                retval = -ERESTARTSYS;
 491                goto exit;
 492        }
 493
 494        /* verify that the device wasn't unplugged */
 495        if (dev->intf == NULL) {
 496                retval = -ENODEV;
 497                pr_err("%s: No device or device unplugged %d\n",
 498                       __func__, retval);
 499                goto unlock_exit;
 500        }
 501
 502        while (dev->ring_head == dev->ring_tail) {
 503                if (file->f_flags & O_NONBLOCK) {
 504                        retval = -EAGAIN;
 505                        goto unlock_exit;
 506                }
 507                dev->interrupt_in_done = 0;
 508                retval =
 509                    wait_event_interruptible(dev->read_wait,
 510                                             dev->interrupt_in_done);
 511                if (retval < 0)
 512                        goto unlock_exit;
 513        }
 514
 515        alphatrack_ocmd_info(&dev->intf->dev,
 516                             &(*dev->ring_buffer)[dev->ring_tail].cmd, "%s",
 517                             ": copying to userspace");
 518
 519        c = 0;
 520        while ((c < count) && (dev->ring_tail != dev->ring_head)) {
 521                if (copy_to_user
 522                    (&buffer[c], &(*dev->ring_buffer)[dev->ring_tail],
 523                     INPUT_CMD_SIZE)) {
 524                        retval = -EFAULT;
 525                        goto unlock_exit;
 526                }
 527                dev->ring_tail = (dev->ring_tail + 1) % ring_buffer_size;
 528                c += INPUT_CMD_SIZE;
 529                dbg_info(&dev->intf->dev, "%s: head, tail are %x, %x\n",
 530                         __func__, dev->ring_head, dev->ring_tail);
 531        }
 532        retval = c;
 533
 534unlock_exit:
 535        /* unlock the device */
 536        mutex_unlock(&dev->mtx);
 537
 538exit:
 539        return retval;
 540}
 541
 542/**
 543 *      usb_alphatrack_write
 544 */
 545static ssize_t usb_alphatrack_write(struct file *file,
 546                                    const char __user *buffer, size_t count,
 547                                    loff_t *ppos)
 548{
 549        struct usb_alphatrack *dev;
 550        size_t bytes_to_write;
 551        int retval = 0;
 552
 553        dev = file->private_data;
 554
 555        /* verify that we actually have some data to write */
 556        if (count == 0)
 557                goto exit;
 558
 559        /* lock this object */
 560        if (mutex_lock_interruptible(&dev->mtx)) {
 561                retval = -ERESTARTSYS;
 562                goto exit;
 563        }
 564
 565        /* verify that the device wasn't unplugged */
 566        if (dev->intf == NULL) {
 567                retval = -ENODEV;
 568                pr_err("%s: No device or device unplugged %d\n",
 569                       __func__, retval);
 570                goto unlock_exit;
 571        }
 572
 573        /* wait until previous transfer is finished */
 574        if (dev->interrupt_out_busy) {
 575                if (file->f_flags & O_NONBLOCK) {
 576                        retval = -EAGAIN;
 577                        goto unlock_exit;
 578                }
 579                retval =
 580                    wait_event_interruptible(dev->write_wait,
 581                                             !dev->interrupt_out_busy);
 582                if (retval < 0)
 583                        goto unlock_exit;
 584        }
 585
 586        /* write the data into interrupt_out_buffer from userspace */
 587        /* FIXME - if you write more than 12 bytes this breaks */
 588        bytes_to_write =
 589            min(count, write_buffer_size * dev->interrupt_out_endpoint_size);
 590        if (bytes_to_write < count)
 591                dev_warn(&dev->intf->dev,
 592                         "Write buffer overflow, %zd bytes dropped\n",
 593                         count - bytes_to_write);
 594
 595        dbg_info(&dev->intf->dev, "%s: count = %zd, bytes_to_write = %zd\n",
 596                 __func__, count, bytes_to_write);
 597
 598        if (copy_from_user(dev->interrupt_out_buffer, buffer, bytes_to_write)) {
 599                retval = -EFAULT;
 600                goto unlock_exit;
 601        }
 602
 603        if (dev->interrupt_out_endpoint == NULL) {
 604                dev_err(&dev->intf->dev, "Endpoint should not be be null!\n");
 605                goto unlock_exit;
 606        }
 607
 608        /* send off the urb */
 609        usb_fill_int_urb(dev->interrupt_out_urb,
 610                         interface_to_usbdev(dev->intf),
 611                         usb_sndintpipe(interface_to_usbdev(dev->intf),
 612                                        dev->interrupt_out_endpoint->
 613                                        bEndpointAddress),
 614                         dev->interrupt_out_buffer, bytes_to_write,
 615                         usb_alphatrack_interrupt_out_callback, dev,
 616                         dev->interrupt_out_interval);
 617        dev->interrupt_out_busy = 1;
 618        atomic_inc(&dev->writes_pending);
 619        wmb();
 620
 621        retval = usb_submit_urb(dev->interrupt_out_urb, GFP_KERNEL);
 622        if (retval) {
 623                dev->interrupt_out_busy = 0;
 624                dev_err(&dev->intf->dev,
 625                        "Couldn't submit interrupt_out_urb %d\n", retval);
 626                atomic_dec(&dev->writes_pending);
 627                goto unlock_exit;
 628        }
 629        retval = bytes_to_write;
 630
 631unlock_exit:
 632        /* unlock the device */
 633        mutex_unlock(&dev->mtx);
 634
 635exit:
 636        return retval;
 637}
 638
 639/* file operations needed when we register this driver */
 640static const struct file_operations usb_alphatrack_fops = {
 641        .owner = THIS_MODULE,
 642        .read = usb_alphatrack_read,
 643        .write = usb_alphatrack_write,
 644        .open = usb_alphatrack_open,
 645        .release = usb_alphatrack_release,
 646        .poll = usb_alphatrack_poll,
 647        .llseek = no_llseek,
 648};
 649
 650/*
 651 * usb class driver info in order to get a minor number from the usb core,
 652 * and to have the device registered with the driver core
 653 */
 654
 655static struct usb_class_driver usb_alphatrack_class = {
 656        .name = "alphatrack%d",
 657        .fops = &usb_alphatrack_fops,
 658        .minor_base = USB_ALPHATRACK_MINOR_BASE,
 659};
 660
 661/**
 662 *      usb_alphatrack_probe
 663 *
 664 *      Called by the usb core when a new device is connected that it thinks
 665 *      this driver might be interested in.
 666 */
 667static int usb_alphatrack_probe(struct usb_interface *intf,
 668                                const struct usb_device_id *id)
 669{
 670        struct usb_device *udev = interface_to_usbdev(intf);
 671        struct usb_alphatrack *dev = NULL;
 672        struct usb_host_interface *iface_desc;
 673        struct usb_endpoint_descriptor *endpoint;
 674        int i;
 675        int true_size;
 676        int retval = -ENOMEM;
 677
 678        /* allocate memory for our device state and initialize it */
 679
 680        dev = kzalloc(sizeof(*dev), GFP_KERNEL);
 681        if (dev == NULL)
 682                goto exit;
 683
 684        mutex_init(&dev->mtx);
 685        dev->intf = intf;
 686        init_waitqueue_head(&dev->read_wait);
 687        init_waitqueue_head(&dev->write_wait);
 688
 689        iface_desc = intf->cur_altsetting;
 690
 691        /* set up the endpoint information */
 692        for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
 693                endpoint = &iface_desc->endpoint[i].desc;
 694
 695                if (usb_endpoint_is_int_in(endpoint))
 696                        dev->interrupt_in_endpoint = endpoint;
 697
 698                if (usb_endpoint_is_int_out(endpoint))
 699                        dev->interrupt_out_endpoint = endpoint;
 700        }
 701        if (dev->interrupt_in_endpoint == NULL) {
 702                dev_err(&intf->dev, "Interrupt in endpoint not found\n");
 703                goto error;
 704        }
 705        if (dev->interrupt_out_endpoint == NULL)
 706                dev_warn(&intf->dev,
 707                         "Interrupt out endpoint not found"
 708                         "(using control endpoint instead)\n");
 709
 710        dev->interrupt_in_endpoint_size =
 711            le16_to_cpu(dev->interrupt_in_endpoint->wMaxPacketSize);
 712
 713        if (dev->interrupt_in_endpoint_size != 64)
 714                dev_warn(&intf->dev, "Interrupt in endpoint size is not 64!\n");
 715
 716        if (ring_buffer_size == 0)
 717                ring_buffer_size = RING_BUFFER_SIZE;
 718
 719        true_size = min(ring_buffer_size, RING_BUFFER_SIZE);
 720
 721        /* FIXME - there are more usb_alloc routines for dma correctness.
 722           Needed? */
 723        dev->ring_buffer = kmalloc_array(true_size,
 724                                         sizeof(struct alphatrack_icmd),
 725                                         GFP_KERNEL);
 726        if (!dev->ring_buffer)
 727                goto error;
 728
 729        dev->interrupt_in_buffer = kmalloc(dev->interrupt_in_endpoint_size,
 730                                           GFP_KERNEL);
 731        if (!dev->interrupt_in_buffer)
 732                goto error;
 733
 734        dev->oldi_buffer = kmalloc(dev->interrupt_in_endpoint_size, GFP_KERNEL);
 735        if (!dev->oldi_buffer)
 736                goto error;
 737
 738        dev->interrupt_in_urb = usb_alloc_urb(0, GFP_KERNEL);
 739        if (!dev->interrupt_in_urb) {
 740                dev_err(&intf->dev, "Couldn't allocate interrupt_in_urb\n");
 741                goto error;
 742        }
 743
 744        dev->interrupt_out_endpoint_size =
 745            dev->interrupt_out_endpoint ? le16_to_cpu(dev->
 746                                                      interrupt_out_endpoint->
 747                                                      wMaxPacketSize) : udev->
 748            descriptor.bMaxPacketSize0;
 749
 750        if (dev->interrupt_out_endpoint_size != 64)
 751                dev_warn(&intf->dev,
 752                         "Interrupt out endpoint size is not 64!)\n");
 753
 754        if (write_buffer_size == 0)
 755                write_buffer_size = WRITE_BUFFER_SIZE;
 756        true_size = min(write_buffer_size, WRITE_BUFFER_SIZE);
 757
 758        dev->interrupt_out_buffer =
 759                kmalloc_array(true_size,
 760                              dev->interrupt_out_endpoint_size,
 761                              GFP_KERNEL);
 762        if (!dev->interrupt_out_buffer)
 763                goto error;
 764
 765        dev->write_buffer = kmalloc_array(true_size,
 766                                          sizeof(struct alphatrack_ocmd),
 767                                          GFP_KERNEL);
 768        if (!dev->write_buffer)
 769                goto error;
 770
 771        dev->interrupt_out_urb = usb_alloc_urb(0, GFP_KERNEL);
 772        if (!dev->interrupt_out_urb) {
 773                dev_err(&intf->dev, "Couldn't allocate interrupt_out_urb\n");
 774                goto error;
 775        }
 776        dev->interrupt_in_interval =
 777            min_interrupt_in_interval >
 778            dev->interrupt_in_endpoint->
 779            bInterval ? min_interrupt_in_interval : dev->interrupt_in_endpoint->
 780            bInterval;
 781        if (dev->interrupt_out_endpoint)
 782                dev->interrupt_out_interval =
 783                    min_interrupt_out_interval >
 784                    dev->interrupt_out_endpoint->
 785                    bInterval ? min_interrupt_out_interval : dev->
 786                    interrupt_out_endpoint->bInterval;
 787
 788        /* we can register the device now, as it is ready */
 789        usb_set_intfdata(intf, dev);
 790
 791        atomic_set(&dev->writes_pending, 0);
 792        retval = usb_register_dev(intf, &usb_alphatrack_class);
 793        if (retval) {
 794                /* something prevented us from registering this driver */
 795                dev_err(&intf->dev,
 796                        "Not able to get a minor for this device.\n");
 797                usb_set_intfdata(intf, NULL);
 798                goto error;
 799        }
 800
 801        /* let the user know what node this device is now attached to */
 802        dev_info(&intf->dev,
 803                 "Alphatrack Device #%d now attached to major %d minor %d\n",
 804                 (intf->minor - USB_ALPHATRACK_MINOR_BASE), USB_MAJOR,
 805                 intf->minor);
 806
 807exit:
 808        return retval;
 809
 810error:
 811        usb_alphatrack_delete(dev);
 812
 813        return retval;
 814}
 815
 816/**
 817 *      usb_alphatrack_disconnect
 818 *
 819 *      Called by the usb core when the device is removed from the system.
 820 */
 821static void usb_alphatrack_disconnect(struct usb_interface *intf)
 822{
 823        struct usb_alphatrack *dev;
 824        int minor;
 825
 826        mutex_lock(&disconnect_mutex);
 827
 828        dev = usb_get_intfdata(intf);
 829        usb_set_intfdata(intf, NULL);
 830
 831        mutex_lock(&dev->mtx);
 832
 833        minor = intf->minor;
 834
 835        /* give back our minor */
 836        usb_deregister_dev(intf, &usb_alphatrack_class);
 837
 838        /* if the device is not opened, then we clean up right now */
 839        if (!dev->open_count) {
 840                mutex_unlock(&dev->mtx);
 841                usb_alphatrack_delete(dev);
 842        } else {
 843                dev->intf = NULL;
 844                mutex_unlock(&dev->mtx);
 845        }
 846
 847        atomic_set(&dev->writes_pending, 0);
 848        mutex_unlock(&disconnect_mutex);
 849
 850        dev_info(&intf->dev, "Alphatrack Surface #%d now disconnected\n",
 851                 (minor - USB_ALPHATRACK_MINOR_BASE));
 852}
 853
 854/* usb specific object needed to register this driver with the usb subsystem */
 855static struct usb_driver usb_alphatrack_driver = {
 856        .name = "alphatrack",
 857        .probe = usb_alphatrack_probe,
 858        .disconnect = usb_alphatrack_disconnect,
 859        .id_table = usb_alphatrack_table,
 860};
 861
 862module_usb_driver(usb_alphatrack_driver);
 863
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.