Blame view
drivers/tty/tty_baudrate.c
6.53 KB
e3b3d0f54 tty: add SPDX ide... |
1 |
// SPDX-License-Identifier: GPL-2.0 |
fff0a2ca3 tty: move baudrat... |
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
/* * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds */ #include <linux/types.h> #include <linux/kernel.h> #include <linux/termios.h> #include <linux/tty.h> #include <linux/export.h> /* * Routine which returns the baud rate of the tty * * Note that the baud_table needs to be kept in sync with the * include/asm/termbits.h file. */ static const speed_t baud_table[] = { |
6ada6064b tty: baudrate: Sy... |
20 21 |
0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, 9600, 19200, 38400, 57600, 115200, 230400, 460800, |
fff0a2ca3 tty: move baudrat... |
22 |
#ifdef __sparc__ |
1ddeb5a74 tty: baudrate: SP... |
23 24 |
76800, 153600, 307200, 614400, 921600, 500000, 576000, 1000000, 1152000, 1500000, 2000000 |
fff0a2ca3 tty: move baudrat... |
25 26 27 28 29 |
#else 500000, 576000, 921600, 1000000, 1152000, 1500000, 2000000, 2500000, 3000000, 3500000, 4000000 #endif }; |
fff0a2ca3 tty: move baudrat... |
30 |
static const tcflag_t baud_bits[] = { |
6ada6064b tty: baudrate: Sy... |
31 32 33 |
B0, B50, B75, B110, B134, B150, B200, B300, B600, B1200, B1800, B2400, B4800, B9600, B19200, B38400, B57600, B115200, B230400, B460800, #ifdef __sparc__ |
1ddeb5a74 tty: baudrate: SP... |
34 35 |
B76800, B153600, B307200, B614400, B921600, B500000, B576000, B1000000, B1152000, B1500000, B2000000 |
fff0a2ca3 tty: move baudrat... |
36 |
#else |
6ada6064b tty: baudrate: Sy... |
37 38 |
B500000, B576000, B921600, B1000000, B1152000, B1500000, B2000000, B2500000, B3000000, B3500000, B4000000 |
fff0a2ca3 tty: move baudrat... |
39 |
#endif |
6ada6064b tty: baudrate: Sy... |
40 |
}; |
fff0a2ca3 tty: move baudrat... |
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
static int n_baud_table = ARRAY_SIZE(baud_table); /** * tty_termios_baud_rate * @termios: termios structure * * Convert termios baud rate data into a speed. This should be called * with the termios lock held if this termios is a terminal termios * structure. May change the termios data. Device drivers can call this * function but should use ->c_[io]speed directly as they are updated. * * Locking: none */ speed_t tty_termios_baud_rate(struct ktermios *termios) { unsigned int cbaud; cbaud = termios->c_cflag & CBAUD; #ifdef BOTHER /* Magic token for arbitrary speed via c_ispeed/c_ospeed */ if (cbaud == BOTHER) return termios->c_ospeed; #endif if (cbaud & CBAUDEX) { cbaud &= ~CBAUDEX; if (cbaud < 1 || cbaud + 15 > n_baud_table) termios->c_cflag &= ~CBAUDEX; else cbaud += 15; } |
991a25194 termios, tty/tty_... |
75 |
return cbaud >= n_baud_table ? 0 : baud_table[cbaud]; |
fff0a2ca3 tty: move baudrat... |
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 |
} EXPORT_SYMBOL(tty_termios_baud_rate); /** * tty_termios_input_baud_rate * @termios: termios structure * * Convert termios baud rate data into a speed. This should be called * with the termios lock held if this termios is a terminal termios * structure. May change the termios data. Device drivers can call this * function but should use ->c_[io]speed directly as they are updated. * * Locking: none */ speed_t tty_termios_input_baud_rate(struct ktermios *termios) { #ifdef IBSHIFT unsigned int cbaud = (termios->c_cflag >> IBSHIFT) & CBAUD; if (cbaud == B0) return tty_termios_baud_rate(termios); |
fefe287e4 tty: support CIBA... |
98 |
#ifdef BOTHER |
fff0a2ca3 tty: move baudrat... |
99 100 101 |
/* Magic token for arbitrary speed via c_ispeed*/ if (cbaud == BOTHER) return termios->c_ispeed; |
fefe287e4 tty: support CIBA... |
102 |
#endif |
fff0a2ca3 tty: move baudrat... |
103 104 105 106 107 108 109 110 |
if (cbaud & CBAUDEX) { cbaud &= ~CBAUDEX; if (cbaud < 1 || cbaud + 15 > n_baud_table) termios->c_cflag &= ~(CBAUDEX << IBSHIFT); else cbaud += 15; } |
991a25194 termios, tty/tty_... |
111 |
return cbaud >= n_baud_table ? 0 : baud_table[cbaud]; |
fefe287e4 tty: support CIBA... |
112 |
#else /* IBSHIFT */ |
fff0a2ca3 tty: move baudrat... |
113 |
return tty_termios_baud_rate(termios); |
fefe287e4 tty: support CIBA... |
114 |
#endif /* IBSHIFT */ |
fff0a2ca3 tty: move baudrat... |
115 116 117 118 119 120 |
} EXPORT_SYMBOL(tty_termios_input_baud_rate); /** * tty_termios_encode_baud_rate * @termios: ktermios structure holding user requested state |
fa4419545 tty: fix kernel-doc |
121 122 |
* @ibaud: input speed * @obaud: output speed |
fff0a2ca3 tty: move baudrat... |
123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 |
* * Encode the speeds set into the passed termios structure. This is * used as a library helper for drivers so that they can report back * the actual speed selected when it differs from the speed requested * * For maximal back compatibility with legacy SYS5/POSIX *nix behaviour * we need to carefully set the bits when the user does not get the * desired speed. We allow small margins and preserve as much of possible * of the input intent to keep compatibility. * * Locking: Caller should hold termios lock. This is already held * when calling this function from the driver termios handler. * * The ifdefs deal with platforms whose owners have yet to update them * and will all go away once this is done. */ void tty_termios_encode_baud_rate(struct ktermios *termios, speed_t ibaud, speed_t obaud) { int i = 0; int ifound = -1, ofound = -1; int iclose = ibaud/50, oclose = obaud/50; int ibinput = 0; if (obaud == 0) /* CD dropped */ ibaud = 0; /* Clear ibaud to be sure */ termios->c_ispeed = ibaud; termios->c_ospeed = obaud; |
fefe287e4 tty: support CIBA... |
153 |
#ifdef IBSHIFT |
1cee38f03 tty: fix termios ... |
154 155 |
if ((termios->c_cflag >> IBSHIFT) & CBAUD) ibinput = 1; /* An input speed was specified */ |
fefe287e4 tty: support CIBA... |
156 157 |
#endif #ifdef BOTHER |
fff0a2ca3 tty: move baudrat... |
158 159 160 |
/* If the user asked for a precise weird speed give a precise weird answer. If they asked for a Bfoo speed they may have problems digesting non-exact replies so fuzz a bit */ |
1cee38f03 tty: fix termios ... |
161 |
if ((termios->c_cflag & CBAUD) == BOTHER) { |
fff0a2ca3 tty: move baudrat... |
162 |
oclose = 0; |
1cee38f03 tty: fix termios ... |
163 164 165 |
if (!ibinput) iclose = 0; } |
fff0a2ca3 tty: move baudrat... |
166 167 |
if (((termios->c_cflag >> IBSHIFT) & CBAUD) == BOTHER) iclose = 0; |
fff0a2ca3 tty: move baudrat... |
168 169 |
#endif termios->c_cflag &= ~CBAUD; |
fada18c48 tty: fix termios ... |
170 171 172 |
#ifdef IBSHIFT termios->c_cflag &= ~(CBAUD << IBSHIFT); #endif |
fff0a2ca3 tty: move baudrat... |
173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 |
/* * Our goal is to find a close match to the standard baud rate * returned. Walk the baud rate table and if we get a very close * match then report back the speed as a POSIX Bxxxx value by * preference */ do { if (obaud - oclose <= baud_table[i] && obaud + oclose >= baud_table[i]) { termios->c_cflag |= baud_bits[i]; ofound = i; } if (ibaud - iclose <= baud_table[i] && ibaud + iclose >= baud_table[i]) { /* For the case input == output don't set IBAUD bits if the user didn't do so */ if (ofound == i && !ibinput) ifound = i; #ifdef IBSHIFT else { ifound = i; termios->c_cflag |= (baud_bits[i] << IBSHIFT); } #endif } } while (++i < n_baud_table); /* * If we found no match then use BOTHER if provided or warn * the user their platform maintainer needs to wake up if not. */ #ifdef BOTHER if (ofound == -1) termios->c_cflag |= BOTHER; /* Set exact input bits only if the input and output differ or the user already did */ if (ifound == -1 && (ibaud != obaud || ibinput)) termios->c_cflag |= (BOTHER << IBSHIFT); #else if (ifound == -1 || ofound == -1) pr_warn_once("tty: Unable to return correct speed data as your architecture needs updating. "); #endif } EXPORT_SYMBOL_GPL(tty_termios_encode_baud_rate); /** * tty_encode_baud_rate - set baud rate of the tty * @ibaud: input baud rate |
fa4419545 tty: fix kernel-doc |
224 |
* @obaud: output baud rate |
fff0a2ca3 tty: move baudrat... |
225 226 227 228 229 230 231 232 233 234 235 |
* * Update the current termios data for the tty with the new speed * settings. The caller must hold the termios_rwsem for the tty in * question. */ void tty_encode_baud_rate(struct tty_struct *tty, speed_t ibaud, speed_t obaud) { tty_termios_encode_baud_rate(&tty->termios, ibaud, obaud); } EXPORT_SYMBOL_GPL(tty_encode_baud_rate); |