Example #1
0
int main(int argc, char *argv[])
{
	int ret = 0, len, ofs;
	unsigned int i, scan_size = 0, cnt = 0;
	unsigned long buf_size;
	void *map = NULL;
	a4l_desc_t dsc = { .sbdata = NULL };

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

	/* Compute arguments */
	while ((ret = getopt_long(argc,
				  argv,
				  "vrd:s:S:c:mwk:h", 
				  cmd_read_opts, NULL)) >= 0) {
		switch (ret) {
		case 'v':
			verbose = 1;
			break;
		case 'r':
			real_time = 1;
			break;
		case 'd':
			filename = optarg;
			break;
		case 's':
			cmd.idx_subd = strtoul(optarg, NULL, 0);
			break;
		case 'S':
			cmd.stop_arg = strtoul(optarg, NULL, 0);
			break;
		case 'c':
			str_chans = optarg;
			break;
		case 'm':
			use_mmap = 1;
			break;
		case 'w':
			dump_function = dump_raw;
			break;
		case 'k':
			wake_count = strtoul(optarg, NULL, 0);
			break;
		case 'h':
		default:
			do_print_usage();
			return 0;
		}
	}

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

	/* Recover the channels to compute */
	do {
		cmd.nb_chan++;
		len = strlen(str_chans);
		ofs = strcspn(str_chans, ",");
		if (sscanf(str_chans, "%u", &chans[cmd.nb_chan - 1]) == 0) {
			fprintf(stderr, "cmd_read: bad channel argument\n");
			return -EINVAL;
		}
		str_chans += ofs + 1;
	} while (len != ofs);

	/* Update the command structure */
	cmd.scan_end_arg = cmd.nb_chan;
	cmd.stop_src = cmd.stop_arg != 0 ? TRIG_COUNT : TRIG_NONE;

	if (real_time != 0) {

		if (verbose != 0)
			printf("cmd_read: switching to real-time mode\n");

		/* Prevent any memory-swapping for this program */
		ret = mlockall(MCL_CURRENT | MCL_FUTURE);
		if (ret < 0) {
			ret = errno;
			fprintf(stderr, "cmd_read: mlockall failed (ret=%d)\n",
				ret);
			goto out_main;
		}

		/* Turn the current process into an RT task */
		ret = rt_task_shadow(&rt_task_desc, NULL, 1, 0);
		if (ret < 0) {
			fprintf(stderr,
				"cmd_read: rt_task_shadow failed (ret=%d)\n",
				ret);
			goto out_main;
		}
	}

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

	if (verbose != 0) {
		printf("cmd_read: device %s opened (fd=%d)\n",
		       filename, dsc.fd);
		printf("cmd_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) {
		fprintf(stderr, "cmd_read: malloc failed \n");
		return -ENOMEM;
	}

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

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

	/* Get the size of a single acquisition */
	for (i = 0; i < cmd.nb_chan; i++) {
		a4l_chinfo_t *info;

		ret = a4l_get_chinfo(&dsc,
				     cmd.idx_subd, cmd.chan_descs[i], &info);
		if (ret < 0) {
			fprintf(stderr,
				"cmd_read: a4l_get_chinfo failed (ret=%d)\n",
				ret);
			goto out_main;
		}

		if (verbose != 0) {
			printf("cmd_read: channel %x\n", cmd.chan_descs[i]);
			printf("\t ranges count = %d\n", info->nb_rng);
			printf("\t bit width = %d (bits)\n", info->nb_bits);
		}

		scan_size += a4l_sizeof_chan(info);
	}

	if (verbose != 0) {
		printf("cmd_read: scan size = %u\n", scan_size);
		if (cmd.stop_arg != 0)
			printf("cmd_read: size to read = %u\n",
			       scan_size * cmd.stop_arg);
	}

	/* Cancel any former command which might be in progress */
	a4l_snd_cancel(&dsc, cmd.idx_subd);

	if (use_mmap != 0) {

		/* Get the buffer size to map */
		ret = a4l_get_bufsize(&dsc, cmd.idx_subd, &buf_size);
		if (ret < 0) {
			fprintf(stderr,
				"cmd_read: a4l_get_bufsize() failed (ret=%d)\n",
				ret);
			goto out_main;
		}

		if (verbose != 0)
			printf("cmd_read: buffer size = %lu bytes\n", buf_size);

		/* Map the analog input subdevice buffer */
		ret = a4l_mmap(&dsc, cmd.idx_subd, buf_size, &map);
		if (ret < 0) {
			fprintf(stderr,
				"cmd_read: a4l_mmap() failed (ret=%d)\n",
				ret);
			goto out_main;
		}

		if (verbose != 0)
			printf
				("cmd_read: mmap performed successfully (map=0x%p)\n",
				 map);
	}

	ret = a4l_set_wakesize(&dsc, wake_count);
	if (ret < 0) {
		fprintf(stderr,
			"cmd_read: a4l_set_wakesize failed (ret=%d)\n", ret);
		goto out_main;
	}

	if (verbose != 0)
		printf("cmd_read: wake size successfully set (%lu)\n", 
		       wake_count);

	/* Send the command to the input device */
	ret = a4l_snd_command(&dsc, &cmd);
	if (ret < 0) {
		fprintf(stderr,
			"cmd_read: a4l_snd_command failed (ret=%d)\n", ret);
		goto out_main;
	}

	if (verbose != 0)
		printf("cmd_read: command successfully sent\n");

	if (use_mmap == 0) {

		/* Fetch data */
		do {
			/* Perform the read operation */
			ret = a4l_async_read(&dsc, buf, BUF_SIZE, A4L_INFINITE);
			if (ret < 0) {
				fprintf(stderr,
					"cmd_read: a4l_read failed (ret=%d)\n",
					ret);
				goto out_main;
			}

			/* Display the results */
			if (dump_function(&dsc, &cmd, buf, ret) < 0) {
				ret = -EIO;
				goto out_main;
			}

			/* Update the counter */
			cnt += ret;

		} while (ret > 0);

	} else {
		unsigned long front = 0;

		/* Fetch data without any memcpy */
		do {

			/* Retrieve and update the buffer's state
			   (In input case, we recover how many bytes are available
			   to read) */
			ret = a4l_mark_bufrw(&dsc, cmd.idx_subd, front, &front);
			if (ret == -ENOENT)
				break;
			else if (ret < 0) {
				fprintf(stderr,
					"cmd_read: a4l_mark_bufrw() failed (ret=%d)\n",
					ret);
				goto out_main;
			}

			/* If there is nothing to read, wait for an event
			   (Note that a4l_poll() also retrieves the data amount
			   to read; in our case it is useless as we have to update
			   the data read counter) */
			if (front == 0) {
				ret = a4l_poll(&dsc, cmd.idx_subd, A4L_INFINITE);
				if (ret == 0)
					break;
				else if (ret < 0) {
					fprintf(stderr,
						"cmd_read: a4l_poll() failed (ret=%d)\n",
						ret);
					goto out_main;
				}
			}

			/* Display the results */
			if (dump_function(&dsc,
					  &cmd,
					  &((unsigned char *)map)[cnt % buf_size],
					  front) < 0) {
				ret = -EIO;
				goto out_main;
			}

			/* Update the counter */
			cnt += front;

		} while (1);
	}

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

	ret = 0;

out_main:

	if (use_mmap != 0)
		/* Clean the pages table */
		munmap(map, buf_size);

	/* Free the buffer used as device descriptor */
	if (dsc.sbdata != NULL)
		free(dsc.sbdata);

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

	return ret;
}
Example #2
0
/*!*****************************************************************************
*******************************************************************************
\note  dio32_NI6259_write_cmd_buffer
\date  Jan. 2011

\remarks

Uses the cmd structure to write a command buffer to the DIO device
at very high communication rate. This function with the abort statement
at the end is still experimental and is not really used so far.

*******************************************************************************
Function Parameters: [in]=input,[out]=output

\param[in]     buf  : the command buffer
\param[in]     n_buf: number of elements to write

******************************************************************************/
int
dio32_NI6259_write_cmd_buffer(int *buf, int n_buf)
{
  int i,j,rc;
  static unsigned long buf_size;
  unsigned long buf_left;
  static int *map = NULL;

  static int firsttime = TRUE;

  unsigned int chans[32]={
    0,1,2,3,4,5,6,7,
    8,9,10,11,12,13,14,15,
    16,17,18,19,20,21,22,23,
    24,25,26,27,28,29,30,31};

  a4l_cmd_t cmd = {
    .idx_subd = SUBDEV_DIO,
    .flags = 0,
    .start_src = TRIG_INT,    // internal trigger
    .start_arg = 0,
    .scan_begin_src = TRIG_EXT,
    .scan_begin_arg = NI_CDIO_SCAN_BEGIN_SRC_G0_OUT, // channel used to trigger the scans
    .convert_src = TRIG_NOW,
    .convert_arg = 0, /* in ns */
    .scan_end_src = TRIG_COUNT,
    .scan_end_arg = 32,
    .stop_src = TRIG_NONE,
    .stop_arg = 0,
    .nb_chan = 32,
    .chan_descs = chans,
  };

  a4l_insn_t insn = {
    .type = A4L_INSN_INTTRIG,
    .idx_subd = SUBDEV_DIO,
    .data_size = 0,
  };


  if (firsttime) {
    firsttime = FALSE;

    // map the communication buffer to user space

    // Get the buffer size to map
    rc = a4l_get_bufsize(&desc, SUBDEV_DIO, &buf_size);
    if (rc < 0) {
      printf("a4l_get_bufsize() failed (rc=%d)\n",rc);
      return FALSE;
    }

    // Map the subdevice buffer
    rc = a4l_mmap(&desc, SUBDEV_DIO, buf_size, (void *)&map);
    if (rc < 0) {
      printf("a4l_mmap() failed (rc=%d)\n",rc);
      return FALSE;
    }

  }

  // configure device in write mode
  rc = dio32_NI6259_config(ajcDATAMASK | ajcCTRLMASK,DIO_WRITE);
  if (rc < 0) {
    printf("write_cmd_buffer: dio32_NI6259_config failed (ret=%d)\n", rc);
    return FALSE;
  }

  // send the command
  rc = a4l_snd_command(&desc, &cmd);
  if (rc < 0) {
    printf("write_cmd_buffer: a4l_snd_command failed (ret=%d)\n", rc);
    return FALSE;
  }

  // write buf to the map buffer
  for (i=1; i<=n_buf; ++i)
    map[i-1] = buf[i];

  // tell the device the size of the data
  rc = a4l_mark_bufrw(&desc, SUBDEV_DIO, n_buf*sizeof(int), &buf_left);
  if (rc < 0) {
    printf("a4l_mark_bufrw() failed (rc=%d)\n",rc);
    return FALSE;
  }

  // trigger the communication
  rc = a4l_snd_insn(&desc, &insn);
  if (rc < 0)
    printf("ni_test: triggering failed (rc=%d)\n",rc);

  // check whether the device is busy and wait
  int count_busy = 0;
  const int max_count_busy = 1000;
  while ((rc = a4l_poll(&desc, SUBDEV_DIO, A4L_INFINITE)) > 0) { // wait for completion
    if (++count_busy > max_count_busy) {
      printf("write_cmd_buffer: dio32_NI6259_config too many (%d) EBUSY timeouts\n",
	     max_count_busy);
      return FALSE;
    }
    taskDelay(10000);
  }
  if (rc < 0 && rc!= -EPIPE) {
    printf("a4l_poll() failed (rc=%d)\n",rc);
    return FALSE;
  }

  return TRUE;

}

/*!*****************************************************************************
*******************************************************************************
\note  dio16_NI6259_read
\date  Feb 2010
 
\remarks 

reads from PFI device a 16 bit value with bit mask

*******************************************************************************
Function Parameters: [in]=input,[out]=output
 
\param[in]   mask    : which bits to read
\param[out]  val     : the value read
 
******************************************************************************/
inline int
dio16_NI6259_read(int mask, int *val) 
{
  int i;
  int rc;

  // configure the device to read mode
  for (i=0; i<16; ++i) {
    if ( ((1 << i) & mask) > 0) {
      if (dio16_channel_mode[i] != DIO_READ) {
	rc = a4l_config_subd(&desc,SUBDEV_PFI,A4L_INSN_CONFIG_DIO_INPUT,i);
	if (rc < 0) {
	  printf("dio16_NI6259_read: failed to configure DIO (rc=%d, channel %d)\n",rc,i);
	  return FALSE;
	}
	dio16_channel_mode[i] = DIO_READ;
      }
    }
  }

  // read the value
  rc = a4l_sync_dio(&desc, SUBDEV_PFI, &mask, val);
  if (rc < 0) {
    printf("dio16_NI6259_read: failed to communicate to DIO (rc=%d)\n",rc);
    return FALSE;
  }

  *val = (*val) & mask;

  return TRUE;
}

/*!*****************************************************************************
*******************************************************************************
\note  dio16_NI6259_write
\date  Feb 2010
 
\remarks 

writes to DIO device a 16 bit value with bit mask

*******************************************************************************
Function Parameters: [in]=input,[out]=output
 
\param[in]   mask    : which bits to write
\param[in]   val     : the value to write
 
******************************************************************************/
inline int
dio16_NI6259_write(int mask, int val) 
{
  int i;
  int rc;

  // configure the device channels to read mode if needed
  for (i=0; i<16; ++i) {
    if ( ((1 << i) & mask) > 0) {
      if (dio16_channel_mode[i] != DIO_WRITE) {
	rc = a4l_config_subd(&desc,SUBDEV_PFI,A4L_INSN_CONFIG_DIO_OUTPUT,i);
	if (rc < 0) {
	  printf("dio16_NI6259_write: failed to configure DIO (rc=%d, channel %d)\n",rc,i);
	  return FALSE;
	}
	dio16_channel_mode[i] = DIO_WRITE;
      }
    }
  }

  // write the value
  rc = a4l_sync_dio(&desc, SUBDEV_PFI, &mask, &val);
  if (rc < 0) {
    printf("dio16_NI6259_write: failed to communicate to DIO (rc=%d)\n",rc);
    return FALSE;
  }

  return TRUE;
}