Version:  2.6.24 2.6.25 2.6.26 2.6.27 2.6.28 2.6.29 2.6.30 2.6.31 2.6.32 2.6.33 2.6.34

Architecture:  x86 arm avr32 blackfin m68k m68knommu microblaze mips powerpc sh

Linux/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 Changelog:
 43 
 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
 48 
 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
 53 */
 54 
 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>
 64 
 65 #include "../comedidev.h"
 66 
 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");
 72 
 73 enum {
 74         DEVICE_VMK8055,
 75         DEVICE_VMK8061
 76 };
 77 
 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 */
 92 };
 93 
 94 MODULE_DEVICE_TABLE(usb, vmk80xx_id_table);
 95 
 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
104 
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
114 
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
121 
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
139 
140 #define VMK80XX_MAX_BOARDS      COMEDI_NUM_BOARD_MINORS
141 
142 #define TRANS_OUT_BUSY          1
143 #define TRANS_IN_BUSY           2
144 #define TRANS_IN_RUNNING        3
145 
146 #define IC3_VERSION             (1 << 0)
147 #define IC6_VERSION             (1 << 1)
148 
149 #define URB_RCV_FLAG            (1 << 0)
150 #define URB_SND_FLAG            (1 << 1)
151 
152 #define CONFIG_VMK80XX_DEBUG
153 #undef CONFIG_VMK80XX_DEBUG
154 
155 #ifdef CONFIG_VMK80XX_DEBUG
156 static int dbgvm = 1;
157 #else
158 static int dbgvm;
159 #endif
160 
161 #ifdef CONFIG_COMEDI_DEBUG
162 static int dbgcm = 1;
163 #else
164 static int dbgcm;
165 #endif
166 
167 #define dbgvm(fmt, arg...)                     \
168 do {                                           \
169         if (dbgvm)                             \
170                 printk(KERN_DEBUG fmt, ##arg); \
171 } while (0)
172 
173 #define dbgcm(fmt, arg...)                     \
174 do {                                           \
175         if (dbgcm)                             \
176                 printk(KERN_DEBUG fmt, ##arg); \
177 } while (0)
178 
179 enum vmk80xx_model {
180         VMK8055_MODEL,
181         VMK8061_MODEL
182 };
183 
184 struct firmware_version {
185         unsigned char ic3_vers[32];     /* USB-Controller */
186         unsigned char ic6_vers[32];     /* CPU */
187 };
188 
189 static const struct comedi_lrange vmk8055_range = {
190         1, {UNI_RANGE(5)}
191 };
192 
193 static const struct comedi_lrange vmk8061_range = {
194         2, {UNI_RANGE(5), UNI_RANGE(10)}
195 };
196 
197 struct vmk80xx_board {
198         const char *name;
199         enum vmk80xx_model model;
200         const struct comedi_lrange *range;
201         __u8 ai_chans;
202         __le16 ai_bits;
203         __u8 ao_chans;
204         __le16 ao_bits;
205         __u8 di_chans;
206         __le16 di_bits;
207         __u8 do_chans;
208         __le16 do_bits;
209         __u8 cnt_chans;
210         __le16 cnt_bits;
211         __u8 pwm_chans;
212         __le16 pwm_bits;
213 };
214 
215 enum {
216         VMK80XX_SUBD_AI,
217         VMK80XX_SUBD_AO,
218         VMK80XX_SUBD_DI,
219         VMK80XX_SUBD_DO,
220         VMK80XX_SUBD_CNT,
221         VMK80XX_SUBD_PWM,
222 };
223 
224 struct vmk80xx_usb {
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;
238         unsigned long flags;
239         int probed;
240         int attached;
241         int count;
242 };
243 
244 static struct vmk80xx_usb vmb[VMK80XX_MAX_BOARDS];
245 
246 static DEFINE_MUTEX(glb_mutex);
247 
248 static void vmk80xx_tx_callback(struct urb *urb)
249 {
250         struct vmk80xx_usb *dev = urb->context;
251         int stat = urb->status;
252 
253         dbgvm("vmk80xx: %s\n", __func__);
254 
255         if (stat && !(stat == -ENOENT
256                       || stat == -ECONNRESET || stat == -ESHUTDOWN))
257                 dbgcm("comedi#: vmk80xx: %s - nonzero urb status (%d)\n",
258                       __func__, stat);
259 
260         if (!test_bit(TRANS_OUT_BUSY, &dev->flags))
261                 return;
262 
263         clear_bit(TRANS_OUT_BUSY, &dev->flags);
264 
265         wake_up_interruptible(&dev->write_wait);
266 }
267 
268 static void vmk80xx_rx_callback(struct urb *urb)
269 {
270         struct vmk80xx_usb *dev = urb->context;
271         int stat = urb->status;
272 
273         dbgvm("vmk80xx: %s\n", __func__);
274 
275         switch (stat) {
276         case 0:
277                 break;
278         case -ENOENT:
279         case -ECONNRESET:
280         case -ESHUTDOWN:
281                 break;
282         default:
283                 dbgcm("comedi#: vmk80xx: %s - nonzero urb status (%d)\n",
284                       __func__, stat);
285                 goto resubmit;
286         }
287 
288         goto exit;
289 resubmit:
290         if (test_bit(TRANS_IN_RUNNING, &dev->flags) && dev->intf) {
291                 usb_anchor_urb(urb, &dev->rx_anchor);
292 
293                 if (!usb_submit_urb(urb, GFP_KERNEL))
294                         goto exit;
295 
296                 err("comedi#: vmk80xx: %s - submit urb failed\n", __func__);
297 
298                 usb_unanchor_urb(urb);
299         }
300 exit:
301         clear_bit(TRANS_IN_BUSY, &dev->flags);
302 
303         wake_up_interruptible(&dev->read_wait);
304 }
305 
306 static int vmk80xx_check_data_link(struct vmk80xx_usb *dev)
307 {
308         unsigned int tx_pipe, rx_pipe;
309         unsigned char tx[1], rx[2];
310 
311         dbgvm("vmk80xx: %s\n", __func__);
312 
313         tx_pipe = usb_sndbulkpipe(dev->udev, 0x01);
314         rx_pipe = usb_rcvbulkpipe(dev->udev, 0x81);
315 
316         tx[0] = VMK8061_CMD_RD_PWR_STAT;
317 
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);
323 
324         return (int)rx[1];
325 }
326 
327 static void vmk80xx_read_eeprom(struct vmk80xx_usb *dev, int flag)
328 {
329         unsigned int tx_pipe, rx_pipe;
330         unsigned char tx[1], rx[64];
331         int cnt;
332 
333         dbgvm("vmk80xx: %s\n", __func__);
334 
335         tx_pipe = usb_sndbulkpipe(dev->udev, 0x01);
336         rx_pipe = usb_rcvbulkpipe(dev->udev, 0x81);
337 
338         tx[0] = VMK8061_CMD_RD_VERSION;
339 
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);
344 
345         rx[cnt] = '\0';
346 
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);
351 }
352 
353 static int vmk80xx_reset_device(struct vmk80xx_usb *dev)
354 {
355         struct urb *urb;
356         unsigned int tx_pipe;
357         int ival;
358         size_t size;
359 
360         dbgvm("vmk80xx: %s\n", __func__);
361 
362         urb = usb_alloc_urb(0, GFP_KERNEL);
363         if (!urb)
364                 return -ENOMEM;
365 
366         tx_pipe = usb_sndintpipe(dev->udev, 0x01);
367 
368         ival = dev->ep_tx->bInterval;
369         size = le16_to_cpu(dev->ep_tx->wMaxPacketSize);
370 
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;
379 
380         usb_fill_int_urb(urb, dev->udev, tx_pipe, dev->usb_tx_buf,
381                          size, vmk80xx_tx_callback, dev, ival);
382 
383         usb_anchor_urb(urb, &dev->tx_anchor);
384 
385         return usb_submit_urb(urb, GFP_KERNEL);
386 }
387 
388 static void vmk80xx_build_int_urb(struct urb *urb, int flag)
389 {
390         struct vmk80xx_usb *dev = urb->context;
391         __u8 rx_addr, tx_addr;
392         unsigned int pipe;
393         unsigned char *buf;
394         size_t size;
395         void (*callback) (struct urb *);
396         int ival;
397 
398         dbgvm("vmk80xx: %s\n", __func__);
399 
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;
414         }
415 
416         usb_fill_int_urb(urb, dev->udev, pipe, buf, size, callback, dev, ival);
417 }
418 
419 static void vmk80xx_do_bulk_msg(struct vmk80xx_usb *dev)
420 {
421         __u8 tx_addr, rx_addr;
422         unsigned int tx_pipe, rx_pipe;
423         size_t size;
424 
425         dbgvm("vmk80xx: %s\n", __func__);
426 
427         set_bit(TRANS_IN_BUSY, &dev->flags);
428         set_bit(TRANS_OUT_BUSY, &dev->flags);
429 
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);
434 
435         /* The max packet size attributes of the K8061
436          * input/output endpoints are identical */
437         size = le16_to_cpu(dev->ep_tx->wMaxPacketSize);
438 
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);
442 
443         clear_bit(TRANS_OUT_BUSY, &dev->flags);
444         clear_bit(TRANS_IN_BUSY, &dev->flags);
445 }
446 
447 static int vmk80xx_read_packet(struct vmk80xx_usb *dev)
448 {
449         struct urb *urb;
450         int retval;
451 
452         dbgvm("vmk80xx: %s\n", __func__);
453 
454         if (!dev->intf)
455                 return -ENODEV;
456 
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,
461                                                        &dev->flags)))
462                         return -ERESTART;
463 
464         if (dev->board.model == VMK8061_MODEL) {
465                 vmk80xx_do_bulk_msg(dev);
466 
467                 return 0;
468         }
469 
470         urb = usb_alloc_urb(0, GFP_KERNEL);
471         if (!urb)
472                 return -ENOMEM;
473 
474         urb->context = dev;
475         vmk80xx_build_int_urb(urb, URB_RCV_FLAG);
476 
477         set_bit(TRANS_IN_RUNNING, &dev->flags);
478         set_bit(TRANS_IN_BUSY, &dev->flags);
479 
480         usb_anchor_urb(urb, &dev->rx_anchor);
481 
482         retval = usb_submit_urb(urb, GFP_KERNEL);
483         if (!retval)
484                 goto exit;
485 
486         clear_bit(TRANS_IN_RUNNING, &dev->flags);
487         usb_unanchor_urb(urb);
488 
489 exit:
490         usb_free_urb(urb);
491 
492         return retval;
493 }
494 
495 static int vmk80xx_write_packet(struct vmk80xx_usb *dev, int cmd)
496 {
497         struct urb *urb;
498         int retval;
499 
500         dbgvm("vmk80xx: %s\n", __func__);
501 
502         if (!dev->intf)
503                 return -ENODEV;
504 
505         if (test_bit(TRANS_OUT_BUSY, &dev->flags))
506                 if (wait_event_interruptible(dev->write_wait,
507                                              !test_bit(TRANS_OUT_BUSY,
508                                                        &dev->flags)))
509                         return -ERESTART;
510 
511         if (dev->board.model == VMK8061_MODEL) {
512                 dev->usb_tx_buf[0] = cmd;
513                 vmk80xx_do_bulk_msg(dev);
514 
515                 return 0;
516         }
517 
518         urb = usb_alloc_urb(0, GFP_KERNEL);
519         if (!urb)
520                 return -ENOMEM;
521 
522         urb->context = dev;
523         vmk80xx_build_int_urb(urb, URB_SND_FLAG);
524 
525         set_bit(TRANS_OUT_BUSY, &dev->flags);
526 
527         usb_anchor_urb(urb, &dev->tx_anchor);
528 
529         dev->usb_tx_buf[0] = cmd;
530 
531         retval = usb_submit_urb(urb, GFP_KERNEL);
532         if (!retval)
533                 goto exit;
534 
535         clear_bit(TRANS_OUT_BUSY, &dev->flags);
536         usb_unanchor_urb(urb);
537 
538 exit:
539         usb_free_urb(urb);
540 
541         return retval;
542 }
543 
544 #define DIR_IN  1
545 #define DIR_OUT 2
546 
547 #define rudimentary_check(dir)                             \
548 do {                                                       \
549         if (!dev)                                          \
550                 return -EFAULT;                            \
551         if (!dev->probed)                                  \
552                 return -ENODEV;                            \
553         if (!dev->attached)                                \
554                 return -ENODEV;                            \
555         if ((dir) & DIR_IN) {                              \
556                 if (test_bit(TRANS_IN_BUSY, &dev->flags))  \
557                         return -EBUSY;                     \
558         } else {  /* DIR_OUT */                            \
559                 if (test_bit(TRANS_OUT_BUSY, &dev->flags)) \
560                         return -EBUSY;                     \
561         }                                                  \
562 } while (0)
563 
564 static int vmk80xx_ai_rinsn(struct comedi_device *cdev,
565                             struct comedi_subdevice *s,
566                             struct comedi_insn *insn, unsigned int *data)
567 {
568         struct vmk80xx_usb *dev = cdev->private;
569         int chan, reg[2];
570         int n;
571 
572         dbgvm("vmk80xx: %s\n", __func__);
573 
574         rudimentary_check(DIR_IN);
575 
576         down(&dev->limit_sem);
577         chan = CR_CHAN(insn->chanspec);
578 
579         switch (dev->board.model) {
580         case VMK8055_MODEL:
581                 if (!chan)
582                         reg[0] = VMK8055_AI1_REG;
583                 else
584                         reg[0] = VMK8055_AI2_REG;
585                 break;
586         case VMK8061_MODEL:
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;
591                 break;
592         }
593 
594         for (n = 0; n < insn->n; n++) {
595                 if (vmk80xx_read_packet(dev))
596                         break;
597 
598                 if (dev->board.model == VMK8055_MODEL) {
599                         data[n] = dev->usb_rx_buf[reg[0]];
600                         continue;
601                 }
602 
603                 /* VMK8061_MODEL */
604                 data[n] = dev->usb_rx_buf[reg[0]] + 256 *
605                     dev->usb_rx_buf[reg[1]];
606         }
607 
608         up(&dev->limit_sem);
609 
610         return n;
611 }
612 
613 static int vmk80xx_ao_winsn(struct comedi_device *cdev,
614                             struct comedi_subdevice *s,
615                             struct comedi_insn *insn, unsigned int *data)
616 {
617         struct vmk80xx_usb *dev = cdev->private;
618         int chan, cmd, reg;
619         int n;
620 
621         dbgvm("vmk80xx: %s\n", __func__);
622 
623         rudimentary_check(DIR_OUT);
624 
625         down(&dev->limit_sem);
626         chan = CR_CHAN(insn->chanspec);
627 
628         switch (dev->board.model) {
629         case VMK8055_MODEL:
630                 cmd = VMK8055_CMD_WRT_AD;
631                 if (!chan)
632                         reg = VMK8055_AO1_REG;
633                 else
634                         reg = VMK8055_AO2_REG;
635                 break;
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;
640                 break;
641         }
642 
643         for (n = 0; n < insn->n; n++) {
644                 dev->usb_tx_buf[reg] = data[n];
645 
646                 if (vmk80xx_write_packet(dev, cmd))
647                         break;
648         }
649 
650         up(&dev->limit_sem);
651 
652         return n;
653 }
654 
655 static int vmk80xx_ao_rinsn(struct comedi_device *cdev,
656                             struct comedi_subdevice *s,
657                             struct comedi_insn *insn, unsigned int *data)
658 {
659         struct vmk80xx_usb *dev = cdev->private;
660         int chan, reg;
661         int n;
662 
663         dbgvm("vmk80xx: %s\n", __func__);
664 
665         rudimentary_check(DIR_IN);
666 
667         down(&dev->limit_sem);
668         chan = CR_CHAN(insn->chanspec);
669 
670         reg = VMK8061_AO_REG - 1;
671 
672         dev->usb_tx_buf[0] = VMK8061_CMD_RD_AO;
673 
674         for (n = 0; n < insn->n; n++) {
675                 if (vmk80xx_read_packet(dev))
676                         break;
677 
678                 data[n] = dev->usb_rx_buf[reg + chan];
679         }
680 
681         up(&dev->limit_sem);
682 
683         return n;
684 }
685 
686 static int vmk80xx_di_rinsn(struct comedi_device *cdev,
687                             struct comedi_subdevice *s,
688                             struct comedi_insn *insn, unsigned int *data)
689 {
690         struct vmk80xx_usb *dev = cdev->private;
691         int chan;
692         unsigned char *rx_buf;
693         int reg, inp;
694         int n;
695 
696         dbgvm("vmk80xx: %s\n", __func__);
697 
698         rudimentary_check(DIR_IN);
699 
700         down(&dev->limit_sem);
701         chan = CR_CHAN(insn->chanspec);
702 
703         rx_buf = dev->usb_rx_buf;
704 
705         if (dev->board.model == VMK8061_MODEL) {
706                 reg = VMK8061_DI_REG;
707                 dev->usb_tx_buf[0] = VMK8061_CMD_RD_DI;
708         } else
709                 reg = VMK8055_DI_REG;
710 
711         for (n = 0; n < insn->n; n++) {
712                 if (vmk80xx_read_packet(dev))
713                         break;
714 
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));
719                 else
720                         inp = rx_buf[reg];
721 
722                 data[n] = ((inp & (1 << chan)) > 0);
723         }
724 
725         up(&dev->limit_sem);
726 
727         return n;
728 }
729 
730 static int vmk80xx_do_winsn(struct comedi_device *cdev,
731                             struct comedi_subdevice *s,
732                             struct comedi_insn *insn, unsigned int *data)
733 {
734 
735         struct vmk80xx_usb *dev = cdev->private;
736         int chan;
737         unsigned char *tx_buf;
738         int reg, cmd;
739         int n;
740 
741         dbgvm("vmk80xx: %s\n", __func__);
742 
743         rudimentary_check(DIR_OUT);
744 
745         down(&dev->limit_sem);
746         chan = CR_CHAN(insn->chanspec);
747 
748         tx_buf = dev->usb_tx_buf;
749 
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;
754                         if (data[n] == 1)
755                                 tx_buf[reg] |= (1 << chan);
756                         else
757                                 tx_buf[reg] ^= (1 << chan);
758 
759                         goto write_packet;
760                 }
761 
762                 /* VMK8061_MODEL */
763                 reg = VMK8061_DO_REG;
764                 if (data[n] == 1) {
765                         cmd = VMK8061_CMD_SET_DO;
766                         tx_buf[reg] = 1 << chan;
767                 } else {
768                         cmd = VMK8061_CMD_CLR_DO;
769                         tx_buf[reg] = 0xff - (1 << chan);
770                 }
771 
772 write_packet:
773                 if (vmk80xx_write_packet(dev, cmd))
774                         break;
775         }
776 
777         up(&dev->limit_sem);
778 
779         return n;
780 }
781 
782 static int vmk80xx_do_rinsn(struct comedi_device *cdev,
783                             struct comedi_subdevice *s,
784                             struct comedi_insn *insn, unsigned int *data)
785 {
786         struct vmk80xx_usb *dev = cdev->private;
787         int chan, reg, mask;
788         int n;
789 
790         dbgvm("vmk80xx: %s\n", __func__);
791 
792         rudimentary_check(DIR_IN);
793 
794         down(&dev->limit_sem);
795         chan = CR_CHAN(insn->chanspec);
796 
797         reg = VMK8061_DO_REG;
798         mask = 1 << chan;
799 
800         dev->usb_tx_buf[0] = VMK8061_CMD_RD_DO;
801 
802         for (n = 0; n < insn->n; n++) {
803                 if (vmk80xx_read_packet(dev))
804                         break;
805 
806                 data[n] = (dev->usb_rx_buf[reg] & mask) >> chan;
807         }
808 
809         up(&dev->limit_sem);
810 
811         return n;
812 }
813 
814 static int vmk80xx_cnt_rinsn(struct comedi_device *cdev,
815                              struct comedi_subdevice *s,
816                              struct comedi_insn *insn, unsigned int *data)
817 {
818         struct vmk80xx_usb *dev = cdev->private;
819         int chan, reg[2];
820         int n;
821 
822         dbgvm("vmk80xx: %s\n", __func__);
823 
824         rudimentary_check(DIR_IN);
825 
826         down(&dev->limit_sem);
827         chan = CR_CHAN(insn->chanspec);
828 
829         switch (dev->board.model) {
830         case VMK8055_MODEL:
831                 if (!chan)
832                         reg[0] = VMK8055_CNT1_REG;
833                 else
834                         reg[0] = VMK8055_CNT2_REG;
835                 break;
836         case VMK8061_MODEL:
837                 reg[0] = VMK8061_CNT_REG;
838                 reg[1] = VMK8061_CNT_REG;
839                 dev->usb_tx_buf[0] = VMK8061_CMD_RD_CNT;
840                 break;
841         }
842 
843         for (n = 0; n < insn->n; n++) {
844                 if (vmk80xx_read_packet(dev))
845                         break;
846 
847                 if (dev->board.model == VMK8055_MODEL) {
848                         data[n] = dev->usb_rx_buf[reg[0]];
849                         continue;
850                 }
851 
852                 /* VMK8061_MODEL */
853                 data[n] = dev->usb_rx_buf[reg[0] * (chan + 1) + 1]
854                     + 256 * dev->usb_rx_buf[reg[1] * 2 + 2];
855         }
856 
857         up(&dev->limit_sem);
858 
859         return n;
860 }
861 
862 static int vmk80xx_cnt_cinsn(struct comedi_device *cdev,
863                              struct comedi_subdevice *s,
864                              struct comedi_insn *insn, unsigned int *data)
865 {
866         struct vmk80xx_usb *dev = cdev->private;
867         unsigned int insn_cmd;
868         int chan, cmd, reg;
869         int n;
870 
871         dbgvm("vmk80xx: %s\n", __func__);
872 
873         rudimentary_check(DIR_OUT);
874 
875         down(&dev->limit_sem);
876 
877         insn_cmd = data[0];
878         if (insn_cmd != INSN_CONFIG_RESET && insn_cmd != GPCT_RESET)
879                 return -EINVAL;
880 
881         chan = CR_CHAN(insn->chanspec);
882 
883         if (dev->board.model == VMK8055_MODEL) {
884                 if (!chan) {
885                         cmd = VMK8055_CMD_RST_CNT1;
886                         reg = VMK8055_CNT1_REG;
887                 } else {
888                         cmd = VMK8055_CMD_RST_CNT2;
889                         reg = VMK8055_CNT2_REG;
890                 }
891 
892                 dev->usb_tx_buf[reg] = 0x00;
893         } else
894                 cmd = VMK8061_CMD_RST_CNT;
895 
896         for (n = 0; n < insn->n; n++)
897                 if (vmk80xx_write_packet(dev, cmd))
898                         break;
899 
900         up(&dev->limit_sem);
901 
902         return n;
903 }
904 
905 static int vmk80xx_cnt_winsn(struct comedi_device *cdev,
906                              struct comedi_subdevice *s,
907                              struct comedi_insn *insn, unsigned int *data)
908 {
909         struct vmk80xx_usb *dev = cdev->private;
910         unsigned long debtime, val;
911         int chan, cmd;
912         int n;
913 
914         dbgvm("vmk80xx: %s\n", __func__);
915 
916         rudimentary_check(DIR_OUT);
917 
918         down(&dev->limit_sem);
919         chan = CR_CHAN(insn->chanspec);
920 
921         if (!chan)
922                 cmd = VMK8055_CMD_DEB1_TIME;
923         else
924                 cmd = VMK8055_CMD_DEB2_TIME;
925 
926         for (n = 0; n < insn->n; n++) {
927                 debtime = data[n];
928                 if (debtime == 0)
929                         debtime = 1;
930 
931                 /* TODO: Prevent overflows */
932                 if (debtime > 7450)
933                         debtime = 7450;
934 
935                 val = int_sqrt(debtime * 1000 / 115);
936                 if (((val + 1) * val) < debtime * 1000 / 115)
937                         val += 1;
938 
939                 dev->usb_tx_buf[6 + chan] = val;
940 
941                 if (vmk80xx_write_packet(dev, cmd))
942                         break;
943         }
944 
945         up(&dev->limit_sem);
946 
947         return n;
948 }
949 
950 static int vmk80xx_pwm_rinsn(struct comedi_device *cdev,
951                              struct comedi_subdevice *s,
952                              struct comedi_insn *insn, unsigned int *data)
953 {
954         struct vmk80xx_usb *dev = cdev->private;
955         int reg[2];
956         int n;
957 
958         dbgvm("vmk80xx: %s\n", __func__);
959 
960         rudimentary_check(DIR_IN);
961 
962         down(&dev->limit_sem);
963 
964         reg[0] = VMK8061_PWM_REG1;
965         reg[1] = VMK8061_PWM_REG2;
966 
967         dev->usb_tx_buf[0] = VMK8061_CMD_RD_PWM;
968 
969         for (n = 0; n < insn->n; n++) {
970                 if (vmk80xx_read_packet(dev))
971                         break;
972 
973                 data[n] = dev->usb_rx_buf[reg[0]] + 4 * dev->usb_rx_buf[reg[1]];
974         }
975 
976         up(&dev->limit_sem);
977 
978         return n;
979 }
980 
981 static int vmk80xx_pwm_winsn(struct comedi_device *cdev,
982                              struct comedi_subdevice *s,
983                              struct comedi_insn *insn, unsigned int *data)
984 {
985         struct vmk80xx_usb *dev = cdev->private;
986         unsigned char *tx_buf;
987         int reg[2], cmd;
988         int n;
989 
990         dbgvm("vmk80xx: %s\n", __func__);
991 
992         rudimentary_check(DIR_OUT);
993 
994         down(&dev->limit_sem);
995 
996         tx_buf = dev->usb_tx_buf;
997 
998         reg[0] = VMK8061_PWM_REG1;
999         reg[1] = VMK8061_PWM_REG2;
1000 
1001         cmd = VMK8061_CMD_OUT_PWM;
1002 
1003         /*
1004          * The followin piece of code was translated from the inline
1005          * assembler code in the DLL source code.
1006          *
1007          * asm
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]])
1011          *   mov eax, k
1012          *   shr eax, 2  ; right shift eax register by 2
1013          *   mov hi, al  ; hi is the high part (tx_buf[reg[1]])
1014          * end;
1015          */
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;
1019 
1020                 if (vmk80xx_write_packet(dev, cmd))
1021                         break;
1022         }
1023 
1024         up(&dev->limit_sem);
1025 
1026         return n;
1027 }
1028 
1029 static int
1030 vmk80xx_attach(struct comedi_device *cdev, struct comedi_devconfig *it)
1031 {
1032         int i;
1033         struct vmk80xx_usb *dev;
1034         int n_subd;
1035         struct comedi_subdevice *s;
1036         int minor;
1037 
1038         dbgvm("vmk80xx: %s\n", __func__);
1039 
1040         mutex_lock(&glb_mutex);
1041 
1042         for (i = 0; i < VMK80XX_MAX_BOARDS; i++)
1043                 if (vmb[i].probed && !vmb[i].attached)
1044                         break;
1045 
1046         if (i == VMK80XX_MAX_BOARDS) {
1047                 mutex_unlock(&glb_mutex);
1048                 return -ENODEV;
1049         }
1050 
1051         dev = &vmb[i];
1052 
1053         down(&dev->limit_sem);
1054 
1055         cdev->board_name = dev->board.name;
1056         cdev->private = dev;
1057 
1058         if (dev->board.model == VMK8055_MODEL)
1059                 n_subd = 5;
1060         else
1061                 n_subd = 6;
1062 
1063         if (alloc_subdevices(cdev, n_subd) < 0) {
1064                 up(&dev->limit_sem);
1065                 mutex_unlock(&glb_mutex);
1066                 return -ENOMEM;
1067         }
1068 
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;
1077 
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;
1086 
1087         if (dev->board.model == VMK8061_MODEL) {
1088                 s->subdev_flags |= SDF_READABLE;
1089                 s->insn_read = vmk80xx_ao_rinsn;
1090         }
1091 
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;
1099 
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;
1107 
1108         if (dev->board.model == VMK8061_MODEL) {
1109                 s->subdev_flags |= SDF_READABLE;
1110                 s->insn_read = vmk80xx_do_rinsn;
1111         }
1112 
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;
1120 
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;
1125         }
1126 
1127         /* PWM subdevice */
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;
1136         }
1137 
1138         dev->attached = 1;
1139 
1140         minor = cdev->minor;
1141 
1142         printk(KERN_INFO
1143                "comedi%d: vmk80xx: board #%d [%s] attached to comedi\n",
1144                minor, dev->count, dev->board.name);
1145 
1146         up(&dev->limit_sem);
1147         mutex_unlock(&glb_mutex);
1148 
1149         return 0;
1150 }
1151 
1152 static int vmk80xx_detach(struct comedi_device *cdev)
1153 {
1154         struct vmk80xx_usb *dev;
1155         int minor;
1156 
1157         dbgvm("vmk80xx: %s\n", __func__);
1158 
1159         if (!cdev)
1160                 return -EFAULT;
1161 
1162         dev = cdev->private;
1163         if (!dev)
1164                 return -EFAULT;
1165 
1166         down(&dev->limit_sem);
1167 
1168         cdev->private = NULL;
1169         dev->attached = 0;
1170 
1171         minor = cdev->minor;
1172 
1173         printk(KERN_INFO
1174                "comedi%d: vmk80xx: board #%d [%s] detached from comedi\n",
1175                minor, dev->count, dev->board.name);
1176 
1177         up(&dev->limit_sem);
1178 
1179         return 0;
1180 }
1181 
1182 static int
1183 vmk80xx_probe(struct usb_interface *intf, const struct usb_device_id *id)
1184 {
1185         int i;
1186         struct vmk80xx_usb *dev;
1187         struct usb_host_interface *iface_desc;
1188         struct usb_endpoint_descriptor *ep_desc;
1189         size_t size;
1190 
1191         dbgvm("vmk80xx: %s\n", __func__);
1192 
1193         mutex_lock(&glb_mutex);
1194 
1195         for (i = 0; i < VMK80XX_MAX_BOARDS; i++)
1196                 if (!vmb[i].probed)
1197                         break;
1198 
1199         if (i == VMK80XX_MAX_BOARDS) {
1200                 mutex_unlock(&glb_mutex);
1201                 return -EMFILE;
1202         }
1203 
1204         dev = &vmb[i];
1205 
1206         memset(dev, 0x00, sizeof(struct vmk80xx_usb));
1207         dev->count = i;
1208 
1209         iface_desc = intf->cur_altsetting;
1210         if (iface_desc->desc.bNumEndpoints != 2)
1211                 goto error;
1212 
1213         for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) {
1214                 ep_desc = &iface_desc->endpoint[i].desc;
1215 
1216                 if (usb_endpoint_is_int_in(ep_desc)) {
1217                         dev->ep_rx = ep_desc;
1218                         continue;
1219                 }
1220 
1221                 if (usb_endpoint_is_int_out(ep_desc)) {
1222                         dev->ep_tx = ep_desc;
1223                         continue;
1224                 }
1225 
1226                 if (usb_endpoint_is_bulk_in(ep_desc)) {
1227                         dev->ep_rx = ep_desc;
1228                         continue;
1229                 }
1230 
1231                 if (usb_endpoint_is_bulk_out(ep_desc)) {
1232                         dev->ep_tx = ep_desc;
1233                         continue;
1234                 }
1235         }
1236 
1237         if (!dev->ep_rx || !dev->ep_tx)
1238                 goto error;
1239 
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);
1244                 return -ENOMEM;
1245         }
1246 
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);
1252                 return -ENOMEM;
1253         }
1254 
1255         dev->udev = interface_to_usbdev(intf);
1256         dev->intf = intf;
1257 
1258         sema_init(&dev->limit_sem, 8);
1259         init_waitqueue_head(&dev->read_wait);
1260         init_waitqueue_head(&dev->write_wait);
1261 
1262         init_usb_anchor(&dev->rx_anchor);
1263         init_usb_anchor(&dev->tx_anchor);
1264 
1265         usb_set_intfdata(intf, dev);
1266 
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;
1284                 break;
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;
1301                 break;
1302         }
1303 
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);
1307 
1308                 if (vmk80xx_check_data_link(dev)) {
1309                         vmk80xx_read_eeprom(dev, IC6_VERSION);
1310                         printk(KERN_INFO "comedi#: vmk80xx: %s\n",
1311                                dev->fw.ic6_vers);
1312                 } else
1313                         dbgcm("comedi#: vmk80xx: no conn. to CPU\n");
1314         }
1315 
1316         if (dev->board.model == VMK8055_MODEL)
1317                 vmk80xx_reset_device(dev);
1318 
1319         dev->probed = 1;
1320 
1321         printk(KERN_INFO "comedi#: vmk80xx: board #%d [%s] now attached\n",
1322                dev->count, dev->board.name);
1323 
1324         mutex_unlock(&glb_mutex);
1325 
1326         return 0;
1327 error:
1328         mutex_unlock(&glb_mutex);
1329 
1330         return -ENODEV;
1331 }
1332 
1333 static void vmk80xx_disconnect(struct usb_interface *intf)
1334 {
1335         struct vmk80xx_usb *dev = usb_get_intfdata(intf);
1336 
1337         dbgvm("vmk80xx: %s\n", __func__);
1338 
1339         if (!dev)
1340                 return;
1341 
1342         mutex_lock(&glb_mutex);
1343         down(&dev->limit_sem);
1344 
1345         dev->probed = 0;
1346         usb_set_intfdata(dev->intf, NULL);
1347 
1348         usb_kill_anchored_urbs(&dev->rx_anchor);
1349         usb_kill_anchored_urbs(&dev->tx_anchor);
1350 
1351         kfree(dev->usb_rx_buf);
1352         kfree(dev->usb_tx_buf);
1353 
1354         printk(KERN_INFO "comedi#: vmk80xx: board #%d [%s] now detached\n",
1355                dev->count, dev->board.name);
1356 
1357         up(&dev->limit_sem);
1358         mutex_unlock(&glb_mutex);
1359 }
1360 
1361 /* TODO: Add support for suspend, resume, pre_reset,
1362  * post_reset and flush */
1363 static struct usb_driver vmk80xx_driver = {
1364         .name = "vmk80xx",
1365         .probe = vmk80xx_probe,
1366         .disconnect = vmk80xx_disconnect,
1367         .id_table = vmk80xx_id_table
1368 };
1369 
1370 static struct comedi_driver driver_vmk80xx = {
1371         .module = THIS_MODULE,
1372         .driver_name = "vmk80xx",
1373         .attach = vmk80xx_attach,
1374         .detach = vmk80xx_detach
1375 };
1376 
1377 static int __init vmk80xx_init(void)
1378 {
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);
1383 }
1384 
1385 static void __exit vmk80xx_exit(void)
1386 {
1387         comedi_driver_unregister(&driver_vmk80xx);
1388         usb_deregister(&vmk80xx_driver);
1389 }
1390 
1391 module_init(vmk80xx_init);
1392 module_exit(vmk80xx_exit);
1393 

This page was automatically generated by LXR 0.3.1.  •  Linux is a registered trademark of Linus Torvalds