rs

FTDI serial communication program
git clone git@git.2f30.org/rs.git
Log | Files | Refs | README | LICENSE

rs.c (3218B)


      1 /* See LICENSE file for copyright and license details. */
      2 #include <errno.h>
      3 #include <stdio.h>
      4 #include <stdlib.h>
      5 #include <termios.h>
      6 #include <unistd.h>
      7 #include <signal.h>
      8 #include <ftdi.h>
      9 #include "util.h"
     10 
     11 static struct ftdi_context ftdictx;
     12 static struct termios tio, savedtio;
     13 
     14 static int bflag = 0;
     15 static int vflag = 0;
     16 static int pflag = 0;
     17 
     18 static sig_atomic_t done = 0;
     19 
     20 static void
     21 interrupt(int sig)
     22 {
     23 	done = 1;
     24 }
     25 
     26 static int
     27 ttyinit(void)
     28 {
     29 	long vdisable;
     30 
     31 	errno = 0;
     32 	vdisable = fpathconf(STDIN_FILENO, _PC_VDISABLE);
     33 	if (vdisable < 0) {
     34 		if (errno)
     35 			eprintf("fpathconf: _PC_VDISABLE:");
     36 		vdisable = 0;
     37 	}
     38 
     39 	tcgetattr(STDIN_FILENO, &tio);
     40 	savedtio = tio;
     41 	cfmakeraw(&tio);
     42 	tio.c_cc[VMIN] = 0;
     43 	tio.c_cc[VTIME] = 0;
     44 	tio.c_lflag |= ISIG;
     45 	tio.c_cc[VQUIT] = CTRL('\\');
     46 	tio.c_cc[VINTR] = vdisable;
     47 	tcsetattr(STDIN_FILENO, TCSAFLUSH, &tio);
     48 	return 0;
     49 }
     50 
     51 static void
     52 ttyrestore(void)
     53 {
     54 	tcsetattr(STDIN_FILENO, TCSAFLUSH, &savedtio);
     55 }
     56 
     57 static int
     58 txrxloop(void)
     59 {
     60 	unsigned char buf[1];
     61 	ssize_t n = 0;
     62 
     63 	while (!done) {
     64 		n = read(STDIN_FILENO, buf, sizeof(buf));
     65 		if (n < 0 && errno == EINTR)
     66 			continue;
     67 		if (n > 0) {
     68 			n = ftdi_write_data(&ftdictx, buf, n);
     69 			if (n < 0) {
     70 				ttyrestore();
     71 				enprintf(EXIT_FAILURE, "ftdi_write_data: write error: %s\n",
     72 					 ftdi_get_error_string(&ftdictx));
     73 			}
     74 		}
     75 		n = ftdi_read_data(&ftdictx, buf, sizeof(buf));
     76 		if (n < 0) {
     77 			ttyrestore();
     78 			enprintf(EXIT_FAILURE, "ftdi_read_data: read error: %s\n",
     79 				 ftdi_get_error_string(&ftdictx));
     80 		}
     81 		write(STDOUT_FILENO, buf, n);
     82 	}
     83 	return n;
     84 }
     85 
     86 static void
     87 usage(void)
     88 {
     89 	fprintf(stderr, "usage: %s [ -b baudrate ] [ -v vendorid ] [ -p productid ]\n", argv0);
     90 	fprintf(stderr, "\t-b\tSet baudrate\n");
     91 	fprintf(stderr, "\t-v\tSpecify vendor, defaults to 0x0403\n");
     92 	fprintf(stderr, "\t-p\tSpecify product, defaults to 0x6001\n");
     93 	exit(EXIT_FAILURE);
     94 }
     95 
     96 int
     97 main(int argc, char *argv[])
     98 {
     99 	struct sigaction sa;
    100 	int baudrate = 115200;
    101 	int ret;
    102 	int vendor = 0x0403;
    103 	int product = 0x6001;
    104 
    105 	ARGBEGIN {
    106 	case 'b':
    107 		bflag = 1;
    108 		baudrate = estrtol(EARGF(usage()), 10);
    109 		break;
    110 	case 'v':
    111 		vflag = 1;
    112 		vendor = estrtol(EARGF(usage()), 0);
    113 		break;
    114 	case 'p':
    115 		pflag = 1;
    116 		product = estrtol(EARGF(usage()), 0);
    117 		break;
    118 	default:
    119 		usage();
    120 	} ARGEND;
    121 
    122 	if (!isatty(STDIN_FILENO))
    123 		eprintf("isatty: stdin:");
    124 
    125 	ret = ftdi_init(&ftdictx);
    126 	if (ret < 0)
    127 		enprintf(EXIT_FAILURE, "failed to initialize ftdi context\n");
    128 
    129 	ret = ftdi_set_interface(&ftdictx, INTERFACE_ANY);
    130 	if (ret < 0)
    131 		enprintf(EXIT_FAILURE, "ftdi_set_interface: %s\n",
    132 			 ftdi_get_error_string(&ftdictx));
    133 
    134 	ret = ftdi_usb_open(&ftdictx, vendor, product);
    135 	if (ret < 0)
    136 		enprintf(EXIT_FAILURE, "ftdi_usb_open: %04x:%04x: %s\n",
    137 			 vendor, product, ftdi_get_error_string(&ftdictx));
    138 
    139 	ret = ftdi_set_baudrate(&ftdictx, baudrate);
    140 	if (ret < 0)
    141 		enprintf(EXIT_FAILURE, "ftdi_set_baudrate: %d: %s\n",
    142 			 baudrate, ftdi_get_error_string(&ftdictx));
    143 
    144 	printf("Break key is set to ^\\\n");
    145 
    146 	sa.sa_handler = interrupt;
    147 	sigemptyset(&sa.sa_mask);
    148 	sa.sa_flags = SA_RESTART;
    149 	sigaction(SIGQUIT, &sa, NULL);
    150 
    151 	ttyinit();
    152 	txrxloop();
    153 	ttyrestore();
    154 	putchar('\n');
    155 	ftdi_usb_close(&ftdictx);
    156 	exit(EXIT_SUCCESS);
    157 }