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: window manager,
on-screen keyboard, gesture daemon, 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
- Device: PinePhone Pro (RK3399S), 4 GB RAM, 720×1440 portrait.
- OS: FreeBSD 15 on SD card.
- Display: X11 via
scfbsoftware rendering. No GPU — every app must work without GL. - Window manager: i3.
- On-screen keyboard: svkbd (built from source; must use
-ddock mode to prevent focus stealing). - Gesture daemon: lisgd, configured for sxmo-style edge gestures.
- Touchscreen: working with multitouch.
- Modem: Quectel EG25-G via USB, AT commands on
/dev/cuaU2. - Audio: RT5640 codec detected, vchan-to-hardware path still being debugged (see essay 13).
- Networking: USB Ethernet to laptop; WiFi via USB dongle (
run(4)) until brcmfmac SDIO comes up.
The critical environment variable
GTK4 apps must be launched with:
export GSK_RENDERER=cairo
Without it GTK4 fails or renders garbage on scfb. GTK3 apps already
default to Cairo on X11 and don’t need it.
Sxmo as the reference
Sxmo is the canonical X11 mobile environment for the PinePhone family. We borrow heavily from its architecture: dmenu/rofi for menus, dunst for notifications, slock for screen lock, shell scripts for everything else. The sxmo gesture map (lisgd) is the direct model for our gesture bindings — edge swipes for back/forward, swipe-up-from-bottom for app menu, swipe-down-from-top for the on-screen keyboard.
What we can’t steal from sxmo: the dwm patches (we use i3),
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. The modem exposes four ports:
| Device | Purpose |
|---|---|
/dev/cuaU0 | DM (diagnostic) |
/dev/cuaU1 | GPS NMEA |
/dev/cuaU2 | AT command port (primary interface) |
/dev/cuaU3 | PPP data |
The plan is a small set of shell scripts modeled on sxmo:
ppp-dial.sh— dmenu interface to dial a number or pick fromcontacts.tsvppp-sms.sh— dmenu interface to compose / read SMSppp-monitor.sh— daemon watching/dev/cuaU2for incoming call/SMS URCs (unsolicited result codes); fires dunst + LED blinkppp-contacts.sh— managecontacts.tsv
Reference repos: fuzzybritches0/pinephone (bash AT scripts), milky-sway/pinephone-scripts, and the gold-standard sxmo-utils.
Audio routing for calls is still blocked on the RT5640 driver — without working playback/capture, even a perfect dialer can’t carry voice.
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:
| Category | Pick (FreeBSD pkg) | Notes |
|---|---|---|
| Browser | netsurf | Lightweight; falls back to surf for sites needing better rendering, w3m in terminal |
| File manager | nnn (terminal) / pcmanfm (GTK2) | Both touch-usable |
| Music | cmus (TUI) / mpv (CLI) | Daemon setup: musicpd + ncmpcpp |
aerc | Modern terminal client, works with svkbd | |
| Calendar | calcurse | Terminal, lightweight, touch-usable |
| Notes | plain text + vi/nano | Sxmo approach |
| Calculator | galculator | GTK2, big touch targets, no GPU |
| Maps | foxtrotgps | OSM tiles, offline cache, GPS support |
| RSS | sfeed (sxmo style) or newsboat | |
| Podcasts | newsboat + podboat + mpv | All in pkg |
mupdf (touch pinch-zoom) / zathura (keyboard) | ||
| Image viewer | nsxiv | Thumbnail mode works on small screens |
| Camera | — | Blocked: no V4L2/media-request on FreeBSD |
| Clock/alarm | shell + at/cron + dunst | |
| Weather | curl wttr.in | Zero deps |
| Password manager | pass + rofi-pass | |
| Night light | redshift | X11 native |
| Messaging | weechat (IRC + Matrix) / profanity (XMPP) |
What not to bother with
- Firefox / Chromium — too heavy for software rendering on 720p; 4 GB RAM swaps under memory pressure.
- Megapixels — needs OpenGL + Linux media-request API. Camera is blocked anyway.
- GNOME Calls / Chatty — depend on ModemManager.
- Phosh / Plasma Mobile — Wayland compositors; we’re X11.
- Wayland-only apps (
wvkbd,foot, etc.). - Flatpak — not available on FreeBSD.
- Maemo Leste / Hildon — interesting X11 mobile stack but deeply tied to Linux/Debian. Take ideas, not code.
Phased install plan (verbatim from the doc)
Phase 1 — Core mobile UX (now)
ssh honor "pkg install -y dmenu rofi dunst slock xautolock xdotool \
xclip xrandr redshift conky htop picocom"
Then configure: lisgd gestures, dmenu/rofi launcher, dunst notifications, slock on power button, xrandr rotation, brightness script, redshift auto night mode.
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 for everything GTK4/GNOME.
i3 keybindings for mobile use
Suggested additions to ~/.config/i3/config:
bindsym $mod+d exec rofi -show drun -theme mobile
bindsym $mod+p exec rofi-power-menu
bindsym $mod+k exec pkill svkbd || svkbd-mobile-intl -d
bindsym $mod+l exec slock
bindsym XF86MonBrightnessUp exec brightness-up.sh
bindsym XF86MonBrightnessDown exec brightness-down.sh
bindsym XF86AudioRaiseVolume exec pamixer -i 5
bindsym XF86AudioLowerVolume exec pamixer -d 5
bindsym XF86AudioMute exec pamixer -t
bindsym Print exec scrot ~/screenshots/%Y-%m-%d-%H%M%S.png
bindsym $mod+r exec rotate-screen.sh
Brightness without xbacklight
scfb doesn’t support xbacklight/RandR backlight. The PWM backlight
is reachable through pwm_backlight (sysctl) or — last-resort — a
direct register poke. Wrap whichever method works in brightness.sh
and bind it to gestures or volume buttons.
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
- Essay 13 — Audio on device — why the RT5640 audio path is the gating dependency for music, podcasts, and call audio.
- The full document at
MOBILE_SOFTWARE.mdhas comparison tables for every app category that this summary collapses into one row each.