Improved UART with async pin control
This commit is contained in:
parent
053dc8d5f8
commit
09ceb92db4
@ -97,6 +97,8 @@ struct serial_port_unix {
|
|||||||
int fd; // Serial port file descriptor
|
int fd; // Serial port file descriptor
|
||||||
struct termios termios_backup; // Terminal info before using the port
|
struct termios termios_backup; // Terminal info before using the port
|
||||||
struct termios termios_new; // Terminal info during the transaction
|
struct termios termios_new; // Terminal info during the transaction
|
||||||
|
int pins_backup;
|
||||||
|
int pins_new;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define UART_DATA( X ) ((struct serial_port_unix *) X)
|
#define UART_DATA( X ) ((struct serial_port_unix *) X)
|
||||||
@ -141,10 +143,15 @@ uart_open(const char *pcPortName)
|
|||||||
uart_close_ext(sp, true);
|
uart_close_ext(sp, true);
|
||||||
return INVALID_SERIAL_PORT;
|
return INVALID_SERIAL_PORT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ioctl(sp->fd, TIOCMGET, &sp->pins_backup);
|
||||||
|
sp->pins_new = sp->pins_backup;
|
||||||
|
uart_set_pins(sp, 0);
|
||||||
|
|
||||||
return sp;
|
return sp;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
int
|
||||||
uart_flush_input(serial_port sp, bool wait)
|
uart_flush_input(serial_port sp, bool wait)
|
||||||
{
|
{
|
||||||
// flush commands may seem to be without effect
|
// flush commands may seem to be without effect
|
||||||
@ -156,34 +163,37 @@ uart_flush_input(serial_port sp, bool wait)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// This line seems to produce absolutely no effect on my system (GNU/Linux 2.6.35)
|
// This line seems to produce absolutely no effect on my system (GNU/Linux 2.6.35)
|
||||||
tcflush(UART_DATA(sp)->fd, TCIFLUSH);
|
if (tcflush(UART_DATA(sp)->fd, TCIFLUSH)) {
|
||||||
|
return NFC_EIO;
|
||||||
|
}
|
||||||
// So, I wrote this byte-eater
|
// So, I wrote this byte-eater
|
||||||
// Retrieve the count of the incoming bytes
|
// Retrieve the count of the incoming bytes
|
||||||
int available_bytes_count = 0;
|
int available_bytes_count = 0;
|
||||||
int res;
|
int res;
|
||||||
res = ioctl(UART_DATA(sp)->fd, FIONREAD, &available_bytes_count);
|
res = ioctl(UART_DATA(sp)->fd, FIONREAD, &available_bytes_count);
|
||||||
if (res != 0) {
|
if (res != 0) {
|
||||||
return;
|
return NFC_EIO;
|
||||||
}
|
}
|
||||||
if (available_bytes_count == 0) {
|
if (available_bytes_count == 0) {
|
||||||
return;
|
return NFC_SUCCESS;
|
||||||
}
|
}
|
||||||
char *rx = malloc(available_bytes_count);
|
char *rx = malloc(available_bytes_count);
|
||||||
if (!rx) {
|
if (!rx) {
|
||||||
perror("malloc");
|
perror("malloc");
|
||||||
return;
|
return NFC_ESOFT;
|
||||||
}
|
}
|
||||||
// There is something available, read the data
|
// There is something available, read the data
|
||||||
if (read(UART_DATA(sp)->fd, rx, available_bytes_count) < 0) {
|
if (read(UART_DATA(sp)->fd, rx, available_bytes_count) < 0) {
|
||||||
perror("uart read");
|
perror("uart read");
|
||||||
free(rx);
|
free(rx);
|
||||||
return;
|
return NFC_EIO;
|
||||||
}
|
}
|
||||||
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%d bytes have eaten.", available_bytes_count);
|
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "%d bytes have eaten.", available_bytes_count);
|
||||||
free(rx);
|
free(rx);
|
||||||
|
return NFC_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
int
|
||||||
uart_set_speed(serial_port sp, const uint32_t uiPortSpeed)
|
uart_set_speed(serial_port sp, const uint32_t uiPortSpeed)
|
||||||
{
|
{
|
||||||
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Serial port speed requested to be set to %d baud.", uiPortSpeed);
|
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "Serial port speed requested to be set to %d baud.", uiPortSpeed);
|
||||||
@ -224,15 +234,17 @@ uart_set_speed(serial_port sp, const uint32_t uiPortSpeed)
|
|||||||
default:
|
default:
|
||||||
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to set serial port speed to %d baud. Speed value must be one of those defined in termios(3).",
|
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to set serial port speed to %d baud. Speed value must be one of those defined in termios(3).",
|
||||||
uiPortSpeed);
|
uiPortSpeed);
|
||||||
return;
|
return NFC_ESOFT;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Set port speed (Input and Output)
|
// Set port speed (Input and Output)
|
||||||
cfsetispeed(&(UART_DATA(sp)->termios_new), stPortSpeed);
|
cfsetispeed(&(UART_DATA(sp)->termios_new), stPortSpeed);
|
||||||
cfsetospeed(&(UART_DATA(sp)->termios_new), stPortSpeed);
|
cfsetospeed(&(UART_DATA(sp)->termios_new), stPortSpeed);
|
||||||
if (tcsetattr(UART_DATA(sp)->fd, TCSADRAIN, &(UART_DATA(sp)->termios_new)) == -1) {
|
if (tcsetattr(UART_DATA(sp)->fd, TCSADRAIN, &(UART_DATA(sp)->termios_new)) == -1) {
|
||||||
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "%s", "Unable to apply new speed settings.");
|
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to apply new speed settings.");
|
||||||
|
return NFC_EIO;
|
||||||
}
|
}
|
||||||
|
return NFC_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t
|
uint32_t
|
||||||
@ -275,11 +287,13 @@ uart_get_speed(serial_port sp)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
uart_close_ext(const serial_port sp, const bool restore_termios)
|
uart_close_ext(const serial_port sp, const bool restore_status)
|
||||||
{
|
{
|
||||||
if (UART_DATA(sp)->fd >= 0) {
|
if (UART_DATA(sp)->fd >= 0) {
|
||||||
if (restore_termios)
|
if (restore_status) {
|
||||||
tcsetattr(UART_DATA(sp)->fd, TCSANOW, &UART_DATA(sp)->termios_backup);
|
tcsetattr(UART_DATA(sp)->fd, TCSANOW, &UART_DATA(sp)->termios_backup);
|
||||||
|
ioctl(UART_DATA(sp)->fd, TIOCMSET, &UART_DATA(sp)->pins_backup);
|
||||||
|
}
|
||||||
close(UART_DATA(sp)->fd);
|
close(UART_DATA(sp)->fd);
|
||||||
}
|
}
|
||||||
free(sp);
|
free(sp);
|
||||||
@ -381,6 +395,36 @@ uart_send(serial_port sp, const uint8_t *pbtTx, const size_t szTx, int timeout)
|
|||||||
return NFC_EIO;
|
return NFC_EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Asserts/deasserts asynchronous control signals of RS232 ports
|
||||||
|
*
|
||||||
|
* @return 0 on success, otherwise a driver error is returned
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
uart_set_pins(serial_port sp, int status)
|
||||||
|
{
|
||||||
|
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_DEBUG, "DTR: %d RTS: %d", (status & UART_DTR) ? 1 : 0, (status & UART_RTS) ? 1 : 0);
|
||||||
|
|
||||||
|
int posix = 0;
|
||||||
|
if (status & UART_DTR)
|
||||||
|
posix |= TIOCM_DTR;
|
||||||
|
if (status & UART_RTS)
|
||||||
|
posix |= TIOCM_RTS;
|
||||||
|
|
||||||
|
/* TODO - Uncomment after fixing Cygwin tcgetattr, which modifies pin status on its own
|
||||||
|
if (UART_DATA(sp)->pins_new == posix)
|
||||||
|
return NFC_SUCCESS;
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (ioctl(UART_DATA(sp)->fd, TIOCMSET, &posix) == -1) {
|
||||||
|
log_put(LOG_GROUP, LOG_CATEGORY, NFC_LOG_PRIORITY_ERROR, "Unable to set asynchronous control pins.");
|
||||||
|
return NFC_EIO;
|
||||||
|
}
|
||||||
|
|
||||||
|
UART_DATA(sp)->pins_new = posix;
|
||||||
|
return NFC_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
char **
|
char **
|
||||||
uart_list_ports(void)
|
uart_list_ports(void)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -49,14 +49,18 @@ typedef void *serial_port;
|
|||||||
|
|
||||||
serial_port uart_open(const char *pcPortName);
|
serial_port uart_open(const char *pcPortName);
|
||||||
void uart_close(const serial_port sp);
|
void uart_close(const serial_port sp);
|
||||||
void uart_flush_input(const serial_port sp, bool wait);
|
int uart_flush_input(const serial_port sp, bool wait);
|
||||||
|
|
||||||
void uart_set_speed(serial_port sp, const uint32_t uiPortSpeed);
|
int uart_set_speed(serial_port sp, const uint32_t uiPortSpeed);
|
||||||
uint32_t uart_get_speed(const serial_port sp);
|
uint32_t uart_get_speed(const serial_port sp);
|
||||||
|
|
||||||
int uart_receive(serial_port sp, uint8_t *pbtRx, const size_t szRx, void *abort_p, int timeout);
|
int uart_receive(serial_port sp, uint8_t *pbtRx, const size_t szRx, void *abort_p, int timeout);
|
||||||
int uart_send(serial_port sp, const uint8_t *pbtTx, const size_t szTx, int timeout);
|
int uart_send(serial_port sp, const uint8_t *pbtTx, const size_t szTx, int timeout);
|
||||||
|
|
||||||
|
#define UART_DTR (1 << 0)
|
||||||
|
#define UART_RTS (1 << 1)
|
||||||
|
int uart_set_pins(serial_port sp, int status);
|
||||||
|
|
||||||
char **uart_list_ports(void);
|
char **uart_list_ports(void);
|
||||||
void uart_list_free(char **acPorts);
|
void uart_list_free(char **acPorts);
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user