How can I set a custom baud rate on Linux?
Solution 1
I noticed the same thing about BOTHER not being defined. Like Jamey Sharp said, you can find it in <asm/termios.h>
. Just a forewarning, I think I ran into problems including both it and the regular <termios.h>
file at the same time.
Aside from that, I found with the glibc I have, it still didn't work because glibc's tcsetattr was doing the ioctl for the old-style version of struct termios which doesn't pay attention to the speed setting. I was able to set a custom speed by manually doing an ioctl with the new style termios2 struct, which should also be available by including <asm/termios.h>
:
struct termios2 tio;
ioctl(fd, TCGETS2, &tio);
tio.c_cflag &= ~CBAUD;
tio.c_cflag |= BOTHER;
tio.c_ispeed = 12345;
tio.c_ospeed = 12345;
ioctl(fd, TCSETS2, &tio);
Solution 2
You can set a custom baud rate using the stty
command on Linux. For example, to set a custom baud rate of 567890 on your serial port /dev/ttyX0, use the command:
stty -F /dev/ttyX0 567890
Solution 3
dougg3 has this pretty much (I can't comment there). The main additional thing you need to know is the headers which don't conflict with each other but do provide the correct prototypes. The answer is
#include <stropts.h>
#include <asm/termios.h>
After that you can use dougg3's code, preferably with error checking round the ioctl() calls. You will probably need to put this in a separate .c file to the rest of your serial port code which uses the normal termios to set other parameters. Doing POSIX manipulations first, then this to set the custom speed, works fine on the built-in UART of the Raspberry Pi to get a 250k baud rate.
Solution 4
BOTHER
appears to be available from <asm/termios.h>
on Linux. Pulling the definition from there is going to be wildly non-portable, but I assume this API is non-portable anyway, so it's probably no big loss.

Admin
Updated on September 28, 2021Comments
-
Admin over 1 year
I want to communicate over my serial port on Linux to a device with a non-standard-baud rate that is not defined in
termios.h
.I tried the "baud rate aliasing"-method from this post, but when I execute my C-program (I’ve named it "testprogram"), Linux says
"testprogram sets custom speed on ttyS0. This is deprecated."
I did some search on Google, and it seems that there is another (newer?) method to change the baud rate to a non-standard-value: On http://sourceware.org/ml/libc-help/2009-06/msg00016.html the author says that the
c_flag
ofstruct termios
must be OR’d withBOTHER (=CBAUDEX | B0)
.With this method the baud rates are set directly in the
c_ispeed
andc_ospeed
-members of thestruct termios
. However, I don’t know how I use this method in my C program. Like the author said, there is noBOTHER
defined/available when I includetermios.h
, so what should be done to set the baud rate this way?How can I set the baud rate to a non-standard-value without changing the kernel?
-
Sławek over 8 yearsLink to the full command line program: gist.github.com/sentinelt/3f1a984533556cf890d9
-
Sławek over 8 yearsOn linux it returns 'invalid argument'
-
manav m-n over 8 years@Sławek Make sure your serial/COM port device supports the baud rate.
stty -F /dev/ttyS0 115200
-
Sławek over 8 yearsIt does. It works with dougg3 solution. Looks like stty supports only predefined baud rates.
-
falstaff over 6 yearsIf you also try to include
sys/ioctl.h
along withasm/termios.h
the compiler might complain about duplicate definitions:error: redefinition of 'struct termios'
. In that case, including onlyasm/ioctls.h
andasm/termbits.h
might help. -
Mustafa Chelik about 4 yearsWhat's the deal with non-POSIX thing? What should I do for that? Only define
_BSD_SOURCE
? Nothing for compiler? -
EFraim over 3 yearsSee unix.stackexchange.com/questions/327188/… for a full solution, including all the missing definitions
-
Peter Mortensen over 1 yearI highly doubt this works at all (I get the same result as Sławek for non-standard baud rate). Can you revise your answer (e.g., under which circumstances it may work)? And delete it if it doesn't actually work? It probably only works for the standard defined ones: 300, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200, 230400, 460800, 500600, 576000, 921600, 1000000, 1152000, 1500000, 2000000, 2500000, 3000000, 3500000, and 4000000