Devices
Dolphone is built for the Flipper One: its panel apps are FlipCTL apps, its
buttons are the Flipper’s, and HARDWARE.md is the Flipper One’s
bring-up. Underneath, though, phoned only needs what any Linux machine with a modem
has: ModemManager for the modem, PipeWire for audio, BlueZ for Bluetooth, logind
and D-Bus. So the daemon, phonectl and the desktop app run elsewhere too.
What differs between machines is the hardware around the modem, and that lives in a device profile: one TOML file that says how to recognise the machine and how its audio is wired.
Which one am I using?
phonectl device # the profile in use, and why it was chosen
phonectl device list # every profile phoned knows
phonectl device use pinephone # choose one by hand (auto to detect again)
Phone Settings > About shows it on the panel too.
The profiles that ship
| Profile | Recognised by | Status | Notes |
|---|---|---|---|
flipper-one | device tree model “Flipper One” | expected | The reference. NAU8822 codec switched with amixer (Speaker, Headphone, from the kernel driver’s controls); the modem’s USB audio bridged by phoned. The board’s device-tree strings are not published yet, so detection is assumed: choose it by hand if it misses. |
clockworkpi-uconsole | dtoverlay=clockworkpi-uconsole in config.txt | untested | The 4G extension is a SIMCom SIM7600G-H, which sends call audio as serial PCM. ModemManager’s SIMCom plugin turns it on (AT+CPCMREG=1) once a call connects and names the port; phoned bridges that port (or /dev/ttyUSB4) to PipeWire at the call’s rate, 8 or 16 kHz (SIMCom USB AUDIO Application Note V1.03). Needs you in the dialout group for the port. |
raspberry-pi | device tree model “Raspberry Pi” | untested | Any modem ModemManager supports. Mobile call audio needs a modem with a USB sound card; use a USB headset for the speaker and microphone. |
pinephone | pine64,pinephone | untested | The EG25-G is wired to the codec; ALSA UCM’s Voice Call verb connects it (call_start_commands); calls start on the earpiece. |
librem5 | purism,librem5 | untested | The BM818 is its own ALSA card (“Modem”), bridged to the codec by phoned, as on the Flipper One; calls start on the earpiece. |
laptop | SMBIOS chassis type (laptop, notebook, convertible), or ThinkPad | untested | The desktop app. Whether the WWAN modem can call and text depends on it: mmcli -m 0 lists Voice and Messaging when it can. SIP works regardless. |
generic | nothing else matched | expected | Default devices, no mixer controls touched. |
“Untested” means the values come from the sources each file cites (kernel device trees, alsa-ucm-conf, vendor documentation), but nobody has yet run the bring-up checks on that machine. Running them and reporting back, pass or fail, is the most useful contribution there is.
On the phones (PinePhone, Librem 5), stop callaudiod and GNOME Calls first: one program should own the modem’s calls and texts, and the package conflicts with GNOME Calls and Chatty for that reason.
Adding a device
Copy generic.toml (in /usr/share/dolphone/devices/ once installed, or
dist/devices/ in the repository) to ~/.config/dolphone/devices/, give it an id,
and fill in what you know:
id = "my-board"
name = "My Board"
status = "untested" # tested once docs/HARDWARE.md passes on it
source = "where the values came from"
notes = "what works, what does not"
front_ends = ["desktop"] # "flipctl" too, if it runs FlipCTL
ring_leds = [] # names under /sys/class/leds to flash while ringing
modem_at = [] # AT commands each time the modem appears
call_at_start = [] # AT commands when a mobile call connects
call_at_end = [] # and when it ends (these four go above [match])
[match] # any one of these picks the profile
dt_compatible = ["vendor,board"] # exact strings from /proc/device-tree/compatible
dt_model = ["My Board"] # substrings of /proc/device-tree/model
dmi_vendor = [] # substrings, on machines with DMI (x86)
dmi_product = []
dmi_family = []
dmi_version = []
dmi_chassis = [] # SMBIOS chassis types: 9 laptop, 10 notebook...
file_contains = [["/etc/hostname", "myboard"]]
priority = 50 # higher wins when several match
[at_port] # a spare AT port of the modem's (see below)
usb_vendor = "2c7c" # hex ids, as lsusb and sysfs write them
usb_products = ["0801"]
usb_interface = "03" # bInterfaceNumber
[audio] # any key of dist/audio.example.json
codec_sink = "" # PipeWire node names; empty for the default
mic_source = ""
speaker_commands = [["amixer", "-q", "sset", "Speaker", "unmute"]]
wired_commands = [["amixer", "-q", "sset", "Headphone", "unmute"]]
modem_match = ["Quectel"] # how to spot the modem's USB audio nodes
call_start_commands = [] # a UCM verb, an AT command, an amplifier
call_stop_commands = []
earpiece_commands = [] # a phone's earpiece: calls start there when set
serial_pcm = "" # a modem's serial audio port, as on a SIM7600
assume_wired = false
Restart phoned (or phonectl device use my-board), place a call, and check with
phonectl device and journalctl --user -u phoned. When it works, a pull request
adding the file to dist/devices/ (and to the list in crates/phoned/src/devices.rs)
brings it to everyone; the unit tests check that every profile parses, is described,
and can be detected.
AT commands without ModemManager’s debug mode
modem_at, call_at_start, call_at_end, phonectl modem setup and the call
forwarding and caller-ID codes are AT commands. ModemManager passes them only in its
debug mode. A profile’s [at_port] names a spare AT port instead, by its place on
USB, and phoned talks to it itself once udev tells ModemManager to leave it alone
(ID_MM_PORT_IGNORE). The package’s /usr/lib/udev/rules.d/70-dolphone-at-port.rules
does that for the Quectel RM520N-GL and RM500Q, interface 3, and gives the port to
the dolphone group; it does nothing until:
sudo dolphone-modem-access port on # port off undoes it; ModemManager restarts
sudo adduser $USER dolphone # then log in again
phonectl modem setup # "at commands ok on phoned's own port /dev/ttyUSB3"
Only the Flipper One profile has an [at_port]; it is untested on a real modem. For
another modem, find an AT port that ModemManager does not need as its primary one
(mmcli -m any lists the ports and what it uses each for; the vendor’s Linux USB
guide gives the interface numbers), copy the rule to /etc/udev/rules.d/ with the
same name and change its ids and interface, and add [at_port] to the profile.
phoned uses a profile’s port only when udev reports ID_MM_PORT_IGNORE on it,
since two programs on one AT port garble each other’s answers. The at_port
setting overrides: phonectl set at_port /dev/ttyUSB3 uses that port whatever udev
says, and modemmanager never uses one.
Flashing LEDs for a ringing call
A profile’s ring_leds names LEDs under /sys/class/leds to flash while a call
rings (the flash_on_ring setting, on by default). Their files belong to root, so the package’s
/usr/lib/udev/rules.d/70-dolphone-leds.rules gives them to the dolphone group,
for the Flipper One’s LEDs (flipper-one:*). Join the group once:
sudo adduser $USER dolphone # then log in again
On another machine, copy the rule to /etc/udev/rules.d/, change its KERNEL
match to your LEDs’ names (ls /sys/class/leds), and run
sudo udevadm control --reload-rules && sudo udevadm trigger --subsystem-match=leds.
Where the facts are
cat /proc/device-tree/compatible | tr '\0' '\n'and/proc/device-tree/modelon ARM boards;/sys/class/dmi/id/*on x86.aplay -landwpctl statusfor the sound cards and PipeWire’s nodes.amixer scontrolsfor the mixer controls, or the codec’s driver in the kernel (sound/soc/codecs/)./usr/share/alsa/ucm2/for a UCM profile and its verbs.mmcli -m 0for what the modem offers, andlsusbfor its USB functions (a “USB Audio” interface is what phoned can bridge).
Order of precedence
Built-in profiles, then /usr/share/dolphone/devices/, then
~/.config/dolphone/devices/ (a later file with the same id replaces an earlier
one). The owner’s device_profile setting picks one by id; otherwise the best match
is used. The owner’s own ~/.config/dolphone/audio.json still has the last word on
any audio key.