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;
186 struct usb_device *udev;
187 struct usb_interface *intf;
188 struct usb_endpoint_descriptor *ep_rx;
189 struct usb_endpoint_descriptor *ep_tx;
190 struct usb_anchor rx_anchor;
191 struct usb_anchor tx_anchor;
192 struct vmk80xx_board board;
193 struct firmware_version fw;
194 struct semaphore limit_sem;
195 wait_queue_head_t read_wait;
196 wait_queue_head_t write_wait;
197 unsigned char *usb_rx_buf;
198 unsigned char *usb_tx_buf;
205 static struct vmk80xx_usb vmb[VMK80XX_MAX_BOARDS];
207 static DEFINE_MUTEX(glb_mutex);
209 static void vmk80xx_tx_callback(struct urb *urb)
211 struct vmk80xx_usb *dev = urb->context;
212 int stat = urb->status;
214 if (stat && !(stat == -ENOENT
215 || stat == -ECONNRESET || stat == -ESHUTDOWN))
216 dbgcm("comedi#: vmk80xx: %s - nonzero urb status (%d)\n",
219 if (!test_bit(TRANS_OUT_BUSY, &dev->flags))
222 clear_bit(TRANS_OUT_BUSY, &dev->flags);
224 wake_up_interruptible(&dev->write_wait);
227 static void vmk80xx_rx_callback(struct urb *urb)
229 struct vmk80xx_usb *dev = urb->context;
230 int stat = urb->status;
240 dbgcm("comedi#: vmk80xx: %s - nonzero urb status (%d)\n",
247 if (test_bit(TRANS_IN_RUNNING, &dev->flags) && dev->intf) {
248 usb_anchor_urb(urb, &dev->rx_anchor);
250 if (!usb_submit_urb(urb, GFP_KERNEL))
253 dev_err(&urb->dev->dev,
254 "comedi#: vmk80xx: %s - submit urb failed\n",
257 usb_unanchor_urb(urb);
260 clear_bit(TRANS_IN_BUSY, &dev->flags);
262 wake_up_interruptible(&dev->read_wait);
265 static int vmk80xx_check_data_link(struct vmk80xx_usb *dev)
267 unsigned int tx_pipe;
268 unsigned int rx_pipe;
272 tx_pipe = usb_sndbulkpipe(dev->udev, 0x01);
273 rx_pipe = usb_rcvbulkpipe(dev->udev, 0x81);
275 tx[0] = VMK8061_CMD_RD_PWR_STAT;
278 * Check that IC6 (PIC16F871) is powered and
279 * running and the data link between IC3 and
280 * IC6 is working properly
282 usb_bulk_msg(dev->udev, tx_pipe, tx, 1, NULL, dev->ep_tx->bInterval);
283 usb_bulk_msg(dev->udev, rx_pipe, rx, 2, NULL, HZ * 10);
288 static void vmk80xx_read_eeprom(struct vmk80xx_usb *dev, int flag)
290 unsigned int tx_pipe;
291 unsigned int rx_pipe;
293 unsigned char rx[64];
296 tx_pipe = usb_sndbulkpipe(dev->udev, 0x01);
297 rx_pipe = usb_rcvbulkpipe(dev->udev, 0x81);
299 tx[0] = VMK8061_CMD_RD_VERSION;
302 * Read the firmware version info of IC3 and
303 * IC6 from the internal EEPROM of the IC
305 usb_bulk_msg(dev->udev, tx_pipe, tx, 1, NULL, dev->ep_tx->bInterval);
306 usb_bulk_msg(dev->udev, rx_pipe, rx, 64, &cnt, HZ * 10);
310 if (flag & IC3_VERSION)
311 strncpy(dev->fw.ic3_vers, rx + 1, 24);
312 else /* IC6_VERSION */
313 strncpy(dev->fw.ic6_vers, rx + 25, 24);
316 static int vmk80xx_reset_device(struct vmk80xx_usb *dev)
319 unsigned int tx_pipe;
323 urb = usb_alloc_urb(0, GFP_KERNEL);
327 tx_pipe = usb_sndintpipe(dev->udev, 0x01);
329 ival = dev->ep_tx->bInterval;
330 size = le16_to_cpu(dev->ep_tx->wMaxPacketSize);
332 dev->usb_tx_buf[0] = VMK8055_CMD_RST;
333 dev->usb_tx_buf[1] = 0x00;
334 dev->usb_tx_buf[2] = 0x00;
335 dev->usb_tx_buf[3] = 0x00;
336 dev->usb_tx_buf[4] = 0x00;
337 dev->usb_tx_buf[5] = 0x00;
338 dev->usb_tx_buf[6] = 0x00;
339 dev->usb_tx_buf[7] = 0x00;
341 usb_fill_int_urb(urb, dev->udev, tx_pipe, dev->usb_tx_buf,
342 size, vmk80xx_tx_callback, dev, ival);
344 usb_anchor_urb(urb, &dev->tx_anchor);
346 return usb_submit_urb(urb, GFP_KERNEL);
349 static void vmk80xx_build_int_urb(struct urb *urb, int flag)
351 struct vmk80xx_usb *dev = urb->context;
357 void (*callback) (struct urb *);
360 if (flag & URB_RCV_FLAG) {
361 rx_addr = dev->ep_rx->bEndpointAddress;
362 pipe = usb_rcvintpipe(dev->udev, rx_addr);
363 buf = dev->usb_rx_buf;
364 size = le16_to_cpu(dev->ep_rx->wMaxPacketSize);
365 callback = vmk80xx_rx_callback;
366 ival = dev->ep_rx->bInterval;
367 } else { /* URB_SND_FLAG */
368 tx_addr = dev->ep_tx->bEndpointAddress;
369 pipe = usb_sndintpipe(dev->udev, tx_addr);
370 buf = dev->usb_tx_buf;
371 size = le16_to_cpu(dev->ep_tx->wMaxPacketSize);
372 callback = vmk80xx_tx_callback;
373 ival = dev->ep_tx->bInterval;
376 usb_fill_int_urb(urb, dev->udev, pipe, buf, size, callback, dev, ival);
379 static void vmk80xx_do_bulk_msg(struct vmk80xx_usb *dev)
383 unsigned int tx_pipe;
384 unsigned int rx_pipe;
387 set_bit(TRANS_IN_BUSY, &dev->flags);
388 set_bit(TRANS_OUT_BUSY, &dev->flags);
390 tx_addr = dev->ep_tx->bEndpointAddress;
391 rx_addr = dev->ep_rx->bEndpointAddress;
392 tx_pipe = usb_sndbulkpipe(dev->udev, tx_addr);
393 rx_pipe = usb_rcvbulkpipe(dev->udev, rx_addr);
396 * The max packet size attributes of the K8061
397 * input/output endpoints are identical
399 size = le16_to_cpu(dev->ep_tx->wMaxPacketSize);
401 usb_bulk_msg(dev->udev, tx_pipe, dev->usb_tx_buf,
402 size, NULL, dev->ep_tx->bInterval);
403 usb_bulk_msg(dev->udev, rx_pipe, dev->usb_rx_buf, size, NULL, HZ * 10);
405 clear_bit(TRANS_OUT_BUSY, &dev->flags);
406 clear_bit(TRANS_IN_BUSY, &dev->flags);
409 static int vmk80xx_read_packet(struct vmk80xx_usb *dev)
417 /* Only useful for interrupt transfers */
418 if (test_bit(TRANS_IN_BUSY, &dev->flags))
419 if (wait_event_interruptible(dev->read_wait,
420 !test_bit(TRANS_IN_BUSY,
424 if (dev->board.model == VMK8061_MODEL) {
425 vmk80xx_do_bulk_msg(dev);
430 urb = usb_alloc_urb(0, GFP_KERNEL);
435 vmk80xx_build_int_urb(urb, URB_RCV_FLAG);
437 set_bit(TRANS_IN_RUNNING, &dev->flags);
438 set_bit(TRANS_IN_BUSY, &dev->flags);
440 usb_anchor_urb(urb, &dev->rx_anchor);
442 retval = usb_submit_urb(urb, GFP_KERNEL);
446 clear_bit(TRANS_IN_RUNNING, &dev->flags);
447 usb_unanchor_urb(urb);
455 static int vmk80xx_write_packet(struct vmk80xx_usb *dev, int cmd)
463 if (test_bit(TRANS_OUT_BUSY, &dev->flags))
464 if (wait_event_interruptible(dev->write_wait,
465 !test_bit(TRANS_OUT_BUSY,
469 if (dev->board.model == VMK8061_MODEL) {
470 dev->usb_tx_buf[0] = cmd;
471 vmk80xx_do_bulk_msg(dev);
476 urb = usb_alloc_urb(0, GFP_KERNEL);
481 vmk80xx_build_int_urb(urb, URB_SND_FLAG);
483 set_bit(TRANS_OUT_BUSY, &dev->flags);
485 usb_anchor_urb(urb, &dev->tx_anchor);
487 dev->usb_tx_buf[0] = cmd;
489 retval = usb_submit_urb(urb, GFP_KERNEL);
493 clear_bit(TRANS_OUT_BUSY, &dev->flags);
494 usb_unanchor_urb(urb);
505 static int rudimentary_check(struct vmk80xx_usb *dev, int dir)
514 if (test_bit(TRANS_IN_BUSY, &dev->flags))
518 if (test_bit(TRANS_OUT_BUSY, &dev->flags))
525 static int vmk80xx_ai_rinsn(struct comedi_device *cdev,
526 struct comedi_subdevice *s,
527 struct comedi_insn *insn, unsigned int *data)
529 struct vmk80xx_usb *dev = cdev->private;
534 n = rudimentary_check(dev, DIR_IN);
538 down(&dev->limit_sem);
539 chan = CR_CHAN(insn->chanspec);
541 switch (dev->board.model) {
544 reg[0] = VMK8055_AI1_REG;
546 reg[0] = VMK8055_AI2_REG;
550 reg[0] = VMK8061_AI_REG1;
551 reg[1] = VMK8061_AI_REG2;
552 dev->usb_tx_buf[0] = VMK8061_CMD_RD_AI;
553 dev->usb_tx_buf[VMK8061_CH_REG] = chan;
557 for (n = 0; n < insn->n; n++) {
558 if (vmk80xx_read_packet(dev))
561 if (dev->board.model == VMK8055_MODEL) {
562 data[n] = dev->usb_rx_buf[reg[0]];
567 data[n] = dev->usb_rx_buf[reg[0]] + 256 *
568 dev->usb_rx_buf[reg[1]];
576 static int vmk80xx_ao_winsn(struct comedi_device *cdev,
577 struct comedi_subdevice *s,
578 struct comedi_insn *insn, unsigned int *data)
580 struct vmk80xx_usb *dev = cdev->private;
586 n = rudimentary_check(dev, DIR_OUT);
590 down(&dev->limit_sem);
591 chan = CR_CHAN(insn->chanspec);
593 switch (dev->board.model) {
595 cmd = VMK8055_CMD_WRT_AD;
597 reg = VMK8055_AO1_REG;
599 reg = VMK8055_AO2_REG;
601 default: /* NOTE: avoid compiler warnings */
602 cmd = VMK8061_CMD_SET_AO;
603 reg = VMK8061_AO_REG;
604 dev->usb_tx_buf[VMK8061_CH_REG] = chan;
608 for (n = 0; n < insn->n; n++) {
609 dev->usb_tx_buf[reg] = data[n];
611 if (vmk80xx_write_packet(dev, cmd))
620 static int vmk80xx_ao_rinsn(struct comedi_device *cdev,
621 struct comedi_subdevice *s,
622 struct comedi_insn *insn, unsigned int *data)
624 struct vmk80xx_usb *dev = cdev->private;
629 n = rudimentary_check(dev, DIR_IN);
633 down(&dev->limit_sem);
634 chan = CR_CHAN(insn->chanspec);
636 reg = VMK8061_AO_REG - 1;
638 dev->usb_tx_buf[0] = VMK8061_CMD_RD_AO;
640 for (n = 0; n < insn->n; n++) {
641 if (vmk80xx_read_packet(dev))
644 data[n] = dev->usb_rx_buf[reg + chan];
652 static int vmk80xx_di_bits(struct comedi_device *cdev,
653 struct comedi_subdevice *s,
654 struct comedi_insn *insn, unsigned int *data)
656 struct vmk80xx_usb *dev = cdev->private;
657 unsigned char *rx_buf;
661 retval = rudimentary_check(dev, DIR_IN);
665 down(&dev->limit_sem);
667 rx_buf = dev->usb_rx_buf;
669 if (dev->board.model == VMK8061_MODEL) {
670 reg = VMK8061_DI_REG;
671 dev->usb_tx_buf[0] = VMK8061_CMD_RD_DI;
673 reg = VMK8055_DI_REG;
676 retval = vmk80xx_read_packet(dev);
679 if (dev->board.model == VMK8055_MODEL)
680 data[1] = (((rx_buf[reg] >> 4) & 0x03) |
681 ((rx_buf[reg] << 2) & 0x04) |
682 ((rx_buf[reg] >> 3) & 0x18));
684 data[1] = rx_buf[reg];
694 static int vmk80xx_di_rinsn(struct comedi_device *cdev,
695 struct comedi_subdevice *s,
696 struct comedi_insn *insn, unsigned int *data)
698 struct vmk80xx_usb *dev = cdev->private;
700 unsigned char *rx_buf;
705 n = rudimentary_check(dev, DIR_IN);
709 down(&dev->limit_sem);
710 chan = CR_CHAN(insn->chanspec);
712 rx_buf = dev->usb_rx_buf;
714 if (dev->board.model == VMK8061_MODEL) {
715 reg = VMK8061_DI_REG;
716 dev->usb_tx_buf[0] = VMK8061_CMD_RD_DI;
718 reg = VMK8055_DI_REG;
720 for (n = 0; n < insn->n; n++) {
721 if (vmk80xx_read_packet(dev))
724 if (dev->board.model == VMK8055_MODEL)
725 inp = (((rx_buf[reg] >> 4) & 0x03) |
726 ((rx_buf[reg] << 2) & 0x04) |
727 ((rx_buf[reg] >> 3) & 0x18));
731 data[n] = (inp >> chan) & 1;
739 static int vmk80xx_do_winsn(struct comedi_device *cdev,
740 struct comedi_subdevice *s,
741 struct comedi_insn *insn, unsigned int *data)
743 struct vmk80xx_usb *dev = cdev->private;
745 unsigned char *tx_buf;
750 n = rudimentary_check(dev, DIR_OUT);
754 down(&dev->limit_sem);
755 chan = CR_CHAN(insn->chanspec);
757 tx_buf = dev->usb_tx_buf;
759 for (n = 0; n < insn->n; n++) {
760 if (dev->board.model == VMK8055_MODEL) {
761 reg = VMK8055_DO_REG;
762 cmd = VMK8055_CMD_WRT_AD;
764 tx_buf[reg] |= (1 << chan);
766 tx_buf[reg] ^= (1 << chan);
767 } else { /* VMK8061_MODEL */
768 reg = VMK8061_DO_REG;
770 cmd = VMK8061_CMD_SET_DO;
771 tx_buf[reg] = 1 << chan;
773 cmd = VMK8061_CMD_CLR_DO;
774 tx_buf[reg] = 0xff - (1 << chan);
778 if (vmk80xx_write_packet(dev, cmd))
787 static int vmk80xx_do_rinsn(struct comedi_device *cdev,
788 struct comedi_subdevice *s,
789 struct comedi_insn *insn, unsigned int *data)
791 struct vmk80xx_usb *dev = cdev->private;
796 n = rudimentary_check(dev, DIR_IN);
800 down(&dev->limit_sem);
801 chan = CR_CHAN(insn->chanspec);
803 reg = VMK8061_DO_REG;
805 dev->usb_tx_buf[0] = VMK8061_CMD_RD_DO;
807 for (n = 0; n < insn->n; n++) {
808 if (vmk80xx_read_packet(dev))
811 data[n] = (dev->usb_rx_buf[reg] >> chan) & 1;
819 static int vmk80xx_do_bits(struct comedi_device *cdev,
820 struct comedi_subdevice *s,
821 struct comedi_insn *insn, unsigned int *data)
823 struct vmk80xx_usb *dev = cdev->private;
824 unsigned char *rx_buf, *tx_buf;
833 if (dev->board.model == VMK8061_MODEL)
836 retval = rudimentary_check(dev, dir);
840 down(&dev->limit_sem);
842 rx_buf = dev->usb_rx_buf;
843 tx_buf = dev->usb_tx_buf;
846 if (dev->board.model == VMK8055_MODEL) {
847 reg = VMK8055_DO_REG;
848 cmd = VMK8055_CMD_WRT_AD;
849 } else { /* VMK8061_MODEL */
850 reg = VMK8061_DO_REG;
851 cmd = VMK8061_CMD_DO;
854 tx_buf[reg] &= ~data[0];
855 tx_buf[reg] |= (data[0] & data[1]);
857 retval = vmk80xx_write_packet(dev, cmd);
863 if (dev->board.model == VMK8061_MODEL) {
864 reg = VMK8061_DO_REG;
865 tx_buf[0] = VMK8061_CMD_RD_DO;
867 retval = vmk80xx_read_packet(dev);
870 data[1] = rx_buf[reg];
874 data[1] = tx_buf[reg];
884 static int vmk80xx_cnt_rinsn(struct comedi_device *cdev,
885 struct comedi_subdevice *s,
886 struct comedi_insn *insn, unsigned int *data)
888 struct vmk80xx_usb *dev = cdev->private;
893 n = rudimentary_check(dev, DIR_IN);
897 down(&dev->limit_sem);
898 chan = CR_CHAN(insn->chanspec);
900 switch (dev->board.model) {
903 reg[0] = VMK8055_CNT1_REG;
905 reg[0] = VMK8055_CNT2_REG;
909 reg[0] = VMK8061_CNT_REG;
910 reg[1] = VMK8061_CNT_REG;
911 dev->usb_tx_buf[0] = VMK8061_CMD_RD_CNT;
915 for (n = 0; n < insn->n; n++) {
916 if (vmk80xx_read_packet(dev))
919 if (dev->board.model == VMK8055_MODEL)
920 data[n] = dev->usb_rx_buf[reg[0]];
921 else /* VMK8061_MODEL */
922 data[n] = dev->usb_rx_buf[reg[0] * (chan + 1) + 1]
923 + 256 * dev->usb_rx_buf[reg[1] * 2 + 2];
931 static int vmk80xx_cnt_cinsn(struct comedi_device *cdev,
932 struct comedi_subdevice *s,
933 struct comedi_insn *insn, unsigned int *data)
935 struct vmk80xx_usb *dev = cdev->private;
936 unsigned int insn_cmd;
942 n = rudimentary_check(dev, DIR_OUT);
947 if (insn_cmd != INSN_CONFIG_RESET && insn_cmd != GPCT_RESET)
950 down(&dev->limit_sem);
952 chan = CR_CHAN(insn->chanspec);
954 if (dev->board.model == VMK8055_MODEL) {
956 cmd = VMK8055_CMD_RST_CNT1;
957 reg = VMK8055_CNT1_REG;
959 cmd = VMK8055_CMD_RST_CNT2;
960 reg = VMK8055_CNT2_REG;
963 dev->usb_tx_buf[reg] = 0x00;
965 cmd = VMK8061_CMD_RST_CNT;
968 for (n = 0; n < insn->n; n++)
969 if (vmk80xx_write_packet(dev, cmd))
977 static int vmk80xx_cnt_winsn(struct comedi_device *cdev,
978 struct comedi_subdevice *s,
979 struct comedi_insn *insn, unsigned int *data)
981 struct vmk80xx_usb *dev = cdev->private;
982 unsigned long debtime;
988 n = rudimentary_check(dev, DIR_OUT);
992 down(&dev->limit_sem);
993 chan = CR_CHAN(insn->chanspec);
996 cmd = VMK8055_CMD_DEB1_TIME;
998 cmd = VMK8055_CMD_DEB2_TIME;
1000 for (n = 0; n < insn->n; n++) {
1005 /* TODO: Prevent overflows */
1009 val = int_sqrt(debtime * 1000 / 115);
1010 if (((val + 1) * val) < debtime * 1000 / 115)
1013 dev->usb_tx_buf[6 + chan] = val;
1015 if (vmk80xx_write_packet(dev, cmd))
1019 up(&dev->limit_sem);
1024 static int vmk80xx_pwm_rinsn(struct comedi_device *cdev,
1025 struct comedi_subdevice *s,
1026 struct comedi_insn *insn, unsigned int *data)
1028 struct vmk80xx_usb *dev = cdev->private;
1032 n = rudimentary_check(dev, DIR_IN);
1036 down(&dev->limit_sem);
1038 reg[0] = VMK8061_PWM_REG1;
1039 reg[1] = VMK8061_PWM_REG2;
1041 dev->usb_tx_buf[0] = VMK8061_CMD_RD_PWM;
1043 for (n = 0; n < insn->n; n++) {
1044 if (vmk80xx_read_packet(dev))
1047 data[n] = dev->usb_rx_buf[reg[0]] + 4 * dev->usb_rx_buf[reg[1]];
1050 up(&dev->limit_sem);
1055 static int vmk80xx_pwm_winsn(struct comedi_device *cdev,
1056 struct comedi_subdevice *s,
1057 struct comedi_insn *insn, unsigned int *data)
1059 struct vmk80xx_usb *dev = cdev->private;
1060 unsigned char *tx_buf;
1065 n = rudimentary_check(dev, DIR_OUT);
1069 down(&dev->limit_sem);
1071 tx_buf = dev->usb_tx_buf;
1073 reg[0] = VMK8061_PWM_REG1;
1074 reg[1] = VMK8061_PWM_REG2;
1076 cmd = VMK8061_CMD_OUT_PWM;
1079 * The followin piece of code was translated from the inline
1080 * assembler code in the DLL source code.
1083 * mov eax, k ; k is the value (data[n])
1084 * and al, 03h ; al are the lower 8 bits of eax
1085 * mov lo, al ; lo is the low part (tx_buf[reg[0]])
1087 * shr eax, 2 ; right shift eax register by 2
1088 * mov hi, al ; hi is the high part (tx_buf[reg[1]])
1091 for (n = 0; n < insn->n; n++) {
1092 tx_buf[reg[0]] = (unsigned char)(data[n] & 0x03);
1093 tx_buf[reg[1]] = (unsigned char)(data[n] >> 2) & 0xff;
1095 if (vmk80xx_write_packet(dev, cmd))
1099 up(&dev->limit_sem);
1104 static int vmk80xx_attach_common(struct comedi_device *cdev,
1105 struct vmk80xx_usb *dev)
1108 struct comedi_subdevice *s;
1111 down(&dev->limit_sem);
1112 cdev->board_name = dev->board.name;
1113 cdev->private = dev;
1114 if (dev->board.model == VMK8055_MODEL)
1118 ret = comedi_alloc_subdevices(cdev, n_subd);
1120 up(&dev->limit_sem);
1123 /* Analog input subdevice */
1124 s = &cdev->subdevices[VMK80XX_SUBD_AI];
1125 s->type = COMEDI_SUBD_AI;
1126 s->subdev_flags = SDF_READABLE | SDF_GROUND;
1127 s->n_chan = dev->board.ai_chans;
1128 s->maxdata = (1 << dev->board.ai_bits) - 1;
1129 s->range_table = dev->board.range;
1130 s->insn_read = vmk80xx_ai_rinsn;
1131 /* Analog output subdevice */
1132 s = &cdev->subdevices[VMK80XX_SUBD_AO];
1133 s->type = COMEDI_SUBD_AO;
1134 s->subdev_flags = SDF_WRITEABLE | SDF_GROUND;
1135 s->n_chan = dev->board.ao_chans;
1136 s->maxdata = (1 << dev->board.ao_bits) - 1;
1137 s->range_table = dev->board.range;
1138 s->insn_write = vmk80xx_ao_winsn;
1139 if (dev->board.model == VMK8061_MODEL) {
1140 s->subdev_flags |= SDF_READABLE;
1141 s->insn_read = vmk80xx_ao_rinsn;
1143 /* Digital input subdevice */
1144 s = &cdev->subdevices[VMK80XX_SUBD_DI];
1145 s->type = COMEDI_SUBD_DI;
1146 s->subdev_flags = SDF_READABLE | SDF_GROUND;
1147 s->n_chan = dev->board.di_chans;
1149 s->insn_read = vmk80xx_di_rinsn;
1150 s->insn_bits = vmk80xx_di_bits;
1151 /* Digital output subdevice */
1152 s = &cdev->subdevices[VMK80XX_SUBD_DO];
1153 s->type = COMEDI_SUBD_DO;
1154 s->subdev_flags = SDF_WRITEABLE | SDF_GROUND;
1155 s->n_chan = dev->board.do_chans;
1157 s->insn_write = vmk80xx_do_winsn;
1158 s->insn_bits = vmk80xx_do_bits;
1159 if (dev->board.model == VMK8061_MODEL) {
1160 s->subdev_flags |= SDF_READABLE;
1161 s->insn_read = vmk80xx_do_rinsn;
1163 /* Counter subdevice */
1164 s = &cdev->subdevices[VMK80XX_SUBD_CNT];
1165 s->type = COMEDI_SUBD_COUNTER;
1166 s->subdev_flags = SDF_READABLE;
1167 s->n_chan = dev->board.cnt_chans;
1168 s->insn_read = vmk80xx_cnt_rinsn;
1169 s->insn_config = vmk80xx_cnt_cinsn;
1170 if (dev->board.model == VMK8055_MODEL) {
1171 s->subdev_flags |= SDF_WRITEABLE;
1172 s->maxdata = (1 << dev->board.cnt_bits) - 1;
1173 s->insn_write = vmk80xx_cnt_winsn;
1176 if (dev->board.model == VMK8061_MODEL) {
1177 s = &cdev->subdevices[VMK80XX_SUBD_PWM];
1178 s->type = COMEDI_SUBD_PWM;
1179 s->subdev_flags = SDF_READABLE | SDF_WRITEABLE;
1180 s->n_chan = dev->board.pwm_chans;
1181 s->maxdata = (1 << dev->board.pwm_bits) - 1;
1182 s->insn_read = vmk80xx_pwm_rinsn;
1183 s->insn_write = vmk80xx_pwm_winsn;
1186 dev_info(cdev->class_dev, "vmk80xx: board #%d [%s] attached\n",
1187 dev->count, dev->board.name);
1188 up(&dev->limit_sem);
1192 static int vmk80xx_auto_attach(struct comedi_device *cdev,
1193 unsigned long context_unused)
1195 struct usb_interface *intf = comedi_to_usb_interface(cdev);
1199 mutex_lock(&glb_mutex);
1200 for (i = 0; i < VMK80XX_MAX_BOARDS; i++)
1201 if (vmb[i].probed && vmb[i].intf == intf)
1203 if (i == VMK80XX_MAX_BOARDS)
1205 else if (vmb[i].attached)
1208 ret = vmk80xx_attach_common(cdev, &vmb[i]);
1209 mutex_unlock(&glb_mutex);
1213 static void vmk80xx_detach(struct comedi_device *dev)
1215 struct vmk80xx_usb *usb = dev->private;
1218 down(&usb->limit_sem);
1219 dev->private = NULL;
1221 up(&usb->limit_sem);
1225 static struct comedi_driver vmk80xx_driver = {
1226 .module = THIS_MODULE,
1227 .driver_name = "vmk80xx",
1228 .auto_attach = vmk80xx_auto_attach,
1229 .detach = vmk80xx_detach,
1232 static int vmk80xx_usb_probe(struct usb_interface *intf,
1233 const struct usb_device_id *id)
1236 struct vmk80xx_usb *dev;
1237 struct usb_host_interface *iface_desc;
1238 struct usb_endpoint_descriptor *ep_desc;
1241 mutex_lock(&glb_mutex);
1243 for (i = 0; i < VMK80XX_MAX_BOARDS; i++)
1247 if (i == VMK80XX_MAX_BOARDS) {
1248 mutex_unlock(&glb_mutex);
1254 memset(dev, 0x00, sizeof(struct vmk80xx_usb));
1257 iface_desc = intf->cur_altsetting;
1258 if (iface_desc->desc.bNumEndpoints != 2)
1261 for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) {
1262 ep_desc = &iface_desc->endpoint[i].desc;
1264 if (usb_endpoint_is_int_in(ep_desc)) {
1265 dev->ep_rx = ep_desc;
1269 if (usb_endpoint_is_int_out(ep_desc)) {
1270 dev->ep_tx = ep_desc;
1274 if (usb_endpoint_is_bulk_in(ep_desc)) {
1275 dev->ep_rx = ep_desc;
1279 if (usb_endpoint_is_bulk_out(ep_desc)) {
1280 dev->ep_tx = ep_desc;
1285 if (!dev->ep_rx || !dev->ep_tx)
1288 size = le16_to_cpu(dev->ep_rx->wMaxPacketSize);
1289 dev->usb_rx_buf = kmalloc(size, GFP_KERNEL);
1290 if (!dev->usb_rx_buf) {
1291 mutex_unlock(&glb_mutex);
1295 size = le16_to_cpu(dev->ep_tx->wMaxPacketSize);
1296 dev->usb_tx_buf = kmalloc(size, GFP_KERNEL);
1297 if (!dev->usb_tx_buf) {
1298 kfree(dev->usb_rx_buf);
1299 mutex_unlock(&glb_mutex);
1303 dev->udev = interface_to_usbdev(intf);
1306 sema_init(&dev->limit_sem, 8);
1307 init_waitqueue_head(&dev->read_wait);
1308 init_waitqueue_head(&dev->write_wait);
1310 init_usb_anchor(&dev->rx_anchor);
1311 init_usb_anchor(&dev->tx_anchor);
1313 usb_set_intfdata(intf, dev);
1315 switch (id->driver_info) {
1316 case DEVICE_VMK8055:
1317 dev->board.name = "K8055 (VM110)";
1318 dev->board.model = VMK8055_MODEL;
1319 dev->board.range = &vmk8055_range;
1320 dev->board.ai_chans = 2;
1321 dev->board.ai_bits = 8;
1322 dev->board.ao_chans = 2;
1323 dev->board.ao_bits = 8;
1324 dev->board.di_chans = 5;
1325 dev->board.di_bits = 1;
1326 dev->board.do_chans = 8;
1327 dev->board.do_bits = 1;
1328 dev->board.cnt_chans = 2;
1329 dev->board.cnt_bits = 16;
1330 dev->board.pwm_chans = 0;
1331 dev->board.pwm_bits = 0;
1333 case DEVICE_VMK8061:
1334 dev->board.name = "K8061 (VM140)";
1335 dev->board.model = VMK8061_MODEL;
1336 dev->board.range = &vmk8061_range;
1337 dev->board.ai_chans = 8;
1338 dev->board.ai_bits = 10;
1339 dev->board.ao_chans = 8;
1340 dev->board.ao_bits = 8;
1341 dev->board.di_chans = 8;
1342 dev->board.di_bits = 1;
1343 dev->board.do_chans = 8;
1344 dev->board.do_bits = 1;
1345 dev->board.cnt_chans = 2;
1346 dev->board.cnt_bits = 0;
1347 dev->board.pwm_chans = 1;
1348 dev->board.pwm_bits = 10;
1352 if (dev->board.model == VMK8061_MODEL) {
1353 vmk80xx_read_eeprom(dev, IC3_VERSION);
1354 dev_info(&intf->dev, "%s\n", dev->fw.ic3_vers);
1356 if (vmk80xx_check_data_link(dev)) {
1357 vmk80xx_read_eeprom(dev, IC6_VERSION);
1358 dev_info(&intf->dev, "%s\n", dev->fw.ic6_vers);
1360 dbgcm("comedi#: vmk80xx: no conn. to CPU\n");
1364 if (dev->board.model == VMK8055_MODEL)
1365 vmk80xx_reset_device(dev);
1369 dev_info(&intf->dev, "board #%d [%s] now attached\n",
1370 dev->count, dev->board.name);
1372 mutex_unlock(&glb_mutex);
1374 comedi_usb_auto_config(intf, &vmk80xx_driver);
1378 mutex_unlock(&glb_mutex);
1383 static void vmk80xx_usb_disconnect(struct usb_interface *intf)
1385 struct vmk80xx_usb *dev = usb_get_intfdata(intf);
1390 comedi_usb_auto_unconfig(intf);
1392 mutex_lock(&glb_mutex);
1393 down(&dev->limit_sem);
1396 usb_set_intfdata(dev->intf, NULL);
1398 usb_kill_anchored_urbs(&dev->rx_anchor);
1399 usb_kill_anchored_urbs(&dev->tx_anchor);
1401 kfree(dev->usb_rx_buf);
1402 kfree(dev->usb_tx_buf);
1404 dev_info(&intf->dev, "board #%d [%s] now detached\n",
1405 dev->count, dev->board.name);
1407 up(&dev->limit_sem);
1408 mutex_unlock(&glb_mutex);
1411 static const struct usb_device_id vmk80xx_usb_id_table[] = {
1412 { USB_DEVICE(0x10cf, 0x5500), .driver_info = DEVICE_VMK8055 },
1413 { USB_DEVICE(0x10cf, 0x5501), .driver_info = DEVICE_VMK8055 },
1414 { USB_DEVICE(0x10cf, 0x5502), .driver_info = DEVICE_VMK8055 },
1415 { USB_DEVICE(0x10cf, 0x5503), .driver_info = DEVICE_VMK8055 },
1416 { USB_DEVICE(0x10cf, 0x8061), .driver_info = DEVICE_VMK8061 },
1417 { USB_DEVICE(0x10cf, 0x8062), .driver_info = DEVICE_VMK8061 },
1418 { USB_DEVICE(0x10cf, 0x8063), .driver_info = DEVICE_VMK8061 },
1419 { USB_DEVICE(0x10cf, 0x8064), .driver_info = DEVICE_VMK8061 },
1420 { USB_DEVICE(0x10cf, 0x8065), .driver_info = DEVICE_VMK8061 },
1421 { USB_DEVICE(0x10cf, 0x8066), .driver_info = DEVICE_VMK8061 },
1422 { USB_DEVICE(0x10cf, 0x8067), .driver_info = DEVICE_VMK8061 },
1423 { USB_DEVICE(0x10cf, 0x8068), .driver_info = DEVICE_VMK8061 },
1426 MODULE_DEVICE_TABLE(usb, vmk80xx_usb_id_table);
1428 /* TODO: Add support for suspend, resume, pre_reset,
1429 * post_reset and flush */
1430 static struct usb_driver vmk80xx_usb_driver = {
1432 .probe = vmk80xx_usb_probe,
1433 .disconnect = vmk80xx_usb_disconnect,
1434 .id_table = vmk80xx_usb_id_table,
1436 module_comedi_usb_driver(vmk80xx_driver, vmk80xx_usb_driver);
1438 MODULE_AUTHOR("Manuel Gebele <forensixs@gmx.de>");
1439 MODULE_DESCRIPTION("Velleman USB Board Low-Level Driver");
1440 MODULE_SUPPORTED_DEVICE("K8055/K8061 aka VM110/VM140");
1441 MODULE_VERSION("0.8.01");
1442 MODULE_LICENSE("GPL");