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