0001
0002
0003
0004
0005
0006 #include <linux/types.h>
0007 #include <linux/kernel.h>
0008 #include <linux/termios.h>
0009 #include <linux/tty.h>
0010 #include <linux/export.h>
0011 #include "tty.h"
0012
0013
0014
0015
0016
0017
0018
0019
0020 static const speed_t baud_table[] = {
0021 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400,
0022 4800, 9600, 19200, 38400, 57600, 115200, 230400, 460800,
0023 #ifdef __sparc__
0024 76800, 153600, 307200, 614400, 921600, 500000, 576000,
0025 1000000, 1152000, 1500000, 2000000
0026 #else
0027 500000, 576000, 921600, 1000000, 1152000, 1500000, 2000000,
0028 2500000, 3000000, 3500000, 4000000
0029 #endif
0030 };
0031
0032 static const tcflag_t baud_bits[] = {
0033 B0, B50, B75, B110, B134, B150, B200, B300, B600, B1200, B1800, B2400,
0034 B4800, B9600, B19200, B38400, B57600, B115200, B230400, B460800,
0035 #ifdef __sparc__
0036 B76800, B153600, B307200, B614400, B921600, B500000, B576000,
0037 B1000000, B1152000, B1500000, B2000000
0038 #else
0039 B500000, B576000, B921600, B1000000, B1152000, B1500000, B2000000,
0040 B2500000, B3000000, B3500000, B4000000
0041 #endif
0042 };
0043
0044 static int n_baud_table = ARRAY_SIZE(baud_table);
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058 speed_t tty_termios_baud_rate(struct ktermios *termios)
0059 {
0060 unsigned int cbaud;
0061
0062 cbaud = termios->c_cflag & CBAUD;
0063
0064
0065 if (cbaud == BOTHER)
0066 return termios->c_ospeed;
0067
0068 if (cbaud & CBAUDEX) {
0069 cbaud &= ~CBAUDEX;
0070
0071 if (cbaud < 1 || cbaud + 15 > n_baud_table)
0072 termios->c_cflag &= ~CBAUDEX;
0073 else
0074 cbaud += 15;
0075 }
0076 return cbaud >= n_baud_table ? 0 : baud_table[cbaud];
0077 }
0078 EXPORT_SYMBOL(tty_termios_baud_rate);
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092 speed_t tty_termios_input_baud_rate(struct ktermios *termios)
0093 {
0094 unsigned int cbaud = (termios->c_cflag >> IBSHIFT) & CBAUD;
0095
0096 if (cbaud == B0)
0097 return tty_termios_baud_rate(termios);
0098
0099
0100 if (cbaud == BOTHER)
0101 return termios->c_ispeed;
0102
0103 if (cbaud & CBAUDEX) {
0104 cbaud &= ~CBAUDEX;
0105
0106 if (cbaud < 1 || cbaud + 15 > n_baud_table)
0107 termios->c_cflag &= ~(CBAUDEX << IBSHIFT);
0108 else
0109 cbaud += 15;
0110 }
0111 return cbaud >= n_baud_table ? 0 : baud_table[cbaud];
0112 }
0113 EXPORT_SYMBOL(tty_termios_input_baud_rate);
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133
0134
0135
0136
0137 void tty_termios_encode_baud_rate(struct ktermios *termios,
0138 speed_t ibaud, speed_t obaud)
0139 {
0140 int i = 0;
0141 int ifound = -1, ofound = -1;
0142 int iclose = ibaud/50, oclose = obaud/50;
0143 int ibinput = 0;
0144
0145 if (obaud == 0)
0146 ibaud = 0;
0147
0148 termios->c_ispeed = ibaud;
0149 termios->c_ospeed = obaud;
0150
0151 if (((termios->c_cflag >> IBSHIFT) & CBAUD) != B0)
0152 ibinput = 1;
0153
0154
0155
0156
0157
0158
0159 if ((termios->c_cflag & CBAUD) == BOTHER) {
0160 oclose = 0;
0161 if (!ibinput)
0162 iclose = 0;
0163 }
0164 if (((termios->c_cflag >> IBSHIFT) & CBAUD) == BOTHER)
0165 iclose = 0;
0166
0167 termios->c_cflag &= ~CBAUD;
0168 termios->c_cflag &= ~(CBAUD << IBSHIFT);
0169
0170
0171
0172
0173
0174
0175
0176
0177 do {
0178 if (obaud - oclose <= baud_table[i] &&
0179 obaud + oclose >= baud_table[i]) {
0180 termios->c_cflag |= baud_bits[i];
0181 ofound = i;
0182 }
0183 if (ibaud - iclose <= baud_table[i] &&
0184 ibaud + iclose >= baud_table[i]) {
0185
0186
0187
0188 if (ofound == i && !ibinput) {
0189 ifound = i;
0190 } else {
0191 ifound = i;
0192 termios->c_cflag |= (baud_bits[i] << IBSHIFT);
0193 }
0194 }
0195 } while (++i < n_baud_table);
0196
0197
0198 if (ofound == -1)
0199 termios->c_cflag |= BOTHER;
0200
0201
0202
0203 if (ifound == -1 && (ibaud != obaud || ibinput))
0204 termios->c_cflag |= (BOTHER << IBSHIFT);
0205 }
0206 EXPORT_SYMBOL_GPL(tty_termios_encode_baud_rate);
0207
0208
0209
0210
0211
0212
0213
0214
0215
0216
0217
0218
0219 void tty_encode_baud_rate(struct tty_struct *tty, speed_t ibaud, speed_t obaud)
0220 {
0221 tty_termios_encode_baud_rate(&tty->termios, ibaud, obaud);
0222 }
0223 EXPORT_SYMBOL_GPL(tty_encode_baud_rate);