diff --git a/drivers/serial/uart_native_tty.c b/drivers/serial/uart_native_tty.c index 259e6c339d5..69b7c919e2a 100644 --- a/drivers/serial/uart_native_tty.c +++ b/drivers/serial/uart_native_tty.c @@ -18,6 +18,7 @@ #include #include +#include #include #include "cmdline.h" @@ -130,6 +131,73 @@ static int native_tty_conv_to_bottom_cfg(struct native_tty_bottom_cfg *bottom_cf return 0; } +/** + * @brief Convert from native_tty_bottom_cfg to uart_config + * + * @param bottom_cfg + * @param cfg + * + * @return 0 on success, negative errno otherwise. + */ +int native_tty_conv_from_bottom_cfg(int fd, struct uart_config *cfg) +{ + struct native_tty_bottom_cfg bottom_cfg; + int rc = 0; + + rc = native_tty_read_bottom_cfg(fd, &bottom_cfg); + if (rc != 0) { + return nsi_errno_from_mid(rc); + } + + cfg->baudrate = bottom_cfg.baudrate; + + switch (bottom_cfg.parity) { + case NTB_PARITY_NONE: + cfg->parity = UART_CFG_PARITY_NONE; + break; + case NTB_PARITY_ODD: + cfg->parity = UART_CFG_PARITY_ODD; + break; + case NTB_PARITY_EVEN: + cfg->parity = UART_CFG_PARITY_EVEN; + break; + default: + return -ENOTSUP; + } + + switch (bottom_cfg.stop_bits) { + case NTB_STOP_BITS_1: + cfg->stop_bits = UART_CFG_STOP_BITS_1; + break; + case NTB_STOP_BITS_2: + cfg->stop_bits = UART_CFG_STOP_BITS_2; + break; + default: + return -ENOTSUP; + } + + switch (bottom_cfg.data_bits) { + case NTB_DATA_BITS_5: + cfg->data_bits = UART_CFG_DATA_BITS_5; + break; + case NTB_DATA_BITS_6: + cfg->data_bits = UART_CFG_DATA_BITS_6; + break; + case NTB_DATA_BITS_7: + cfg->data_bits = UART_CFG_DATA_BITS_7; + break; + case NTB_DATA_BITS_8: + cfg->data_bits = UART_CFG_DATA_BITS_8; + break; + default: + return -ENOTSUP; + } + + cfg->flow_ctrl = UART_CFG_FLOW_CTRL_NONE; + + return 0; +} + /* * @brief Output a character towards the serial port * @@ -177,6 +245,20 @@ static int native_tty_configure(const struct device *dev, const struct uart_conf return native_tty_configure_bottom(fd, &bottom_cfg); } +static int native_tty_config_get(const struct device *dev, struct uart_config *cfg) +{ + int fd = ((struct native_tty_data *)dev->data)->fd; + int rc = 0; + + rc = native_tty_conv_from_bottom_cfg(fd, cfg); + if (rc) { + WARN("Could not convert native tty bottom cfg to uart config\n"); + return rc; + } + + return 0; +} + #ifdef CONFIG_UART_INTERRUPT_DRIVEN static int native_tty_uart_fifo_fill(const struct device *dev, const uint8_t *tx_data, @@ -375,6 +457,7 @@ static DEVICE_API(uart, native_tty_uart_driver_api) = { .poll_in = native_tty_uart_poll_in, #ifdef CONFIG_UART_USE_RUNTIME_CONFIGURE .configure = native_tty_configure, + .config_get = native_tty_config_get, #endif #ifdef CONFIG_UART_INTERRUPT_DRIVEN .fifo_fill = native_tty_uart_fifo_fill, diff --git a/drivers/serial/uart_native_tty_bottom.c b/drivers/serial/uart_native_tty_bottom.c index 279ebca4100..7fe37ee2424 100644 --- a/drivers/serial/uart_native_tty_bottom.c +++ b/drivers/serial/uart_native_tty_bottom.c @@ -15,6 +15,7 @@ #include #include +#include #include #define WARN(...) nsi_print_warning(__VA_ARGS__) @@ -90,6 +91,31 @@ static inline void native_tty_baud_speed_set(struct termios *ter, int baudrate) ERROR("Could not set baudrate, as %d is not supported.\n", baudrate); } +/** + * @brief Get the baud rate speed from the termios structure + * + * @param ter + * @param baudrate + */ +static inline void native_tty_baud_speed_get(const struct termios *ter, uint32_t *baudrate) +{ + speed_t ispeed = cfgetispeed(ter); + speed_t ospeed = cfgetospeed(ter); + + if (ispeed != ospeed) { + ERROR("Input and output baud rates differ: %d vs %d\n", ispeed, ospeed); + } + + for (int i = 0; i < ARRAY_SIZE(baudrate_lut); i++) { + if (baudrate_lut[i].termios_baudrate == ispeed) { + *baudrate = baudrate_lut[i].baudrate; + return; + } + } + + ERROR("Unsupported termios baudrate: %d\n", ispeed); +} + /** * @brief Set parity setting in the termios structure * @@ -117,6 +143,24 @@ static inline void native_tty_baud_parity_set(struct termios *ter, } } +/** + * @brief Get the parity setting from the termios structure + * + * @param ter + * @param parity + */ +static inline void native_tty_baud_parity_get(const struct termios *ter, + enum native_tty_bottom_parity *parity) +{ + if ((ter->c_cflag & PARENB) == 0) { + *parity = NTB_PARITY_NONE; + } else if (ter->c_cflag & PARODD) { + *parity = NTB_PARITY_ODD; + } else { + *parity = NTB_PARITY_EVEN; + } +} + /** * @brief Set the number of stop bits in the termios structure * @@ -140,6 +184,18 @@ static inline void native_tty_stop_bits_set(struct termios *ter, } } +/** + * @brief Get the number of stop bits from the termios structure + * + * @param ter + * @param stop_bits + */ +static inline void native_tty_stop_bits_get(const struct termios *ter, + enum native_tty_bottom_stop_bits *stop_bits) +{ + *stop_bits = (ter->c_cflag & CSTOPB) ? NTB_STOP_BITS_2 : NTB_STOP_BITS_1; +} + /** * @brief Set the number of data bits in the termios structure * @@ -175,6 +231,33 @@ static inline void native_tty_data_bits_set(struct termios *ter, ter->c_cflag |= data_bits_to_set; } +/** + * @brief Get the number of data bits from the termios structure + * + * @param ter + * @param data_bits + */ +static inline void native_tty_data_bits_get(const struct termios *ter, + enum native_tty_bottom_data_bits *data_bits) +{ + switch (ter->c_cflag & CSIZE) { + case CS5: + *data_bits = NTB_DATA_BITS_5; + break; + case CS6: + *data_bits = NTB_DATA_BITS_6; + break; + case CS7: + *data_bits = NTB_DATA_BITS_7; + break; + case CS8: + *data_bits = NTB_DATA_BITS_8; + break; + default: + ERROR("Unsupported data bits setting in termios.\n"); + } +} + int native_tty_poll_bottom(int fd) { struct pollfd pfd = { .fd = fd, .events = POLLIN }; @@ -252,3 +335,26 @@ int native_tty_configure_bottom(int fd, struct native_tty_bottom_cfg *cfg) return 0; } + +int native_tty_read_bottom_cfg(int fd, struct native_tty_bottom_cfg *cfg) +{ + struct termios ter; + int rc = 0; + + rc = tcgetattr(fd, &ter); + if (rc != 0) { + int err = 0; + + err = errno; + WARN("Could not read terminal driver settings: %s\n", strerror(err)); + return -nsi_errno_to_mid(err); + } + + native_tty_baud_speed_get(&ter, &cfg->baudrate); + native_tty_baud_parity_get(&ter, &cfg->parity); + native_tty_data_bits_get(&ter, &cfg->data_bits); + native_tty_stop_bits_get(&ter, &cfg->stop_bits); + cfg->flow_ctrl = NTB_FLOW_CTRL_NONE; + + return 0; +} diff --git a/drivers/serial/uart_native_tty_bottom.h b/drivers/serial/uart_native_tty_bottom.h index aa5b819c0a8..f044ff2c5f7 100644 --- a/drivers/serial/uart_native_tty_bottom.h +++ b/drivers/serial/uart_native_tty_bottom.h @@ -86,6 +86,16 @@ int native_tty_open_tty_bottom(const char *pathname); */ int native_tty_configure_bottom(int fd, struct native_tty_bottom_cfg *cfg); +/** + * @brief Read bottom tty configuration + * + * @param fd + * @param cfg + * + * @return 0 on success, negative value on error + */ +int native_tty_read_bottom_cfg(int fd, struct native_tty_bottom_cfg *cfg); + #ifdef __cplusplus } #endif