Lines Matching +full:scan +full:- +full:interval +full:- +full:ms
1 // SPDX-License-Identifier: GPL-2.0+
4 * Copyright (C) 2003-2014 Bernd Porr, mail@berndporr.me.uk
10 * Devices: [ITL] USB-DUX (usbdux)
26 * wrote the driver for AT-MIO-16d. I used some parts of this
46 * | kernel | registration | usbdux-usb | usbdux-comedi | comedi |
66 * Thanks to Jan-Matthias Braun and Ian to spot the bug and fix it.
97 /* timeout for the USB-transfer in ms */
110 * Size of the input-buffer IN BYTES
122 * Size of the output-buffer in bytes
134 /* Number of in-URBs which receive the data: min=2 */
137 /* Number of out-URBs which send the data: min=2 */
140 /* Number of in-URBs which receive the data: min=5 */
144 /* Number of out-URBs which send the data: min=5 */
168 /* actual number of in-buffers */
170 /* actual number of out-buffers */
172 /* ISO-transfer handling: buffers */
175 /* pwm-transfer handling */
183 /* input buffer for the ISO-transfer */
199 /* interval in frames/uframes */
216 struct usbdux_private *devpriv = dev->private; in usbdux_ai_stop()
218 if (do_unlink && devpriv->ai_urbs) in usbdux_ai_stop()
219 usbdux_unlink_urbs(devpriv->ai_urbs, devpriv->n_ai_urbs); in usbdux_ai_stop()
221 devpriv->ai_cmd_running = 0; in usbdux_ai_stop()
227 struct usbdux_private *devpriv = dev->private; in usbdux_ai_cancel()
230 mutex_lock(&devpriv->mut); in usbdux_ai_cancel()
232 usbdux_ai_stop(dev, devpriv->ai_cmd_running); in usbdux_ai_cancel()
233 mutex_unlock(&devpriv->mut); in usbdux_ai_cancel()
242 struct usbdux_private *devpriv = dev->private; in usbduxsub_ai_handle_urb()
243 struct comedi_async *async = s->async; in usbduxsub_ai_handle_urb()
244 struct comedi_cmd *cmd = &async->cmd; in usbduxsub_ai_handle_urb()
248 devpriv->ai_counter--; in usbduxsub_ai_handle_urb()
249 if (devpriv->ai_counter == 0) { in usbduxsub_ai_handle_urb()
250 devpriv->ai_counter = devpriv->ai_timer; in usbduxsub_ai_handle_urb()
253 for (i = 0; i < cmd->chanlist_len; i++) { in usbduxsub_ai_handle_urb()
254 unsigned int range = CR_RANGE(cmd->chanlist[i]); in usbduxsub_ai_handle_urb()
255 u16 val = le16_to_cpu(devpriv->in_buf[i]); in usbduxsub_ai_handle_urb()
257 /* bipolar data is two's-complement */ in usbduxsub_ai_handle_urb()
266 if (cmd->stop_src == TRIG_COUNT && in usbduxsub_ai_handle_urb()
267 async->scans_done >= cmd->stop_arg) in usbduxsub_ai_handle_urb()
268 async->events |= COMEDI_CB_EOA; in usbduxsub_ai_handle_urb()
272 if (!(async->events & COMEDI_CB_CANCEL_MASK)) { in usbduxsub_ai_handle_urb()
273 urb->dev = comedi_to_usb_dev(dev); in usbduxsub_ai_handle_urb()
276 dev_err(dev->class_dev, in usbduxsub_ai_handle_urb()
277 "urb resubmit failed in int-context! err=%d\n", in usbduxsub_ai_handle_urb()
279 if (ret == -EL2NSYNC) in usbduxsub_ai_handle_urb()
280 dev_err(dev->class_dev, in usbduxsub_ai_handle_urb()
282 async->events |= COMEDI_CB_ERROR; in usbduxsub_ai_handle_urb()
289 struct comedi_device *dev = urb->context; in usbduxsub_ai_isoc_irq()
290 struct comedi_subdevice *s = dev->read_subdev; in usbduxsub_ai_isoc_irq()
291 struct comedi_async *async = s->async; in usbduxsub_ai_isoc_irq()
292 struct usbdux_private *devpriv = dev->private; in usbduxsub_ai_isoc_irq()
295 if (!devpriv->ai_cmd_running) in usbduxsub_ai_isoc_irq()
298 switch (urb->status) { in usbduxsub_ai_isoc_irq()
301 memcpy(devpriv->in_buf, urb->transfer_buffer, SIZEINBUF); in usbduxsub_ai_isoc_irq()
305 case -EILSEQ: in usbduxsub_ai_isoc_irq()
311 dev_dbg(dev->class_dev, "CRC error in ISO IN stream\n"); in usbduxsub_ai_isoc_irq()
315 case -ECONNRESET: in usbduxsub_ai_isoc_irq()
316 case -ENOENT: in usbduxsub_ai_isoc_irq()
317 case -ESHUTDOWN: in usbduxsub_ai_isoc_irq()
318 case -ECONNABORTED: in usbduxsub_ai_isoc_irq()
320 async->events |= COMEDI_CB_ERROR; in usbduxsub_ai_isoc_irq()
325 dev_err(dev->class_dev, in usbduxsub_ai_isoc_irq()
326 "Non-zero urb status received in ai intr context: %d\n", in usbduxsub_ai_isoc_irq()
327 urb->status); in usbduxsub_ai_isoc_irq()
328 async->events |= COMEDI_CB_ERROR; in usbduxsub_ai_isoc_irq()
336 if (async->events & COMEDI_CB_CANCEL_MASK) in usbduxsub_ai_isoc_irq()
344 struct usbdux_private *devpriv = dev->private; in usbdux_ao_stop()
346 if (do_unlink && devpriv->ao_urbs) in usbdux_ao_stop()
347 usbdux_unlink_urbs(devpriv->ao_urbs, devpriv->n_ao_urbs); in usbdux_ao_stop()
349 devpriv->ao_cmd_running = 0; in usbdux_ao_stop()
355 struct usbdux_private *devpriv = dev->private; in usbdux_ao_cancel()
358 mutex_lock(&devpriv->mut); in usbdux_ao_cancel()
360 usbdux_ao_stop(dev, devpriv->ao_cmd_running); in usbdux_ao_cancel()
361 mutex_unlock(&devpriv->mut); in usbdux_ao_cancel()
370 struct usbdux_private *devpriv = dev->private; in usbduxsub_ao_handle_urb()
371 struct comedi_async *async = s->async; in usbduxsub_ao_handle_urb()
372 struct comedi_cmd *cmd = &async->cmd; in usbduxsub_ao_handle_urb()
377 devpriv->ao_counter--; in usbduxsub_ao_handle_urb()
378 if (devpriv->ao_counter == 0) { in usbduxsub_ao_handle_urb()
379 devpriv->ao_counter = devpriv->ao_timer; in usbduxsub_ao_handle_urb()
381 if (cmd->stop_src == TRIG_COUNT && in usbduxsub_ao_handle_urb()
382 async->scans_done >= cmd->stop_arg) { in usbduxsub_ao_handle_urb()
383 async->events |= COMEDI_CB_EOA; in usbduxsub_ao_handle_urb()
388 datap = urb->transfer_buffer; in usbduxsub_ao_handle_urb()
389 *datap++ = cmd->chanlist_len; in usbduxsub_ao_handle_urb()
390 for (i = 0; i < cmd->chanlist_len; i++) { in usbduxsub_ao_handle_urb()
391 unsigned int chan = CR_CHAN(cmd->chanlist[i]); in usbduxsub_ao_handle_urb()
395 dev_err(dev->class_dev, "buffer underflow\n"); in usbduxsub_ao_handle_urb()
396 async->events |= COMEDI_CB_OVERFLOW; in usbduxsub_ao_handle_urb()
404 s->readback[chan] = val; in usbduxsub_ao_handle_urb()
409 if (!(async->events & COMEDI_CB_CANCEL_MASK)) { in usbduxsub_ao_handle_urb()
410 urb->transfer_buffer_length = SIZEOUTBUF; in usbduxsub_ao_handle_urb()
411 urb->dev = comedi_to_usb_dev(dev); in usbduxsub_ao_handle_urb()
412 urb->status = 0; in usbduxsub_ao_handle_urb()
413 if (devpriv->high_speed) in usbduxsub_ao_handle_urb()
414 urb->interval = 8; /* uframes */ in usbduxsub_ao_handle_urb()
416 urb->interval = 1; /* frames */ in usbduxsub_ao_handle_urb()
417 urb->number_of_packets = 1; in usbduxsub_ao_handle_urb()
418 urb->iso_frame_desc[0].offset = 0; in usbduxsub_ao_handle_urb()
419 urb->iso_frame_desc[0].length = SIZEOUTBUF; in usbduxsub_ao_handle_urb()
420 urb->iso_frame_desc[0].status = 0; in usbduxsub_ao_handle_urb()
423 dev_err(dev->class_dev, in usbduxsub_ao_handle_urb()
424 "ao urb resubm failed in int-cont. ret=%d", in usbduxsub_ao_handle_urb()
426 if (ret == -EL2NSYNC) in usbduxsub_ao_handle_urb()
427 dev_err(dev->class_dev, in usbduxsub_ao_handle_urb()
429 async->events |= COMEDI_CB_ERROR; in usbduxsub_ao_handle_urb()
436 struct comedi_device *dev = urb->context; in usbduxsub_ao_isoc_irq()
437 struct comedi_subdevice *s = dev->write_subdev; in usbduxsub_ao_isoc_irq()
438 struct comedi_async *async = s->async; in usbduxsub_ao_isoc_irq()
439 struct usbdux_private *devpriv = dev->private; in usbduxsub_ao_isoc_irq()
442 if (!devpriv->ao_cmd_running) in usbduxsub_ao_isoc_irq()
445 switch (urb->status) { in usbduxsub_ao_isoc_irq()
450 case -ECONNRESET: in usbduxsub_ao_isoc_irq()
451 case -ENOENT: in usbduxsub_ao_isoc_irq()
452 case -ESHUTDOWN: in usbduxsub_ao_isoc_irq()
453 case -ECONNABORTED: in usbduxsub_ao_isoc_irq()
455 async->events |= COMEDI_CB_ERROR; in usbduxsub_ao_isoc_irq()
460 dev_err(dev->class_dev, in usbduxsub_ao_isoc_irq()
461 "Non-zero urb status received in ao intr context: %d\n", in usbduxsub_ao_isoc_irq()
462 urb->status); in usbduxsub_ao_isoc_irq()
463 async->events |= COMEDI_CB_ERROR; in usbduxsub_ao_isoc_irq()
471 if (async->events & COMEDI_CB_CANCEL_MASK) in usbduxsub_ao_isoc_irq()
482 struct usbdux_private *devpriv = dev->private; in usbdux_submit_urbs()
493 urb->interval = devpriv->ai_interval; in usbdux_submit_urbs()
494 urb->context = dev; in usbdux_submit_urbs()
495 urb->dev = usb; in usbdux_submit_urbs()
496 urb->status = 0; in usbdux_submit_urbs()
497 urb->transfer_flags = URB_ISO_ASAP; in usbdux_submit_urbs()
509 struct usbdux_private *devpriv = dev->private; in usbdux_ai_cmdtest()
514 err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT); in usbdux_ai_cmdtest()
515 err |= comedi_check_trigger_src(&cmd->scan_begin_src, TRIG_TIMER); in usbdux_ai_cmdtest()
516 err |= comedi_check_trigger_src(&cmd->convert_src, TRIG_NOW); in usbdux_ai_cmdtest()
517 err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); in usbdux_ai_cmdtest()
518 err |= comedi_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE); in usbdux_ai_cmdtest()
525 err |= comedi_check_trigger_is_unique(cmd->start_src); in usbdux_ai_cmdtest()
526 err |= comedi_check_trigger_is_unique(cmd->stop_src); in usbdux_ai_cmdtest()
535 err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0); in usbdux_ai_cmdtest()
537 if (cmd->scan_begin_src == TRIG_FOLLOW) /* internal trigger */ in usbdux_ai_cmdtest()
538 err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, 0); in usbdux_ai_cmdtest()
540 if (cmd->scan_begin_src == TRIG_TIMER) { in usbdux_ai_cmdtest()
545 if (devpriv->high_speed) { in usbdux_ai_cmdtest()
555 while (i < cmd->chanlist_len) in usbdux_ai_cmdtest()
561 err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg, in usbdux_ai_cmdtest()
564 arg = (cmd->scan_begin_arg / arg) * arg; in usbdux_ai_cmdtest()
565 err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, arg); in usbdux_ai_cmdtest()
568 err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg, in usbdux_ai_cmdtest()
569 cmd->chanlist_len); in usbdux_ai_cmdtest()
571 if (cmd->stop_src == TRIG_COUNT) in usbdux_ai_cmdtest()
572 err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1); in usbdux_ai_cmdtest()
574 err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0); in usbdux_ai_cmdtest()
597 struct usbdux_private *devpriv = dev->private; in send_dux_commands()
600 devpriv->dux_commands[0] = cmd_type; in send_dux_commands()
603 devpriv->dux_commands, SIZEOFDUXBUFFER, in send_dux_commands()
610 struct usbdux_private *devpriv = dev->private; in receive_dux_commands()
617 devpriv->insn_buf, SIZEINSNBUF, in receive_dux_commands()
621 if (le16_to_cpu(devpriv->insn_buf[0]) == command) in receive_dux_commands()
625 return -EFAULT; in receive_dux_commands()
632 struct usbdux_private *devpriv = dev->private; in usbdux_ai_inttrig()
633 struct comedi_cmd *cmd = &s->async->cmd; in usbdux_ai_inttrig()
636 if (trig_num != cmd->start_arg) in usbdux_ai_inttrig()
637 return -EINVAL; in usbdux_ai_inttrig()
639 mutex_lock(&devpriv->mut); in usbdux_ai_inttrig()
641 if (!devpriv->ai_cmd_running) { in usbdux_ai_inttrig()
642 devpriv->ai_cmd_running = 1; in usbdux_ai_inttrig()
643 ret = usbdux_submit_urbs(dev, devpriv->ai_urbs, in usbdux_ai_inttrig()
644 devpriv->n_ai_urbs, 1); in usbdux_ai_inttrig()
646 devpriv->ai_cmd_running = 0; in usbdux_ai_inttrig()
649 s->async->inttrig = NULL; in usbdux_ai_inttrig()
651 ret = -EBUSY; in usbdux_ai_inttrig()
655 mutex_unlock(&devpriv->mut); in usbdux_ai_inttrig()
661 struct usbdux_private *devpriv = dev->private; in usbdux_ai_cmd()
662 struct comedi_cmd *cmd = &s->async->cmd; in usbdux_ai_cmd()
663 int len = cmd->chanlist_len; in usbdux_ai_cmd()
664 int ret = -EBUSY; in usbdux_ai_cmd()
668 mutex_lock(&devpriv->mut); in usbdux_ai_cmd()
670 if (devpriv->ai_cmd_running) in usbdux_ai_cmd()
673 devpriv->dux_commands[1] = len; in usbdux_ai_cmd()
675 unsigned int chan = CR_CHAN(cmd->chanlist[i]); in usbdux_ai_cmd()
676 unsigned int range = CR_RANGE(cmd->chanlist[i]); in usbdux_ai_cmd()
678 devpriv->dux_commands[i + 2] = create_adc_command(chan, range); in usbdux_ai_cmd()
685 if (devpriv->high_speed) { in usbdux_ai_cmd()
688 * sample all 8 channels we need 1ms. If we sample only one in usbdux_ai_cmd()
691 devpriv->ai_interval = 1; in usbdux_ai_cmd()
692 /* find a power of 2 for the interval */ in usbdux_ai_cmd()
693 while (devpriv->ai_interval < len) in usbdux_ai_cmd()
694 devpriv->ai_interval *= 2; in usbdux_ai_cmd()
696 devpriv->ai_timer = cmd->scan_begin_arg / in usbdux_ai_cmd()
697 (125000 * devpriv->ai_interval); in usbdux_ai_cmd()
699 /* interval always 1ms */ in usbdux_ai_cmd()
700 devpriv->ai_interval = 1; in usbdux_ai_cmd()
701 devpriv->ai_timer = cmd->scan_begin_arg / 1000000; in usbdux_ai_cmd()
703 if (devpriv->ai_timer < 1) { in usbdux_ai_cmd()
704 ret = -EINVAL; in usbdux_ai_cmd()
708 devpriv->ai_counter = devpriv->ai_timer; in usbdux_ai_cmd()
710 if (cmd->start_src == TRIG_NOW) { in usbdux_ai_cmd()
712 devpriv->ai_cmd_running = 1; in usbdux_ai_cmd()
713 ret = usbdux_submit_urbs(dev, devpriv->ai_urbs, in usbdux_ai_cmd()
714 devpriv->n_ai_urbs, 1); in usbdux_ai_cmd()
716 devpriv->ai_cmd_running = 0; in usbdux_ai_cmd()
720 s->async->inttrig = NULL; in usbdux_ai_cmd()
725 s->async->inttrig = usbdux_ai_inttrig; in usbdux_ai_cmd()
729 mutex_unlock(&devpriv->mut); in usbdux_ai_cmd()
740 struct usbdux_private *devpriv = dev->private; in usbdux_ai_insn_read()
741 unsigned int chan = CR_CHAN(insn->chanspec); in usbdux_ai_insn_read()
742 unsigned int range = CR_RANGE(insn->chanspec); in usbdux_ai_insn_read()
744 int ret = -EBUSY; in usbdux_ai_insn_read()
747 mutex_lock(&devpriv->mut); in usbdux_ai_insn_read()
749 if (devpriv->ai_cmd_running) in usbdux_ai_insn_read()
753 devpriv->dux_commands[1] = create_adc_command(chan, range); in usbdux_ai_insn_read()
760 for (i = 0; i < insn->n; i++) { in usbdux_ai_insn_read()
765 val = le16_to_cpu(devpriv->insn_buf[1]); in usbdux_ai_insn_read()
767 /* bipolar data is two's-complement */ in usbdux_ai_insn_read()
775 mutex_unlock(&devpriv->mut); in usbdux_ai_insn_read()
777 return ret ? ret : insn->n; in usbdux_ai_insn_read()
785 struct usbdux_private *devpriv = dev->private; in usbdux_ao_insn_read()
788 mutex_lock(&devpriv->mut); in usbdux_ao_insn_read()
790 mutex_unlock(&devpriv->mut); in usbdux_ao_insn_read()
800 struct usbdux_private *devpriv = dev->private; in usbdux_ao_insn_write()
801 unsigned int chan = CR_CHAN(insn->chanspec); in usbdux_ao_insn_write()
802 __le16 *p = (__le16 *)&devpriv->dux_commands[2]; in usbdux_ao_insn_write()
803 int ret = -EBUSY; in usbdux_ao_insn_write()
806 mutex_lock(&devpriv->mut); in usbdux_ao_insn_write()
808 if (devpriv->ao_cmd_running) in usbdux_ao_insn_write()
812 devpriv->dux_commands[1] = 1; in usbdux_ao_insn_write()
814 devpriv->dux_commands[4] = chan << 6; in usbdux_ao_insn_write()
816 for (i = 0; i < insn->n; i++) { in usbdux_ao_insn_write()
826 s->readback[chan] = val; in usbdux_ao_insn_write()
830 mutex_unlock(&devpriv->mut); in usbdux_ao_insn_write()
832 return ret ? ret : insn->n; in usbdux_ao_insn_write()
839 struct usbdux_private *devpriv = dev->private; in usbdux_ao_inttrig()
840 struct comedi_cmd *cmd = &s->async->cmd; in usbdux_ao_inttrig()
843 if (trig_num != cmd->start_arg) in usbdux_ao_inttrig()
844 return -EINVAL; in usbdux_ao_inttrig()
846 mutex_lock(&devpriv->mut); in usbdux_ao_inttrig()
848 if (!devpriv->ao_cmd_running) { in usbdux_ao_inttrig()
849 devpriv->ao_cmd_running = 1; in usbdux_ao_inttrig()
850 ret = usbdux_submit_urbs(dev, devpriv->ao_urbs, in usbdux_ao_inttrig()
851 devpriv->n_ao_urbs, 0); in usbdux_ao_inttrig()
853 devpriv->ao_cmd_running = 0; in usbdux_ao_inttrig()
856 s->async->inttrig = NULL; in usbdux_ao_inttrig()
858 ret = -EBUSY; in usbdux_ao_inttrig()
862 mutex_unlock(&devpriv->mut); in usbdux_ao_inttrig()
874 err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_INT); in usbdux_ao_cmdtest()
876 if (0) { /* (devpriv->high_speed) */ in usbdux_ao_cmdtest()
880 /* start a new scan (output at once) with a timer */ in usbdux_ao_cmdtest()
883 err |= comedi_check_trigger_src(&cmd->scan_begin_src, flags); in usbdux_ao_cmdtest()
885 if (0) { /* (devpriv->high_speed) */ in usbdux_ao_cmdtest()
887 * in usb-2.0 only one conversion it transmitted in usbdux_ao_cmdtest()
898 err |= comedi_check_trigger_src(&cmd->convert_src, flags); in usbdux_ao_cmdtest()
900 err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT); in usbdux_ao_cmdtest()
901 err |= comedi_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE); in usbdux_ao_cmdtest()
908 err |= comedi_check_trigger_is_unique(cmd->start_src); in usbdux_ao_cmdtest()
909 err |= comedi_check_trigger_is_unique(cmd->stop_src); in usbdux_ao_cmdtest()
918 err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0); in usbdux_ao_cmdtest()
920 if (cmd->scan_begin_src == TRIG_FOLLOW) /* internal trigger */ in usbdux_ao_cmdtest()
921 err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, 0); in usbdux_ao_cmdtest()
923 if (cmd->scan_begin_src == TRIG_TIMER) { in usbdux_ao_cmdtest()
924 err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg, in usbdux_ao_cmdtest()
929 if (cmd->convert_src == TRIG_TIMER) in usbdux_ao_cmdtest()
930 err |= comedi_check_trigger_arg_min(&cmd->convert_arg, 125000); in usbdux_ao_cmdtest()
932 err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg, in usbdux_ao_cmdtest()
933 cmd->chanlist_len); in usbdux_ao_cmdtest()
935 if (cmd->stop_src == TRIG_COUNT) in usbdux_ao_cmdtest()
936 err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1); in usbdux_ao_cmdtest()
938 err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0); in usbdux_ao_cmdtest()
948 struct usbdux_private *devpriv = dev->private; in usbdux_ao_cmd()
949 struct comedi_cmd *cmd = &s->async->cmd; in usbdux_ao_cmd()
950 int ret = -EBUSY; in usbdux_ao_cmd()
952 mutex_lock(&devpriv->mut); in usbdux_ao_cmd()
954 if (devpriv->ao_cmd_running) in usbdux_ao_cmd()
957 /* we count in steps of 1ms (125us) */ in usbdux_ao_cmd()
959 if (0) { /* (devpriv->high_speed) */ in usbdux_ao_cmd()
962 devpriv->ao_timer = cmd->convert_arg / 125000; in usbdux_ao_cmd()
964 /* 1ms */ in usbdux_ao_cmd()
965 /* timing of the scan: we get all channels at once */ in usbdux_ao_cmd()
966 devpriv->ao_timer = cmd->scan_begin_arg / 1000000; in usbdux_ao_cmd()
967 if (devpriv->ao_timer < 1) { in usbdux_ao_cmd()
968 ret = -EINVAL; in usbdux_ao_cmd()
973 devpriv->ao_counter = devpriv->ao_timer; in usbdux_ao_cmd()
975 if (cmd->start_src == TRIG_NOW) { in usbdux_ao_cmd()
977 devpriv->ao_cmd_running = 1; in usbdux_ao_cmd()
978 ret = usbdux_submit_urbs(dev, devpriv->ao_urbs, in usbdux_ao_cmd()
979 devpriv->n_ao_urbs, 0); in usbdux_ao_cmd()
981 devpriv->ao_cmd_running = 0; in usbdux_ao_cmd()
985 s->async->inttrig = NULL; in usbdux_ao_cmd()
990 s->async->inttrig = usbdux_ao_inttrig; in usbdux_ao_cmd()
994 mutex_unlock(&devpriv->mut); in usbdux_ao_cmd()
1014 return insn->n; in usbdux_dio_insn_config()
1022 struct usbdux_private *devpriv = dev->private; in usbdux_dio_insn_bits()
1025 mutex_lock(&devpriv->mut); in usbdux_dio_insn_bits()
1030 devpriv->dux_commands[1] = s->io_bits; in usbdux_dio_insn_bits()
1031 devpriv->dux_commands[2] = s->state; in usbdux_dio_insn_bits()
1044 data[1] = le16_to_cpu(devpriv->insn_buf[1]); in usbdux_dio_insn_bits()
1047 mutex_unlock(&devpriv->mut); in usbdux_dio_insn_bits()
1049 return ret ? ret : insn->n; in usbdux_dio_insn_bits()
1057 struct usbdux_private *devpriv = dev->private; in usbdux_counter_read()
1058 unsigned int chan = CR_CHAN(insn->chanspec); in usbdux_counter_read()
1062 mutex_lock(&devpriv->mut); in usbdux_counter_read()
1064 for (i = 0; i < insn->n; i++) { in usbdux_counter_read()
1072 data[i] = le16_to_cpu(devpriv->insn_buf[chan + 1]); in usbdux_counter_read()
1076 mutex_unlock(&devpriv->mut); in usbdux_counter_read()
1078 return ret ? ret : insn->n; in usbdux_counter_read()
1086 struct usbdux_private *devpriv = dev->private; in usbdux_counter_write()
1087 unsigned int chan = CR_CHAN(insn->chanspec); in usbdux_counter_write()
1088 __le16 *p = (__le16 *)&devpriv->dux_commands[2]; in usbdux_counter_write()
1092 mutex_lock(&devpriv->mut); in usbdux_counter_write()
1094 devpriv->dux_commands[1] = chan; in usbdux_counter_write()
1096 for (i = 0; i < insn->n; i++) { in usbdux_counter_write()
1104 mutex_unlock(&devpriv->mut); in usbdux_counter_write()
1106 return ret ? ret : insn->n; in usbdux_counter_write()
1119 struct usbdux_private *devpriv = dev->private; in usbduxsub_unlink_pwm_urbs()
1121 usb_kill_urb(devpriv->pwm_urb); in usbduxsub_unlink_pwm_urbs()
1126 struct usbdux_private *devpriv = dev->private; in usbdux_pwm_stop()
1131 devpriv->pwm_cmd_running = 0; in usbdux_pwm_stop()
1137 struct usbdux_private *devpriv = dev->private; in usbdux_pwm_cancel()
1140 mutex_lock(&devpriv->mut); in usbdux_pwm_cancel()
1142 usbdux_pwm_stop(dev, devpriv->pwm_cmd_running); in usbdux_pwm_cancel()
1144 mutex_unlock(&devpriv->mut); in usbdux_pwm_cancel()
1151 struct comedi_device *dev = urb->context; in usbduxsub_pwm_irq()
1152 struct usbdux_private *devpriv = dev->private; in usbduxsub_pwm_irq()
1155 switch (urb->status) { in usbduxsub_pwm_irq()
1160 case -ECONNRESET: in usbduxsub_pwm_irq()
1161 case -ENOENT: in usbduxsub_pwm_irq()
1162 case -ESHUTDOWN: in usbduxsub_pwm_irq()
1163 case -ECONNABORTED: in usbduxsub_pwm_irq()
1168 if (devpriv->pwm_cmd_running) in usbduxsub_pwm_irq()
1175 if (devpriv->pwm_cmd_running) { in usbduxsub_pwm_irq()
1176 dev_err(dev->class_dev, in usbduxsub_pwm_irq()
1177 "Non-zero urb status received in pwm intr context: %d\n", in usbduxsub_pwm_irq()
1178 urb->status); in usbduxsub_pwm_irq()
1185 if (!devpriv->pwm_cmd_running) in usbduxsub_pwm_irq()
1188 urb->transfer_buffer_length = devpriv->pwm_buf_sz; in usbduxsub_pwm_irq()
1189 urb->dev = comedi_to_usb_dev(dev); in usbduxsub_pwm_irq()
1190 urb->status = 0; in usbduxsub_pwm_irq()
1191 if (devpriv->pwm_cmd_running) { in usbduxsub_pwm_irq()
1194 dev_err(dev->class_dev, in usbduxsub_pwm_irq()
1195 "pwm urb resubm failed in int-cont. ret=%d", in usbduxsub_pwm_irq()
1197 if (ret == -EL2NSYNC) in usbduxsub_pwm_irq()
1198 dev_err(dev->class_dev, in usbduxsub_pwm_irq()
1210 struct usbdux_private *devpriv = dev->private; in usbduxsub_submit_pwm_urbs()
1211 struct urb *urb = devpriv->pwm_urb; in usbduxsub_submit_pwm_urbs()
1215 urb->transfer_buffer, in usbduxsub_submit_pwm_urbs()
1216 devpriv->pwm_buf_sz, in usbduxsub_submit_pwm_urbs()
1227 struct usbdux_private *devpriv = dev->private; in usbdux_pwm_period()
1231 return -EAGAIN; in usbdux_pwm_period()
1233 fx2delay = (period / (6 * 512 * 1000 / 33)) - 6; in usbdux_pwm_period()
1235 return -EAGAIN; in usbdux_pwm_period()
1237 devpriv->pwm_delay = fx2delay; in usbdux_pwm_period()
1238 devpriv->pwm_period = period; in usbdux_pwm_period()
1246 struct usbdux_private *devpriv = dev->private; in usbdux_pwm_start()
1249 mutex_lock(&devpriv->mut); in usbdux_pwm_start()
1251 if (devpriv->pwm_cmd_running) in usbdux_pwm_start()
1254 devpriv->dux_commands[1] = devpriv->pwm_delay; in usbdux_pwm_start()
1260 memset(devpriv->pwm_urb->transfer_buffer, 0, devpriv->pwm_buf_sz); in usbdux_pwm_start()
1262 devpriv->pwm_cmd_running = 1; in usbdux_pwm_start()
1265 devpriv->pwm_cmd_running = 0; in usbdux_pwm_start()
1268 mutex_unlock(&devpriv->mut); in usbdux_pwm_start()
1279 struct usbdux_private *devpriv = dev->private; in usbdux_pwm_pattern()
1282 char *buf = (char *)(devpriv->pwm_urb->transfer_buffer); in usbdux_pwm_pattern()
1283 int szbuf = devpriv->pwm_buf_sz; in usbdux_pwm_pattern()
1305 unsigned int chan = CR_CHAN(insn->chanspec); in usbdux_pwm_write()
1311 if (insn->n != 1) in usbdux_pwm_write()
1312 return -EINVAL; in usbdux_pwm_write()
1320 return insn->n; in usbdux_pwm_write()
1328 struct usbdux_private *devpriv = dev->private; in usbdux_pwm_config()
1329 unsigned int chan = CR_CHAN(insn->chanspec); in usbdux_pwm_config()
1338 return -EINVAL; in usbdux_pwm_config()
1343 data[1] = devpriv->pwm_cmd_running; in usbdux_pwm_config()
1348 data[1] = devpriv->pwm_period; in usbdux_pwm_config()
1359 return -EINVAL; in usbdux_pwm_config()
1361 return -EINVAL; in usbdux_pwm_config()
1377 dev_err(dev->class_dev, in usbdux_firmware_upload()
1379 return -ENOMEM; in usbdux_firmware_upload()
1385 return -ENOMEM; in usbdux_firmware_upload()
1391 return -ENOMEM; in usbdux_firmware_upload()
1403 dev_err(dev->class_dev, "can not stop firmware\n"); in usbdux_firmware_upload()
1415 dev_err(dev->class_dev, "firmware upload failed\n"); in usbdux_firmware_upload()
1428 dev_err(dev->class_dev, "can not start firmware\n"); in usbdux_firmware_upload()
1439 struct usbdux_private *devpriv = dev->private; in usbdux_alloc_usb_buffers()
1443 devpriv->dux_commands = kzalloc(SIZEOFDUXBUFFER, GFP_KERNEL); in usbdux_alloc_usb_buffers()
1444 devpriv->in_buf = kzalloc(SIZEINBUF, GFP_KERNEL); in usbdux_alloc_usb_buffers()
1445 devpriv->insn_buf = kzalloc(SIZEINSNBUF, GFP_KERNEL); in usbdux_alloc_usb_buffers()
1446 devpriv->ai_urbs = kcalloc(devpriv->n_ai_urbs, sizeof(void *), in usbdux_alloc_usb_buffers()
1448 devpriv->ao_urbs = kcalloc(devpriv->n_ao_urbs, sizeof(void *), in usbdux_alloc_usb_buffers()
1450 if (!devpriv->dux_commands || !devpriv->in_buf || !devpriv->insn_buf || in usbdux_alloc_usb_buffers()
1451 !devpriv->ai_urbs || !devpriv->ao_urbs) in usbdux_alloc_usb_buffers()
1452 return -ENOMEM; in usbdux_alloc_usb_buffers()
1454 for (i = 0; i < devpriv->n_ai_urbs; i++) { in usbdux_alloc_usb_buffers()
1455 /* one frame: 1ms */ in usbdux_alloc_usb_buffers()
1458 return -ENOMEM; in usbdux_alloc_usb_buffers()
1459 devpriv->ai_urbs[i] = urb; in usbdux_alloc_usb_buffers()
1461 urb->dev = usb; in usbdux_alloc_usb_buffers()
1462 urb->context = dev; in usbdux_alloc_usb_buffers()
1463 urb->pipe = usb_rcvisocpipe(usb, 6); in usbdux_alloc_usb_buffers()
1464 urb->transfer_flags = URB_ISO_ASAP; in usbdux_alloc_usb_buffers()
1465 urb->transfer_buffer = kzalloc(SIZEINBUF, GFP_KERNEL); in usbdux_alloc_usb_buffers()
1466 if (!urb->transfer_buffer) in usbdux_alloc_usb_buffers()
1467 return -ENOMEM; in usbdux_alloc_usb_buffers()
1469 urb->complete = usbduxsub_ai_isoc_irq; in usbdux_alloc_usb_buffers()
1470 urb->number_of_packets = 1; in usbdux_alloc_usb_buffers()
1471 urb->transfer_buffer_length = SIZEINBUF; in usbdux_alloc_usb_buffers()
1472 urb->iso_frame_desc[0].offset = 0; in usbdux_alloc_usb_buffers()
1473 urb->iso_frame_desc[0].length = SIZEINBUF; in usbdux_alloc_usb_buffers()
1476 for (i = 0; i < devpriv->n_ao_urbs; i++) { in usbdux_alloc_usb_buffers()
1477 /* one frame: 1ms */ in usbdux_alloc_usb_buffers()
1480 return -ENOMEM; in usbdux_alloc_usb_buffers()
1481 devpriv->ao_urbs[i] = urb; in usbdux_alloc_usb_buffers()
1483 urb->dev = usb; in usbdux_alloc_usb_buffers()
1484 urb->context = dev; in usbdux_alloc_usb_buffers()
1485 urb->pipe = usb_sndisocpipe(usb, 2); in usbdux_alloc_usb_buffers()
1486 urb->transfer_flags = URB_ISO_ASAP; in usbdux_alloc_usb_buffers()
1487 urb->transfer_buffer = kzalloc(SIZEOUTBUF, GFP_KERNEL); in usbdux_alloc_usb_buffers()
1488 if (!urb->transfer_buffer) in usbdux_alloc_usb_buffers()
1489 return -ENOMEM; in usbdux_alloc_usb_buffers()
1491 urb->complete = usbduxsub_ao_isoc_irq; in usbdux_alloc_usb_buffers()
1492 urb->number_of_packets = 1; in usbdux_alloc_usb_buffers()
1493 urb->transfer_buffer_length = SIZEOUTBUF; in usbdux_alloc_usb_buffers()
1494 urb->iso_frame_desc[0].offset = 0; in usbdux_alloc_usb_buffers()
1495 urb->iso_frame_desc[0].length = SIZEOUTBUF; in usbdux_alloc_usb_buffers()
1496 if (devpriv->high_speed) in usbdux_alloc_usb_buffers()
1497 urb->interval = 8; /* uframes */ in usbdux_alloc_usb_buffers()
1499 urb->interval = 1; /* frames */ in usbdux_alloc_usb_buffers()
1503 if (devpriv->pwm_buf_sz) { in usbdux_alloc_usb_buffers()
1506 return -ENOMEM; in usbdux_alloc_usb_buffers()
1507 devpriv->pwm_urb = urb; in usbdux_alloc_usb_buffers()
1510 urb->transfer_buffer = kzalloc(devpriv->pwm_buf_sz, in usbdux_alloc_usb_buffers()
1512 if (!urb->transfer_buffer) in usbdux_alloc_usb_buffers()
1513 return -ENOMEM; in usbdux_alloc_usb_buffers()
1521 struct usbdux_private *devpriv = dev->private; in usbdux_free_usb_buffers()
1525 urb = devpriv->pwm_urb; in usbdux_free_usb_buffers()
1527 kfree(urb->transfer_buffer); in usbdux_free_usb_buffers()
1530 if (devpriv->ao_urbs) { in usbdux_free_usb_buffers()
1531 for (i = 0; i < devpriv->n_ao_urbs; i++) { in usbdux_free_usb_buffers()
1532 urb = devpriv->ao_urbs[i]; in usbdux_free_usb_buffers()
1534 kfree(urb->transfer_buffer); in usbdux_free_usb_buffers()
1538 kfree(devpriv->ao_urbs); in usbdux_free_usb_buffers()
1540 if (devpriv->ai_urbs) { in usbdux_free_usb_buffers()
1541 for (i = 0; i < devpriv->n_ai_urbs; i++) { in usbdux_free_usb_buffers()
1542 urb = devpriv->ai_urbs[i]; in usbdux_free_usb_buffers()
1544 kfree(urb->transfer_buffer); in usbdux_free_usb_buffers()
1548 kfree(devpriv->ai_urbs); in usbdux_free_usb_buffers()
1550 kfree(devpriv->insn_buf); in usbdux_free_usb_buffers()
1551 kfree(devpriv->in_buf); in usbdux_free_usb_buffers()
1552 kfree(devpriv->dux_commands); in usbdux_free_usb_buffers()
1566 return -ENOMEM; in usbdux_auto_attach()
1568 mutex_init(&devpriv->mut); in usbdux_auto_attach()
1572 devpriv->high_speed = (usb->speed == USB_SPEED_HIGH); in usbdux_auto_attach()
1573 if (devpriv->high_speed) { in usbdux_auto_attach()
1574 devpriv->n_ai_urbs = NUMOFINBUFFERSHIGH; in usbdux_auto_attach()
1575 devpriv->n_ao_urbs = NUMOFOUTBUFFERSHIGH; in usbdux_auto_attach()
1576 devpriv->pwm_buf_sz = 512; in usbdux_auto_attach()
1578 devpriv->n_ai_urbs = NUMOFINBUFFERSFULL; in usbdux_auto_attach()
1579 devpriv->n_ao_urbs = NUMOFOUTBUFFERSFULL; in usbdux_auto_attach()
1587 ret = usb_set_interface(usb, intf->altsetting->desc.bInterfaceNumber, in usbdux_auto_attach()
1590 dev_err(dev->class_dev, in usbdux_auto_attach()
1595 ret = comedi_load_firmware(dev, &usb->dev, USBDUX_FIRMWARE, in usbdux_auto_attach()
1600 ret = comedi_alloc_subdevices(dev, (devpriv->high_speed) ? 5 : 4); in usbdux_auto_attach()
1605 s = &dev->subdevices[0]; in usbdux_auto_attach()
1606 dev->read_subdev = s; in usbdux_auto_attach()
1607 s->type = COMEDI_SUBD_AI; in usbdux_auto_attach()
1608 s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_CMD_READ; in usbdux_auto_attach()
1609 s->n_chan = 8; in usbdux_auto_attach()
1610 s->maxdata = 0x0fff; in usbdux_auto_attach()
1611 s->len_chanlist = 8; in usbdux_auto_attach()
1612 s->range_table = &range_usbdux_ai_range; in usbdux_auto_attach()
1613 s->insn_read = usbdux_ai_insn_read; in usbdux_auto_attach()
1614 s->do_cmdtest = usbdux_ai_cmdtest; in usbdux_auto_attach()
1615 s->do_cmd = usbdux_ai_cmd; in usbdux_auto_attach()
1616 s->cancel = usbdux_ai_cancel; in usbdux_auto_attach()
1619 s = &dev->subdevices[1]; in usbdux_auto_attach()
1620 dev->write_subdev = s; in usbdux_auto_attach()
1621 s->type = COMEDI_SUBD_AO; in usbdux_auto_attach()
1622 s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_CMD_WRITE; in usbdux_auto_attach()
1623 s->n_chan = 4; in usbdux_auto_attach()
1624 s->maxdata = 0x0fff; in usbdux_auto_attach()
1625 s->len_chanlist = s->n_chan; in usbdux_auto_attach()
1626 s->range_table = &range_usbdux_ao_range; in usbdux_auto_attach()
1627 s->do_cmdtest = usbdux_ao_cmdtest; in usbdux_auto_attach()
1628 s->do_cmd = usbdux_ao_cmd; in usbdux_auto_attach()
1629 s->cancel = usbdux_ao_cancel; in usbdux_auto_attach()
1630 s->insn_read = usbdux_ao_insn_read; in usbdux_auto_attach()
1631 s->insn_write = usbdux_ao_insn_write; in usbdux_auto_attach()
1638 s = &dev->subdevices[2]; in usbdux_auto_attach()
1639 s->type = COMEDI_SUBD_DIO; in usbdux_auto_attach()
1640 s->subdev_flags = SDF_READABLE | SDF_WRITABLE; in usbdux_auto_attach()
1641 s->n_chan = 8; in usbdux_auto_attach()
1642 s->maxdata = 1; in usbdux_auto_attach()
1643 s->range_table = &range_digital; in usbdux_auto_attach()
1644 s->insn_bits = usbdux_dio_insn_bits; in usbdux_auto_attach()
1645 s->insn_config = usbdux_dio_insn_config; in usbdux_auto_attach()
1648 s = &dev->subdevices[3]; in usbdux_auto_attach()
1649 s->type = COMEDI_SUBD_COUNTER; in usbdux_auto_attach()
1650 s->subdev_flags = SDF_WRITABLE | SDF_READABLE; in usbdux_auto_attach()
1651 s->n_chan = 4; in usbdux_auto_attach()
1652 s->maxdata = 0xffff; in usbdux_auto_attach()
1653 s->insn_read = usbdux_counter_read; in usbdux_auto_attach()
1654 s->insn_write = usbdux_counter_write; in usbdux_auto_attach()
1655 s->insn_config = usbdux_counter_config; in usbdux_auto_attach()
1657 if (devpriv->high_speed) { in usbdux_auto_attach()
1659 s = &dev->subdevices[4]; in usbdux_auto_attach()
1660 s->type = COMEDI_SUBD_PWM; in usbdux_auto_attach()
1661 s->subdev_flags = SDF_WRITABLE | SDF_PWM_HBRIDGE; in usbdux_auto_attach()
1662 s->n_chan = 8; in usbdux_auto_attach()
1663 s->maxdata = devpriv->pwm_buf_sz; in usbdux_auto_attach()
1664 s->insn_write = usbdux_pwm_write; in usbdux_auto_attach()
1665 s->insn_config = usbdux_pwm_config; in usbdux_auto_attach()
1676 struct usbdux_private *devpriv = dev->private; in usbdux_detach()
1683 mutex_lock(&devpriv->mut); in usbdux_detach()
1692 mutex_unlock(&devpriv->mut); in usbdux_detach()
1694 mutex_destroy(&devpriv->mut); in usbdux_detach()
1726 MODULE_DESCRIPTION("Stirling/ITL USB-DUX -- Bernd.Porr@f2s.com");