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