Files
fds-os/docs/developer/dasung.md
T
2026-09-24 13:03:52 +08:00

191 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Dasung Paperlike 13K base-system integration
Development reference and historical context. For current operating instructions, use the [user manual](../README.md). Acceptance applies only to the source and artifacts identified in each record.
[Documentation index](README.md) · [First build](getting-started.md) · [Services](services.md)
FDS includes the Rust **dasungd** controller from the project's earlier
**Fix Dasung monitor black screen** task. It targets the user's **Paperlike 13K
grayscale**, serial `L56051794302`, with the confirmed 3200 × 2400 timing at about
37 Hz. This is core display support: its package is required for the base SYSTEM
image, and its service belongs to the base boot bundle, including console-only use.
It does not require an ENVIRONMENT cartridge, WindowMaker, or a graphical session.
**Implementation boundary:** the daemon, ARM package, and s6 service definitions
are included by the [rootfs assembler](rootfs.md). [M2 native init](init.md) starts
the controller in the base boot graph, including in the ARM VM with no monitor.
The [M4 boot path](boot.md) starts an early copy before SYSTEM exists, then stops
and reaps it before base s6 starts the normal daemon. Software handoff is tested
in a VM; physical Pi display and monitor recovery remain unverified. The final
s6 database is compiled at image build time.
## Build it on the workstation
Complete `make bootstrap` as described in [Your first build](getting-started.md),
then run from the repository root, as your regular user:
```sh
make dasung
make dasung-test
```
The first command prepares the additional C cross compiler inside the existing
Void build container, fetches the crates pinned in `Cargo.lock`, and cross-builds
static-musl `dasungd`. It verifies the ELF, builds the `fds-dasungd` XBPS overlay,
indexes the output, and compiles the actual s6 source into a validation database.
The second runs unit tests and a simulated serial monitor, then inspects the
package and compiles the service definitions extracted from that package. It also
runs that s6 graph with a native test binary, a read-only container root, and no
physical device access to check startup, logging, permissions, restart, and stop.
Python 3 is needed **only on the host for the simulator**. If absent on Arch,
install `python` with pacman. No Python interpreter is shipped for the daemon.
The first additional toolchain download is approximately 243 MB and needs roughly
1 GB of extra container space. Builds still depend on rolling Void binary inputs.
Run these commands sequentially with other FDS builds; they share the container.
| Output | Purpose |
| --- | --- |
| `out/dasungd` | Static AArch64 executable; no target glibc, musl, libusb, or libudev shared library dependency |
| `out/packages/fds-dasungd-0.1.0_1.aarch64.xbps` | Target package with executable, config, exact EDID, s6 source, udev rule, and licenses |
| `out/manifests/dasung-s6-database.txt` | Path to the service database compiled on the host for validation |
| `out/manifests/dasung-artifacts.sha256` | Executable and package hashes |
| `out/manifests/dasung-build-packages.txt` | Installed build-container input versions |
| `out/logs/dasung-build.log`, `dasung-checks.log` | Build and test evidence |
The standalone validation database contains only the Dasung subset. The M2
image assembler merges it with the init package and compiles the full current
graph while building the rootfs. No daemon is started on the workstation by these targets;
the integration test uses its own temporary socket and pseudo-terminal.
## What goes into the base system
`image/base-packages.list` makes `fds-dasungd` a mandatory hardware package.
`packages/fds-dasungd/template` is the active FDS-owned XBPS overlay. The upstream
Void tree remains pinned and unchanged. Source is maintained at `rust/dasungd/`;
the original task directory is not required for future builds.
The package installs:
- `/usr/bin/dasungd` and `/etc/dasungd.toml`.
- `/usr/lib/firmware/edid/dasung-paperlike13k-37hz.bin`.
- `/etc/s6-rc/source/dasungd`, its runtime-directory and log services, and the
`boot/contents.d/dasungd` membership entry.
- `/usr/lib/udev/rules.d/99-dasung-spi.rules`, adapted to eudev syntax.
- Documentation and the controller/libusb licenses.
s6 supervises the foreground daemon. A short oneshot creates private writable
runtime/log directories; it does not wait for the display. The daemon starts with
no monitor attached and retries discovery. Its initial service transition does
not wait for a monitor reply, a desktop, the network, or all cartridge bays.
The log service rotates a small log under `/run/log/dasungd`.
The init package adds a dependency on `runtime-fs` so the controller starts with
its kernel interfaces mounted. The service runs as root because it claims USB interfaces. Its socket
is under a root-owned mode-0750 directory; runtime control is restricted to root.
A future FDS CLI can expose selected operations through an explicit policy.
No world-writable USB rule, systemd unit, or runit service is installed.
## Confirmed profile and Pi-specific choices
| Property | Recorded value |
| --- | --- |
| Monitor | Paperlike 13K grayscale; `L56051794302` |
| Resolution | 3200 × 2400 |
| Pixel clock | **304210 kHz** (304.21 MHz) |
| Horizontal active / sync start / sync end / total | 3200 / 3248 / 3280 / 3360 |
| Vertical active / sync start / sync end / total | 2400 / 2423 / 2427 / 2447 |
| Sync polarities | Positive horizontal and vertical |
| EDID SHA-256 | `b6c1e0a8d315d9cf5c2fb83784a177530bcc085c2d0724dc7478a9c12449e4f4` |
| Control transport | USB UART `1a86:7523`, with companion SPI bridge `1a86:5512` |
| Startup parameters | Raw mode 1 and contrast 4, previously read back on this unit |
| Keepalive | `20 01` every two seconds; minimum 150 ms between command writes |
The video timing was confirmed on the original AMD workstation, **not on a Pi**.
The original USB-C video connection is not a Pi cabling prescription. Pi connector,
cable/adapter, mode acceptance, and picture stability require hardware validation.
For the current HDMI video plus USB control procedure, including separate monitor
power and a reversible native-EDID experiment, use the [display guide](../dasung.md).
Desktop 2× scaling is separate from EDID timing; a console uses its own font size.
FDS configures `display.enabled=false` and `hotplug="none"`: the daemon handles
USB control without applying the source project's AMD debugfs disconnect/reconnect
procedure. The Pi boot/display integration must supply the appropriate KMS/firmware
EDID configuration for its real connector. The Pi boot-volume builder now supplies
an unqualified firmware EDID override for this dedicated monitor; it does not
assume `DP-2` or a numbered HDMI connector. See the [boot guide](boot.md) for
the exact command line and the remaining physical mode test.
The daemon requires the configured monitor's DRM EDID and the matching USB
companion topology before claiming a device. Multiple matching UARTs are rejected;
`usb_path` can disambiguate a verified Pi topology. Do not substitute a blanket
match for all CH340 adapters or copy this unit's identity to a different monitor.
The original monitor's SPI driver interaction caused a dark picture after a power
cycle. `image/kernel/dasung.config` requires `CONFIG_SPI_CH341=n`; the Pi kernel
builder enforces this before boot, including the initramfs environment. The scoped
udev rule is secondary protection: it cannot prevent a built-in or already-loaded
SPI driver from probing. The daemon also reserves the companion interface without
sending SPI data and refuses to take it from an already-bound kernel driver.
## Runtime usage once installed in an FDS image
These are target commands, **not commands to run against the workstation's live
monitor during the build**:
```text
dasungd status
dasungd query
dasungd refresh
dasungd set contrast 4
dasungd set mode 1 --save
dasungd forget mode
```
`status` returns JSON including `connected`, `responsive`, reply age, and cached
parameters. A successful set means a packet was sent; use query/status to check
observed values. It is not proof of physical image quality. Color-model mode names
are not assigned to this grayscale monitor's raw numeric modes.
The default socket is `/run/dasungd/control.sock`. External programs can use its
newline-delimited JSON protocol; the daemon remains the only USB owner:
```json
{"op":"status"}
{"op":"set","parameter":"contrast","value":4,"save":true}
```
In FDS's current payload, saved overrides live in `/run/dasungd/settings.json`.
They survive a daemon restart **within the same boot**, but not power loss.
Mode 1/contrast 4 are persistent image configuration defaults. Once persistent
machine-state mounts are implemented, point `state_file` at that internal writable
storage to retain user overrides across boots. Do not put it on read-only SYSTEM
or make the base display daemon depend on a removable DATA cartridge.
## Dependencies and source provenance
The imported Rust dependencies are retained and pinned by the workspace lockfile:
`rusb` wraps USB access; `libc` supports Linux serial/locking calls; `ctrlc` handles
termination; `clap` provides CLI parsing; `serde`, `serde_json`, and `toml` support
configuration and the local socket; `anyhow` supplies contextual errors.
Transitive versions are recorded in `Cargo.lock`.
The `vendored` feature builds libusb from the pinned `libusb1-sys` crate. The Void
`cross-aarch64-linux-musl` toolchain supplies C headers/compiler for that library;
Rust's bundled musl target alone was enough for the old pure-Rust smoke-test, but
is insufficient for this C dependency. `LIBUSB_NO_PKG_CONFIG` and
`LIBUDEV_NO_PKG_CONFIG` prevent accidental host/shared-library linkage. libusb uses
its Linux netlink backend. No libusb/libudev shared runtime package is needed.
The target package depends on GNU coreutils for directory preparation, execline
for service launch, s6/s6-rc for supervision, and eudev for device rules. These
match the planned base userspace. The container's s6-rc is a build-time compiler,
not a target PID 1 running on Arch.
[Import provenance](../../rust/dasungd/IMPORT.md) records the original source hashes.
[Original validation](../../rust/dasungd/VALIDATION.md) records the live handoff and
remaining physical test. Protocol and reconnect tests use simulated hardware;
Pi boot, image quality, physical disconnect/reconnect, and corrected cold-power
recovery must still be verified on the actual target. No boot benchmark is claimed.