schmonz.com is a Fediverse instance that uses the ActivityPub protocol. In other words, users at this host can communicate with people that use software like Mastodon, Pleroma, Friendica, etc. all around the world.
This server runs the snac software and there is no automatic sign-up process.
Whilst researching this, I had a look at some of the libraries out there to see how they do it on different operating systems.
Microsoft Windows and Apple MacOS X provide system APIs for doing this.
On Linux, some libraries go poking around in `/dev/serial/*`, others go nosing through `/sys/class/tty/*`. Some just look for specific names in `/dev` and hope for the best. `pyserial` also checks `/proc/tty/drivers` on Linux, but everywhere else in POSIX land it uses `glob`.
Most do not consider BSD at all. You're on your own to learn what serial ports your computer has. It's a mess.
#NetBSD has a `/kern` virtual filesystem which is similar to `/sys` in Linux… so there *is* scope there to maybe put some sort of virtual text file that dumps a mapping of devices and what device nodes they're at. My mind also thinks about OpenFirmware's DeviceTree.
BSD in general, has the same problem Linux had years ago: it assumed the hardware never changed. In the 80s and 90s, that was mostly true, your devices were hard-wired into "busses". You mostly ignored that there was a ISA bus, you just "knew" you had a device at address 0x300 and "talked" to it. It was there at power on, and there at shutdown.
SCSI was a little more complicated, you spoke to your disk drive *through* this HBA card.
Then came along Firewire, USB and Bluetooth. Devices could come and go as they pleased. Moreover, USB is a tree structure and Bluetooth is a mesh radio network. A flat structure doesn't quite describe the situation. I'm seeing a lot of wisdom behind the idea of Open Firmware's DeviceTree… and it seems to me, the kernel of a modern OS needs to track a live changing representation of this. A big part of keeping track will be providing a mechanism for the userspace to learn of changes in this tree, and to find where things are.
While I don't expect them to wholesale copy Linux, I think there is merit in the kernel calling a userspace application to "set up" devices when they are detected, and "tear down" those devices when they are removed.
This is `udev` in Linux and it is very handy even if it can be a pain in the bum to debug.
I've also seen the virtual `/dev` filesystem route used. Linux used to have `devfs`, and SyllableOS also used such a system. Not saying that's the best approach, but it is another way of exposing this information to the system.
Not sure which is the "right" approach, but I don't think a static "nothing ever changes" approach is viable here.
Playing around with #NetBSD again… so I have a Intel NUC running it. One of the thing I frequently have to deal with, being an embedded software developer *and* an amateur radio operator, is #SerialPorts.
More often than not, USB serial ports. Now, I'm used to the Linux way of doing things, where everything is accessed through a /dev/tty* device.
We used to do it the BSD way with a device like /dev/cua0 (16550 UART on ISA 0x3f8 IRQ 4; COM1 for you DOS people) being your serial port ignoring carrier detect, and /dev/ttyS0 was the same serial port but required CD to be up. This got deprecated years ago, so /dev/cua0 disappeared, and we were left with /dev/ttyS0.
I grabbed a test rig I made for work, this is Zephyr RTOS on a Raspberry Pi Pico. It enumerates two CDC-ACM serial ports, one with the Zephyr shell, and the other is a USB serial port. You use the shell port to tell it how to route the RXD/TXD lines on the other serial port, with the board supporting RS-485, RS-422 and TTL serial. On Linux, it shows up as `/dev/ttyACM${n}` and `/dev/ttyACM$(( ${n} + 1 )`. `udev` also creates these symbolic links:
```
stuartl@rikishi ~ $ ls -l /dev/serial/by-id
total 0
lrwxrwxrwx 1 root root 13 Jul 26 10:58 usb-WideSky.Cloud_Pty_Ltd_WideSky_Hub_Test_Rig_E663AC91D3665F30-if00 -> ../../ttyACM0
lrwxrwxrwx 1 root root 13 Jul 26 10:58 usb-WideSky.Cloud_Pty_Ltd_WideSky_Hub_Test_Rig_E663AC91D3665F30-if02 -> ../../ttyACM1
stuartl@rikishi ~ $ ls -l /dev/serial/by-path/
total 0
lrwxrwxrwx 1 root root 13 Jul 26 10:58 pci-0000:00:14.0-usb-0:2:1.0 -> ../../ttyACM0
lrwxrwxrwx 1 root root 13 Jul 26 10:58 pci-0000:00:14.0-usb-0:2:1.2 -> ../../ttyACM1
lrwxrwxrwx 1 root root 13 Jul 26 10:58 pci-0000:00:14.0-usbv2-0:2:1.0 -> ../../ttyACM0
lrwxrwxrwx 1 root root 13 Jul 26 10:58 pci-0000:00:14.0-usbv2-0:2:1.2 -> ../../ttyACM1
```
This is handy because if I have two of these, it doesn't matter which gets detected first, I know which device is which. The links ending in `-if02` or `.2` will be the data port, and the `-if00` / `.0` ones will be the shell control port.
In NetBSD, I plug this same MCU in and I get 4 devices:
- `/dev/dtyU0`
- `/dev/dtyU1`
- `/dev/ttyU0`
- `/dev/ttyU1`
The files actually always exist, but they get mapped to this physical device when the driver detects it and enumerates it on USB.
If I plug in another dongle, I get another pair, a `/dev/dtyU2` and a `/dev/ttyU2`. The choice of `/dev/dtyU[012]` is dependent on which order the devices is detected… which on USB is indeterminate as they can be hotplugged.
The only clue I get is the `usbdevs -v`; it shows a device number and serial number information.
```
vk4msl-nbsd# usbdevs -v
Controller /dev/usb0:
addr 0: super speed, self powered, config 1, xHCI root hub(0x0000), NetBSD(0x0000), rev 1.00(0x0100)
port 1 disabled
port 2 disabled
port 3 disabled
port 4 disabled
Controller /dev/usb1:
addr 0: high speed, self powered, config 1, xHCI root hub(0x0000), NetBSD(0x0000), rev 1.00(0x0100)
port 1 powered
port 2 addr 17: full speed, power 100 mA, config 1, USB-Serial Controller D(0x2303), Prolific Technology Inc.(0x067b), rev 4.00(0x0400)
port 3 addr 1: low speed, power 100 mA, config 1, CASUE USB KB(0x6a21), vendor 2a7a(0x2a7a), rev 0.01(0x0001)
port 4 addr 18: full speed, self powered, config 1, WideSky Hub Test Rig(0x5678), WideSky.Cloud Pty Ltd(0x1234), rev 4.03(0x0403), serial E663AC91D3665F30
port 5 powered
port 6 powered
port 7 addr 3: full speed, self powered, config 1, product 0a2a(0x0a2a), Intel(0x8087), rev 0.01(0x0001)
port 8 powered
port 9 powered
port 10 powered
port 11 powered
…
```
lacking is the knowledge that there are *two* devices allocated to device 18 (the test rig).
Given a `/dev/ttyU${n}` or `/dev/dtyU${n}` device node, how do I find out about the device attached to it? Seems assuming a device node is fraught with danger.
The Blog Option in littleFedi
...and yes, this is build and served by the Raspberry Pi Zero W, powered by NetBSD
https://rpi0w.stefanomarinelli.it/@stefano/blog/691cb62e-e7a1-434b-ba65-d059ee58ac41/
The Blog Option in littleFedi
littleFedi, like many social platforms, had both a strength and a limit. Posts, by their nature, are ephemeral. They get published, federated (unless local-only, which littleFedi handles) and then, over time, lost. Partly through self-deletion, partly through their normal blending in with the thousands of other posts that pile up over time. Sometimes, though, we want something to stay. And not just stay as a social post, but as an actual blog. A bit like with BSSG, I had thought it would be convenient to have a minimal system. Not to compete with WordPress or other solutions, but to have a small blog, integrated into littleFedi, that would produce and serve a blog updated every now and then, whenever the person writing felt like doing it.
And that's why the blog option was born.
The idea is simple: when you write a post, from the web UI or from the CLI, there's a checkbox, "blog post". If you check it, that post stops being just a status that will scroll past and disappear. littleFedi renders it into a real static site. No JavaScript, just HTML and CSS, an Atom feed, tag pages, a chronological archive. Nothing exotic, nothing that needs maintenance five years from now.
The blog isn't a parallel system you have to feed separately. It's not an export, not an import, not a bridge to some other CMS. The post you wrote is the blog post. Same database, same act of writing, still boostable, still repliable, still part of the conversation on the fediverse side. The blog is just a second representation of the same content, generated automatically. Every time you create, edit, or delete a blog post, the whole static site for your account gets rebuilt from scratch, and the new version replaces the old one atomically, so nobody ever lands on a half-built page. If the build fails, the previous version stays in place. Simple, but it has to work reliably, or the whole idea is pointless.
That's the core of it: two representations of the same post. As a status, it lives in the fediverse, interactive, part of the conversation, subject to replies and boosts like anything else. As a static page, it lives on the web, durable, indexable, with a permalink, something an RSS reader can hold onto. You don't have to decide in advance which posts deserve to last. You write normally, and if something turns out to be worth keeping, you flag it, and it gets its own page.
One detail I cared about while thinking this through: the generated site has to be self-contained. When littleFedi builds it, media gets copied or hard-linked into the generated directory - images, audio, video. If it's stored on S3, it keeps its public URL directly. Either way, the point is that the site on disk doesn't depend on the instance staying up. If the server goes down tomorrow, the blog files are still a complete, working website. That wasn't an afterthought, it was one of the requirements from the start.
Not every account gets a blog, and that's intentional. The instance admin has to enable the feature globally ([blog] enabled = true), and then grant it per account. It's not meant to be a CMS, and I didn't want it to become one. Blog posts can't be replies, can't be boosts, have to be public and top-level. These are constraints, not missing features: the blog is for your own writing, not for threads or reshared content.
There's no JavaScript anywhere in the generated site. That was deliberate too. It loads fast, it works offline if you cache it, and it will still render correctly in ten years without anyone having to update a dependency.
In the end, the blog option doesn't ask you to choose between writing socially and writing something permanent. You keep writing the way you always do, on littleFedi, and if a post is worth keeping, you check a box. No separate platform, no migration, no vendor lock-in. Just your own posts, some of them rendered into a small static site you can host anywhere, built out of something that already existed on the open web.
Remember: all this is being currently served by a Raspberry PI Zero W powered by NetBSD
#littleFedi #SSG #BSSG #OwnYourData #Blogging #Fediverse #NetBSD
Since I am an idiot, let's just download RC7 on the RC6 machine, reformat the USB drive and reinstall from that.
Friday night is all right for reinstalling #NetBSD 