dt9812.c revision 63274cd7d38a3322d90b66a5bc976de1fb899051
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/* 26Driver: dt9812 27Description: Data Translation DT9812 USB module 28Author: anders.blomdell@control.lth.se (Anders Blomdell) 29Status: in development 30Devices: [Data Translation] DT9812 (dt9812) 31Updated: Sun Nov 20 20:18:34 EST 2005 32 33This driver works, but bulk transfers not implemented. Might be a starting point 34for someone else. I found out too late that USB has too high latencies (>1 ms) 35for 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 62static DECLARE_MUTEX(dt9812_mutex); 63 64static struct usb_device_id dt9812_table[] = { 65 {USB_DEVICE(0x0867, 0x9812)}, 66 {} /* Terminating entry */ 67}; 68 69MODULE_DEVICE_TABLE(usb, dt9812_table); 70 71typedef 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 88typedef struct comedi_dt9812 { 89 struct slot_dt9812 *slot; 90 u32 serial; 91} comedi_dt9812_t; 92 93typedef 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 100static const comedi_lrange dt9812_10_ain_range = { 1, { 101 BIP_RANGE(10), 102 } 103}; 104 105static const comedi_lrange dt9812_2pt5_ain_range = { 1, { 106 UNI_RANGE(2.5), 107 } 108}; 109 110static const comedi_lrange dt9812_10_aout_range = { 1, { 111 BIP_RANGE(10), 112 } 113}; 114 115static const comedi_lrange dt9812_2pt5_aout_range = { 1, { 116 UNI_RANGE(2.5), 117 } 118}; 119 120static slot_dt9812_t dt9812[DT9812_NUM_SLOTS]; 121 122// Useful shorthand access to private data 123#define devpriv ((comedi_dt9812_t *)dev->private) 124 125static inline usb_dt9812_t *to_dt9812_dev(struct kref *d) 126{ 127 return container_of(d, usb_dt9812_t, kref); 128} 129 130static 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 138static 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 160static 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 182static 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 199static 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 215static 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 238static 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 257static 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 270static 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 286static 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 337static 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 401static 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 416static 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 472static 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 651static 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 673static 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 687static 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 735static 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 748static 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 767static 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 782static 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 796static 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 807static 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 900static int dt9812_detach(comedi_device * dev) 901{ 902 903 return 0; 904} 905 906static comedi_driver dt9812_comedi_driver = { 907 .module = THIS_MODULE, 908 .driver_name = "dt9812", 909 .attach = dt9812_attach, 910 .detach = dt9812_detach, 911}; 912 913static 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 941static 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 950module_init(usb_dt9812_init); 951module_exit(usb_dt9812_exit); 952 953MODULE_AUTHOR("Anders Blomdell <anders.blomdell@control.lth.se>"); 954MODULE_DESCRIPTION("Comedi DT9812 driver"); 955MODULE_LICENSE("GPL"); 956 957#endif // LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) 958