1#define DRIVER_VERSION "v0.6" 2#define DRIVER_AUTHOR "Bernd Porr, BerndPorr@f2s.com" 3#define DRIVER_DESC "Stirling/ITL USB-DUX SIGMA -- Bernd.Porr@f2s.com" 4/* 5 comedi/drivers/usbdux.c 6 Copyright (C) 2011 Bernd Porr, Bernd.Porr@f2s.com 7 8 This program is free software; you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation; either version 2 of the License, or 11 (at your option) any later version. 12 13 This program is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program; if not, write to the Free Software 20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 21 22 */ 23/* 24Driver: usbduxsigma 25Description: University of Stirling USB DAQ & INCITE Technology Limited 26Devices: [ITL] USB-DUX (usbduxsigma.o) 27Author: Bernd Porr <BerndPorr@f2s.com> 28Updated: 8 Nov 2011 29Status: testing 30*/ 31/* 32 * I must give credit here to Chris Baugher who 33 * wrote the driver for AT-MIO-16d. I used some parts of this 34 * driver. I also must give credits to David Brownell 35 * who supported me with the USB development. 36 * 37 * Note: the raw data from the A/D converter is 24 bit big endian 38 * anything else is little endian to/from the dux board 39 * 40 * 41 * Revision history: 42 * 0.1: initial version 43 * 0.2: all basic functions implemented, digital I/O only for one port 44 * 0.3: proper vendor ID and driver name 45 * 0.4: fixed D/A voltage range 46 * 0.5: various bug fixes, health check at startup 47 * 0.6: corrected wrong input range 48 */ 49 50/* generates loads of debug info */ 51/* #define NOISY_DUX_DEBUGBUG */ 52 53#include <linux/kernel.h> 54#include <linux/module.h> 55#include <linux/init.h> 56#include <linux/slab.h> 57#include <linux/input.h> 58#include <linux/usb.h> 59#include <linux/fcntl.h> 60#include <linux/compiler.h> 61#include <linux/firmware.h> 62#include "comedi_fc.h" 63#include "../comedidev.h" 64 65#define BOARDNAME "usbduxsigma" 66 67/* timeout for the USB-transfer in ms*/ 68#define BULK_TIMEOUT 1000 69 70/* constants for "firmware" upload and download */ 71#define USBDUXSUB_FIRMWARE 0xA0 72#define VENDOR_DIR_IN 0xC0 73#define VENDOR_DIR_OUT 0x40 74 75/* internal addresses of the 8051 processor */ 76#define USBDUXSUB_CPUCS 0xE600 77 78/* 79 * the minor device number, major is 180 only for debugging purposes and to 80 * upload special firmware (programming the eeprom etc) which is not 81 * compatible with the comedi framwork 82 */ 83#define USBDUXSUB_MINOR 32 84 85/* max lenghth of the transfer-buffer for software upload */ 86#define TB_LEN 0x2000 87 88/* Input endpoint number: ISO/IRQ */ 89#define ISOINEP 6 90 91/* Output endpoint number: ISO/IRQ */ 92#define ISOOUTEP 2 93 94/* This EP sends DUX commands to USBDUX */ 95#define COMMAND_OUT_EP 1 96 97/* This EP receives the DUX commands from USBDUX */ 98#define COMMAND_IN_EP 8 99 100/* Output endpoint for PWM */ 101#define PWM_EP 4 102 103/* 300Hz max frequ under PWM */ 104#define MIN_PWM_PERIOD ((long)(1E9/300)) 105 106/* Default PWM frequency */ 107#define PWM_DEFAULT_PERIOD ((long)(1E9/100)) 108 109/* Number of channels (16 AD and offset)*/ 110#define NUMCHANNELS 16 111 112/* Size of one A/D value */ 113#define SIZEADIN ((sizeof(int32_t))) 114 115/* 116 * Size of the async input-buffer IN BYTES, the DIO state is transmitted 117 * as the first byte. 118 */ 119#define SIZEINBUF (((NUMCHANNELS+1)*SIZEADIN)) 120 121/* 16 bytes. */ 122#define SIZEINSNBUF 16 123 124/* Number of DA channels */ 125#define NUMOUTCHANNELS 8 126 127/* size of one value for the D/A converter: channel and value */ 128#define SIZEDAOUT ((sizeof(uint8_t)+sizeof(int16_t))) 129 130/* 131 * Size of the output-buffer in bytes 132 * Actually only the first 4 triplets are used but for the 133 * high speed mode we need to pad it to 8 (microframes). 134 */ 135#define SIZEOUTBUF ((8*SIZEDAOUT)) 136 137/* 138 * Size of the buffer for the dux commands: just now max size is determined 139 * by the analogue out + command byte + panic bytes... 140 */ 141#define SIZEOFDUXBUFFER ((8*SIZEDAOUT+2)) 142 143/* Number of in-URBs which receive the data: min=2 */ 144#define NUMOFINBUFFERSFULL 5 145 146/* Number of out-URBs which send the data: min=2 */ 147#define NUMOFOUTBUFFERSFULL 5 148 149/* Number of in-URBs which receive the data: min=5 */ 150/* must have more buffers due to buggy USB ctr */ 151#define NUMOFINBUFFERSHIGH 10 152 153/* Number of out-URBs which send the data: min=5 */ 154/* must have more buffers due to buggy USB ctr */ 155#define NUMOFOUTBUFFERSHIGH 10 156 157/* Total number of usbdux devices */ 158#define NUMUSBDUX 16 159 160/* Analogue in subdevice */ 161#define SUBDEV_AD 0 162 163/* Analogue out subdevice */ 164#define SUBDEV_DA 1 165 166/* Digital I/O */ 167#define SUBDEV_DIO 2 168 169/* timer aka pwm output */ 170#define SUBDEV_PWM 3 171 172/* number of retries to get the right dux command */ 173#define RETRIES 10 174 175/**************************************************/ 176/* comedi constants */ 177static const struct comedi_lrange range_usbdux_ai_range = { 1, { 178 BIP_RANGE 179 (2.65/2.0) 180 } 181}; 182 183static const struct comedi_lrange range_usbdux_ao_range = { 1, { 184 UNI_RANGE 185 (2.5), 186 } 187}; 188 189/* 190 * private structure of one subdevice 191 */ 192 193/* 194 * This is the structure which holds all the data of 195 * this driver one sub device just now: A/D 196 */ 197struct usbduxsub { 198 /* attached? */ 199 int attached; 200 /* is it associated with a subdevice? */ 201 int probed; 202 /* pointer to the usb-device */ 203 struct usb_device *usbdev; 204 /* actual number of in-buffers */ 205 int numOfInBuffers; 206 /* actual number of out-buffers */ 207 int numOfOutBuffers; 208 /* ISO-transfer handling: buffers */ 209 struct urb **urbIn; 210 struct urb **urbOut; 211 /* pwm-transfer handling */ 212 struct urb *urbPwm; 213 /* PWM period */ 214 unsigned int pwmPeriod; 215 /* PWM internal delay for the GPIF in the FX2 */ 216 uint8_t pwmDelay; 217 /* size of the PWM buffer which holds the bit pattern */ 218 int sizePwmBuf; 219 /* input buffer for the ISO-transfer */ 220 int32_t *inBuffer; 221 /* input buffer for single insn */ 222 int8_t *insnBuffer; 223 /* output buffer for single DA outputs */ 224 int16_t *outBuffer; 225 /* interface number */ 226 int ifnum; 227 /* interface structure in 2.6 */ 228 struct usb_interface *interface; 229 /* comedi device for the interrupt context */ 230 struct comedi_device *comedidev; 231 /* is it USB_SPEED_HIGH or not? */ 232 short int high_speed; 233 /* asynchronous command is running */ 234 short int ai_cmd_running; 235 short int ao_cmd_running; 236 /* pwm is running */ 237 short int pwm_cmd_running; 238 /* continuous acquisition */ 239 short int ai_continuous; 240 short int ao_continuous; 241 /* number of samples to acquire */ 242 int ai_sample_count; 243 int ao_sample_count; 244 /* time between samples in units of the timer */ 245 unsigned int ai_timer; 246 unsigned int ao_timer; 247 /* counter between acquisitions */ 248 unsigned int ai_counter; 249 unsigned int ao_counter; 250 /* interval in frames/uframes */ 251 unsigned int ai_interval; 252 /* D/A commands */ 253 uint8_t *dac_commands; 254 /* commands */ 255 uint8_t *dux_commands; 256 struct semaphore sem; 257}; 258 259/* 260 * The pointer to the private usb-data of the driver is also the private data 261 * for the comedi-device. This has to be global as the usb subsystem needs 262 * global variables. The other reason is that this structure must be there 263 * _before_ any comedi command is issued. The usb subsystem must be initialised 264 * before comedi can access it. 265 */ 266static struct usbduxsub usbduxsub[NUMUSBDUX]; 267 268static DEFINE_SEMAPHORE(start_stop_sem); 269 270/* 271 * Stops the data acquision 272 * It should be safe to call this function from any context 273 */ 274static int usbduxsub_unlink_InURBs(struct usbduxsub *usbduxsub_tmp) 275{ 276 int i = 0; 277 int err = 0; 278 279 if (usbduxsub_tmp && usbduxsub_tmp->urbIn) { 280 for (i = 0; i < usbduxsub_tmp->numOfInBuffers; i++) { 281 if (usbduxsub_tmp->urbIn[i]) { 282 /* We wait here until all transfers have been 283 * cancelled. */ 284 usb_kill_urb(usbduxsub_tmp->urbIn[i]); 285 } 286 dev_dbg(&usbduxsub_tmp->interface->dev, 287 "comedi: usbdux: unlinked InURB %d, err=%d\n", 288 i, err); 289 } 290 } 291 return err; 292} 293 294/* 295 * This will stop a running acquisition operation 296 * Is called from within this driver from both the 297 * interrupt context and from comedi 298 */ 299static int usbdux_ai_stop(struct usbduxsub *this_usbduxsub, int do_unlink) 300{ 301 int ret = 0; 302 303 if (!this_usbduxsub) { 304 pr_err("comedi?: usbdux_ai_stop: this_usbduxsub=NULL!\n"); 305 return -EFAULT; 306 } 307 dev_dbg(&this_usbduxsub->interface->dev, "comedi: usbdux_ai_stop\n"); 308 309 if (do_unlink) { 310 /* stop aquistion */ 311 ret = usbduxsub_unlink_InURBs(this_usbduxsub); 312 } 313 314 this_usbduxsub->ai_cmd_running = 0; 315 316 return ret; 317} 318 319/* 320 * This will cancel a running acquisition operation. 321 * This is called by comedi but never from inside the driver. 322 */ 323static int usbdux_ai_cancel(struct comedi_device *dev, 324 struct comedi_subdevice *s) 325{ 326 struct usbduxsub *this_usbduxsub; 327 int res = 0; 328 329 /* force unlink of all urbs */ 330 this_usbduxsub = dev->private; 331 if (!this_usbduxsub) 332 return -EFAULT; 333 334 dev_dbg(&this_usbduxsub->interface->dev, "comedi: usbdux_ai_cancel\n"); 335 336 /* prevent other CPUs from submitting new commands just now */ 337 down(&this_usbduxsub->sem); 338 if (!(this_usbduxsub->probed)) { 339 up(&this_usbduxsub->sem); 340 return -ENODEV; 341 } 342 /* unlink only if the urb really has been submitted */ 343 res = usbdux_ai_stop(this_usbduxsub, this_usbduxsub->ai_cmd_running); 344 up(&this_usbduxsub->sem); 345 return res; 346} 347 348/* analogue IN - interrupt service routine */ 349static void usbduxsub_ai_IsocIrq(struct urb *urb) 350{ 351 int i, err, n; 352 struct usbduxsub *this_usbduxsub; 353 struct comedi_device *this_comedidev; 354 struct comedi_subdevice *s; 355 int32_t v; 356 unsigned int dio_state; 357 358 /* the context variable points to the comedi device */ 359 this_comedidev = urb->context; 360 /* the private structure of the subdevice is struct usbduxsub */ 361 this_usbduxsub = this_comedidev->private; 362 /* subdevice which is the AD converter */ 363 s = this_comedidev->subdevices + SUBDEV_AD; 364 365 /* first we test if something unusual has just happened */ 366 switch (urb->status) { 367 case 0: 368 /* copy the result in the transfer buffer */ 369 memcpy(this_usbduxsub->inBuffer, 370 urb->transfer_buffer, SIZEINBUF); 371 break; 372 case -EILSEQ: 373 /* error in the ISOchronous data */ 374 /* we don't copy the data into the transfer buffer */ 375 /* and recycle the last data byte */ 376 dev_dbg(&urb->dev->dev, 377 "comedi%d: usbdux: CRC error in ISO IN stream.\n", 378 this_usbduxsub->comedidev->minor); 379 380 break; 381 382 case -ECONNRESET: 383 case -ENOENT: 384 case -ESHUTDOWN: 385 case -ECONNABORTED: 386 /* happens after an unlink command */ 387 if (this_usbduxsub->ai_cmd_running) { 388 /* we are still running a command */ 389 /* tell this comedi */ 390 s->async->events |= COMEDI_CB_EOA; 391 s->async->events |= COMEDI_CB_ERROR; 392 comedi_event(this_usbduxsub->comedidev, s); 393 /* stop the transfer w/o unlink */ 394 usbdux_ai_stop(this_usbduxsub, 0); 395 } 396 return; 397 398 default: 399 /* a real error on the bus */ 400 /* pass error to comedi if we are really running a command */ 401 if (this_usbduxsub->ai_cmd_running) { 402 dev_err(&urb->dev->dev, 403 "Non-zero urb status received in ai intr " 404 "context: %d\n", urb->status); 405 s->async->events |= COMEDI_CB_EOA; 406 s->async->events |= COMEDI_CB_ERROR; 407 comedi_event(this_usbduxsub->comedidev, s); 408 /* don't do an unlink here */ 409 usbdux_ai_stop(this_usbduxsub, 0); 410 } 411 return; 412 } 413 414 /* 415 * at this point we are reasonably sure that nothing dodgy has happened 416 * are we running a command? 417 */ 418 if (unlikely((!(this_usbduxsub->ai_cmd_running)))) { 419 /* 420 * not running a command, do not continue execution if no 421 * asynchronous command is running in particular not resubmit 422 */ 423 return; 424 } 425 426 urb->dev = this_usbduxsub->usbdev; 427 428 /* resubmit the urb */ 429 err = usb_submit_urb(urb, GFP_ATOMIC); 430 if (unlikely(err < 0)) { 431 dev_err(&urb->dev->dev, 432 "comedi_: urb resubmit failed in int-context!" 433 "err=%d\n", 434 err); 435 if (err == -EL2NSYNC) 436 dev_err(&urb->dev->dev, 437 "buggy USB host controller or bug in IRQ " 438 "handler!\n"); 439 s->async->events |= COMEDI_CB_EOA; 440 s->async->events |= COMEDI_CB_ERROR; 441 comedi_event(this_usbduxsub->comedidev, s); 442 /* don't do an unlink here */ 443 usbdux_ai_stop(this_usbduxsub, 0); 444 return; 445 } 446 447 /* get the state of the dio pins to allow external trigger */ 448 dio_state = be32_to_cpu(this_usbduxsub->inBuffer[0]); 449 450 this_usbduxsub->ai_counter--; 451 if (likely(this_usbduxsub->ai_counter > 0)) 452 return; 453 454 /* timer zero, transfer measurements to comedi */ 455 this_usbduxsub->ai_counter = this_usbduxsub->ai_timer; 456 457 /* test, if we transmit only a fixed number of samples */ 458 if (!(this_usbduxsub->ai_continuous)) { 459 /* not continuous, fixed number of samples */ 460 this_usbduxsub->ai_sample_count--; 461 /* all samples received? */ 462 if (this_usbduxsub->ai_sample_count < 0) { 463 /* prevent a resubmit next time */ 464 usbdux_ai_stop(this_usbduxsub, 0); 465 /* say comedi that the acquistion is over */ 466 s->async->events |= COMEDI_CB_EOA; 467 comedi_event(this_usbduxsub->comedidev, s); 468 return; 469 } 470 } 471 /* get the data from the USB bus and hand it over to comedi */ 472 n = s->async->cmd.chanlist_len; 473 for (i = 0; i < n; i++) { 474 /* transfer data, note first byte is the DIO state */ 475 v = be32_to_cpu(this_usbduxsub->inBuffer[i+1]); 476 /* strip status byte */ 477 v = v & 0x00ffffff; 478 /* convert to unsigned */ 479 v = v ^ 0x00800000; 480 /* write the byte to the buffer */ 481 err = cfc_write_array_to_buffer(s, &v, sizeof(uint32_t)); 482 if (unlikely(err == 0)) { 483 /* buffer overflow */ 484 usbdux_ai_stop(this_usbduxsub, 0); 485 return; 486 } 487 } 488 /* tell comedi that data is there */ 489 s->async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOS; 490 comedi_event(this_usbduxsub->comedidev, s); 491} 492 493static int usbduxsub_unlink_OutURBs(struct usbduxsub *usbduxsub_tmp) 494{ 495 int i = 0; 496 int err = 0; 497 498 if (usbduxsub_tmp && usbduxsub_tmp->urbOut) { 499 for (i = 0; i < usbduxsub_tmp->numOfOutBuffers; i++) { 500 if (usbduxsub_tmp->urbOut[i]) 501 usb_kill_urb(usbduxsub_tmp->urbOut[i]); 502 503 dev_dbg(&usbduxsub_tmp->interface->dev, 504 "comedi: usbdux: unlinked OutURB %d: res=%d\n", 505 i, err); 506 } 507 } 508 return err; 509} 510 511/* This will cancel a running acquisition operation 512 * in any context. 513 */ 514static int usbdux_ao_stop(struct usbduxsub *this_usbduxsub, int do_unlink) 515{ 516 int ret = 0; 517 518 if (!this_usbduxsub) 519 return -EFAULT; 520 dev_dbg(&this_usbduxsub->interface->dev, "comedi: usbdux_ao_cancel\n"); 521 522 if (do_unlink) 523 ret = usbduxsub_unlink_OutURBs(this_usbduxsub); 524 525 this_usbduxsub->ao_cmd_running = 0; 526 527 return ret; 528} 529 530/* force unlink, is called by comedi */ 531static int usbdux_ao_cancel(struct comedi_device *dev, 532 struct comedi_subdevice *s) 533{ 534 struct usbduxsub *this_usbduxsub = dev->private; 535 int res = 0; 536 537 if (!this_usbduxsub) 538 return -EFAULT; 539 540 /* prevent other CPUs from submitting a command just now */ 541 down(&this_usbduxsub->sem); 542 if (!(this_usbduxsub->probed)) { 543 up(&this_usbduxsub->sem); 544 return -ENODEV; 545 } 546 /* unlink only if it is really running */ 547 res = usbdux_ao_stop(this_usbduxsub, this_usbduxsub->ao_cmd_running); 548 up(&this_usbduxsub->sem); 549 return res; 550} 551 552static void usbduxsub_ao_IsocIrq(struct urb *urb) 553{ 554 int i, ret; 555 uint8_t *datap; 556 struct usbduxsub *this_usbduxsub; 557 struct comedi_device *this_comedidev; 558 struct comedi_subdevice *s; 559 560 /* the context variable points to the subdevice */ 561 this_comedidev = urb->context; 562 /* the private structure of the subdevice is struct usbduxsub */ 563 this_usbduxsub = this_comedidev->private; 564 565 s = this_comedidev->subdevices + SUBDEV_DA; 566 567 switch (urb->status) { 568 case 0: 569 /* success */ 570 break; 571 572 case -ECONNRESET: 573 case -ENOENT: 574 case -ESHUTDOWN: 575 case -ECONNABORTED: 576 /* after an unlink command, unplug, ... etc */ 577 /* no unlink needed here. Already shutting down. */ 578 if (this_usbduxsub->ao_cmd_running) { 579 s->async->events |= COMEDI_CB_EOA; 580 comedi_event(this_usbduxsub->comedidev, s); 581 usbdux_ao_stop(this_usbduxsub, 0); 582 } 583 return; 584 585 default: 586 /* a real error */ 587 if (this_usbduxsub->ao_cmd_running) { 588 dev_err(&urb->dev->dev, 589 "comedi_: Non-zero urb status received in ao " 590 "intr context: %d\n", urb->status); 591 s->async->events |= COMEDI_CB_ERROR; 592 s->async->events |= COMEDI_CB_EOA; 593 comedi_event(this_usbduxsub->comedidev, s); 594 /* we do an unlink if we are in the high speed mode */ 595 usbdux_ao_stop(this_usbduxsub, 0); 596 } 597 return; 598 } 599 600 /* are we actually running? */ 601 if (!(this_usbduxsub->ao_cmd_running)) 602 return; 603 604 /* normal operation: executing a command in this subdevice */ 605 this_usbduxsub->ao_counter--; 606 if ((int)this_usbduxsub->ao_counter <= 0) { 607 /* timer zero */ 608 this_usbduxsub->ao_counter = this_usbduxsub->ao_timer; 609 610 /* handle non continuous acquisition */ 611 if (!(this_usbduxsub->ao_continuous)) { 612 /* fixed number of samples */ 613 this_usbduxsub->ao_sample_count--; 614 if (this_usbduxsub->ao_sample_count < 0) { 615 /* all samples transmitted */ 616 usbdux_ao_stop(this_usbduxsub, 0); 617 s->async->events |= COMEDI_CB_EOA; 618 comedi_event(this_usbduxsub->comedidev, s); 619 /* no resubmit of the urb */ 620 return; 621 } 622 } 623 /* transmit data to the USB bus */ 624 ((uint8_t *) (urb->transfer_buffer))[0] = 625 s->async->cmd.chanlist_len; 626 for (i = 0; i < s->async->cmd.chanlist_len; i++) { 627 short temp; 628 if (i >= NUMOUTCHANNELS) 629 break; 630 631 /* pointer to the DA */ 632 datap = 633 (&(((uint8_t *) urb->transfer_buffer)[i * 2 + 1])); 634 /* get the data from comedi */ 635 ret = comedi_buf_get(s->async, &temp); 636 datap[0] = temp; 637 datap[1] = this_usbduxsub->dac_commands[i]; 638 /* printk("data[0]=%x, data[1]=%x, data[2]=%x\n", */ 639 /* datap[0],datap[1],datap[2]); */ 640 if (ret < 0) { 641 dev_err(&urb->dev->dev, 642 "comedi: buffer underflow\n"); 643 s->async->events |= COMEDI_CB_EOA; 644 s->async->events |= COMEDI_CB_OVERFLOW; 645 } 646 /* transmit data to comedi */ 647 s->async->events |= COMEDI_CB_BLOCK; 648 comedi_event(this_usbduxsub->comedidev, s); 649 } 650 } 651 urb->transfer_buffer_length = SIZEOUTBUF; 652 urb->dev = this_usbduxsub->usbdev; 653 urb->status = 0; 654 if (this_usbduxsub->ao_cmd_running) { 655 if (this_usbduxsub->high_speed) { 656 /* uframes */ 657 urb->interval = 8; 658 } else { 659 /* frames */ 660 urb->interval = 1; 661 } 662 urb->number_of_packets = 1; 663 urb->iso_frame_desc[0].offset = 0; 664 urb->iso_frame_desc[0].length = SIZEOUTBUF; 665 urb->iso_frame_desc[0].status = 0; 666 ret = usb_submit_urb(urb, GFP_ATOMIC); 667 if (ret < 0) { 668 dev_err(&urb->dev->dev, 669 "comedi_: ao urb resubm failed in int-cont. " 670 "ret=%d", ret); 671 if (ret == EL2NSYNC) 672 dev_err(&urb->dev->dev, 673 "buggy USB host controller or bug in " 674 "IRQ handling!\n"); 675 676 s->async->events |= COMEDI_CB_EOA; 677 s->async->events |= COMEDI_CB_ERROR; 678 comedi_event(this_usbduxsub->comedidev, s); 679 /* don't do an unlink here */ 680 usbdux_ao_stop(this_usbduxsub, 0); 681 } 682 } 683} 684 685static int usbduxsub_start(struct usbduxsub *usbduxsub) 686{ 687 int errcode = 0; 688 uint8_t local_transfer_buffer[16]; 689 690 /* 7f92 to zero */ 691 local_transfer_buffer[0] = 0; 692 errcode = usb_control_msg(usbduxsub->usbdev, 693 /* create a pipe for a control transfer */ 694 usb_sndctrlpipe(usbduxsub->usbdev, 0), 695 /* bRequest, "Firmware" */ 696 USBDUXSUB_FIRMWARE, 697 /* bmRequestType */ 698 VENDOR_DIR_OUT, 699 /* Value */ 700 USBDUXSUB_CPUCS, 701 /* Index */ 702 0x0000, 703 /* address of the transfer buffer */ 704 local_transfer_buffer, 705 /* Length */ 706 1, 707 /* Timeout */ 708 BULK_TIMEOUT); 709 if (errcode < 0) { 710 dev_err(&usbduxsub->interface->dev, 711 "comedi_: control msg failed (start)\n"); 712 return errcode; 713 } 714 return 0; 715} 716 717static int usbduxsub_stop(struct usbduxsub *usbduxsub) 718{ 719 int errcode = 0; 720 721 uint8_t local_transfer_buffer[16]; 722 723 /* 7f92 to one */ 724 local_transfer_buffer[0] = 1; 725 errcode = usb_control_msg(usbduxsub->usbdev, 726 usb_sndctrlpipe(usbduxsub->usbdev, 0), 727 /* bRequest, "Firmware" */ 728 USBDUXSUB_FIRMWARE, 729 /* bmRequestType */ 730 VENDOR_DIR_OUT, 731 /* Value */ 732 USBDUXSUB_CPUCS, 733 /* Index */ 734 0x0000, local_transfer_buffer, 735 /* Length */ 736 1, 737 /* Timeout */ 738 BULK_TIMEOUT); 739 if (errcode < 0) { 740 dev_err(&usbduxsub->interface->dev, 741 "comedi_: control msg failed (stop)\n"); 742 return errcode; 743 } 744 return 0; 745} 746 747static int usbduxsub_upload(struct usbduxsub *usbduxsub, 748 uint8_t *local_transfer_buffer, 749 unsigned int startAddr, unsigned int len) 750{ 751 int errcode; 752 753 errcode = usb_control_msg(usbduxsub->usbdev, 754 usb_sndctrlpipe(usbduxsub->usbdev, 0), 755 /* brequest, firmware */ 756 USBDUXSUB_FIRMWARE, 757 /* bmRequestType */ 758 VENDOR_DIR_OUT, 759 /* value */ 760 startAddr, 761 /* index */ 762 0x0000, 763 /* our local safe buffer */ 764 local_transfer_buffer, 765 /* length */ 766 len, 767 /* timeout */ 768 BULK_TIMEOUT); 769 dev_dbg(&usbduxsub->interface->dev, "comedi_: result=%d\n", errcode); 770 if (errcode < 0) { 771 dev_err(&usbduxsub->interface->dev, 772 "comedi_: upload failed\n"); 773 return errcode; 774 } 775 return 0; 776} 777 778/* the FX2LP has twice as much as the standard FX2 */ 779#define FIRMWARE_MAX_LEN 0x4000 780 781static int firmwareUpload(struct usbduxsub *usbduxsub, 782 const u8 *firmwareBinary, int sizeFirmware) 783{ 784 int ret; 785 uint8_t *fwBuf; 786 787 if (!firmwareBinary) 788 return 0; 789 790 if (sizeFirmware > FIRMWARE_MAX_LEN) { 791 dev_err(&usbduxsub->interface->dev, 792 "usbduxsigma firmware binary it too large for FX2.\n"); 793 return -ENOMEM; 794 } 795 796 /* we generate a local buffer for the firmware */ 797 fwBuf = kmemdup(firmwareBinary, sizeFirmware, GFP_KERNEL); 798 if (!fwBuf) { 799 dev_err(&usbduxsub->interface->dev, 800 "comedi_: mem alloc for firmware failed\n"); 801 return -ENOMEM; 802 } 803 804 ret = usbduxsub_stop(usbduxsub); 805 if (ret < 0) { 806 dev_err(&usbduxsub->interface->dev, 807 "comedi_: can not stop firmware\n"); 808 kfree(fwBuf); 809 return ret; 810 } 811 812 ret = usbduxsub_upload(usbduxsub, fwBuf, 0, sizeFirmware); 813 if (ret < 0) { 814 dev_err(&usbduxsub->interface->dev, 815 "comedi_: firmware upload failed\n"); 816 kfree(fwBuf); 817 return ret; 818 } 819 ret = usbduxsub_start(usbduxsub); 820 if (ret < 0) { 821 dev_err(&usbduxsub->interface->dev, 822 "comedi_: can not start firmware\n"); 823 kfree(fwBuf); 824 return ret; 825 } 826 kfree(fwBuf); 827 return 0; 828} 829 830static int usbduxsub_submit_InURBs(struct usbduxsub *usbduxsub) 831{ 832 int i, errFlag; 833 834 if (!usbduxsub) 835 return -EFAULT; 836 837 /* Submit all URBs and start the transfer on the bus */ 838 for (i = 0; i < usbduxsub->numOfInBuffers; i++) { 839 /* in case of a resubmission after an unlink... */ 840 usbduxsub->urbIn[i]->interval = usbduxsub->ai_interval; 841 usbduxsub->urbIn[i]->context = usbduxsub->comedidev; 842 usbduxsub->urbIn[i]->dev = usbduxsub->usbdev; 843 usbduxsub->urbIn[i]->status = 0; 844 usbduxsub->urbIn[i]->transfer_flags = URB_ISO_ASAP; 845 dev_dbg(&usbduxsub->interface->dev, 846 "comedi%d: submitting in-urb[%d]: %p,%p intv=%d\n", 847 usbduxsub->comedidev->minor, i, 848 (usbduxsub->urbIn[i]->context), 849 (usbduxsub->urbIn[i]->dev), 850 (usbduxsub->urbIn[i]->interval)); 851 errFlag = usb_submit_urb(usbduxsub->urbIn[i], GFP_ATOMIC); 852 if (errFlag) { 853 dev_err(&usbduxsub->interface->dev, 854 "comedi_: ai: usb_submit_urb(%d) error %d\n", 855 i, errFlag); 856 return errFlag; 857 } 858 } 859 return 0; 860} 861 862static int usbduxsub_submit_OutURBs(struct usbduxsub *usbduxsub) 863{ 864 int i, errFlag; 865 866 if (!usbduxsub) 867 return -EFAULT; 868 869 for (i = 0; i < usbduxsub->numOfOutBuffers; i++) { 870 dev_dbg(&usbduxsub->interface->dev, 871 "comedi_: submitting out-urb[%d]\n", i); 872 /* in case of a resubmission after an unlink... */ 873 usbduxsub->urbOut[i]->context = usbduxsub->comedidev; 874 usbduxsub->urbOut[i]->dev = usbduxsub->usbdev; 875 usbduxsub->urbOut[i]->status = 0; 876 usbduxsub->urbOut[i]->transfer_flags = URB_ISO_ASAP; 877 errFlag = usb_submit_urb(usbduxsub->urbOut[i], GFP_ATOMIC); 878 if (errFlag) { 879 dev_err(&usbduxsub->interface->dev, 880 "comedi_: ao: usb_submit_urb(%d) error %d\n", 881 i, errFlag); 882 return errFlag; 883 } 884 } 885 return 0; 886} 887 888static int chanToInterval(int nChannels) 889{ 890 if (nChannels <= 2) 891 /* 4kHz */ 892 return 2; 893 if (nChannels <= 8) 894 /* 2kHz */ 895 return 4; 896 /* 1kHz */ 897 return 8; 898} 899 900static int usbdux_ai_cmdtest(struct comedi_device *dev, 901 struct comedi_subdevice *s, 902 struct comedi_cmd *cmd) 903{ 904 int err = 0, tmp, i; 905 unsigned int tmpTimer; 906 struct usbduxsub *this_usbduxsub = dev->private; 907 908 if (!(this_usbduxsub->probed)) 909 return -ENODEV; 910 911 dev_dbg(&this_usbduxsub->interface->dev, 912 "comedi%d: usbdux_ai_cmdtest\n", dev->minor); 913 914 /* make sure triggers are valid */ 915 /* Only immediate triggers are allowed */ 916 tmp = cmd->start_src; 917 cmd->start_src &= TRIG_NOW | TRIG_INT; 918 if (!cmd->start_src || tmp != cmd->start_src) 919 err++; 920 921 /* trigger should happen timed */ 922 tmp = cmd->scan_begin_src; 923 /* start a new _scan_ with a timer */ 924 cmd->scan_begin_src &= TRIG_TIMER; 925 if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) 926 err++; 927 928 /* scanning is continuous */ 929 tmp = cmd->convert_src; 930 cmd->convert_src &= TRIG_NOW; 931 if (!cmd->convert_src || tmp != cmd->convert_src) 932 err++; 933 934 /* issue a trigger when scan is finished and start a new scan */ 935 tmp = cmd->scan_end_src; 936 cmd->scan_end_src &= TRIG_COUNT; 937 if (!cmd->scan_end_src || tmp != cmd->scan_end_src) 938 err++; 939 940 /* trigger at the end of count events or not, stop condition or not */ 941 tmp = cmd->stop_src; 942 cmd->stop_src &= TRIG_COUNT | TRIG_NONE; 943 if (!cmd->stop_src || tmp != cmd->stop_src) 944 err++; 945 946 if (err) 947 return 1; 948 949 /* 950 * step 2: make sure trigger sources are unique and mutually compatible 951 * note that mutual compatibility is not an issue here 952 */ 953 if (cmd->scan_begin_src != TRIG_FOLLOW && 954 cmd->scan_begin_src != TRIG_EXT && 955 cmd->scan_begin_src != TRIG_TIMER) 956 err++; 957 if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE) 958 err++; 959 960 if (err) 961 return 2; 962 963 /* step 3: make sure arguments are trivially compatible */ 964 if (cmd->start_arg != 0) { 965 cmd->start_arg = 0; 966 err++; 967 } 968 969 if (cmd->scan_begin_src == TRIG_FOLLOW) { 970 /* internal trigger */ 971 if (cmd->scan_begin_arg != 0) { 972 cmd->scan_begin_arg = 0; 973 err++; 974 } 975 } 976 977 if (cmd->scan_begin_src == TRIG_TIMER) { 978 if (this_usbduxsub->high_speed) { 979 /* 980 * In high speed mode microframes are possible. 981 * However, during one microframe we can roughly 982 * sample two channels. Thus, the more channels 983 * are in the channel list the more time we need. 984 */ 985 i = chanToInterval(cmd->chanlist_len); 986 if (cmd->scan_begin_arg < (1000000 / 8 * i)) { 987 cmd->scan_begin_arg = 1000000 / 8 * i; 988 err++; 989 } 990 /* now calc the real sampling rate with all the 991 * rounding errors */ 992 tmpTimer = 993 ((unsigned int)(cmd->scan_begin_arg / 125000)) * 994 125000; 995 if (cmd->scan_begin_arg != tmpTimer) { 996 cmd->scan_begin_arg = tmpTimer; 997 err++; 998 } 999 } else { 1000 /* full speed */ 1001 /* 1kHz scans every USB frame */ 1002 if (cmd->scan_begin_arg < 1000000) { 1003 cmd->scan_begin_arg = 1000000; 1004 err++; 1005 } 1006 /* 1007 * calc the real sampling rate with the rounding errors 1008 */ 1009 tmpTimer = ((unsigned int)(cmd->scan_begin_arg / 1010 1000000)) * 1000000; 1011 if (cmd->scan_begin_arg != tmpTimer) { 1012 cmd->scan_begin_arg = tmpTimer; 1013 err++; 1014 } 1015 } 1016 } 1017 /* the same argument */ 1018 if (cmd->scan_end_arg != cmd->chanlist_len) { 1019 cmd->scan_end_arg = cmd->chanlist_len; 1020 err++; 1021 } 1022 1023 if (cmd->stop_src == TRIG_COUNT) { 1024 /* any count is allowed */ 1025 } else { 1026 /* TRIG_NONE */ 1027 if (cmd->stop_arg != 0) { 1028 cmd->stop_arg = 0; 1029 err++; 1030 } 1031 } 1032 1033 if (err) 1034 return 3; 1035 1036 return 0; 1037} 1038 1039/* 1040 * creates the ADC command for the MAX1271 1041 * range is the range value from comedi 1042 */ 1043static void create_adc_command(unsigned int chan, 1044 uint8_t *muxsg0, 1045 uint8_t *muxsg1) 1046{ 1047 if (chan < 8) 1048 (*muxsg0) = (*muxsg0) | (1 << chan); 1049 else if (chan < 16) 1050 (*muxsg1) = (*muxsg1) | (1 << (chan-8)); 1051} 1052 1053 1054/* bulk transfers to usbdux */ 1055 1056#define SENDADCOMMANDS 0 1057#define SENDDACOMMANDS 1 1058#define SENDDIOCONFIGCOMMAND 2 1059#define SENDDIOBITSCOMMAND 3 1060#define SENDSINGLEAD 4 1061#define SENDPWMON 7 1062#define SENDPWMOFF 8 1063 1064static int send_dux_commands(struct usbduxsub *this_usbduxsub, int cmd_type) 1065{ 1066 int result, nsent; 1067 1068 this_usbduxsub->dux_commands[0] = cmd_type; 1069#ifdef NOISY_DUX_DEBUGBUG 1070 printk(KERN_DEBUG "comedi%d: usbdux: dux_commands: ", 1071 this_usbduxsub->comedidev->minor); 1072 for (result = 0; result < SIZEOFDUXBUFFER; result++) 1073 printk(" %02x", this_usbduxsub->dux_commands[result]); 1074 printk("\n"); 1075#endif 1076 result = usb_bulk_msg(this_usbduxsub->usbdev, 1077 usb_sndbulkpipe(this_usbduxsub->usbdev, 1078 COMMAND_OUT_EP), 1079 this_usbduxsub->dux_commands, SIZEOFDUXBUFFER, 1080 &nsent, BULK_TIMEOUT); 1081 if (result < 0) 1082 dev_err(&this_usbduxsub->interface->dev, "comedi%d: " 1083 "could not transmit dux_command to the usb-device, " 1084 "err=%d\n", this_usbduxsub->comedidev->minor, result); 1085 1086 return result; 1087} 1088 1089static int receive_dux_commands(struct usbduxsub *this_usbduxsub, int command) 1090{ 1091 int result = (-EFAULT); 1092 int nrec; 1093 int i; 1094 1095 for (i = 0; i < RETRIES; i++) { 1096 result = usb_bulk_msg(this_usbduxsub->usbdev, 1097 usb_rcvbulkpipe(this_usbduxsub->usbdev, 1098 COMMAND_IN_EP), 1099 this_usbduxsub->insnBuffer, SIZEINSNBUF, 1100 &nrec, BULK_TIMEOUT); 1101 if (result < 0) { 1102 dev_err(&this_usbduxsub->interface->dev, "comedi%d: " 1103 "insn: USB error %d " 1104 "while receiving DUX command" 1105 "\n", this_usbduxsub->comedidev->minor, 1106 result); 1107 return result; 1108 } 1109 if (this_usbduxsub->insnBuffer[0] == command) 1110 return result; 1111 } 1112 /* this is only reached if the data has been requested a couple of 1113 * times */ 1114 dev_err(&this_usbduxsub->interface->dev, "comedi%d: insn: " 1115 "wrong data returned from firmware: want %d, got %d.\n", 1116 this_usbduxsub->comedidev->minor, command, 1117 this_usbduxsub->insnBuffer[0]); 1118 return -EFAULT; 1119} 1120 1121static int usbdux_ai_inttrig(struct comedi_device *dev, 1122 struct comedi_subdevice *s, unsigned int trignum) 1123{ 1124 int ret; 1125 struct usbduxsub *this_usbduxsub = dev->private; 1126 if (!this_usbduxsub) 1127 return -EFAULT; 1128 1129 down(&this_usbduxsub->sem); 1130 if (!(this_usbduxsub->probed)) { 1131 up(&this_usbduxsub->sem); 1132 return -ENODEV; 1133 } 1134 dev_dbg(&this_usbduxsub->interface->dev, 1135 "comedi%d: usbdux_ai_inttrig\n", dev->minor); 1136 1137 if (trignum != 0) { 1138 dev_err(&this_usbduxsub->interface->dev, 1139 "comedi%d: usbdux_ai_inttrig: invalid trignum\n", 1140 dev->minor); 1141 up(&this_usbduxsub->sem); 1142 return -EINVAL; 1143 } 1144 if (!(this_usbduxsub->ai_cmd_running)) { 1145 this_usbduxsub->ai_cmd_running = 1; 1146 ret = usbduxsub_submit_InURBs(this_usbduxsub); 1147 if (ret < 0) { 1148 dev_err(&this_usbduxsub->interface->dev, 1149 "comedi%d: usbdux_ai_inttrig: " 1150 "urbSubmit: err=%d\n", dev->minor, ret); 1151 this_usbduxsub->ai_cmd_running = 0; 1152 up(&this_usbduxsub->sem); 1153 return ret; 1154 } 1155 s->async->inttrig = NULL; 1156 } else { 1157 dev_err(&this_usbduxsub->interface->dev, 1158 "comedi%d: ai_inttrig but acqu is already running\n", 1159 dev->minor); 1160 } 1161 up(&this_usbduxsub->sem); 1162 return 1; 1163} 1164 1165static int usbdux_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) 1166{ 1167 struct comedi_cmd *cmd = &s->async->cmd; 1168 unsigned int chan; 1169 int i, ret; 1170 struct usbduxsub *this_usbduxsub = dev->private; 1171 int result; 1172 uint8_t muxsg0 = 0; 1173 uint8_t muxsg1 = 0; 1174 uint8_t sysred = 0; 1175 1176 if (!this_usbduxsub) 1177 return -EFAULT; 1178 1179 dev_dbg(&this_usbduxsub->interface->dev, 1180 "comedi%d: usbdux_ai_cmd\n", dev->minor); 1181 1182 /* block other CPUs from starting an ai_cmd */ 1183 down(&this_usbduxsub->sem); 1184 1185 if (!(this_usbduxsub->probed)) { 1186 up(&this_usbduxsub->sem); 1187 return -ENODEV; 1188 } 1189 if (this_usbduxsub->ai_cmd_running) { 1190 dev_err(&this_usbduxsub->interface->dev, "comedi%d: " 1191 "ai_cmd not possible. Another ai_cmd is running.\n", 1192 dev->minor); 1193 up(&this_usbduxsub->sem); 1194 return -EBUSY; 1195 } 1196 /* set current channel of the running acquisition to zero */ 1197 s->async->cur_chan = 0; 1198 1199 /* first the number of channels per time step */ 1200 this_usbduxsub->dux_commands[1] = cmd->chanlist_len; 1201 1202 /* CONFIG0 */ 1203 this_usbduxsub->dux_commands[2] = 0x12; 1204 1205 /* CONFIG1: 23kHz sampling rate, delay = 0us, */ 1206 this_usbduxsub->dux_commands[3] = 0x03; 1207 1208 /* CONFIG3: differential channels off */ 1209 this_usbduxsub->dux_commands[4] = 0x00; 1210 1211 for (i = 0; i < cmd->chanlist_len; i++) { 1212 chan = CR_CHAN(cmd->chanlist[i]); 1213 create_adc_command(chan, &muxsg0, &muxsg1); 1214 if (i >= NUMCHANNELS) { 1215 dev_err(&this_usbduxsub->interface->dev, 1216 "comedi%d: channel list too long\n", 1217 dev->minor); 1218 break; 1219 } 1220 } 1221 this_usbduxsub->dux_commands[5] = muxsg0; 1222 this_usbduxsub->dux_commands[6] = muxsg1; 1223 this_usbduxsub->dux_commands[7] = sysred; 1224 1225 dev_dbg(&this_usbduxsub->interface->dev, 1226 "comedi %d: sending commands to the usb device: size=%u\n", 1227 dev->minor, NUMCHANNELS); 1228 1229 result = send_dux_commands(this_usbduxsub, SENDADCOMMANDS); 1230 if (result < 0) { 1231 up(&this_usbduxsub->sem); 1232 return result; 1233 } 1234 1235 if (this_usbduxsub->high_speed) { 1236 /* 1237 * every 2 channels get a time window of 125us. Thus, if we 1238 * sample all 16 channels we need 1ms. If we sample only one 1239 * channel we need only 125us 1240 */ 1241 this_usbduxsub->ai_interval = 1242 chanToInterval(cmd->chanlist_len); 1243 this_usbduxsub->ai_timer = cmd->scan_begin_arg / (125000 * 1244 (this_usbduxsub-> 1245 ai_interval)); 1246 } else { 1247 /* interval always 1ms */ 1248 this_usbduxsub->ai_interval = 1; 1249 this_usbduxsub->ai_timer = cmd->scan_begin_arg / 1000000; 1250 } 1251 if (this_usbduxsub->ai_timer < 1) { 1252 dev_err(&this_usbduxsub->interface->dev, "comedi%d: ai_cmd: " 1253 "timer=%d, scan_begin_arg=%d. " 1254 "Not properly tested by cmdtest?\n", dev->minor, 1255 this_usbduxsub->ai_timer, cmd->scan_begin_arg); 1256 up(&this_usbduxsub->sem); 1257 return -EINVAL; 1258 } 1259 this_usbduxsub->ai_counter = this_usbduxsub->ai_timer; 1260 1261 if (cmd->stop_src == TRIG_COUNT) { 1262 /* data arrives as one packet */ 1263 this_usbduxsub->ai_sample_count = cmd->stop_arg; 1264 this_usbduxsub->ai_continuous = 0; 1265 } else { 1266 /* continuous acquisition */ 1267 this_usbduxsub->ai_continuous = 1; 1268 this_usbduxsub->ai_sample_count = 0; 1269 } 1270 1271 if (cmd->start_src == TRIG_NOW) { 1272 /* enable this acquisition operation */ 1273 this_usbduxsub->ai_cmd_running = 1; 1274 ret = usbduxsub_submit_InURBs(this_usbduxsub); 1275 if (ret < 0) { 1276 this_usbduxsub->ai_cmd_running = 0; 1277 /* fixme: unlink here?? */ 1278 up(&this_usbduxsub->sem); 1279 return ret; 1280 } 1281 s->async->inttrig = NULL; 1282 } else { 1283 /* TRIG_INT */ 1284 /* don't enable the acquision operation */ 1285 /* wait for an internal signal */ 1286 s->async->inttrig = usbdux_ai_inttrig; 1287 } 1288 up(&this_usbduxsub->sem); 1289 return 0; 1290} 1291 1292/* Mode 0 is used to get a single conversion on demand */ 1293static int usbdux_ai_insn_read(struct comedi_device *dev, 1294 struct comedi_subdevice *s, 1295 struct comedi_insn *insn, unsigned int *data) 1296{ 1297 int i; 1298 int32_t one = 0; 1299 int chan; 1300 int err; 1301 struct usbduxsub *this_usbduxsub = dev->private; 1302 uint8_t muxsg0 = 0; 1303 uint8_t muxsg1 = 0; 1304 uint8_t sysred = 0; 1305 1306 if (!this_usbduxsub) 1307 return 0; 1308 1309 dev_dbg(&this_usbduxsub->interface->dev, 1310 "comedi%d: ai_insn_read, insn->n=%d, insn->subdev=%d\n", 1311 dev->minor, insn->n, insn->subdev); 1312 1313 down(&this_usbduxsub->sem); 1314 if (!(this_usbduxsub->probed)) { 1315 up(&this_usbduxsub->sem); 1316 return -ENODEV; 1317 } 1318 if (this_usbduxsub->ai_cmd_running) { 1319 dev_err(&this_usbduxsub->interface->dev, 1320 "comedi%d: ai_insn_read not possible. " 1321 "Async Command is running.\n", dev->minor); 1322 up(&this_usbduxsub->sem); 1323 return 0; 1324 } 1325 1326 /* sample one channel */ 1327 /* CONFIG0: chopper on */ 1328 this_usbduxsub->dux_commands[1] = 0x16; 1329 1330 /* CONFIG1: 2kHz sampling rate */ 1331 this_usbduxsub->dux_commands[2] = 0x80; 1332 1333 /* CONFIG3: differential channels off */ 1334 this_usbduxsub->dux_commands[3] = 0x00; 1335 1336 chan = CR_CHAN(insn->chanspec); 1337 create_adc_command(chan, &muxsg0, &muxsg1); 1338 1339 this_usbduxsub->dux_commands[4] = muxsg0; 1340 this_usbduxsub->dux_commands[5] = muxsg1; 1341 this_usbduxsub->dux_commands[6] = sysred; 1342 1343 /* adc commands */ 1344 err = send_dux_commands(this_usbduxsub, SENDSINGLEAD); 1345 if (err < 0) { 1346 up(&this_usbduxsub->sem); 1347 return err; 1348 } 1349 1350 for (i = 0; i < insn->n; i++) { 1351 err = receive_dux_commands(this_usbduxsub, SENDSINGLEAD); 1352 if (err < 0) { 1353 up(&this_usbduxsub->sem); 1354 return 0; 1355 } 1356 /* 32 bits big endian from the A/D converter */ 1357 one = be32_to_cpu(*((int32_t *) 1358 ((this_usbduxsub->insnBuffer)+1))); 1359 /* mask out the staus byte */ 1360 one = one & 0x00ffffff; 1361 /* turn it into an unsigned integer */ 1362 one = one ^ 0x00800000; 1363 data[i] = one; 1364 } 1365 up(&this_usbduxsub->sem); 1366 return i; 1367} 1368 1369 1370 1371 1372static int usbdux_getstatusinfo(struct comedi_device *dev, int chan) 1373{ 1374 struct usbduxsub *this_usbduxsub = dev->private; 1375 uint8_t sysred = 0; 1376 uint32_t one; 1377 int err; 1378 1379 if (!this_usbduxsub) 1380 return 0; 1381 1382 if (this_usbduxsub->ai_cmd_running) { 1383 dev_err(&this_usbduxsub->interface->dev, 1384 "comedi%d: status read not possible. " 1385 "Async Command is running.\n", dev->minor); 1386 return 0; 1387 } 1388 1389 /* CONFIG0 */ 1390 this_usbduxsub->dux_commands[1] = 0x12; 1391 1392 /* CONFIG1: 2kHz sampling rate */ 1393 this_usbduxsub->dux_commands[2] = 0x80; 1394 1395 /* CONFIG3: differential channels off */ 1396 this_usbduxsub->dux_commands[3] = 0x00; 1397 1398 if (chan == 1) { 1399 /* ADC offset */ 1400 sysred = sysred | 1; 1401 } else if (chan == 2) { 1402 /* VCC */ 1403 sysred = sysred | 4; 1404 } else if (chan == 3) { 1405 /* temperature */ 1406 sysred = sysred | 8; 1407 } else if (chan == 4) { 1408 /* gain */ 1409 sysred = sysred | 16; 1410 } else if (chan == 5) { 1411 /* ref */ 1412 sysred = sysred | 32; 1413 } 1414 1415 this_usbduxsub->dux_commands[4] = 0; 1416 this_usbduxsub->dux_commands[5] = 0; 1417 this_usbduxsub->dux_commands[6] = sysred; 1418 1419 /* adc commands */ 1420 err = send_dux_commands(this_usbduxsub, SENDSINGLEAD); 1421 if (err < 0) 1422 return err; 1423 1424 err = receive_dux_commands(this_usbduxsub, SENDSINGLEAD); 1425 if (err < 0) 1426 return err; 1427 1428 /* 32 bits big endian from the A/D converter */ 1429 one = be32_to_cpu(*((int32_t *)((this_usbduxsub->insnBuffer)+1))); 1430 /* mask out the staus byte */ 1431 one = one & 0x00ffffff; 1432 one = one ^ 0x00800000; 1433 1434 return (int)one; 1435} 1436 1437 1438 1439 1440 1441 1442/************************************/ 1443/* analog out */ 1444 1445static int usbdux_ao_insn_read(struct comedi_device *dev, 1446 struct comedi_subdevice *s, 1447 struct comedi_insn *insn, unsigned int *data) 1448{ 1449 int i; 1450 int chan = CR_CHAN(insn->chanspec); 1451 struct usbduxsub *this_usbduxsub = dev->private; 1452 1453 if (!this_usbduxsub) 1454 return -EFAULT; 1455 1456 down(&this_usbduxsub->sem); 1457 if (!(this_usbduxsub->probed)) { 1458 up(&this_usbduxsub->sem); 1459 return -ENODEV; 1460 } 1461 for (i = 0; i < insn->n; i++) 1462 data[i] = this_usbduxsub->outBuffer[chan]; 1463 1464 up(&this_usbduxsub->sem); 1465 return i; 1466} 1467 1468static int usbdux_ao_insn_write(struct comedi_device *dev, 1469 struct comedi_subdevice *s, 1470 struct comedi_insn *insn, unsigned int *data) 1471{ 1472 int i, err; 1473 int chan = CR_CHAN(insn->chanspec); 1474 struct usbduxsub *this_usbduxsub = dev->private; 1475 1476 if (!this_usbduxsub) 1477 return -EFAULT; 1478 1479 dev_dbg(&this_usbduxsub->interface->dev, 1480 "comedi%d: ao_insn_write\n", dev->minor); 1481 1482 down(&this_usbduxsub->sem); 1483 if (!(this_usbduxsub->probed)) { 1484 up(&this_usbduxsub->sem); 1485 return -ENODEV; 1486 } 1487 if (this_usbduxsub->ao_cmd_running) { 1488 dev_err(&this_usbduxsub->interface->dev, 1489 "comedi%d: ao_insn_write: " 1490 "ERROR: asynchronous ao_cmd is running\n", dev->minor); 1491 up(&this_usbduxsub->sem); 1492 return 0; 1493 } 1494 1495 for (i = 0; i < insn->n; i++) { 1496 dev_dbg(&this_usbduxsub->interface->dev, 1497 "comedi%d: ao_insn_write: data[chan=%d,i=%d]=%d\n", 1498 dev->minor, chan, i, data[i]); 1499 1500 /* number of channels: 1 */ 1501 this_usbduxsub->dux_commands[1] = 1; 1502 /* channel number */ 1503 this_usbduxsub->dux_commands[2] = data[i]; 1504 this_usbduxsub->outBuffer[chan] = data[i]; 1505 this_usbduxsub->dux_commands[3] = chan; 1506 err = send_dux_commands(this_usbduxsub, SENDDACOMMANDS); 1507 if (err < 0) { 1508 up(&this_usbduxsub->sem); 1509 return err; 1510 } 1511 } 1512 up(&this_usbduxsub->sem); 1513 1514 return i; 1515} 1516 1517static int usbdux_ao_inttrig(struct comedi_device *dev, 1518 struct comedi_subdevice *s, unsigned int trignum) 1519{ 1520 int ret; 1521 struct usbduxsub *this_usbduxsub = dev->private; 1522 1523 if (!this_usbduxsub) 1524 return -EFAULT; 1525 1526 down(&this_usbduxsub->sem); 1527 1528 if (!(this_usbduxsub->probed)) { 1529 ret = -ENODEV; 1530 goto out; 1531 } 1532 if (trignum != 0) { 1533 dev_err(&this_usbduxsub->interface->dev, 1534 "comedi%d: usbdux_ao_inttrig: invalid trignum\n", 1535 dev->minor); 1536 ret = -EINVAL; 1537 goto out; 1538 } 1539 if (!(this_usbduxsub->ao_cmd_running)) { 1540 this_usbduxsub->ao_cmd_running = 1; 1541 ret = usbduxsub_submit_OutURBs(this_usbduxsub); 1542 if (ret < 0) { 1543 dev_err(&this_usbduxsub->interface->dev, 1544 "comedi%d: usbdux_ao_inttrig: submitURB: " 1545 "err=%d\n", dev->minor, ret); 1546 this_usbduxsub->ao_cmd_running = 0; 1547 goto out; 1548 } 1549 s->async->inttrig = NULL; 1550 } else { 1551 dev_err(&this_usbduxsub->interface->dev, 1552 "comedi%d: ao_inttrig but acqu is already running.\n", 1553 dev->minor); 1554 } 1555 ret = 1; 1556out: 1557 up(&this_usbduxsub->sem); 1558 return ret; 1559} 1560 1561static int usbdux_ao_cmdtest(struct comedi_device *dev, 1562 struct comedi_subdevice *s, 1563 struct comedi_cmd *cmd) 1564{ 1565 int err = 0, tmp; 1566 struct usbduxsub *this_usbduxsub = dev->private; 1567 1568 if (!this_usbduxsub) 1569 return -EFAULT; 1570 1571 if (!(this_usbduxsub->probed)) 1572 return -ENODEV; 1573 1574 dev_dbg(&this_usbduxsub->interface->dev, 1575 "comedi%d: usbdux_ao_cmdtest\n", dev->minor); 1576 1577 /* make sure triggers are valid */ 1578 /* Only immediate triggers are allowed */ 1579 tmp = cmd->start_src; 1580 cmd->start_src &= TRIG_NOW | TRIG_INT; 1581 if (!cmd->start_src || tmp != cmd->start_src) 1582 err++; 1583 1584 /* trigger should happen timed */ 1585 tmp = cmd->scan_begin_src; 1586 /* just now we scan also in the high speed mode every frame */ 1587 /* this is due to ehci driver limitations */ 1588 if (0) { /* (this_usbduxsub->high_speed) */ 1589 /* start immediately a new scan */ 1590 /* the sampling rate is set by the coversion rate */ 1591 cmd->scan_begin_src &= TRIG_FOLLOW; 1592 } else { 1593 /* start a new scan (output at once) with a timer */ 1594 cmd->scan_begin_src &= TRIG_TIMER; 1595 } 1596 if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src) 1597 err++; 1598 1599 /* scanning is continuous */ 1600 tmp = cmd->convert_src; 1601 1602 /* all conversion events happen simultaneously */ 1603 cmd->convert_src &= TRIG_NOW; 1604 1605 if (!cmd->convert_src || tmp != cmd->convert_src) 1606 err++; 1607 1608 /* issue a trigger when scan is finished and start a new scan */ 1609 tmp = cmd->scan_end_src; 1610 cmd->scan_end_src &= TRIG_COUNT; 1611 if (!cmd->scan_end_src || tmp != cmd->scan_end_src) 1612 err++; 1613 1614 /* trigger at the end of count events or not, stop condition or not */ 1615 tmp = cmd->stop_src; 1616 cmd->stop_src &= TRIG_COUNT | TRIG_NONE; 1617 if (!cmd->stop_src || tmp != cmd->stop_src) 1618 err++; 1619 1620 if (err) 1621 return 1; 1622 1623 /* 1624 * step 2: make sure trigger sources 1625 * are unique and mutually compatible 1626 * note that mutual compatibility is not an issue here 1627 */ 1628 if (cmd->scan_begin_src != TRIG_FOLLOW && 1629 cmd->scan_begin_src != TRIG_EXT && 1630 cmd->scan_begin_src != TRIG_TIMER) 1631 err++; 1632 if (cmd->stop_src != TRIG_COUNT && cmd->stop_src != TRIG_NONE) 1633 err++; 1634 1635 if (err) 1636 return 2; 1637 1638 /* step 3: make sure arguments are trivially compatible */ 1639 1640 if (cmd->start_arg != 0) { 1641 cmd->start_arg = 0; 1642 err++; 1643 } 1644 1645 if (cmd->scan_begin_src == TRIG_FOLLOW) { 1646 /* internal trigger */ 1647 if (cmd->scan_begin_arg != 0) { 1648 cmd->scan_begin_arg = 0; 1649 err++; 1650 } 1651 } 1652 1653 if (cmd->scan_begin_src == TRIG_TIMER) { 1654 /* timer */ 1655 if (cmd->scan_begin_arg < 1000000) { 1656 cmd->scan_begin_arg = 1000000; 1657 err++; 1658 } 1659 } 1660 /* not used now, is for later use */ 1661 if (cmd->convert_src == TRIG_TIMER) { 1662 if (cmd->convert_arg < 125000) { 1663 cmd->convert_arg = 125000; 1664 err++; 1665 } 1666 } 1667 1668 /* the same argument */ 1669 if (cmd->scan_end_arg != cmd->chanlist_len) { 1670 cmd->scan_end_arg = cmd->chanlist_len; 1671 err++; 1672 } 1673 1674 if (cmd->stop_src == TRIG_COUNT) { 1675 /* any count is allowed */ 1676 } else { 1677 /* TRIG_NONE */ 1678 if (cmd->stop_arg != 0) { 1679 cmd->stop_arg = 0; 1680 err++; 1681 } 1682 } 1683 1684 dev_dbg(&this_usbduxsub->interface->dev, "comedi%d: err=%d, " 1685 "scan_begin_src=%d, scan_begin_arg=%d, convert_src=%d, " 1686 "convert_arg=%d\n", dev->minor, err, cmd->scan_begin_src, 1687 cmd->scan_begin_arg, cmd->convert_src, cmd->convert_arg); 1688 1689 if (err) 1690 return 3; 1691 1692 return 0; 1693} 1694 1695static int usbdux_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s) 1696{ 1697 struct comedi_cmd *cmd = &s->async->cmd; 1698 unsigned int chan, gain; 1699 int i, ret; 1700 struct usbduxsub *this_usbduxsub = dev->private; 1701 1702 if (!this_usbduxsub) 1703 return -EFAULT; 1704 1705 down(&this_usbduxsub->sem); 1706 if (!(this_usbduxsub->probed)) { 1707 up(&this_usbduxsub->sem); 1708 return -ENODEV; 1709 } 1710 dev_dbg(&this_usbduxsub->interface->dev, 1711 "comedi%d: %s\n", dev->minor, __func__); 1712 1713 /* set current channel of the running acquisition to zero */ 1714 s->async->cur_chan = 0; 1715 for (i = 0; i < cmd->chanlist_len; ++i) { 1716 chan = CR_CHAN(cmd->chanlist[i]); 1717 gain = CR_RANGE(cmd->chanlist[i]); 1718 if (i >= NUMOUTCHANNELS) { 1719 dev_err(&this_usbduxsub->interface->dev, 1720 "comedi%d: %s: channel list too long\n", 1721 dev->minor, __func__); 1722 break; 1723 } 1724 this_usbduxsub->dac_commands[i] = chan; 1725 dev_dbg(&this_usbduxsub->interface->dev, 1726 "comedi%d: dac command for ch %d is %x\n", 1727 dev->minor, i, this_usbduxsub->dac_commands[i]); 1728 } 1729 1730 /* we count in steps of 1ms (125us) */ 1731 /* 125us mode not used yet */ 1732 if (0) { /* (this_usbduxsub->high_speed) */ 1733 /* 125us */ 1734 /* timing of the conversion itself: every 125 us */ 1735 this_usbduxsub->ao_timer = cmd->convert_arg / 125000; 1736 } else { 1737 /* 1ms */ 1738 /* timing of the scan: we get all channels at once */ 1739 this_usbduxsub->ao_timer = cmd->scan_begin_arg / 1000000; 1740 dev_dbg(&this_usbduxsub->interface->dev, 1741 "comedi%d: scan_begin_src=%d, scan_begin_arg=%d, " 1742 "convert_src=%d, convert_arg=%d\n", dev->minor, 1743 cmd->scan_begin_src, cmd->scan_begin_arg, 1744 cmd->convert_src, cmd->convert_arg); 1745 dev_dbg(&this_usbduxsub->interface->dev, 1746 "comedi%d: ao_timer=%d (ms)\n", 1747 dev->minor, this_usbduxsub->ao_timer); 1748 if (this_usbduxsub->ao_timer < 1) { 1749 dev_err(&this_usbduxsub->interface->dev, 1750 "comedi%d: usbdux: ao_timer=%d, " 1751 "scan_begin_arg=%d. " 1752 "Not properly tested by cmdtest?\n", 1753 dev->minor, this_usbduxsub->ao_timer, 1754 cmd->scan_begin_arg); 1755 up(&this_usbduxsub->sem); 1756 return -EINVAL; 1757 } 1758 } 1759 this_usbduxsub->ao_counter = this_usbduxsub->ao_timer; 1760 1761 if (cmd->stop_src == TRIG_COUNT) { 1762 /* not continuous */ 1763 /* counter */ 1764 /* high speed also scans everything at once */ 1765 if (0) { /* (this_usbduxsub->high_speed) */ 1766 this_usbduxsub->ao_sample_count = 1767 (cmd->stop_arg) * (cmd->scan_end_arg); 1768 } else { 1769 /* there's no scan as the scan has been */ 1770 /* perf inside the FX2 */ 1771 /* data arrives as one packet */ 1772 this_usbduxsub->ao_sample_count = cmd->stop_arg; 1773 } 1774 this_usbduxsub->ao_continuous = 0; 1775 } else { 1776 /* continuous acquisition */ 1777 this_usbduxsub->ao_continuous = 1; 1778 this_usbduxsub->ao_sample_count = 0; 1779 } 1780 1781 if (cmd->start_src == TRIG_NOW) { 1782 /* enable this acquisition operation */ 1783 this_usbduxsub->ao_cmd_running = 1; 1784 ret = usbduxsub_submit_OutURBs(this_usbduxsub); 1785 if (ret < 0) { 1786 this_usbduxsub->ao_cmd_running = 0; 1787 /* fixme: unlink here?? */ 1788 up(&this_usbduxsub->sem); 1789 return ret; 1790 } 1791 s->async->inttrig = NULL; 1792 } else { 1793 /* TRIG_INT */ 1794 /* submit the urbs later */ 1795 /* wait for an internal signal */ 1796 s->async->inttrig = usbdux_ao_inttrig; 1797 } 1798 1799 up(&this_usbduxsub->sem); 1800 return 0; 1801} 1802 1803static int usbdux_dio_insn_config(struct comedi_device *dev, 1804 struct comedi_subdevice *s, 1805 struct comedi_insn *insn, unsigned int *data) 1806{ 1807 int chan = CR_CHAN(insn->chanspec); 1808 1809 /* The input or output configuration of each digital line is 1810 * configured by a special insn_config instruction. chanspec 1811 * contains the channel to be changed, and data[0] contains the 1812 * value COMEDI_INPUT or COMEDI_OUTPUT. */ 1813 1814 switch (data[0]) { 1815 case INSN_CONFIG_DIO_OUTPUT: 1816 s->io_bits |= 1 << chan; /* 1 means Out */ 1817 break; 1818 case INSN_CONFIG_DIO_INPUT: 1819 s->io_bits &= ~(1 << chan); 1820 break; 1821 case INSN_CONFIG_DIO_QUERY: 1822 data[1] = 1823 (s->io_bits & (1 << chan)) ? COMEDI_OUTPUT : COMEDI_INPUT; 1824 break; 1825 default: 1826 return -EINVAL; 1827 break; 1828 } 1829 /* we don't tell the firmware here as it would take 8 frames */ 1830 /* to submit the information. We do it in the insn_bits. */ 1831 return insn->n; 1832} 1833 1834static int usbdux_dio_insn_bits(struct comedi_device *dev, 1835 struct comedi_subdevice *s, 1836 struct comedi_insn *insn, 1837 unsigned int *data) 1838{ 1839 1840 struct usbduxsub *this_usbduxsub = dev->private; 1841 int err; 1842 1843 if (!this_usbduxsub) 1844 return -EFAULT; 1845 1846 if (insn->n != 2) 1847 return -EINVAL; 1848 1849 down(&this_usbduxsub->sem); 1850 1851 if (!(this_usbduxsub->probed)) { 1852 up(&this_usbduxsub->sem); 1853 return -ENODEV; 1854 } 1855 1856 /* The insn data is a mask in data[0] and the new data 1857 * in data[1], each channel cooresponding to a bit. */ 1858 s->state &= ~data[0]; 1859 s->state |= data[0] & data[1]; 1860 /* The commands are 8 bits wide */ 1861 this_usbduxsub->dux_commands[1] = (s->io_bits) & 0x000000FF; 1862 this_usbduxsub->dux_commands[4] = (s->state) & 0x000000FF; 1863 this_usbduxsub->dux_commands[2] = ((s->io_bits) & 0x0000FF00) >> 8; 1864 this_usbduxsub->dux_commands[5] = ((s->state) & 0x0000FF00) >> 8; 1865 this_usbduxsub->dux_commands[3] = ((s->io_bits) & 0x00FF0000) >> 16; 1866 this_usbduxsub->dux_commands[6] = ((s->state) & 0x00FF0000) >> 16; 1867 1868 /* This command also tells the firmware to return */ 1869 /* the digital input lines */ 1870 err = send_dux_commands(this_usbduxsub, SENDDIOBITSCOMMAND); 1871 if (err < 0) { 1872 up(&this_usbduxsub->sem); 1873 return err; 1874 } 1875 err = receive_dux_commands(this_usbduxsub, SENDDIOBITSCOMMAND); 1876 if (err < 0) { 1877 up(&this_usbduxsub->sem); 1878 return err; 1879 } 1880 1881 data[1] = (((unsigned int)(this_usbduxsub->insnBuffer[1]))&0xff) | 1882 ((((unsigned int)(this_usbduxsub->insnBuffer[2]))&0xff) << 8) | 1883 ((((unsigned int)(this_usbduxsub->insnBuffer[3]))&0xff) << 16); 1884 1885 s->state = data[1]; 1886 1887 up(&this_usbduxsub->sem); 1888 return 2; 1889} 1890 1891/***********************************/ 1892/* PWM */ 1893 1894static int usbduxsub_unlink_PwmURBs(struct usbduxsub *usbduxsub_tmp) 1895{ 1896 int err = 0; 1897 1898 if (usbduxsub_tmp && usbduxsub_tmp->urbPwm) { 1899 if (usbduxsub_tmp->urbPwm) 1900 usb_kill_urb(usbduxsub_tmp->urbPwm); 1901 dev_dbg(&usbduxsub_tmp->interface->dev, 1902 "comedi: unlinked PwmURB: res=%d\n", err); 1903 } 1904 return err; 1905} 1906 1907/* This cancels a running acquisition operation 1908 * in any context. 1909 */ 1910static int usbdux_pwm_stop(struct usbduxsub *this_usbduxsub, int do_unlink) 1911{ 1912 int ret = 0; 1913 1914 if (!this_usbduxsub) 1915 return -EFAULT; 1916 1917 dev_dbg(&this_usbduxsub->interface->dev, "comedi: %s\n", __func__); 1918 if (do_unlink) 1919 ret = usbduxsub_unlink_PwmURBs(this_usbduxsub); 1920 1921 this_usbduxsub->pwm_cmd_running = 0; 1922 1923 return ret; 1924} 1925 1926/* force unlink - is called by comedi */ 1927static int usbdux_pwm_cancel(struct comedi_device *dev, 1928 struct comedi_subdevice *s) 1929{ 1930 struct usbduxsub *this_usbduxsub = dev->private; 1931 int res = 0; 1932 1933 /* unlink only if it is really running */ 1934 res = usbdux_pwm_stop(this_usbduxsub, this_usbduxsub->pwm_cmd_running); 1935 1936 dev_dbg(&this_usbduxsub->interface->dev, 1937 "comedi %d: sending pwm off command to the usb device.\n", 1938 dev->minor); 1939 res = send_dux_commands(this_usbduxsub, SENDPWMOFF); 1940 if (res < 0) 1941 return res; 1942 1943 return res; 1944} 1945 1946static void usbduxsub_pwm_irq(struct urb *urb) 1947{ 1948 int ret; 1949 struct usbduxsub *this_usbduxsub; 1950 struct comedi_device *this_comedidev; 1951 struct comedi_subdevice *s; 1952 1953 /* printk(KERN_DEBUG "PWM: IRQ\n"); */ 1954 1955 /* the context variable points to the subdevice */ 1956 this_comedidev = urb->context; 1957 /* the private structure of the subdevice is struct usbduxsub */ 1958 this_usbduxsub = this_comedidev->private; 1959 1960 s = this_comedidev->subdevices + SUBDEV_DA; 1961 1962 switch (urb->status) { 1963 case 0: 1964 /* success */ 1965 break; 1966 1967 case -ECONNRESET: 1968 case -ENOENT: 1969 case -ESHUTDOWN: 1970 case -ECONNABORTED: 1971 /* 1972 * after an unlink command, unplug, ... etc 1973 * no unlink needed here. Already shutting down. 1974 */ 1975 if (this_usbduxsub->pwm_cmd_running) 1976 usbdux_pwm_stop(this_usbduxsub, 0); 1977 1978 return; 1979 1980 default: 1981 /* a real error */ 1982 if (this_usbduxsub->pwm_cmd_running) { 1983 dev_err(&this_usbduxsub->interface->dev, 1984 "comedi_: Non-zero urb status received in " 1985 "pwm intr context: %d\n", urb->status); 1986 usbdux_pwm_stop(this_usbduxsub, 0); 1987 } 1988 return; 1989 } 1990 1991 /* are we actually running? */ 1992 if (!(this_usbduxsub->pwm_cmd_running)) 1993 return; 1994 1995 urb->transfer_buffer_length = this_usbduxsub->sizePwmBuf; 1996 urb->dev = this_usbduxsub->usbdev; 1997 urb->status = 0; 1998 if (this_usbduxsub->pwm_cmd_running) { 1999 ret = usb_submit_urb(urb, GFP_ATOMIC); 2000 if (ret < 0) { 2001 dev_err(&this_usbduxsub->interface->dev, 2002 "comedi_: pwm urb resubm failed in int-cont. " 2003 "ret=%d", ret); 2004 if (ret == EL2NSYNC) 2005 dev_err(&this_usbduxsub->interface->dev, 2006 "buggy USB host controller or bug in " 2007 "IRQ handling!\n"); 2008 2009 /* don't do an unlink here */ 2010 usbdux_pwm_stop(this_usbduxsub, 0); 2011 } 2012 } 2013} 2014 2015static int usbduxsub_submit_PwmURBs(struct usbduxsub *usbduxsub) 2016{ 2017 int errFlag; 2018 2019 if (!usbduxsub) 2020 return -EFAULT; 2021 2022 dev_dbg(&usbduxsub->interface->dev, "comedi_: submitting pwm-urb\n"); 2023 2024 /* in case of a resubmission after an unlink... */ 2025 usb_fill_bulk_urb(usbduxsub->urbPwm, 2026 usbduxsub->usbdev, 2027 usb_sndbulkpipe(usbduxsub->usbdev, PWM_EP), 2028 usbduxsub->urbPwm->transfer_buffer, 2029 usbduxsub->sizePwmBuf, usbduxsub_pwm_irq, 2030 usbduxsub->comedidev); 2031 2032 errFlag = usb_submit_urb(usbduxsub->urbPwm, GFP_ATOMIC); 2033 if (errFlag) { 2034 dev_err(&usbduxsub->interface->dev, 2035 "comedi_: usbduxsigma: pwm: usb_submit_urb error %d\n", 2036 errFlag); 2037 return errFlag; 2038 } 2039 return 0; 2040} 2041 2042static int usbdux_pwm_period(struct comedi_device *dev, 2043 struct comedi_subdevice *s, unsigned int period) 2044{ 2045 struct usbduxsub *this_usbduxsub = dev->private; 2046 int fx2delay = 255; 2047 2048 if (period < MIN_PWM_PERIOD) { 2049 dev_err(&this_usbduxsub->interface->dev, 2050 "comedi%d: illegal period setting for pwm.\n", 2051 dev->minor); 2052 return -EAGAIN; 2053 } else { 2054 fx2delay = period / ((int)(6 * 512 * (1.0 / 0.033))) - 6; 2055 if (fx2delay > 255) { 2056 dev_err(&this_usbduxsub->interface->dev, 2057 "comedi%d: period %d for pwm is too low.\n", 2058 dev->minor, period); 2059 return -EAGAIN; 2060 } 2061 } 2062 this_usbduxsub->pwmDelay = fx2delay; 2063 this_usbduxsub->pwmPeriod = period; 2064 dev_dbg(&this_usbduxsub->interface->dev, "%s: frequ=%d, period=%d\n", 2065 __func__, period, fx2delay); 2066 return 0; 2067} 2068 2069/* is called from insn so there's no need to do all the sanity checks */ 2070static int usbdux_pwm_start(struct comedi_device *dev, 2071 struct comedi_subdevice *s) 2072{ 2073 int ret, i; 2074 struct usbduxsub *this_usbduxsub = dev->private; 2075 2076 dev_dbg(&this_usbduxsub->interface->dev, "comedi%d: %s\n", 2077 dev->minor, __func__); 2078 2079 if (this_usbduxsub->pwm_cmd_running) { 2080 /* already running */ 2081 return 0; 2082 } 2083 2084 this_usbduxsub->dux_commands[1] = ((uint8_t) this_usbduxsub->pwmDelay); 2085 ret = send_dux_commands(this_usbduxsub, SENDPWMON); 2086 if (ret < 0) 2087 return ret; 2088 2089 /* initialise the buffer */ 2090 for (i = 0; i < this_usbduxsub->sizePwmBuf; i++) 2091 ((char *)(this_usbduxsub->urbPwm->transfer_buffer))[i] = 0; 2092 2093 this_usbduxsub->pwm_cmd_running = 1; 2094 ret = usbduxsub_submit_PwmURBs(this_usbduxsub); 2095 if (ret < 0) { 2096 this_usbduxsub->pwm_cmd_running = 0; 2097 return ret; 2098 } 2099 return 0; 2100} 2101 2102/* generates the bit pattern for PWM with the optional sign bit */ 2103static int usbdux_pwm_pattern(struct comedi_device *dev, 2104 struct comedi_subdevice *s, int channel, 2105 unsigned int value, unsigned int sign) 2106{ 2107 struct usbduxsub *this_usbduxsub = dev->private; 2108 int i, szbuf; 2109 char *pBuf; 2110 char pwm_mask; 2111 char sgn_mask; 2112 char c; 2113 2114 if (!this_usbduxsub) 2115 return -EFAULT; 2116 2117 /* this is the DIO bit which carries the PWM data */ 2118 pwm_mask = (1 << channel); 2119 /* this is the DIO bit which carries the optional direction bit */ 2120 sgn_mask = (16 << channel); 2121 /* this is the buffer which will be filled with the with bit */ 2122 /* pattern for one period */ 2123 szbuf = this_usbduxsub->sizePwmBuf; 2124 pBuf = (char *)(this_usbduxsub->urbPwm->transfer_buffer); 2125 for (i = 0; i < szbuf; i++) { 2126 c = *pBuf; 2127 /* reset bits */ 2128 c = c & (~pwm_mask); 2129 /* set the bit as long as the index is lower than the value */ 2130 if (i < value) 2131 c = c | pwm_mask; 2132 /* set the optional sign bit for a relay */ 2133 if (!sign) { 2134 /* positive value */ 2135 c = c & (~sgn_mask); 2136 } else { 2137 /* negative value */ 2138 c = c | sgn_mask; 2139 } 2140 *(pBuf++) = c; 2141 } 2142 return 1; 2143} 2144 2145static int usbdux_pwm_write(struct comedi_device *dev, 2146 struct comedi_subdevice *s, 2147 struct comedi_insn *insn, unsigned int *data) 2148{ 2149 struct usbduxsub *this_usbduxsub = dev->private; 2150 2151 if (!this_usbduxsub) 2152 return -EFAULT; 2153 2154 if ((insn->n) != 1) { 2155 /* 2156 * doesn't make sense to have more than one value here because 2157 * it would just overwrite the PWM buffer a couple of times 2158 */ 2159 return -EINVAL; 2160 } 2161 2162 /* 2163 * the sign is set via a special INSN only, this gives us 8 bits for 2164 * normal operation 2165 * relay sign 0 by default 2166 */ 2167 return usbdux_pwm_pattern(dev, s, CR_CHAN(insn->chanspec), data[0], 0); 2168} 2169 2170static int usbdux_pwm_read(struct comedi_device *x1, 2171 struct comedi_subdevice *x2, struct comedi_insn *x3, 2172 unsigned int *x4) 2173{ 2174 /* not needed */ 2175 return -EINVAL; 2176}; 2177 2178/* switches on/off PWM */ 2179static int usbdux_pwm_config(struct comedi_device *dev, 2180 struct comedi_subdevice *s, 2181 struct comedi_insn *insn, unsigned int *data) 2182{ 2183 struct usbduxsub *this_usbduxsub = dev->private; 2184 switch (data[0]) { 2185 case INSN_CONFIG_ARM: 2186 /* switch it on */ 2187 dev_dbg(&this_usbduxsub->interface->dev, 2188 "comedi%d: %s: pwm on\n", dev->minor, __func__); 2189 /* 2190 * if not zero the PWM is limited to a certain time which is 2191 * not supported here 2192 */ 2193 if (data[1] != 0) 2194 return -EINVAL; 2195 return usbdux_pwm_start(dev, s); 2196 case INSN_CONFIG_DISARM: 2197 dev_dbg(&this_usbduxsub->interface->dev, 2198 "comedi%d: %s: pwm off\n", dev->minor, __func__); 2199 return usbdux_pwm_cancel(dev, s); 2200 case INSN_CONFIG_GET_PWM_STATUS: 2201 /* 2202 * to check if the USB transmission has failed or in case PWM 2203 * was limited to n cycles to check if it has terminated 2204 */ 2205 data[1] = this_usbduxsub->pwm_cmd_running; 2206 return 0; 2207 case INSN_CONFIG_PWM_SET_PERIOD: 2208 dev_dbg(&this_usbduxsub->interface->dev, 2209 "comedi%d: %s: setting period\n", dev->minor, 2210 __func__); 2211 return usbdux_pwm_period(dev, s, data[1]); 2212 case INSN_CONFIG_PWM_GET_PERIOD: 2213 data[1] = this_usbduxsub->pwmPeriod; 2214 return 0; 2215 case INSN_CONFIG_PWM_SET_H_BRIDGE: 2216 /* value in the first byte and the sign in the second for a 2217 relay */ 2218 return usbdux_pwm_pattern(dev, s, 2219 /* the channel number */ 2220 CR_CHAN(insn->chanspec), 2221 /* actual PWM data */ 2222 data[1], 2223 /* just a sign */ 2224 (data[2] != 0)); 2225 case INSN_CONFIG_PWM_GET_H_BRIDGE: 2226 /* values are not kept in this driver, nothing to return */ 2227 return -EINVAL; 2228 } 2229 return -EINVAL; 2230} 2231 2232/* end of PWM */ 2233/*****************************************************************/ 2234 2235static void tidy_up(struct usbduxsub *usbduxsub_tmp) 2236{ 2237 int i; 2238 2239 if (!usbduxsub_tmp) 2240 return; 2241 dev_dbg(&usbduxsub_tmp->interface->dev, "comedi_: tiding up\n"); 2242 2243 /* shows the usb subsystem that the driver is down */ 2244 if (usbduxsub_tmp->interface) 2245 usb_set_intfdata(usbduxsub_tmp->interface, NULL); 2246 2247 usbduxsub_tmp->probed = 0; 2248 2249 if (usbduxsub_tmp->urbIn) { 2250 if (usbduxsub_tmp->ai_cmd_running) { 2251 usbduxsub_tmp->ai_cmd_running = 0; 2252 usbduxsub_unlink_InURBs(usbduxsub_tmp); 2253 } 2254 for (i = 0; i < usbduxsub_tmp->numOfInBuffers; i++) { 2255 kfree(usbduxsub_tmp->urbIn[i]->transfer_buffer); 2256 usbduxsub_tmp->urbIn[i]->transfer_buffer = NULL; 2257 usb_kill_urb(usbduxsub_tmp->urbIn[i]); 2258 usb_free_urb(usbduxsub_tmp->urbIn[i]); 2259 usbduxsub_tmp->urbIn[i] = NULL; 2260 } 2261 kfree(usbduxsub_tmp->urbIn); 2262 usbduxsub_tmp->urbIn = NULL; 2263 } 2264 if (usbduxsub_tmp->urbOut) { 2265 if (usbduxsub_tmp->ao_cmd_running) { 2266 usbduxsub_tmp->ao_cmd_running = 0; 2267 usbduxsub_unlink_OutURBs(usbduxsub_tmp); 2268 } 2269 for (i = 0; i < usbduxsub_tmp->numOfOutBuffers; i++) { 2270 if (usbduxsub_tmp->urbOut[i]->transfer_buffer) { 2271 kfree(usbduxsub_tmp-> 2272 urbOut[i]->transfer_buffer); 2273 usbduxsub_tmp->urbOut[i]->transfer_buffer = 2274 NULL; 2275 } 2276 if (usbduxsub_tmp->urbOut[i]) { 2277 usb_kill_urb(usbduxsub_tmp->urbOut[i]); 2278 usb_free_urb(usbduxsub_tmp->urbOut[i]); 2279 usbduxsub_tmp->urbOut[i] = NULL; 2280 } 2281 } 2282 kfree(usbduxsub_tmp->urbOut); 2283 usbduxsub_tmp->urbOut = NULL; 2284 } 2285 if (usbduxsub_tmp->urbPwm) { 2286 if (usbduxsub_tmp->pwm_cmd_running) { 2287 usbduxsub_tmp->pwm_cmd_running = 0; 2288 usbduxsub_unlink_PwmURBs(usbduxsub_tmp); 2289 } 2290 kfree(usbduxsub_tmp->urbPwm->transfer_buffer); 2291 usbduxsub_tmp->urbPwm->transfer_buffer = NULL; 2292 usb_kill_urb(usbduxsub_tmp->urbPwm); 2293 usb_free_urb(usbduxsub_tmp->urbPwm); 2294 usbduxsub_tmp->urbPwm = NULL; 2295 } 2296 kfree(usbduxsub_tmp->inBuffer); 2297 usbduxsub_tmp->inBuffer = NULL; 2298 kfree(usbduxsub_tmp->insnBuffer); 2299 usbduxsub_tmp->insnBuffer = NULL; 2300 kfree(usbduxsub_tmp->outBuffer); 2301 usbduxsub_tmp->outBuffer = NULL; 2302 kfree(usbduxsub_tmp->dac_commands); 2303 usbduxsub_tmp->dac_commands = NULL; 2304 kfree(usbduxsub_tmp->dux_commands); 2305 usbduxsub_tmp->dux_commands = NULL; 2306 usbduxsub_tmp->ai_cmd_running = 0; 2307 usbduxsub_tmp->ao_cmd_running = 0; 2308 usbduxsub_tmp->pwm_cmd_running = 0; 2309} 2310 2311static void usbdux_firmware_request_complete_handler(const struct firmware *fw, 2312 void *context) 2313{ 2314 struct usbduxsub *usbduxsub_tmp = context; 2315 struct usb_device *usbdev = usbduxsub_tmp->usbdev; 2316 int ret; 2317 2318 if (fw == NULL) { 2319 dev_err(&usbdev->dev, 2320 "Firmware complete handler without firmware!\n"); 2321 return; 2322 } 2323 2324 /* 2325 * we need to upload the firmware here because fw will be 2326 * freed once we've left this function 2327 */ 2328 ret = firmwareUpload(usbduxsub_tmp, fw->data, fw->size); 2329 2330 if (ret) { 2331 dev_err(&usbdev->dev, 2332 "Could not upload firmware (err=%d)\n", ret); 2333 goto out; 2334 } 2335 comedi_usb_auto_config(usbdev, BOARDNAME); 2336out: 2337 release_firmware(fw); 2338} 2339 2340/* allocate memory for the urbs and initialise them */ 2341static int usbduxsigma_probe(struct usb_interface *uinterf, 2342 const struct usb_device_id *id) 2343{ 2344 struct usb_device *udev = interface_to_usbdev(uinterf); 2345 struct device *dev = &uinterf->dev; 2346 int i; 2347 int index; 2348 int ret; 2349 2350 dev_dbg(dev, "comedi_: usbdux_: " 2351 "finding a free structure for the usb-device\n"); 2352 2353 down(&start_stop_sem); 2354 /* look for a free place in the usbdux array */ 2355 index = -1; 2356 for (i = 0; i < NUMUSBDUX; i++) { 2357 if (!(usbduxsub[i].probed)) { 2358 index = i; 2359 break; 2360 } 2361 } 2362 2363 /* no more space */ 2364 if (index == -1) { 2365 dev_err(dev, "Too many usbduxsigma-devices connected.\n"); 2366 up(&start_stop_sem); 2367 return -EMFILE; 2368 } 2369 dev_dbg(dev, "comedi_: usbdux: " 2370 "usbduxsub[%d] is ready to connect to comedi.\n", index); 2371 2372 sema_init(&(usbduxsub[index].sem), 1); 2373 /* save a pointer to the usb device */ 2374 usbduxsub[index].usbdev = udev; 2375 2376 /* save the interface itself */ 2377 usbduxsub[index].interface = uinterf; 2378 /* get the interface number from the interface */ 2379 usbduxsub[index].ifnum = uinterf->altsetting->desc.bInterfaceNumber; 2380 /* hand the private data over to the usb subsystem */ 2381 /* will be needed for disconnect */ 2382 usb_set_intfdata(uinterf, &(usbduxsub[index])); 2383 2384 dev_dbg(dev, "comedi_: usbdux: ifnum=%d\n", usbduxsub[index].ifnum); 2385 2386 /* test if it is high speed (USB 2.0) */ 2387 usbduxsub[index].high_speed = 2388 (usbduxsub[index].usbdev->speed == USB_SPEED_HIGH); 2389 2390 /* create space for the commands of the DA converter */ 2391 usbduxsub[index].dac_commands = kzalloc(NUMOUTCHANNELS, GFP_KERNEL); 2392 if (!usbduxsub[index].dac_commands) { 2393 dev_err(dev, "comedi_: usbduxsigma: " 2394 "error alloc space for dac commands\n"); 2395 tidy_up(&(usbduxsub[index])); 2396 up(&start_stop_sem); 2397 return -ENOMEM; 2398 } 2399 /* create space for the commands going to the usb device */ 2400 usbduxsub[index].dux_commands = kzalloc(SIZEOFDUXBUFFER, GFP_KERNEL); 2401 if (!usbduxsub[index].dux_commands) { 2402 dev_err(dev, "comedi_: usbduxsigma: " 2403 "error alloc space for dux commands\n"); 2404 tidy_up(&(usbduxsub[index])); 2405 up(&start_stop_sem); 2406 return -ENOMEM; 2407 } 2408 /* create space for the in buffer and set it to zero */ 2409 usbduxsub[index].inBuffer = kzalloc(SIZEINBUF, GFP_KERNEL); 2410 if (!(usbduxsub[index].inBuffer)) { 2411 dev_err(dev, "comedi_: usbduxsigma: " 2412 "could not alloc space for inBuffer\n"); 2413 tidy_up(&(usbduxsub[index])); 2414 up(&start_stop_sem); 2415 return -ENOMEM; 2416 } 2417 /* create space of the instruction buffer */ 2418 usbduxsub[index].insnBuffer = kzalloc(SIZEINSNBUF, GFP_KERNEL); 2419 if (!(usbduxsub[index].insnBuffer)) { 2420 dev_err(dev, "comedi_: usbduxsigma: " 2421 "could not alloc space for insnBuffer\n"); 2422 tidy_up(&(usbduxsub[index])); 2423 up(&start_stop_sem); 2424 return -ENOMEM; 2425 } 2426 /* create space for the outbuffer */ 2427 usbduxsub[index].outBuffer = kzalloc(SIZEOUTBUF, GFP_KERNEL); 2428 if (!(usbduxsub[index].outBuffer)) { 2429 dev_err(dev, "comedi_: usbduxsigma: " 2430 "could not alloc space for outBuffer\n"); 2431 tidy_up(&(usbduxsub[index])); 2432 up(&start_stop_sem); 2433 return -ENOMEM; 2434 } 2435 /* setting to alternate setting 3: enabling iso ep and bulk ep. */ 2436 i = usb_set_interface(usbduxsub[index].usbdev, 2437 usbduxsub[index].ifnum, 3); 2438 if (i < 0) { 2439 dev_err(dev, "comedi_: usbduxsigma%d: " 2440 "could not set alternate setting 3 in high speed.\n", 2441 index); 2442 tidy_up(&(usbduxsub[index])); 2443 up(&start_stop_sem); 2444 return -ENODEV; 2445 } 2446 if (usbduxsub[index].high_speed) 2447 usbduxsub[index].numOfInBuffers = NUMOFINBUFFERSHIGH; 2448 else 2449 usbduxsub[index].numOfInBuffers = NUMOFINBUFFERSFULL; 2450 2451 usbduxsub[index].urbIn = 2452 kzalloc(sizeof(struct urb *) * usbduxsub[index].numOfInBuffers, 2453 GFP_KERNEL); 2454 if (!(usbduxsub[index].urbIn)) { 2455 dev_err(dev, "comedi_: usbduxsigma: " 2456 "Could not alloc. urbIn array\n"); 2457 tidy_up(&(usbduxsub[index])); 2458 up(&start_stop_sem); 2459 return -ENOMEM; 2460 } 2461 for (i = 0; i < usbduxsub[index].numOfInBuffers; i++) { 2462 /* one frame: 1ms */ 2463 usbduxsub[index].urbIn[i] = usb_alloc_urb(1, GFP_KERNEL); 2464 if (usbduxsub[index].urbIn[i] == NULL) { 2465 dev_err(dev, "comedi_: usbduxsigma%d: " 2466 "Could not alloc. urb(%d)\n", index, i); 2467 tidy_up(&(usbduxsub[index])); 2468 up(&start_stop_sem); 2469 return -ENOMEM; 2470 } 2471 usbduxsub[index].urbIn[i]->dev = usbduxsub[index].usbdev; 2472 /* will be filled later with a pointer to the comedi-device */ 2473 /* and ONLY then the urb should be submitted */ 2474 usbduxsub[index].urbIn[i]->context = NULL; 2475 usbduxsub[index].urbIn[i]->pipe = 2476 usb_rcvisocpipe(usbduxsub[index].usbdev, ISOINEP); 2477 usbduxsub[index].urbIn[i]->transfer_flags = URB_ISO_ASAP; 2478 usbduxsub[index].urbIn[i]->transfer_buffer = 2479 kzalloc(SIZEINBUF, GFP_KERNEL); 2480 if (!(usbduxsub[index].urbIn[i]->transfer_buffer)) { 2481 dev_err(dev, "comedi_: usbduxsigma%d: " 2482 "could not alloc. transb.\n", index); 2483 tidy_up(&(usbduxsub[index])); 2484 up(&start_stop_sem); 2485 return -ENOMEM; 2486 } 2487 usbduxsub[index].urbIn[i]->complete = usbduxsub_ai_IsocIrq; 2488 usbduxsub[index].urbIn[i]->number_of_packets = 1; 2489 usbduxsub[index].urbIn[i]->transfer_buffer_length = SIZEINBUF; 2490 usbduxsub[index].urbIn[i]->iso_frame_desc[0].offset = 0; 2491 usbduxsub[index].urbIn[i]->iso_frame_desc[0].length = 2492 SIZEINBUF; 2493 } 2494 2495 /* out */ 2496 if (usbduxsub[index].high_speed) 2497 usbduxsub[index].numOfOutBuffers = NUMOFOUTBUFFERSHIGH; 2498 else 2499 usbduxsub[index].numOfOutBuffers = NUMOFOUTBUFFERSFULL; 2500 2501 usbduxsub[index].urbOut = 2502 kzalloc(sizeof(struct urb *) * usbduxsub[index].numOfOutBuffers, 2503 GFP_KERNEL); 2504 if (!(usbduxsub[index].urbOut)) { 2505 dev_err(dev, "comedi_: usbduxsigma: " 2506 "Could not alloc. urbOut array\n"); 2507 tidy_up(&(usbduxsub[index])); 2508 up(&start_stop_sem); 2509 return -ENOMEM; 2510 } 2511 for (i = 0; i < usbduxsub[index].numOfOutBuffers; i++) { 2512 /* one frame: 1ms */ 2513 usbduxsub[index].urbOut[i] = usb_alloc_urb(1, GFP_KERNEL); 2514 if (usbduxsub[index].urbOut[i] == NULL) { 2515 dev_err(dev, "comedi_: usbduxsigma%d: " 2516 "Could not alloc. urb(%d)\n", index, i); 2517 tidy_up(&(usbduxsub[index])); 2518 up(&start_stop_sem); 2519 return -ENOMEM; 2520 } 2521 usbduxsub[index].urbOut[i]->dev = usbduxsub[index].usbdev; 2522 /* will be filled later with a pointer to the comedi-device */ 2523 /* and ONLY then the urb should be submitted */ 2524 usbduxsub[index].urbOut[i]->context = NULL; 2525 usbduxsub[index].urbOut[i]->pipe = 2526 usb_sndisocpipe(usbduxsub[index].usbdev, ISOOUTEP); 2527 usbduxsub[index].urbOut[i]->transfer_flags = URB_ISO_ASAP; 2528 usbduxsub[index].urbOut[i]->transfer_buffer = 2529 kzalloc(SIZEOUTBUF, GFP_KERNEL); 2530 if (!(usbduxsub[index].urbOut[i]->transfer_buffer)) { 2531 dev_err(dev, "comedi_: usbduxsigma%d: " 2532 "could not alloc. transb.\n", index); 2533 tidy_up(&(usbduxsub[index])); 2534 up(&start_stop_sem); 2535 return -ENOMEM; 2536 } 2537 usbduxsub[index].urbOut[i]->complete = usbduxsub_ao_IsocIrq; 2538 usbduxsub[index].urbOut[i]->number_of_packets = 1; 2539 usbduxsub[index].urbOut[i]->transfer_buffer_length = 2540 SIZEOUTBUF; 2541 usbduxsub[index].urbOut[i]->iso_frame_desc[0].offset = 0; 2542 usbduxsub[index].urbOut[i]->iso_frame_desc[0].length = 2543 SIZEOUTBUF; 2544 if (usbduxsub[index].high_speed) { 2545 /* uframes */ 2546 usbduxsub[index].urbOut[i]->interval = 8; 2547 } else { 2548 /* frames */ 2549 usbduxsub[index].urbOut[i]->interval = 1; 2550 } 2551 } 2552 2553 /* pwm */ 2554 if (usbduxsub[index].high_speed) { 2555 /* max bulk ep size in high speed */ 2556 usbduxsub[index].sizePwmBuf = 512; 2557 usbduxsub[index].urbPwm = usb_alloc_urb(0, GFP_KERNEL); 2558 if (usbduxsub[index].urbPwm == NULL) { 2559 dev_err(dev, "comedi_: usbduxsigma%d: " 2560 "Could not alloc. pwm urb\n", index); 2561 tidy_up(&(usbduxsub[index])); 2562 up(&start_stop_sem); 2563 return -ENOMEM; 2564 } 2565 usbduxsub[index].urbPwm->transfer_buffer = 2566 kzalloc(usbduxsub[index].sizePwmBuf, GFP_KERNEL); 2567 if (!(usbduxsub[index].urbPwm->transfer_buffer)) { 2568 dev_err(dev, "comedi_: usbduxsigma%d: " 2569 "could not alloc. transb. for pwm\n", index); 2570 tidy_up(&(usbduxsub[index])); 2571 up(&start_stop_sem); 2572 return -ENOMEM; 2573 } 2574 } else { 2575 usbduxsub[index].urbPwm = NULL; 2576 usbduxsub[index].sizePwmBuf = 0; 2577 } 2578 2579 usbduxsub[index].ai_cmd_running = 0; 2580 usbduxsub[index].ao_cmd_running = 0; 2581 usbduxsub[index].pwm_cmd_running = 0; 2582 2583 /* we've reached the bottom of the function */ 2584 usbduxsub[index].probed = 1; 2585 up(&start_stop_sem); 2586 2587 ret = request_firmware_nowait(THIS_MODULE, 2588 FW_ACTION_HOTPLUG, 2589 "usbduxsigma_firmware.bin", 2590 &udev->dev, 2591 GFP_KERNEL, 2592 usbduxsub + index, 2593 usbdux_firmware_request_complete_handler 2594 ); 2595 2596 if (ret) { 2597 dev_err(dev, "Could not load firmware (err=%d)\n", ret); 2598 return ret; 2599 } 2600 2601 dev_info(dev, "comedi_: successfully initialised.\n"); 2602 /* success */ 2603 return 0; 2604} 2605 2606static void usbduxsigma_disconnect(struct usb_interface *intf) 2607{ 2608 struct usbduxsub *usbduxsub_tmp = usb_get_intfdata(intf); 2609 struct usb_device *udev = interface_to_usbdev(intf); 2610 2611 if (!usbduxsub_tmp) { 2612 dev_err(&intf->dev, 2613 "comedi_: disconnect called with null pointer.\n"); 2614 return; 2615 } 2616 if (usbduxsub_tmp->usbdev != udev) { 2617 dev_err(&intf->dev, "comedi_: BUG! wrong ptr!\n"); 2618 return; 2619 } 2620 if (usbduxsub_tmp->ai_cmd_running) 2621 /* we are still running a command */ 2622 usbdux_ai_stop(usbduxsub_tmp, 1); 2623 if (usbduxsub_tmp->ao_cmd_running) 2624 /* we are still running a command */ 2625 usbdux_ao_stop(usbduxsub_tmp, 1); 2626 comedi_usb_auto_unconfig(udev); 2627 down(&start_stop_sem); 2628 down(&usbduxsub_tmp->sem); 2629 tidy_up(usbduxsub_tmp); 2630 up(&usbduxsub_tmp->sem); 2631 up(&start_stop_sem); 2632 dev_info(&intf->dev, "comedi_: disconnected from the usb\n"); 2633} 2634 2635/* is called when comedi-config is called */ 2636static int usbduxsigma_attach(struct comedi_device *dev, 2637 struct comedi_devconfig *it) 2638{ 2639 int ret; 2640 int index; 2641 int i; 2642 struct usbduxsub *udev; 2643 2644 int offset; 2645 2646 struct comedi_subdevice *s = NULL; 2647 dev->private = NULL; 2648 2649 down(&start_stop_sem); 2650 /* find a valid device which has been detected by the probe function of 2651 * the usb */ 2652 index = -1; 2653 for (i = 0; i < NUMUSBDUX; i++) { 2654 if ((usbduxsub[i].probed) && (!usbduxsub[i].attached)) { 2655 index = i; 2656 break; 2657 } 2658 } 2659 2660 if (index < 0) { 2661 printk(KERN_ERR "comedi%d: usbduxsigma: error: attach failed," 2662 "dev not connected to the usb bus.\n", dev->minor); 2663 up(&start_stop_sem); 2664 return -ENODEV; 2665 } 2666 2667 udev = &usbduxsub[index]; 2668 down(&udev->sem); 2669 /* pointer back to the corresponding comedi device */ 2670 udev->comedidev = dev; 2671 2672 /* trying to upload the firmware into the FX2 */ 2673 if (comedi_aux_data(it->options, 0) && 2674 it->options[COMEDI_DEVCONF_AUX_DATA_LENGTH]) { 2675 firmwareUpload(udev, comedi_aux_data(it->options, 0), 2676 it->options[COMEDI_DEVCONF_AUX_DATA_LENGTH]); 2677 } 2678 2679 dev->board_name = BOARDNAME; 2680 2681 /* set number of subdevices */ 2682 if (udev->high_speed) { 2683 /* with pwm */ 2684 dev->n_subdevices = 4; 2685 } else { 2686 /* without pwm */ 2687 dev->n_subdevices = 3; 2688 } 2689 2690 /* allocate space for the subdevices */ 2691 ret = alloc_subdevices(dev, dev->n_subdevices); 2692 if (ret < 0) { 2693 dev_err(&udev->interface->dev, 2694 "comedi%d: no space for subdev\n", dev->minor); 2695 up(&udev->sem); 2696 up(&start_stop_sem); 2697 return ret; 2698 } 2699 2700 /* private structure is also simply the usb-structure */ 2701 dev->private = udev; 2702 2703 /* the first subdevice is the A/D converter */ 2704 s = dev->subdevices + SUBDEV_AD; 2705 /* the URBs get the comedi subdevice */ 2706 /* which is responsible for reading */ 2707 /* this is the subdevice which reads data */ 2708 dev->read_subdev = s; 2709 /* the subdevice receives as private structure the */ 2710 /* usb-structure */ 2711 s->private = NULL; 2712 /* analog input */ 2713 s->type = COMEDI_SUBD_AI; 2714 /* readable and ref is to ground, 32 bit wide data! */ 2715 s->subdev_flags = SDF_READABLE | SDF_GROUND | 2716 SDF_CMD_READ | SDF_LSAMPL; 2717 /* 16 A/D channels */ 2718 s->n_chan = NUMCHANNELS; 2719 /* length of the channellist */ 2720 s->len_chanlist = NUMCHANNELS; 2721 /* callback functions */ 2722 s->insn_read = usbdux_ai_insn_read; 2723 s->do_cmdtest = usbdux_ai_cmdtest; 2724 s->do_cmd = usbdux_ai_cmd; 2725 s->cancel = usbdux_ai_cancel; 2726 /* max value from the A/D converter (24bit) */ 2727 s->maxdata = 0x00FFFFFF; 2728 /* range table to convert to physical units */ 2729 s->range_table = (&range_usbdux_ai_range); 2730 2731 /* analog out */ 2732 s = dev->subdevices + SUBDEV_DA; 2733 /* analog out */ 2734 s->type = COMEDI_SUBD_AO; 2735 /* backward pointer */ 2736 dev->write_subdev = s; 2737 /* the subdevice receives as private structure the */ 2738 /* usb-structure */ 2739 s->private = NULL; 2740 /* are writable */ 2741 s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_CMD_WRITE; 2742 /* 4 channels */ 2743 s->n_chan = 4; 2744 /* length of the channellist */ 2745 s->len_chanlist = 4; 2746 /* 8 bit resolution */ 2747 s->maxdata = 0x00ff; 2748 /* unipolar range */ 2749 s->range_table = (&range_usbdux_ao_range); 2750 /* callback */ 2751 s->do_cmdtest = usbdux_ao_cmdtest; 2752 s->do_cmd = usbdux_ao_cmd; 2753 s->cancel = usbdux_ao_cancel; 2754 s->insn_read = usbdux_ao_insn_read; 2755 s->insn_write = usbdux_ao_insn_write; 2756 2757 /* digital I/O */ 2758 s = dev->subdevices + SUBDEV_DIO; 2759 s->type = COMEDI_SUBD_DIO; 2760 s->subdev_flags = SDF_READABLE | SDF_WRITABLE; 2761 /* 8 external and 16 internal channels */ 2762 s->n_chan = 24; 2763 s->maxdata = 1; 2764 s->range_table = (&range_digital); 2765 s->insn_bits = usbdux_dio_insn_bits; 2766 s->insn_config = usbdux_dio_insn_config; 2767 /* we don't use it */ 2768 s->private = NULL; 2769 2770 if (udev->high_speed) { 2771 /* timer / pwm */ 2772 s = dev->subdevices + SUBDEV_PWM; 2773 s->type = COMEDI_SUBD_PWM; 2774 s->subdev_flags = SDF_WRITABLE | SDF_PWM_HBRIDGE; 2775 s->n_chan = 8; 2776 /* this defines the max duty cycle resolution */ 2777 s->maxdata = udev->sizePwmBuf; 2778 s->insn_write = usbdux_pwm_write; 2779 s->insn_read = usbdux_pwm_read; 2780 s->insn_config = usbdux_pwm_config; 2781 usbdux_pwm_period(dev, s, PWM_DEFAULT_PERIOD); 2782 } 2783 /* finally decide that it's attached */ 2784 udev->attached = 1; 2785 2786 up(&udev->sem); 2787 2788 up(&start_stop_sem); 2789 2790 offset = usbdux_getstatusinfo(dev, 0); 2791 if (offset < 0) 2792 dev_err(&udev->interface->dev, 2793 "Communication to USBDUXSIGMA failed!" 2794 "Check firmware and cabling."); 2795 2796 dev_info(&udev->interface->dev, 2797 "comedi%d: attached, ADC_zero = %x", dev->minor, offset); 2798 2799 return 0; 2800} 2801 2802static int usbduxsigma_detach(struct comedi_device *dev) 2803{ 2804 struct usbduxsub *usbduxsub_tmp; 2805 2806 if (!dev) { 2807 printk(KERN_ERR 2808 "comedi? usbduxsigma detach: dev=NULL\n"); 2809 return -EFAULT; 2810 } 2811 2812 usbduxsub_tmp = dev->private; 2813 if (!usbduxsub_tmp) { 2814 printk(KERN_ERR 2815 "comedi?: usbduxsigma detach: private=NULL\n"); 2816 return -EFAULT; 2817 } 2818 2819 dev_dbg(&usbduxsub_tmp->interface->dev, 2820 "comedi%d: detach usb device\n", 2821 dev->minor); 2822 2823 down(&usbduxsub_tmp->sem); 2824 /* Don't allow detach to free the private structure */ 2825 /* It's one entry of of usbduxsub[] */ 2826 dev->private = NULL; 2827 usbduxsub_tmp->attached = 0; 2828 usbduxsub_tmp->comedidev = NULL; 2829 dev_info(&usbduxsub_tmp->interface->dev, 2830 "comedi%d: successfully detached.\n", dev->minor); 2831 up(&usbduxsub_tmp->sem); 2832 return 0; 2833} 2834 2835/* main driver struct */ 2836static struct comedi_driver driver_usbduxsigma = { 2837 .driver_name = "usbduxsigma", 2838 .module = THIS_MODULE, 2839 .attach = usbduxsigma_attach, 2840 .detach = usbduxsigma_detach, 2841}; 2842 2843/* Table with the USB-devices */ 2844static const struct usb_device_id usbduxsigma_table[] = { 2845 {USB_DEVICE(0x13d8, 0x0020)}, 2846 {USB_DEVICE(0x13d8, 0x0021)}, 2847 {USB_DEVICE(0x13d8, 0x0022)}, 2848 {} /* Terminating entry */ 2849}; 2850 2851MODULE_DEVICE_TABLE(usb, usbduxsigma_table); 2852 2853/* The usbduxsub-driver */ 2854static struct usb_driver usbduxsigma_driver = { 2855 .name = BOARDNAME, 2856 .probe = usbduxsigma_probe, 2857 .disconnect = usbduxsigma_disconnect, 2858 .id_table = usbduxsigma_table, 2859}; 2860 2861/* Can't use the nice macro as I have also to initialise the USB */ 2862/* subsystem: */ 2863/* registering the usb-system _and_ the comedi-driver */ 2864static int __init init_usbduxsigma(void) 2865{ 2866 printk(KERN_INFO KBUILD_MODNAME ": " 2867 DRIVER_VERSION ":" DRIVER_DESC "\n"); 2868 usb_register(&usbduxsigma_driver); 2869 comedi_driver_register(&driver_usbduxsigma); 2870 return 0; 2871} 2872 2873/* deregistering the comedi driver and the usb-subsystem */ 2874static void __exit exit_usbduxsigma(void) 2875{ 2876 comedi_driver_unregister(&driver_usbduxsigma); 2877 usb_deregister(&usbduxsigma_driver); 2878} 2879 2880module_init(init_usbduxsigma); 2881module_exit(exit_usbduxsigma); 2882 2883MODULE_AUTHOR(DRIVER_AUTHOR); 2884MODULE_DESCRIPTION(DRIVER_DESC); 2885MODULE_LICENSE("GPL"); 2886