xref: /haiku/src/system/libroot/posix/termios.c (revision 344ded80d400028c8f561b4b876257b94c12db4a)
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