# \[adacl-serial 8.0.1\] I pointed GNAT.Serial\_Communications at the wrong termios

**URL:** https://forum.ada-lang.io/t/adacl-serial-8-0-1-i-pointed-gnat-serial-communications-at-the-wrong-termios/4799
**Category:** Releases
**Tags:** spark, embedded, ada, gnat
**Created:** [October 5, 2026, 2:35pm UTC](https://forum.ada-lang.io/t/adacl-serial-8-0-1-i-pointed-gnat-serial-communications-at-the-wrong-termios/4799 "2026-10-05T14:35:18Z")
**Posts on this page:** 3
**Page:** 1

<div class="post-metadata">

### Author: ![krischik](https://forum.ada-lang.io/user_avatar/forum.ada-lang.io/krischik/32/420_2.png) [@krischik](https://forum.ada-lang.io/u/krischik)
#### Post date: [October 5, 2026, 2:35pm UTC](https://forum.ada-lang.io/t/adacl-serial-8-0-1-i-pointed-gnat-serial-communications-at-the-wrong-termios/4799/1 "2026-10-05T14:35:18Z")

</div>

I wanted a serial port on macOS, so I did the obvious thing and reached for `GNAT.Serial_Communications`. The manual  
does say GNU/Linux and Windows only. I tried anyway.

The simple case worked. Open the calculator first, then the application, and the link came up. Establishing it the other  
way round did not. Timeouts did not fire, so a retry never ran. I spent the afternoon tuning those timeouts so the two  
ends could meet in either order, staring at `Searching for Calculator .` and waiting for the second dot — the one  
that means a retry — which never appeared.

That is the undesired behaviour. Not a dead port: a port that works until the program depends on a timeout. Linux and  
macOS both have `termios`, `tcflag_t` and `speed_t`, and from the Ada side those names look portable. They are not the  
same bits.

On Linux the baud rate is a token in `c_cflag`, in the `CBAUD` / `CBAUDEX` field. `B9600` is `8#000015#` — thirteen, not  
9600 — and `B115200` is `8#0010002#`. `tcflag_t` and `speed_t` are unsigned int. `cfsetospeed` writes the token; the  
kernel turns the token into a line speed. Classic `struct termios` has no separate speed members.

On macOS both types are unsigned long. The structure has `c_ispeed` and `c_ospeed`, and `cfsetospeed` stores a numeric  
rate in `c_ospeed`. There `B9600` really is 9600. A rate that is not one of the `B*` constants goes through the  
`IOSSIOSPEED` ioctl, not through another flag token.

So a Linux body pointed at a Darwin port is not a clean failure. A plain transfer can still complete, which is why  
opening the calculator first looked fine. What does not survive is the rest of the structure. `tcflag_t` is a different  
width, `speed_t` is a numeric rate on macOS and a `CBAUD` token on Linux, and the timeout lives in `c_cc` as `VMIN` /  
`VTIME` — the array that, on macOS, is followed by `c_ispeed` and `c_ospeed`. Feed it the Linux layout and a read that  
should have timed out waits instead. The second dot never comes.

The fix is in the [`adacl_serial`](https://alire.ada.dev/crates/adacl_serial) crate, version 8.0.0.  
`AdaCL.Serial_Communications` keeps the GNAT specification. On Linux and Windows it is a rename of  
`GNAT.Serial_Communications`, because that body is the right one there. On macOS it is a Darwin body: numeric `speed_t`,  
the macOS layout, and `IOSSIOSPEED` where the rate is not a standard constant. `AdaCL.Serial_IO` sits on top — a null  
extension, so the calls read as `Port.Put_Line` and `Port.Expect` — and is proven to SPARK gold. Application code uses  
the one package name on every host.

I have written up how to open a port, including why `Block => False` matters for a calculator protocol, at  
[https://adacl.sourceforge.net/adacl-serial/](https://adacl.sourceforge.net/adacl-serial/). GNATdoc is the reference for the subprograms; that page is only the  
start.

The proper long-term home for the Darwin body is GCC. I have not prepared that patch — the contribution process is new  
to me. If someone who already knows how a GCC change is put together is willing to help, I would like to upstream it.  
Shameless vanity: having my name in the GCC source tree would be cool.

Thanks in advance.

---

<div class="post-metadata">

### Author: ![Max](https://forum.ada-lang.io/user_avatar/forum.ada-lang.io/max/32/21_2.png) [@Max](https://forum.ada-lang.io/u/Max)
#### Post date: [October 5, 2026, 2:41pm UTC](https://forum.ada-lang.io/t/adacl-serial-8-0-1-i-pointed-gnat-serial-communications-at-the-wrong-termios/4799/2 "2026-10-05T14:41:16Z")

</div>

Recent Glibc versions have changed encoding for speed and it breaks API and GNAT.Serial\_Communications. I’ve opened a ticket at AdaCore. See details:

> [@\`GNAT.Serial\_Communications\` broke on Ubuntu 26.04](https://forum.ada-lang.io/t/gnat-serial-communications-broke-on-ubuntu-26-04/4459):
>
> GNAT.Serial\_Communications broke on Ubuntu 26.04 / glibc 2.42+, here is why (and how to fix it) Hey everyone, If you’ve recently upgraded your Linux environment (running Ubuntu 26.04 or any distro with glibc 2.42+) and noticed your Ada serial port code suddenly stopped working, you aren’t losing your mind. If you are using an Alire-provided GNAT toolchain (like GCC 15), there is a subtle breaking change under the hood of glibc that directly clashes with how GNAT bakes in OS constants. …

---

<div class="post-metadata">

### Author: ![krischik](https://forum.ada-lang.io/user_avatar/forum.ada-lang.io/krischik/32/420_2.png) [@krischik](https://forum.ada-lang.io/u/krischik)
#### Post date: [October 5, 2026, 2:59pm UTC](https://forum.ada-lang.io/t/adacl-serial-8-0-1-i-pointed-gnat-serial-communications-at-the-wrong-termios/4799/3 "2026-10-05T14:59:04Z")

</div>

That’s annoying as I provide **swiss\_micros\_tools** for windows, linux and macOS and now I have to fix the linux version of `GNAT.Serial_Communications` as well. And in a way that `alr get -b swiss_micros_tools` just works.
