forked from Minki/linux
fa44195455
With W=1, the kernel-doc checker complains quite a lot in the tty layer. Over the time, many documented parameters were renamed, removed or switched from tty to tty_port and similar. Some were mistyped in the doc too. So fix all these in the tty core. (But do not add the missing ones which the checker complains about too. Not now.) The rest in the tty layer will follow in the next patches. Signed-off-by: Jiri Slaby <jslaby@suse.cz> Link: https://lore.kernel.org/r/20200818085655.12071-4-jslaby@suse.cz Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
238 lines
6.5 KiB
C
238 lines
6.5 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/*
|
|
* 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[] = {
|
|
0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400,
|
|
4800, 9600, 19200, 38400, 57600, 115200, 230400, 460800,
|
|
#ifdef __sparc__
|
|
76800, 153600, 307200, 614400, 921600, 500000, 576000,
|
|
1000000, 1152000, 1500000, 2000000
|
|
#else
|
|
500000, 576000, 921600, 1000000, 1152000, 1500000, 2000000,
|
|
2500000, 3000000, 3500000, 4000000
|
|
#endif
|
|
};
|
|
|
|
static const tcflag_t baud_bits[] = {
|
|
B0, B50, B75, B110, B134, B150, B200, B300, B600, B1200, B1800, B2400,
|
|
B4800, B9600, B19200, B38400, B57600, B115200, B230400, B460800,
|
|
#ifdef __sparc__
|
|
B76800, B153600, B307200, B614400, B921600, B500000, B576000,
|
|
B1000000, B1152000, B1500000, B2000000
|
|
#else
|
|
B500000, B576000, B921600, B1000000, B1152000, B1500000, B2000000,
|
|
B2500000, B3000000, B3500000, B4000000
|
|
#endif
|
|
};
|
|
|
|
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;
|
|
}
|
|
return cbaud >= n_baud_table ? 0 : baud_table[cbaud];
|
|
}
|
|
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);
|
|
#ifdef BOTHER
|
|
/* Magic token for arbitrary speed via c_ispeed*/
|
|
if (cbaud == BOTHER)
|
|
return termios->c_ispeed;
|
|
#endif
|
|
if (cbaud & CBAUDEX) {
|
|
cbaud &= ~CBAUDEX;
|
|
|
|
if (cbaud < 1 || cbaud + 15 > n_baud_table)
|
|
termios->c_cflag &= ~(CBAUDEX << IBSHIFT);
|
|
else
|
|
cbaud += 15;
|
|
}
|
|
return cbaud >= n_baud_table ? 0 : baud_table[cbaud];
|
|
#else /* IBSHIFT */
|
|
return tty_termios_baud_rate(termios);
|
|
#endif /* IBSHIFT */
|
|
}
|
|
EXPORT_SYMBOL(tty_termios_input_baud_rate);
|
|
|
|
/**
|
|
* tty_termios_encode_baud_rate
|
|
* @termios: ktermios structure holding user requested state
|
|
* @ibaud: input speed
|
|
* @obaud: output speed
|
|
*
|
|
* 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;
|
|
|
|
#ifdef IBSHIFT
|
|
if ((termios->c_cflag >> IBSHIFT) & CBAUD)
|
|
ibinput = 1; /* An input speed was specified */
|
|
#endif
|
|
#ifdef BOTHER
|
|
/* 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 */
|
|
|
|
if ((termios->c_cflag & CBAUD) == BOTHER) {
|
|
oclose = 0;
|
|
if (!ibinput)
|
|
iclose = 0;
|
|
}
|
|
if (((termios->c_cflag >> IBSHIFT) & CBAUD) == BOTHER)
|
|
iclose = 0;
|
|
#endif
|
|
termios->c_cflag &= ~CBAUD;
|
|
#ifdef IBSHIFT
|
|
termios->c_cflag &= ~(CBAUD << IBSHIFT);
|
|
#endif
|
|
|
|
/*
|
|
* 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.\n");
|
|
#endif
|
|
}
|
|
EXPORT_SYMBOL_GPL(tty_termios_encode_baud_rate);
|
|
|
|
/**
|
|
* tty_encode_baud_rate - set baud rate of the tty
|
|
* @ibaud: input baud rate
|
|
* @obaud: output baud rate
|
|
*
|
|
* 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);
|