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"
67 MODULE_AUTHOR("Manuel Gebele <forensixs@gmx.de>");
68 MODULE_DESCRIPTION("Velleman USB Board Low-Level Driver");
69 MODULE_SUPPORTED_DEVICE("K8055/K8061 aka VM110/VM140");
70 MODULE_VERSION("0.8.01");
71 MODULE_LICENSE("GPL");
78 static const struct usb_device_id vmk80xx_id_table
[] = {
79 {USB_DEVICE(0x10cf, 0x5500), .driver_info
= DEVICE_VMK8055
},
80 {USB_DEVICE(0x10cf, 0x5501), .driver_info
= DEVICE_VMK8055
},
81 {USB_DEVICE(0x10cf, 0x5502), .driver_info
= DEVICE_VMK8055
},
82 {USB_DEVICE(0x10cf, 0x5503), .driver_info
= DEVICE_VMK8055
},
83 {USB_DEVICE(0x10cf, 0x8061), .driver_info
= DEVICE_VMK8061
},
84 {USB_DEVICE(0x10cf, 0x8062), .driver_info
= DEVICE_VMK8061
},
85 {USB_DEVICE(0x10cf, 0x8063), .driver_info
= DEVICE_VMK8061
},
86 {USB_DEVICE(0x10cf, 0x8064), .driver_info
= DEVICE_VMK8061
},
87 {USB_DEVICE(0x10cf, 0x8065), .driver_info
= DEVICE_VMK8061
},
88 {USB_DEVICE(0x10cf, 0x8066), .driver_info
= DEVICE_VMK8061
},
89 {USB_DEVICE(0x10cf, 0x8067), .driver_info
= DEVICE_VMK8061
},
90 {USB_DEVICE(0x10cf, 0x8068), .driver_info
= DEVICE_VMK8061
},
91 {} /* terminating entry */
94 MODULE_DEVICE_TABLE(usb
, vmk80xx_id_table
);
96 #define VMK8055_DI_REG 0x00
97 #define VMK8055_DO_REG 0x01
98 #define VMK8055_AO1_REG 0x02
99 #define VMK8055_AO2_REG 0x03
100 #define VMK8055_AI1_REG 0x02
101 #define VMK8055_AI2_REG 0x03
102 #define VMK8055_CNT1_REG 0x04
103 #define VMK8055_CNT2_REG 0x06
105 #define VMK8061_CH_REG 0x01
106 #define VMK8061_DI_REG 0x01
107 #define VMK8061_DO_REG 0x01
108 #define VMK8061_PWM_REG1 0x01
109 #define VMK8061_PWM_REG2 0x02
110 #define VMK8061_CNT_REG 0x02
111 #define VMK8061_AO_REG 0x02
112 #define VMK8061_AI_REG1 0x02
113 #define VMK8061_AI_REG2 0x03
115 #define VMK8055_CMD_RST 0x00
116 #define VMK8055_CMD_DEB1_TIME 0x01
117 #define VMK8055_CMD_DEB2_TIME 0x02
118 #define VMK8055_CMD_RST_CNT1 0x03
119 #define VMK8055_CMD_RST_CNT2 0x04
120 #define VMK8055_CMD_WRT_AD 0x05
122 #define VMK8061_CMD_RD_AI 0x00
123 #define VMK8061_CMR_RD_ALL_AI 0x01 /* !non-active! */
124 #define VMK8061_CMD_SET_AO 0x02
125 #define VMK8061_CMD_SET_ALL_AO 0x03 /* !non-active! */
126 #define VMK8061_CMD_OUT_PWM 0x04
127 #define VMK8061_CMD_RD_DI 0x05
128 #define VMK8061_CMD_DO 0x06 /* !non-active! */
129 #define VMK8061_CMD_CLR_DO 0x07
130 #define VMK8061_CMD_SET_DO 0x08
131 #define VMK8061_CMD_RD_CNT 0x09 /* TODO: completely pointless? */
132 #define VMK8061_CMD_RST_CNT 0x0a /* TODO: completely pointless? */
133 #define VMK8061_CMD_RD_VERSION 0x0b /* internal usage */
134 #define VMK8061_CMD_RD_JMP_STAT 0x0c /* TODO: not implemented yet */
135 #define VMK8061_CMD_RD_PWR_STAT 0x0d /* internal usage */
136 #define VMK8061_CMD_RD_DO 0x0e
137 #define VMK8061_CMD_RD_AO 0x0f
138 #define VMK8061_CMD_RD_PWM 0x10
140 #define VMK80XX_MAX_BOARDS COMEDI_NUM_BOARD_MINORS
142 #define TRANS_OUT_BUSY 1
143 #define TRANS_IN_BUSY 2
144 #define TRANS_IN_RUNNING 3
146 #define IC3_VERSION (1 << 0)
147 #define IC6_VERSION (1 << 1)
149 #define URB_RCV_FLAG (1 << 0)
150 #define URB_SND_FLAG (1 << 1)
152 #define CONFIG_VMK80XX_DEBUG
153 #undef CONFIG_VMK80XX_DEBUG
155 #ifdef CONFIG_VMK80XX_DEBUG
156 static int dbgvm
= 1;
161 #ifdef CONFIG_COMEDI_DEBUG
162 static int dbgcm
= 1;
167 #define dbgvm(fmt, arg...) \
170 printk(KERN_DEBUG fmt, ##arg); \
173 #define dbgcm(fmt, arg...) \
176 printk(KERN_DEBUG fmt, ##arg); \
184 struct firmware_version
{
185 unsigned char ic3_vers
[32]; /* USB-Controller */
186 unsigned char ic6_vers
[32]; /* CPU */
189 static const struct comedi_lrange vmk8055_range
= {
193 static const struct comedi_lrange vmk8061_range
= {
194 2, {UNI_RANGE(5), UNI_RANGE(10)}
197 struct vmk80xx_board
{
199 enum vmk80xx_model model
;
200 const struct comedi_lrange
*range
;
225 struct usb_device
*udev
;
226 struct usb_interface
*intf
;
227 struct usb_endpoint_descriptor
*ep_rx
;
228 struct usb_endpoint_descriptor
*ep_tx
;
229 struct usb_anchor rx_anchor
;
230 struct usb_anchor tx_anchor
;
231 struct vmk80xx_board board
;
232 struct firmware_version fw
;
233 struct semaphore limit_sem
;
234 wait_queue_head_t read_wait
;
235 wait_queue_head_t write_wait
;
236 unsigned char *usb_rx_buf
;
237 unsigned char *usb_tx_buf
;
244 static struct vmk80xx_usb vmb
[VMK80XX_MAX_BOARDS
];
246 static DEFINE_MUTEX(glb_mutex
);
248 static void vmk80xx_tx_callback(struct urb
*urb
)
250 struct vmk80xx_usb
*dev
= urb
->context
;
251 int stat
= urb
->status
;
253 dbgvm("vmk80xx: %s\n", __func__
);
255 if (stat
&& !(stat
== -ENOENT
256 || stat
== -ECONNRESET
|| stat
== -ESHUTDOWN
))
257 dbgcm("comedi#: vmk80xx: %s - nonzero urb status (%d)\n",
260 if (!test_bit(TRANS_OUT_BUSY
, &dev
->flags
))
263 clear_bit(TRANS_OUT_BUSY
, &dev
->flags
);
265 wake_up_interruptible(&dev
->write_wait
);
268 static void vmk80xx_rx_callback(struct urb
*urb
)
270 struct vmk80xx_usb
*dev
= urb
->context
;
271 int stat
= urb
->status
;
273 dbgvm("vmk80xx: %s\n", __func__
);
283 dbgcm("comedi#: vmk80xx: %s - nonzero urb status (%d)\n",
290 if (test_bit(TRANS_IN_RUNNING
, &dev
->flags
) && dev
->intf
) {
291 usb_anchor_urb(urb
, &dev
->rx_anchor
);
293 if (!usb_submit_urb(urb
, GFP_KERNEL
))
296 err("comedi#: vmk80xx: %s - submit urb failed\n", __func__
);
298 usb_unanchor_urb(urb
);
301 clear_bit(TRANS_IN_BUSY
, &dev
->flags
);
303 wake_up_interruptible(&dev
->read_wait
);
306 static int vmk80xx_check_data_link(struct vmk80xx_usb
*dev
)
308 unsigned int tx_pipe
, rx_pipe
;
309 unsigned char tx
[1], rx
[2];
311 dbgvm("vmk80xx: %s\n", __func__
);
313 tx_pipe
= usb_sndbulkpipe(dev
->udev
, 0x01);
314 rx_pipe
= usb_rcvbulkpipe(dev
->udev
, 0x81);
316 tx
[0] = VMK8061_CMD_RD_PWR_STAT
;
318 /* Check that IC6 (PIC16F871) is powered and
319 * running and the data link between IC3 and
320 * IC6 is working properly */
321 usb_bulk_msg(dev
->udev
, tx_pipe
, tx
, 1, NULL
, dev
->ep_tx
->bInterval
);
322 usb_bulk_msg(dev
->udev
, rx_pipe
, rx
, 2, NULL
, HZ
* 10);
327 static void vmk80xx_read_eeprom(struct vmk80xx_usb
*dev
, int flag
)
329 unsigned int tx_pipe
, rx_pipe
;
330 unsigned char tx
[1], rx
[64];
333 dbgvm("vmk80xx: %s\n", __func__
);
335 tx_pipe
= usb_sndbulkpipe(dev
->udev
, 0x01);
336 rx_pipe
= usb_rcvbulkpipe(dev
->udev
, 0x81);
338 tx
[0] = VMK8061_CMD_RD_VERSION
;
340 /* Read the firmware version info of IC3 and
341 * 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 dbgvm("vmk80xx: %s\n", __func__
);
362 urb
= usb_alloc_urb(0, GFP_KERNEL
);
366 tx_pipe
= usb_sndintpipe(dev
->udev
, 0x01);
368 ival
= dev
->ep_tx
->bInterval
;
369 size
= le16_to_cpu(dev
->ep_tx
->wMaxPacketSize
);
371 dev
->usb_tx_buf
[0] = VMK8055_CMD_RST
;
372 dev
->usb_tx_buf
[1] = 0x00;
373 dev
->usb_tx_buf
[2] = 0x00;
374 dev
->usb_tx_buf
[3] = 0x00;
375 dev
->usb_tx_buf
[4] = 0x00;
376 dev
->usb_tx_buf
[5] = 0x00;
377 dev
->usb_tx_buf
[6] = 0x00;
378 dev
->usb_tx_buf
[7] = 0x00;
380 usb_fill_int_urb(urb
, dev
->udev
, tx_pipe
, dev
->usb_tx_buf
,
381 size
, vmk80xx_tx_callback
, dev
, ival
);
383 usb_anchor_urb(urb
, &dev
->tx_anchor
);
385 return usb_submit_urb(urb
, GFP_KERNEL
);
388 static void vmk80xx_build_int_urb(struct urb
*urb
, int flag
)
390 struct vmk80xx_usb
*dev
= urb
->context
;
391 __u8 rx_addr
, tx_addr
;
395 void (*callback
) (struct urb
*);
398 dbgvm("vmk80xx: %s\n", __func__
);
400 if (flag
& URB_RCV_FLAG
) {
401 rx_addr
= dev
->ep_rx
->bEndpointAddress
;
402 pipe
= usb_rcvintpipe(dev
->udev
, rx_addr
);
403 buf
= dev
->usb_rx_buf
;
404 size
= le16_to_cpu(dev
->ep_rx
->wMaxPacketSize
);
405 callback
= vmk80xx_rx_callback
;
406 ival
= dev
->ep_rx
->bInterval
;
407 } else { /* URB_SND_FLAG */
408 tx_addr
= dev
->ep_tx
->bEndpointAddress
;
409 pipe
= usb_sndintpipe(dev
->udev
, tx_addr
);
410 buf
= dev
->usb_tx_buf
;
411 size
= le16_to_cpu(dev
->ep_tx
->wMaxPacketSize
);
412 callback
= vmk80xx_tx_callback
;
413 ival
= dev
->ep_tx
->bInterval
;
416 usb_fill_int_urb(urb
, dev
->udev
, pipe
, buf
, size
, callback
, dev
, ival
);
419 static void vmk80xx_do_bulk_msg(struct vmk80xx_usb
*dev
)
421 __u8 tx_addr
, rx_addr
;
422 unsigned int tx_pipe
, rx_pipe
;
425 dbgvm("vmk80xx: %s\n", __func__
);
427 set_bit(TRANS_IN_BUSY
, &dev
->flags
);
428 set_bit(TRANS_OUT_BUSY
, &dev
->flags
);
430 tx_addr
= dev
->ep_tx
->bEndpointAddress
;
431 rx_addr
= dev
->ep_rx
->bEndpointAddress
;
432 tx_pipe
= usb_sndbulkpipe(dev
->udev
, tx_addr
);
433 rx_pipe
= usb_rcvbulkpipe(dev
->udev
, rx_addr
);
435 /* The max packet size attributes of the K8061
436 * input/output endpoints are identical */
437 size
= le16_to_cpu(dev
->ep_tx
->wMaxPacketSize
);
439 usb_bulk_msg(dev
->udev
, tx_pipe
, dev
->usb_tx_buf
,
440 size
, NULL
, dev
->ep_tx
->bInterval
);
441 usb_bulk_msg(dev
->udev
, rx_pipe
, dev
->usb_rx_buf
, size
, NULL
, HZ
* 10);
443 clear_bit(TRANS_OUT_BUSY
, &dev
->flags
);
444 clear_bit(TRANS_IN_BUSY
, &dev
->flags
);
447 static int vmk80xx_read_packet(struct vmk80xx_usb
*dev
)
452 dbgvm("vmk80xx: %s\n", __func__
);
457 /* Only useful for interrupt transfers */
458 if (test_bit(TRANS_IN_BUSY
, &dev
->flags
))
459 if (wait_event_interruptible(dev
->read_wait
,
460 !test_bit(TRANS_IN_BUSY
,
464 if (dev
->board
.model
== VMK8061_MODEL
) {
465 vmk80xx_do_bulk_msg(dev
);
470 urb
= usb_alloc_urb(0, GFP_KERNEL
);
475 vmk80xx_build_int_urb(urb
, URB_RCV_FLAG
);
477 set_bit(TRANS_IN_RUNNING
, &dev
->flags
);
478 set_bit(TRANS_IN_BUSY
, &dev
->flags
);
480 usb_anchor_urb(urb
, &dev
->rx_anchor
);
482 retval
= usb_submit_urb(urb
, GFP_KERNEL
);
486 clear_bit(TRANS_IN_RUNNING
, &dev
->flags
);
487 usb_unanchor_urb(urb
);
495 static int vmk80xx_write_packet(struct vmk80xx_usb
*dev
, int cmd
)
500 dbgvm("vmk80xx: %s\n", __func__
);
505 if (test_bit(TRANS_OUT_BUSY
, &dev
->flags
))
506 if (wait_event_interruptible(dev
->write_wait
,
507 !test_bit(TRANS_OUT_BUSY
,
511 if (dev
->board
.model
== VMK8061_MODEL
) {
512 dev
->usb_tx_buf
[0] = cmd
;
513 vmk80xx_do_bulk_msg(dev
);
518 urb
= usb_alloc_urb(0, GFP_KERNEL
);
523 vmk80xx_build_int_urb(urb
, URB_SND_FLAG
);
525 set_bit(TRANS_OUT_BUSY
, &dev
->flags
);
527 usb_anchor_urb(urb
, &dev
->tx_anchor
);
529 dev
->usb_tx_buf
[0] = cmd
;
531 retval
= usb_submit_urb(urb
, GFP_KERNEL
);
535 clear_bit(TRANS_OUT_BUSY
, &dev
->flags
);
536 usb_unanchor_urb(urb
);
547 #define rudimentary_check(dir) \
553 if (!dev->attached) \
555 if ((dir) & DIR_IN) { \
556 if (test_bit(TRANS_IN_BUSY, &dev->flags)) \
558 } else { /* DIR_OUT */ \
559 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 struct vmk80xx_usb
*dev
= cdev
->private;
572 dbgvm("vmk80xx: %s\n", __func__
);
574 rudimentary_check(DIR_IN
);
576 down(&dev
->limit_sem
);
577 chan
= CR_CHAN(insn
->chanspec
);
579 switch (dev
->board
.model
) {
582 reg
[0] = VMK8055_AI1_REG
;
584 reg
[0] = VMK8055_AI2_REG
;
587 reg
[0] = VMK8061_AI_REG1
;
588 reg
[1] = VMK8061_AI_REG2
;
589 dev
->usb_tx_buf
[0] = VMK8061_CMD_RD_AI
;
590 dev
->usb_tx_buf
[VMK8061_CH_REG
] = chan
;
594 for (n
= 0; n
< insn
->n
; n
++) {
595 if (vmk80xx_read_packet(dev
))
598 if (dev
->board
.model
== VMK8055_MODEL
) {
599 data
[n
] = dev
->usb_rx_buf
[reg
[0]];
604 data
[n
] = dev
->usb_rx_buf
[reg
[0]] + 256 *
605 dev
->usb_rx_buf
[reg
[1]];
613 static int vmk80xx_ao_winsn(struct comedi_device
*cdev
,
614 struct comedi_subdevice
*s
,
615 struct comedi_insn
*insn
, unsigned int *data
)
617 struct vmk80xx_usb
*dev
= cdev
->private;
621 dbgvm("vmk80xx: %s\n", __func__
);
623 rudimentary_check(DIR_OUT
);
625 down(&dev
->limit_sem
);
626 chan
= CR_CHAN(insn
->chanspec
);
628 switch (dev
->board
.model
) {
630 cmd
= VMK8055_CMD_WRT_AD
;
632 reg
= VMK8055_AO1_REG
;
634 reg
= VMK8055_AO2_REG
;
636 default: /* NOTE: avoid compiler warnings */
637 cmd
= VMK8061_CMD_SET_AO
;
638 reg
= VMK8061_AO_REG
;
639 dev
->usb_tx_buf
[VMK8061_CH_REG
] = chan
;
643 for (n
= 0; n
< insn
->n
; n
++) {
644 dev
->usb_tx_buf
[reg
] = data
[n
];
646 if (vmk80xx_write_packet(dev
, cmd
))
655 static int vmk80xx_ao_rinsn(struct comedi_device
*cdev
,
656 struct comedi_subdevice
*s
,
657 struct comedi_insn
*insn
, unsigned int *data
)
659 struct vmk80xx_usb
*dev
= cdev
->private;
663 dbgvm("vmk80xx: %s\n", __func__
);
665 rudimentary_check(DIR_IN
);
667 down(&dev
->limit_sem
);
668 chan
= CR_CHAN(insn
->chanspec
);
670 reg
= VMK8061_AO_REG
- 1;
672 dev
->usb_tx_buf
[0] = VMK8061_CMD_RD_AO
;
674 for (n
= 0; n
< insn
->n
; n
++) {
675 if (vmk80xx_read_packet(dev
))
678 data
[n
] = dev
->usb_rx_buf
[reg
+ chan
];
686 static int vmk80xx_di_rinsn(struct comedi_device
*cdev
,
687 struct comedi_subdevice
*s
,
688 struct comedi_insn
*insn
, unsigned int *data
)
690 struct vmk80xx_usb
*dev
= cdev
->private;
692 unsigned char *rx_buf
;
696 dbgvm("vmk80xx: %s\n", __func__
);
698 rudimentary_check(DIR_IN
);
700 down(&dev
->limit_sem
);
701 chan
= CR_CHAN(insn
->chanspec
);
703 rx_buf
= dev
->usb_rx_buf
;
705 if (dev
->board
.model
== VMK8061_MODEL
) {
706 reg
= VMK8061_DI_REG
;
707 dev
->usb_tx_buf
[0] = VMK8061_CMD_RD_DI
;
709 reg
= VMK8055_DI_REG
;
711 for (n
= 0; n
< insn
->n
; n
++) {
712 if (vmk80xx_read_packet(dev
))
715 if (dev
->board
.model
== VMK8055_MODEL
)
716 inp
= (((rx_buf
[reg
] >> 4) & 0x03) |
717 ((rx_buf
[reg
] << 2) & 0x04) |
718 ((rx_buf
[reg
] >> 3) & 0x18));
722 data
[n
] = ((inp
& (1 << chan
)) > 0);
730 static int vmk80xx_do_winsn(struct comedi_device
*cdev
,
731 struct comedi_subdevice
*s
,
732 struct comedi_insn
*insn
, unsigned int *data
)
735 struct vmk80xx_usb
*dev
= cdev
->private;
737 unsigned char *tx_buf
;
741 dbgvm("vmk80xx: %s\n", __func__
);
743 rudimentary_check(DIR_OUT
);
745 down(&dev
->limit_sem
);
746 chan
= CR_CHAN(insn
->chanspec
);
748 tx_buf
= dev
->usb_tx_buf
;
750 for (n
= 0; n
< insn
->n
; n
++) {
751 if (dev
->board
.model
== VMK8055_MODEL
) {
752 reg
= VMK8055_DO_REG
;
753 cmd
= VMK8055_CMD_WRT_AD
;
755 tx_buf
[reg
] |= (1 << chan
);
757 tx_buf
[reg
] ^= (1 << chan
);
763 reg
= VMK8061_DO_REG
;
765 cmd
= VMK8061_CMD_SET_DO
;
766 tx_buf
[reg
] = 1 << chan
;
768 cmd
= VMK8061_CMD_CLR_DO
;
769 tx_buf
[reg
] = 0xff - (1 << chan
);
773 if (vmk80xx_write_packet(dev
, cmd
))
782 static int vmk80xx_do_rinsn(struct comedi_device
*cdev
,
783 struct comedi_subdevice
*s
,
784 struct comedi_insn
*insn
, unsigned int *data
)
786 struct vmk80xx_usb
*dev
= cdev
->private;
790 dbgvm("vmk80xx: %s\n", __func__
);
792 rudimentary_check(DIR_IN
);
794 down(&dev
->limit_sem
);
795 chan
= CR_CHAN(insn
->chanspec
);
797 reg
= VMK8061_DO_REG
;
800 dev
->usb_tx_buf
[0] = VMK8061_CMD_RD_DO
;
802 for (n
= 0; n
< insn
->n
; n
++) {
803 if (vmk80xx_read_packet(dev
))
806 data
[n
] = (dev
->usb_rx_buf
[reg
] & mask
) >> chan
;
814 static int vmk80xx_cnt_rinsn(struct comedi_device
*cdev
,
815 struct comedi_subdevice
*s
,
816 struct comedi_insn
*insn
, unsigned int *data
)
818 struct vmk80xx_usb
*dev
= cdev
->private;
822 dbgvm("vmk80xx: %s\n", __func__
);
824 rudimentary_check(DIR_IN
);
826 down(&dev
->limit_sem
);
827 chan
= CR_CHAN(insn
->chanspec
);
829 switch (dev
->board
.model
) {
832 reg
[0] = VMK8055_CNT1_REG
;
834 reg
[0] = VMK8055_CNT2_REG
;
837 reg
[0] = VMK8061_CNT_REG
;
838 reg
[1] = VMK8061_CNT_REG
;
839 dev
->usb_tx_buf
[0] = VMK8061_CMD_RD_CNT
;
843 for (n
= 0; n
< insn
->n
; n
++) {
844 if (vmk80xx_read_packet(dev
))
847 if (dev
->board
.model
== VMK8055_MODEL
) {
848 data
[n
] = dev
->usb_rx_buf
[reg
[0]];
853 data
[n
] = dev
->usb_rx_buf
[reg
[0] * (chan
+ 1) + 1]
854 + 256 * dev
->usb_rx_buf
[reg
[1] * 2 + 2];
862 static int vmk80xx_cnt_cinsn(struct comedi_device
*cdev
,
863 struct comedi_subdevice
*s
,
864 struct comedi_insn
*insn
, unsigned int *data
)
866 struct vmk80xx_usb
*dev
= cdev
->private;
867 unsigned int insn_cmd
;
871 dbgvm("vmk80xx: %s\n", __func__
);
873 rudimentary_check(DIR_OUT
);
875 down(&dev
->limit_sem
);
878 if (insn_cmd
!= INSN_CONFIG_RESET
&& insn_cmd
!= GPCT_RESET
)
881 chan
= CR_CHAN(insn
->chanspec
);
883 if (dev
->board
.model
== VMK8055_MODEL
) {
885 cmd
= VMK8055_CMD_RST_CNT1
;
886 reg
= VMK8055_CNT1_REG
;
888 cmd
= VMK8055_CMD_RST_CNT2
;
889 reg
= VMK8055_CNT2_REG
;
892 dev
->usb_tx_buf
[reg
] = 0x00;
894 cmd
= VMK8061_CMD_RST_CNT
;
896 for (n
= 0; n
< insn
->n
; n
++)
897 if (vmk80xx_write_packet(dev
, cmd
))
905 static int vmk80xx_cnt_winsn(struct comedi_device
*cdev
,
906 struct comedi_subdevice
*s
,
907 struct comedi_insn
*insn
, unsigned int *data
)
909 struct vmk80xx_usb
*dev
= cdev
->private;
910 unsigned long debtime
, val
;
914 dbgvm("vmk80xx: %s\n", __func__
);
916 rudimentary_check(DIR_OUT
);
918 down(&dev
->limit_sem
);
919 chan
= CR_CHAN(insn
->chanspec
);
922 cmd
= VMK8055_CMD_DEB1_TIME
;
924 cmd
= VMK8055_CMD_DEB2_TIME
;
926 for (n
= 0; n
< insn
->n
; n
++) {
931 /* TODO: Prevent overflows */
935 val
= int_sqrt(debtime
* 1000 / 115);
936 if (((val
+ 1) * val
) < debtime
* 1000 / 115)
939 dev
->usb_tx_buf
[6 + chan
] = val
;
941 if (vmk80xx_write_packet(dev
, cmd
))
950 static int vmk80xx_pwm_rinsn(struct comedi_device
*cdev
,
951 struct comedi_subdevice
*s
,
952 struct comedi_insn
*insn
, unsigned int *data
)
954 struct vmk80xx_usb
*dev
= cdev
->private;
958 dbgvm("vmk80xx: %s\n", __func__
);
960 rudimentary_check(DIR_IN
);
962 down(&dev
->limit_sem
);
964 reg
[0] = VMK8061_PWM_REG1
;
965 reg
[1] = VMK8061_PWM_REG2
;
967 dev
->usb_tx_buf
[0] = VMK8061_CMD_RD_PWM
;
969 for (n
= 0; n
< insn
->n
; n
++) {
970 if (vmk80xx_read_packet(dev
))
973 data
[n
] = dev
->usb_rx_buf
[reg
[0]] + 4 * dev
->usb_rx_buf
[reg
[1]];
981 static int vmk80xx_pwm_winsn(struct comedi_device
*cdev
,
982 struct comedi_subdevice
*s
,
983 struct comedi_insn
*insn
, unsigned int *data
)
985 struct vmk80xx_usb
*dev
= cdev
->private;
986 unsigned char *tx_buf
;
990 dbgvm("vmk80xx: %s\n", __func__
);
992 rudimentary_check(DIR_OUT
);
994 down(&dev
->limit_sem
);
996 tx_buf
= dev
->usb_tx_buf
;
998 reg
[0] = VMK8061_PWM_REG1
;
999 reg
[1] = VMK8061_PWM_REG2
;
1001 cmd
= VMK8061_CMD_OUT_PWM
;
1004 * The followin piece of code was translated from the inline
1005 * assembler code in the DLL source code.
1008 * mov eax, k ; k is the value (data[n])
1009 * and al, 03h ; al are the lower 8 bits of eax
1010 * mov lo, al ; lo is the low part (tx_buf[reg[0]])
1012 * shr eax, 2 ; right shift eax register by 2
1013 * mov hi, al ; hi is the high part (tx_buf[reg[1]])
1016 for (n
= 0; n
< insn
->n
; n
++) {
1017 tx_buf
[reg
[0]] = (unsigned char)(data
[n
] & 0x03);
1018 tx_buf
[reg
[1]] = (unsigned char)(data
[n
] >> 2) & 0xff;
1020 if (vmk80xx_write_packet(dev
, cmd
))
1024 up(&dev
->limit_sem
);
1030 vmk80xx_attach(struct comedi_device
*cdev
, struct comedi_devconfig
*it
)
1033 struct vmk80xx_usb
*dev
;
1035 struct comedi_subdevice
*s
;
1038 dbgvm("vmk80xx: %s\n", __func__
);
1040 mutex_lock(&glb_mutex
);
1042 for (i
= 0; i
< VMK80XX_MAX_BOARDS
; i
++)
1043 if (vmb
[i
].probed
&& !vmb
[i
].attached
)
1046 if (i
== VMK80XX_MAX_BOARDS
) {
1047 mutex_unlock(&glb_mutex
);
1053 down(&dev
->limit_sem
);
1055 cdev
->board_name
= dev
->board
.name
;
1056 cdev
->private = dev
;
1058 if (dev
->board
.model
== VMK8055_MODEL
)
1063 if (alloc_subdevices(cdev
, n_subd
) < 0) {
1064 up(&dev
->limit_sem
);
1065 mutex_unlock(&glb_mutex
);
1069 /* Analog input subdevice */
1070 s
= cdev
->subdevices
+ VMK80XX_SUBD_AI
;
1071 s
->type
= COMEDI_SUBD_AI
;
1072 s
->subdev_flags
= SDF_READABLE
| SDF_GROUND
;
1073 s
->n_chan
= dev
->board
.ai_chans
;
1074 s
->maxdata
= (1 << dev
->board
.ai_bits
) - 1;
1075 s
->range_table
= dev
->board
.range
;
1076 s
->insn_read
= vmk80xx_ai_rinsn
;
1078 /* Analog output subdevice */
1079 s
= cdev
->subdevices
+ VMK80XX_SUBD_AO
;
1080 s
->type
= COMEDI_SUBD_AO
;
1081 s
->subdev_flags
= SDF_WRITEABLE
| SDF_GROUND
;
1082 s
->n_chan
= dev
->board
.ao_chans
;
1083 s
->maxdata
= (1 << dev
->board
.ao_bits
) - 1;
1084 s
->range_table
= dev
->board
.range
;
1085 s
->insn_write
= vmk80xx_ao_winsn
;
1087 if (dev
->board
.model
== VMK8061_MODEL
) {
1088 s
->subdev_flags
|= SDF_READABLE
;
1089 s
->insn_read
= vmk80xx_ao_rinsn
;
1092 /* Digital input subdevice */
1093 s
= cdev
->subdevices
+ VMK80XX_SUBD_DI
;
1094 s
->type
= COMEDI_SUBD_DI
;
1095 s
->subdev_flags
= SDF_READABLE
| SDF_GROUND
;
1096 s
->n_chan
= dev
->board
.di_chans
;
1097 s
->maxdata
= (1 << dev
->board
.di_bits
) - 1;
1098 s
->insn_read
= vmk80xx_di_rinsn
;
1100 /* Digital output subdevice */
1101 s
= cdev
->subdevices
+ VMK80XX_SUBD_DO
;
1102 s
->type
= COMEDI_SUBD_DO
;
1103 s
->subdev_flags
= SDF_WRITEABLE
| SDF_GROUND
;
1104 s
->n_chan
= dev
->board
.do_chans
;
1105 s
->maxdata
= (1 << dev
->board
.do_bits
) - 1;
1106 s
->insn_write
= vmk80xx_do_winsn
;
1108 if (dev
->board
.model
== VMK8061_MODEL
) {
1109 s
->subdev_flags
|= SDF_READABLE
;
1110 s
->insn_read
= vmk80xx_do_rinsn
;
1113 /* Counter subdevice */
1114 s
= cdev
->subdevices
+ VMK80XX_SUBD_CNT
;
1115 s
->type
= COMEDI_SUBD_COUNTER
;
1116 s
->subdev_flags
= SDF_READABLE
;
1117 s
->n_chan
= dev
->board
.cnt_chans
;
1118 s
->insn_read
= vmk80xx_cnt_rinsn
;
1119 s
->insn_config
= vmk80xx_cnt_cinsn
;
1121 if (dev
->board
.model
== VMK8055_MODEL
) {
1122 s
->subdev_flags
|= SDF_WRITEABLE
;
1123 s
->maxdata
= (1 << dev
->board
.cnt_bits
) - 1;
1124 s
->insn_write
= vmk80xx_cnt_winsn
;
1128 if (dev
->board
.model
== VMK8061_MODEL
) {
1129 s
= cdev
->subdevices
+ VMK80XX_SUBD_PWM
;
1130 s
->type
= COMEDI_SUBD_PWM
;
1131 s
->subdev_flags
= SDF_READABLE
| SDF_WRITEABLE
;
1132 s
->n_chan
= dev
->board
.pwm_chans
;
1133 s
->maxdata
= (1 << dev
->board
.pwm_bits
) - 1;
1134 s
->insn_read
= vmk80xx_pwm_rinsn
;
1135 s
->insn_write
= vmk80xx_pwm_winsn
;
1140 minor
= cdev
->minor
;
1143 "comedi%d: vmk80xx: board #%d [%s] attached to comedi\n",
1144 minor
, dev
->count
, dev
->board
.name
);
1146 up(&dev
->limit_sem
);
1147 mutex_unlock(&glb_mutex
);
1152 static int vmk80xx_detach(struct comedi_device
*cdev
)
1154 struct vmk80xx_usb
*dev
;
1157 dbgvm("vmk80xx: %s\n", __func__
);
1162 dev
= cdev
->private;
1166 down(&dev
->limit_sem
);
1168 cdev
->private = NULL
;
1171 minor
= cdev
->minor
;
1174 "comedi%d: vmk80xx: board #%d [%s] detached from comedi\n",
1175 minor
, dev
->count
, dev
->board
.name
);
1177 up(&dev
->limit_sem
);
1183 vmk80xx_probe(struct usb_interface
*intf
, const struct usb_device_id
*id
)
1186 struct vmk80xx_usb
*dev
;
1187 struct usb_host_interface
*iface_desc
;
1188 struct usb_endpoint_descriptor
*ep_desc
;
1191 dbgvm("vmk80xx: %s\n", __func__
);
1193 mutex_lock(&glb_mutex
);
1195 for (i
= 0; i
< VMK80XX_MAX_BOARDS
; i
++)
1199 if (i
== VMK80XX_MAX_BOARDS
) {
1200 mutex_unlock(&glb_mutex
);
1206 memset(dev
, 0x00, sizeof(struct vmk80xx_usb
));
1209 iface_desc
= intf
->cur_altsetting
;
1210 if (iface_desc
->desc
.bNumEndpoints
!= 2)
1213 for (i
= 0; i
< iface_desc
->desc
.bNumEndpoints
; i
++) {
1214 ep_desc
= &iface_desc
->endpoint
[i
].desc
;
1216 if (usb_endpoint_is_int_in(ep_desc
)) {
1217 dev
->ep_rx
= ep_desc
;
1221 if (usb_endpoint_is_int_out(ep_desc
)) {
1222 dev
->ep_tx
= ep_desc
;
1226 if (usb_endpoint_is_bulk_in(ep_desc
)) {
1227 dev
->ep_rx
= ep_desc
;
1231 if (usb_endpoint_is_bulk_out(ep_desc
)) {
1232 dev
->ep_tx
= ep_desc
;
1237 if (!dev
->ep_rx
|| !dev
->ep_tx
)
1240 size
= le16_to_cpu(dev
->ep_rx
->wMaxPacketSize
);
1241 dev
->usb_rx_buf
= kmalloc(size
, GFP_KERNEL
);
1242 if (!dev
->usb_rx_buf
) {
1243 mutex_unlock(&glb_mutex
);
1247 size
= le16_to_cpu(dev
->ep_tx
->wMaxPacketSize
);
1248 dev
->usb_tx_buf
= kmalloc(size
, GFP_KERNEL
);
1249 if (!dev
->usb_tx_buf
) {
1250 kfree(dev
->usb_rx_buf
);
1251 mutex_unlock(&glb_mutex
);
1255 dev
->udev
= interface_to_usbdev(intf
);
1258 sema_init(&dev
->limit_sem
, 8);
1259 init_waitqueue_head(&dev
->read_wait
);
1260 init_waitqueue_head(&dev
->write_wait
);
1262 init_usb_anchor(&dev
->rx_anchor
);
1263 init_usb_anchor(&dev
->tx_anchor
);
1265 usb_set_intfdata(intf
, dev
);
1267 switch (id
->driver_info
) {
1268 case DEVICE_VMK8055
:
1269 dev
->board
.name
= "K8055 (VM110)";
1270 dev
->board
.model
= VMK8055_MODEL
;
1271 dev
->board
.range
= &vmk8055_range
;
1272 dev
->board
.ai_chans
= 2;
1273 dev
->board
.ai_bits
= 8;
1274 dev
->board
.ao_chans
= 2;
1275 dev
->board
.ao_bits
= 8;
1276 dev
->board
.di_chans
= 5;
1277 dev
->board
.di_bits
= 1;
1278 dev
->board
.do_chans
= 8;
1279 dev
->board
.do_bits
= 1;
1280 dev
->board
.cnt_chans
= 2;
1281 dev
->board
.cnt_bits
= 16;
1282 dev
->board
.pwm_chans
= 0;
1283 dev
->board
.pwm_bits
= 0;
1285 case DEVICE_VMK8061
:
1286 dev
->board
.name
= "K8061 (VM140)";
1287 dev
->board
.model
= VMK8061_MODEL
;
1288 dev
->board
.range
= &vmk8061_range
;
1289 dev
->board
.ai_chans
= 8;
1290 dev
->board
.ai_bits
= 10;
1291 dev
->board
.ao_chans
= 8;
1292 dev
->board
.ao_bits
= 8;
1293 dev
->board
.di_chans
= 8;
1294 dev
->board
.di_bits
= 1;
1295 dev
->board
.do_chans
= 8;
1296 dev
->board
.do_bits
= 1;
1297 dev
->board
.cnt_chans
= 2;
1298 dev
->board
.cnt_bits
= 0;
1299 dev
->board
.pwm_chans
= 1;
1300 dev
->board
.pwm_bits
= 10;
1304 if (dev
->board
.model
== VMK8061_MODEL
) {
1305 vmk80xx_read_eeprom(dev
, IC3_VERSION
);
1306 printk(KERN_INFO
"comedi#: vmk80xx: %s\n", dev
->fw
.ic3_vers
);
1308 if (vmk80xx_check_data_link(dev
)) {
1309 vmk80xx_read_eeprom(dev
, IC6_VERSION
);
1310 printk(KERN_INFO
"comedi#: vmk80xx: %s\n",
1313 dbgcm("comedi#: vmk80xx: no conn. to CPU\n");
1316 if (dev
->board
.model
== VMK8055_MODEL
)
1317 vmk80xx_reset_device(dev
);
1321 printk(KERN_INFO
"comedi#: vmk80xx: board #%d [%s] now attached\n",
1322 dev
->count
, dev
->board
.name
);
1324 mutex_unlock(&glb_mutex
);
1328 mutex_unlock(&glb_mutex
);
1333 static void vmk80xx_disconnect(struct usb_interface
*intf
)
1335 struct vmk80xx_usb
*dev
= usb_get_intfdata(intf
);
1337 dbgvm("vmk80xx: %s\n", __func__
);
1342 mutex_lock(&glb_mutex
);
1343 down(&dev
->limit_sem
);
1346 usb_set_intfdata(dev
->intf
, NULL
);
1348 usb_kill_anchored_urbs(&dev
->rx_anchor
);
1349 usb_kill_anchored_urbs(&dev
->tx_anchor
);
1351 kfree(dev
->usb_rx_buf
);
1352 kfree(dev
->usb_tx_buf
);
1354 printk(KERN_INFO
"comedi#: vmk80xx: board #%d [%s] now detached\n",
1355 dev
->count
, dev
->board
.name
);
1357 up(&dev
->limit_sem
);
1358 mutex_unlock(&glb_mutex
);
1361 /* TODO: Add support for suspend, resume, pre_reset,
1362 * post_reset and flush */
1363 static struct usb_driver vmk80xx_driver
= {
1365 .probe
= vmk80xx_probe
,
1366 .disconnect
= vmk80xx_disconnect
,
1367 .id_table
= vmk80xx_id_table
1370 static struct comedi_driver driver_vmk80xx
= {
1371 .module
= THIS_MODULE
,
1372 .driver_name
= "vmk80xx",
1373 .attach
= vmk80xx_attach
,
1374 .detach
= vmk80xx_detach
1377 static int __init
vmk80xx_init(void)
1379 printk(KERN_INFO
"vmk80xx: version 0.8.01 "
1380 "Manuel Gebele <forensixs@gmx.de>\n");
1381 usb_register(&vmk80xx_driver
);
1382 return comedi_driver_register(&driver_vmk80xx
);
1385 static void __exit
vmk80xx_exit(void)
1387 comedi_driver_unregister(&driver_vmk80xx
);
1388 usb_deregister(&vmk80xx_driver
);
1391 module_init(vmk80xx_init
);
1392 module_exit(vmk80xx_exit
);