xref: /haiku/src/system/libroot/posix/termios.c (revision 2b76973fa2401f7a5edf68e6470f3d3210cbcff3)
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 	return termios->c_cflag & CBAUD;
109 }
110 
111 
112 int
113 cfsetispeed(struct termios *termios, speed_t speed)
114 {
115 	/*	Check for values that the system cannot handle:
116 	greater values than B230400 which is
117 	the maximum value defined in termios.h
118 	Note that errors from hardware device are detected only
119 	until the tcsetattr() function is called */
120 	if (speed > B230400 || (speed & CBAUD) != speed) {
121 		__set_errno(EINVAL);
122 		return -1;
123 	}
124 
125 	termios->c_cflag &= ~CBAUD;
126 	termios->c_cflag |= speed;
127 	return 0;
128 }
129 
130 
131 speed_t
132 cfgetospeed(const struct termios *termios)
133 {
134 	return termios->c_cflag & CBAUD;
135 }
136 
137 
138 int
139 cfsetospeed(struct termios *termios, speed_t speed)
140 {
141 	/* Check for unaccepted speed values (see above) */
142 	if (speed > B230400 || (speed & CBAUD) != speed) {
143 		__set_errno(EINVAL);
144 		return -1;
145 	}
146 
147 	termios->c_cflag &= ~CBAUD;
148 	termios->c_cflag |= speed;
149 	return 0;
150 }
151 
152 
153 void
154 cfmakeraw(struct termios *termios)
155 {
156 	termios->c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR
157 		| ICRNL | IXON);
158 	termios->c_oflag &= ~OPOST;
159 	termios->c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
160 	termios->c_cflag &= ~(CSIZE | PARENB);
161 	termios->c_cflag |= CS8;
162 }
163