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