drivers/comedi/drivers/usbdux.c

Source file repositories/reference/linux-study-clean/drivers/comedi/drivers/usbdux.c

File Facts

System
Linux kernel
Corpus path
drivers/comedi/drivers/usbdux.c
Extension
.c
Size
43520 bytes
Lines
1729
Domain
Driver Families
Bucket
drivers/comedi
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct usbdux_private {
	/* actual number of in-buffers */
	int n_ai_urbs;
	/* actual number of out-buffers */
	int n_ao_urbs;
	/* ISO-transfer handling: buffers */
	struct urb **ai_urbs;
	struct urb **ao_urbs;
	/* pwm-transfer handling */
	struct urb *pwm_urb;
	/* PWM period */
	unsigned int pwm_period;
	/* PWM internal delay for the GPIF in the FX2 */
	u8 pwm_delay;
	/* size of the PWM buffer which holds the bit pattern */
	int pwm_buf_sz;
	/* input buffer for the ISO-transfer */
	__le16 *in_buf;
	/* input buffer for single insn */
	__le16 *insn_buf;

	unsigned int high_speed:1;
	unsigned int ai_cmd_running:1;
	unsigned int ao_cmd_running:1;
	unsigned int pwm_cmd_running:1;

	/* time between samples in units of the timer */
	unsigned int ai_timer;
	unsigned int ao_timer;
	/* counter between aquisitions */
	unsigned int ai_counter;
	unsigned int ao_counter;
	/* interval in frames/uframes */
	unsigned int ai_interval;
	/* commands */
	u8 *dux_commands;
	struct mutex mut;
};

static void usbdux_unlink_urbs(struct urb **urbs, int num_urbs)
{
	int i;

	for (i = 0; i < num_urbs; i++)
		usb_kill_urb(urbs[i]);
}

static void usbdux_ai_stop(struct comedi_device *dev, int do_unlink)
{
	struct usbdux_private *devpriv = dev->private;

	if (do_unlink && devpriv->ai_urbs)
		usbdux_unlink_urbs(devpriv->ai_urbs, devpriv->n_ai_urbs);

	devpriv->ai_cmd_running = 0;
}

static int usbdux_ai_cancel(struct comedi_device *dev,
			    struct comedi_subdevice *s)
{
	struct usbdux_private *devpriv = dev->private;

	/* prevent other CPUs from submitting new commands just now */
	mutex_lock(&devpriv->mut);
	/* unlink only if the urb really has been submitted */
	usbdux_ai_stop(dev, devpriv->ai_cmd_running);
	mutex_unlock(&devpriv->mut);

	return 0;
}

static void usbduxsub_ai_handle_urb(struct comedi_device *dev,
				    struct comedi_subdevice *s,
				    struct urb *urb)
{
	struct usbdux_private *devpriv = dev->private;
	struct comedi_async *async = s->async;
	struct comedi_cmd *cmd = &async->cmd;
	int ret;
	int i;

	devpriv->ai_counter--;
	if (devpriv->ai_counter == 0) {
		devpriv->ai_counter = devpriv->ai_timer;

		/* get the data from the USB bus and hand it over to comedi */
		for (i = 0; i < cmd->chanlist_len; i++) {
			unsigned int range = CR_RANGE(cmd->chanlist[i]);
			u16 val = le16_to_cpu(devpriv->in_buf[i]);

Annotation

Implementation Notes