Arrow DragonBoard 410c (arrow-db410c)

DragonBoard 410c is a single board computer designed by Qualcomm and manufactured by Arrow. It's a reference design for apq8016e devices and as with many other DragonBoards it has great mainline support. The board is based on the 96Boards CE specification. A lot of the documentation for the board and it's apq8016e platform is available on the Qualcomm Developer Portal. The availability of this documentation makes apq8016e, db410c and all other msm8916 based devices into a very good mainlining target. Some other manufacturers (e.g. Geniatech) make other sbc's based on the db410c design and those boards can be fully or in most compatible with this port. Boards that are known to be compatible include: Geniatech DB4 (v1). 
== Contributors ==
* minecrell
== Users owning this device ==
== How to enter flash mode ==
At the moment, the recommended way is to flash postmarketOS to a SD card. The SD card needs to be manually prepared with the bootloader and necessary firmware. Then you can boot the board into Fastboot mode and flash postmarketOS normally from there.
=== Prepare SD card ===
First, connect the SD card to your PC and find out the device name (usually either /dev/sdX or /dev/mmcblkX). lsblk might be helpful. Make sure it is the correct device, since it will be entirely erased by the following commands.
Download https://releases.linaro.org/96boards/dragonboard410c/linaro/rescue/latest/dragonboard-410c-bootloader-sd-linux-*.zip and unpack it.
 $ git clone https://git.linaro.org/landing-teams/working/qualcomm/db-boot-tools.git
$ cd db-boot-tools
$ SD_CARD="/dev/sdX" # Replace this by your device name
$ sudo ./mksdcard -o "$SD_CARD" -p dragonboard410c/linux/partitions.txt -i ../dragonboard-410c-bootloader-sd-linux-*/ -s $(($(sudo blockdev --getsz "$SD_CARD") / 2))
Writing the SD card will take a while. Then insert it into the DragonBoard 410c and turn it on. Now you can connect a micro USB cable to get access to Fastboot.
If you want to access Fastboot again later (after flashing a boot image), press Volume Down before turning on the device.
== Installation ==
Follow Qualcomm_Snapdragon_410/412_(MSM8916)#Installation. Note that lk2nd is not required for the Dragonboard 410c, but the bootloader installed above behaves essentially the same way.
== Audio ==
See Qualcomm_Snapdragon_410_(MSM8916)#Audio.
To play via HDMI, use set _verb HDMI or select HDMI in the PulseAudio mixer.
=="Modem" (remote processor services) access ==
This APQxxxx device has no cellular modem. The interaction of interest is with the DSP. The IPC driver is QRTR (linux kernel net/qrtr).
Install the qrtr package containing the qrtr-lookup command.
The prebuilt images include modemmanager and soc-qcom-msm8916-rproc-all; ofono is untested.
 $ mmcli -m any status
 error: couldn't find modem
For simplicity, (stop and delete the modemmanager services and) remove those two packages, add soc-qcom-msm8916-rproc-no-modem, and reboot. The change in rproc package may or may not affect audio routing (untested); retaining rproc-all is probably ok.
The "services" that qrtr-lookup lists are obviously 
independent of any userland modem management software stack, 
but may depend on device-specific firmware / rproc packaging.
 $ qrtr-lookup
 Service Version Instance Node Port
 256 0 1 0 1 <unknown>
 43 1 0 0 2 Subsystem control service
 15 1 0 0 8 Test service
 51 1 2 0 9 CoreSight remote tracing service
 24 1 0 0 10 Thermal mitigation device service
 23 1 0 0 11 Thermal sensors service
 22 1 1 0 12 Time service
 34 1 0 0 13 Coexistence service
 16 2 0 0 14 Location service (~ PDS v2)
 14 1 0 1 14 Remote file system service
 256 0 1 7 1 <unknown>
 15 1 0 7 2 Test service
For now, only location service, specifically PDS, and probably only version 2, is considered.
The acronym PDS may stand for Position Delivery Service.
Whether there are other types of location service is undocumented.
The meaning of the versioning is undocumented.
==Location service (PDS)==
===Hardware===
GPS may not function on early (rev A?) boards that lacked the cpu, pm, and memory chip shields (untested).
The gps antenna is next to J12 / J11 (near the power plug J1). For more details, search online archives for a Qualcomm Application Note validating DragonBoard 410c GPS.
The following tests were done with db410c rev B,
pre-built image 20240619-0959-postmarketOS-v24.06-console-0.1-arrow-db410c.img
installed to EMMC.
===qrtr/qmi===
According to MSM8916 Modem, it may be possible to directly access gps "content" (raw bytes or digested NMEA sentences?) from the location service via qmicli (qmi-utils package). 
The following location service features and defaults are easily accessed, see qmicli --help-loc,
 $ qmicli -V
 qmicli 1.34.0
 $ qmicli -d qrtr://0 --loc-get-operation-mode
 Successfully retrieved operation mode: standalone
 $ qmicli -d qrtr://0 --loc-get-nmea-types 
 Successfully retrieved NMEA types: gga, rmc, gsv, gsa, vtg, pqxfi
There are also set- flags; altering any value may require a power cycle to reset to defaults (guessing: DSP is started at boot [dependent on rproc], no user control).
Starting and receiving updates from the location service is probably simple, but
the precise commands have not been documented.
See the WIP MSM8916 Modem: Hardware variant table.
===gpsd===
Gpsd is a sophisticated tool intended to automagically (plug and play) extract and present location data from a variety of sources via custom drivers.
Upstream gpsd at time of writing does not support PDS.
 $ gpsd -V
 gpsd: 3.25 (revision 3.25)
 $ gpsd -l | grep -i pds || { echo "this gpsd does not include pds driver"; }
Patches to gpsd to include a PDS driver were developed (circa 2019) during the Linaro db410c project based an earlier version (gpsd-3.22).
The patches have not been accepted upstream.
These patches make direct use the qmi protocol, and put the data in a form that gpsd can digest. See also the historical downstream repo.
Here, for testing, we build a local "minimal" version using the original known good tarballs (and adding a few new minor patches). This is intended to expose / test only the PDS service / driver (via a couple of simple existing clients). 
Note: it is not intended to exist alongside the upstream gpsd package (depending on your PATH).
Download and unpack two unmaintained tarballs,
the 'latest' (final) Linaro gpsd tarball (an old branch or release of upstream gpsd),
old gpsd, 
and 
the Linaro "debian overlay" (.deb) patching and packaging tarball,
debian overlay. (Only the patches subdirectory is used here).
In the gpsd-3.22 directory, apply at least these two patches
 0001-Introduce-Qualcomm-PDS-service-support.patch
 7f30d88d0_gpsd-timebase.c-Don-t-compute-wrong-GPS-rollover-after-2020-10-23
Additionally, apply these three simple patches to clean up the PDS implementation,
0002-pds-fix-missing-string.h-patch
--- a/drivers/driver_pds.c	2024-07-03 16:35:55.093627716 -0700
+++ b/drivers/driver_pds.c	2024-07-03 16:36:45.056961960 -0700
@@ -20,6 +20,7 @@
 #include "../include/driver_pds.h"
 
 #include <linux/qrtr.h>
+#include <string.h>
 
 #define QMI_PDS_MAX		16
 #define QMI_PDS_SERVICE_ID	0x10
0003-pds-requires-nmea0183.patch
--- a/SConscript
+++ b/SConscript
@@ -612,6 +612,7 @@
 'gpsclock',
 'mtk3301',
 'oceanserver',
+ 'pds',
 'skytraq',
 'tnt',
 'tripmate', ):
0004-pds-requires-socket-export.patch
--- a/SConscript
+++ b/SConscript
@@ -619,6 +619,9 @@
 env['nmea0183'] = True
 break
 
+# Qualcomm PDS operates via socket.
+if env['pds']:
+ env['socket_export'] = True
 
 # iSync uses ublox underneath, so we force to enable it
 if env['isync']:
In order to build this natively on the device (gcc, scons) (pmbootstrap untested),
check for or install (at least) the two -dev packages qrtr-dev and
ncurses-dev.
Build (as root; sudo untested), using these specific arguments (flag -j 4 solely for faster build):
 # scons -j 4 minimal=True pds=True ncurses=True gpsdclients=True
The PDS driver should probably build correctly with no arguments, but creates a much larger troubleshooting surface (untested).
Review the build output for any missing requirements. The build may complete successfully, but without building the desired driver(s).
Review both stdout and stderr for warnings. 
Some potential coding errors remain in the pds driver code, and are flagged with warnings.
Use scons --clean between rebuilds.
The test suite will fail early, but for reasons unrelated to PDS (possibly due to minimal build)
 # scons check
There do not seem to be any PDS-related tests, so this step is optional.
Install to /usr/local (default) 
 # scons install
Confirm (or prefix) root PATH
 # which gpsd
 /usr/local/sbin/gpsd
See the header of the 0001 patch for any and all userland PDS documentation, specifically,
 The PDS driver is selected by the url pds://<host>, where host is either
 a numerical identifier of the node in the AF_QIPCRTR network or the
 string "any".
This is not to be confused with the uri qrtr://0 mentioned above.
Start gpsd (as root, not via sudo!) in background (default) mode, or foreground, debugging mode.
 # gpsd pds://any
 # gpsd pds://any -b -n -N -D 3
Using the node listed by qrtr-lookup will also work
 # gpsd -b pds://0
The more correct(?) gpsdctl pds://any does not behave as expected.
Confirm expected active process
 # pgrep -u nobody gpsd
On the first (very cold start) attempt to access the gps, prefer the debugging mode 
to observe the possibly many minutes incremental evolution of the gps fix
(see Troubleshooting below). 
Expect fair gps reception relative to mobile devices. These tests were done with the db410c ~2-3m away from a south-facing window. 
As user (or root), use the cgps client to monitor the location updates (at 1Hz)
 $ /usr/local/bin/cgps
Confirm the expected device field in the scrolling status lines at the bottom of the display. A typo in the uri might not be trapped by the driver, leaving a null feed to gpsd.
The NO FIX line should increment at 1/sec (but may remain frozen at 0 during slow ephemeris, etc. downloads?).
In regular use, 
TTFF may be ~200s cold start, 2s hot start, and first satellite at 40s for warm start.
Upon FIX, the bottom of the display (as vertical space permits) should scroll with raw gpsd ~JSON-formatted data lines, 1/sec, (see -s flag).
The 3D FIX line resets to zero at FF, and should increment at 1/sec.
If 3D FIX flips back to zero, check the top right satellite Seen / Used field, for Used < 3.
Only the GP talker ID seems to be seen / acquired (or at least so labelled).
The cgps client is ncurses-based, and may not tolerate small displays. In that
case, try gpscsv (time,lat,lon,altHAE). The minimal build will require the additional argument python=True. This may output three duplicated records for each update, depending on build arguments. 
The minimal setup does not build another useful ncurses-based tool, gpsmon; build it by including the argument netfeed=True. It requires term window >= 80x25.
To stop gpsd, as root run
 # pkill -u nobody gpsd
====Troubleshooting==== 
For first use, or if no response, confirm sky access and try debugging in the foreground, and be patient (12.5 minutes or more?). Ignore lines mentioning "PPS", it is an unrelated feature that is not masked by the minimal build.
debug output
 # gpsd pds://any -n -N -D 3
 gpsd:INFO: launching (Version 3.22)
 gpsd:INFO: listening on port gpsd
 gpsd:INFO: stashing device pds://any at slot 0
 gpsd:INFO: gpsd_activate(2): activated GPS (fd 5)
 gpsd:INFO: PPS: activated pds://any ntpshm_link_activate(): Clock
 gpsd:INFO: running with effective group ID 20
 gpsd:INFO: running with effective user ID 65534
 gpsd:INFO: startup at 2024-07-08T23:38:15.000Z (1720481895)
 gpsd:INFO: QRTR open: Found PDS at 0 14.
 gpsd:WARN: cycle-start detector failed.
 gpsd:WARN: cycle-start detector failed.
 gpsd:WARN: cycle-start detector failed.
 gpsd:WARN: cycle-start detector failed.
 gpsd:WARN: cycle-start detector failed.
 gpsd:WARN: cycle-start detector failed.
 gpsd:INFO: Sats used (0):
 gpsd:WARN: cycle-start detector failed.
 gpsd:WARN: cycle-start detector failed.
 gpsd:WARN: cycle-start detector failed.
 gpsd:INFO: Sats used (0):
 gpsd:WARN: NMEA0183: can't use GGA time until after ZDA or RMC has supplied a year.
 gpsd:WARN: cycle-start detector failed.
 gpsd:INFO: PRN 2 az 313.0 el 32.0 (-0.620223, 0.578367, 0.529919)
 gpsd:INFO: PRN 8 az 243.0 el 19.0 (-0.842463, -0.429256, 0.325568)
 ...
 gpsd:INFO: PRN 31 az 174.0 el 26.0 ( 0.093950, -0.893870, 0.438371)
 gpsd:INFO: PRN 32 az 30.0 el 58.0 ( 0.264960, 0.458924, 0.848048)
 gpsd:INFO: Sats used (9):
 gpsd:WARN: cycle-start detector failed.
 gpsd:WARN: cycle-start detector failed.
 gpsd:INFO: PRN 2 az 312.0 el 33.0 (-0.623254, 0.561180, 0.544639)
 gpsd:INFO: PRN 8 az 243.0 el 19.0 (-0.842463, -0.429256, 0.325568)
 gpsd:INFO: PRN 10 az 71.0 el 43.0 ( 0.691509, 0.238105, 0.681998)
 [ctrl-c]
== See also ==
* Initial merge request
* 
* msm8916 mainline kernel package
* Mainline kernel tree for msm8916 devices
* APQ8016e on the Qualcomm Developer Portal
* db410c on the 96boards portal