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