Things are, unfortunately, driver-dependent. Good drivers will implement all of the methods below. Bad drivers will implement only some of the methods. Thus you need to try them all. All of the methods below are implemented in the helper functions in linux/drivers/tty/serial/serial_core.c.
The following 4 choices are available.
Standard baud rates are set in
tty->termios->c_cflag
. You can choose from:B0 B50 B75 B110 B134 B150 B200 B300 B600 B1200 B1800 B2400 B4800 B9600 B19200 B38400 B57600 B115200 B230400
If you need rates not listed above, e.g. 460800 (this is a deprecated hack that the kernel developers wish to die, per the source code comments):
set
tty->termios->c_cflag
speed toB38400
call
TIOCSSERIAL
ioctl with (struct serial_struct) set as follows:serial->flags & ASYNC_SPD_MASK == ASYNC_SPD_[HI, VHI, SHI, WARP] // this is an assertion, i.e. what your code must achieve, not how
This sets alternate speed to HI: 57600, VHI: 115200, SHI: 230400, WARP: 460800
You can set an arbitrary speed using alt_speed as follows:
Set
tty->termios->c_cflag
speed toB38400
. This is unrelated to the speed you chose!Set the intended speed in
tty->alt_speed
. It gets ignored whenalt_speed==0
.
You can also an arbitrary speed rate by setting custom divisor as follows:
Set
tty->termios->c_cflag
speed toB38400
. This is unrelated to the speed you chose!bool set_baudrate(int fd, long baudrate) { struct termios term; if (tcgetattr(fd, &term)) return false; term.c_cflag &= ~(CBAUD | CBAUDEX); term.c_cflag |= B38400; if (tcsetattr(fd, TCSANOW, &term)) return false; // cont'd below
Call
TIOCSSERIAL
ioctl withstruct serial_struct
set as follows:serial->flags & ASYNC_SPD_MASK == ASYNC_SPD_CUST serial->custom_divisor == serial->baud_base / your_new_baudrate // these are assertions, i.e. what your code must achieve, not how
How to do it? First get the structure filled (including
baud_base
you need) by callingTIOCGSERIAL
ioctl. Then modify it to indicate the new baudrate and set it withTIOCSSERIAL
:// cont'd struct serial_struct serial; if (ioctl(fd, TIOCGSERIAL, &serial)) return false; serial->flags &= ~ASYNC_SPD_MASK; serial->flags |= ASYNC_SPD_CUST; serial->custom_divisor = serial->baud_base / baudrate. if (ioctl(fd, TIOCSSERIAL, &serial)) return false; return true; }