2 comedi/drivers/vmk80xx.c
3 Velleman USB Board Low-Level Driver
5 Copyright (C) 2009 Manuel Gebele <forensixs@gmx.de>, Germany
7 COMEDI - Linux Control and Measurement Device Interface
8 Copyright (C) 2000 David A. Schleef <ds@schleef.org>
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.
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.
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.
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
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
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
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>
65 #include "../comedidev.h"
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
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
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
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
116 #define VMK80XX_MAX_BOARDS COMEDI_NUM_BOARD_MINORS
118 #define TRANS_OUT_BUSY 1
119 #define TRANS_IN_BUSY 2
120 #define TRANS_IN_RUNNING 3
122 #define IC3_VERSION (1 << 0)
123 #define IC6_VERSION (1 << 1)
125 #define URB_RCV_FLAG (1 << 0)
126 #define URB_SND_FLAG (1 << 1)
128 #ifdef CONFIG_COMEDI_DEBUG
129 static int dbgcm = 1;
134 #define dbgcm(fmt, arg...) \
137 printk(KERN_DEBUG fmt, ##arg); \
145 struct firmware_version {
146 unsigned char ic3_vers[32]; /* USB-Controller */
147 unsigned char ic6_vers[32]; /* CPU */
150 static const struct comedi_lrange vmk8055_range = {
154 static const struct comedi_lrange vmk8061_range = {
155 2, {UNI_RANGE(5), UNI_RANGE(10)}
158 struct vmk80xx_board {
160 enum vmk80xx_model model;
161 const struct comedi_lrange *range;
176 static const struct vmk80xx_board vmk80xx_boardinfo[] = {
178 .name = "K8055 (VM110)",
179 .model = VMK8055_MODEL,
180 .range = &vmk8055_range,
195 .name = "K8061 (VM140)",
196 .model = VMK8061_MODEL,
197 .range = &vmk8061_range,
223 struct usb_device *udev;
224 struct usb_interface *intf;
225 struct usb_endpoint_descriptor *ep_rx;
226 struct usb_endpoint_descriptor *ep_tx;
227 struct usb_anchor rx_anchor;
228 struct usb_anchor tx_anchor;
229 const struct vmk80xx_board *board;
230 struct firmware_version fw;
231 struct semaphore limit_sem;
232 wait_queue_head_t read_wait;
233 wait_queue_head_t write_wait;
234 unsigned char *usb_rx_buf;
235 unsigned char *usb_tx_buf;
242 static struct vmk80xx_usb vmb[VMK80XX_MAX_BOARDS];
244 static DEFINE_MUTEX(glb_mutex);
246 static void vmk80xx_tx_callback(struct urb *urb)
248 struct vmk80xx_usb *dev = urb->context;
249 int stat = urb->status;
251 if (stat && !(stat == -ENOENT
252 || stat == -ECONNRESET || stat == -ESHUTDOWN))
253 dbgcm("comedi#: vmk80xx: %s - nonzero urb status (%d)\n",
256 if (!test_bit(TRANS_OUT_BUSY, &dev->flags))
259 clear_bit(TRANS_OUT_BUSY, &dev->flags);
261 wake_up_interruptible(&dev->write_wait);
264 static void vmk80xx_rx_callback(struct urb *urb)
266 struct vmk80xx_usb *dev = urb->context;
267 int stat = urb->status;
277 dbgcm("comedi#: vmk80xx: %s - nonzero urb status (%d)\n",
284 if (test_bit(TRANS_IN_RUNNING, &dev->flags) && dev->intf) {
285 usb_anchor_urb(urb, &dev->rx_anchor);
287 if (!usb_submit_urb(urb, GFP_KERNEL))
290 dev_err(&urb->dev->dev,
291 "comedi#: vmk80xx: %s - submit urb failed\n",
294 usb_unanchor_urb(urb);
297 clear_bit(TRANS_IN_BUSY, &dev->flags);
299 wake_up_interruptible(&dev->read_wait);
302 static int vmk80xx_check_data_link(struct vmk80xx_usb *dev)
304 unsigned int tx_pipe;
305 unsigned int rx_pipe;
309 tx_pipe = usb_sndbulkpipe(dev->udev, 0x01);
310 rx_pipe = usb_rcvbulkpipe(dev->udev, 0x81);
312 tx[0] = VMK8061_CMD_RD_PWR_STAT;
315 * Check that IC6 (PIC16F871) is powered and
316 * running and the data link between IC3 and
317 * IC6 is working properly
319 usb_bulk_msg(dev->udev, tx_pipe, tx, 1, NULL, dev->ep_tx->bInterval);
320 usb_bulk_msg(dev->udev, rx_pipe, rx, 2, NULL, HZ * 10);
325 static void vmk80xx_read_eeprom(struct vmk80xx_usb *dev, int flag)
327 unsigned int tx_pipe;
328 unsigned int rx_pipe;
330 unsigned char rx[64];
333 tx_pipe = usb_sndbulkpipe(dev->udev, 0x01);
334 rx_pipe = usb_rcvbulkpipe(dev->udev, 0x81);
336 tx[0] = VMK8061_CMD_RD_VERSION;
339 * Read the firmware version info of IC3 and
340 * IC6 from the internal EEPROM of the IC
342 usb_bulk_msg(dev->udev, tx_pipe, tx, 1, NULL, dev->ep_tx->bInterval);
343 usb_bulk_msg(dev->udev, rx_pipe, rx, 64, &cnt, HZ * 10);
347 if (flag & IC3_VERSION)
348 strncpy(dev->fw.ic3_vers, rx + 1, 24);
349 else /* IC6_VERSION */
350 strncpy(dev->fw.ic6_vers, rx + 25, 24);
353 static int vmk80xx_reset_device(struct vmk80xx_usb *dev)
356 unsigned int tx_pipe;
360 urb = usb_alloc_urb(0, GFP_KERNEL);
364 tx_pipe = usb_sndintpipe(dev->udev, 0x01);
366 ival = dev->ep_tx->bInterval;
367 size = le16_to_cpu(dev->ep_tx->wMaxPacketSize);
369 dev->usb_tx_buf[0] = VMK8055_CMD_RST;
370 dev->usb_tx_buf[1] = 0x00;
371 dev->usb_tx_buf[2] = 0x00;
372 dev->usb_tx_buf[3] = 0x00;
373 dev->usb_tx_buf[4] = 0x00;
374 dev->usb_tx_buf[5] = 0x00;
375 dev->usb_tx_buf[6] = 0x00;
376 dev->usb_tx_buf[7] = 0x00;
378 usb_fill_int_urb(urb, dev->udev, tx_pipe, dev->usb_tx_buf,
379 size, vmk80xx_tx_callback, dev, ival);
381 usb_anchor_urb(urb, &dev->tx_anchor);
383 return usb_submit_urb(urb, GFP_KERNEL);
386 static void vmk80xx_build_int_urb(struct urb *urb, int flag)
388 struct vmk80xx_usb *dev = urb->context;
394 void (*callback) (struct urb *);
397 if (flag & URB_RCV_FLAG) {
398 rx_addr = dev->ep_rx->bEndpointAddress;
399 pipe = usb_rcvintpipe(dev->udev, rx_addr);
400 buf = dev->usb_rx_buf;
401 size = le16_to_cpu(dev->ep_rx->wMaxPacketSize);
402 callback = vmk80xx_rx_callback;
403 ival = dev->ep_rx->bInterval;
404 } else { /* URB_SND_FLAG */
405 tx_addr = dev->ep_tx->bEndpointAddress;
406 pipe = usb_sndintpipe(dev->udev, tx_addr);
407 buf = dev->usb_tx_buf;
408 size = le16_to_cpu(dev->ep_tx->wMaxPacketSize);
409 callback = vmk80xx_tx_callback;
410 ival = dev->ep_tx->bInterval;
413 usb_fill_int_urb(urb, dev->udev, pipe, buf, size, callback, dev, ival);
416 static void vmk80xx_do_bulk_msg(struct vmk80xx_usb *dev)
420 unsigned int tx_pipe;
421 unsigned int rx_pipe;
424 set_bit(TRANS_IN_BUSY, &dev->flags);
425 set_bit(TRANS_OUT_BUSY, &dev->flags);
427 tx_addr = dev->ep_tx->bEndpointAddress;
428 rx_addr = dev->ep_rx->bEndpointAddress;
429 tx_pipe = usb_sndbulkpipe(dev->udev, tx_addr);
430 rx_pipe = usb_rcvbulkpipe(dev->udev, rx_addr);
433 * The max packet size attributes of the K8061
434 * input/output endpoints are identical
436 size = le16_to_cpu(dev->ep_tx->wMaxPacketSize);
438 usb_bulk_msg(dev->udev, tx_pipe, dev->usb_tx_buf,
439 size, NULL, dev->ep_tx->bInterval);
440 usb_bulk_msg(dev->udev, rx_pipe, dev->usb_rx_buf, size, NULL, HZ * 10);
442 clear_bit(TRANS_OUT_BUSY, &dev->flags);
443 clear_bit(TRANS_IN_BUSY, &dev->flags);
446 static int vmk80xx_read_packet(struct vmk80xx_usb *dev)
448 const struct vmk80xx_board *boardinfo = dev->board;
455 /* Only useful for interrupt transfers */
456 if (test_bit(TRANS_IN_BUSY, &dev->flags))
457 if (wait_event_interruptible(dev->read_wait,
458 !test_bit(TRANS_IN_BUSY,
462 if (boardinfo->model == VMK8061_MODEL) {
463 vmk80xx_do_bulk_msg(dev);
468 urb = usb_alloc_urb(0, GFP_KERNEL);
473 vmk80xx_build_int_urb(urb, URB_RCV_FLAG);
475 set_bit(TRANS_IN_RUNNING, &dev->flags);
476 set_bit(TRANS_IN_BUSY, &dev->flags);
478 usb_anchor_urb(urb, &dev->rx_anchor);
480 retval = usb_submit_urb(urb, GFP_KERNEL);
484 clear_bit(TRANS_IN_RUNNING, &dev->flags);
485 usb_unanchor_urb(urb);
493 static int vmk80xx_write_packet(struct vmk80xx_usb *dev, int cmd)
495 const struct vmk80xx_board *boardinfo = dev->board;
502 if (test_bit(TRANS_OUT_BUSY, &dev->flags))
503 if (wait_event_interruptible(dev->write_wait,
504 !test_bit(TRANS_OUT_BUSY,
508 if (boardinfo->model == VMK8061_MODEL) {
509 dev->usb_tx_buf[0] = cmd;
510 vmk80xx_do_bulk_msg(dev);
515 urb = usb_alloc_urb(0, GFP_KERNEL);
520 vmk80xx_build_int_urb(urb, URB_SND_FLAG);
522 set_bit(TRANS_OUT_BUSY, &dev->flags);
524 usb_anchor_urb(urb, &dev->tx_anchor);
526 dev->usb_tx_buf[0] = cmd;
528 retval = usb_submit_urb(urb, GFP_KERNEL);
532 clear_bit(TRANS_OUT_BUSY, &dev->flags);
533 usb_unanchor_urb(urb);
544 static int rudimentary_check(struct vmk80xx_usb *dev, int dir)
553 if (test_bit(TRANS_IN_BUSY, &dev->flags))
557 if (test_bit(TRANS_OUT_BUSY, &dev->flags))
564 static int vmk80xx_ai_rinsn(struct comedi_device *cdev,
565 struct comedi_subdevice *s,
566 struct comedi_insn *insn, unsigned int *data)
568 const struct vmk80xx_board *boardinfo = comedi_board(cdev);
569 struct vmk80xx_usb *dev = cdev->private;
574 n = rudimentary_check(dev, DIR_IN);
578 down(&dev->limit_sem);
579 chan = CR_CHAN(insn->chanspec);
581 switch (boardinfo->model) {
584 reg[0] = VMK8055_AI1_REG;
586 reg[0] = VMK8055_AI2_REG;
590 reg[0] = VMK8061_AI_REG1;
591 reg[1] = VMK8061_AI_REG2;
592 dev->usb_tx_buf[0] = VMK8061_CMD_RD_AI;
593 dev->usb_tx_buf[VMK8061_CH_REG] = chan;
597 for (n = 0; n < insn->n; n++) {
598 if (vmk80xx_read_packet(dev))
601 if (boardinfo->model == VMK8055_MODEL) {
602 data[n] = dev->usb_rx_buf[reg[0]];
607 data[n] = dev->usb_rx_buf[reg[0]] + 256 *
608 dev->usb_rx_buf[reg[1]];
616 static int vmk80xx_ao_winsn(struct comedi_device *cdev,
617 struct comedi_subdevice *s,
618 struct comedi_insn *insn, unsigned int *data)
620 const struct vmk80xx_board *boardinfo = comedi_board(cdev);
621 struct vmk80xx_usb *dev = cdev->private;
627 n = rudimentary_check(dev, DIR_OUT);
631 down(&dev->limit_sem);
632 chan = CR_CHAN(insn->chanspec);
634 switch (boardinfo->model) {
636 cmd = VMK8055_CMD_WRT_AD;
638 reg = VMK8055_AO1_REG;
640 reg = VMK8055_AO2_REG;
642 default: /* NOTE: avoid compiler warnings */
643 cmd = VMK8061_CMD_SET_AO;
644 reg = VMK8061_AO_REG;
645 dev->usb_tx_buf[VMK8061_CH_REG] = chan;
649 for (n = 0; n < insn->n; n++) {
650 dev->usb_tx_buf[reg] = data[n];
652 if (vmk80xx_write_packet(dev, cmd))
661 static int vmk80xx_ao_rinsn(struct comedi_device *cdev,
662 struct comedi_subdevice *s,
663 struct comedi_insn *insn, unsigned int *data)
665 struct vmk80xx_usb *dev = cdev->private;
670 n = rudimentary_check(dev, DIR_IN);
674 down(&dev->limit_sem);
675 chan = CR_CHAN(insn->chanspec);
677 reg = VMK8061_AO_REG - 1;
679 dev->usb_tx_buf[0] = VMK8061_CMD_RD_AO;
681 for (n = 0; n < insn->n; n++) {
682 if (vmk80xx_read_packet(dev))
685 data[n] = dev->usb_rx_buf[reg + chan];
693 static int vmk80xx_di_bits(struct comedi_device *cdev,
694 struct comedi_subdevice *s,
695 struct comedi_insn *insn, unsigned int *data)
697 const struct vmk80xx_board *boardinfo = comedi_board(cdev);
698 struct vmk80xx_usb *dev = cdev->private;
699 unsigned char *rx_buf;
703 retval = rudimentary_check(dev, DIR_IN);
707 down(&dev->limit_sem);
709 rx_buf = dev->usb_rx_buf;
711 if (boardinfo->model == VMK8061_MODEL) {
712 reg = VMK8061_DI_REG;
713 dev->usb_tx_buf[0] = VMK8061_CMD_RD_DI;
715 reg = VMK8055_DI_REG;
718 retval = vmk80xx_read_packet(dev);
721 if (boardinfo->model == VMK8055_MODEL)
722 data[1] = (((rx_buf[reg] >> 4) & 0x03) |
723 ((rx_buf[reg] << 2) & 0x04) |
724 ((rx_buf[reg] >> 3) & 0x18));
726 data[1] = rx_buf[reg];
736 static int vmk80xx_di_rinsn(struct comedi_device *cdev,
737 struct comedi_subdevice *s,
738 struct comedi_insn *insn, unsigned int *data)
740 const struct vmk80xx_board *boardinfo = comedi_board(cdev);
741 struct vmk80xx_usb *dev = cdev->private;
743 unsigned char *rx_buf;
748 n = rudimentary_check(dev, DIR_IN);
752 down(&dev->limit_sem);
753 chan = CR_CHAN(insn->chanspec);
755 rx_buf = dev->usb_rx_buf;
757 if (boardinfo->model == VMK8061_MODEL) {
758 reg = VMK8061_DI_REG;
759 dev->usb_tx_buf[0] = VMK8061_CMD_RD_DI;
761 reg = VMK8055_DI_REG;
763 for (n = 0; n < insn->n; n++) {
764 if (vmk80xx_read_packet(dev))
767 if (boardinfo->model == VMK8055_MODEL)
768 inp = (((rx_buf[reg] >> 4) & 0x03) |
769 ((rx_buf[reg] << 2) & 0x04) |
770 ((rx_buf[reg] >> 3) & 0x18));
774 data[n] = (inp >> chan) & 1;
782 static int vmk80xx_do_winsn(struct comedi_device *cdev,
783 struct comedi_subdevice *s,
784 struct comedi_insn *insn, unsigned int *data)
786 const struct vmk80xx_board *boardinfo = comedi_board(cdev);
787 struct vmk80xx_usb *dev = cdev->private;
789 unsigned char *tx_buf;
794 n = rudimentary_check(dev, DIR_OUT);
798 down(&dev->limit_sem);
799 chan = CR_CHAN(insn->chanspec);
801 tx_buf = dev->usb_tx_buf;
803 for (n = 0; n < insn->n; n++) {
804 if (boardinfo->model == VMK8055_MODEL) {
805 reg = VMK8055_DO_REG;
806 cmd = VMK8055_CMD_WRT_AD;
808 tx_buf[reg] |= (1 << chan);
810 tx_buf[reg] ^= (1 << chan);
811 } else { /* VMK8061_MODEL */
812 reg = VMK8061_DO_REG;
814 cmd = VMK8061_CMD_SET_DO;
815 tx_buf[reg] = 1 << chan;
817 cmd = VMK8061_CMD_CLR_DO;
818 tx_buf[reg] = 0xff - (1 << chan);
822 if (vmk80xx_write_packet(dev, cmd))
831 static int vmk80xx_do_rinsn(struct comedi_device *cdev,
832 struct comedi_subdevice *s,
833 struct comedi_insn *insn, unsigned int *data)
835 struct vmk80xx_usb *dev = cdev->private;
840 n = rudimentary_check(dev, DIR_IN);
844 down(&dev->limit_sem);
845 chan = CR_CHAN(insn->chanspec);
847 reg = VMK8061_DO_REG;
849 dev->usb_tx_buf[0] = VMK8061_CMD_RD_DO;
851 for (n = 0; n < insn->n; n++) {
852 if (vmk80xx_read_packet(dev))
855 data[n] = (dev->usb_rx_buf[reg] >> chan) & 1;
863 static int vmk80xx_do_bits(struct comedi_device *cdev,
864 struct comedi_subdevice *s,
865 struct comedi_insn *insn, unsigned int *data)
867 const struct vmk80xx_board *boardinfo = comedi_board(cdev);
868 struct vmk80xx_usb *dev = cdev->private;
869 unsigned char *rx_buf, *tx_buf;
878 if (boardinfo->model == VMK8061_MODEL)
881 retval = rudimentary_check(dev, dir);
885 down(&dev->limit_sem);
887 rx_buf = dev->usb_rx_buf;
888 tx_buf = dev->usb_tx_buf;
891 if (boardinfo->model == VMK8055_MODEL) {
892 reg = VMK8055_DO_REG;
893 cmd = VMK8055_CMD_WRT_AD;
894 } else { /* VMK8061_MODEL */
895 reg = VMK8061_DO_REG;
896 cmd = VMK8061_CMD_DO;
899 tx_buf[reg] &= ~data[0];
900 tx_buf[reg] |= (data[0] & data[1]);
902 retval = vmk80xx_write_packet(dev, cmd);
908 if (boardinfo->model == VMK8061_MODEL) {
909 reg = VMK8061_DO_REG;
910 tx_buf[0] = VMK8061_CMD_RD_DO;
912 retval = vmk80xx_read_packet(dev);
915 data[1] = rx_buf[reg];
919 data[1] = tx_buf[reg];
929 static int vmk80xx_cnt_rinsn(struct comedi_device *cdev,
930 struct comedi_subdevice *s,
931 struct comedi_insn *insn, unsigned int *data)
933 const struct vmk80xx_board *boardinfo = comedi_board(cdev);
934 struct vmk80xx_usb *dev = cdev->private;
939 n = rudimentary_check(dev, DIR_IN);
943 down(&dev->limit_sem);
944 chan = CR_CHAN(insn->chanspec);
946 switch (boardinfo->model) {
949 reg[0] = VMK8055_CNT1_REG;
951 reg[0] = VMK8055_CNT2_REG;
955 reg[0] = VMK8061_CNT_REG;
956 reg[1] = VMK8061_CNT_REG;
957 dev->usb_tx_buf[0] = VMK8061_CMD_RD_CNT;
961 for (n = 0; n < insn->n; n++) {
962 if (vmk80xx_read_packet(dev))
965 if (boardinfo->model == VMK8055_MODEL)
966 data[n] = dev->usb_rx_buf[reg[0]];
967 else /* VMK8061_MODEL */
968 data[n] = dev->usb_rx_buf[reg[0] * (chan + 1) + 1]
969 + 256 * dev->usb_rx_buf[reg[1] * 2 + 2];
977 static int vmk80xx_cnt_cinsn(struct comedi_device *cdev,
978 struct comedi_subdevice *s,
979 struct comedi_insn *insn, unsigned int *data)
981 const struct vmk80xx_board *boardinfo = comedi_board(cdev);
982 struct vmk80xx_usb *dev = cdev->private;
983 unsigned int insn_cmd;
989 n = rudimentary_check(dev, DIR_OUT);
994 if (insn_cmd != INSN_CONFIG_RESET && insn_cmd != GPCT_RESET)
997 down(&dev->limit_sem);
999 chan = CR_CHAN(insn->chanspec);
1001 if (boardinfo->model == VMK8055_MODEL) {
1003 cmd = VMK8055_CMD_RST_CNT1;
1004 reg = VMK8055_CNT1_REG;
1006 cmd = VMK8055_CMD_RST_CNT2;
1007 reg = VMK8055_CNT2_REG;
1010 dev->usb_tx_buf[reg] = 0x00;
1012 cmd = VMK8061_CMD_RST_CNT;
1015 for (n = 0; n < insn->n; n++)
1016 if (vmk80xx_write_packet(dev, cmd))
1019 up(&dev->limit_sem);
1024 static int vmk80xx_cnt_winsn(struct comedi_device *cdev,
1025 struct comedi_subdevice *s,
1026 struct comedi_insn *insn, unsigned int *data)
1028 struct vmk80xx_usb *dev = cdev->private;
1029 unsigned long debtime;
1035 n = rudimentary_check(dev, DIR_OUT);
1039 down(&dev->limit_sem);
1040 chan = CR_CHAN(insn->chanspec);
1043 cmd = VMK8055_CMD_DEB1_TIME;
1045 cmd = VMK8055_CMD_DEB2_TIME;
1047 for (n = 0; n < insn->n; n++) {
1052 /* TODO: Prevent overflows */
1056 val = int_sqrt(debtime * 1000 / 115);
1057 if (((val + 1) * val) < debtime * 1000 / 115)
1060 dev->usb_tx_buf[6 + chan] = val;
1062 if (vmk80xx_write_packet(dev, cmd))
1066 up(&dev->limit_sem);
1071 static int vmk80xx_pwm_rinsn(struct comedi_device *cdev,
1072 struct comedi_subdevice *s,
1073 struct comedi_insn *insn, unsigned int *data)
1075 struct vmk80xx_usb *dev = cdev->private;
1079 n = rudimentary_check(dev, DIR_IN);
1083 down(&dev->limit_sem);
1085 reg[0] = VMK8061_PWM_REG1;
1086 reg[1] = VMK8061_PWM_REG2;
1088 dev->usb_tx_buf[0] = VMK8061_CMD_RD_PWM;
1090 for (n = 0; n < insn->n; n++) {
1091 if (vmk80xx_read_packet(dev))
1094 data[n] = dev->usb_rx_buf[reg[0]] + 4 * dev->usb_rx_buf[reg[1]];
1097 up(&dev->limit_sem);
1102 static int vmk80xx_pwm_winsn(struct comedi_device *cdev,
1103 struct comedi_subdevice *s,
1104 struct comedi_insn *insn, unsigned int *data)
1106 struct vmk80xx_usb *dev = cdev->private;
1107 unsigned char *tx_buf;
1112 n = rudimentary_check(dev, DIR_OUT);
1116 down(&dev->limit_sem);
1118 tx_buf = dev->usb_tx_buf;
1120 reg[0] = VMK8061_PWM_REG1;
1121 reg[1] = VMK8061_PWM_REG2;
1123 cmd = VMK8061_CMD_OUT_PWM;
1126 * The followin piece of code was translated from the inline
1127 * assembler code in the DLL source code.
1130 * mov eax, k ; k is the value (data[n])
1131 * and al, 03h ; al are the lower 8 bits of eax
1132 * mov lo, al ; lo is the low part (tx_buf[reg[0]])
1134 * shr eax, 2 ; right shift eax register by 2
1135 * mov hi, al ; hi is the high part (tx_buf[reg[1]])
1138 for (n = 0; n < insn->n; n++) {
1139 tx_buf[reg[0]] = (unsigned char)(data[n] & 0x03);
1140 tx_buf[reg[1]] = (unsigned char)(data[n] >> 2) & 0xff;
1142 if (vmk80xx_write_packet(dev, cmd))
1146 up(&dev->limit_sem);
1151 static int vmk80xx_attach_common(struct comedi_device *cdev,
1152 struct vmk80xx_usb *dev)
1154 const struct vmk80xx_board *boardinfo;
1156 struct comedi_subdevice *s;
1159 down(&dev->limit_sem);
1161 boardinfo = dev->board;
1162 cdev->board_ptr = boardinfo;
1163 cdev->board_name = boardinfo->name;
1164 cdev->private = dev;
1166 if (boardinfo->model == VMK8055_MODEL)
1170 ret = comedi_alloc_subdevices(cdev, n_subd);
1172 up(&dev->limit_sem);
1176 /* Analog input subdevice */
1177 s = &cdev->subdevices[VMK80XX_SUBD_AI];
1178 s->type = COMEDI_SUBD_AI;
1179 s->subdev_flags = SDF_READABLE | SDF_GROUND;
1180 s->n_chan = boardinfo->ai_chans;
1181 s->maxdata = (1 << boardinfo->ai_bits) - 1;
1182 s->range_table = boardinfo->range;
1183 s->insn_read = vmk80xx_ai_rinsn;
1185 /* Analog output subdevice */
1186 s = &cdev->subdevices[VMK80XX_SUBD_AO];
1187 s->type = COMEDI_SUBD_AO;
1188 s->subdev_flags = SDF_WRITEABLE | SDF_GROUND;
1189 s->n_chan = boardinfo->ao_chans;
1190 s->maxdata = (1 << boardinfo->ao_bits) - 1;
1191 s->range_table = boardinfo->range;
1192 s->insn_write = vmk80xx_ao_winsn;
1193 if (boardinfo->model == VMK8061_MODEL) {
1194 s->subdev_flags |= SDF_READABLE;
1195 s->insn_read = vmk80xx_ao_rinsn;
1198 /* Digital input subdevice */
1199 s = &cdev->subdevices[VMK80XX_SUBD_DI];
1200 s->type = COMEDI_SUBD_DI;
1201 s->subdev_flags = SDF_READABLE | SDF_GROUND;
1202 s->n_chan = boardinfo->di_chans;
1204 s->insn_read = vmk80xx_di_rinsn;
1205 s->insn_bits = vmk80xx_di_bits;
1207 /* Digital output subdevice */
1208 s = &cdev->subdevices[VMK80XX_SUBD_DO];
1209 s->type = COMEDI_SUBD_DO;
1210 s->subdev_flags = SDF_WRITEABLE | SDF_GROUND;
1211 s->n_chan = boardinfo->do_chans;
1213 s->insn_write = vmk80xx_do_winsn;
1214 s->insn_bits = vmk80xx_do_bits;
1215 if (boardinfo->model == VMK8061_MODEL) {
1216 s->subdev_flags |= SDF_READABLE;
1217 s->insn_read = vmk80xx_do_rinsn;
1220 /* Counter subdevice */
1221 s = &cdev->subdevices[VMK80XX_SUBD_CNT];
1222 s->type = COMEDI_SUBD_COUNTER;
1223 s->subdev_flags = SDF_READABLE;
1224 s->n_chan = boardinfo->cnt_chans;
1225 s->insn_read = vmk80xx_cnt_rinsn;
1226 s->insn_config = vmk80xx_cnt_cinsn;
1227 if (boardinfo->model == VMK8055_MODEL) {
1228 s->subdev_flags |= SDF_WRITEABLE;
1229 s->maxdata = (1 << boardinfo->cnt_bits) - 1;
1230 s->insn_write = vmk80xx_cnt_winsn;
1234 if (boardinfo->model == VMK8061_MODEL) {
1235 s = &cdev->subdevices[VMK80XX_SUBD_PWM];
1236 s->type = COMEDI_SUBD_PWM;
1237 s->subdev_flags = SDF_READABLE | SDF_WRITEABLE;
1238 s->n_chan = boardinfo->pwm_chans;
1239 s->maxdata = (1 << boardinfo->pwm_bits) - 1;
1240 s->insn_read = vmk80xx_pwm_rinsn;
1241 s->insn_write = vmk80xx_pwm_winsn;
1245 dev_info(cdev->class_dev, "vmk80xx: board #%d [%s] attached\n",
1246 dev->count, boardinfo->name);
1248 up(&dev->limit_sem);
1253 static int vmk80xx_auto_attach(struct comedi_device *cdev,
1254 unsigned long context_unused)
1256 struct usb_interface *intf = comedi_to_usb_interface(cdev);
1260 mutex_lock(&glb_mutex);
1261 for (i = 0; i < VMK80XX_MAX_BOARDS; i++)
1262 if (vmb[i].probed && vmb[i].intf == intf)
1264 if (i == VMK80XX_MAX_BOARDS)
1266 else if (vmb[i].attached)
1269 ret = vmk80xx_attach_common(cdev, &vmb[i]);
1270 mutex_unlock(&glb_mutex);
1274 static void vmk80xx_detach(struct comedi_device *dev)
1276 struct vmk80xx_usb *usb = dev->private;
1281 mutex_lock(&glb_mutex);
1282 down(&usb->limit_sem);
1284 dev->private = NULL;
1288 usb_set_intfdata(usb->intf, NULL);
1290 usb_kill_anchored_urbs(&usb->rx_anchor);
1291 usb_kill_anchored_urbs(&usb->tx_anchor);
1293 kfree(usb->usb_rx_buf);
1294 kfree(usb->usb_tx_buf);
1296 up(&usb->limit_sem);
1297 mutex_unlock(&glb_mutex);
1300 static struct comedi_driver vmk80xx_driver = {
1301 .module = THIS_MODULE,
1302 .driver_name = "vmk80xx",
1303 .auto_attach = vmk80xx_auto_attach,
1304 .detach = vmk80xx_detach,
1307 static int vmk80xx_usb_probe(struct usb_interface *intf,
1308 const struct usb_device_id *id)
1310 const struct vmk80xx_board *boardinfo;
1312 struct vmk80xx_usb *dev;
1313 struct usb_host_interface *iface_desc;
1314 struct usb_endpoint_descriptor *ep_desc;
1317 mutex_lock(&glb_mutex);
1319 for (i = 0; i < VMK80XX_MAX_BOARDS; i++)
1323 if (i == VMK80XX_MAX_BOARDS) {
1324 mutex_unlock(&glb_mutex);
1330 memset(dev, 0x00, sizeof(struct vmk80xx_usb));
1333 iface_desc = intf->cur_altsetting;
1334 if (iface_desc->desc.bNumEndpoints != 2)
1337 for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) {
1338 ep_desc = &iface_desc->endpoint[i].desc;
1340 if (usb_endpoint_is_int_in(ep_desc)) {
1341 dev->ep_rx = ep_desc;
1345 if (usb_endpoint_is_int_out(ep_desc)) {
1346 dev->ep_tx = ep_desc;
1350 if (usb_endpoint_is_bulk_in(ep_desc)) {
1351 dev->ep_rx = ep_desc;
1355 if (usb_endpoint_is_bulk_out(ep_desc)) {
1356 dev->ep_tx = ep_desc;
1361 if (!dev->ep_rx || !dev->ep_tx)
1364 size = le16_to_cpu(dev->ep_rx->wMaxPacketSize);
1365 dev->usb_rx_buf = kmalloc(size, GFP_KERNEL);
1366 if (!dev->usb_rx_buf) {
1367 mutex_unlock(&glb_mutex);
1371 size = le16_to_cpu(dev->ep_tx->wMaxPacketSize);
1372 dev->usb_tx_buf = kmalloc(size, GFP_KERNEL);
1373 if (!dev->usb_tx_buf) {
1374 kfree(dev->usb_rx_buf);
1375 mutex_unlock(&glb_mutex);
1379 dev->udev = interface_to_usbdev(intf);
1382 sema_init(&dev->limit_sem, 8);
1383 init_waitqueue_head(&dev->read_wait);
1384 init_waitqueue_head(&dev->write_wait);
1386 init_usb_anchor(&dev->rx_anchor);
1387 init_usb_anchor(&dev->tx_anchor);
1389 usb_set_intfdata(intf, dev);
1391 boardinfo = &vmk80xx_boardinfo[id->driver_info];
1392 dev->board = boardinfo;
1394 if (boardinfo->model == VMK8061_MODEL) {
1395 vmk80xx_read_eeprom(dev, IC3_VERSION);
1396 dev_info(&intf->dev, "%s\n", dev->fw.ic3_vers);
1398 if (vmk80xx_check_data_link(dev)) {
1399 vmk80xx_read_eeprom(dev, IC6_VERSION);
1400 dev_info(&intf->dev, "%s\n", dev->fw.ic6_vers);
1402 dbgcm("comedi#: vmk80xx: no conn. to CPU\n");
1406 if (boardinfo->model == VMK8055_MODEL)
1407 vmk80xx_reset_device(dev);
1411 dev_info(&intf->dev, "board #%d [%s] now attached\n",
1412 dev->count, boardinfo->name);
1414 mutex_unlock(&glb_mutex);
1416 comedi_usb_auto_config(intf, &vmk80xx_driver);
1420 mutex_unlock(&glb_mutex);
1425 static const struct usb_device_id vmk80xx_usb_id_table[] = {
1426 { USB_DEVICE(0x10cf, 0x5500), .driver_info = DEVICE_VMK8055 },
1427 { USB_DEVICE(0x10cf, 0x5501), .driver_info = DEVICE_VMK8055 },
1428 { USB_DEVICE(0x10cf, 0x5502), .driver_info = DEVICE_VMK8055 },
1429 { USB_DEVICE(0x10cf, 0x5503), .driver_info = DEVICE_VMK8055 },
1430 { USB_DEVICE(0x10cf, 0x8061), .driver_info = DEVICE_VMK8061 },
1431 { USB_DEVICE(0x10cf, 0x8062), .driver_info = DEVICE_VMK8061 },
1432 { USB_DEVICE(0x10cf, 0x8063), .driver_info = DEVICE_VMK8061 },
1433 { USB_DEVICE(0x10cf, 0x8064), .driver_info = DEVICE_VMK8061 },
1434 { USB_DEVICE(0x10cf, 0x8065), .driver_info = DEVICE_VMK8061 },
1435 { USB_DEVICE(0x10cf, 0x8066), .driver_info = DEVICE_VMK8061 },
1436 { USB_DEVICE(0x10cf, 0x8067), .driver_info = DEVICE_VMK8061 },
1437 { USB_DEVICE(0x10cf, 0x8068), .driver_info = DEVICE_VMK8061 },
1440 MODULE_DEVICE_TABLE(usb, vmk80xx_usb_id_table);
1442 static struct usb_driver vmk80xx_usb_driver = {
1444 .id_table = vmk80xx_usb_id_table,
1445 .probe = vmk80xx_usb_probe,
1446 .disconnect = comedi_usb_auto_unconfig,
1448 module_comedi_usb_driver(vmk80xx_driver, vmk80xx_usb_driver);
1450 MODULE_AUTHOR("Manuel Gebele <forensixs@gmx.de>");
1451 MODULE_DESCRIPTION("Velleman USB Board Low-Level Driver");
1452 MODULE_SUPPORTED_DEVICE("K8055/K8061 aka VM110/VM140");
1453 MODULE_VERSION("0.8.01");
1454 MODULE_LICENSE("GPL");