Added some ack'ing of b interrupts, and do acks before handling
[comedi.git] / comedi / drivers / dt9812.c
1 /*
2  * comedi/drivers/dt9812.c
3  *   COMEDI driver for DataTranslation DT9812 USB module
4  *
5  * Copyright (C) 2005 Anders Blomdell <anders.blomdell@control.lth.se>
6  *
7  * COMEDI - Linux Control and Measurement Device Interface
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13
14  *  This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22  *
23  */
24
25 /*
26 Driver: dt9812.o
27 Description: Data Translation DT9812 USB module
28 Author: anders.blomdell@control.lth.se (Anders Blomdell)
29 Status: in development
30 Devices: [Data Translation] DT9812 (dt9812)
31 Updated: Sun Nov 20 20:18:34 EST 2005
32
33 This driver works, but bulk transfers not implemented. Might be a starting point
34 for someone else. I found out too late that USB has too high latencies (>1 ms)
35 for my needs.
36 */
37
38 /*
39  * Nota Bene:
40  *   1. All writes to command pipe has to be 32 bytes (ISP1181B SHRTP=0 ?)
41  *   2. The DDK source (as of sep 2005) is in error regarding the 
42  *      input MUX bits (example code says P4, but firmware schematics 
43  *      says P1).
44  */
45
46 #include <linux/version.h>
47 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
48
49 #include <linux/config.h>
50 #include <linux/kernel.h>
51 #include <linux/errno.h>
52 #include <linux/init.h>
53 #include <linux/slab.h>
54 #include <linux/module.h>
55 #include <linux/kref.h>
56 #include <asm/uaccess.h>
57 #include <linux/usb.h>
58 #include <linux/comedidev.h>
59 #include "dt9812.h"
60
61
62 #define DT9812_NUM_SLOTS 16
63
64 static DECLARE_MUTEX(dt9812_mutex);
65
66 static struct usb_device_id dt9812_table [] = {
67         { USB_DEVICE(0x0867, 0x9812) },
68         { }                                     /* Terminating entry */
69 };
70
71 MODULE_DEVICE_TABLE (usb, dt9812_table);
72
73 typedef struct usb_dt9812 {
74   struct slot_dt9812 *slot;
75   struct usb_device *udev;
76   struct usb_interface *interface;
77   u16 vendor;
78   u16 product;
79   u16 device;
80   u32 serial;
81   struct {
82     __u8 addr;
83     size_t size;
84   } message_pipe, command_write, command_read, write_stream, read_stream;
85   struct kref kref;
86   u16 analog_out_shadow[2];
87   u8 digital_out_shadow;
88 } usb_dt9812_t;
89
90 typedef struct comedi_dt9812 {
91   struct slot_dt9812 *slot;
92   u32 serial;
93 } comedi_dt9812_t;
94
95 typedef struct slot_dt9812 {
96   struct semaphore mutex;
97   u32 serial;
98   usb_dt9812_t *usb;
99   comedi_dt9812_t *comedi;
100 } slot_dt9812_t;
101
102 static comedi_lrange dt9812_10_ain_range={ 1, {
103     BIP_RANGE(10),
104   }
105 };
106
107 static comedi_lrange dt9812_2pt5_ain_range={ 1, {
108     UNI_RANGE(2.5),
109   }
110 };
111
112 static comedi_lrange dt9812_10_aout_range={ 1, {
113     BIP_RANGE(10),
114   }
115 };
116
117 static comedi_lrange dt9812_2pt5_aout_range={ 1, {
118     UNI_RANGE(2.5),
119   }
120 };
121
122 static slot_dt9812_t dt9812[DT9812_NUM_SLOTS];
123
124 // Useful shorthand access to private data
125 #define devpriv ((comedi_dt9812_t *)dev->private)
126
127
128 static inline usb_dt9812_t *to_dt9812_dev(struct kref *d) 
129 {
130   return container_of(d, usb_dt9812_t, kref);
131 }
132
133 static void dt9812_delete(struct kref *kref)
134 {       
135   usb_dt9812_t *dev = to_dt9812_dev(kref);
136
137   usb_put_dev(dev->udev);
138   kfree (dev);
139 }
140
141 static int dt9812_read_info(usb_dt9812_t *dev, 
142                             int offset, void *buf, size_t buf_size) 
143
144   dt9812_usb_cmd_t cmd;
145   int count, retval;
146
147   cmd.cmd = cpu_to_le32(DT9812_R_FLASH_DATA);
148   cmd.u.flash_data_info.address = 
149     cpu_to_le16(DT9812_DIAGS_BOARD_INFO_ADDR + offset);
150   cmd.u.flash_data_info.numbytes = cpu_to_le16(buf_size);
151
152   count = 32;
153   retval = usb_bulk_msg(dev->udev,
154                         usb_sndbulkpipe(dev->udev, dev->command_write.addr),
155                         &cmd,
156                         32, // DT9812 only responds to 32 byte writes!!
157                         &count, HZ*1);
158   if (retval == 0) {
159     retval = usb_bulk_msg(dev->udev,
160                           usb_rcvbulkpipe(dev->udev, dev->command_read.addr),
161                           buf, 
162                           buf_size,
163                           &count, HZ*1);
164   }
165   return retval;
166 }
167
168 static int dt9812_read_multiple_registers(usb_dt9812_t *dev, 
169                                           int reg_count,
170                                           u8 *address,
171                                           u8 *value)
172 {
173   dt9812_usb_cmd_t cmd;
174   int i, count, retval;
175
176   cmd.cmd = cpu_to_le32(DT9812_R_MULTI_BYTE_REG);
177   cmd.u.read_multi_info.count = reg_count;
178   for (i = 0 ; i < reg_count ; i++) {
179     cmd.u.read_multi_info.address[i] = address[i];
180   }
181   count = 32;
182   retval = usb_bulk_msg(dev->udev,
183                         usb_sndbulkpipe(dev->udev, dev->command_write.addr),
184                         &cmd,
185                         32, // DT9812 only responds to 32 byte writes!!
186                         &count, HZ*1);
187   if (retval == 0) {
188     retval = usb_bulk_msg(dev->udev,
189                           usb_rcvbulkpipe(dev->udev, dev->command_read.addr),
190                           value, 
191                           reg_count,
192                           &count, HZ*1);
193   }
194   return retval;
195 }
196
197 static int dt9812_write_multiple_registers(usb_dt9812_t *dev, 
198                                            int reg_count,
199                                            u8 *address,
200                                            u8 *value)
201
202 {
203   dt9812_usb_cmd_t cmd;
204   int i, count, retval;
205
206   cmd.cmd = cpu_to_le32(DT9812_W_MULTI_BYTE_REG);
207   cmd.u.read_multi_info.count = reg_count;
208   for (i = 0 ; i < reg_count ; i++) {
209     cmd.u.write_multi_info.write[i].address = address[i];
210     cmd.u.write_multi_info.write[i].value = value[i];
211   }
212   retval = usb_bulk_msg(dev->udev,
213                         usb_sndbulkpipe(dev->udev, dev->command_write.addr),
214                         &cmd,
215                         32, // DT9812 only responds to 32 byte writes!!
216                         &count, HZ*1);
217   return retval;
218 }
219   
220 static int dt9812_rmw_multiple_registers(usb_dt9812_t *dev, 
221                                          int reg_count,
222                                          dt9812_rmw_byte_t rmw[])
223 {
224   dt9812_usb_cmd_t cmd;
225   int i, count, retval;
226
227   cmd.cmd = cpu_to_le32(DT9812_RMW_MULTI_BYTE_REG);
228   cmd.u.rmw_multi_info.count = reg_count;
229   for (i = 0 ; i < reg_count ; i++) {
230     cmd.u.rmw_multi_info.rmw[i] = rmw[i];
231   }
232   retval = usb_bulk_msg(dev->udev,
233                         usb_sndbulkpipe(dev->udev, dev->command_write.addr),
234                         &cmd,
235                         32, // DT9812 only responds to 32 byte writes!!
236                         &count, HZ*1);
237   return retval;
238 }
239   
240 static int dt9812_digital_in(slot_dt9812_t *slot, u8 *bits) 
241 {
242   int result = -ENODEV;
243
244   down(&slot->mutex);
245   if (slot->usb) {
246     u8 reg[2] = { F020_SFR_P3, F020_SFR_P1 };
247     u8 value[2];
248
249     result = dt9812_read_multiple_registers(slot->usb, 2, reg, value);
250     if (result == 0) {
251       // bits 0-6 in F020_SFR_P3 are bits 0-6 in the digital input port
252       // bit 3 in F020_SFR_P1 is bit 7 in the digital input port
253       *bits = (value[0] & 0x7f) | ((value[1] & 0x08) << 4);
254 //    printk("%2.2x, %2.2x -> %2.2x\n", value[0], value[1], *bits);
255     }
256   }
257   up(&slot->mutex);
258  
259   return result;
260 }
261
262 static int dt9812_digital_out(slot_dt9812_t *slot, u8 bits) 
263 {
264   int result = -ENODEV;
265
266   down(&slot->mutex);
267   if (slot->usb) {
268     u8 reg[1];
269     u8 value[1];
270
271     reg[0] = F020_SFR_P2;
272     value[0] = bits;
273     result = dt9812_write_multiple_registers(slot->usb, 1, reg, value);
274     slot->usb->digital_out_shadow = bits;
275   }
276   up(&slot->mutex);
277   return result;
278 }
279
280 static int dt9812_digital_out_shadow(slot_dt9812_t *slot, u8 *bits) 
281 {
282   int result = -ENODEV;
283
284   down(&slot->mutex);
285   if (slot->usb) {
286     *bits = slot->usb->digital_out_shadow;
287     result = 0;
288   }
289   up(&slot->mutex);
290   return result;
291 }
292
293 static void dt9812_configure_mux(usb_dt9812_t *dev, 
294                                  dt9812_rmw_byte_t *rmw, 
295                                  int channel)
296 {
297   if (dev->device == DT9812_DEVID_DT9812_10) {
298     // In the DT9812/10V MUX is selected by P1.5-7
299     rmw->address = F020_SFR_P1;
300     rmw->and_mask = 0xe0;
301     rmw->or_value = channel << 5;
302   } else {
303     // In the DT9812/2.5V, the internal mux is selected by bits 0:2
304     rmw->address = F020_SFR_AMX0SL;
305     rmw->and_mask =  0xff;
306     rmw->or_value = channel & 0x07;
307   }
308 }
309
310 static void dt9812_configure_gain(usb_dt9812_t *dev, 
311                                   dt9812_rmw_byte_t *rmw, 
312                                   dt9812_gain_t gain)
313 {
314   if (dev->device == DT9812_DEVID_DT9812_10) {
315     // In the DT9812/10V, there is an external gain of 0.5
316     gain <<= 1;
317   }
318
319   rmw->address = F020_SFR_ADC0CF;
320   rmw->and_mask = 
321     F020_MASK_ADC0CF_AMP0GN2 | 
322     F020_MASK_ADC0CF_AMP0GN1 | 
323     F020_MASK_ADC0CF_AMP0GN0;
324   switch (gain) {
325     // 000 -> Gain =  1 
326     // 001 -> Gain =  2
327     // 010 -> Gain =  4 
328     // 011 -> Gain =  8 
329     // 10x -> Gain = 16 
330     // 11x -> Gain =  0.5 
331     case DT9812_GAIN_0PT5: {
332       rmw->or_value = F020_MASK_ADC0CF_AMP0GN2 || F020_MASK_ADC0CF_AMP0GN1; 
333     } break;
334     case DT9812_GAIN_1: {
335       rmw->or_value = 0x00;
336     } break;
337     case DT9812_GAIN_2: {   
338       rmw->or_value = F020_MASK_ADC0CF_AMP0GN0;
339     } break;
340     case DT9812_GAIN_4: { 
341       rmw->or_value = F020_MASK_ADC0CF_AMP0GN1;
342     } break;
343     case DT9812_GAIN_8: { 
344       rmw->or_value = F020_MASK_ADC0CF_AMP0GN1 || F020_MASK_ADC0CF_AMP0GN0;
345     } break;
346     case DT9812_GAIN_16: {
347       rmw->or_value = F020_MASK_ADC0CF_AMP0GN2;
348     } break;
349     default: {
350       err("Illegal gain %d\n", gain);
351     }
352   }
353 }
354
355 static int dt9812_analog_in(slot_dt9812_t *slot, 
356                             int channel, 
357                             u16 *value,
358                             dt9812_gain_t gain) 
359 {
360   int result = -ENODEV;
361
362   down(&slot->mutex);
363   if (slot->usb) {
364     dt9812_rmw_byte_t rmw[3];
365   
366     // 1 select the gain 
367     dt9812_configure_gain(slot->usb, &rmw[0], gain);
368   
369     // 2 set the MUX to select the channel
370     dt9812_configure_mux(slot->usb, &rmw[1], channel);
371
372     // 3 start conversion
373     rmw[2].address = F020_SFR_ADC0CN; 
374     rmw[2].and_mask = 0xff;
375     rmw[2].or_value = F020_MASK_ADC0CN_AD0EN | F020_MASK_ADC0CN_AD0BUSY; 
376
377     
378     result = dt9812_rmw_multiple_registers(slot->usb, 3, rmw);
379     if (result == 0) {    
380       // read the status and ADC
381       u8 reg[3] = { F020_SFR_ADC0CN, F020_SFR_ADC0H, F020_SFR_ADC0L };
382       u8 val[3];
383       result = dt9812_read_multiple_registers(slot->usb, 3, reg, val);
384       if (result == 0) {
385         // An ADC conversion takes 16 SAR clocks cycles, i.e. about 9us. 
386         // Therefore, between the instant that AD0BUSY was set via 
387         // dt9812_rmw_multiple_registers and the read of AD0BUSY via 
388         // dt9812_read_multiple_registers, the conversion 
389         // should be complete since these two operations require two USB 
390         // transactions each taking at least a millisecond to complete. 
391         // However, lets make sure that conversion is finished.
392         if ((val[0] & (F020_MASK_ADC0CN_AD0INT | F020_MASK_ADC0CN_AD0BUSY)) == 
393             F020_MASK_ADC0CN_AD0INT) {
394           switch (slot->usb->device) {
395             case DT9812_DEVID_DT9812_10: {
396               // For DT9812-10V the personality module set the encoding to 2's 
397               // complement. Hence, convert it before returning it
398               *value = ((val[1] << 8) | val[2]) + 0x800;
399             } break;
400             case DT9812_DEVID_DT9812_2PT5: {
401               *value = (val[1] << 8) | val[2];
402             } break;
403           }
404         }
405       } 
406     }
407   }
408   up(&slot->mutex);
409   return result;
410 }
411
412 static int dt9812_analog_out_shadow(slot_dt9812_t *slot, int channel, 
413                                     u16 *value) 
414 {
415   int result = -ENODEV;
416
417   down(&slot->mutex);
418   if (slot->usb) {
419     *value = slot->usb->analog_out_shadow[channel];
420     result = 0;
421   }
422   up(&slot->mutex);
423
424   return result;
425 }
426
427 static int dt9812_analog_out(slot_dt9812_t *slot, int channel, u16 value) 
428 {
429   int result = -ENODEV;
430
431   down(&slot->mutex);
432   if (slot->usb) {
433     dt9812_rmw_byte_t rmw[3];
434
435     switch (channel) {
436       case 0: {
437         // 1. Set DAC mode
438         rmw[0].address = F020_SFR_DAC0CN;
439         rmw[0].and_mask =  0xff;
440         rmw[0].or_value = F020_MASK_DACxCN_DACxEN;
441
442         // 2 load low byte of DAC value first
443         rmw[1].address = F020_SFR_DAC0L;
444         rmw[1].and_mask = 0xff;
445         rmw[1].or_value = value & 0xff; 
446
447         // 3 load high byte of DAC value next to latch the 12-bit value
448         rmw[2].address = F020_SFR_DAC0H;
449         rmw[2].and_mask = 0xff;
450         rmw[2].or_value = (value >> 8) & 0xf; 
451       } break;
452       case 1: {
453         // 1. Set DAC mode
454         rmw[0].address = F020_SFR_DAC1CN;
455         rmw[0].and_mask =  0xff;
456         rmw[0].or_value = F020_MASK_DACxCN_DACxEN;
457    
458         // 2 load low byte of DAC value first
459         rmw[1].address = F020_SFR_DAC1L;
460         rmw[1].and_mask = 0xff;
461         rmw[1].or_value = value & 0xff; 
462    
463         // 3 load high byte of DAC value next to latch the 12-bit value
464         rmw[2].address = F020_SFR_DAC1H;
465         rmw[2].and_mask = 0xff;
466         rmw[2].or_value = (value >> 8) & 0xf; 
467       } break;
468     }
469     result = dt9812_rmw_multiple_registers(slot->usb, 3, rmw);
470     slot->usb->analog_out_shadow[channel] = value;
471   }
472   up(&slot->mutex);
473
474   return result;
475 }
476
477 /*
478  * USB framework functions
479  */
480
481 static int dt9812_probe(struct usb_interface *interface, 
482                         const struct usb_device_id *id)
483 {
484   int retval = -ENOMEM;
485   usb_dt9812_t *dev = NULL;
486   struct usb_host_interface *iface_desc;
487   struct usb_endpoint_descriptor *endpoint;
488   int i;
489   u8 fw;
490
491   // allocate memory for our device state and initialize it
492   dev = kmalloc(sizeof(*dev), GFP_KERNEL);
493   if (dev == NULL) {
494     err("Out of memory");
495     goto error;
496   }
497   memset(dev, 0x00, sizeof(*dev));
498   KREF_INIT(&dev->kref, dt9812_delete);
499   
500   dev->udev = usb_get_dev(interface_to_usbdev(interface));
501   dev->interface = interface;
502   
503   // Check endpoints
504   iface_desc = interface->cur_altsetting;
505   
506   if (iface_desc->desc.bNumEndpoints != 5) {
507     err("Wrong number of endpints.");
508     retval = -ENODEV;
509     goto error;
510   }
511           
512   for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) {
513     int direction = -1;
514     endpoint = &iface_desc->endpoint[i].desc;
515     switch (i) {
516       case 0: { 
517         direction = USB_DIR_IN; 
518         dev->message_pipe.addr = endpoint->bEndpointAddress;
519         dev->message_pipe.size = le16_to_cpu(endpoint->wMaxPacketSize);
520       } break;
521       case 1: { 
522         direction = USB_DIR_OUT; 
523         dev->command_write.addr = endpoint->bEndpointAddress;
524         dev->command_write.size = le16_to_cpu(endpoint->wMaxPacketSize);
525       } break;
526       case 2: { 
527         direction = USB_DIR_IN; 
528         dev->command_read.addr = endpoint->bEndpointAddress;
529         dev->command_read.size = le16_to_cpu(endpoint->wMaxPacketSize);
530       } break;
531       case 3: {
532         direction = USB_DIR_OUT; 
533         dev->write_stream.addr = endpoint->bEndpointAddress;
534         dev->write_stream.size = le16_to_cpu(endpoint->wMaxPacketSize);
535       } break;
536       case 4: { 
537         direction = USB_DIR_IN; 
538         dev->read_stream.addr = endpoint->bEndpointAddress;
539         dev->read_stream.size = le16_to_cpu(endpoint->wMaxPacketSize);
540       } break;
541     }
542     if ((endpoint->bEndpointAddress & USB_DIR_IN) != direction) {
543       err("Endpoint has wrong direction.");
544       retval = -ENODEV;
545       goto error;
546     }
547   }
548   if (dt9812_read_info(dev, 0, &fw, sizeof(fw)) != 0) {
549     // Seems like a configuration reset is necessary if driver
550     // is reloaded while device is attached
551     int i;
552
553     usb_reset_configuration(dev->udev);
554     for (i = 0 ; i < 10 ; i++) {
555       retval = dt9812_read_info(dev, 1, &fw, sizeof(fw));
556       if (retval == 0){
557         printk("usb_reset_configuration succeded after %d iterations\n", i);
558         break;
559       }
560     }
561   }
562
563   if (dt9812_read_info(dev, 1, &dev->vendor, sizeof(dev->vendor)) != 0) {
564     err("Failed to read vendor.");
565     retval = -ENODEV;
566     goto error;
567   }
568   if (dt9812_read_info(dev, 3, &dev->product, sizeof(dev->product)) != 0) {
569     err("Failed to read product.");
570     retval = -ENODEV;
571     goto error;
572   }
573   if (dt9812_read_info(dev, 5, &dev->device, sizeof(dev->device)) != 0) {
574     err("Failed to read device.");
575     retval = -ENODEV;
576     goto error;
577   }
578   if (dt9812_read_info(dev, 7, &dev->serial, sizeof(dev->serial)) != 0) {
579     err("Failed to read serial.");
580     retval = -ENODEV;
581     goto error;
582   }
583
584   dev->vendor = le16_to_cpu(dev->vendor);
585   dev->product = le16_to_cpu(dev->product);
586   dev->device = le16_to_cpu(dev->device);
587   dev->serial = le32_to_cpu(dev->serial);
588   switch (dev->device) {
589     case DT9812_DEVID_DT9812_10: {
590       dev->analog_out_shadow[0] = 0x0800; 
591       dev->analog_out_shadow[1] = 0x800;
592     } break;
593     case DT9812_DEVID_DT9812_2PT5: {
594       dev->analog_out_shadow[0] = 0x0000; 
595       dev->analog_out_shadow[1] = 0x0000;
596     } break;
597   }
598   dev->digital_out_shadow = 0;
599
600   // save our data pointer in this interface device a
601   usb_set_intfdata(interface, dev);
602
603   // let the user know what node this device is now attached to
604   info("USB DT9812 (%4.4x.%4.4x.%4.4x) #0x%8.8x", 
605        dev->vendor, dev->product, dev->device, dev->serial);
606
607   down(&dt9812_mutex);
608   {
609     // Find a slot for the USB device
610     slot_dt9812_t *first = NULL;
611     slot_dt9812_t *best = NULL;
612  
613     for (i = 0 ; i < DT9812_NUM_SLOTS ; i++) {
614       if (!first && !dt9812[i].usb && dt9812[i].serial == 0) {
615         first = &dt9812[i];
616       }
617       if (!best && dt9812[i].serial == dev->serial) {
618         best = &dt9812[i];
619       }
620     }
621
622     if (!best) {
623       best = first;
624     }
625
626     if (best) {
627       down(&best->mutex);
628       best->usb = dev;
629       dev->slot = best;
630       up(&best->mutex);
631     }
632   }
633   up(&dt9812_mutex);
634
635   return 0;
636
637 error:
638   if (dev) {
639     KREF_PUT(&dev->kref, dt9812_delete);
640   }
641   return retval;
642 }
643
644 static void dt9812_disconnect(struct usb_interface *interface)
645 {
646   usb_dt9812_t *dev;
647   int minor = interface->minor;
648
649   down(&dt9812_mutex);
650   dev = usb_get_intfdata(interface);
651   if (dev->slot) {
652     down(&dev->slot->mutex);
653     dev->slot->usb = NULL;
654     up(&dev->slot->mutex);
655     dev->slot = NULL;
656   }
657   usb_set_intfdata(interface, NULL);
658   up(&dt9812_mutex);
659
660   /* queue final destruction */
661   KREF_PUT(&dev->kref, dt9812_delete);
662
663   info("USB Dt9812 #%d now disconnected", minor);
664 }
665
666 static struct usb_driver dt9812_usb_driver = {
667 #ifdef COMEDI_HAVE_USB_DRIVER_OWNER
668         .owner =        THIS_MODULE,
669 #endif
670         .name =         "dt9812",
671         .probe =        dt9812_probe,
672         .disconnect =   dt9812_disconnect,
673         .id_table =     dt9812_table,
674 };
675
676 /*
677  * Comedi functions
678  */
679
680 static void dt9812_comedi_open(comedi_device *dev) {
681   down(&devpriv->slot->mutex);
682   if (devpriv->slot->usb) {
683     // We have an attached device, fill in current range info
684     comedi_subdevice *s;
685   
686     s = &dev->subdevices[0];
687     s->n_chan = 8;
688     s->maxdata = 1;
689
690     s = &dev->subdevices[1];
691     s->n_chan = 8;
692     s->maxdata = 1;
693
694     s = &dev->subdevices[2];
695     s->n_chan = 8;
696     switch (devpriv->slot->usb->device) {
697       case 0: {
698         s->maxdata = 4095;
699         s->range_table = &dt9812_10_ain_range;
700       } break;
701       case 1: {
702         s->maxdata = 4095;
703         s->range_table = &dt9812_2pt5_ain_range;
704       } break;
705     }
706
707     s = &dev->subdevices[3];
708     s->n_chan = 2;
709     switch (devpriv->slot->usb->device) {
710       case 0: {
711         s->maxdata = 4095;
712         s->range_table = &dt9812_10_aout_range;
713       } break;
714       case 1: {
715         s->maxdata = 4095;
716         s->range_table = &dt9812_2pt5_aout_range;
717       } break;
718     }
719   }
720   up(&devpriv->slot->mutex);
721 }
722
723 static int dt9812_di_rinsn(comedi_device *dev, comedi_subdevice *s,
724                            comedi_insn *insn, lsampl_t *data)
725 {
726   int n;
727   u8 bits = 0;
728
729   dt9812_digital_in(devpriv->slot, &bits); 
730   for(n = 0 ; n < insn->n ; n++){
731     data[n] = ((1<<insn->chanspec) & bits) != 0;
732   }
733   return n;
734 }
735
736 static int dt9812_do_winsn(comedi_device *dev, comedi_subdevice *s,
737                            comedi_insn *insn, lsampl_t *data)
738 {
739   int n;
740   u8 bits = 0;
741
742   dt9812_digital_out_shadow(devpriv->slot, &bits); 
743   for(n = 0 ; n < insn->n ; n++){
744     u8 mask = 1<<insn->chanspec;
745
746     bits &= ~mask;
747     if (data[n]) {
748       bits |= mask;
749     }
750   }
751   dt9812_digital_out(devpriv->slot, bits); 
752   return n;
753 }
754
755
756 static int dt9812_ai_rinsn(comedi_device *dev, comedi_subdevice *s,
757                            comedi_insn *insn, lsampl_t *data)
758 {
759   int n;
760
761   for(n = 0 ; n < insn->n ; n++){
762     u16 value = 0;
763     
764     dt9812_analog_in(devpriv->slot, insn->chanspec, &value, DT9812_GAIN_1); 
765     data[n] = value;
766   }
767   return n;
768 }
769
770
771 static int dt9812_ao_rinsn(comedi_device *dev, comedi_subdevice *s,
772                            comedi_insn *insn, lsampl_t *data)
773 {
774   int n;
775
776   for(n = 0 ; n < insn->n ; n++){
777     u16 value = 0;
778
779     dt9812_analog_out_shadow(devpriv->slot, insn->chanspec, &value); 
780     data[n] = value;    
781   }
782   return n;
783 }
784
785
786 static int dt9812_ao_winsn(comedi_device *dev, comedi_subdevice *s,
787                            comedi_insn *insn, lsampl_t *data)
788 {
789   int n;
790
791   for(n = 0 ; n < insn->n ; n++){
792     dt9812_analog_out(devpriv->slot, insn->chanspec, data[n]); 
793   }
794   return n;
795 }
796
797
798 static int dt9812_attach(comedi_device *dev, comedi_devconfig *it)
799 {
800   int i;
801   comedi_subdevice *s;
802
803   dev->board_name = "dt9812";
804
805   if(alloc_private(dev,sizeof(comedi_dt9812_t)) < 0) {
806     return -ENOMEM;
807   }
808
809   // Special open routine, since USB unit may be unattached at
810   // comedi_config time, hence range can not be determined
811   dev->open = dt9812_comedi_open;
812
813   devpriv->serial = it->options[0];
814
815   // Allocate subdevices
816   if(alloc_subdevices(dev, 4) < 0) {
817     return -ENOMEM;
818   }
819          
820   /* digital input subdevice */
821   s = dev->subdevices+0;
822   s->type = COMEDI_SUBD_DI;
823   s->subdev_flags = SDF_READABLE;
824   s->n_chan = 0;
825   s->maxdata = 1;
826   s->range_table = &range_digital;
827   s->insn_read = &dt9812_di_rinsn;
828   
829   /* digital output subdevice */
830   s = dev->subdevices+1;
831   s->type = COMEDI_SUBD_DO;
832   s->subdev_flags = SDF_WRITEABLE;
833   s->n_chan = 0;
834   s->maxdata = 1;
835   s->range_table = &range_digital;
836   s->insn_write = &dt9812_do_winsn;
837   
838   /* analog input subdevice */
839   s=dev->subdevices+2;
840   s->type = COMEDI_SUBD_AI;
841   s->subdev_flags = SDF_READABLE|SDF_GROUND;
842   s->n_chan = 0;
843   s->maxdata = 1;
844   s->range_table = 0;
845   s->insn_read = &dt9812_ai_rinsn;
846   
847   /* analog output subdevice */
848   s=dev->subdevices+3;
849   s->type = COMEDI_SUBD_AO;
850   s->subdev_flags = SDF_WRITEABLE;
851   s->n_chan = 0;
852   s->maxdata = 1;
853   s->range_table = 0;
854   s->insn_write = &dt9812_ao_winsn;
855   s->insn_read = &dt9812_ao_rinsn;
856
857   printk("comedi%d: successfully attached to dt9812.\n",
858          dev->minor);
859
860   down(&dt9812_mutex);
861   // Find a slot for the comedi device
862   {
863     slot_dt9812_t *first = NULL;
864     slot_dt9812_t *best = NULL; 
865     for (i = 0 ; i < DT9812_NUM_SLOTS ; i++) {
866       if (!first && !dt9812[i].comedi) {
867         // First free slot from comedi side
868         first = &dt9812[i];
869       }
870       if (!best && 
871           dt9812[i].usb && dt9812[i].usb->serial == devpriv->serial) {
872         // We have an attaced device with matching ID
873         best = &dt9812[i];
874       }
875     }
876     if (!best) {
877       best = first;
878     }
879     if (best) {
880       down(&best->mutex);
881       best->comedi = devpriv;
882       best->serial = devpriv->serial;
883       devpriv->slot = best;
884       up(&best->mutex);
885     }
886   }
887   up(&dt9812_mutex);
888
889   return 0;
890 }
891
892 static int dt9812_detach(comedi_device *dev)
893 {
894
895   return 0;
896 }
897
898 static comedi_driver dt9812_comedi_driver = {
899         .module =       THIS_MODULE,
900         .driver_name = "dt9812",
901         .attach =       dt9812_attach,
902         .detach=        dt9812_detach,
903 };
904
905 static int __init usb_dt9812_init(void)
906 {
907   int result, i;
908
909   // Initialize all driver slots
910   for (i = 0 ; i < DT9812_NUM_SLOTS ; i++) {
911     init_MUTEX(&dt9812[i].mutex);
912     dt9812[i].serial = 0;
913     dt9812[i].usb = NULL;
914     dt9812[i].comedi = NULL;
915   }
916   dt9812[12].serial = 0x0;
917
918   // register with the USB subsystem 
919   result = usb_register(&dt9812_usb_driver);
920   if (result) {
921     err("usb_register failed. Error number %d", result);
922   }
923
924   // register with comedi
925   result = comedi_driver_register(&dt9812_comedi_driver);
926   if (result) {
927     usb_deregister(&dt9812_usb_driver);
928     err("comedi_driver_register failed. Error number %d", result);
929   }
930
931   return result;
932 }
933
934 static void __exit usb_dt9812_exit(void)
935 {
936   // unregister with comedi
937   comedi_driver_unregister(&dt9812_comedi_driver);
938
939   /* deregister this driver with the USB subsystem */
940   usb_deregister(&dt9812_usb_driver);
941 }
942
943 module_init (usb_dt9812_init);
944 module_exit (usb_dt9812_exit);
945
946 MODULE_AUTHOR("Anders Blomdell <anders.blomdell@control.lth.se>");
947 MODULE_DESCRIPTION("Comedi DT9812 driver");
948 MODULE_LICENSE("GPL");
949
950 #endif  // LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)