|
|
- #include <stdio.h> /* Standard input/output definitions */
- #include <stdlib.h>
- #include <stdint.h> /* Standard types */
- #include <string.h> /* String function definitions */
- #include <unistd.h> /* UNIX standard function definitions */
- #include <fcntl.h> /* File control definitions */
- #include <errno.h> /* Error number definitions */
- #include <termios.h> /* POSIX terminal control definitions */
- #include <sys/ioctl.h>
-
-
- #ifdef __APPLE__
- // define 460k baud rate, seems not to be available in headers on osx
- #define B460800 460800
- #endif
-
-
- void help(void);
- int serialport_init(const char* serialport, unsigned int baud);
- int serialport_read_until(int fd, unsigned int until);
-
-
- // Checks for an argument (characters with a leading '-')
- // Returns 0 if argument does not exist or the index of argument
- // type in the argv[] array
- int parArgTypExists (int argc, char *argv[], char argType)
- {
- char tmp[3];
-
- tmp[0] = '-';
- tmp[1] = argType;
- tmp[2] = 0;
-
- if (argc > 1) {
- for (int i = 1; i < argc; i++) {
- if (!strcmp (argv[i], tmp))
- return i;
- }
- }
- return 0;
- }
-
-
- // Get string argument value
- // Returns 0 in error case, returns 1 if OK
- // (string is limited to max. 4096 characters)
- int parGetString (int argc, char *argv[], char argType, char *value)
- {
- int a = parArgTypExists(argc, argv, argType);
-
- // Check for errors
- if (a == 0) return 0;
- if (a >= (argc -1)) return 0;
- if (strlen(argv[a+1]) > 256) return 0;
-
- strcpy(value, argv[a+1]);
- return 1;
- }
-
-
- // Get unsigned int argument value
- // Returns 0 in error case, 1 if OK
- int parGetUnsignedInt (int argc, char *argv[], char argType,
- unsigned int *value)
- {
- int a = parArgTypExists (argc, argv, argType);
-
- /* error checking */
- if (a == 0) return 0;
- if (a >= (argc -1)) return 0;
-
- a = sscanf(argv[a+1], "%iu", value);
-
- return a;
- }
-
-
- void help(void) {
- printf("Usage: uart_trng -p <serialport> [OPTIONS]\n"
- "\n"
- "Options:\n"
- " -h, --help Print this help message\n"
- " -p, --port=serialport Serial port where the uart_trng device is plugged on\n"
- " -b, --baud=baudrate Baudrate (bps) of uart_trng device, default = 9600\n"
- " -s, --size number of bytes to receive from uart_trng device,\n"
- " 0 for reading until break with Ctrl-c, default = 1024\n"
- "\n");
- }
-
-
- int main(int argc, char *argv[])
- {
- int fd = 0;
- int r = 0;
- char serialport[256];
- unsigned int baudrate = 9600;
- unsigned int size = 1024;
-
- // check for command line arguments
- if (argc == 1) {
- help();
- return 1;
- }
- else {
- if (parArgTypExists (argc, argv, 'h')) {
- help();
- return 1;
- }
- // get serial port
- if (parArgTypExists (argc, argv, 'p')) {
- r = parGetString (argc, argv, 'p', serialport);
- if (r == 0) {
- return (1);
- }
- } else {
- help();
- return (1);
- }
- // get baud rate
- if (parArgTypExists (argc, argv, 'b')) {
- r = parGetUnsignedInt (argc, argv, 'b', &baudrate);
- if (r == 0) {
- return (1);
- }
- }
- // get read size in bytes
- if (parArgTypExists (argc, argv, 's')) {
- r = parGetUnsignedInt (argc, argv, 's', &size);
- if (r == 0) {
- return (1);
- }
- }
- }
-
- fd = serialport_init(serialport, baudrate);
- if (fd == -1)
- return -1;
- serialport_read_until(fd, size);
-
- exit(EXIT_SUCCESS);
- }
-
-
- int serialport_read_until(int fd, unsigned int until)
- {
- char b[1];
- int index = 0;
- int n;
- while (1) {
- while (1) {
- // read one char
- n = read(fd, b, 1);
- // we had a read error
- // check if there were no bytes to read or if it was a real error
- if (n == -1) {
- if (errno != EAGAIN) {
- fprintf(stderr,"serial read error at byte %d", index);
- return -1;
- }
- } else {
- break;
- }
- }
- // we got no byte, so wait 10 ms for the next try
- if (n == 0) {
- usleep (10 * 1000);
- continue;
- }
- printf("%c",b[0]);
- if (until == 0) {
- continue;
- } else {
- index++;
- if (index == until) {
- break;
- }
- }
- };
-
- fprintf(stderr,"uart_trng: read %d random bytes from device\n", until);
- return 0;
- }
-
-
- // takes the string name of the serial port (e.g. "/dev/tty.usbserial","COM1")
- // and a baud rate (bps) and connects to that port at that speed and 8N1.
- // opens the port in fully raw mode so you can send binary data.
- // returns valid fd, or -1 on error
- int serialport_init(const char* serialport, unsigned int baud)
- {
- struct termios toptions;
- int fd;
-
- fprintf(stderr,"init_serialport: opening port %s @ %u bps\n",
- serialport, baud);
-
- fd = open(serialport, O_RDWR | O_NOCTTY | O_NDELAY);
- if (fd == -1) {
- perror("init_serialport: Unable to open port ");
- return -1;
- }
-
- if (tcgetattr(fd, &toptions) < 0) {
- perror("init_serialport: Couldn't get term attributes");
- return -1;
- }
- speed_t brate = baud; // let you override switch below if needed
- switch(baud) {
- case 4800: brate=B4800; break;
- case 9600: brate=B9600; break;
- #ifdef B14400
- case 14400: brate=B14400; break;
- #endif
- case 19200: brate=B19200; break;
- #ifdef B28800
- case 28800: brate=B28800; break;
- #endif
- case 38400: brate=B38400; break;
- case 57600: brate=B57600; break;
- case 115200: brate=B115200; break;
- case 230400: brate=B230400; break;
- case 460800: brate=B460800; break;
- }
- cfsetispeed(&toptions, brate);
- cfsetospeed(&toptions, brate);
-
- // 8N1
- toptions.c_cflag &= ~PARENB;
- toptions.c_cflag &= ~CSTOPB;
- toptions.c_cflag &= ~CSIZE;
- toptions.c_cflag |= CS8;
- // no flow control
- toptions.c_cflag &= ~CRTSCTS;
-
- toptions.c_cflag |= CREAD | CLOCAL; // turn on READ & ignore ctrl lines
- toptions.c_iflag &= ~(IXON | IXOFF | IXANY); // turn off s/w flow ctrl
-
- toptions.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); // make raw
- toptions.c_oflag &= ~OPOST; // make raw
-
- // see: http://unixwiz.net/techtips/termios-vmin-vtime.html
- toptions.c_cc[VMIN] = 0;
- toptions.c_cc[VTIME] = 20;
-
- if( tcsetattr(fd, TCSANOW, &toptions) < 0) {
- perror("init_serialport: Couldn't set term attributes");
- return -1;
- }
-
- return fd;
- }
-
|