Appendix · reference

Mobile software

What runs on top of the kernel: Sway, omfreebdy, fuzzel menus, phone controls, and per-category app picks.

This entry summarizes MOBILE_SOFTWARE.md in the repo root — a userland inventory for the FreeBSD-on-PinePhone-Pro setup. Where the rest of this site is about the kernel, drivers, and firmware, this is about everything above init: Sway session, omfreebdy menus, on-screen keyboard, gesture daemon, phone controls, telephony scripts, and per-category recommendations for browser, email, music, calendar, etc.

The full document includes detailed comparison tables for every category and a phased install plan. The summary below picks the load-bearing decisions; consult the source doc for the long tables.

Our setup baseline

GTK fallback knob

The live path is Wayland/Sway. Keep this fallback for GTK4 apps if they hit rendering problems on the phone:

export GSK_RENDERER=cairo

GTK3 apps usually default to Cairo and do not need it.

Sxmo as the reference

Sxmo is still the reference architecture: small programs, shell glue, one-purpose menus, and gestures instead of a giant phone daemon. Our live stack swaps in Sway, fuzzel, mako, wvkbd, and omfreebdy, but the shape is the same. The sxmo gesture map is the direct model for our lisgd bindings: edge swipes for back/forward, app menu, system menu, and keyboard control.

What we can’t steal from sxmo: the dwm patches (we use Sway), callaudiod (Linux-only audio daemon — we’ll use sndio/OSS), ModemManager/mmcli (replaced with direct AT commands), pipewire (Linux-only).

Telephony stack: AT commands, not ModemManager

FreeBSD has no ModemManager, so we talk directly to the EG25-G over USB serial. After mise run modem:power:phone, u3g0 exposes five ports:

DevicePurpose
/dev/cuaU0.0DM / diagnostic candidate
/dev/cuaU0.1GPS NMEA candidate
/dev/cuaU0.2AT command port (confirmed)
/dev/cuaU0.3AT / PPP data candidate (AT confirmed)
/dev/cuaU0.4auxiliary port

The plan is a small set of shell scripts modeled on sxmo:

Reference repos: fuzzybritches0/pinephone (bash AT scripts), milky-sway/pinephone-scripts, and the gold-standard sxmo-utils.

Audio routing for calls is no longer blocked on basic playback: RT5640 loudspeaker output works. The remaining call-audio work is microphone capture plus routing policy between earpiece, loudspeaker, headset, and Bluetooth.

Per-category app picks (one-line summary)

The full document compares 5–8 options per category in a table; the short version of the picks is:

CategoryPick (FreeBSD pkg)Notes
BrowsernetsurfLightweight; falls back to surf for sites needing better rendering, w3m in terminal
File managernnn (terminal) / pcmanfm (GTK2)Both touch-usable
Musiccmus (TUI) / mpv (CLI)Daemon setup: musicpd + ncmpcpp
EmailaercModern terminal client, works with wvkbd
CalendarcalcurseTerminal, lightweight, touch-usable
Notesplain text + vi/nanoSxmo approach
CalculatorgalculatorGTK2, big touch targets, no GPU
MapsfoxtrotgpsOSM tiles, offline cache, GPS support
RSSsfeed (sxmo style) or newsboat
Podcastsnewsboat + podboat + mpvAll in pkg
PDFmupdf (touch pinch-zoom) / zathura (keyboard)
Image viewernsxivThumbnail mode works on small screens
CameraBlocked: no V4L2/media-request on FreeBSD
Clock/alarmshell + at/cron + mako
Weathercurl wttr.inZero deps
Password managerpass + fuzzel wrapper
Night lightwlsunset or custom helperWayland path, package availability TBD
Messagingweechat (IRC + Matrix) / profanity (XMPP)

What not to bother with

Phased install plan

Phase 1 — Core mobile UX (now)

pkg install -y sway swaybg swayidle swaylock fuzzel mako \
  grim slurp wl-clipboard htop picocom

Then install omfreebdy, run its phone install task, and let it manage Sway config blocks for gestures, fuzzel menus, notification/OSD styling, screen power on the hardware power button, WiFi UI, and theme hooks. The install path must also build or install the phone-specific pieces that FreeBSD packages do not provide in the right shape yet: wvkbd-mobintl, lisgd, the fuzzel 1.14.1 touch fix, and the gdk-pixbuf loader cache used by image-backed swaybg. Firefox comes from the package, while the mobile chrome comes from the vendored postmarketOS mobile-config-firefox files.

The account shell is part of the install contract. The phone user must use /usr/local/bin/bash, with .bash_profile sourcing .profile and .bashrc, because omfreebdy’s CLI layer is bash-based. Without that, packages such as eza and the Nerd Font set are present but the visible behavior is missing: plain ls runs instead of the eza --icons --group-directories-first alias. Install gettext-runtime with bash, then refresh ldconfig. If a locally built bundle such as Ladybird is extracted into /usr/local, do not preserve the build user’s owner IDs: a jadams-owned /usr/local/lib makes ldconfig ignore the directory, which breaks SSH login with libintl.so.8 missing before the shell can start.

The live overlay carries the current phone-session repair rules:

Phase 2 — Communication (after modem + SIM working)

Install minicom and picocom; build the AT shell scripts above.

Phase 3 — Daily apps

ssh honor "pkg install -y netsurf pcmanfm nnn galculator calcurse \
  newsboat sfeed feh nsxiv mupdf zathura zathura-pdf-mupdf mpv cmus \
  password-store"

Phase 4 — Rich apps (after audio works)

ssh honor "pkg install -y musicpd ncmpcpp aerc foxtrotgps gpodder"

Phase 5 — Optional enhancements

ssh honor "pkg install -y gnome-calculator gnome-clocks gnome-weather \
  geary keepassxc pidgin weechat profanity"

Remember GSK_RENDERER=cairo as the first fallback for GTK4/GNOME apps that misbehave on the current GPU stack.

Sway media bindings on the phone

The live PinePhone Pro setup is Sway, and the working volume path is FreeBSD mixer(8) plus a tiny wrapper that keeps a single transient OSD on screen. The hardware side buttons arrive as KEY_VOLUMEUP / KEY_VOLUMEDOWN from the local rk_adc_keys driver; Sway just binds those to volume-osd.

bindsym XF86AudioRaiseVolume exec ~/.local/bin/volume-osd up
bindsym XF86AudioLowerVolume exec ~/.local/bin/volume-osd down
bindsym XF86AudioMute exec ~/.local/bin/volume-osd mute
exec_always ~/.local/bin/volume-osd init

Under the hood the helper drives mixer with FreeBSD’s current syntax:

mixer vol=+5%
mixer vol=-5%
mixer vol.mute=toggle

and sends a single replacing mako popup with a progress hint, so the UI behaves like a volume meter instead of a notification stack. The mako styling is generated from the active omfreebdy theme during post-theme-set, so the volume OSD tracks the same accent/background colors as the rest of the session instead of living in a hardcoded config file.

Sway screen power on the phone

The side power button now toggles panel power without locking or suspending the device. libinput debug-events reports the GPIO key as KEY_POWER (116); Sway receives it through XKB as XF86PowerOff, so omfreebdy installs this managed block:

### OMFREEBDY_PHONE_SCREEN_START
bindsym --release XF86PowerOff exec ~/.local/bin/screen-toggle toggle
### OMFREEBDY_PHONE_SCREEN_END

The helper uses swaymsg output <active-output> power off|on on Sway and Hyprland DPMS on Hyprland. On the PinePhone Pro this is intentionally only a screen toggle; suspend and lock policy can be layered on later when the rest of the power-management path is deterministic.

Brightness without desktop assumptions

The panel backlight is PWM-driven, not an ACPI laptop backlight. Do not assume xbacklight or RandR brightness will exist. The right path is a small omfreebdy helper over the kernel backlight/sysctl interface, then bind it to Sway keys or a fuzzel menu.

Battery monitoring

The RK818 PMIC has an on-chip fuel gauge; the driver loads but doesn’t yet expose to userspace. Until it does, polling I²C registers directly is the workaround:

# RK818 on i2c0 addr 0x1c
# 0x21 = BAT_VOL_REGL, 0x22 = BAT_VOL_REGH
i2c -a 0x1c -d r -c 1 -o 0x21 ...

Convert voltage to percentage in your status-bar script.

Cross-references