Skip to content
Snippets Groups Projects
Commit 981be2fa authored by Jonas Höppner's avatar Jonas Höppner
Browse files

rs485echo: Support all baudrates using termios2 ioctl directly from kernel header

The kernel has support for setting the baudrate as integer using BOTHER
as id with the termios2 struct. It seems that this is not yet supported
in the libc, so we are using kernel headers directly.
parent ccb24247
No related branches found
No related tags found
1 merge request!275rs485echo: Support all baudrates using termios2 ioctl directly from kernel header
......@@ -4,16 +4,16 @@ SYSROOT ?= SDKTARGETSYSROOT
top_srcdir ?= $(SYSROOT)/usr
CFLAGS+= -I$(top_srcdir)/include -Wall -Werror
CFLAGS+= -I$(top_srcdir)/include -I. -Wall -Werror
LOADLIBES+= -L$(top_srcdir)/lib -lltp
SRCS=$(TARGET).c
SRCS=$(TARGET).c termios2.c
all: $(TARGET)
$(TARGET): $(SRCS)
@mkdir -p ../bin
@$(CC) $(CFLAGS) $(LDFLAGS) $< $(LOADLIBES) -o ../bin/$@
@$(CC) $(CFLAGS) $(LDFLAGS) $^ $(LOADLIBES) -o ../bin/$@
clean:
rm -f $(TARGET) *.o *.bak *~
......@@ -52,10 +52,12 @@
#include <asm/ioctls.h>
#include <linux/serial.h>
/* Harness Specific Include Files. */
#include "old/test.h"
#include "config.h"
#include "termios2.h"
/* Local Defines */
#if !defined(TRUE) && !defined(FALSE)
......@@ -227,7 +229,7 @@ void tst_dump_data(const char * pre, const char * data, int len)
void
setup()
{
int i;
int i, ret;
struct serial_rs485 rs485;
speed_t baud = B0;
......@@ -242,7 +244,7 @@ setup()
}
if (baud == B0)
//tst_brkm(TBROK, cleanup, "Baud rate not supported (%d)", baudrate);
tst_resm(TWARN, "Baud rate is non standard, tryin anyway (%d)", baudrate);
tst_resm(TWARN, "Baud rate is non standard, trying anyway (%d)", baudrate);
if (!echo_mode)
{
......@@ -305,37 +307,8 @@ setup()
memcpy(termios.c_cc, ttydefchars, MIN(sizeof(termios.c_cc), sizeof(ttydefchars)));
// Set Speed into termios structure
if( baud == B0 )
if( baud != B0 )
{
struct serial_struct serial;
int baudrate_rounded;
// Non standard baudrate
// https://stackoverflow.com/questions/19440268/how-to-set-a-non-standard-baudrate-on-a-serial-port-device-on-linux
// drivers/tty/serial/serial_core.c +491
if (cfsetspeed (&termios, B38400)) {
tst_brkm(TBROK, cleanup,
"Can't set baud rate. Error:%d, %s\n",
errno, strerror(errno));
}
if (ioctl(fd, TIOCGSERIAL, &serial)){
tst_brkm(TBROK, cleanup,
"Failed to do TIOCGSERIAL IOCTL. Error:%d, %s\n",
errno, strerror(errno));
}
serial.flags &= ~ASYNC_SPD_MASK;
serial.flags |= ASYNC_SPD_CUST;
serial.custom_divisor = serial.baud_base / baudrate;
baudrate_rounded = serial.baud_base / serial.custom_divisor;
if( baudrate != baudrate_rounded)
tst_resm(TWARN, "Selected closest baudrate %d.\n", baudrate_rounded);
if (ioctl(fd, TIOCSSERIAL, &serial)){
tst_brkm(TBROK, cleanup,
"Can't set baud rate. Error:%d, %s\n",
errno, strerror(errno));
}
}else{
if (cfsetspeed (&termios, baud)) {
tst_brkm(TBROK, cleanup,
"Can't set baud rate. Error:%d, %s\n",
......@@ -358,10 +331,17 @@ setup()
}
// set new attribute
if (tcsetattr (fd, TCSANOW, &termios)) {
tst_brkm(TBROK, cleanup,
"Can't set device configuration. Error:%d, %s\n",
errno, strerror(errno));
if( baud == B0 ) // Non standard baudrate
{
ret = tty_set_arbitrary_speed(fd, baudrate, &termios);
if( ret < 0)
tst_brkm(TBROK, cleanup, "Can't set baud rate %d.\n", baudrate);
}else{
if (tcsetattr (fd, TCSANOW, &termios)) {
tst_brkm(TBROK, cleanup,
"Can't set device configuration. Error:%d, %s\n",
errno, strerror(errno));
}
}
return;
......@@ -447,6 +427,7 @@ main(int argc, /* number of command line parameters */
char *str_device_name, *str_repetitions, *str_bytes, *str_timeout,
*str_baudrate, *str_delaytime, *str_receive_sleep, *str_fake_data_len,
*str_fake_data;
int ret;
option_t options[] = {
{"b:", &opt_bytes, &str_bytes},
......@@ -571,7 +552,9 @@ main(int argc, /* number of command line parameters */
cycle_count+1, message->data, message->length > 1000 ? "[...]" : "");
// Send message
write(fd, (char*)message, size_of_message);
ret = write(fd, (char*)message, size_of_message);
if( ret < 0 )
tst_brkm(TBROK, cleanup, "Failed to write bytes (%d)", errno);
// Get current time for measuring timeout
gettimeofday(&start, NULL);
......@@ -740,7 +723,9 @@ main(int argc, /* number of command line parameters */
usleep(send_delay);
tst_resm(TINFO, "Received data: %.1000s%s", received_data,
data_length > 1000 ? "[...]" : "");
write(fd, received_data, data_length);
ret = write(fd, received_data, data_length);
if( ret < 0 )
tst_brkm(TBROK, cleanup, "Failed to write bytes (%d)", errno);
tst_resm(TINFO, "Echoed data back to sender");
free(received_data);
received_data = NULL;
......
/* as these includes colide with the ones used in the rs485echo file
this function is in its own file.
The 'termios2' struct seems not available and used in the standard headers
so we use it directly from the kernel headers.
*/
#include <sys/ioctl.h>
#include "/usr/include/asm-generic/termbits.h"
#include "/usr/include/asm-generic/ioctls.h"
int tty_set_arbitrary_speed( int fd, int speed, struct termios * termios)
{
struct termios2 to;
int r, i;
r = ioctl(fd, TCGETS2, &to);
if (r) return -1;
to.c_iflag = termios->c_iflag;
to.c_oflag = termios->c_oflag;
to.c_cflag = termios->c_cflag;
to.c_lflag = termios->c_lflag;
to.c_line = termios->c_line;
for( i = 0; i < NCCS; i++)
to.c_cc[i] = termios->c_cc[i];
speed_t spd = speed;
to.c_ispeed = to.c_ospeed = spd;
to.c_cflag &= ~CBAUD;
to.c_cflag |= BOTHER;
r = ioctl(fd, TCSETSF2, &to);
if (r) return -1;
return 0;
}
int tty_set_arbitrary_speed( int fd, int speed, struct termios * termios);
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment