Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

serial-unix: on linux, use the termios2 api to support arbitrary baud rates #49

Open
codysch opened this issue Feb 5, 2018 · 2 comments
Milestone

Comments

@codysch
Copy link

codysch commented Feb 5, 2018

Picocom includes some documentation on it: https://github.com/npat-efault/picocom/blob/master/termios2.txt

Assuming underlying adapter support, using termios2 allows more flexible baud rate selection.

@TechnoSam
Copy link

I'm not sure when this was added, but there is a BaudOther available.

@dcuddeback I tried to use a baud rate of 187500 on OS X and I got an "Invalid argument" error. Is this what you mean by

Non-standard baud rates may not be supported on all systems.

I may be able to change the baud rate of of my chip, but its an embedded platform and I'd prefer to not use a bunch of clock dividers to get a standard rate.

This may work on Raspbian Linux, which is my eventual target platform, but for now I'm having trouble getting the serial pins to behave, so I'm not sure when I'll get to test that.

@dcuddeback
Copy link
Owner

@TechnoSam Each platform has a different set of baud rates that it supports via B* constants, with Windows being the lowest common denominator. The BaudNNN constants in serial-core represent the baud rates that are well supported across platforms, and BaudOther can be used to access some platform-specific baud rates. The list that's currently supported are the ones defined in the platforms' termios.h header files. You can see that list here:

let baud = match baud_rate {
core::BaudOther(50) => B50,
core::BaudOther(75) => B75,
core::Baud110 => B110,
core::BaudOther(134) => B134,
core::BaudOther(150) => B150,
core::BaudOther(200) => B200,
core::Baud300 => B300,
core::Baud600 => B600,
core::Baud1200 => B1200,
core::BaudOther(1800) => B1800,
core::Baud2400 => B2400,
core::Baud4800 => B4800,
#[cfg(any(target_os = "macos", target_os = "freebsd", target_os = "openbsd"))]
core::BaudOther(7200) => B7200,
core::Baud9600 => B9600,
#[cfg(any(target_os = "macos", target_os = "freebsd", target_os = "openbsd"))]
core::BaudOther(14400) => B14400,
core::Baud19200 => B19200,
#[cfg(any(target_os = "macos", target_os = "freebsd", target_os = "openbsd"))]
core::BaudOther(28800) => B28800,
core::Baud38400 => B38400,
core::Baud57600 => B57600,
#[cfg(any(target_os = "macos", target_os = "freebsd", target_os = "openbsd"))]
core::BaudOther(76800) => B76800,
core::Baud115200 => B115200,
core::BaudOther(230400) => B230400,
#[cfg(any(target_os = "linux", target_os = "freebsd"))]
core::BaudOther(460800) => B460800,
#[cfg(target_os = "linux")]
core::BaudOther(500000) => B500000,
#[cfg(target_os = "linux")]
core::BaudOther(576000) => B576000,
#[cfg(any(target_os = "linux", target_os = "freebsd"))]
core::BaudOther(921600) => B921600,
#[cfg(target_os = "linux")]
core::BaudOther(1000000) => B1000000,
#[cfg(target_os = "linux")]
core::BaudOther(1152000) => B1152000,
#[cfg(target_os = "linux")]
core::BaudOther(1500000) => B1500000,
#[cfg(target_os = "linux")]
core::BaudOther(2000000) => B2000000,
#[cfg(target_os = "linux")]
core::BaudOther(2500000) => B2500000,
#[cfg(target_os = "linux")]
core::BaudOther(3000000) => B3000000,
#[cfg(target_os = "linux")]
core::BaudOther(3500000) => B3500000,
#[cfg(target_os = "linux")]
core::BaudOther(4000000) => B4000000,
core::BaudOther(_) => return Err(super::error::from_raw_os_error(EINVAL)),
};
.

Those are platform-specific baud rates, but not arbitrary baud rates. The plan is to support arbitrary baud rates, too, but that's not implemented yet. Arbitrary baud rates are also platform-specific. Linux (this ticket) is probably the easiest to support, because it provides the TCSETS2 and TCGETS2 ioctls which are very similar to tcsetattr() and tcgetattr() functions from the POSIX-portable termios API.

For Raspian, you would want to follow this ticket. For OS X, #37 is a complementary ticket.

@dcuddeback dcuddeback added this to the v0.5.0 milestone Jun 19, 2018
dcuddeback added a commit that referenced this issue Jun 22, 2018
termios(3) definitions were added to libc in v0.2.3. Baud rate constants
were added to libc in v0.2.21.

Utilitizing the libc definitions for the termios API enables dropping
the termios crate as a dependency. Fewer dependencies is nice in its own
right, but this also paves the way for a simpler implementation of
custom baud rates on Linux (#49).

Custom baud rates on Linux are best implemented with the termios2 API
provided by the Linux kernel, which is not part of the termios crate.
This most likely means the Linux implementation will use the "unsafe"
interfaces directly for termios2. Doing the same for other termios-based
implementations allows the implementations to remain as similar as
possible, which makes it easier to maintain both implementations in
parallel.
dcuddeback added a commit that referenced this issue Jun 22, 2018
The termios2 struct with TCSETS2/TCGETS2 ioctls is the modern way to set
arbitrary baud rates on Linux. This commit does *not* implement custom
baud rates (#49), but lays the groundwork for doing so by replacing the
POSIX termios API with the Linux-specific termios2 API when Linux is the
compilation target.

Since this is an alternative to the termios(3) API, it was necessary to
manually modify baud rates in c_cflags, c_ospeed, and c_ispeed members
of termios2 in order to implement replacements for cfsetspeed(),
cfgetispeed(), and cfgetospeed(). Helpful documentation can be found in
Picocom's writeup of termios2 [1] and drivers/tty/tty_baudrate.c from
the Linux kernel source [2].

No behavior should change due to this commit.

The termios2 struct was added to libc in v0.2.33.

[1]: https://github.com/npat-efault/picocom/blob/1acf1ddabaf3576b4023c4f6f09c5a3e4b086fb8/termios2.txt
[2]: https://github.com/torvalds/linux/blob/ba4dbdedd3edc2798659bcd8b1a184ea8bdd04dc/drivers/tty/tty_baudrate.c#L49-L121
dcuddeback added a commit that referenced this issue Jun 22, 2018
[close #49]

Implements arbitrary baud rates for Linux by utilizing BOTHER and
c_ospeed/c_ispeed in the termios2 struct.
KoffeinFlummi pushed a commit to KoffeinFlummi/serial-rs that referenced this issue Aug 26, 2020
termios(3) definitions were added to libc in v0.2.3. Baud rate constants
were added to libc in v0.2.21.

Utilitizing the libc definitions for the termios API enables dropping
the termios crate as a dependency. Fewer dependencies is nice in its own
right, but this also paves the way for a simpler implementation of
custom baud rates on Linux (dcuddeback#49).

Custom baud rates on Linux are best implemented with the termios2 API
provided by the Linux kernel, which is not part of the termios crate.
This most likely means the Linux implementation will use the "unsafe"
interfaces directly for termios2. Doing the same for other termios-based
implementations allows the implementations to remain as similar as
possible, which makes it easier to maintain both implementations in
parallel.
KoffeinFlummi pushed a commit to KoffeinFlummi/serial-rs that referenced this issue Aug 26, 2020
The termios2 struct with TCSETS2/TCGETS2 ioctls is the modern way to set
arbitrary baud rates on Linux. This commit does *not* implement custom
baud rates (dcuddeback#49), but lays the groundwork for doing so by replacing the
POSIX termios API with the Linux-specific termios2 API when Linux is the
compilation target.

Since this is an alternative to the termios(3) API, it was necessary to
manually modify baud rates in c_cflags, c_ospeed, and c_ispeed members
of termios2 in order to implement replacements for cfsetspeed(),
cfgetispeed(), and cfgetospeed(). Helpful documentation can be found in
Picocom's writeup of termios2 [1] and drivers/tty/tty_baudrate.c from
the Linux kernel source [2].

No behavior should change due to this commit.

The termios2 struct was added to libc in v0.2.33.

[1]: https://github.com/npat-efault/picocom/blob/1acf1ddabaf3576b4023c4f6f09c5a3e4b086fb8/termios2.txt
[2]: https://github.com/torvalds/linux/blob/ba4dbdedd3edc2798659bcd8b1a184ea8bdd04dc/drivers/tty/tty_baudrate.c#L49-L121
KoffeinFlummi pushed a commit to KoffeinFlummi/serial-rs that referenced this issue Aug 26, 2020
[close dcuddeback#49]

Implements arbitrary baud rates for Linux by utilizing BOTHER and
c_ospeed/c_ispeed in the termios2 struct.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants