[PATCH 34/35] tty: make tty_get_byte_size available

From: Jiri Slaby
Date: Wed May 05 2021 - 05:21:41 EST


Many tty drivers contain code to compute bits count depending on termios
cflags. So extract this code from serial core to a separate tty helper
function called tty_get_byte_size.

In the next patch, call to this new function will replace many copies of
this code.

Signed-off-by: Jiri Slaby <jslaby@xxxxxxx>
---
drivers/tty/serial/serial_core.c | 30 +++--------------------
drivers/tty/tty_ioctl.c | 41 ++++++++++++++++++++++++++++++++
include/linux/tty.h | 2 ++
3 files changed, 46 insertions(+), 27 deletions(-)

diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index d29329eb52f4..b3fc2b02a705 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -334,39 +334,15 @@ void
uart_update_timeout(struct uart_port *port, unsigned int cflag,
unsigned int baud)
{
- unsigned int bits;
+ unsigned int size;

- /* byte size and parity */
- switch (cflag & CSIZE) {
- case CS5:
- bits = 7;
- break;
- case CS6:
- bits = 8;
- break;
- case CS7:
- bits = 9;
- break;
- default:
- bits = 10;
- break; /* CS8 */
- }
-
- if (cflag & CSTOPB)
- bits++;
- if (cflag & PARENB)
- bits++;
-
- /*
- * The total number of bits to be transmitted in the fifo.
- */
- bits = bits * port->fifosize;
+ size = tty_get_byte_size(cflag, true) * port->fifosize;

/*
* Figure the timeout to send the above number of bits.
* Add .02 seconds of slop
*/
- port->timeout = (HZ * bits) / baud + HZ/50;
+ port->timeout = (HZ * size) / baud + HZ/50;
}

EXPORT_SYMBOL(uart_update_timeout);
diff --git a/drivers/tty/tty_ioctl.c b/drivers/tty/tty_ioctl.c
index aa9ecc8be990..72d036917b14 100644
--- a/drivers/tty/tty_ioctl.c
+++ b/drivers/tty/tty_ioctl.c
@@ -300,6 +300,47 @@ int tty_termios_hw_change(const struct ktermios *a, const struct ktermios *b)
}
EXPORT_SYMBOL(tty_termios_hw_change);

+/**
+ * tty_get_byte_size - get size of a byte
+ * @cflag: termios cflag value
+ * @account_flags: account for start and stop bits, second stop bit (if
+ * set), and parity (if set)
+ *
+ * Get the size of a byte in bits depending on @cflag. Depending on
+ * @account_flags parameter, the result also accounts start and stop bits,
+ * the second stop bit, and parity bit.
+ */
+unsigned char tty_get_byte_size(unsigned int cflag, bool account_flags)
+{
+ unsigned char bits = account_flags ? 2 : 0;
+
+ /* byte size and parity */
+ switch (cflag & CSIZE) {
+ case CS5:
+ bits += 5;
+ break;
+ case CS6:
+ bits += 6;
+ break;
+ case CS7:
+ bits += 7;
+ break;
+ case CS8:
+ default:
+ bits += 8;
+ break;
+ }
+
+ if (account_flags && (cflag & CSTOPB))
+ bits++;
+
+ if (account_flags && (cflag & PARENB))
+ bits++;
+
+ return bits;
+}
+EXPORT_SYMBOL_GPL(tty_get_byte_size);
+
/**
* tty_set_termios - update termios values
* @tty: tty to update
diff --git a/include/linux/tty.h b/include/linux/tty.h
index 5cf6b2e7331b..a14b4588368c 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -496,6 +496,8 @@ static inline speed_t tty_get_baud_rate(struct tty_struct *tty)
return tty_termios_baud_rate(&tty->termios);
}

+unsigned char tty_get_byte_size(unsigned int cflag, bool account_flags);
+
extern void tty_termios_copy_hw(struct ktermios *new, struct ktermios *old);
extern int tty_termios_hw_change(const struct ktermios *a, const struct ktermios *b);
extern int tty_set_termios(struct tty_struct *tty, struct ktermios *kt);
--
2.31.1