linux/drivers/staging/comedi/drivers/vmk80xx.c
<<
>>
Prefs
   1/*
   2    comedi/drivers/vmk80xx.c
   3    Velleman USB Board Low-Level Driver
   4
   5    Copyright (C) 2009 Manuel Gebele <forensixs@gmx.de>, Germany
   6
   7    COMEDI - Linux Control and Measurement Device Interface
   8    Copyright (C) 2000 David A. Schleef <ds@schleef.org>
   9
  10    This program is free software; you can redistribute it and/or modify
  11    it under the terms of the GNU General Public License as published by
  12    the Free Software Foundation; either version 2 of the License, or
  13    (at your option) any later version.
  14
  15    This program is distributed in the hope that it will be useful,
  16    but WITHOUT ANY WARRANTY; without even the implied warranty of
  17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18    GNU General Public License for more details.
  19
  20    You should have received a copy of the GNU General Public License
  21    along with this program; if not, write to the Free Software
  22    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  23
  24*/
  25/*
  26Driver: vmk80xx
  27Description: Velleman USB Board Low-Level Driver
  28Devices: K8055/K8061 aka VM110/VM140
  29Author: Manuel Gebele <forensixs@gmx.de>
  30Updated: Sun, 10 May 2009 11:14:59 +0200
  31Status: works
  32
  33Supports:
  34 - analog input
  35 - analog output
  36 - digital input
  37 - digital output
  38 - counter
  39 - pwm
  40*/
  41/*
  42Changelog:
  43
  440.8.81  -3-  code completely rewritten (adjust driver logic)
  450.8.81  -2-  full support for K8061
  460.8.81  -1-  fix some mistaken among others the number of
  47             supported boards and I/O handling
  48
  490.7.76  -4-  renamed to vmk80xx
  500.7.76  -3-  detect K8061 (only theoretically supported)
  510.7.76  -2-  code completely rewritten (adjust driver logic)
  520.7.76  -1-  support for digital and counter subdevice
  53*/
  54
  55#include <linux/kernel.h>
  56#include <linux/module.h>
  57#include <linux/mutex.h>
  58#include <linux/errno.h>
  59#include <linux/input.h>
  60#include <linux/slab.h>
  61#include <linux/poll.h>
  62#include <linux/usb.h>
  63#include <linux/uaccess.h>
  64
  65#include "../comedidev.h"
  66
  67MODULE_AUTHOR("Manuel Gebele <forensixs@gmx.de>");
  68MODULE_DESCRIPTION("Velleman USB Board Low-Level Driver");
  69MODULE_SUPPORTED_DEVICE("K8055/K8061 aka VM110/VM140");
  70MODULE_VERSION("0.8.01");
  71MODULE_LICENSE("GPL");
  72
  73enum {
  74        DEVICE_VMK8055,
  75        DEVICE_VMK8061
  76};
  77
  78static struct usb_device_id vmk80xx_id_table[] = {
  79        {USB_DEVICE(0x10cf, 0x5500),.driver_info = DEVICE_VMK8055},
  80        {USB_DEVICE(0x10cf, 0x5501),.driver_info = DEVICE_VMK8055},
  81        {USB_DEVICE(0x10cf, 0x5502),.driver_info = DEVICE_VMK8055},
  82        {USB_DEVICE(0x10cf, 0x5503),.driver_info = DEVICE_VMK8055},
  83        {USB_DEVICE(0x10cf, 0x8061),.driver_info = DEVICE_VMK8061},
  84        {USB_DEVICE(0x10cf, 0x8062),.driver_info = DEVICE_VMK8061},
  85        {USB_DEVICE(0x10cf, 0x8063),.driver_info = DEVICE_VMK8061},
  86        {USB_DEVICE(0x10cf, 0x8064),.driver_info = DEVICE_VMK8061},
  87        {USB_DEVICE(0x10cf, 0x8065),.driver_info = DEVICE_VMK8061},
  88        {USB_DEVICE(0x10cf, 0x8066),.driver_info = DEVICE_VMK8061},
  89        {USB_DEVICE(0x10cf, 0x8067),.driver_info = DEVICE_VMK8061},
  90        {USB_DEVICE(0x10cf, 0x8068),.driver_info = DEVICE_VMK8061},
  91        {}                      /* terminating entry */
  92};
  93
  94MODULE_DEVICE_TABLE(usb, vmk80xx_id_table);
  95
  96#define VMK8055_DI_REG          0x00
  97#define VMK8055_DO_REG          0x01
  98#define VMK8055_AO1_REG         0x02
  99#define VMK8055_AO2_REG         0x03
 100#define VMK8055_AI1_REG         0x02
 101#define VMK8055_AI2_REG         0x03
 102#define VMK8055_CNT1_REG        0x04
 103#define VMK8055_CNT2_REG        0x06
 104
 105#define VMK8061_CH_REG          0x01
 106#define VMK8061_DI_REG          0x01
 107#define VMK8061_DO_REG          0x01
 108#define VMK8061_PWM_REG1        0x01
 109#define VMK8061_PWM_REG2        0x02
 110#define VMK8061_CNT_REG         0x02
 111#define VMK8061_AO_REG          0x02
 112#define VMK8061_AI_REG1         0x02
 113#define VMK8061_AI_REG2         0x03
 114
 115#define VMK8055_CMD_RST         0x00
 116#define VMK8055_CMD_DEB1_TIME   0x01
 117#define VMK8055_CMD_DEB2_TIME   0x02
 118#define VMK8055_CMD_RST_CNT1    0x03
 119#define VMK8055_CMD_RST_CNT2    0x04
 120#define VMK8055_CMD_WRT_AD      0x05
 121
 122#define VMK8061_CMD_RD_AI       0x00
 123#define VMK8061_CMR_RD_ALL_AI   0x01    /* !non-active! */
 124#define VMK8061_CMD_SET_AO      0x02
 125#define VMK8061_CMD_SET_ALL_AO  0x03    /* !non-active! */
 126#define VMK8061_CMD_OUT_PWM     0x04
 127#define VMK8061_CMD_RD_DI       0x05
 128#define VMK8061_CMD_DO          0x06    /* !non-active! */
 129#define VMK8061_CMD_CLR_DO      0x07
 130#define VMK8061_CMD_SET_DO      0x08
 131#define VMK8061_CMD_RD_CNT      0x09    /* TODO: completely pointless? */
 132#define VMK8061_CMD_RST_CNT     0x0a    /* TODO: completely pointless? */
 133#define VMK8061_CMD_RD_VERSION  0x0b    /* internal usage */
 134#define VMK8061_CMD_RD_JMP_STAT 0x0c    /* TODO: not implemented yet */
 135#define VMK8061_CMD_RD_PWR_STAT 0x0d    /* internal usage */
 136#define VMK8061_CMD_RD_DO       0x0e
 137#define VMK8061_CMD_RD_AO       0x0f
 138#define VMK8061_CMD_RD_PWM      0x10
 139
 140#define VMK80XX_MAX_BOARDS      COMEDI_NUM_BOARD_MINORS
 141
 142#define TRANS_OUT_BUSY          1
 143#define TRANS_IN_BUSY           2
 144#define TRANS_IN_RUNNING        3
 145
 146#define IC3_VERSION             (1 << 0)
 147#define IC6_VERSION             (1 << 1)
 148
 149#define URB_RCV_FLAG            (1 << 0)
 150#define URB_SND_FLAG            (1 << 1)
 151
 152#define CONFIG_VMK80XX_DEBUG
 153#undef CONFIG_VMK80XX_DEBUG
 154
 155#ifdef CONFIG_VMK80XX_DEBUG
 156static int dbgvm = 1;
 157#else
 158static int dbgvm;
 159#endif
 160
 161#ifdef CONFIG_COMEDI_DEBUG
 162static int dbgcm = 1;
 163#else
 164static int dbgcm;
 165#endif
 166
 167#define dbgvm(fmt, arg...)                     \
 168do {                                           \
 169        if (dbgvm)                             \
 170                printk(KERN_DEBUG fmt, ##arg); \
 171} while (0)
 172
 173#define dbgcm(fmt, arg...)                     \
 174do {                                           \
 175        if (dbgcm)                             \
 176                printk(KERN_DEBUG fmt, ##arg); \
 177} while (0)
 178
 179enum vmk80xx_model {
 180        VMK8055_MODEL,
 181        VMK8061_MODEL
 182};
 183
 184struct firmware_version {
 185        unsigned char ic3_vers[32];     /* USB-Controller */
 186        unsigned char ic6_vers[32];     /* CPU */
 187};
 188
 189static const struct comedi_lrange vmk8055_range = {
 190        1, {UNI_RANGE(5)}
 191};
 192
 193static const struct comedi_lrange vmk8061_range = {
 194        2, {UNI_RANGE(5), UNI_RANGE(10)}
 195};
 196
 197struct vmk80xx_board {
 198        const char *name;
 199        enum vmk80xx_model model;
 200        const struct comedi_lrange *range;
 201        __u8 ai_chans;
 202        __le16 ai_bits;
 203        __u8 ao_chans;
 204        __le16 ao_bits;
 205        __u8 di_chans;
 206        __le16 di_bits;
 207        __u8 do_chans;
 208        __le16 do_bits;
 209        __u8 cnt_chans;
 210        __le16 cnt_bits;
 211        __u8 pwm_chans;
 212        __le16 pwm_bits;
 213};
 214
 215enum {
 216        VMK80XX_SUBD_AI,
 217        VMK80XX_SUBD_AO,
 218        VMK80XX_SUBD_DI,
 219        VMK80XX_SUBD_DO,
 220        VMK80XX_SUBD_CNT,
 221        VMK80XX_SUBD_PWM,
 222};
 223
 224struct vmk80xx_usb {
 225        struct usb_device *udev;
 226        struct usb_interface *intf;
 227        struct usb_endpoint_descriptor *ep_rx;
 228        struct usb_endpoint_descriptor *ep_tx;
 229        struct usb_anchor rx_anchor;
 230        struct usb_anchor tx_anchor;
 231        struct vmk80xx_board board;
 232        struct firmware_version fw;
 233        struct semaphore limit_sem;
 234        wait_queue_head_t read_wait;
 235        wait_queue_head_t write_wait;
 236        unsigned char *usb_rx_buf;
 237        unsigned char *usb_tx_buf;
 238        unsigned long flags;
 239        int probed;
 240        int attached;
 241        int count;
 242};
 243
 244static struct vmk80xx_usb vmb[VMK80XX_MAX_BOARDS];
 245
 246static DEFINE_MUTEX(glb_mutex);
 247
 248static void vmk80xx_tx_callback(struct urb *urb)
 249{
 250        struct vmk80xx_usb *dev = urb->context;
 251        int stat = urb->status;
 252
 253        dbgvm("vmk80xx: %s\n", __func__);
 254
 255        if (stat && !(stat == -ENOENT
 256                      || stat == -ECONNRESET || stat == -ESHUTDOWN))
 257                dbgcm("comedi#: vmk80xx: %s - nonzero urb status (%d)\n",
 258                      __func__, stat);
 259
 260        if (!test_bit(TRANS_OUT_BUSY, &dev->flags))
 261                return;
 262
 263        clear_bit(TRANS_OUT_BUSY, &dev->flags);
 264
 265        wake_up_interruptible(&dev->write_wait);
 266}
 267
 268static void vmk80xx_rx_callback(struct urb *urb)
 269{
 270        struct vmk80xx_usb *dev = urb->context;
 271        int stat = urb->status;
 272
 273        dbgvm("vmk80xx: %s\n", __func__);
 274
 275        switch (stat) {
 276        case 0:
 277                break;
 278        case -ENOENT:
 279        case -ECONNRESET:
 280        case -ESHUTDOWN:
 281                break;
 282        default:
 283                dbgcm("comedi#: vmk80xx: %s - nonzero urb status (%d)\n",
 284                      __func__, stat);
 285                goto resubmit;
 286        }
 287
 288        goto exit;
 289resubmit:
 290        if (test_bit(TRANS_IN_RUNNING, &dev->flags) && dev->intf) {
 291                usb_anchor_urb(urb, &dev->rx_anchor);
 292
 293                if (!usb_submit_urb(urb, GFP_KERNEL))
 294                        goto exit;
 295
 296                err("comedi#: vmk80xx: %s - submit urb failed\n", __func__);
 297
 298                usb_unanchor_urb(urb);
 299        }
 300exit:
 301        clear_bit(TRANS_IN_BUSY, &dev->flags);
 302
 303        wake_up_interruptible(&dev->read_wait);
 304}
 305
 306static int vmk80xx_check_data_link(struct vmk80xx_usb *dev)
 307{
 308        unsigned int tx_pipe, rx_pipe;
 309        unsigned char tx[1], rx[2];
 310
 311        dbgvm("vmk80xx: %s\n", __func__);
 312
 313        tx_pipe = usb_sndbulkpipe(dev->udev, 0x01);
 314        rx_pipe = usb_rcvbulkpipe(dev->udev, 0x81);
 315
 316        tx[0] = VMK8061_CMD_RD_PWR_STAT;
 317
 318        /* Check that IC6 (PIC16F871) is powered and
 319         * running and the data link between IC3 and
 320         * IC6 is working properly */
 321        usb_bulk_msg(dev->udev, tx_pipe, tx, 1, NULL, dev->ep_tx->bInterval);
 322        usb_bulk_msg(dev->udev, rx_pipe, rx, 2, NULL, HZ * 10);
 323
 324        return (int)rx[1];
 325}
 326
 327static void vmk80xx_read_eeprom(struct vmk80xx_usb *dev, int flag)
 328{
 329        unsigned int tx_pipe, rx_pipe;
 330        unsigned char tx[1], rx[64];
 331        int cnt;
 332
 333        dbgvm("vmk80xx: %s\n", __func__);
 334
 335        tx_pipe = usb_sndbulkpipe(dev->udev, 0x01);
 336        rx_pipe = usb_rcvbulkpipe(dev->udev, 0x81);
 337
 338        tx[0] = VMK8061_CMD_RD_VERSION;
 339
 340        /* Read the firmware version info of IC3 and
 341         * IC6 from the internal EEPROM of the IC */
 342        usb_bulk_msg(dev->udev, tx_pipe, tx, 1, NULL, dev->ep_tx->bInterval);
 343        usb_bulk_msg(dev->udev, rx_pipe, rx, 64, &cnt, HZ * 10);
 344
 345        rx[cnt] = '\0';
 346
 347        if (flag & IC3_VERSION)
 348                strncpy(dev->fw.ic3_vers, rx + 1, 24);
 349        else                    /* IC6_VERSION */
 350                strncpy(dev->fw.ic6_vers, rx + 25, 24);
 351}
 352
 353static int vmk80xx_reset_device(struct vmk80xx_usb *dev)
 354{
 355        struct urb *urb;
 356        unsigned int tx_pipe;
 357        int ival;
 358        size_t size;
 359
 360        dbgvm("vmk80xx: %s\n", __func__);
 361
 362        urb = usb_alloc_urb(0, GFP_KERNEL);
 363        if (!urb)
 364                return -ENOMEM;
 365
 366        tx_pipe = usb_sndintpipe(dev->udev, 0x01);
 367
 368        ival = dev->ep_tx->bInterval;
 369        size = le16_to_cpu(dev->ep_tx->wMaxPacketSize);
 370
 371        dev->usb_tx_buf[0] = VMK8055_CMD_RST;
 372        dev->usb_tx_buf[1] = 0x00;
 373        dev->usb_tx_buf[2] = 0x00;
 374        dev->usb_tx_buf[3] = 0x00;
 375        dev->usb_tx_buf[4] = 0x00;
 376        dev->usb_tx_buf[5] = 0x00;
 377        dev->usb_tx_buf[6] = 0x00;
 378        dev->usb_tx_buf[7] = 0x00;
 379
 380        usb_fill_int_urb(urb, dev->udev, tx_pipe, dev->usb_tx_buf,
 381                         size, vmk80xx_tx_callback, dev, ival);
 382
 383        usb_anchor_urb(urb, &dev->tx_anchor);
 384
 385        return usb_submit_urb(urb, GFP_KERNEL);
 386}
 387
 388static void vmk80xx_build_int_urb(struct urb *urb, int flag)
 389{
 390        struct vmk80xx_usb *dev = urb->context;
 391        __u8 rx_addr, tx_addr;
 392        unsigned int pipe;
 393        unsigned char *buf;
 394        size_t size;
 395        void (*callback) (struct urb *);
 396        int ival;
 397
 398        dbgvm("vmk80xx: %s\n", __func__);
 399
 400        if (flag & URB_RCV_FLAG) {
 401                rx_addr = dev->ep_rx->bEndpointAddress;
 402                pipe = usb_rcvintpipe(dev->udev, rx_addr);
 403                buf = dev->usb_rx_buf;
 404                size = le16_to_cpu(dev->ep_rx->wMaxPacketSize);
 405                callback = vmk80xx_rx_callback;
 406                ival = dev->ep_rx->bInterval;
 407        } else {                /* URB_SND_FLAG */
 408                tx_addr = dev->ep_tx->bEndpointAddress;
 409                pipe = usb_sndintpipe(dev->udev, tx_addr);
 410                buf = dev->usb_tx_buf;
 411                size = le16_to_cpu(dev->ep_tx->wMaxPacketSize);
 412                callback = vmk80xx_tx_callback;
 413                ival = dev->ep_tx->bInterval;
 414        }
 415
 416        usb_fill_int_urb(urb, dev->udev, pipe, buf, size, callback, dev, ival);
 417}
 418
 419static void vmk80xx_do_bulk_msg(struct vmk80xx_usb *dev)
 420{
 421        __u8 tx_addr, rx_addr;
 422        unsigned int tx_pipe, rx_pipe;
 423        size_t size;
 424
 425        dbgvm("vmk80xx: %s\n", __func__);
 426
 427        set_bit(TRANS_IN_BUSY, &dev->flags);
 428        set_bit(TRANS_OUT_BUSY, &dev->flags);
 429
 430        tx_addr = dev->ep_tx->bEndpointAddress;
 431        rx_addr = dev->ep_rx->bEndpointAddress;
 432        tx_pipe = usb_sndbulkpipe(dev->udev, tx_addr);
 433        rx_pipe = usb_rcvbulkpipe(dev->udev, rx_addr);
 434
 435        /* The max packet size attributes of the K8061
 436         * input/output endpoints are identical */
 437        size = le16_to_cpu(dev->ep_tx->wMaxPacketSize);
 438
 439        usb_bulk_msg(dev->udev, tx_pipe, dev->usb_tx_buf,
 440                     size, NULL, dev->ep_tx->bInterval);
 441        usb_bulk_msg(dev->udev, rx_pipe, dev->usb_rx_buf, size, NULL, HZ * 10);
 442
 443        clear_bit(TRANS_OUT_BUSY, &dev->flags);
 444        clear_bit(TRANS_IN_BUSY, &dev->flags);
 445}
 446
 447static int vmk80xx_read_packet(struct vmk80xx_usb *dev)
 448{
 449        struct urb *urb;
 450        int retval;
 451
 452        dbgvm("vmk80xx: %s\n", __func__);
 453
 454        if (!dev->intf)
 455                return -ENODEV;
 456
 457        /* Only useful for interrupt transfers */
 458        if (test_bit(TRANS_IN_BUSY, &dev->flags))
 459                if (wait_event_interruptible(dev->read_wait,
 460                                             !test_bit(TRANS_IN_BUSY,
 461                                                       &dev->flags)))
 462                        return -ERESTART;
 463
 464        if (dev->board.model == VMK8061_MODEL) {
 465                vmk80xx_do_bulk_msg(dev);
 466
 467                return 0;
 468        }
 469
 470        urb = usb_alloc_urb(0, GFP_KERNEL);
 471        if (!urb)
 472                return -ENOMEM;
 473
 474        urb->context = dev;
 475        vmk80xx_build_int_urb(urb, URB_RCV_FLAG);
 476
 477        set_bit(TRANS_IN_RUNNING, &dev->flags);
 478        set_bit(TRANS_IN_BUSY, &dev->flags);
 479
 480        usb_anchor_urb(urb, &dev->rx_anchor);
 481
 482        retval = usb_submit_urb(urb, GFP_KERNEL);
 483        if (!retval)
 484                goto exit;
 485
 486        clear_bit(TRANS_IN_RUNNING, &dev->flags);
 487        usb_unanchor_urb(urb);
 488
 489exit:
 490        usb_free_urb(urb);
 491
 492        return retval;
 493}
 494
 495static int vmk80xx_write_packet(struct vmk80xx_usb *dev, int cmd)
 496{
 497        struct urb *urb;
 498        int retval;
 499
 500        dbgvm("vmk80xx: %s\n", __func__);
 501
 502        if (!dev->intf)
 503                return -ENODEV;
 504
 505        if (test_bit(TRANS_OUT_BUSY, &dev->flags))
 506                if (wait_event_interruptible(dev->write_wait,
 507                                             !test_bit(TRANS_OUT_BUSY,
 508                                                       &dev->flags)))
 509                        return -ERESTART;
 510
 511        if (dev->board.model == VMK8061_MODEL) {
 512                dev->usb_tx_buf[0] = cmd;
 513                vmk80xx_do_bulk_msg(dev);
 514
 515                return 0;
 516        }
 517
 518        urb = usb_alloc_urb(0, GFP_KERNEL);
 519        if (!urb)
 520                return -ENOMEM;
 521
 522        urb->context = dev;
 523        vmk80xx_build_int_urb(urb, URB_SND_FLAG);
 524
 525        set_bit(TRANS_OUT_BUSY, &dev->flags);
 526
 527        usb_anchor_urb(urb, &dev->tx_anchor);
 528
 529        dev->usb_tx_buf[0] = cmd;
 530
 531        retval = usb_submit_urb(urb, GFP_KERNEL);
 532        if (!retval)
 533                goto exit;
 534
 535        clear_bit(TRANS_OUT_BUSY, &dev->flags);
 536        usb_unanchor_urb(urb);
 537
 538exit:
 539        usb_free_urb(urb);
 540
 541        return retval;
 542}
 543
 544#define DIR_IN  1
 545#define DIR_OUT 2
 546
 547#define rudimentary_check(dir)                             \
 548do {                                                       \
 549        if (!dev)                                          \
 550                return -EFAULT;                            \
 551        if (!dev->probed)                                  \
 552                return -ENODEV;                            \
 553        if (!dev->attached)                                \
 554                return -ENODEV;                            \
 555        if ((dir) & DIR_IN) {                              \
 556                if (test_bit(TRANS_IN_BUSY, &dev->flags))  \
 557                        return -EBUSY;                     \
 558        } else {  /* DIR_OUT */                            \
 559                if (test_bit(TRANS_OUT_BUSY, &dev->flags)) \
 560                        return -EBUSY;                     \
 561        }                                                  \
 562} while (0)
 563
 564static int vmk80xx_ai_rinsn(struct comedi_device *cdev,
 565                            struct comedi_subdevice *s,
 566                            struct comedi_insn *insn, unsigned int *data)
 567{
 568        struct vmk80xx_usb *dev = cdev->private;
 569        int chan, reg[2];
 570        int n;
 571
 572        dbgvm("vmk80xx: %s\n", __func__);
 573
 574        rudimentary_check(DIR_IN);
 575
 576        down(&dev->limit_sem);
 577        chan = CR_CHAN(insn->chanspec);
 578
 579        switch (dev->board.model) {
 580        case VMK8055_MODEL:
 581                if (!chan)
 582                        reg[0] = VMK8055_AI1_REG;
 583                else
 584                        reg[0] = VMK8055_AI2_REG;
 585                break;
 586        case VMK8061_MODEL:
 587                reg[0] = VMK8061_AI_REG1;
 588                reg[1] = VMK8061_AI_REG2;
 589                dev->usb_tx_buf[0] = VMK8061_CMD_RD_AI;
 590                dev->usb_tx_buf[VMK8061_CH_REG] = chan;
 591                break;
 592        }
 593
 594        for (n = 0; n < insn->n; n++) {
 595                if (vmk80xx_read_packet(dev))
 596                        break;
 597
 598                if (dev->board.model == VMK8055_MODEL) {
 599                        data[n] = dev->usb_rx_buf[reg[0]];
 600                        continue;
 601                }
 602
 603                /* VMK8061_MODEL */
 604                data[n] = dev->usb_rx_buf[reg[0]] + 256 *
 605                    dev->usb_rx_buf[reg[1]];
 606        }
 607
 608        up(&dev->limit_sem);
 609
 610        return n;
 611}
 612
 613static int vmk80xx_ao_winsn(struct comedi_device *cdev,
 614                            struct comedi_subdevice *s,
 615                            struct comedi_insn *insn, unsigned int *data)
 616{
 617        struct vmk80xx_usb *dev = cdev->private;
 618        int chan, cmd, reg;
 619        int n;
 620
 621        dbgvm("vmk80xx: %s\n", __func__);
 622
 623        rudimentary_check(DIR_OUT);
 624
 625        down(&dev->limit_sem);
 626        chan = CR_CHAN(insn->chanspec);
 627
 628        switch (dev->board.model) {
 629        case VMK8055_MODEL:
 630                cmd = VMK8055_CMD_WRT_AD;
 631                if (!chan)
 632                        reg = VMK8055_AO1_REG;
 633                else
 634                        reg = VMK8055_AO2_REG;
 635                break;
 636        default:                /* NOTE: avoid compiler warnings */
 637                cmd = VMK8061_CMD_SET_AO;
 638                reg = VMK8061_AO_REG;
 639                dev->usb_tx_buf[VMK8061_CH_REG] = chan;
 640                break;
 641        }
 642
 643        for (n = 0; n < insn->n; n++) {
 644                dev->usb_tx_buf[reg] = data[n];
 645
 646                if (vmk80xx_write_packet(dev, cmd))
 647                        break;
 648        }
 649
 650        up(&dev->limit_sem);
 651
 652        return n;
 653}
 654
 655static int vmk80xx_ao_rinsn(struct comedi_device *cdev,
 656                            struct comedi_subdevice *s,
 657                            struct comedi_insn *insn, unsigned int *data)
 658{
 659        struct vmk80xx_usb *dev = cdev->private;
 660        int chan, reg;
 661        int n;
 662
 663        dbgvm("vmk80xx: %s\n", __func__);
 664
 665        rudimentary_check(DIR_IN);
 666
 667        down(&dev->limit_sem);
 668        chan = CR_CHAN(insn->chanspec);
 669
 670        reg = VMK8061_AO_REG - 1;
 671
 672        dev->usb_tx_buf[0] = VMK8061_CMD_RD_AO;
 673
 674        for (n = 0; n < insn->n; n++) {
 675                if (vmk80xx_read_packet(dev))
 676                        break;
 677
 678                data[n] = dev->usb_rx_buf[reg + chan];
 679        }
 680
 681        up(&dev->limit_sem);
 682
 683        return n;
 684}
 685
 686static int vmk80xx_di_rinsn(struct comedi_device *cdev,
 687                            struct comedi_subdevice *s,
 688                            struct comedi_insn *insn, unsigned int *data)
 689{
 690        struct vmk80xx_usb *dev = cdev->private;
 691        int chan;
 692        unsigned char *rx_buf;
 693        int reg, inp;
 694        int n;
 695
 696        dbgvm("vmk80xx: %s\n", __func__);
 697
 698        rudimentary_check(DIR_IN);
 699
 700        down(&dev->limit_sem);
 701        chan = CR_CHAN(insn->chanspec);
 702
 703        rx_buf = dev->usb_rx_buf;
 704
 705        if (dev->board.model == VMK8061_MODEL) {
 706                reg = VMK8061_DI_REG;
 707                dev->usb_tx_buf[0] = VMK8061_CMD_RD_DI;
 708        } else
 709                reg = VMK8055_DI_REG;
 710
 711        for (n = 0; n < insn->n; n++) {
 712                if (vmk80xx_read_packet(dev))
 713                        break;
 714
 715                if (dev->board.model == VMK8055_MODEL)
 716                        inp = (((rx_buf[reg] >> 4) & 0x03) |
 717                               ((rx_buf[reg] << 2) & 0x04) |
 718                               ((rx_buf[reg] >> 3) & 0x18));
 719                else
 720                        inp = rx_buf[reg];
 721
 722                data[n] = ((inp & (1 << chan)) > 0);
 723        }
 724
 725        up(&dev->limit_sem);
 726
 727        return n;
 728}
 729
 730static int vmk80xx_do_winsn(struct comedi_device *cdev,
 731                            struct comedi_subdevice *s,
 732                            struct comedi_insn *insn, unsigned int *data)
 733{
 734
 735        struct vmk80xx_usb *dev = cdev->private;
 736        int chan;
 737        unsigned char *tx_buf;
 738        int reg, cmd;
 739        int n;
 740
 741        dbgvm("vmk80xx: %s\n", __func__);
 742
 743        rudimentary_check(DIR_OUT);
 744
 745        down(&dev->limit_sem);
 746        chan = CR_CHAN(insn->chanspec);
 747
 748        tx_buf = dev->usb_tx_buf;
 749
 750        for (n = 0; n < insn->n; n++) {
 751                if (dev->board.model == VMK8055_MODEL) {
 752                        reg = VMK8055_DO_REG;
 753                        cmd = VMK8055_CMD_WRT_AD;
 754                        if (data[n] == 1)
 755                                tx_buf[reg] |= (1 << chan);
 756                        else
 757                                tx_buf[reg] ^= (1 << chan);
 758
 759                        goto write_packet;
 760                }
 761
 762                /* VMK8061_MODEL */
 763                reg = VMK8061_DO_REG;
 764                if (data[n] == 1) {
 765                        cmd = VMK8061_CMD_SET_DO;
 766                        tx_buf[reg] = 1 << chan;
 767                } else {
 768                        cmd = VMK8061_CMD_CLR_DO;
 769                        tx_buf[reg] = 0xff - (1 << chan);
 770                }
 771
 772write_packet:
 773                if (vmk80xx_write_packet(dev, cmd))
 774                        break;
 775        }
 776
 777        up(&dev->limit_sem);
 778
 779        return n;
 780}
 781
 782static int vmk80xx_do_rinsn(struct comedi_device *cdev,
 783                            struct comedi_subdevice *s,
 784                            struct comedi_insn *insn, unsigned int *data)
 785{
 786        struct vmk80xx_usb *dev = cdev->private;
 787        int chan, reg, mask;
 788        int n;
 789
 790        dbgvm("vmk80xx: %s\n", __func__);
 791
 792        rudimentary_check(DIR_IN);
 793
 794        down(&dev->limit_sem);
 795        chan = CR_CHAN(insn->chanspec);
 796
 797        reg = VMK8061_DO_REG;
 798        mask = 1 << chan;
 799
 800        dev->usb_tx_buf[0] = VMK8061_CMD_RD_DO;
 801
 802        for (n = 0; n < insn->n; n++) {
 803                if (vmk80xx_read_packet(dev))
 804                        break;
 805
 806                data[n] = (dev->usb_rx_buf[reg] & mask) >> chan;
 807        }
 808
 809        up(&dev->limit_sem);
 810
 811        return n;
 812}
 813
 814static int vmk80xx_cnt_rinsn(struct comedi_device *cdev,
 815                             struct comedi_subdevice *s,
 816                             struct comedi_insn *insn, unsigned int *data)
 817{
 818        struct vmk80xx_usb *dev = cdev->private;
 819        int chan, reg[2];
 820        int n;
 821
 822        dbgvm("vmk80xx: %s\n", __func__);
 823
 824        rudimentary_check(DIR_IN);
 825
 826        down(&dev->limit_sem);
 827        chan = CR_CHAN(insn->chanspec);
 828
 829        switch (dev->board.model) {
 830        case VMK8055_MODEL:
 831                if (!chan)
 832                        reg[0] = VMK8055_CNT1_REG;
 833                else
 834                        reg[0] = VMK8055_CNT2_REG;
 835                break;
 836        case VMK8061_MODEL:
 837                reg[0] = VMK8061_CNT_REG;
 838                reg[1] = VMK8061_CNT_REG;
 839                dev->usb_tx_buf[0] = VMK8061_CMD_RD_CNT;
 840                break;
 841        }
 842
 843        for (n = 0; n < insn->n; n++) {
 844                if (vmk80xx_read_packet(dev))
 845                        break;
 846
 847                if (dev->board.model == VMK8055_MODEL) {
 848                        data[n] = dev->usb_rx_buf[reg[0]];
 849                        continue;
 850                }
 851
 852                /* VMK8061_MODEL */
 853                data[n] = dev->usb_rx_buf[reg[0] * (chan + 1) + 1]
 854                    + 256 * dev->usb_rx_buf[reg[1] * 2 + 2];
 855        }
 856
 857        up(&dev->limit_sem);
 858
 859        return n;
 860}
 861
 862static int vmk80xx_cnt_cinsn(struct comedi_device *cdev,
 863                             struct comedi_subdevice *s,
 864                             struct comedi_insn *insn, unsigned int *data)
 865{
 866        struct vmk80xx_usb *dev = cdev->private;
 867        unsigned int insn_cmd;
 868        int chan, cmd, reg;
 869        int n;
 870
 871        dbgvm("vmk80xx: %s\n", __func__);
 872
 873        rudimentary_check(DIR_OUT);
 874
 875        down(&dev->limit_sem);
 876
 877        insn_cmd = data[0];
 878        if (insn_cmd != INSN_CONFIG_RESET && insn_cmd != GPCT_RESET)
 879                return -EINVAL;
 880
 881        chan = CR_CHAN(insn->chanspec);
 882
 883        if (dev->board.model == VMK8055_MODEL) {
 884                if (!chan) {
 885                        cmd = VMK8055_CMD_RST_CNT1;
 886                        reg = VMK8055_CNT1_REG;
 887                } else {
 888                        cmd = VMK8055_CMD_RST_CNT2;
 889                        reg = VMK8055_CNT2_REG;
 890                }
 891
 892                dev->usb_tx_buf[reg] = 0x00;
 893        } else
 894                cmd = VMK8061_CMD_RST_CNT;
 895
 896        for (n = 0; n < insn->n; n++)
 897                if (vmk80xx_write_packet(dev, cmd))
 898                        break;
 899
 900        up(&dev->limit_sem);
 901
 902        return n;
 903}
 904
 905static int vmk80xx_cnt_winsn(struct comedi_device *cdev,
 906                             struct comedi_subdevice *s,
 907                             struct comedi_insn *insn, unsigned int *data)
 908{
 909        struct vmk80xx_usb *dev = cdev->private;
 910        unsigned long debtime, val;
 911        int chan, cmd;
 912        int n;
 913
 914        dbgvm("vmk80xx: %s\n", __func__);
 915
 916        rudimentary_check(DIR_OUT);
 917
 918        down(&dev->limit_sem);
 919        chan = CR_CHAN(insn->chanspec);
 920
 921        if (!chan)
 922                cmd = VMK8055_CMD_DEB1_TIME;
 923        else
 924                cmd = VMK8055_CMD_DEB2_TIME;
 925
 926        for (n = 0; n < insn->n; n++) {
 927                debtime = data[n];
 928                if (debtime == 0)
 929                        debtime = 1;
 930
 931                /* TODO: Prevent overflows */
 932                if (debtime > 7450)
 933                        debtime = 7450;
 934
 935                val = int_sqrt(debtime * 1000 / 115);
 936                if (((val + 1) * val) < debtime * 1000 / 115)
 937                        val += 1;
 938
 939                dev->usb_tx_buf[6 + chan] = val;
 940
 941                if (vmk80xx_write_packet(dev, cmd))
 942                        break;
 943        }
 944
 945        up(&dev->limit_sem);
 946
 947        return n;
 948}
 949
 950static int vmk80xx_pwm_rinsn(struct comedi_device *cdev,
 951                             struct comedi_subdevice *s,
 952                             struct comedi_insn *insn, unsigned int *data)
 953{
 954        struct vmk80xx_usb *dev = cdev->private;
 955        int reg[2];
 956        int n;
 957
 958        dbgvm("vmk80xx: %s\n", __func__);
 959
 960        rudimentary_check(DIR_IN);
 961
 962        down(&dev->limit_sem);
 963
 964        reg[0] = VMK8061_PWM_REG1;
 965        reg[1] = VMK8061_PWM_REG2;
 966
 967        dev->usb_tx_buf[0] = VMK8061_CMD_RD_PWM;
 968
 969        for (n = 0; n < insn->n; n++) {
 970                if (vmk80xx_read_packet(dev))
 971                        break;
 972
 973                data[n] = dev->usb_rx_buf[reg[0]] + 4 * dev->usb_rx_buf[reg[1]];
 974        }
 975
 976        up(&dev->limit_sem);
 977
 978        return n;
 979}
 980
 981static int vmk80xx_pwm_winsn(struct comedi_device *cdev,
 982                             struct comedi_subdevice *s,
 983                             struct comedi_insn *insn, unsigned int *data)
 984{
 985        struct vmk80xx_usb *dev = cdev->private;
 986        unsigned char *tx_buf;
 987        int reg[2], cmd;
 988        int n;
 989
 990        dbgvm("vmk80xx: %s\n", __func__);
 991
 992        rudimentary_check(DIR_OUT);
 993
 994        down(&dev->limit_sem);
 995
 996        tx_buf = dev->usb_tx_buf;
 997
 998        reg[0] = VMK8061_PWM_REG1;
 999        reg[1] = VMK8061_PWM_REG2;
1000
1001        cmd = VMK8061_CMD_OUT_PWM;
1002
1003        /*
1004         * The followin piece of code was translated from the inline
1005         * assembler code in the DLL source code.
1006         *
1007         * asm
1008         *   mov eax, k  ; k is the value (data[n])
1009         *   and al, 03h ; al are the lower 8 bits of eax
1010         *   mov lo, al  ; lo is the low part (tx_buf[reg[0]])
1011         *   mov eax, k
1012         *   shr eax, 2  ; right shift eax register by 2
1013         *   mov hi, al  ; hi is the high part (tx_buf[reg[1]])
1014         * end;
1015         */
1016        for (n = 0; n < insn->n; n++) {
1017                tx_buf[reg[0]] = (unsigned char)(data[n] & 0x03);
1018                tx_buf[reg[1]] = (unsigned char)(data[n] >> 2) & 0xff;
1019
1020                if (vmk80xx_write_packet(dev, cmd))
1021                        break;
1022        }
1023
1024        up(&dev->limit_sem);
1025
1026        return n;
1027}
1028
1029static int
1030vmk80xx_attach(struct comedi_device *cdev, struct comedi_devconfig *it)
1031{
1032        int i;
1033        struct vmk80xx_usb *dev;
1034        int n_subd;
1035        struct comedi_subdevice *s;
1036        int minor;
1037
1038        dbgvm("vmk80xx: %s\n", __func__);
1039
1040        mutex_lock(&glb_mutex);
1041
1042        for (i = 0; i < VMK80XX_MAX_BOARDS; i++)
1043                if (vmb[i].probed && !vmb[i].attached)
1044                        break;
1045
1046        if (i == VMK80XX_MAX_BOARDS) {
1047                mutex_unlock(&glb_mutex);
1048                return -ENODEV;
1049        }
1050
1051        dev = &vmb[i];
1052
1053        down(&dev->limit_sem);
1054
1055        cdev->board_name = dev->board.name;
1056        cdev->private = dev;
1057
1058        if (dev->board.model == VMK8055_MODEL)
1059                n_subd = 5;
1060        else
1061                n_subd = 6;
1062
1063        if (alloc_subdevices(cdev, n_subd) < 0) {
1064                up(&dev->limit_sem);
1065                mutex_unlock(&glb_mutex);
1066                return -ENOMEM;
1067        }
1068
1069        /* Analog input subdevice */
1070        s = cdev->subdevices + VMK80XX_SUBD_AI;
1071        s->type = COMEDI_SUBD_AI;
1072        s->subdev_flags = SDF_READABLE | SDF_GROUND;
1073        s->n_chan = dev->board.ai_chans;
1074        s->maxdata = (1 << dev->board.ai_bits) - 1;
1075        s->range_table = dev->board.range;
1076        s->insn_read = vmk80xx_ai_rinsn;
1077
1078        /* Analog output subdevice */
1079        s = cdev->subdevices + VMK80XX_SUBD_AO;
1080        s->type = COMEDI_SUBD_AO;
1081        s->subdev_flags = SDF_WRITEABLE | SDF_GROUND;
1082        s->n_chan = dev->board.ao_chans;
1083        s->maxdata = (1 << dev->board.ao_bits) - 1;
1084        s->range_table = dev->board.range;
1085        s->insn_write = vmk80xx_ao_winsn;
1086
1087        if (dev->board.model == VMK8061_MODEL) {
1088                s->subdev_flags |= SDF_READABLE;
1089                s->insn_read = vmk80xx_ao_rinsn;
1090        }
1091
1092        /* Digital input subdevice */
1093        s = cdev->subdevices + VMK80XX_SUBD_DI;
1094        s->type = COMEDI_SUBD_DI;
1095        s->subdev_flags = SDF_READABLE | SDF_GROUND;
1096        s->n_chan = dev->board.di_chans;
1097        s->maxdata = (1 << dev->board.di_bits) - 1;
1098        s->insn_read = vmk80xx_di_rinsn;
1099
1100        /* Digital output subdevice */
1101        s = cdev->subdevices + VMK80XX_SUBD_DO;
1102        s->type = COMEDI_SUBD_DO;
1103        s->subdev_flags = SDF_WRITEABLE | SDF_GROUND;
1104        s->n_chan = dev->board.do_chans;
1105        s->maxdata = (1 << dev->board.do_bits) - 1;
1106        s->insn_write = vmk80xx_do_winsn;
1107
1108        if (dev->board.model == VMK8061_MODEL) {
1109                s->subdev_flags |= SDF_READABLE;
1110                s->insn_read = vmk80xx_do_rinsn;
1111        }
1112
1113        /* Counter subdevice */
1114        s = cdev->subdevices + VMK80XX_SUBD_CNT;
1115        s->type = COMEDI_SUBD_COUNTER;
1116        s->subdev_flags = SDF_READABLE;
1117        s->n_chan = dev->board.cnt_chans;
1118        s->insn_read = vmk80xx_cnt_rinsn;
1119        s->insn_config = vmk80xx_cnt_cinsn;
1120
1121        if (dev->board.model == VMK8055_MODEL) {
1122                s->subdev_flags |= SDF_WRITEABLE;
1123                s->maxdata = (1 << dev->board.cnt_bits) - 1;
1124                s->insn_write = vmk80xx_cnt_winsn;
1125        }
1126
1127        /* PWM subdevice */
1128        if (dev->board.model == VMK8061_MODEL) {
1129                s = cdev->subdevices + VMK80XX_SUBD_PWM;
1130                s->type = COMEDI_SUBD_PWM;
1131                s->subdev_flags = SDF_READABLE | SDF_WRITEABLE;
1132                s->n_chan = dev->board.pwm_chans;
1133                s->maxdata = (1 << dev->board.pwm_bits) - 1;
1134                s->insn_read = vmk80xx_pwm_rinsn;
1135                s->insn_write = vmk80xx_pwm_winsn;
1136        }
1137
1138        dev->attached = 1;
1139
1140        minor = cdev->minor;
1141
1142        printk(KERN_INFO
1143               "comedi%d: vmk80xx: board #%d [%s] attached to comedi\n",
1144               minor, dev->count, dev->board.name);
1145
1146        up(&dev->limit_sem);
1147        mutex_unlock(&glb_mutex);
1148
1149        return 0;
1150}
1151
1152static int vmk80xx_detach(struct comedi_device *cdev)
1153{
1154        struct vmk80xx_usb *dev;
1155        int minor;
1156
1157        dbgvm("vmk80xx: %s\n", __func__);
1158
1159        if (!cdev)
1160                return -EFAULT;
1161
1162        dev = cdev->private;
1163        if (!dev)
1164                return -EFAULT;
1165
1166        down(&dev->limit_sem);
1167
1168        cdev->private = NULL;
1169        dev->attached = 0;
1170
1171        minor = cdev->minor;
1172
1173        printk(KERN_INFO
1174               "comedi%d: vmk80xx: board #%d [%s] detached from comedi\n",
1175               minor, dev->count, dev->board.name);
1176
1177        up(&dev->limit_sem);
1178
1179        return 0;
1180}
1181
1182static int
1183vmk80xx_probe(struct usb_interface *intf, const struct usb_device_id *id)
1184{
1185        int i;
1186        struct vmk80xx_usb *dev;
1187        struct usb_host_interface *iface_desc;
1188        struct usb_endpoint_descriptor *ep_desc;
1189        size_t size;
1190
1191        dbgvm("vmk80xx: %s\n", __func__);
1192
1193        mutex_lock(&glb_mutex);
1194
1195        for (i = 0; i < VMK80XX_MAX_BOARDS; i++)
1196                if (!vmb[i].probed)
1197                        break;
1198
1199        if (i == VMK80XX_MAX_BOARDS) {
1200                mutex_unlock(&glb_mutex);
1201                return -EMFILE;
1202        }
1203
1204        dev = &vmb[i];
1205
1206        memset(dev, 0x00, sizeof(struct vmk80xx_usb));
1207        dev->count = i;
1208
1209        iface_desc = intf->cur_altsetting;
1210        if (iface_desc->desc.bNumEndpoints != 2)
1211                goto error;
1212
1213        for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) {
1214                ep_desc = &iface_desc->endpoint[i].desc;
1215
1216                if (usb_endpoint_is_int_in(ep_desc)) {
1217                        dev->ep_rx = ep_desc;
1218                        continue;
1219                }
1220
1221                if (usb_endpoint_is_int_out(ep_desc)) {
1222                        dev->ep_tx = ep_desc;
1223                        continue;
1224                }
1225
1226                if (usb_endpoint_is_bulk_in(ep_desc)) {
1227                        dev->ep_rx = ep_desc;
1228                        continue;
1229                }
1230
1231                if (usb_endpoint_is_bulk_out(ep_desc)) {
1232                        dev->ep_tx = ep_desc;
1233                        continue;
1234                }
1235        }
1236
1237        if (!dev->ep_rx || !dev->ep_tx)
1238                goto error;
1239
1240        size = le16_to_cpu(dev->ep_rx->wMaxPacketSize);
1241        dev->usb_rx_buf = kmalloc(size, GFP_KERNEL);
1242        if (!dev->usb_rx_buf) {
1243                mutex_unlock(&glb_mutex);
1244                return -ENOMEM;
1245        }
1246
1247        size = le16_to_cpu(dev->ep_tx->wMaxPacketSize);
1248        dev->usb_tx_buf = kmalloc(size, GFP_KERNEL);
1249        if (!dev->usb_tx_buf) {
1250                kfree(dev->usb_rx_buf);
1251                mutex_unlock(&glb_mutex);
1252                return -ENOMEM;
1253        }
1254
1255        dev->udev = interface_to_usbdev(intf);
1256        dev->intf = intf;
1257
1258        sema_init(&dev->limit_sem, 8);
1259        init_waitqueue_head(&dev->read_wait);
1260        init_waitqueue_head(&dev->write_wait);
1261
1262        init_usb_anchor(&dev->rx_anchor);
1263        init_usb_anchor(&dev->tx_anchor);
1264
1265        usb_set_intfdata(intf, dev);
1266
1267        switch (id->driver_info) {
1268        case DEVICE_VMK8055:
1269                dev->board.name = "K8055 (VM110)";
1270                dev->board.model = VMK8055_MODEL;
1271                dev->board.range = &vmk8055_range;
1272                dev->board.ai_chans = 2;
1273                dev->board.ai_bits = 8;
1274                dev->board.ao_chans = 2;
1275                dev->board.ao_bits = 8;
1276                dev->board.di_chans = 5;
1277                dev->board.di_bits = 1;
1278                dev->board.do_chans = 8;
1279                dev->board.do_bits = 1;
1280                dev->board.cnt_chans = 2;
1281                dev->board.cnt_bits = 16;
1282                dev->board.pwm_chans = 0;
1283                dev->board.pwm_bits = 0;
1284                break;
1285        case DEVICE_VMK8061:
1286                dev->board.name = "K8061 (VM140)";
1287                dev->board.model = VMK8061_MODEL;
1288                dev->board.range = &vmk8061_range;
1289                dev->board.ai_chans = 8;
1290                dev->board.ai_bits = 10;
1291                dev->board.ao_chans = 8;
1292                dev->board.ao_bits = 8;
1293                dev->board.di_chans = 8;
1294                dev->board.di_bits = 1;
1295                dev->board.do_chans = 8;
1296                dev->board.do_bits = 1;
1297                dev->board.cnt_chans = 2;
1298                dev->board.cnt_bits = 0;
1299                dev->board.pwm_chans = 1;
1300                dev->board.pwm_bits = 10;
1301                break;
1302        }
1303
1304        if (dev->board.model == VMK8061_MODEL) {
1305                vmk80xx_read_eeprom(dev, IC3_VERSION);
1306                printk(KERN_INFO "comedi#: vmk80xx: %s\n", dev->fw.ic3_vers);
1307
1308                if (vmk80xx_check_data_link(dev)) {
1309                        vmk80xx_read_eeprom(dev, IC6_VERSION);
1310                        printk(KERN_INFO "comedi#: vmk80xx: %s\n",
1311                               dev->fw.ic6_vers);
1312                } else
1313                        dbgcm("comedi#: vmk80xx: no conn. to CPU\n");
1314        }
1315
1316        if (dev->board.model == VMK8055_MODEL)
1317                vmk80xx_reset_device(dev);
1318
1319        dev->probed = 1;
1320
1321        printk(KERN_INFO "comedi#: vmk80xx: board #%d [%s] now attached\n",
1322               dev->count, dev->board.name);
1323
1324        mutex_unlock(&glb_mutex);
1325
1326        return 0;
1327error:
1328        mutex_unlock(&glb_mutex);
1329
1330        return -ENODEV;
1331}
1332
1333static void vmk80xx_disconnect(struct usb_interface *intf)
1334{
1335        struct vmk80xx_usb *dev = usb_get_intfdata(intf);
1336
1337        dbgvm("vmk80xx: %s\n", __func__);
1338
1339        if (!dev)
1340                return;
1341
1342        mutex_lock(&glb_mutex);
1343        down(&dev->limit_sem);
1344
1345        dev->probed = 0;
1346        usb_set_intfdata(dev->intf, NULL);
1347
1348        usb_kill_anchored_urbs(&dev->rx_anchor);
1349        usb_kill_anchored_urbs(&dev->tx_anchor);
1350
1351        kfree(dev->usb_rx_buf);
1352        kfree(dev->usb_tx_buf);
1353
1354        printk(KERN_INFO "comedi#: vmk80xx: board #%d [%s] now detached\n",
1355               dev->count, dev->board.name);
1356
1357        up(&dev->limit_sem);
1358        mutex_unlock(&glb_mutex);
1359}
1360
1361/* TODO: Add support for suspend, resume, pre_reset,
1362 * post_reset and flush */
1363static struct usb_driver vmk80xx_driver = {
1364        .name = "vmk80xx",
1365        .probe = vmk80xx_probe,
1366        .disconnect = vmk80xx_disconnect,
1367        .id_table = vmk80xx_id_table
1368};
1369
1370static struct comedi_driver driver_vmk80xx = {
1371        .module = THIS_MODULE,
1372        .driver_name = "vmk80xx",
1373        .attach = vmk80xx_attach,
1374        .detach = vmk80xx_detach
1375};
1376
1377static int __init vmk80xx_init(void)
1378{
1379        printk(KERN_INFO "vmk80xx: version 0.8.01 "
1380               "Manuel Gebele <forensixs@gmx.de>\n");
1381        usb_register(&vmk80xx_driver);
1382        return comedi_driver_register(&driver_vmk80xx);
1383}
1384
1385static void __exit vmk80xx_exit(void)
1386{
1387        comedi_driver_unregister(&driver_vmk80xx);
1388        usb_deregister(&vmk80xx_driver);
1389}
1390
1391module_init(vmk80xx_init);
1392module_exit(vmk80xx_exit);
1393