2 * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds
5 #include <linux/types.h>
6 #include <linux/kernel.h>
7 #include <linux/termios.h>
9 #include <linux/export.h>
13 * Routine which returns the baud rate of the tty
15 * Note that the baud_table needs to be kept in sync with the
16 * include/asm/termbits.h file.
18 static const speed_t baud_table
[] = {
19 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
20 9600, 19200, 38400, 57600, 115200, 230400, 460800,
22 76800, 153600, 307200, 614400, 921600
24 500000, 576000, 921600, 1000000, 1152000, 1500000, 2000000,
25 2500000, 3000000, 3500000, 4000000
30 static const tcflag_t baud_bits
[] = {
31 B0
, B50
, B75
, B110
, B134
, B150
, B200
, B300
, B600
,
32 B1200
, B1800
, B2400
, B4800
, B9600
, B19200
, B38400
,
33 B57600
, B115200
, B230400
, B460800
, B500000
, B576000
,
34 B921600
, B1000000
, B1152000
, B1500000
, B2000000
, B2500000
,
35 B3000000
, B3500000
, B4000000
38 static const tcflag_t baud_bits
[] = {
39 B0
, B50
, B75
, B110
, B134
, B150
, B200
, B300
, B600
,
40 B1200
, B1800
, B2400
, B4800
, B9600
, B19200
, B38400
,
41 B57600
, B115200
, B230400
, B460800
, B76800
, B153600
,
42 B307200
, B614400
, B921600
46 static int n_baud_table
= ARRAY_SIZE(baud_table
);
49 * tty_termios_baud_rate
50 * @termios: termios structure
52 * Convert termios baud rate data into a speed. This should be called
53 * with the termios lock held if this termios is a terminal termios
54 * structure. May change the termios data. Device drivers can call this
55 * function but should use ->c_[io]speed directly as they are updated.
60 speed_t
tty_termios_baud_rate(struct ktermios
*termios
)
64 cbaud
= termios
->c_cflag
& CBAUD
;
67 /* Magic token for arbitrary speed via c_ispeed/c_ospeed */
69 return termios
->c_ospeed
;
71 if (cbaud
& CBAUDEX
) {
74 if (cbaud
< 1 || cbaud
+ 15 > n_baud_table
)
75 termios
->c_cflag
&= ~CBAUDEX
;
79 return baud_table
[cbaud
];
81 EXPORT_SYMBOL(tty_termios_baud_rate
);
84 * tty_termios_input_baud_rate
85 * @termios: termios structure
87 * Convert termios baud rate data into a speed. This should be called
88 * with the termios lock held if this termios is a terminal termios
89 * structure. May change the termios data. Device drivers can call this
90 * function but should use ->c_[io]speed directly as they are updated.
95 speed_t
tty_termios_input_baud_rate(struct ktermios
*termios
)
98 unsigned int cbaud
= (termios
->c_cflag
>> IBSHIFT
) & CBAUD
;
101 return tty_termios_baud_rate(termios
);
103 /* Magic token for arbitrary speed via c_ispeed*/
105 return termios
->c_ispeed
;
107 if (cbaud
& CBAUDEX
) {
110 if (cbaud
< 1 || cbaud
+ 15 > n_baud_table
)
111 termios
->c_cflag
&= ~(CBAUDEX
<< IBSHIFT
);
115 return baud_table
[cbaud
];
117 return tty_termios_baud_rate(termios
);
120 EXPORT_SYMBOL(tty_termios_input_baud_rate
);
123 * tty_termios_encode_baud_rate
124 * @termios: ktermios structure holding user requested state
125 * @ispeed: input speed
126 * @ospeed: output speed
128 * Encode the speeds set into the passed termios structure. This is
129 * used as a library helper for drivers so that they can report back
130 * the actual speed selected when it differs from the speed requested
132 * For maximal back compatibility with legacy SYS5/POSIX *nix behaviour
133 * we need to carefully set the bits when the user does not get the
134 * desired speed. We allow small margins and preserve as much of possible
135 * of the input intent to keep compatibility.
137 * Locking: Caller should hold termios lock. This is already held
138 * when calling this function from the driver termios handler.
140 * The ifdefs deal with platforms whose owners have yet to update them
141 * and will all go away once this is done.
144 void tty_termios_encode_baud_rate(struct ktermios
*termios
,
145 speed_t ibaud
, speed_t obaud
)
148 int ifound
= -1, ofound
= -1;
149 int iclose
= ibaud
/50, oclose
= obaud
/50;
152 if (obaud
== 0) /* CD dropped */
153 ibaud
= 0; /* Clear ibaud to be sure */
155 termios
->c_ispeed
= ibaud
;
156 termios
->c_ospeed
= obaud
;
159 /* If the user asked for a precise weird speed give a precise weird
160 answer. If they asked for a Bfoo speed they may have problems
161 digesting non-exact replies so fuzz a bit */
163 if ((termios
->c_cflag
& CBAUD
) == BOTHER
)
165 if (((termios
->c_cflag
>> IBSHIFT
) & CBAUD
) == BOTHER
)
167 if ((termios
->c_cflag
>> IBSHIFT
) & CBAUD
)
168 ibinput
= 1; /* An input speed was specified */
170 termios
->c_cflag
&= ~CBAUD
;
173 * Our goal is to find a close match to the standard baud rate
174 * returned. Walk the baud rate table and if we get a very close
175 * match then report back the speed as a POSIX Bxxxx value by
180 if (obaud
- oclose
<= baud_table
[i
] &&
181 obaud
+ oclose
>= baud_table
[i
]) {
182 termios
->c_cflag
|= baud_bits
[i
];
185 if (ibaud
- iclose
<= baud_table
[i
] &&
186 ibaud
+ iclose
>= baud_table
[i
]) {
187 /* For the case input == output don't set IBAUD bits
188 if the user didn't do so */
189 if (ofound
== i
&& !ibinput
)
194 termios
->c_cflag
|= (baud_bits
[i
] << IBSHIFT
);
198 } while (++i
< n_baud_table
);
201 * If we found no match then use BOTHER if provided or warn
202 * the user their platform maintainer needs to wake up if not.
206 termios
->c_cflag
|= BOTHER
;
207 /* Set exact input bits only if the input and output differ or the
209 if (ifound
== -1 && (ibaud
!= obaud
|| ibinput
))
210 termios
->c_cflag
|= (BOTHER
<< IBSHIFT
);
212 if (ifound
== -1 || ofound
== -1)
213 pr_warn_once("tty: Unable to return correct speed data as your architecture needs updating.\n");
216 EXPORT_SYMBOL_GPL(tty_termios_encode_baud_rate
);
219 * tty_encode_baud_rate - set baud rate of the tty
220 * @ibaud: input baud rate
221 * @obad: output baud rate
223 * Update the current termios data for the tty with the new speed
224 * settings. The caller must hold the termios_rwsem for the tty in
228 void tty_encode_baud_rate(struct tty_struct
*tty
, speed_t ibaud
, speed_t obaud
)
230 tty_termios_encode_baud_rate(&tty
->termios
, ibaud
, obaud
);
232 EXPORT_SYMBOL_GPL(tty_encode_baud_rate
);