usbduxfast.c revision 9ebfbd45f9d4ee9cd72529cf99e5f300eb398e67
1/* 2 * Copyright (C) 2004 Bernd Porr, Bernd.Porr@f2s.com 3 * 4 * This program is free software; you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation; either version 2 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the Free Software 16 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 17 */ 18 19/* 20 * I must give credit here to Chris Baugher who 21 * wrote the driver for AT-MIO-16d. I used some parts of this 22 * driver. I also must give credits to David Brownell 23 * who supported me with the USB development. 24 * 25 * Bernd Porr 26 * 27 * 28 * Revision history: 29 * 0.9: Dropping the first data packet which seems to be from the last transfer. 30 * Buffer overflows in the FX2 are handed over to comedi. 31 * 0.92: Dropping now 4 packets. The quad buffer has to be emptied. 32 * Added insn command basically for testing. Sample rate is 33 * 1MHz/16ch=62.5kHz 34 * 0.99: Ian Abbott pointed out a bug which has been corrected. Thanks! 35 * 0.99a: added external trigger. 36 * 1.00: added firmware kernel request to the driver which fixed 37 * udev coldplug problem 38 */ 39 40#include <linux/kernel.h> 41#include <linux/firmware.h> 42#include <linux/module.h> 43#include <linux/init.h> 44#include <linux/slab.h> 45#include <linux/input.h> 46#include <linux/usb.h> 47#include <linux/smp_lock.h> 48#include <linux/fcntl.h> 49#include <linux/compiler.h> 50#include "comedi_fc.h" 51#include "../comedidev.h" 52 53#define DRIVER_VERSION "v1.0" 54#define DRIVER_AUTHOR "Bernd Porr, BerndPorr@f2s.com" 55#define DRIVER_DESC "USB-DUXfast, BerndPorr@f2s.com" 56#define BOARDNAME "usbduxfast" 57 58/* 59 * timeout for the USB-transfer 60 */ 61#define EZTIMEOUT 30 62 63/* 64 * constants for "firmware" upload and download 65 */ 66#define USBDUXFASTSUB_FIRMWARE 0xA0 67#define VENDOR_DIR_IN 0xC0 68#define VENDOR_DIR_OUT 0x40 69 70/* 71 * internal adresses of the 8051 processor 72 */ 73#define USBDUXFASTSUB_CPUCS 0xE600 74 75/* 76 * max lenghth of the transfer-buffer for software upload 77 */ 78#define TB_LEN 0x2000 79 80/* 81 * input endpoint number 82 */ 83#define BULKINEP 6 84 85/* 86 * endpoint for the A/D channellist: bulk OUT 87 */ 88#define CHANNELLISTEP 4 89 90/* 91 * number of channels 92 */ 93#define NUMCHANNELS 32 94 95/* 96 * size of the waveform descriptor 97 */ 98#define WAVESIZE 0x20 99 100/* 101 * size of one A/D value 102 */ 103#define SIZEADIN (sizeof(int16_t)) 104 105/* 106 * size of the input-buffer IN BYTES 107 */ 108#define SIZEINBUF 512 109 110/* 111 * 16 bytes 112 */ 113#define SIZEINSNBUF 512 114 115/* 116 * size of the buffer for the dux commands in bytes 117 */ 118#define SIZEOFDUXBUFFER 256 119 120/* 121 * number of in-URBs which receive the data: min=5 122 */ 123#define NUMOFINBUFFERSHIGH 10 124 125/* 126 * total number of usbduxfast devices 127 */ 128#define NUMUSBDUXFAST 16 129 130/* 131 * number of subdevices 132 */ 133#define N_SUBDEVICES 1 134 135/* 136 * analogue in subdevice 137 */ 138#define SUBDEV_AD 0 139 140/* 141 * min delay steps for more than one channel 142 * basically when the mux gives up ;-) 143 * 144 * steps at 30MHz in the FX2 145 */ 146#define MIN_SAMPLING_PERIOD 9 147 148/* 149 * max number of 1/30MHz delay steps 150 */ 151#define MAX_SAMPLING_PERIOD 500 152 153/* 154 * number of received packets to ignore before we start handing data 155 * over to comedi, it's quad buffering and we have to ignore 4 packets 156 */ 157#define PACKETS_TO_IGNORE 4 158 159/* 160 * comedi constants 161 */ 162static const struct comedi_lrange range_usbduxfast_ai_range = { 163 2, {BIP_RANGE(0.75), BIP_RANGE(0.5)} 164}; 165 166/* 167 * private structure of one subdevice 168 * 169 * this is the structure which holds all the data of this driver 170 * one sub device just now: A/D 171 */ 172struct usbduxfastsub_s { 173 int attached; /* is attached? */ 174 int probed; /* is it associated with a subdevice? */ 175 struct usb_device *usbdev; /* pointer to the usb-device */ 176 struct urb *urbIn; /* BULK-transfer handling: urb */ 177 int8_t *transfer_buffer; 178 int16_t *insnBuffer; /* input buffer for single insn */ 179 int ifnum; /* interface number */ 180 struct usb_interface *interface; /* interface structure */ 181 struct comedi_device *comedidev; /* comedi device for the interrupt 182 context */ 183 short int ai_cmd_running; /* asynchronous command is running */ 184 short int ai_continous; /* continous aquisition */ 185 long int ai_sample_count; /* number of samples to aquire */ 186 uint8_t *dux_commands; /* commands */ 187 int ignore; /* counter which ignores the first 188 buffers */ 189 struct semaphore sem; 190}; 191 192/* 193 * The pointer to the private usb-data of the driver 194 * is also the private data for the comedi-device. 195 * This has to be global as the usb subsystem needs 196 * global variables. The other reason is that this 197 * structure must be there _before_ any comedi 198 * command is issued. The usb subsystem must be 199 * initialised before comedi can access it. 200 */ 201static struct usbduxfastsub_s usbduxfastsub[NUMUSBDUXFAST]; 202 203static DECLARE_MUTEX(start_stop_sem); 204 205/* 206 * bulk transfers to usbduxfast 207 */ 208#define SENDADCOMMANDS 0 209#define SENDINITEP6 1 210 211static int send_dux_commands(struct usbduxfastsub_s *udfs, int cmd_type) 212{ 213 int tmp, nsent; 214 215 udfs->dux_commands[0] = cmd_type; 216 217#ifdef CONFIG_COMEDI_DEBUG 218 printk(KERN_DEBUG "comedi%d: usbduxfast: dux_commands: ", 219 udfs->comedidev->minor); 220 for (tmp = 0; tmp < SIZEOFDUXBUFFER; tmp++) 221 printk(" %02x", udfs->dux_commands[tmp]); 222 printk("\n"); 223#endif 224 225 tmp = usb_bulk_msg(udfs->usbdev, 226 usb_sndbulkpipe(udfs->usbdev, CHANNELLISTEP), 227 udfs->dux_commands, SIZEOFDUXBUFFER, &nsent, 10000); 228 if (tmp < 0) 229 printk(KERN_ERR "comedi%d: could not transmit dux_commands to" 230 "the usb-device, err=%d\n", udfs->comedidev->minor, tmp); 231 return tmp; 232} 233 234/* 235 * Stops the data acquision. 236 * It should be safe to call this function from any context. 237 */ 238static int usbduxfastsub_unlink_InURBs(struct usbduxfastsub_s *udfs) 239{ 240 int j = 0; 241 int err = 0; 242 243 if (udfs && udfs->urbIn) { 244 udfs->ai_cmd_running = 0; 245 /* waits until a running transfer is over */ 246 usb_kill_urb(udfs->urbIn); 247 j = 0; 248 } 249#ifdef CONFIG_COMEDI_DEBUG 250 printk(KERN_DEBUG "comedi: usbduxfast: unlinked InURB: res=%d\n", j); 251#endif 252 return err; 253} 254 255/* 256 * This will stop a running acquisition operation. 257 * Is called from within this driver from both the 258 * interrupt context and from comedi. 259 */ 260static int usbduxfast_ai_stop(struct usbduxfastsub_s *udfs, int do_unlink) 261{ 262 int ret = 0; 263 264 if (!udfs) { 265 printk(KERN_ERR "comedi?: usbduxfast_ai_stop: udfs=NULL!\n"); 266 return -EFAULT; 267 } 268#ifdef CONFIG_COMEDI_DEBUG 269 printk(KERN_DEBUG "comedi: usbduxfast_ai_stop\n"); 270#endif 271 272 udfs->ai_cmd_running = 0; 273 274 if (do_unlink) 275 ret = usbduxfastsub_unlink_InURBs(udfs); /* stop aquistion */ 276 277 return ret; 278} 279 280/* 281 * This will cancel a running acquisition operation. 282 * This is called by comedi but never from inside the driver. 283 */ 284static int usbduxfast_ai_cancel(struct comedi_device *dev, 285 struct comedi_subdevice *s) 286{ 287 struct usbduxfastsub_s *udfs; 288 int ret; 289 290 /* force unlink of all urbs */ 291#ifdef CONFIG_COMEDI_DEBUG 292 printk(KERN_DEBUG "comedi: usbduxfast_ai_cancel\n"); 293#endif 294 udfs = dev->private; 295 if (!udfs) { 296 printk(KERN_ERR "comedi: usbduxfast_ai_cancel: udfs=NULL\n"); 297 return -EFAULT; 298 } 299 down(&udfs->sem); 300 if (!udfs->probed) { 301 up(&udfs->sem); 302 return -ENODEV; 303 } 304 /* unlink */ 305 ret = usbduxfast_ai_stop(udfs, 1); 306 up(&udfs->sem); 307 308 return ret; 309} 310 311/* 312 * analogue IN 313 * interrupt service routine 314 */ 315static void usbduxfastsub_ai_Irq(struct urb *urb) 316{ 317 int n, err; 318 struct usbduxfastsub_s *udfs; 319 struct comedi_device *this_comedidev; 320 struct comedi_subdevice *s; 321 uint16_t *p; 322 323 /* sanity checks - is the urb there? */ 324 if (!urb) { 325 printk(KERN_ERR "comedi_: usbduxfast_: ao int-handler called " 326 "with urb=NULL!\n"); 327 return; 328 } 329 /* the context variable points to the subdevice */ 330 this_comedidev = urb->context; 331 if (!this_comedidev) { 332 printk(KERN_ERR "comedi_: usbduxfast_: urb context is a NULL " 333 "pointer!\n"); 334 return; 335 } 336 /* the private structure of the subdevice is usbduxfastsub_s */ 337 udfs = this_comedidev->private; 338 if (!udfs) { 339 printk(KERN_ERR "comedi_: usbduxfast_: private of comedi " 340 "subdev is a NULL pointer!\n"); 341 return; 342 } 343 /* are we running a command? */ 344 if (unlikely(!udfs->ai_cmd_running)) { 345 /* 346 * not running a command 347 * do not continue execution if no asynchronous command 348 * is running in particular not resubmit 349 */ 350 return; 351 } 352 353 if (unlikely(!udfs->attached)) { 354 /* no comedi device there */ 355 return; 356 } 357 /* subdevice which is the AD converter */ 358 s = this_comedidev->subdevices + SUBDEV_AD; 359 360 /* first we test if something unusual has just happened */ 361 switch (urb->status) { 362 case 0: 363 break; 364 365 /* 366 * happens after an unlink command or when the device 367 * is plugged out 368 */ 369 case -ECONNRESET: 370 case -ENOENT: 371 case -ESHUTDOWN: 372 case -ECONNABORTED: 373 /* tell this comedi */ 374 s->async->events |= COMEDI_CB_EOA; 375 s->async->events |= COMEDI_CB_ERROR; 376 comedi_event(udfs->comedidev, s); 377 /* stop the transfer w/o unlink */ 378 usbduxfast_ai_stop(udfs, 0); 379 return; 380 381 default: 382 printk("comedi%d: usbduxfast: non-zero urb status received in " 383 "ai intr context: %d\n", 384 udfs->comedidev->minor, urb->status); 385 s->async->events |= COMEDI_CB_EOA; 386 s->async->events |= COMEDI_CB_ERROR; 387 comedi_event(udfs->comedidev, s); 388 usbduxfast_ai_stop(udfs, 0); 389 return; 390 } 391 392 p = urb->transfer_buffer; 393 if (!udfs->ignore) { 394 if (!udfs->ai_continous) { 395 /* not continous, fixed number of samples */ 396 n = urb->actual_length / sizeof(uint16_t); 397 if (unlikely(udfs->ai_sample_count < n)) { 398 /* 399 * we have send only a fraction of the bytes 400 * received 401 */ 402 cfc_write_array_to_buffer(s, 403 urb->transfer_buffer, 404 udfs->ai_sample_count 405 * sizeof(uint16_t)); 406 usbduxfast_ai_stop(udfs, 0); 407 /* tell comedi that the acquistion is over */ 408 s->async->events |= COMEDI_CB_EOA; 409 comedi_event(udfs->comedidev, s); 410 return; 411 } 412 udfs->ai_sample_count -= n; 413 } 414 /* write the full buffer to comedi */ 415 err = cfc_write_array_to_buffer(s, urb->transfer_buffer, 416 urb->actual_length); 417 if (unlikely(err == 0)) { 418 /* buffer overflow */ 419 usbduxfast_ai_stop(udfs, 0); 420 return; 421 } 422 423 /* tell comedi that data is there */ 424 comedi_event(udfs->comedidev, s); 425 426 } else { 427 /* ignore this packet */ 428 udfs->ignore--; 429 } 430 431 /* 432 * command is still running 433 * resubmit urb for BULK transfer 434 */ 435 urb->dev = udfs->usbdev; 436 urb->status = 0; 437 err = usb_submit_urb(urb, GFP_ATOMIC); 438 if (err < 0) { 439 printk(KERN_ERR "comedi%d: usbduxfast: urb resubm failed: %d", 440 udfs->comedidev->minor, err); 441 s->async->events |= COMEDI_CB_EOA; 442 s->async->events |= COMEDI_CB_ERROR; 443 comedi_event(udfs->comedidev, s); 444 usbduxfast_ai_stop(udfs, 0); 445 } 446} 447 448static int usbduxfastsub_start(struct usbduxfastsub_s *udfs) 449{ 450 int ret; 451 unsigned char local_transfer_buffer[16]; 452 453 /* 7f92 to zero */ 454 local_transfer_buffer[0] = 0; 455 ret = usb_control_msg(udfs->usbdev, usb_sndctrlpipe(udfs->usbdev, 0), USBDUXFASTSUB_FIRMWARE, /* bRequest, "Firmware" */ 456 VENDOR_DIR_OUT, /* bmRequestType */ 457 USBDUXFASTSUB_CPUCS, /* Value */ 458 0x0000, /* Index */ 459 local_transfer_buffer, /* address of the transfer buffer */ 460 1, /* Length */ 461 EZTIMEOUT); /* Timeout */ 462 if (ret < 0) { 463 printk("comedi_: usbduxfast_: control msg failed (start)\n"); 464 return ret; 465 } 466 467 return 0; 468} 469 470static int usbduxfastsub_stop(struct usbduxfastsub_s *udfs) 471{ 472 int ret; 473 unsigned char local_transfer_buffer[16]; 474 475 /* 7f92 to one */ 476 local_transfer_buffer[0] = 1; 477 ret = usb_control_msg(udfs->usbdev, usb_sndctrlpipe(udfs->usbdev, 0), USBDUXFASTSUB_FIRMWARE, /* bRequest, "Firmware" */ 478 VENDOR_DIR_OUT, /* bmRequestType */ 479 USBDUXFASTSUB_CPUCS, /* Value */ 480 0x0000, /* Index */ 481 local_transfer_buffer, 1, /* Length */ 482 EZTIMEOUT); /* Timeout */ 483 if (ret < 0) { 484 printk(KERN_ERR "comedi_: usbduxfast: control msg failed " 485 "(stop)\n"); 486 return ret; 487 } 488 489 return 0; 490} 491 492static int usbduxfastsub_upload(struct usbduxfastsub_s *udfs, 493 unsigned char *local_transfer_buffer, 494 unsigned int startAddr, unsigned int len) 495{ 496 int ret; 497 498#ifdef CONFIG_COMEDI_DEBUG 499 printk(KERN_DEBUG "comedi: usbduxfast: uploading %d bytes", len); 500 printk(KERN_DEBUG " to addr %d, first byte=%d.\n", 501 startAddr, local_transfer_buffer[0]); 502#endif 503 ret = usb_control_msg(udfs->usbdev, usb_sndctrlpipe(udfs->usbdev, 0), USBDUXFASTSUB_FIRMWARE, /* brequest, firmware */ 504 VENDOR_DIR_OUT, /* bmRequestType */ 505 startAddr, /* value */ 506 0x0000, /* index */ 507 local_transfer_buffer, /* our local safe buffer */ 508 len, /* length */ 509 EZTIMEOUT); /* timeout */ 510 511#ifdef CONFIG_COMEDI_DEBUG 512 printk(KERN_DEBUG "comedi_: usbduxfast: result=%d\n", ret); 513#endif 514 515 if (ret < 0) { 516 printk(KERN_ERR "comedi_: usbduxfast: uppload failed\n"); 517 return ret; 518 } 519 520 return 0; 521} 522 523int usbduxfastsub_submit_InURBs(struct usbduxfastsub_s *udfs) 524{ 525 int ret; 526 527 if (!udfs) 528 return -EFAULT; 529 530 usb_fill_bulk_urb(udfs->urbIn, udfs->usbdev, 531 usb_rcvbulkpipe(udfs->usbdev, BULKINEP), 532 udfs->transfer_buffer, 533 SIZEINBUF, usbduxfastsub_ai_Irq, udfs->comedidev); 534 535#ifdef CONFIG_COMEDI_DEBUG 536 printk(KERN_DEBUG "comedi%d: usbduxfast: submitting in-urb: " 537 "0x%p,0x%p\n", udfs->comedidev->minor, udfs->urbIn->context, 538 udfs->urbIn->dev); 539#endif 540 ret = usb_submit_urb(udfs->urbIn, GFP_ATOMIC); 541 if (ret) { 542 printk(KERN_ERR "comedi_: usbduxfast: ai: usb_submit_urb error" 543 " %d\n", ret); 544 return ret; 545 } 546 return 0; 547} 548 549static int usbduxfast_ai_cmdtest(struct comedi_device *dev, 550 struct comedi_subdevice *s, 551 struct comedi_cmd *cmd) 552{ 553 int err = 0, stop_mask = 0; 554 long int steps, tmp; 555 int minSamplPer; 556 struct usbduxfastsub_s *udfs = dev->private; 557 558 if (!udfs->probed) 559 return -ENODEV; 560 561#ifdef CONFIG_COMEDI_DEBUG 562 printk(KERN_DEBUG "comedi%d: usbduxfast_ai_cmdtest\n", dev->minor); 563 printk(KERN_DEBUG "comedi%d: usbduxfast: convert_arg=%u " 564 "scan_begin_arg=%u\n", 565 dev->minor, cmd->convert_arg, cmd->scan_begin_arg); 566#endif 567 /* step 1: make sure trigger sources are trivially valid */ 568 569 tmp = cmd->start_src; 570 cmd->start_src &= TRIG_NOW | TRIG_EXT | TRIG_INT; 571 if (!cmd->start_src || tmp != cmd->start_src) 572 err++; 573 574 tmp = cmd->scan_begin_src; 575 cmd->scan_begin_src &= TRIG_TIMER | TRIG_FOLLOW | TRIG_EXT; 576 if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) 577 err++; 578 579 tmp = cmd->convert_src; 580 cmd->convert_src &= TRIG_TIMER | TRIG_EXT; 581 if (!cmd->convert_src || tmp != cmd->convert_src) 582 err++; 583 584 tmp = cmd->scan_end_src; 585 cmd->scan_end_src &= TRIG_COUNT; 586 if (!cmd->scan_end_src || tmp != cmd->scan_end_src) 587 err++; 588 589 tmp = cmd->stop_src; 590 stop_mask = TRIG_COUNT | TRIG_NONE; 591 cmd->stop_src &= stop_mask; 592 if (!cmd->stop_src || tmp != cmd->stop_src) 593 err++; 594 595 if (err) 596 return 1; 597 598 /* 599 * step 2: make sure trigger sources are unique and mutually compatible 600 */ 601 602 if (cmd->start_src != TRIG_NOW && 603 cmd->start_src != TRIG_EXT && cmd->start_src != TRIG_INT) 604 err++; 605 if (cmd->scan_begin_src != TRIG_TIMER && 606 cmd->scan_begin_src != TRIG_FOLLOW && 607 cmd->scan_begin_src != TRIG_EXT) 608 err++; 609 if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT) 610 err++; 611 if (cmd->stop_src != TRIG_COUNT && 612 cmd->stop_src != TRIG_EXT && cmd->stop_src != TRIG_NONE) 613 err++; 614 615 /* can't have external stop and start triggers at once */ 616 if (cmd->start_src == TRIG_EXT && cmd->stop_src == TRIG_EXT) 617 err++; 618 619 if (err) 620 return 2; 621 622 /* step 3: make sure arguments are trivially compatible */ 623 624 if (cmd->start_src == TRIG_NOW && cmd->start_arg != 0) { 625 cmd->start_arg = 0; 626 err++; 627 } 628 629 if (!cmd->chanlist_len) 630 err++; 631 632 if (cmd->scan_end_arg != cmd->chanlist_len) { 633 cmd->scan_end_arg = cmd->chanlist_len; 634 err++; 635 } 636 637 if (cmd->chanlist_len == 1) 638 minSamplPer = 1; 639 else 640 minSamplPer = MIN_SAMPLING_PERIOD; 641 642 if (cmd->convert_src == TRIG_TIMER) { 643 steps = cmd->convert_arg * 30; 644 if (steps < (minSamplPer * 1000)) 645 steps = minSamplPer * 1000; 646 647 if (steps > (MAX_SAMPLING_PERIOD * 1000)) 648 steps = MAX_SAMPLING_PERIOD * 1000; 649 650 /* calc arg again */ 651 tmp = steps / 30; 652 if (cmd->convert_arg != tmp) { 653 cmd->convert_arg = tmp; 654 err++; 655 } 656 } 657 658 if (cmd->scan_begin_src == TRIG_TIMER) 659 err++; 660 661 /* stop source */ 662 switch (cmd->stop_src) { 663 case TRIG_COUNT: 664 if (!cmd->stop_arg) { 665 cmd->stop_arg = 1; 666 err++; 667 } 668 break; 669 case TRIG_NONE: 670 if (cmd->stop_arg != 0) { 671 cmd->stop_arg = 0; 672 err++; 673 } 674 break; 675 /* 676 * TRIG_EXT doesn't care since it doesn't trigger 677 * off a numbered channel 678 */ 679 default: 680 break; 681 } 682 683 if (err) 684 return 3; 685 686 /* step 4: fix up any arguments */ 687 688 return 0; 689 690} 691 692static int usbduxfast_ai_inttrig(struct comedi_device *dev, 693 struct comedi_subdevice *s, 694 unsigned int trignum) 695{ 696 int ret; 697 struct usbduxfastsub_s *udfs = dev->private; 698 699 if (!udfs) 700 return -EFAULT; 701 702 down(&udfs->sem); 703 if (!udfs->probed) { 704 up(&udfs->sem); 705 return -ENODEV; 706 } 707#ifdef CONFIG_COMEDI_DEBUG 708 printk(KERN_DEBUG "comedi%d: usbduxfast_ai_inttrig\n", dev->minor); 709#endif 710 711 if (trignum != 0) { 712 printk(KERN_ERR "comedi%d: usbduxfast_ai_inttrig: invalid" 713 " trignum\n", dev->minor); 714 up(&udfs->sem); 715 return -EINVAL; 716 } 717 if (!udfs->ai_cmd_running) { 718 udfs->ai_cmd_running = 1; 719 ret = usbduxfastsub_submit_InURBs(udfs); 720 if (ret < 0) { 721 printk(KERN_ERR "comedi%d: usbduxfast_ai_inttrig: " 722 "urbSubmit: err=%d\n", dev->minor, ret); 723 udfs->ai_cmd_running = 0; 724 up(&udfs->sem); 725 return ret; 726 } 727 s->async->inttrig = NULL; 728 } else { 729 printk(KERN_ERR "comedi%d: ai_inttrig but acqu is already" 730 " running\n", dev->minor); 731 } 732 up(&udfs->sem); 733 return 1; 734} 735 736/* 737 * offsets for the GPIF bytes 738 * the first byte is the command byte 739 */ 740#define LENBASE (1+0x00) 741#define OPBASE (1+0x08) 742#define OUTBASE (1+0x10) 743#define LOGBASE (1+0x18) 744 745static int usbduxfast_ai_cmd(struct comedi_device *dev, 746 struct comedi_subdevice *s) 747{ 748 struct comedi_cmd *cmd = &s->async->cmd; 749 unsigned int chan, gain, rngmask = 0xff; 750 int i, j, ret; 751 struct usbduxfastsub_s *udfs; 752 int result; 753 long steps, steps_tmp; 754 755#ifdef CONFIG_COMEDI_DEBUG 756 printk(KERN_DEBUG "comedi%d: usbduxfast_ai_cmd\n", dev->minor); 757#endif 758 udfs = dev->private; 759 if (!udfs) 760 return -EFAULT; 761 762 down(&udfs->sem); 763 if (!udfs->probed) { 764 up(&udfs->sem); 765 return -ENODEV; 766 } 767 if (udfs->ai_cmd_running) { 768 printk(KERN_ERR "comedi%d: ai_cmd not possible. Another ai_cmd" 769 " is running.\n", dev->minor); 770 up(&udfs->sem); 771 return -EBUSY; 772 } 773 /* set current channel of the running aquisition to zero */ 774 s->async->cur_chan = 0; 775 776 /* 777 * ignore the first buffers from the device if there 778 * is an error condition 779 */ 780 udfs->ignore = PACKETS_TO_IGNORE; 781 782 if (cmd->chanlist_len > 0) { 783 gain = CR_RANGE(cmd->chanlist[0]); 784 for (i = 0; i < cmd->chanlist_len; ++i) { 785 chan = CR_CHAN(cmd->chanlist[i]); 786 if (chan != i) { 787 printk(KERN_ERR "comedi%d: cmd is accepting " 788 "only consecutive channels.\n", 789 dev->minor); 790 up(&udfs->sem); 791 return -EINVAL; 792 } 793 if ((gain != CR_RANGE(cmd->chanlist[i])) 794 && (cmd->chanlist_len > 3)) { 795 printk(KERN_ERR "comedi%d: the gain must be" 796 " the same for all channels.\n", 797 dev->minor); 798 up(&udfs->sem); 799 return -EINVAL; 800 } 801 if (i >= NUMCHANNELS) { 802 printk(KERN_ERR "comedi%d: channel list too" 803 " long\n", dev->minor); 804 break; 805 } 806 } 807 } 808 steps = 0; 809 if (cmd->scan_begin_src == TRIG_TIMER) { 810 printk(KERN_ERR "comedi%d: usbduxfast: " 811 "scan_begin_src==TRIG_TIMER not valid.\n", dev->minor); 812 up(&udfs->sem); 813 return -EINVAL; 814 } 815 if (cmd->convert_src == TRIG_TIMER) 816 steps = (cmd->convert_arg * 30) / 1000; 817 818 if ((steps < MIN_SAMPLING_PERIOD) && (cmd->chanlist_len != 1)) { 819 printk(KERN_ERR "comedi%d: usbduxfast: ai_cmd: steps=%ld, " 820 "scan_begin_arg=%d. Not properly tested by cmdtest?\n", 821 dev->minor, steps, cmd->scan_begin_arg); 822 up(&udfs->sem); 823 return -EINVAL; 824 } 825 if (steps > MAX_SAMPLING_PERIOD) { 826 printk(KERN_ERR "comedi%d: usbduxfast: ai_cmd: sampling rate " 827 "too low.\n", dev->minor); 828 up(&udfs->sem); 829 return -EINVAL; 830 } 831 if ((cmd->start_src == TRIG_EXT) && (cmd->chanlist_len != 1) 832 && (cmd->chanlist_len != 16)) { 833 printk(KERN_ERR "comedi%d: usbduxfast: ai_cmd: TRIG_EXT only" 834 " with 1 or 16 channels possible.\n", dev->minor); 835 up(&udfs->sem); 836 return -EINVAL; 837 } 838#ifdef CONFIG_COMEDI_DEBUG 839 printk(KERN_DEBUG "comedi%d: usbduxfast: steps=%ld, convert_arg=%u\n", 840 dev->minor, steps, cmd->convert_arg); 841#endif 842 843 switch (cmd->chanlist_len) { 844 case 1: 845 /* 846 * one channel 847 */ 848 849 if (CR_RANGE(cmd->chanlist[0]) > 0) 850 rngmask = 0xff - 0x04; 851 else 852 rngmask = 0xff; 853 854 /* 855 * for external trigger: looping in this state until 856 * the RDY0 pin becomes zero 857 */ 858 859 /* we loop here until ready has been set */ 860 if (cmd->start_src == TRIG_EXT) { 861 /* branch back to state 0 */ 862 udfs->dux_commands[LENBASE + 0] = 0x01; 863 /* deceision state w/o data */ 864 udfs->dux_commands[OPBASE + 0] = 0x01; 865 udfs->dux_commands[OUTBASE + 0] = 0xFF & rngmask; 866 /* RDY0 = 0 */ 867 udfs->dux_commands[LOGBASE + 0] = 0x00; 868 } else { /* we just proceed to state 1 */ 869 udfs->dux_commands[LENBASE + 0] = 1; 870 udfs->dux_commands[OPBASE + 0] = 0; 871 udfs->dux_commands[OUTBASE + 0] = 0xFF & rngmask; 872 udfs->dux_commands[LOGBASE + 0] = 0; 873 } 874 875 if (steps < MIN_SAMPLING_PERIOD) { 876 /* for fast single channel aqu without mux */ 877 if (steps <= 1) { 878 /* 879 * we just stay here at state 1 and rexecute 880 * the same state this gives us 30MHz sampling 881 * rate 882 */ 883 884 /* branch back to state 1 */ 885 udfs->dux_commands[LENBASE + 1] = 0x89; 886 /* deceision state with data */ 887 udfs->dux_commands[OPBASE + 1] = 0x03; 888 udfs->dux_commands[OUTBASE + 1] = 889 0xFF & rngmask; 890 /* doesn't matter */ 891 udfs->dux_commands[LOGBASE + 1] = 0xFF; 892 } else { 893 /* 894 * we loop through two states: data and delay 895 * max rate is 15MHz 896 */ 897 udfs->dux_commands[LENBASE + 1] = steps - 1; 898 /* data */ 899 udfs->dux_commands[OPBASE + 1] = 0x02; 900 udfs->dux_commands[OUTBASE + 1] = 901 0xFF & rngmask; 902 /* doesn't matter */ 903 udfs->dux_commands[LOGBASE + 1] = 0; 904 /* branch back to state 1 */ 905 udfs->dux_commands[LENBASE + 2] = 0x09; 906 /* deceision state w/o data */ 907 udfs->dux_commands[OPBASE + 2] = 0x01; 908 udfs->dux_commands[OUTBASE + 2] = 909 0xFF & rngmask; 910 /* doesn't matter */ 911 udfs->dux_commands[LOGBASE + 2] = 0xFF; 912 } 913 } else { 914 /* 915 * we loop through 3 states: 2x delay and 1x data 916 * this gives a min sampling rate of 60kHz 917 */ 918 919 /* we have 1 state with duration 1 */ 920 steps = steps - 1; 921 922 /* do the first part of the delay */ 923 udfs->dux_commands[LENBASE + 1] = steps / 2; 924 udfs->dux_commands[OPBASE + 1] = 0; 925 udfs->dux_commands[OUTBASE + 1] = 0xFF & rngmask; 926 udfs->dux_commands[LOGBASE + 1] = 0; 927 928 /* and the second part */ 929 udfs->dux_commands[LENBASE + 2] = steps - steps / 2; 930 udfs->dux_commands[OPBASE + 2] = 0; 931 udfs->dux_commands[OUTBASE + 2] = 0xFF & rngmask; 932 udfs->dux_commands[LOGBASE + 2] = 0; 933 934 /* get the data and branch back */ 935 936 /* branch back to state 1 */ 937 udfs->dux_commands[LENBASE + 3] = 0x09; 938 /* deceision state w data */ 939 udfs->dux_commands[OPBASE + 3] = 0x03; 940 udfs->dux_commands[OUTBASE + 3] = 0xFF & rngmask; 941 /* doesn't matter */ 942 udfs->dux_commands[LOGBASE + 3] = 0xFF; 943 } 944 break; 945 946 case 2: 947 /* 948 * two channels 949 * commit data to the FIFO 950 */ 951 952 if (CR_RANGE(cmd->chanlist[0]) > 0) 953 rngmask = 0xff - 0x04; 954 else 955 rngmask = 0xff; 956 957 udfs->dux_commands[LENBASE + 0] = 1; 958 /* data */ 959 udfs->dux_commands[OPBASE + 0] = 0x02; 960 udfs->dux_commands[OUTBASE + 0] = 0xFF & rngmask; 961 udfs->dux_commands[LOGBASE + 0] = 0; 962 963 /* we have 1 state with duration 1: state 0 */ 964 steps_tmp = steps - 1; 965 966 if (CR_RANGE(cmd->chanlist[1]) > 0) 967 rngmask = 0xff - 0x04; 968 else 969 rngmask = 0xff; 970 971 /* do the first part of the delay */ 972 udfs->dux_commands[LENBASE + 1] = steps_tmp / 2; 973 udfs->dux_commands[OPBASE + 1] = 0; 974 /* count */ 975 udfs->dux_commands[OUTBASE + 1] = 0xFE & rngmask; 976 udfs->dux_commands[LOGBASE + 1] = 0; 977 978 /* and the second part */ 979 udfs->dux_commands[LENBASE + 2] = steps_tmp - steps_tmp / 2; 980 udfs->dux_commands[OPBASE + 2] = 0; 981 udfs->dux_commands[OUTBASE + 2] = 0xFF & rngmask; 982 udfs->dux_commands[LOGBASE + 2] = 0; 983 984 udfs->dux_commands[LENBASE + 3] = 1; 985 /* data */ 986 udfs->dux_commands[OPBASE + 3] = 0x02; 987 udfs->dux_commands[OUTBASE + 3] = 0xFF & rngmask; 988 udfs->dux_commands[LOGBASE + 3] = 0; 989 990 /* 991 * we have 2 states with duration 1: step 6 and 992 * the IDLE state 993 */ 994 steps_tmp = steps - 2; 995 996 if (CR_RANGE(cmd->chanlist[0]) > 0) 997 rngmask = 0xff - 0x04; 998 else 999 rngmask = 0xff; 1000 1001 /* do the first part of the delay */ 1002 udfs->dux_commands[LENBASE + 4] = steps_tmp / 2; 1003 udfs->dux_commands[OPBASE + 4] = 0; 1004 /* reset */ 1005 udfs->dux_commands[OUTBASE + 4] = (0xFF - 0x02) & rngmask; 1006 udfs->dux_commands[LOGBASE + 4] = 0; 1007 1008 /* and the second part */ 1009 udfs->dux_commands[LENBASE + 5] = steps_tmp - steps_tmp / 2; 1010 udfs->dux_commands[OPBASE + 5] = 0; 1011 udfs->dux_commands[OUTBASE + 5] = 0xFF & rngmask; 1012 udfs->dux_commands[LOGBASE + 5] = 0; 1013 1014 udfs->dux_commands[LENBASE + 6] = 1; 1015 udfs->dux_commands[OPBASE + 6] = 0; 1016 udfs->dux_commands[OUTBASE + 6] = 0xFF & rngmask; 1017 udfs->dux_commands[LOGBASE + 6] = 0; 1018 break; 1019 1020 case 3: 1021 /* 1022 * three channels 1023 */ 1024 for (j = 0; j < 1; j++) { 1025 if (CR_RANGE(cmd->chanlist[j]) > 0) 1026 rngmask = 0xff - 0x04; 1027 else 1028 rngmask = 0xff; 1029 /* 1030 * commit data to the FIFO and do the first part 1031 * of the delay 1032 */ 1033 udfs->dux_commands[LENBASE + j * 2] = steps / 2; 1034 /* data */ 1035 udfs->dux_commands[OPBASE + j * 2] = 0x02; 1036 /* no change */ 1037 udfs->dux_commands[OUTBASE + j * 2] = 0xFF & rngmask; 1038 udfs->dux_commands[LOGBASE + j * 2] = 0; 1039 1040 if (CR_RANGE(cmd->chanlist[j + 1]) > 0) 1041 rngmask = 0xff - 0x04; 1042 else 1043 rngmask = 0xff; 1044 1045 /* do the second part of the delay */ 1046 udfs->dux_commands[LENBASE + j * 2 + 1] = 1047 steps - steps / 2; 1048 /* no data */ 1049 udfs->dux_commands[OPBASE + j * 2 + 1] = 0; 1050 /* count */ 1051 udfs->dux_commands[OUTBASE + j * 2 + 1] = 1052 0xFE & rngmask; 1053 udfs->dux_commands[LOGBASE + j * 2 + 1] = 0; 1054 } 1055 1056 /* 2 steps with duration 1: the idele step and step 6: */ 1057 steps_tmp = steps - 2; 1058 1059 /* commit data to the FIFO and do the first part of the delay */ 1060 udfs->dux_commands[LENBASE + 4] = steps_tmp / 2; 1061 /* data */ 1062 udfs->dux_commands[OPBASE + 4] = 0x02; 1063 udfs->dux_commands[OUTBASE + 4] = 0xFF & rngmask; 1064 udfs->dux_commands[LOGBASE + 4] = 0; 1065 1066 if (CR_RANGE(cmd->chanlist[0]) > 0) 1067 rngmask = 0xff - 0x04; 1068 else 1069 rngmask = 0xff; 1070 1071 /* do the second part of the delay */ 1072 udfs->dux_commands[LENBASE + 5] = steps_tmp - steps_tmp / 2; 1073 /* no data */ 1074 udfs->dux_commands[OPBASE + 5] = 0; 1075 /* reset */ 1076 udfs->dux_commands[OUTBASE + 5] = (0xFF - 0x02) & rngmask; 1077 udfs->dux_commands[LOGBASE + 5] = 0; 1078 1079 udfs->dux_commands[LENBASE + 6] = 1; 1080 udfs->dux_commands[OPBASE + 6] = 0; 1081 udfs->dux_commands[OUTBASE + 6] = 0xFF & rngmask; 1082 udfs->dux_commands[LOGBASE + 6] = 0; 1083 1084 case 16: 1085 if (CR_RANGE(cmd->chanlist[0]) > 0) 1086 rngmask = 0xff - 0x04; 1087 else 1088 rngmask = 0xff; 1089 1090 if (cmd->start_src == TRIG_EXT) { 1091 /* 1092 * we loop here until ready has been set 1093 */ 1094 1095 /* branch back to state 0 */ 1096 udfs->dux_commands[LENBASE + 0] = 0x01; 1097 /* deceision state w/o data */ 1098 udfs->dux_commands[OPBASE + 0] = 0x01; 1099 /* reset */ 1100 udfs->dux_commands[OUTBASE + 0] = 1101 (0xFF - 0x02) & rngmask; 1102 /* RDY0 = 0 */ 1103 udfs->dux_commands[LOGBASE + 0] = 0x00; 1104 } else { 1105 /* 1106 * we just proceed to state 1 1107 */ 1108 1109 /* 30us reset pulse */ 1110 udfs->dux_commands[LENBASE + 0] = 255; 1111 udfs->dux_commands[OPBASE + 0] = 0; 1112 /* reset */ 1113 udfs->dux_commands[OUTBASE + 0] = 1114 (0xFF - 0x02) & rngmask; 1115 udfs->dux_commands[LOGBASE + 0] = 0; 1116 } 1117 1118 /* commit data to the FIFO */ 1119 udfs->dux_commands[LENBASE + 1] = 1; 1120 /* data */ 1121 udfs->dux_commands[OPBASE + 1] = 0x02; 1122 udfs->dux_commands[OUTBASE + 1] = 0xFF & rngmask; 1123 udfs->dux_commands[LOGBASE + 1] = 0; 1124 1125 /* we have 2 states with duration 1 */ 1126 steps = steps - 2; 1127 1128 /* do the first part of the delay */ 1129 udfs->dux_commands[LENBASE + 2] = steps / 2; 1130 udfs->dux_commands[OPBASE + 2] = 0; 1131 udfs->dux_commands[OUTBASE + 2] = 0xFE & rngmask; 1132 udfs->dux_commands[LOGBASE + 2] = 0; 1133 1134 /* and the second part */ 1135 udfs->dux_commands[LENBASE + 3] = steps - steps / 2; 1136 udfs->dux_commands[OPBASE + 3] = 0; 1137 udfs->dux_commands[OUTBASE + 3] = 0xFF & rngmask; 1138 udfs->dux_commands[LOGBASE + 3] = 0; 1139 1140 /* branch back to state 1 */ 1141 udfs->dux_commands[LENBASE + 4] = 0x09; 1142 /* deceision state w/o data */ 1143 udfs->dux_commands[OPBASE + 4] = 0x01; 1144 udfs->dux_commands[OUTBASE + 4] = 0xFF & rngmask; 1145 /* doesn't matter */ 1146 udfs->dux_commands[LOGBASE + 4] = 0xFF; 1147 1148 break; 1149 1150 default: 1151 printk(KERN_ERR "comedi %d: unsupported combination of " 1152 "channels\n", dev->minor); 1153 up(&udfs->sem); 1154 return -EFAULT; 1155 } 1156 1157#ifdef CONFIG_COMEDI_DEBUG 1158 printk(KERN_DEBUG "comedi %d: sending commands to the usb device\n", 1159 dev->minor); 1160#endif 1161 /* 0 means that the AD commands are sent */ 1162 result = send_dux_commands(udfs, SENDADCOMMANDS); 1163 if (result < 0) { 1164 printk(KERN_ERR "comedi%d: adc command could not be submitted." 1165 "Aborting...\n", dev->minor); 1166 up(&udfs->sem); 1167 return result; 1168 } 1169 if (cmd->stop_src == TRIG_COUNT) { 1170 udfs->ai_sample_count = cmd->stop_arg * cmd->scan_end_arg; 1171 if (udfs->ai_sample_count < 1) { 1172 printk(KERN_ERR "comedi%d: " 1173 "(cmd->stop_arg)*(cmd->scan_end_arg)<1, " 1174 "aborting.\n", dev->minor); 1175 up(&udfs->sem); 1176 return -EFAULT; 1177 } 1178 udfs->ai_continous = 0; 1179 } else { 1180 /* continous aquisition */ 1181 udfs->ai_continous = 1; 1182 udfs->ai_sample_count = 0; 1183 } 1184 1185 if ((cmd->start_src == TRIG_NOW) || (cmd->start_src == TRIG_EXT)) { 1186 /* enable this acquisition operation */ 1187 udfs->ai_cmd_running = 1; 1188 ret = usbduxfastsub_submit_InURBs(udfs); 1189 if (ret < 0) { 1190 udfs->ai_cmd_running = 0; 1191 /* fixme: unlink here?? */ 1192 up(&udfs->sem); 1193 return ret; 1194 } 1195 s->async->inttrig = NULL; 1196 } else { 1197 /* 1198 * TRIG_INT 1199 * don't enable the acquision operation 1200 * wait for an internal signal 1201 */ 1202 s->async->inttrig = usbduxfast_ai_inttrig; 1203 } 1204 up(&udfs->sem); 1205 1206 return 0; 1207} 1208 1209/* 1210 * Mode 0 is used to get a single conversion on demand. 1211 */ 1212static int usbduxfast_ai_insn_read(struct comedi_device *dev, 1213 struct comedi_subdevice *s, 1214 struct comedi_insn *insn, unsigned int *data) 1215{ 1216 int i, j, n, actual_length; 1217 int chan, range, rngmask; 1218 int err; 1219 struct usbduxfastsub_s *udfs; 1220 1221 udfs = dev->private; 1222 if (!udfs) { 1223 printk(KERN_ERR "comedi%d: ai_insn_read: no usb dev.\n", 1224 dev->minor); 1225 return -ENODEV; 1226 } 1227#ifdef CONFIG_COMEDI_DEBUG 1228 printk(KERN_DEBUG "comedi%d: ai_insn_read, insn->n=%d, " 1229 "insn->subdev=%d\n", dev->minor, insn->n, insn->subdev); 1230#endif 1231 down(&udfs->sem); 1232 if (!udfs->probed) { 1233 up(&udfs->sem); 1234 return -ENODEV; 1235 } 1236 if (udfs->ai_cmd_running) { 1237 printk(KERN_ERR "comedi%d: ai_insn_read not possible. Async " 1238 "Command is running.\n", dev->minor); 1239 up(&udfs->sem); 1240 return -EBUSY; 1241 } 1242 /* sample one channel */ 1243 chan = CR_CHAN(insn->chanspec); 1244 range = CR_RANGE(insn->chanspec); 1245 /* set command for the first channel */ 1246 1247 if (range > 0) 1248 rngmask = 0xff - 0x04; 1249 else 1250 rngmask = 0xff; 1251 1252 /* commit data to the FIFO */ 1253 udfs->dux_commands[LENBASE + 0] = 1; 1254 /* data */ 1255 udfs->dux_commands[OPBASE + 0] = 0x02; 1256 udfs->dux_commands[OUTBASE + 0] = 0xFF & rngmask; 1257 udfs->dux_commands[LOGBASE + 0] = 0; 1258 1259 /* do the first part of the delay */ 1260 udfs->dux_commands[LENBASE + 1] = 12; 1261 udfs->dux_commands[OPBASE + 1] = 0; 1262 udfs->dux_commands[OUTBASE + 1] = 0xFE & rngmask; 1263 udfs->dux_commands[LOGBASE + 1] = 0; 1264 1265 udfs->dux_commands[LENBASE + 2] = 1; 1266 udfs->dux_commands[OPBASE + 2] = 0; 1267 udfs->dux_commands[OUTBASE + 2] = 0xFE & rngmask; 1268 udfs->dux_commands[LOGBASE + 2] = 0; 1269 1270 udfs->dux_commands[LENBASE + 3] = 1; 1271 udfs->dux_commands[OPBASE + 3] = 0; 1272 udfs->dux_commands[OUTBASE + 3] = 0xFE & rngmask; 1273 udfs->dux_commands[LOGBASE + 3] = 0; 1274 1275 udfs->dux_commands[LENBASE + 4] = 1; 1276 udfs->dux_commands[OPBASE + 4] = 0; 1277 udfs->dux_commands[OUTBASE + 4] = 0xFE & rngmask; 1278 udfs->dux_commands[LOGBASE + 4] = 0; 1279 1280 /* second part */ 1281 udfs->dux_commands[LENBASE + 5] = 12; 1282 udfs->dux_commands[OPBASE + 5] = 0; 1283 udfs->dux_commands[OUTBASE + 5] = 0xFF & rngmask; 1284 udfs->dux_commands[LOGBASE + 5] = 0; 1285 1286 udfs->dux_commands[LENBASE + 6] = 1; 1287 udfs->dux_commands[OPBASE + 6] = 0; 1288 udfs->dux_commands[OUTBASE + 6] = 0xFF & rngmask; 1289 udfs->dux_commands[LOGBASE + 0] = 0; 1290 1291#ifdef CONFIG_COMEDI_DEBUG 1292 printk(KERN_DEBUG "comedi %d: sending commands to the usb device\n", 1293 dev->minor); 1294#endif 1295 /* 0 means that the AD commands are sent */ 1296 err = send_dux_commands(udfs, SENDADCOMMANDS); 1297 if (err < 0) { 1298 printk(KERN_ERR "comedi%d: adc command could not be submitted." 1299 "Aborting...\n", dev->minor); 1300 up(&udfs->sem); 1301 return err; 1302 } 1303#ifdef CONFIG_COMEDI_DEBUG 1304 printk(KERN_DEBUG "comedi%d: usbduxfast: submitting in-urb: " 1305 "0x%p,0x%p\n", udfs->comedidev->minor, udfs->urbIn->context, 1306 udfs->urbIn->dev); 1307#endif 1308 for (i = 0; i < PACKETS_TO_IGNORE; i++) { 1309 err = usb_bulk_msg(udfs->usbdev, 1310 usb_rcvbulkpipe(udfs->usbdev, BULKINEP), 1311 udfs->transfer_buffer, SIZEINBUF, 1312 &actual_length, 10000); 1313 if (err < 0) { 1314 printk(KERN_ERR "comedi%d: insn timeout. No data.\n", 1315 dev->minor); 1316 up(&udfs->sem); 1317 return err; 1318 } 1319 } 1320 /* data points */ 1321 for (i = 0; i < insn->n;) { 1322 err = usb_bulk_msg(udfs->usbdev, 1323 usb_rcvbulkpipe(udfs->usbdev, BULKINEP), 1324 udfs->transfer_buffer, SIZEINBUF, 1325 &actual_length, 10000); 1326 if (err < 0) { 1327 printk(KERN_ERR "comedi%d: insn data error: %d\n", 1328 dev->minor, err); 1329 up(&udfs->sem); 1330 return err; 1331 } 1332 n = actual_length / sizeof(uint16_t); 1333 if ((n % 16) != 0) { 1334 printk(KERN_ERR "comedi%d: insn data packet " 1335 "corrupted.\n", dev->minor); 1336 up(&udfs->sem); 1337 return -EINVAL; 1338 } 1339 for (j = chan; (j < n) && (i < insn->n); j = j + 16) { 1340 data[i] = ((uint16_t *) (udfs->transfer_buffer))[j]; 1341 i++; 1342 } 1343 } 1344 up(&udfs->sem); 1345 return i; 1346} 1347 1348#define FIRMWARE_MAX_LEN 0x2000 1349 1350static int firmwareUpload(struct usbduxfastsub_s *usbduxfastsub, 1351 const u8 * firmwareBinary, int sizeFirmware) 1352{ 1353 int ret; 1354 uint8_t *fwBuf; 1355 1356 if (!firmwareBinary) 1357 return 0; 1358 1359 if (sizeFirmware > FIRMWARE_MAX_LEN) { 1360 dev_err(&usbduxfastsub->interface->dev, 1361 "comedi_: usbduxfast firmware binary it too large for FX2.\n"); 1362 return -ENOMEM; 1363 } 1364 1365 /* we generate a local buffer for the firmware */ 1366 fwBuf = kzalloc(sizeFirmware, GFP_KERNEL); 1367 if (!fwBuf) { 1368 dev_err(&usbduxfastsub->interface->dev, 1369 "comedi_: mem alloc for firmware failed\n"); 1370 return -ENOMEM; 1371 } 1372 memcpy(fwBuf, firmwareBinary, sizeFirmware); 1373 1374 ret = usbduxfastsub_stop(usbduxfastsub); 1375 if (ret < 0) { 1376 dev_err(&usbduxfastsub->interface->dev, 1377 "comedi_: can not stop firmware\n"); 1378 kfree(fwBuf); 1379 return ret; 1380 } 1381 1382 ret = usbduxfastsub_upload(usbduxfastsub, fwBuf, 0, sizeFirmware); 1383 if (ret < 0) { 1384 dev_err(&usbduxfastsub->interface->dev, 1385 "comedi_: firmware upload failed\n"); 1386 kfree(fwBuf); 1387 return ret; 1388 } 1389 ret = usbduxfastsub_start(usbduxfastsub); 1390 if (ret < 0) { 1391 dev_err(&usbduxfastsub->interface->dev, 1392 "comedi_: can not start firmware\n"); 1393 kfree(fwBuf); 1394 return ret; 1395 } 1396 kfree(fwBuf); 1397 return 0; 1398} 1399 1400static void tidy_up(struct usbduxfastsub_s *udfs) 1401{ 1402#ifdef CONFIG_COMEDI_DEBUG 1403 printk(KERN_DEBUG "comedi_: usbduxfast: tiding up\n"); 1404#endif 1405 1406 if (!udfs) 1407 return; 1408 1409 /* shows the usb subsystem that the driver is down */ 1410 if (udfs->interface) 1411 usb_set_intfdata(udfs->interface, NULL); 1412 1413 udfs->probed = 0; 1414 1415 if (udfs->urbIn) { 1416 /* waits until a running transfer is over */ 1417 usb_kill_urb(udfs->urbIn); 1418 1419 kfree(udfs->transfer_buffer); 1420 udfs->transfer_buffer = NULL; 1421 1422 usb_free_urb(udfs->urbIn); 1423 udfs->urbIn = NULL; 1424 } 1425 1426 kfree(udfs->insnBuffer); 1427 udfs->insnBuffer = NULL; 1428 1429 kfree(udfs->dux_commands); 1430 udfs->dux_commands = NULL; 1431 1432 udfs->ai_cmd_running = 0; 1433} 1434 1435static void usbduxfast_firmware_request_complete_handler(const struct firmware 1436 *fw, void *context) 1437{ 1438 struct usbduxfastsub_s *usbduxfastsub_tmp = context; 1439 struct usb_device *usbdev = usbduxfastsub_tmp->usbdev; 1440 int ret; 1441 1442 if (fw == NULL) 1443 return; 1444 1445 /* 1446 * we need to upload the firmware here because fw will be 1447 * freed once we've left this function 1448 */ 1449 ret = firmwareUpload(usbduxfastsub_tmp, fw->data, fw->size); 1450 1451 if (ret) { 1452 dev_err(&usbdev->dev, 1453 "Could not upload firmware (err=%d)\n", ret); 1454 goto out; 1455 } 1456 1457 comedi_usb_auto_config(usbdev, BOARDNAME); 1458 out: 1459 release_firmware(fw); 1460} 1461 1462/* 1463 * allocate memory for the urbs and initialise them 1464 */ 1465static int usbduxfastsub_probe(struct usb_interface *uinterf, 1466 const struct usb_device_id *id) 1467{ 1468 struct usb_device *udev = interface_to_usbdev(uinterf); 1469 int i; 1470 int index; 1471 int ret; 1472 1473 if (udev->speed != USB_SPEED_HIGH) { 1474 printk(KERN_ERR "comedi_: usbduxfast_: This driver needs" 1475 "USB 2.0 to operate. Aborting...\n"); 1476 return -ENODEV; 1477 } 1478#ifdef CONFIG_COMEDI_DEBUG 1479 printk(KERN_DEBUG "comedi_: usbduxfast_: finding a free structure for " 1480 "the usb-device\n"); 1481#endif 1482 down(&start_stop_sem); 1483 /* look for a free place in the usbduxfast array */ 1484 index = -1; 1485 for (i = 0; i < NUMUSBDUXFAST; i++) { 1486 if (!usbduxfastsub[i].probed) { 1487 index = i; 1488 break; 1489 } 1490 } 1491 1492 /* no more space */ 1493 if (index == -1) { 1494 printk(KERN_ERR "Too many usbduxfast-devices connected.\n"); 1495 up(&start_stop_sem); 1496 return -EMFILE; 1497 } 1498#ifdef CONFIG_COMEDI_DEBUG 1499 printk(KERN_DEBUG "comedi_: usbduxfast: usbduxfastsub[%d] is ready to " 1500 "connect to comedi.\n", index); 1501#endif 1502 1503 init_MUTEX(&(usbduxfastsub[index].sem)); 1504 /* save a pointer to the usb device */ 1505 usbduxfastsub[index].usbdev = udev; 1506 1507 /* save the interface itself */ 1508 usbduxfastsub[index].interface = uinterf; 1509 /* get the interface number from the interface */ 1510 usbduxfastsub[index].ifnum = uinterf->altsetting->desc.bInterfaceNumber; 1511 /* 1512 * hand the private data over to the usb subsystem 1513 * will be needed for disconnect 1514 */ 1515 usb_set_intfdata(uinterf, &(usbduxfastsub[index])); 1516 1517#ifdef CONFIG_COMEDI_DEBUG 1518 printk(KERN_DEBUG "comedi_: usbduxfast: ifnum=%d\n", 1519 usbduxfastsub[index].ifnum); 1520#endif 1521 /* create space for the commands going to the usb device */ 1522 usbduxfastsub[index].dux_commands = kmalloc(SIZEOFDUXBUFFER, 1523 GFP_KERNEL); 1524 if (!usbduxfastsub[index].dux_commands) { 1525 printk(KERN_ERR "comedi_: usbduxfast: error alloc space for " 1526 "dac commands\n"); 1527 tidy_up(&(usbduxfastsub[index])); 1528 up(&start_stop_sem); 1529 return -ENOMEM; 1530 } 1531 /* create space of the instruction buffer */ 1532 usbduxfastsub[index].insnBuffer = kmalloc(SIZEINSNBUF, GFP_KERNEL); 1533 if (!usbduxfastsub[index].insnBuffer) { 1534 printk(KERN_ERR "comedi_: usbduxfast: could not alloc space " 1535 "for insnBuffer\n"); 1536 tidy_up(&(usbduxfastsub[index])); 1537 up(&start_stop_sem); 1538 return -ENOMEM; 1539 } 1540 /* setting to alternate setting 1: enabling bulk ep */ 1541 i = usb_set_interface(usbduxfastsub[index].usbdev, 1542 usbduxfastsub[index].ifnum, 1); 1543 if (i < 0) { 1544 printk(KERN_ERR "comedi_: usbduxfast%d: could not switch to " 1545 "alternate setting 1.\n", index); 1546 tidy_up(&(usbduxfastsub[index])); 1547 up(&start_stop_sem); 1548 return -ENODEV; 1549 } 1550 usbduxfastsub[index].urbIn = usb_alloc_urb(0, GFP_KERNEL); 1551 if (!usbduxfastsub[index].urbIn) { 1552 printk(KERN_ERR "comedi_: usbduxfast%d: Could not alloc." 1553 "urb\n", index); 1554 tidy_up(&(usbduxfastsub[index])); 1555 up(&start_stop_sem); 1556 return -ENOMEM; 1557 } 1558 usbduxfastsub[index].transfer_buffer = kmalloc(SIZEINBUF, GFP_KERNEL); 1559 if (!usbduxfastsub[index].transfer_buffer) { 1560 printk(KERN_ERR "comedi_: usbduxfast%d: could not alloc. " 1561 "transb.\n", index); 1562 tidy_up(&(usbduxfastsub[index])); 1563 up(&start_stop_sem); 1564 return -ENOMEM; 1565 } 1566 /* we've reached the bottom of the function */ 1567 usbduxfastsub[index].probed = 1; 1568 up(&start_stop_sem); 1569 1570 ret = request_firmware_nowait(THIS_MODULE, 1571 FW_ACTION_HOTPLUG, 1572 "usbduxfast_firmware.bin", 1573 &udev->dev, 1574 GFP_KERNEL, 1575 usbduxfastsub + index, 1576 usbduxfast_firmware_request_complete_handler); 1577 1578 if (ret) { 1579 dev_err(&udev->dev, "could not load firmware (err=%d)\n", ret); 1580 return ret; 1581 } 1582 1583 printk(KERN_INFO "comedi_: usbduxfast%d has been successfully " 1584 "initialized.\n", index); 1585 /* success */ 1586 return 0; 1587} 1588 1589static void usbduxfastsub_disconnect(struct usb_interface *intf) 1590{ 1591 struct usbduxfastsub_s *udfs = usb_get_intfdata(intf); 1592 struct usb_device *udev = interface_to_usbdev(intf); 1593 1594 if (!udfs) { 1595 printk(KERN_ERR "comedi_: usbduxfast: disconnect called with " 1596 "null pointer.\n"); 1597 return; 1598 } 1599 if (udfs->usbdev != udev) { 1600 printk(KERN_ERR "comedi_: usbduxfast: BUG! called with wrong " 1601 "ptr!!!\n"); 1602 return; 1603 } 1604 1605 comedi_usb_auto_unconfig(udev); 1606 1607 down(&start_stop_sem); 1608 down(&udfs->sem); 1609 tidy_up(udfs); 1610 up(&udfs->sem); 1611 up(&start_stop_sem); 1612 1613#ifdef CONFIG_COMEDI_DEBUG 1614 printk(KERN_DEBUG "comedi_: usbduxfast: disconnected from the usb\n"); 1615#endif 1616} 1617 1618/* 1619 * is called when comedi-config is called 1620 */ 1621static int usbduxfast_attach(struct comedi_device *dev, 1622 struct comedi_devconfig *it) 1623{ 1624 int ret; 1625 int index; 1626 int i; 1627 struct comedi_subdevice *s = NULL; 1628 dev->private = NULL; 1629 1630 down(&start_stop_sem); 1631 /* 1632 * find a valid device which has been detected by the 1633 * probe function of the usb 1634 */ 1635 index = -1; 1636 for (i = 0; i < NUMUSBDUXFAST; i++) { 1637 if (usbduxfastsub[i].probed && !usbduxfastsub[i].attached) { 1638 index = i; 1639 break; 1640 } 1641 } 1642 1643 if (index < 0) { 1644 printk(KERN_ERR "comedi%d: usbduxfast: error: attach failed, " 1645 "no usbduxfast devs connected to the usb bus.\n", 1646 dev->minor); 1647 up(&start_stop_sem); 1648 return -ENODEV; 1649 } 1650 1651 down(&(usbduxfastsub[index].sem)); 1652 /* pointer back to the corresponding comedi device */ 1653 usbduxfastsub[index].comedidev = dev; 1654 1655 /* trying to upload the firmware into the chip */ 1656 if (comedi_aux_data(it->options, 0) && 1657 it->options[COMEDI_DEVCONF_AUX_DATA_LENGTH]) { 1658 firmwareUpload(&usbduxfastsub[index], 1659 comedi_aux_data(it->options, 0), 1660 it->options[COMEDI_DEVCONF_AUX_DATA_LENGTH]); 1661 } 1662 1663 dev->board_name = BOARDNAME; 1664 1665 /* set number of subdevices */ 1666 dev->n_subdevices = N_SUBDEVICES; 1667 1668 /* allocate space for the subdevices */ 1669 ret = alloc_subdevices(dev, N_SUBDEVICES); 1670 if (ret < 0) { 1671 printk(KERN_ERR "comedi%d: usbduxfast: error alloc space for " 1672 "subdev\n", dev->minor); 1673 up(&(usbduxfastsub[index].sem)); 1674 up(&start_stop_sem); 1675 return ret; 1676 } 1677 1678 printk(KERN_INFO "comedi%d: usbduxfast: usb-device %d is attached to " 1679 "comedi.\n", dev->minor, index); 1680 /* private structure is also simply the usb-structure */ 1681 dev->private = usbduxfastsub + index; 1682 /* the first subdevice is the A/D converter */ 1683 s = dev->subdevices + SUBDEV_AD; 1684 /* 1685 * the URBs get the comedi subdevice which is responsible for reading 1686 * this is the subdevice which reads data 1687 */ 1688 dev->read_subdev = s; 1689 /* the subdevice receives as private structure the usb-structure */ 1690 s->private = NULL; 1691 /* analog input */ 1692 s->type = COMEDI_SUBD_AI; 1693 /* readable and ref is to ground */ 1694 s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_CMD_READ; 1695 /* 16 channels */ 1696 s->n_chan = 16; 1697 /* length of the channellist */ 1698 s->len_chanlist = 16; 1699 /* callback functions */ 1700 s->insn_read = usbduxfast_ai_insn_read; 1701 s->do_cmdtest = usbduxfast_ai_cmdtest; 1702 s->do_cmd = usbduxfast_ai_cmd; 1703 s->cancel = usbduxfast_ai_cancel; 1704 /* max value from the A/D converter (12bit+1 bit for overflow) */ 1705 s->maxdata = 0x1000; 1706 /* range table to convert to physical units */ 1707 s->range_table = &range_usbduxfast_ai_range; 1708 1709 /* finally decide that it's attached */ 1710 usbduxfastsub[index].attached = 1; 1711 1712 up(&(usbduxfastsub[index].sem)); 1713 up(&start_stop_sem); 1714 printk(KERN_INFO "comedi%d: successfully attached to usbduxfast.\n", 1715 dev->minor); 1716 1717 return 0; 1718} 1719 1720static int usbduxfast_detach(struct comedi_device *dev) 1721{ 1722 struct usbduxfastsub_s *udfs; 1723 1724 if (!dev) { 1725 printk(KERN_ERR "comedi?: usbduxfast: detach without dev " 1726 "variable...\n"); 1727 return -EFAULT; 1728 } 1729#ifdef CONFIG_COMEDI_DEBUG 1730 printk(KERN_DEBUG "comedi%d: usbduxfast: detach usb device\n", 1731 dev->minor); 1732#endif 1733 1734 udfs = dev->private; 1735 if (!udfs) { 1736 printk(KERN_ERR "comedi?: usbduxfast: detach without ptr to " 1737 "usbduxfastsub[]\n"); 1738 return -EFAULT; 1739 } 1740 1741 down(&udfs->sem); 1742 down(&start_stop_sem); 1743 /* 1744 * Don't allow detach to free the private structure 1745 * It's one entry of of usbduxfastsub[] 1746 */ 1747 dev->private = NULL; 1748 udfs->attached = 0; 1749 udfs->comedidev = NULL; 1750#ifdef CONFIG_COMEDI_DEBUG 1751 printk(KERN_DEBUG "comedi%d: usbduxfast: detach: successfully " 1752 "removed\n", dev->minor); 1753#endif 1754 up(&start_stop_sem); 1755 up(&udfs->sem); 1756 return 0; 1757} 1758 1759/* 1760 * main driver struct 1761 */ 1762static struct comedi_driver driver_usbduxfast = { 1763 .driver_name = "usbduxfast", 1764 .module = THIS_MODULE, 1765 .attach = usbduxfast_attach, 1766 .detach = usbduxfast_detach 1767}; 1768 1769/* 1770 * Table with the USB-devices: just now only testing IDs 1771 */ 1772static struct usb_device_id usbduxfastsub_table[] = { 1773 /* { USB_DEVICE(0x4b4, 0x8613) }, testing */ 1774 {USB_DEVICE(0x13d8, 0x0010)}, /* real ID */ 1775 {USB_DEVICE(0x13d8, 0x0011)}, /* real ID */ 1776 {} /* Terminating entry */ 1777}; 1778 1779MODULE_DEVICE_TABLE(usb, usbduxfastsub_table); 1780 1781/* 1782 * The usbduxfastsub-driver 1783 */ 1784static struct usb_driver usbduxfastsub_driver = { 1785#ifdef COMEDI_HAVE_USB_DRIVER_OWNER 1786 .owner = THIS_MODULE, 1787#endif 1788 .name = BOARDNAME, 1789 .probe = usbduxfastsub_probe, 1790 .disconnect = usbduxfastsub_disconnect, 1791 .id_table = usbduxfastsub_table 1792}; 1793 1794/* 1795 * Can't use the nice macro as I have also to initialise the USB subsystem: 1796 * registering the usb-system _and_ the comedi-driver 1797 */ 1798static int __init init_usbduxfast(void) 1799{ 1800 printk(KERN_INFO 1801 KBUILD_MODNAME ": " DRIVER_VERSION ":" DRIVER_DESC "\n"); 1802 usb_register(&usbduxfastsub_driver); 1803 comedi_driver_register(&driver_usbduxfast); 1804 return 0; 1805} 1806 1807/* 1808 * deregistering the comedi driver and the usb-subsystem 1809 */ 1810static void __exit exit_usbduxfast(void) 1811{ 1812 comedi_driver_unregister(&driver_usbduxfast); 1813 usb_deregister(&usbduxfastsub_driver); 1814} 1815 1816module_init(init_usbduxfast); 1817module_exit(exit_usbduxfast); 1818 1819MODULE_AUTHOR(DRIVER_AUTHOR); 1820MODULE_DESCRIPTION(DRIVER_DESC); 1821MODULE_LICENSE("GPL"); 1822