1 #include 2 #include 3 #include 4 #include 5 #include 6 #include 7 #include "dce.h" 8 #include "debug.h" 9 10 #include "serial.h" 11 12 int ser_get_bps_const(int speed) { 13 int bps_rate = 0; 14 15 LOG_ENTER(); 16 17 LOG(LOG_DEBUG,"Checking speed: %d",speed); 18 19 switch (speed) { 20 #if defined (B921600) 21 case 921600: 22 bps_rate = B921600; 23 break; 24 #endif /* B921600 */ 25 #if defined (B460800) 26 case 460800: 27 bps_rate = B460800; 28 break; 29 #endif /* B460800 */ 30 #if defined (B230400) 31 case 230400: 32 bps_rate = B230400; 33 break; 34 #endif /* B230400 */ 35 #if defined (B115200) 36 case 115200: 37 bps_rate = B115200; 38 break; 39 #endif /* B115200 */ 40 #if defined (B57600) 41 case 57600: 42 bps_rate = B57600; 43 break; 44 #endif /* B57600 */ 45 #if defined (B38400) 46 case 38400: 47 bps_rate = B38400; 48 break; 49 #endif /* B38400 */ 50 #if defined (B19200) 51 case 19200: 52 bps_rate = B19200; 53 break; 54 #endif /* B19200 */ 55 #if defined (B9600) 56 case 9600: 57 bps_rate = B9600; 58 break; 59 #endif /* B9600 */ 60 #if defined (B4800) 61 case 4800: 62 bps_rate = B4800; 63 break; 64 #endif /* B4800 */ 65 #if defined (B2400) 66 case 2400: 67 bps_rate = B2400; 68 break; 69 #endif /* B2400 */ 70 #if defined (B1200) 71 case 1200: 72 bps_rate = B1200; 73 break; 74 #endif /* B1200 */ 75 #if defined (B600) 76 case 600: 77 bps_rate = B600; 78 break; 79 #endif /* B600 */ 80 #if defined (B300) 81 case 300: 82 bps_rate = B300; 83 break; 84 #endif /* B300 */ 85 #if defined (B150) 86 case 150: 87 bps_rate = B150; 88 break; 89 #endif /* B150 */ 90 #if defined (B134) 91 case 134: 92 bps_rate = B134; 93 break; 94 #endif /* B134 */ 95 #if defined (B110) 96 case 110: 97 bps_rate = B110; 98 break; 99 #endif /* B110 */ 100 #if defined (B75) 101 case 75: 102 bps_rate = B75; 103 break; 104 #endif /* B75 */ 105 #if defined (B50) 106 case 50: 107 bps_rate = B50; 108 break; 109 #endif /* B50 */ 110 #if defined (B0) 111 case 0: 112 bps_rate = B0; 113 break; 114 #endif /* B0 */ 115 default: 116 ELOG(LOG_FATAL, "Unknown baud rate"); 117 bps_rate = -1; 118 } 119 LOG_EXIT(); 120 return bps_rate; 121 122 } 123 124 int ser_init_conn(char *tty, int speed) { 125 int fd = -1; 126 struct termios tio; 127 int bps_rate = 0; 128 129 LOG_ENTER(); 130 131 bps_rate = ser_get_bps_const(speed); 132 133 if(bps_rate > -1) { 134 /* open the device to be non-blocking (read will return immediatly) */ 135 LOG(LOG_INFO, "Opening serial device %s at speed %d", tty, speed); 136 137 fd = open(tty, O_RDWR | O_NOCTTY | O_NONBLOCK); 138 139 if (fd <0) { 140 ELOG(LOG_FATAL, "TTY %s could not be opened", tty); 141 } else { 142 LOG(LOG_INFO, "Opened serial device %s at speed %d as fd %d", tty, speed, fd); 143 144 /* Make the file descriptor asynchronous (the manual page says only 145 O_APPEND and O_NONBLOCK, will work with F_SETFL...) */ 146 fcntl(fd, F_SETFL, FASYNC); 147 148 if (0 != tcgetattr(fd, &tio)) { 149 ELOG(LOG_FATAL, "Could not get serial port attributes"); 150 return -1; 151 } 152 153 // leave CRTSCTS off when building for Windows on Rapsberry Pi... 154 // https://github.com/driver1998/tcpser 155 #ifdef WIN_RPI 156 tio.c_cflag = CS8 | CLOCAL | CREAD; 157 #else 158 tio.c_cflag = CS8 | CLOCAL | CREAD | CRTSCTS; 159 #endif 160 tio.c_iflag = IGNBRK; 161 tio.c_oflag = 0; 162 tio.c_lflag = 0; 163 cfsetispeed(&tio, bps_rate); 164 cfsetospeed(&tio, bps_rate); 165 166 tio.c_cc[VMIN] = 1; 167 tio.c_cc[VTIME] = 0; 168 169 tcflush(fd, TCIFLUSH); 170 tcsetattr(fd, TCSANOW, &tio); 171 LOG(LOG_INFO, "serial device configured"); 172 } 173 } 174 175 LOG_EXIT(); 176 return fd; 177 } 178 179 int ser_set_flow_control(int fd, int status) { 180 struct termios tio; 181 if(0 != tcgetattr(fd, &tio)) { 182 ELOG(LOG_FATAL, "Could not get serial port attributes"); 183 return -1; 184 } 185 // turn all off. 186 tio.c_cflag &= ~(IXON | IXOFF | CRTSCTS); 187 tio.c_cflag |= status; 188 if(0 != tcsetattr(fd, TCSANOW, &tio)) { 189 ELOG(LOG_FATAL,"Could not set serial port attributes"); 190 return -1; 191 } 192 return 0; 193 } 194 195 int ser_get_control_lines(int fd) { 196 int status; 197 198 if(0 > ioctl(fd, TIOCMGET, &status)) { 199 ELOG(LOG_FATAL, "Could not obtain serial port status"); 200 return -1; 201 } 202 203 return (DCE_CL_LE // RS232 link is always up. 204 | ((status & TIOCM_DSR) ? DCE_CL_DTR : 0) 205 //| ((status & TIOCM_CTS) ? DCE_CL_RTS : 0) 206 ); 207 } 208 209 int ser_set_control_lines(int fd, int state) { 210 int status; 211 212 if(0 > ioctl(fd, TIOCMGET, &status)) { 213 ELOG(LOG_FATAL, "Could not obtain serial port status"); 214 return -1; 215 } 216 217 status &= ~(TIOCM_DTR); 218 //status &= ~(TIOCM_RTS | TIOCM_DTR); 219 status |= (state & DCE_CL_DCD ? TIOCM_DTR : 0); 220 //status |= (state & DCE_CL_CTS ? TIOCM_RTS : 0); 221 if(0 > ioctl(fd, TIOCMSET, &status)) { 222 ELOG(LOG_WARN, "Could not set serial port status"); 223 } 224 return 0; 225 } 226 227 int ser_write(int fd, unsigned char* data, int len) { 228 log_trace(TRACE_MODEM_OUT, data, len); 229 return write(fd, data, len); 230 } 231 232 int ser_read(int fd, unsigned char* data, int len) { 233 int res; 234 235 res = read(fd, data, len); 236 log_trace(TRACE_MODEM_IN, data, res); 237 return res; 238 }