static int ai_cmdtest()

in drivers/cb_pcidas64.c [2097:2221]


static int ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
		      struct comedi_cmd *cmd)
{
	const struct pcidas64_board *board = dev->board_ptr;
	int err = 0;
	unsigned int tmp_arg, tmp_arg2;
	unsigned int triggers;

	/* Step 1 : check if triggers are trivially valid */

	err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT);

	triggers = TRIG_TIMER;
	if (board->layout == LAYOUT_4020)
		triggers |= TRIG_OTHER;
	else
		triggers |= TRIG_FOLLOW;
	err |= comedi_check_trigger_src(&cmd->scan_begin_src, triggers);

	triggers = TRIG_TIMER;
	if (board->layout == LAYOUT_4020)
		triggers |= TRIG_NOW;
	else
		triggers |= TRIG_EXT;
	err |= comedi_check_trigger_src(&cmd->convert_src, triggers);
	err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
	err |= comedi_check_trigger_src(&cmd->stop_src,
					TRIG_COUNT | TRIG_EXT | TRIG_NONE);

	if (err)
		return 1;

	/* Step 2a : make sure trigger sources are unique */

	err |= comedi_check_trigger_is_unique(cmd->start_src);
	err |= comedi_check_trigger_is_unique(cmd->scan_begin_src);
	err |= comedi_check_trigger_is_unique(cmd->convert_src);
	err |= comedi_check_trigger_is_unique(cmd->stop_src);

	/* Step 2b : and mutually compatible */

	if (cmd->convert_src == TRIG_EXT && cmd->scan_begin_src == TRIG_TIMER)
		err |= -EINVAL;

	if (err)
		return 2;

	/* Step 3: check if arguments are trivially valid */

	switch (cmd->start_src) {
	case TRIG_NOW:
		err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
		break;
	case TRIG_EXT:
		/*
		 * start_arg is the CR_CHAN | CR_INVERT of the
		 * external trigger.
		 */
		break;
	}

	if (cmd->convert_src == TRIG_TIMER) {
		if (board->layout == LAYOUT_4020) {
			err |= comedi_check_trigger_arg_is(&cmd->convert_arg,
							   0);
		} else {
			err |= comedi_check_trigger_arg_min(&cmd->convert_arg,
							    board->ai_speed);
			/*
			 * if scans are timed faster than conversion rate
			 * allows
			 */
			if (cmd->scan_begin_src == TRIG_TIMER) {
				err |= comedi_check_trigger_arg_min(
						&cmd->scan_begin_arg,
						cmd->convert_arg *
						cmd->chanlist_len);
			}
		}
	}

	err |= comedi_check_trigger_arg_min(&cmd->chanlist_len, 1);
	err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
					   cmd->chanlist_len);

	switch (cmd->stop_src) {
	case TRIG_EXT:
		break;
	case TRIG_COUNT:
		err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1);
		break;
	case TRIG_NONE:
		err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
		break;
	default:
		break;
	}

	if (err)
		return 3;

	/* step 4: fix up any arguments */

	if (cmd->convert_src == TRIG_TIMER) {
		tmp_arg = cmd->convert_arg;
		tmp_arg2 = cmd->scan_begin_arg;
		check_adc_timing(dev, cmd);
		if (tmp_arg != cmd->convert_arg)
			err++;
		if (tmp_arg2 != cmd->scan_begin_arg)
			err++;
	}

	if (err)
		return 4;

	/* Step 5: check channel list if it exists */
	if (cmd->chanlist && cmd->chanlist_len > 0)
		err |= cb_pcidas64_ai_check_chanlist(dev, s, cmd);

	if (err)
		return 5;

	return 0;
}