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