diff --git a/api/mraa/uart.h b/api/mraa/uart.h index 4b580fe..d07356e 100644 --- a/api/mraa/uart.h +++ b/api/mraa/uart.h @@ -148,6 +148,41 @@ mraa_result_t mraa_uart_set_non_blocking(mraa_uart_context dev, mraa_boolean_t n */ const char* mraa_uart_get_dev_path(mraa_uart_context dev); +/** + * Get the current settings of an UART. This is an unintrusive function. Meaning + * it intends not to change anything, only read the values without disturbing. + * + * All but the first index parameter are "outparameters". That means they can + * contain values on return. If any parameter is not interesting, a null pointer + * can be sent instead as a placeholder. + * The devpath parameter can be either in or out parameter. In case of a negative + * index, the UART is identified using *devpath instead. This functionality is + * intended for and needed by for instance USB serial adapters. + * + * In case of a non-success return value, the outparameters are undefined. + * + * @param index uart index to look up, if negative, *devpath will be used instead + * @param devpath points to the device path of the UART, eg: /dev/ttyS0 + * @param name outparameter that on return will point to the name of the UART + * @param baudrate pointer to an integer to contain the current baudrate (0--4M) + * @param databits pointer to an integer to contain the number databits (5--8) + * @param stopbits pointer to an integer to contain the number stopbits (1--2) + * @param parity will contain the current parity mode + * @param rtscts will point to non-zero if CTS/RTS flow control is enabled, zero otherwise + * @param xonxoff will point to a non-zero value if xon/xoff flow control is enabled + * @return result + */ +mraa_result_t +mraa_uart_settings(int index, + const char **devpath, + const char **name, + int* baudrate, + int* databits, + int* stopbits, + mraa_uart_parity_t* parity, + unsigned int* rtscts, + unsigned int* xonxoff); + /** * Destroy a mraa_uart_context * diff --git a/src/uart/uart.c b/src/uart/uart.c index 39bf25f..9e5d75f 100644 --- a/src/uart/uart.c +++ b/src/uart/uart.c @@ -351,6 +351,97 @@ mraa_uart_stop(mraa_uart_context dev) return MRAA_SUCCESS; } +mraa_result_t +mraa_uart_settings(int index, const char **devpath, const char **name, int* baudrate, int* databits, int* stopbits, mraa_uart_parity_t* parity, unsigned int* ctsrts, unsigned int* xonxoff) { + struct termios term; + int fd; + + if (plat == NULL) { + return MRAA_ERROR_PLATFORM_NOT_INITIALISED; + } + + /* Access through UART index? */ + if (index >= 0 && index < plat->uart_dev_count) { + if (devpath != NULL) { + *devpath = plat->uart_dev[index].device_path; + } + if (name != NULL) { + *name = plat->uart_dev[index].name; + } + } + + /* is any information that requires opening the device requested? */ + if (baudrate != NULL || stopbits != NULL || parity != NULL || databits != NULL || ctsrts != NULL || xonxoff != NULL) { + const char *dev; + + /* Access UART by index or devpath? */ + if (index >=0 && index < plat->uart_dev_count) { + dev = plat->uart_dev[index].device_path; + } else + if (devpath != NULL) { + dev = *devpath; + } else { + return MRAA_ERROR_INVALID_RESOURCE; + } + + fd = open(dev, O_RDONLY | O_NOCTTY); + + if (fd < 0) { + return MRAA_ERROR_INVALID_RESOURCE; + } + + if (tcgetattr(fd, &term)) { + close(fd); + return MRAA_ERROR_INVALID_RESOURCE; + } + + if (databits != NULL) { + switch (term.c_cflag & CSIZE) { + case CS8: + *databits = 8; + break; + case CS7: + *databits = 7; + break; + case CS6: + *databits = 6; + break; + case CS5: + *databits = 5; + default: /* Cannot happen? Linux kernel CSIZE mask is exactly two bits wide */ + break; + } + } + + if (stopbits != NULL) { + *stopbits = term.c_cflag & CSTOPB ? 2 : 1; + } + + if (parity != NULL) { + if (term.c_cflag & PARODD) *parity = MRAA_UART_PARITY_ODD; + else + if (term.c_cflag & PARENB) *parity = MRAA_UART_PARITY_EVEN; + else + *parity = MRAA_UART_PARITY_NONE; + } + + if (baudrate != NULL) { + *baudrate = speed_to_uint(cfgetospeed(&term)); + } + + if (ctsrts != NULL) { + *ctsrts = term.c_cflag & CRTSCTS; + } + + if (xonxoff != NULL) { + *xonxoff = term.c_cflag & (IXON|IXOFF); + } + + close(fd); + } + return MRAA_SUCCESS; +} + mraa_result_t mraa_uart_flush(mraa_uart_context dev) {