141 lines
6.8 KiB
Markdown
141 lines
6.8 KiB
Markdown
|
|
# Chatter — Phase 1 On-Device Findings
|
|||
|
|
|
|||
|
|
**Date:** 2026-06-25
|
|||
|
|
**Device:** reMarkable Paper Pro Move (RM03A, codename "Chiappa")
|
|||
|
|
**Method:** Read-only SSH probing from Jatke (`ssh chatter`). No changes made to
|
|||
|
|
the device except enabling developer mode / SSH (Phase 0) and adding our SSH key.
|
|||
|
|
|
|||
|
|
This document records what we learned and the implementation decisions those
|
|||
|
|
findings support. It feeds the phase plan in
|
|||
|
|
[`Chatter_implementation.md`](Chatter_implementation.md).
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 1. Hardware & OS
|
|||
|
|
|
|||
|
|
- **SoC / arch:** NXP **i.MX93**, **aarch64** (Arm Cortex-A55). Kernel
|
|||
|
|
`6.12.49+git-imx93-chiappa`.
|
|||
|
|
- **OS:** Codex Linux 5.7.121 (Yocto **scarthgap**), image `3.27.1.0`. glibc
|
|||
|
|
(`/lib/ld-linux-aarch64.so.1`, `libc.so.6`).
|
|||
|
|
- **RAM:** 2 GB (~1.4 GB free) — ample for our app.
|
|||
|
|
- **Storage (matters for deployment):**
|
|||
|
|
- `/` (rootfs): ~435 MB, **only ~88 MB free (78% used)** — also an
|
|||
|
|
OS-managed overlay, likely reset by firmware updates. **Do not install here.**
|
|||
|
|
- `/home`: **46 GB encrypted volume, ~45.8 GB free.** Install Chatter under
|
|||
|
|
`/home` (e.g. `/home/root/chatter`).
|
|||
|
|
|
|||
|
|
## 2. Input devices
|
|||
|
|
|
|||
|
|
Pen and finger are **separate evdev devices** — finger-vs-stylus discrimination
|
|||
|
|
is free, exactly what Chatter's gesture design needs.
|
|||
|
|
|
|||
|
|
| Node | Name | Role | Notes |
|
|||
|
|
|---|---|---|---|
|
|||
|
|
| `event0` | `bbnsm:pwrkey` | Power button | |
|
|||
|
|
| `event1` | Hall effect sensors | Folio open/close | switch events |
|
|||
|
|
| **`event2`** | **Elan marker input** | **Stylus / Marker** | on SPI |
|
|||
|
|
| **`event3`** | **Elan touch input** | **Capacitive multitouch (finger)** | `INPUT_PROP_DIRECT` |
|
|||
|
|
|
|||
|
|
**Pen (`event2`)** — digitizer space **6760 × 11960**:
|
|||
|
|
- Buttons: `BTN_TOOL_PEN`, **`BTN_TOOL_RUBBER`** (Marker Plus eraser end —
|
|||
|
|
flip-to-erase is detectable), `BTN_TOUCH`, `BTN_STYLUS`, `BTN_STYLUS2`.
|
|||
|
|
- `ABS_PRESSURE` 0–4096, `ABS_DISTANCE` (hover) 0–65535, `ABS_TILT_X/Y` ±9000.
|
|||
|
|
|
|||
|
|
**Touch (`event3`)** — grid **1248 × 2208**:
|
|||
|
|
- Up to **10 contacts** (`ABS_MT_SLOT` 0–9) with `ABS_MT_POSITION_X/Y`,
|
|||
|
|
`ABS_MT_PRESSURE` (0–255), `ABS_MT_TRACKING_ID`, `ABS_MT_TOOL_TYPE`.
|
|||
|
|
|
|||
|
|
All three coordinate spaces share the screen's portrait aspect (~0.5625):
|
|||
|
|
panel 954×1696, pen 6760×11960, touch 1248×2208.
|
|||
|
|
|
|||
|
|
## 3. Display pipeline
|
|||
|
|
|
|||
|
|
- **DRM/KMS only — there is NO `/dev/fb*`** and `/sys/class/graphics` is empty.
|
|||
|
|
Driver is **`imx-drm`**; device `/dev/dri/card0`; connector
|
|||
|
|
**`card0-LVDS-1`** ("connected", "disabled" at rest — normal for e-ink, which
|
|||
|
|
holds its image without continuous scanout).
|
|||
|
|
- The connector advertises a **packed `365×1700` mode** (hardware buffer for the
|
|||
|
|
E Ink Gallery 3 color subpixel layout); the logical screen is 954×1696. The
|
|||
|
|
mapping is handled by the epaper plugin (below) — we don't touch it directly.
|
|||
|
|
- **Implication:** the `mmap /dev/fb0` approach used by rmkit / libreMarkable on
|
|||
|
|
older grayscale models **does not apply** to this device.
|
|||
|
|
|
|||
|
|
## 4. Graphics / UI stack — the key finding
|
|||
|
|
|
|||
|
|
- The stock app **`xochitl`** is a **Qt 6.8.2 / Qt Quick (QML)** application.
|
|||
|
|
- It renders through a **custom Qt platform (QPA) plugin: `epaper`**
|
|||
|
|
(`/usr/lib/plugins/platforms/libepaper.so`, links `libdrm`). Available QPA
|
|||
|
|
plugins on-device: **`epaper`**, `minimal`, `offscreen`, `vnc`.
|
|||
|
|
- Qt 6.8.2 runtime libraries and QML modules (`QtQuick`, `QtQuickControls2`,
|
|||
|
|
etc.) are all present under `/usr/lib` and `/usr/lib/qml`. No dev headers
|
|||
|
|
on-device (expected — we cross-build).
|
|||
|
|
|
|||
|
|
**This means the native path is wide open:** build Chatter as a **Qt 6 app** and
|
|||
|
|
run it with **`-platform epaper`** to inherit working e-ink display + refresh,
|
|||
|
|
instead of reverse-engineering DRM/KMS and waveform handling. This resolves the
|
|||
|
|
project's highest-risk unknown in our favor.
|
|||
|
|
|
|||
|
|
## 5. Stock app & services
|
|||
|
|
|
|||
|
|
- `xochitl.service` — the main UI app (`/usr/bin/xochitl`, pid varies).
|
|||
|
|
- `marker-manager.service` — "Remarkable CSL Marker Manager" (pen support).
|
|||
|
|
- `rm-sync.service` — document sync to the reMarkable cloud.
|
|||
|
|
- Plus metrics / MDM / crash-uploader services.
|
|||
|
|
|
|||
|
|
**Coexistence / toggle implication:** on a DRM/KMS device only one process owns
|
|||
|
|
the display (DRM master) at a time, and xochitl holds it (and likely grabs the
|
|||
|
|
input devices) while running. So the Chatter ↔ standard-GUI **toggle is a
|
|||
|
|
hand-off** (stop or pause `xochitl` ↔ run Chatter, and a return path), **not an
|
|||
|
|
overlay**. The exact mechanism (systemctl stop/start vs. SIGSTOP/SIGCONT) is to
|
|||
|
|
be validated in the Phase 2 spike.
|
|||
|
|
|
|||
|
|
## 6. Document store (for the Save phase)
|
|||
|
|
|
|||
|
|
Location: **`/home/root/.local/share/remarkable/xochitl/`**. Per document:
|
|||
|
|
|
|||
|
|
- `UUID.metadata` — JSON: `visibleName`, `parent` (empty = top level; a folder
|
|||
|
|
is a `CollectionType` document whose UUID is used as children's `parent`),
|
|||
|
|
`type` (`DocumentType`), timestamps, `pinned`, etc.
|
|||
|
|
- `UUID.content` — JSON: page list under `cPages.pages[]` (each page has an `id`,
|
|||
|
|
ordering `idx`, `template`, scroll position, CRDT-style `timestamp` fields).
|
|||
|
|
- `UUID/` — directory of per-page **`<pageUUID>.rm`** files.
|
|||
|
|
- `UUID.thumbnails/` — page thumbnails.
|
|||
|
|
- Store-root extras (Codex additions): `.tree` (binary "rM sync tree" index) and
|
|||
|
|
`rm-search-index.db` (SQLite **search index**, not the canonical store).
|
|||
|
|
|
|||
|
|
**`.rm` page format:** header confirmed as **`reMarkable .lines file,
|
|||
|
|
version=6`** — the v6 binary scene-tree format (documented by the community,
|
|||
|
|
e.g. `rmscene`). Authoring valid v6 is possible but non-trivial.
|
|||
|
|
|
|||
|
|
**Save options (decide in Phase 5):**
|
|||
|
|
1. **PDF/PNG-backed document** — render Chatter's canvas to PDF/PNG and create a
|
|||
|
|
document that references it (xochitl already supports PDF documents). Far
|
|||
|
|
simpler and robust; still a real, renamable/syncable library item.
|
|||
|
|
2. **Native v6 `.rm`** — author the binary page format so the transcript is an
|
|||
|
|
editable notebook. More work; revisit only if option 1 proves insufficient.
|
|||
|
|
|
|||
|
|
Either way, transcripts go under a **`Chatter`** `CollectionType` folder, with
|
|||
|
|
filenames derived from date/time.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 7. Decisions supported by Phase 1
|
|||
|
|
|
|||
|
|
1. **Stack: C++ / Qt 6.8.2**, rendered via the on-device **`epaper` QPA plugin**.
|
|||
|
|
Cross-build with a Yocto **scarthgap** aarch64 SDK matching Qt 6.8.2 / the
|
|||
|
|
device glibc.
|
|||
|
|
2. **Input:** pen from `event2` (including `BTN_TOOL_RUBBER` for flip-to-erase),
|
|||
|
|
finger from `event3` (10-pt). Confirm in Phase 2 whether Qt+epaper already
|
|||
|
|
delivers these or we read evdev directly for custom gestures.
|
|||
|
|
3. **Toggle = display/input hand-off** with xochitl, not an overlay.
|
|||
|
|
4. **Save = PDF-backed document** (leaning), in a `Chatter` folder.
|
|||
|
|
5. **Deploy under `/home`,** never the rootfs.
|
|||
|
|
|
|||
|
|
## 8. Open items for the Phase 2 spike
|
|||
|
|
|
|||
|
|
- Stand up the cross-SDK and build a trivial Qt app; run it with
|
|||
|
|
`-platform epaper` **after stopping xochitl**; confirm it draws and refreshes.
|
|||
|
|
- Verify how input arrives in a Qt app under epaper (Qt event stream vs. raw
|
|||
|
|
evdev) and how reliably finger and pen separate at the Qt layer.
|
|||
|
|
- Validate the toggle hand-off (stop/start vs. stop/cont) and a return path.
|