示例#1
0
/**
 * @brief Find the must suitable range
 *
 * @param[in] dsc Device descriptor filled by a4l_open() and
 * a4l_fill_desc()
 *
 * @param[in] idx_subd Index of the concerned subdevice
 * @param[in] idx_chan Index of the concerned channel
 * @param[in] unit Unit type used in the range
 * @param[in] min Minimal limit value
 * @param[in] max Maximal limit value
 * @param[out] rng Found range
 *
 * @return The index of the most suitable range on success. Otherwise:
 *
 * - -ENOENT is returned if a suitable range is not found.
 * - -EINVAL is returned if some argument is missing or wrong;
 *    idx_subd, idx_chan and the dsc pointer should be checked; check
 *    also the kernel log ("dmesg"); WARNING: a4l_fill_desc() should
 *    be called before using a4l_find_range()
 *
 */
int a4l_find_range(a4l_desc_t * dsc,
		   unsigned int idx_subd,
		   unsigned int idx_chan,
		   unsigned long unit,
		   double min, double max, a4l_rnginfo_t ** rng)
{
	int i, ret;
	long lmin, lmax;
	a4l_chinfo_t *chinfo;
	a4l_rnginfo_t *rnginfo, *tmp = NULL;
	unsigned int idx_rng = -ENOENT;

	if (rng != NULL)
		*rng = NULL;

	/* Basic checkings */
	if (dsc == NULL)
		return -EINVAL;

	/* a4l_fill_desc() must have been called on this descriptor */
	if (dsc->magic != MAGIC_CPLX_DESC)
		return -EINVAL;

	/* Retrieves the ranges count */
	ret = a4l_get_chinfo(dsc, idx_subd, idx_chan, &chinfo);
	if (ret < 0)
		return ret;

	/* Initializes variables */
	lmin = (long)(min * A4L_RNG_FACTOR);
	lmax = (long)(max * A4L_RNG_FACTOR);

	/* Performs the research */
	for (i = 0; i < chinfo->nb_rng; i++) {

		ret = a4l_get_rnginfo(dsc, idx_subd, idx_chan, i, &rnginfo);
		if (ret < 0)
			return ret;

		if (A4L_RNG_UNIT(rnginfo->flags) == unit &&
		    rnginfo->min <= lmin && rnginfo->max >= lmax) {

			if (tmp != NULL) {
				if (rnginfo->min >= tmp->min &&
				    rnginfo->max <= tmp->max) {
					idx_rng = i;
					tmp = rnginfo;
				}
			} else {
				idx_rng = i;
				tmp = rnginfo;
			}
		}
	}

	if (rng != NULL)
		*rng = tmp;

	return idx_rng;
}
示例#2
0
static int dump_converted(a4l_desc_t *dsc, unsigned char *buf, int size)
{
	int err = 0, width, tmp_size = 0;
	a4l_chinfo_t *chan;
	a4l_rnginfo_t *rng;

	/* Retrieve the channel info */
	err = a4l_get_chinfo(dsc, idx_subd, idx_chan, &chan);
	if (err < 0) {
		fprintf(stderr,
			"insn_read: info for channel %d "
			"on subdevice %d not available (err=%d)\n",
			idx_chan, idx_subd, err);
		goto out;
	}

	/* Retrieve the range info */
	err = a4l_get_rnginfo(dsc, idx_subd, idx_chan, idx_rng, &rng);
	if (err < 0) {
		fprintf(stderr,
			"insn_read: failed to recover range descriptor\n");
		goto out;
	}

	width = a4l_sizeof_chan(chan);
	if (width < 0) {
		fprintf(stderr,
			"insn_read: incoherent info for channel %d\n",
			idx_chan);
		err = width;
		goto out;
	}

	fprintf(stdout, "Non Calibrated values: \n");
	while (size - tmp_size > 0) {
		double values[64];
		int i, tmp_cnt = ((size - tmp_size) / width > 64) ?
			64 : ((size - tmp_size) / width);

		err = a4l_rawtod(chan, rng, values, buf + tmp_size, tmp_cnt);
		if (err < 0)
			goto out;

		for (i = 0; i < tmp_cnt; i++) {
			fprintf(stdout, "%F\n", values[i]);
		}

		tmp_size += tmp_cnt * width;
	}

out:
	return err;
}
示例#3
0
int main(int argc, char *argv[])
{
	int err = 0;
	unsigned int cnt = 0;
	a4l_desc_t dsc = { .sbdata = NULL };
	a4l_sbinfo_t *sbinfo;
	a4l_chinfo_t *chinfo;
	a4l_rnginfo_t *rnginfo;

	int (*dump_function) (a4l_desc_t *, unsigned char *, int) = dump_text;

	/* Compute arguments */
	while ((err = getopt_long(argc,
				  argv,
				  "vrd:s:S:c:R:y:wh", insn_read_opts,
				  NULL)) >= 0) {
		switch (err) {
		case 'v':
			verbose = 1;
			break;
		case 'd':
			filename = optarg;
			break;
		case 's':
			idx_subd = strtoul(optarg, NULL, 0);
			break;
		case 'S':
			scan_size = strtoul(optarg, NULL, 0);
			break;
		case 'c':
			idx_chan = strtoul(optarg, NULL, 0);
			break;
		case 'R':
			idx_rng = strtoul(optarg, NULL, 0);
			dump_function = dump_converted;
			break;
		case 'w':
			dump_function = dump_raw;
			break;
		case 'y':
			dump_function = dump_calibrated;
			calibration_file = optarg;
			break;
		case 'h':
		default:
			do_print_usage();
			return 0;
		}
	}

	if (isatty(STDOUT_FILENO) && dump_function == dump_raw) {
		fprintf(stderr,
			"insn_read: cannot dump raw data on a terminal\n\n");
		return -EINVAL;
	}

	/* Open the device */
	err = a4l_open(&dsc, filename);
	if (err < 0) {
		fprintf(stderr,
			"insn_read: a4l_open %s failed (err=%d)\n",
			filename, err);
		return err;
	}

	if (verbose != 0) {
		printf("insn_read: device %s opened (fd=%d)\n", filename,
		       dsc.fd);
		printf("insn_read: basic descriptor retrieved\n");
		printf("\t subdevices count = %d\n", dsc.nb_subd);
		printf("\t read subdevice index = %d\n", dsc.idx_read_subd);
		printf("\t write subdevice index = %d\n", dsc.idx_write_subd);
	}

	/* Allocate a buffer so as to get more info (subd, chan, rng) */
	dsc.sbdata = malloc(dsc.sbsize);
	if (dsc.sbdata == NULL) {
		err = -ENOMEM;
		fprintf(stderr, "insn_read: info buffer allocation failed\n");
		goto out_insn_read;
	}

	/* Get this data */
	err = a4l_fill_desc(&dsc);
	if (err < 0) {
		fprintf(stderr, "insn_read: a4l_fill_desc failed (err=%d)\n",
			err);
		goto out_insn_read;
	}

	if (verbose != 0)
		printf("insn_read: complex descriptor retrieved\n");

	/* If no subdevice index was set, look for an analog input
	   subdevice */
	if (idx_subd == -1)
		idx_subd = dsc.idx_read_subd;

	if (idx_subd == -1) {
		fprintf(stderr,
			"insn_read: no analog input subdevice available\n");
		err = -EINVAL;
		goto  out_insn_read;
	}

	if (verbose != 0)
		printf("insn_read: selected subdevice index = %d\n", idx_subd);

	/* We must check that the subdevice is really an AI one
	   (in case, the subdevice index was set with the option -s) */
	err = a4l_get_subdinfo(&dsc, idx_subd, &sbinfo);
	if (err < 0) {
		fprintf(stderr,
			"insn_read: get_sbinfo(%d) failed (err = %d)\n",
			idx_subd, err);
		err = -EINVAL;
		goto out_insn_read;
	}

	if ((sbinfo->flags & A4L_SUBD_TYPES) != A4L_SUBD_AI) {
		fprintf(stderr,
			"insn_read: wrong subdevice selected "
			"(not an analog input)\n");
		err = -EINVAL;
		goto out_insn_read;
	}

	if (idx_rng >= 0) {

		err = a4l_get_rnginfo(&dsc,
				      idx_subd, idx_chan, idx_rng, &rnginfo);
		if (err < 0) {
			fprintf(stderr,
				"insn_read: failed to recover range descriptor\n");
			goto out_insn_read;
		}

		if (verbose != 0) {
			printf("insn_read: range descriptor retrieved\n");
			printf("\t min = %ld\n", rnginfo->min);
			printf("\t max = %ld\n", rnginfo->max);
		}
	}

	/* Retrieve the subdevice data size */
	err = a4l_get_chinfo(&dsc, idx_subd, idx_chan, &chinfo);
	if (err < 0) {
		fprintf(stderr,
			"insn_read: info for channel %d on subdevice %d not available (err=%d)\n",
			idx_chan, idx_subd, err);
		goto out_insn_read;
	}

	/* Set the data size to read */
	scan_size *= a4l_sizeof_chan(chinfo);

	if (verbose != 0) {
		printf("insn_read: channel width is %u bits\n",
		       chinfo->nb_bits);
		printf("insn_read: global scan size is %u\n", scan_size);
	}

	while (cnt < scan_size) {
		int tmp = (scan_size - cnt) < BUF_SIZE ?
			(scan_size - cnt) : BUF_SIZE;

		/* Perform the synchronous read */
		err = a4l_sync_read(&dsc,
				    idx_subd, CHAN(idx_chan), 0, buf, tmp);

		if (err < 0) {
			fprintf(stderr,
				"insn_read: a4l_sync_read failed (err=%d)\n",
				err);
			goto out_insn_read;
		}

		/* Dump the read data */
		tmp = dump_function(&dsc, buf, err);
		if (tmp < 0) {
			err = tmp;
			goto out_insn_read;
		}

		/* Update the count */
		cnt += err;
	}

	if (verbose != 0)
		printf("insn_read: %u bytes successfully received\n", cnt);

	err = 0;

out_insn_read:

	/* Free the information buffer */
	if (dsc.sbdata != NULL)
		free(dsc.sbdata);

	/* Release the file descriptor */
	a4l_close(&dsc);

	return err;
}
示例#4
0
static int dump_calibrated(a4l_desc_t *dsc, unsigned char *buf, int size)
{
	struct a4l_calibration_data cal_info;
	struct a4l_polynomial converter;
	int err = 0, width, tmp_size = 0;
	a4l_chinfo_t *chan;
	a4l_rnginfo_t *rng;


	/* Retrieve the channel info */
	err = a4l_get_chinfo(dsc, idx_subd, idx_chan, &chan);
	if (err < 0) {
		fprintf(stderr,
			"insn_read: info for channel %d "
			"on subdevice %d not available (err=%d)\n",
			idx_chan, idx_subd, err);
		goto out;
	}

	/* Retrieve the range info */
	err = a4l_get_rnginfo(dsc, idx_subd, idx_chan, idx_rng, &rng);
	if (err < 0) {
		fprintf(stderr,
			"insn_read: failed to recover range descriptor\n");
		goto out;
	}

	width = a4l_sizeof_chan(chan);
	if (width < 0) {
		fprintf(stderr,
			"insn_read: incoherent info for channel %d\n",
			idx_chan);
		err = width;
		goto out;
	}

	err = a4l_read_calibration_file(calibration_file, &cal_info);
	if (err < 0) {
		fprintf(stderr,
			"insn_read: error reading the calibration file \n");
		goto out;
	}

	err = a4l_get_softcal_converter(&converter, idx_subd, idx_chan, idx_rng,
		                        &cal_info);
	if (err < 0) {
		fprintf(stderr,
			"insn_read: failed to get the softcal converter  \n");
		goto out;
	}

	fprintf(stdout, "Calibrated values: \n");
	while (size - tmp_size > 0) {
		double values[64];
		int i, tmp_cnt = ((size - tmp_size) / width > 64) ?
			64 : ((size - tmp_size) / width);

		err = a4l_rawtodcal(chan, values, buf + tmp_size, tmp_cnt,
			            &converter);
		if (err < 0)
			goto out;

		for (i = 0; i < tmp_cnt; i++)
			fprintf(stdout, "%F\n", values[i]);

		tmp_size += tmp_cnt * width;
	}

out:
	return err;
}