xref: /haiku/src/system/libroot/posix/termios.c (revision 7749d0bb0c358a3279b1b9cc76d8376e900130a5)
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 
14 /*! get the attributes of the TTY device at fd */
15 int
16 tcgetattr(int fd, struct termios *termios)
17 {
18 	return ioctl(fd, TCGETA, termios);
19 }
20 
21 
22 /*! set the attributes for the TTY device at fd */
23 int
24 tcsetattr(int fd, int opt, const struct termios *termios)
25 {
26 	int method;
27 
28 	switch (opt) {
29 		case TCSANOW:
30 			// set the attributes immediately
31 			method = TCSETA;
32 			break;
33 		case TCSADRAIN:
34 			// wait for ouput to finish before setting the attributes
35 			method = TCSETAW;
36 			break;
37 		case TCSAFLUSH:
38 			method = TCSETAF;
39 			break;
40 
41 		default:
42 			// no other valid options
43 			errno = EINVAL;
44 			return -1;
45 	}
46 
47 	return ioctl(fd, method, termios);
48 }
49 
50 
51 /*! wait for all output to be transmitted */
52 int
53 tcdrain(int fd)
54 {
55 	/* Some termios implementations have a TIOCDRAIN command
56 	 * expressly for this purpose (e.g. ioctl(fd, TIOCDRAIN, 0).
57 	 * However, the BeOS implementation adheres to another
58 	 * interface which uses a non-zero last parameter to the
59 	 * TCSBRK ioctl to signify this functionality.
60 	 */
61 	return ioctl(fd, TCSBRK, 1);
62 }
63 
64 
65 /*! suspend or restart transmission */
66 int
67 tcflow(int fd, int action)
68 {
69 	switch (action) {
70 		case TCIOFF:
71 		case TCION:
72 		case TCOOFF:
73 		case TCOON:
74 			break;
75 
76 		default:
77 			errno = EINVAL;
78 			return -1;
79 	}
80 
81 	return ioctl(fd, TCXONC, action);
82 }
83 
84 
85 /*! flush all pending data (input or output) */
86 int
87 tcflush(int fd, int queueSelector)
88 {
89 	return ioctl(fd, TCFLSH, queueSelector);
90 }
91 
92 
93 /*! send zero bits for the specified duration */
94 int
95 tcsendbreak(int fd, int duration)
96 {
97 	// Posix spec says this should take ~ 0.25 to 0.5 seconds.
98 	// As the interpretation of the duration is undefined, we'll just ignore it
99 	return ioctl(fd, TCSBRK, 0);
100 }
101 
102 
103 speed_t
104 cfgetispeed(const struct termios *termios)
105 {
106 	return termios->c_cflag & CBAUD;
107 }
108 
109 
110 int
111 cfsetispeed(struct termios *termios, speed_t speed)
112 {
113 	/*	Check for values that the system cannot handle:
114 	greater values than B230400 which is
115 	the maximum value defined in termios.h
116 	Note that errors from hardware device are detected only
117 	until the tcsetattr() function is called */
118 	if (speed > B230400 || (speed & CBAUD) != speed) {
119 		errno = EINVAL;
120 		return -1;
121 	}
122 
123 	termios->c_cflag &= ~CBAUD;
124 	termios->c_cflag |= speed;
125 	return 0;
126 }
127 
128 
129 speed_t
130 cfgetospeed(const struct termios *termios)
131 {
132 	return termios->c_cflag & CBAUD;
133 }
134 
135 
136 int
137 cfsetospeed(struct termios *termios, speed_t speed)
138 {
139 	/* Check for unaccepted speed values (see above) */
140 	if (speed > B230400 || (speed & CBAUD) != speed) {
141 		errno = EINVAL;
142 		return -1;
143 	}
144 
145 	termios->c_cflag &= ~CBAUD;
146 	termios->c_cflag |= speed;
147 	return 0;
148 }
149 
150 
151 void
152 cfmakeraw(struct termios *termios)
153 {
154 	termios->c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR
155 		| ICRNL | IXON);
156 	termios->c_oflag &= ~OPOST;
157 	termios->c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
158 	termios->c_cflag &= ~(CSIZE | PARENB);
159 	termios->c_cflag |= CS8;
160 }
161