3 * Copyright 2019 AT&T Intellectual Property
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
21 // arduino-serial-lib -- simple library for reading/writing serial ports
23 // 2006-2013, Tod E. Kurt, http://todbot.com/blog/
26 #include "arduino-serial-lib.h"
28 #include <stdio.h> // Standard input/output definitions
29 #include <unistd.h> // UNIX standard function definitions
30 #include <fcntl.h> // File control definitions
31 #include <errno.h> // Error number definitions
32 #include <termios.h> // POSIX terminal control definitions
33 #include <string.h> // String function definitions
34 #include <sys/ioctl.h>
36 // uncomment this to debug reads
37 //#define SERIALPORTDEBUG
39 // takes the string name of the serial port (e.g. "/dev/tty.usbserial","COM1")
40 // and a baud rate (bps) and connects to that port at that speed and 8N1.
41 // opens the port in fully raw mode so you can send binary data.
42 // returns valid fd, or -1 on error
43 int serialport_init(const char* serialport, int baud)
45 struct termios toptions;
48 //fd = open(serialport, O_RDWR | O_NOCTTY | O_NDELAY);
49 fd = open(serialport, O_RDWR | O_NONBLOCK );
52 perror("serialport_init: Unable to open port s");
56 //int iflags = TIOCM_DTR;
57 //ioctl(fd, TIOCMBIS, &iflags); // turn on DTR
58 //ioctl(fd, TIOCMBIC, &iflags); // turn off DTR
60 if (tcgetattr(fd, &toptions) < 0) {
61 perror("serialport_init: Couldn't get term attributes");
64 speed_t brate = baud; // let you override switch below if needed
67 case 4800: brate=B4800; break;
68 case 9600: brate=B9600; break;
70 case 14400: brate=B14400; break;
72 case 19200: brate=B19200; break;
74 case 28800: brate=B28800; break;
76 case 38400: brate=B38400; break;
77 case 57600: brate=B57600; break;
78 case 115200: brate=B115200; break;
80 cfsetispeed(&toptions, brate);
81 cfsetospeed(&toptions, brate);
84 toptions.c_cflag &= ~PARENB;
85 toptions.c_cflag &= ~CSTOPB;
86 toptions.c_cflag &= ~CSIZE;
87 toptions.c_cflag |= CS8;
89 toptions.c_cflag &= ~CRTSCTS;
91 //toptions.c_cflag &= ~HUPCL; // disable hang-up-on-close to avoid reset
93 toptions.c_cflag |= CREAD | CLOCAL; // turn on READ & ignore ctrl lines
94 toptions.c_iflag &= ~(IXON | IXOFF | IXANY); // turn off s/w flow ctrl
96 toptions.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); // make raw
97 toptions.c_oflag &= ~OPOST; // make raw
99 // see: http://unixwiz.net/techtips/termios-vmin-vtime.html
100 toptions.c_cc[VMIN] = 0;
101 toptions.c_cc[VTIME] = 0;
102 //toptions.c_cc[VTIME] = 20;
104 tcsetattr(fd, TCSANOW, &toptions);
105 if( tcsetattr(fd, TCSAFLUSH, &toptions) < 0) {
106 perror("init_serialport: Couldn't set term attributes");
114 int serialport_close( int fd )
120 int serialport_writebyte( int fd, uint8_t b)
122 int n = write(fd,&b,1);
129 int serialport_write(int fd, const char* str)
131 int len = strlen(str);
132 int n = write(fd, str, len);
134 perror("serialport_write: couldn't write whole string\n");
141 int serialport_read_until(int fd, char* buf, char until, int buf_max, int timeout)
143 char b[1]; // read expects an array, so we give it a 1-byte array
146 int n = read(fd, b, 1); // read a char at a time
147 if( n==-1) return -1; // couldn't read
149 usleep( 1 * 1000 ); // wait 1 msec try again
151 if( timeout==0 ) return -2;
154 #ifdef SERIALPORTDEBUG
155 fprintf(stderr, "serialport_read_until: i=%d, n=%d b='%c'\n",i,n,b[0]); // debug
159 } while( b[0] != until && i < buf_max && timeout>0 );
161 buf[i] = 0; // null terminate the string
166 int serialport_flush(int fd)
168 sleep(2); //required to make flush work, for some reason
169 return tcflush(fd, TCIOFLUSH);