1 /* 2 * (C) Copyright 2000 3 * Murray Jensen <Murray.Jensen@csiro.au> 4 * 5 * SPDX-License-Identifier: GPL-2.0+ 6 */ 7 8 #include <unistd.h> 9 #include <string.h> 10 #include <fcntl.h> 11 #include <sys/time.h> 12 #include "serial.h" 13 14 #if defined(__sun__) || \ 15 defined(__OpenBSD__) || \ 16 defined(__FreeBSD__) || \ 17 defined(__NetBSD__) || \ 18 defined(__APPLE__) 19 static struct termios tios = { BRKINT, 0, B115200|CS8|CREAD, 0, { 0 } }; 20 #else 21 static struct termios tios = { BRKINT, 0, B115200|CS8|CREAD, 0, 0 }; 22 #endif 23 24 static struct speedmap { 25 char *str; 26 speed_t val; 27 } speedmap[] = { 28 { "50", B50 }, { "75", B75 }, { "110", B110 }, 29 { "134", B134 }, { "150", B150 }, { "200", B200 }, 30 { "300", B300 }, { "600", B600 }, { "1200", B1200 }, 31 { "1800", B1800 }, { "2400", B2400 }, { "4800", B4800 }, 32 { "9600", B9600 }, { "19200", B19200 }, { "38400", B38400 }, 33 { "57600", B57600 }, 34 #ifdef B76800 35 { "76800", B76800 }, 36 #endif 37 { "115200", B115200 }, 38 #ifdef B153600 39 { "153600", B153600 }, 40 #endif 41 { "230400", B230400 }, 42 #ifdef B307200 43 { "307200", B307200 }, 44 #endif 45 #ifdef B460800 46 { "460800", B460800 } 47 #endif 48 }; 49 static int nspeeds = sizeof speedmap / sizeof speedmap[0]; 50 51 speed_t 52 cvtspeed(char *str) 53 { 54 struct speedmap *smp = speedmap, *esmp = &speedmap[nspeeds]; 55 56 while (smp < esmp) { 57 if (strcmp(str, smp->str) == 0) 58 return (smp->val); 59 smp++; 60 } 61 return B0; 62 } 63 64 int 65 serialopen(char *device, speed_t speed) 66 { 67 int fd; 68 69 if (cfsetospeed(&tios, speed) < 0) 70 return -1; 71 72 if ((fd = open(device, O_RDWR)) < 0) 73 return -1; 74 75 if (tcsetattr(fd, TCSAFLUSH, &tios) < 0) { 76 (void)close(fd); 77 return -1; 78 } 79 80 return fd; 81 } 82 83 int 84 serialreadchar(int fd, int timeout) 85 { 86 fd_set fds; 87 struct timeval tv; 88 int n; 89 char ch; 90 91 tv.tv_sec = timeout; 92 tv.tv_usec = 0; 93 94 FD_ZERO(&fds); 95 FD_SET(fd, &fds); 96 97 /* this is a fucking horrible quick hack - fix this */ 98 99 if ((n = select(fd + 1, &fds, 0, 0, &tv)) < 0) 100 return SERIAL_ERROR; 101 102 if (n == 0) 103 return SERIAL_TIMEOUT; 104 105 if ((n = read(fd, &ch, 1)) < 0) 106 return SERIAL_ERROR; 107 108 if (n == 0) 109 return SERIAL_EOF; 110 111 return ch; 112 } 113 114 int 115 serialwrite(int fd, char *buf, int len) 116 { 117 int n; 118 119 do { 120 n = write(fd, buf, len); 121 if (n < 0) 122 return 1; 123 len -= n; 124 buf += n; 125 } while (len > 0); 126 return 0; 127 } 128 129 int 130 serialclose(int fd) 131 { 132 return close(fd); 133 } 134