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