Serenity Operating System
1/*
2 * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
3 *
4 * SPDX-License-Identifier: BSD-2-Clause
5 */
6
7#include <assert.h>
8#include <bits/pthread_cancel.h>
9#include <errno.h>
10#include <sys/ioctl.h>
11#include <termios.h>
12
13extern "C" {
14
15int tcgetattr(int fd, struct termios* t)
16{
17 return ioctl(fd, TCGETS, t);
18}
19
20int tcsetattr(int fd, int optional_actions, const struct termios* t)
21{
22 switch (optional_actions) {
23 case TCSANOW:
24 return ioctl(fd, TCSETS, t);
25 case TCSADRAIN:
26 return ioctl(fd, TCSETSW, t);
27 case TCSAFLUSH:
28 return ioctl(fd, TCSETSF, t);
29 }
30 errno = EINVAL;
31 return -1;
32}
33
34// https://pubs.opengroup.org/onlinepubs/009695399/functions/tcsendbreak.html
35int tcsendbreak([[maybe_unused]] int fd, [[maybe_unused]] int duration)
36{
37 // FIXME: Implement this for real.
38 return 0;
39}
40
41int tcflow([[maybe_unused]] int fd, [[maybe_unused]] int action)
42{
43 errno = EINVAL;
44 return -1;
45}
46
47int tcflush(int fd, int queue_selector)
48{
49 return ioctl(fd, TCFLSH, queue_selector);
50}
51
52// https://pubs.opengroup.org/onlinepubs/009695399/functions/tcdrain.html
53int tcdrain([[maybe_unused]] int fd)
54{
55 __pthread_maybe_cancel();
56
57 // FIXME: Implement this for real.
58 return 0;
59}
60
61speed_t cfgetispeed(const struct termios* tp)
62{
63 return tp->c_ispeed;
64}
65
66speed_t cfgetospeed(const struct termios* tp)
67{
68 return tp->c_ospeed;
69}
70
71static int baud_rate_from_speed(speed_t speed)
72{
73 int rate = -EINVAL;
74 switch (speed) {
75 case B0:
76 rate = 0;
77 break;
78 case B50:
79 rate = 50;
80 break;
81 case B75:
82 rate = 75;
83 break;
84 case B110:
85 rate = 110;
86 break;
87 case B134:
88 rate = 134;
89 break;
90 case B150:
91 rate = 150;
92 break;
93 case B200:
94 rate = 200;
95 break;
96 case B300:
97 rate = 300;
98 break;
99 case B600:
100 rate = 600;
101 break;
102 case B1200:
103 rate = 1200;
104 break;
105 case B1800:
106 rate = 1800;
107 break;
108 case B2400:
109 rate = 2400;
110 break;
111 case B4800:
112 rate = 4800;
113 break;
114 case B9600:
115 rate = 9600;
116 break;
117 case B19200:
118 rate = 19200;
119 break;
120 case B38400:
121 rate = 38400;
122 break;
123 }
124
125 return rate;
126}
127
128int cfsetispeed(struct termios* tp, speed_t speed)
129{
130 auto ispeed = baud_rate_from_speed(speed);
131 if (ispeed > 0) {
132 tp->c_ispeed = ispeed;
133 }
134 __RETURN_WITH_ERRNO(ispeed, 0, -1);
135}
136
137int cfsetospeed(struct termios* tp, speed_t speed)
138{
139 auto ospeed = baud_rate_from_speed(speed);
140 if (ospeed > 0) {
141 tp->c_ispeed = ospeed;
142 }
143 __RETURN_WITH_ERRNO(ospeed, 0, -1);
144}
145
146void cfmakeraw(struct termios* tp)
147{
148 if (!tp)
149 return;
150
151 auto& termios = *tp;
152 termios.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON);
153 termios.c_lflag &= ~OPOST;
154 termios.c_cflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
155 termios.c_cflag |= CS8;
156}
157}