1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds
6 #include <linux/types.h>
7 #include <linux/kernel.h>
8 #include <linux/termios.h>
10 #include <linux/export.h>
15 * Routine which returns the baud rate of the tty
17 * Note that the baud_table needs to be kept in sync with the
18 * include/asm/termbits.h file.
20 static const speed_t baud_table
[] = {
21 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400,
22 4800, 9600, 19200, 38400, 57600, 115200, 230400, 460800,
24 76800, 153600, 307200, 614400, 921600, 500000, 576000,
25 1000000, 1152000, 1500000, 2000000
27 500000, 576000, 921600, 1000000, 1152000, 1500000, 2000000,
28 2500000, 3000000, 3500000, 4000000
32 static const tcflag_t baud_bits
[] = {
33 B0
, B50
, B75
, B110
, B134
, B150
, B200
, B300
, B600
, B1200
, B1800
, B2400
,
34 B4800
, B9600
, B19200
, B38400
, B57600
, B115200
, B230400
, B460800
,
36 B76800
, B153600
, B307200
, B614400
, B921600
, B500000
, B576000
,
37 B1000000
, B1152000
, B1500000
, B2000000
39 B500000
, B576000
, B921600
, B1000000
, B1152000
, B1500000
, B2000000
,
40 B2500000
, B3000000
, B3500000
, B4000000
44 static int n_baud_table
= ARRAY_SIZE(baud_table
);
47 * tty_termios_baud_rate
48 * @termios: termios structure
50 * Convert termios baud rate data into a speed. This should be called
51 * with the termios lock held if this termios is a terminal termios
52 * structure. Device drivers can call this function but should use
53 * ->c_[io]speed directly as they are updated.
58 speed_t
tty_termios_baud_rate(const struct ktermios
*termios
)
62 cbaud
= termios
->c_cflag
& CBAUD
;
64 /* Magic token for arbitrary speed via c_ispeed/c_ospeed */
66 return termios
->c_ospeed
;
68 if (cbaud
& CBAUDEX
) {
72 return cbaud
>= n_baud_table
? 0 : baud_table
[cbaud
];
74 EXPORT_SYMBOL(tty_termios_baud_rate
);
77 * tty_termios_input_baud_rate
78 * @termios: termios structure
80 * Convert termios baud rate data into a speed. This should be called
81 * with the termios lock held if this termios is a terminal termios
82 * structure. Device drivers can call this function but should use
83 * ->c_[io]speed directly as they are updated.
88 speed_t
tty_termios_input_baud_rate(const struct ktermios
*termios
)
90 unsigned int cbaud
= (termios
->c_cflag
>> IBSHIFT
) & CBAUD
;
93 return tty_termios_baud_rate(termios
);
95 /* Magic token for arbitrary speed via c_ispeed */
97 return termios
->c_ispeed
;
99 if (cbaud
& CBAUDEX
) {
103 return cbaud
>= n_baud_table
? 0 : baud_table
[cbaud
];
105 EXPORT_SYMBOL(tty_termios_input_baud_rate
);
108 * tty_termios_encode_baud_rate
109 * @termios: ktermios structure holding user requested state
110 * @ibaud: input speed
111 * @obaud: output speed
113 * Encode the speeds set into the passed termios structure. This is
114 * used as a library helper for drivers so that they can report back
115 * the actual speed selected when it differs from the speed requested
117 * For maximal back compatibility with legacy SYS5/POSIX *nix behaviour
118 * we need to carefully set the bits when the user does not get the
119 * desired speed. We allow small margins and preserve as much of possible
120 * of the input intent to keep compatibility.
122 * Locking: Caller should hold termios lock. This is already held
123 * when calling this function from the driver termios handler.
125 * The ifdefs deal with platforms whose owners have yet to update them
126 * and will all go away once this is done.
129 void tty_termios_encode_baud_rate(struct ktermios
*termios
,
130 speed_t ibaud
, speed_t obaud
)
133 int ifound
= -1, ofound
= -1;
134 int iclose
= ibaud
/50, oclose
= obaud
/50;
137 if (obaud
== 0) /* CD dropped */
138 ibaud
= 0; /* Clear ibaud to be sure */
140 termios
->c_ispeed
= ibaud
;
141 termios
->c_ospeed
= obaud
;
143 if (((termios
->c_cflag
>> IBSHIFT
) & CBAUD
) != B0
)
144 ibinput
= 1; /* An input speed was specified */
146 /* If the user asked for a precise weird speed give a precise weird
147 * answer. If they asked for a Bfoo speed they may have problems
148 * digesting non-exact replies so fuzz a bit.
151 if ((termios
->c_cflag
& CBAUD
) == BOTHER
) {
156 if (((termios
->c_cflag
>> IBSHIFT
) & CBAUD
) == BOTHER
)
159 termios
->c_cflag
&= ~CBAUD
;
160 termios
->c_cflag
&= ~(CBAUD
<< IBSHIFT
);
163 * Our goal is to find a close match to the standard baud rate
164 * returned. Walk the baud rate table and if we get a very close
165 * match then report back the speed as a POSIX Bxxxx value by
170 if (obaud
- oclose
<= baud_table
[i
] &&
171 obaud
+ oclose
>= baud_table
[i
]) {
172 termios
->c_cflag
|= baud_bits
[i
];
175 if (ibaud
- iclose
<= baud_table
[i
] &&
176 ibaud
+ iclose
>= baud_table
[i
]) {
177 /* For the case input == output don't set IBAUD bits
178 * if the user didn't do so.
180 if (ofound
== i
&& !ibinput
) {
184 termios
->c_cflag
|= (baud_bits
[i
] << IBSHIFT
);
187 } while (++i
< n_baud_table
);
189 /* If we found no match then use BOTHER. */
191 termios
->c_cflag
|= BOTHER
;
192 /* Set exact input bits only if the input and output differ or the
195 if (ifound
== -1 && (ibaud
!= obaud
|| ibinput
))
196 termios
->c_cflag
|= (BOTHER
<< IBSHIFT
);
198 EXPORT_SYMBOL_GPL(tty_termios_encode_baud_rate
);
201 * tty_encode_baud_rate - set baud rate of the tty
202 * @tty: terminal device
203 * @ibaud: input baud rate
204 * @obaud: output baud rate
206 * Update the current termios data for the tty with the new speed
207 * settings. The caller must hold the termios_rwsem for the tty in
211 void tty_encode_baud_rate(struct tty_struct
*tty
, speed_t ibaud
, speed_t obaud
)
213 tty_termios_encode_baud_rate(&tty
->termios
, ibaud
, obaud
);
215 EXPORT_SYMBOL_GPL(tty_encode_baud_rate
);