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