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 */
17int
18tcgetattr(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 */
25int
26tcsetattr(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 */
54int
55tcdrain(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 */
68int
69tcflow(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) */
88int
89tcflush(int fd, int queueSelector)
90{
91	return ioctl(fd, TCFLSH, queueSelector);
92}
93
94
95/*! send zero bits for the specified duration */
96int
97tcsendbreak(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
105speed_t
106cfgetispeed(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
115int
116cfsetispeed(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
134speed_t
135cfgetospeed(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
144int
145cfsetospeed(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
160void
161cfmakeraw(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
174pid_t
175tcgetsid(int fd)
176{
177	int sid;
178
179	if (ioctl(fd, TIOCGSID, &sid) == 0)
180		return sid;
181
182	return -1;
183}
184
185
186int
187tcsetsid(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