1 /* 2 * Copyright 2004-2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved. 3 * Copyright 2003, Daniel Reinhold, danielre@users.sf.net. All rights reserved. 4 * 5 * Distributed under the terms of the MIT License. 6 */ 7 8 9 #include <termios.h> 10 #include <unistd.h> 11 #include <errno.h> 12 13 #include <errno_private.h> 14 15 16 /*! get the attributes of the TTY device at fd */ 17 int 18 tcgetattr(int fd, struct termios *termios) 19 { 20 return ioctl(fd, TCGETA, termios); 21 } 22 23 24 /*! set the attributes for the TTY device at fd */ 25 int 26 tcsetattr(int fd, int opt, const struct termios *termios) 27 { 28 int method; 29 30 switch (opt) { 31 case TCSANOW: 32 // set the attributes immediately 33 method = TCSETA; 34 break; 35 case TCSADRAIN: 36 // wait for ouput to finish before setting the attributes 37 method = TCSETAW; 38 break; 39 case TCSAFLUSH: 40 method = TCSETAF; 41 break; 42 43 default: 44 // no other valid options 45 __set_errno(EINVAL); 46 return -1; 47 } 48 49 return ioctl(fd, method, termios); 50 } 51 52 53 /*! wait for all output to be transmitted */ 54 int 55 tcdrain(int fd) 56 { 57 /* Some termios implementations have a TIOCDRAIN command 58 * expressly for this purpose (e.g. ioctl(fd, TIOCDRAIN, 0). 59 * However, the BeOS implementation adheres to another 60 * interface which uses a non-zero last parameter to the 61 * TCSBRK ioctl to signify this functionality. 62 */ 63 return ioctl(fd, TCSBRK, 1); 64 } 65 66 67 /*! suspend or restart transmission */ 68 int 69 tcflow(int fd, int action) 70 { 71 switch (action) { 72 case TCIOFF: 73 case TCION: 74 case TCOOFF: 75 case TCOON: 76 break; 77 78 default: 79 __set_errno(EINVAL); 80 return -1; 81 } 82 83 return ioctl(fd, TCXONC, action); 84 } 85 86 87 /*! flush all pending data (input or output) */ 88 int 89 tcflush(int fd, int queueSelector) 90 { 91 return ioctl(fd, TCFLSH, queueSelector); 92 } 93 94 95 /*! send zero bits for the specified duration */ 96 int 97 tcsendbreak(int fd, int duration) 98 { 99 // Posix spec says this should take ~ 0.25 to 0.5 seconds. 100 // As the interpretation of the duration is undefined, we'll just ignore it 101 return ioctl(fd, TCSBRK, 0); 102 } 103 104 105 speed_t 106 cfgetispeed(const struct termios *termios) 107 { 108 if ((termios->c_cflag & CBAUD) == CBAUD) 109 return termios->c_ispeed; 110 111 return termios->c_cflag & CBAUD; 112 } 113 114 115 int 116 cfsetispeed(struct termios *termios, speed_t speed) 117 { 118 /* Check for custom baudrates, which must be stored in the c_ispeed 119 field instead of inlined in the flags. 120 Note that errors from hardware device (unsupported baudrates, etc) are 121 detected only when the tcsetattr() function is called */ 122 if (speed > B31250) { 123 termios->c_cflag |= CBAUD; 124 termios->c_ispeed = speed; 125 return 0; 126 } 127 128 termios->c_cflag &= ~CBAUD; 129 termios->c_cflag |= speed; 130 return 0; 131 } 132 133 134 speed_t 135 cfgetospeed(const struct termios *termios) 136 { 137 if ((termios->c_cflag & CBAUD) == CBAUD) 138 return termios->c_ospeed; 139 140 return termios->c_cflag & CBAUD; 141 } 142 143 144 int 145 cfsetospeed(struct termios *termios, speed_t speed) 146 { 147 /* Check for custom speed values (see above) */ 148 if (speed > B31250) { 149 termios->c_cflag |= CBAUD; 150 termios->c_ospeed = speed; 151 return 0; 152 } 153 154 termios->c_cflag &= ~CBAUD; 155 termios->c_cflag |= speed; 156 return 0; 157 } 158 159 160 void 161 cfmakeraw(struct termios *termios) 162 { 163 termios->c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR 164 | ICRNL | IXON); 165 termios->c_oflag &= ~OPOST; 166 termios->c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN); 167 termios->c_cflag &= ~(CSIZE | PARENB); 168 termios->c_cflag |= CS8; 169 termios->c_cc[VMIN] = 1; // input is available character by character 170 termios->c_cc[VTIME] = 0; 171 } 172 173 174 pid_t 175 tcgetsid(int fd) 176 { 177 int sid; 178 179 if (ioctl(fd, TIOCGSID, &sid) == 0) 180 return sid; 181 182 return -1; 183 } 184 185 186 int 187 tcsetsid(int fd, pid_t pid) 188 { 189 if (pid != getsid(0)) { 190 errno = EINVAL; 191 return -1; 192 } 193 194 return ioctl(fd, TIOCSCTTY, NULL); 195 } 196 197 198 int 199 tcgetwinsize(int fd, struct winsize* winsize) 200 { 201 return ioctl(fd, TIOCGWINSZ, winsize, sizeof(*winsize)); 202 } 203 204 205 int 206 tcsetwinsize(int fd, const struct winsize* winsize) 207 { 208 return ioctl(fd, TIOCSWINSZ, winsize, sizeof(*winsize)); 209 } 210