GNU Linux-libre 4.14.332-gnu1
[releases.git] / drivers / staging / comedi / drivers / vmk80xx.c
1 /*
2  * 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
21 /*
22  * Driver: vmk80xx
23  * Description: Velleman USB Board Low-Level Driver
24  * Devices: [Velleman] K8055 (K8055/VM110), K8061 (K8061/VM140),
25  *   VM110 (K8055/VM110), VM140 (K8061/VM140)
26  * Author: Manuel Gebele <forensixs@gmx.de>
27  * Updated: Sun, 10 May 2009 11:14:59 +0200
28  * Status: works
29  *
30  * Supports:
31  *  - analog input
32  *  - analog output
33  *  - digital input
34  *  - digital output
35  *  - counter
36  *  - pwm
37  */
38
39 #include <linux/kernel.h>
40 #include <linux/module.h>
41 #include <linux/mutex.h>
42 #include <linux/errno.h>
43 #include <linux/input.h>
44 #include <linux/slab.h>
45 #include <linux/poll.h>
46 #include <linux/uaccess.h>
47
48 #include "../comedi_usb.h"
49
50 enum {
51         DEVICE_VMK8055,
52         DEVICE_VMK8061
53 };
54
55 #define VMK8055_DI_REG          0x00
56 #define VMK8055_DO_REG          0x01
57 #define VMK8055_AO1_REG         0x02
58 #define VMK8055_AO2_REG         0x03
59 #define VMK8055_AI1_REG         0x02
60 #define VMK8055_AI2_REG         0x03
61 #define VMK8055_CNT1_REG        0x04
62 #define VMK8055_CNT2_REG        0x06
63
64 #define VMK8061_CH_REG          0x01
65 #define VMK8061_DI_REG          0x01
66 #define VMK8061_DO_REG          0x01
67 #define VMK8061_PWM_REG1        0x01
68 #define VMK8061_PWM_REG2        0x02
69 #define VMK8061_CNT_REG         0x02
70 #define VMK8061_AO_REG          0x02
71 #define VMK8061_AI_REG1         0x02
72 #define VMK8061_AI_REG2         0x03
73
74 #define VMK8055_CMD_RST         0x00
75 #define VMK8055_CMD_DEB1_TIME   0x01
76 #define VMK8055_CMD_DEB2_TIME   0x02
77 #define VMK8055_CMD_RST_CNT1    0x03
78 #define VMK8055_CMD_RST_CNT2    0x04
79 #define VMK8055_CMD_WRT_AD      0x05
80
81 #define VMK8061_CMD_RD_AI       0x00
82 #define VMK8061_CMR_RD_ALL_AI   0x01    /* !non-active! */
83 #define VMK8061_CMD_SET_AO      0x02
84 #define VMK8061_CMD_SET_ALL_AO  0x03    /* !non-active! */
85 #define VMK8061_CMD_OUT_PWM     0x04
86 #define VMK8061_CMD_RD_DI       0x05
87 #define VMK8061_CMD_DO          0x06    /* !non-active! */
88 #define VMK8061_CMD_CLR_DO      0x07
89 #define VMK8061_CMD_SET_DO      0x08
90 #define VMK8061_CMD_RD_CNT      0x09    /* TODO: completely pointless? */
91 #define VMK8061_CMD_RST_CNT     0x0a    /* TODO: completely pointless? */
92 #define VMK8061_CMD_RD_VERSION  0x0b    /* internal usage */
93 #define VMK8061_CMD_RD_JMP_STAT 0x0c    /* TODO: not implemented yet */
94 #define VMK8061_CMD_RD_PWR_STAT 0x0d    /* internal usage */
95 #define VMK8061_CMD_RD_DO       0x0e
96 #define VMK8061_CMD_RD_AO       0x0f
97 #define VMK8061_CMD_RD_PWM      0x10
98
99 #define IC3_VERSION             BIT(0)
100 #define IC6_VERSION             BIT(1)
101
102 #define MIN_BUF_SIZE            64
103 #define PACKET_TIMEOUT          10000   /* ms */
104
105 enum vmk80xx_model {
106         VMK8055_MODEL,
107         VMK8061_MODEL
108 };
109
110 static const struct comedi_lrange vmk8061_range = {
111         2, {
112                 UNI_RANGE(5),
113                 UNI_RANGE(10)
114         }
115 };
116
117 struct vmk80xx_board {
118         const char *name;
119         enum vmk80xx_model model;
120         const struct comedi_lrange *range;
121         int ai_nchans;
122         unsigned int ai_maxdata;
123         int ao_nchans;
124         int di_nchans;
125         unsigned int cnt_maxdata;
126         int pwm_nchans;
127         unsigned int pwm_maxdata;
128 };
129
130 static const struct vmk80xx_board vmk80xx_boardinfo[] = {
131         [DEVICE_VMK8055] = {
132                 .name           = "K8055 (VM110)",
133                 .model          = VMK8055_MODEL,
134                 .range          = &range_unipolar5,
135                 .ai_nchans      = 2,
136                 .ai_maxdata     = 0x00ff,
137                 .ao_nchans      = 2,
138                 .di_nchans      = 6,
139                 .cnt_maxdata    = 0xffff,
140         },
141         [DEVICE_VMK8061] = {
142                 .name           = "K8061 (VM140)",
143                 .model          = VMK8061_MODEL,
144                 .range          = &vmk8061_range,
145                 .ai_nchans      = 8,
146                 .ai_maxdata     = 0x03ff,
147                 .ao_nchans      = 8,
148                 .di_nchans      = 8,
149                 .cnt_maxdata    = 0,    /* unknown, device is not writeable */
150                 .pwm_nchans     = 1,
151                 .pwm_maxdata    = 0x03ff,
152         },
153 };
154
155 struct vmk80xx_private {
156         struct usb_endpoint_descriptor *ep_rx;
157         struct usb_endpoint_descriptor *ep_tx;
158         struct semaphore limit_sem;
159         unsigned char *usb_rx_buf;
160         unsigned char *usb_tx_buf;
161         enum vmk80xx_model model;
162 };
163
164 static void vmk80xx_do_bulk_msg(struct comedi_device *dev)
165 {
166         struct vmk80xx_private *devpriv = dev->private;
167         struct usb_device *usb = comedi_to_usb_dev(dev);
168         __u8 tx_addr;
169         __u8 rx_addr;
170         unsigned int tx_pipe;
171         unsigned int rx_pipe;
172         size_t tx_size;
173         size_t rx_size;
174
175         tx_addr = devpriv->ep_tx->bEndpointAddress;
176         rx_addr = devpriv->ep_rx->bEndpointAddress;
177         tx_pipe = usb_sndbulkpipe(usb, tx_addr);
178         rx_pipe = usb_rcvbulkpipe(usb, rx_addr);
179         tx_size = usb_endpoint_maxp(devpriv->ep_tx);
180         rx_size = usb_endpoint_maxp(devpriv->ep_rx);
181
182         usb_bulk_msg(usb, tx_pipe, devpriv->usb_tx_buf, tx_size, NULL,
183                      PACKET_TIMEOUT);
184
185         usb_bulk_msg(usb, rx_pipe, devpriv->usb_rx_buf, rx_size, NULL,
186                      PACKET_TIMEOUT);
187 }
188
189 static int vmk80xx_read_packet(struct comedi_device *dev)
190 {
191         struct vmk80xx_private *devpriv = dev->private;
192         struct usb_device *usb = comedi_to_usb_dev(dev);
193         struct usb_endpoint_descriptor *ep;
194         unsigned int pipe;
195
196         if (devpriv->model == VMK8061_MODEL) {
197                 vmk80xx_do_bulk_msg(dev);
198                 return 0;
199         }
200
201         ep = devpriv->ep_rx;
202         pipe = usb_rcvintpipe(usb, ep->bEndpointAddress);
203         return usb_interrupt_msg(usb, pipe, devpriv->usb_rx_buf,
204                                  usb_endpoint_maxp(ep), NULL,
205                                  PACKET_TIMEOUT);
206 }
207
208 static int vmk80xx_write_packet(struct comedi_device *dev, int cmd)
209 {
210         struct vmk80xx_private *devpriv = dev->private;
211         struct usb_device *usb = comedi_to_usb_dev(dev);
212         struct usb_endpoint_descriptor *ep;
213         unsigned int pipe;
214
215         devpriv->usb_tx_buf[0] = cmd;
216
217         if (devpriv->model == VMK8061_MODEL) {
218                 vmk80xx_do_bulk_msg(dev);
219                 return 0;
220         }
221
222         ep = devpriv->ep_tx;
223         pipe = usb_sndintpipe(usb, ep->bEndpointAddress);
224         return usb_interrupt_msg(usb, pipe, devpriv->usb_tx_buf,
225                                  usb_endpoint_maxp(ep), NULL,
226                                  PACKET_TIMEOUT);
227 }
228
229 static int vmk80xx_reset_device(struct comedi_device *dev)
230 {
231         struct vmk80xx_private *devpriv = dev->private;
232         size_t size;
233         int retval;
234
235         size = usb_endpoint_maxp(devpriv->ep_tx);
236         memset(devpriv->usb_tx_buf, 0, size);
237         retval = vmk80xx_write_packet(dev, VMK8055_CMD_RST);
238         if (retval)
239                 return retval;
240         /* set outputs to known state as we cannot read them */
241         return vmk80xx_write_packet(dev, VMK8055_CMD_WRT_AD);
242 }
243
244 static int vmk80xx_ai_insn_read(struct comedi_device *dev,
245                                 struct comedi_subdevice *s,
246                                 struct comedi_insn *insn,
247                                 unsigned int *data)
248 {
249         struct vmk80xx_private *devpriv = dev->private;
250         int chan;
251         int reg[2];
252         int n;
253
254         down(&devpriv->limit_sem);
255         chan = CR_CHAN(insn->chanspec);
256
257         switch (devpriv->model) {
258         case VMK8055_MODEL:
259                 if (!chan)
260                         reg[0] = VMK8055_AI1_REG;
261                 else
262                         reg[0] = VMK8055_AI2_REG;
263                 break;
264         case VMK8061_MODEL:
265         default:
266                 reg[0] = VMK8061_AI_REG1;
267                 reg[1] = VMK8061_AI_REG2;
268                 devpriv->usb_tx_buf[0] = VMK8061_CMD_RD_AI;
269                 devpriv->usb_tx_buf[VMK8061_CH_REG] = chan;
270                 break;
271         }
272
273         for (n = 0; n < insn->n; n++) {
274                 if (vmk80xx_read_packet(dev))
275                         break;
276
277                 if (devpriv->model == VMK8055_MODEL) {
278                         data[n] = devpriv->usb_rx_buf[reg[0]];
279                         continue;
280                 }
281
282                 /* VMK8061_MODEL */
283                 data[n] = devpriv->usb_rx_buf[reg[0]] + 256 *
284                     devpriv->usb_rx_buf[reg[1]];
285         }
286
287         up(&devpriv->limit_sem);
288
289         return n;
290 }
291
292 static int vmk80xx_ao_insn_write(struct comedi_device *dev,
293                                  struct comedi_subdevice *s,
294                                  struct comedi_insn *insn,
295                                  unsigned int *data)
296 {
297         struct vmk80xx_private *devpriv = dev->private;
298         int chan;
299         int cmd;
300         int reg;
301         int n;
302
303         down(&devpriv->limit_sem);
304         chan = CR_CHAN(insn->chanspec);
305
306         switch (devpriv->model) {
307         case VMK8055_MODEL:
308                 cmd = VMK8055_CMD_WRT_AD;
309                 if (!chan)
310                         reg = VMK8055_AO1_REG;
311                 else
312                         reg = VMK8055_AO2_REG;
313                 break;
314         default:                /* NOTE: avoid compiler warnings */
315                 cmd = VMK8061_CMD_SET_AO;
316                 reg = VMK8061_AO_REG;
317                 devpriv->usb_tx_buf[VMK8061_CH_REG] = chan;
318                 break;
319         }
320
321         for (n = 0; n < insn->n; n++) {
322                 devpriv->usb_tx_buf[reg] = data[n];
323
324                 if (vmk80xx_write_packet(dev, cmd))
325                         break;
326         }
327
328         up(&devpriv->limit_sem);
329
330         return n;
331 }
332
333 static int vmk80xx_ao_insn_read(struct comedi_device *dev,
334                                 struct comedi_subdevice *s,
335                                 struct comedi_insn *insn,
336                                 unsigned int *data)
337 {
338         struct vmk80xx_private *devpriv = dev->private;
339         int chan;
340         int reg;
341         int n;
342
343         down(&devpriv->limit_sem);
344         chan = CR_CHAN(insn->chanspec);
345
346         reg = VMK8061_AO_REG - 1;
347
348         devpriv->usb_tx_buf[0] = VMK8061_CMD_RD_AO;
349
350         for (n = 0; n < insn->n; n++) {
351                 if (vmk80xx_read_packet(dev))
352                         break;
353
354                 data[n] = devpriv->usb_rx_buf[reg + chan];
355         }
356
357         up(&devpriv->limit_sem);
358
359         return n;
360 }
361
362 static int vmk80xx_di_insn_bits(struct comedi_device *dev,
363                                 struct comedi_subdevice *s,
364                                 struct comedi_insn *insn,
365                                 unsigned int *data)
366 {
367         struct vmk80xx_private *devpriv = dev->private;
368         unsigned char *rx_buf;
369         int reg;
370         int retval;
371
372         down(&devpriv->limit_sem);
373
374         rx_buf = devpriv->usb_rx_buf;
375
376         if (devpriv->model == VMK8061_MODEL) {
377                 reg = VMK8061_DI_REG;
378                 devpriv->usb_tx_buf[0] = VMK8061_CMD_RD_DI;
379         } else {
380                 reg = VMK8055_DI_REG;
381         }
382
383         retval = vmk80xx_read_packet(dev);
384
385         if (!retval) {
386                 if (devpriv->model == VMK8055_MODEL)
387                         data[1] = (((rx_buf[reg] >> 4) & 0x03) |
388                                   ((rx_buf[reg] << 2) & 0x04) |
389                                   ((rx_buf[reg] >> 3) & 0x18));
390                 else
391                         data[1] = rx_buf[reg];
392
393                 retval = 2;
394         }
395
396         up(&devpriv->limit_sem);
397
398         return retval;
399 }
400
401 static int vmk80xx_do_insn_bits(struct comedi_device *dev,
402                                 struct comedi_subdevice *s,
403                                 struct comedi_insn *insn,
404                                 unsigned int *data)
405 {
406         struct vmk80xx_private *devpriv = dev->private;
407         unsigned char *rx_buf = devpriv->usb_rx_buf;
408         unsigned char *tx_buf = devpriv->usb_tx_buf;
409         int reg, cmd;
410         int ret = 0;
411
412         if (devpriv->model == VMK8061_MODEL) {
413                 reg = VMK8061_DO_REG;
414                 cmd = VMK8061_CMD_DO;
415         } else { /* VMK8055_MODEL */
416                 reg = VMK8055_DO_REG;
417                 cmd = VMK8055_CMD_WRT_AD;
418         }
419
420         down(&devpriv->limit_sem);
421
422         if (comedi_dio_update_state(s, data)) {
423                 tx_buf[reg] = s->state;
424                 ret = vmk80xx_write_packet(dev, cmd);
425                 if (ret)
426                         goto out;
427         }
428
429         if (devpriv->model == VMK8061_MODEL) {
430                 tx_buf[0] = VMK8061_CMD_RD_DO;
431                 ret = vmk80xx_read_packet(dev);
432                 if (ret)
433                         goto out;
434                 data[1] = rx_buf[reg];
435         } else {
436                 data[1] = s->state;
437         }
438
439 out:
440         up(&devpriv->limit_sem);
441
442         return ret ? ret : insn->n;
443 }
444
445 static int vmk80xx_cnt_insn_read(struct comedi_device *dev,
446                                  struct comedi_subdevice *s,
447                                  struct comedi_insn *insn,
448                                  unsigned int *data)
449 {
450         struct vmk80xx_private *devpriv = dev->private;
451         int chan;
452         int reg[2];
453         int n;
454
455         down(&devpriv->limit_sem);
456         chan = CR_CHAN(insn->chanspec);
457
458         switch (devpriv->model) {
459         case VMK8055_MODEL:
460                 if (!chan)
461                         reg[0] = VMK8055_CNT1_REG;
462                 else
463                         reg[0] = VMK8055_CNT2_REG;
464                 break;
465         case VMK8061_MODEL:
466         default:
467                 reg[0] = VMK8061_CNT_REG;
468                 reg[1] = VMK8061_CNT_REG;
469                 devpriv->usb_tx_buf[0] = VMK8061_CMD_RD_CNT;
470                 break;
471         }
472
473         for (n = 0; n < insn->n; n++) {
474                 if (vmk80xx_read_packet(dev))
475                         break;
476
477                 if (devpriv->model == VMK8055_MODEL)
478                         data[n] = devpriv->usb_rx_buf[reg[0]];
479                 else /* VMK8061_MODEL */
480                         data[n] = devpriv->usb_rx_buf[reg[0] * (chan + 1) + 1]
481                             + 256 * devpriv->usb_rx_buf[reg[1] * 2 + 2];
482         }
483
484         up(&devpriv->limit_sem);
485
486         return n;
487 }
488
489 static int vmk80xx_cnt_insn_config(struct comedi_device *dev,
490                                    struct comedi_subdevice *s,
491                                    struct comedi_insn *insn,
492                                    unsigned int *data)
493 {
494         struct vmk80xx_private *devpriv = dev->private;
495         unsigned int chan = CR_CHAN(insn->chanspec);
496         int cmd;
497         int reg;
498         int ret;
499
500         down(&devpriv->limit_sem);
501         switch (data[0]) {
502         case INSN_CONFIG_RESET:
503                 if (devpriv->model == VMK8055_MODEL) {
504                         if (!chan) {
505                                 cmd = VMK8055_CMD_RST_CNT1;
506                                 reg = VMK8055_CNT1_REG;
507                         } else {
508                                 cmd = VMK8055_CMD_RST_CNT2;
509                                 reg = VMK8055_CNT2_REG;
510                         }
511                         devpriv->usb_tx_buf[reg] = 0x00;
512                 } else {
513                         cmd = VMK8061_CMD_RST_CNT;
514                 }
515                 ret = vmk80xx_write_packet(dev, cmd);
516                 break;
517         default:
518                 ret = -EINVAL;
519                 break;
520         }
521         up(&devpriv->limit_sem);
522
523         return ret ? ret : insn->n;
524 }
525
526 static int vmk80xx_cnt_insn_write(struct comedi_device *dev,
527                                   struct comedi_subdevice *s,
528                                   struct comedi_insn *insn,
529                                   unsigned int *data)
530 {
531         struct vmk80xx_private *devpriv = dev->private;
532         unsigned long debtime;
533         unsigned long val;
534         int chan;
535         int cmd;
536         int n;
537
538         down(&devpriv->limit_sem);
539         chan = CR_CHAN(insn->chanspec);
540
541         if (!chan)
542                 cmd = VMK8055_CMD_DEB1_TIME;
543         else
544                 cmd = VMK8055_CMD_DEB2_TIME;
545
546         for (n = 0; n < insn->n; n++) {
547                 debtime = data[n];
548                 if (debtime == 0)
549                         debtime = 1;
550
551                 /* TODO: Prevent overflows */
552                 if (debtime > 7450)
553                         debtime = 7450;
554
555                 val = int_sqrt(debtime * 1000 / 115);
556                 if (((val + 1) * val) < debtime * 1000 / 115)
557                         val += 1;
558
559                 devpriv->usb_tx_buf[6 + chan] = val;
560
561                 if (vmk80xx_write_packet(dev, cmd))
562                         break;
563         }
564
565         up(&devpriv->limit_sem);
566
567         return n;
568 }
569
570 static int vmk80xx_pwm_insn_read(struct comedi_device *dev,
571                                  struct comedi_subdevice *s,
572                                  struct comedi_insn *insn,
573                                  unsigned int *data)
574 {
575         struct vmk80xx_private *devpriv = dev->private;
576         unsigned char *tx_buf;
577         unsigned char *rx_buf;
578         int reg[2];
579         int n;
580
581         down(&devpriv->limit_sem);
582
583         tx_buf = devpriv->usb_tx_buf;
584         rx_buf = devpriv->usb_rx_buf;
585
586         reg[0] = VMK8061_PWM_REG1;
587         reg[1] = VMK8061_PWM_REG2;
588
589         tx_buf[0] = VMK8061_CMD_RD_PWM;
590
591         for (n = 0; n < insn->n; n++) {
592                 if (vmk80xx_read_packet(dev))
593                         break;
594
595                 data[n] = rx_buf[reg[0]] + 4 * rx_buf[reg[1]];
596         }
597
598         up(&devpriv->limit_sem);
599
600         return n;
601 }
602
603 static int vmk80xx_pwm_insn_write(struct comedi_device *dev,
604                                   struct comedi_subdevice *s,
605                                   struct comedi_insn *insn,
606                                   unsigned int *data)
607 {
608         struct vmk80xx_private *devpriv = dev->private;
609         unsigned char *tx_buf;
610         int reg[2];
611         int cmd;
612         int n;
613
614         down(&devpriv->limit_sem);
615
616         tx_buf = devpriv->usb_tx_buf;
617
618         reg[0] = VMK8061_PWM_REG1;
619         reg[1] = VMK8061_PWM_REG2;
620
621         cmd = VMK8061_CMD_OUT_PWM;
622
623         /*
624          * The followin piece of code was translated from the inline
625          * assembler code in the DLL source code.
626          *
627          * asm
628          *   mov eax, k  ; k is the value (data[n])
629          *   and al, 03h ; al are the lower 8 bits of eax
630          *   mov lo, al  ; lo is the low part (tx_buf[reg[0]])
631          *   mov eax, k
632          *   shr eax, 2  ; right shift eax register by 2
633          *   mov hi, al  ; hi is the high part (tx_buf[reg[1]])
634          * end;
635          */
636         for (n = 0; n < insn->n; n++) {
637                 tx_buf[reg[0]] = (unsigned char)(data[n] & 0x03);
638                 tx_buf[reg[1]] = (unsigned char)(data[n] >> 2) & 0xff;
639
640                 if (vmk80xx_write_packet(dev, cmd))
641                         break;
642         }
643
644         up(&devpriv->limit_sem);
645
646         return n;
647 }
648
649 static int vmk80xx_find_usb_endpoints(struct comedi_device *dev)
650 {
651         struct vmk80xx_private *devpriv = dev->private;
652         struct usb_interface *intf = comedi_to_usb_interface(dev);
653         struct usb_host_interface *iface_desc = intf->cur_altsetting;
654         struct usb_endpoint_descriptor *ep_desc;
655         int i;
656
657         if (iface_desc->desc.bNumEndpoints != 2)
658                 return -ENODEV;
659
660         for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) {
661                 ep_desc = &iface_desc->endpoint[i].desc;
662
663                 if (usb_endpoint_is_int_in(ep_desc) ||
664                     usb_endpoint_is_bulk_in(ep_desc)) {
665                         if (!devpriv->ep_rx)
666                                 devpriv->ep_rx = ep_desc;
667                         continue;
668                 }
669
670                 if (usb_endpoint_is_int_out(ep_desc) ||
671                     usb_endpoint_is_bulk_out(ep_desc)) {
672                         if (!devpriv->ep_tx)
673                                 devpriv->ep_tx = ep_desc;
674                         continue;
675                 }
676         }
677
678         if (!devpriv->ep_rx || !devpriv->ep_tx)
679                 return -ENODEV;
680
681         if (!usb_endpoint_maxp(devpriv->ep_rx) || !usb_endpoint_maxp(devpriv->ep_tx))
682                 return -EINVAL;
683
684         return 0;
685 }
686
687 static int vmk80xx_alloc_usb_buffers(struct comedi_device *dev)
688 {
689         struct vmk80xx_private *devpriv = dev->private;
690         size_t size;
691
692         size = max(usb_endpoint_maxp(devpriv->ep_rx), MIN_BUF_SIZE);
693         devpriv->usb_rx_buf = kzalloc(size, GFP_KERNEL);
694         if (!devpriv->usb_rx_buf)
695                 return -ENOMEM;
696
697         size = max(usb_endpoint_maxp(devpriv->ep_tx), MIN_BUF_SIZE);
698         devpriv->usb_tx_buf = kzalloc(size, GFP_KERNEL);
699         if (!devpriv->usb_tx_buf)
700                 return -ENOMEM;
701
702         return 0;
703 }
704
705 static int vmk80xx_init_subdevices(struct comedi_device *dev)
706 {
707         const struct vmk80xx_board *board = dev->board_ptr;
708         struct vmk80xx_private *devpriv = dev->private;
709         struct comedi_subdevice *s;
710         int n_subd;
711         int ret;
712
713         down(&devpriv->limit_sem);
714
715         if (devpriv->model == VMK8055_MODEL)
716                 n_subd = 5;
717         else
718                 n_subd = 6;
719         ret = comedi_alloc_subdevices(dev, n_subd);
720         if (ret) {
721                 up(&devpriv->limit_sem);
722                 return ret;
723         }
724
725         /* Analog input subdevice */
726         s = &dev->subdevices[0];
727         s->type         = COMEDI_SUBD_AI;
728         s->subdev_flags = SDF_READABLE | SDF_GROUND;
729         s->n_chan       = board->ai_nchans;
730         s->maxdata      = board->ai_maxdata;
731         s->range_table  = board->range;
732         s->insn_read    = vmk80xx_ai_insn_read;
733
734         /* Analog output subdevice */
735         s = &dev->subdevices[1];
736         s->type         = COMEDI_SUBD_AO;
737         s->subdev_flags = SDF_WRITABLE | SDF_GROUND;
738         s->n_chan       = board->ao_nchans;
739         s->maxdata      = 0x00ff;
740         s->range_table  = board->range;
741         s->insn_write   = vmk80xx_ao_insn_write;
742         if (devpriv->model == VMK8061_MODEL) {
743                 s->subdev_flags |= SDF_READABLE;
744                 s->insn_read    = vmk80xx_ao_insn_read;
745         }
746
747         /* Digital input subdevice */
748         s = &dev->subdevices[2];
749         s->type         = COMEDI_SUBD_DI;
750         s->subdev_flags = SDF_READABLE;
751         s->n_chan       = board->di_nchans;
752         s->maxdata      = 1;
753         s->range_table  = &range_digital;
754         s->insn_bits    = vmk80xx_di_insn_bits;
755
756         /* Digital output subdevice */
757         s = &dev->subdevices[3];
758         s->type         = COMEDI_SUBD_DO;
759         s->subdev_flags = SDF_WRITABLE;
760         s->n_chan       = 8;
761         s->maxdata      = 1;
762         s->range_table  = &range_digital;
763         s->insn_bits    = vmk80xx_do_insn_bits;
764
765         /* Counter subdevice */
766         s = &dev->subdevices[4];
767         s->type         = COMEDI_SUBD_COUNTER;
768         s->subdev_flags = SDF_READABLE;
769         s->n_chan       = 2;
770         s->maxdata      = board->cnt_maxdata;
771         s->insn_read    = vmk80xx_cnt_insn_read;
772         s->insn_config  = vmk80xx_cnt_insn_config;
773         if (devpriv->model == VMK8055_MODEL) {
774                 s->subdev_flags |= SDF_WRITABLE;
775                 s->insn_write   = vmk80xx_cnt_insn_write;
776         }
777
778         /* PWM subdevice */
779         if (devpriv->model == VMK8061_MODEL) {
780                 s = &dev->subdevices[5];
781                 s->type         = COMEDI_SUBD_PWM;
782                 s->subdev_flags = SDF_READABLE | SDF_WRITABLE;
783                 s->n_chan       = board->pwm_nchans;
784                 s->maxdata      = board->pwm_maxdata;
785                 s->insn_read    = vmk80xx_pwm_insn_read;
786                 s->insn_write   = vmk80xx_pwm_insn_write;
787         }
788
789         up(&devpriv->limit_sem);
790
791         return 0;
792 }
793
794 static int vmk80xx_auto_attach(struct comedi_device *dev,
795                                unsigned long context)
796 {
797         struct usb_interface *intf = comedi_to_usb_interface(dev);
798         const struct vmk80xx_board *board = NULL;
799         struct vmk80xx_private *devpriv;
800         int ret;
801
802         if (context < ARRAY_SIZE(vmk80xx_boardinfo))
803                 board = &vmk80xx_boardinfo[context];
804         if (!board)
805                 return -ENODEV;
806         dev->board_ptr = board;
807         dev->board_name = board->name;
808
809         devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
810         if (!devpriv)
811                 return -ENOMEM;
812
813         devpriv->model = board->model;
814
815         sema_init(&devpriv->limit_sem, 8);
816
817         ret = vmk80xx_find_usb_endpoints(dev);
818         if (ret)
819                 return ret;
820
821         ret = vmk80xx_alloc_usb_buffers(dev);
822         if (ret)
823                 return ret;
824
825         usb_set_intfdata(intf, devpriv);
826
827         if (devpriv->model == VMK8055_MODEL)
828                 vmk80xx_reset_device(dev);
829
830         return vmk80xx_init_subdevices(dev);
831 }
832
833 static void vmk80xx_detach(struct comedi_device *dev)
834 {
835         struct usb_interface *intf = comedi_to_usb_interface(dev);
836         struct vmk80xx_private *devpriv = dev->private;
837
838         if (!devpriv)
839                 return;
840
841         down(&devpriv->limit_sem);
842
843         usb_set_intfdata(intf, NULL);
844
845         kfree(devpriv->usb_rx_buf);
846         kfree(devpriv->usb_tx_buf);
847
848         up(&devpriv->limit_sem);
849 }
850
851 static struct comedi_driver vmk80xx_driver = {
852         .module         = THIS_MODULE,
853         .driver_name    = "vmk80xx",
854         .auto_attach    = vmk80xx_auto_attach,
855         .detach         = vmk80xx_detach,
856 };
857
858 static int vmk80xx_usb_probe(struct usb_interface *intf,
859                              const struct usb_device_id *id)
860 {
861         return comedi_usb_auto_config(intf, &vmk80xx_driver, id->driver_info);
862 }
863
864 static const struct usb_device_id vmk80xx_usb_id_table[] = {
865         { USB_DEVICE(0x10cf, 0x5500), .driver_info = DEVICE_VMK8055 },
866         { USB_DEVICE(0x10cf, 0x5501), .driver_info = DEVICE_VMK8055 },
867         { USB_DEVICE(0x10cf, 0x5502), .driver_info = DEVICE_VMK8055 },
868         { USB_DEVICE(0x10cf, 0x5503), .driver_info = DEVICE_VMK8055 },
869         { USB_DEVICE(0x10cf, 0x8061), .driver_info = DEVICE_VMK8061 },
870         { USB_DEVICE(0x10cf, 0x8062), .driver_info = DEVICE_VMK8061 },
871         { USB_DEVICE(0x10cf, 0x8063), .driver_info = DEVICE_VMK8061 },
872         { USB_DEVICE(0x10cf, 0x8064), .driver_info = DEVICE_VMK8061 },
873         { USB_DEVICE(0x10cf, 0x8065), .driver_info = DEVICE_VMK8061 },
874         { USB_DEVICE(0x10cf, 0x8066), .driver_info = DEVICE_VMK8061 },
875         { USB_DEVICE(0x10cf, 0x8067), .driver_info = DEVICE_VMK8061 },
876         { USB_DEVICE(0x10cf, 0x8068), .driver_info = DEVICE_VMK8061 },
877         { }
878 };
879 MODULE_DEVICE_TABLE(usb, vmk80xx_usb_id_table);
880
881 static struct usb_driver vmk80xx_usb_driver = {
882         .name           = "vmk80xx",
883         .id_table       = vmk80xx_usb_id_table,
884         .probe          = vmk80xx_usb_probe,
885         .disconnect     = comedi_usb_auto_unconfig,
886 };
887 module_comedi_usb_driver(vmk80xx_driver, vmk80xx_usb_driver);
888
889 MODULE_AUTHOR("Manuel Gebele <forensixs@gmx.de>");
890 MODULE_DESCRIPTION("Velleman USB Board Low-Level Driver");
891 MODULE_SUPPORTED_DEVICE("K8055/K8061 aka VM110/VM140");
892 MODULE_LICENSE("GPL");