User-mode emulation for PocketBook 6.1-6.11 firmware on Linux desktop (podman + Wayland)
README.md

C components #

All native code lives under src/. Each component is built independently by passing its source dir to cmake with the appropriate compiler and toolchain; the developer CLI (tools/pbemu/) drives all builds inside the pbdev container.

Subtree Platform Output Purpose
shim/ ARM libshim.so LD_PRELOAD compatibility layer for guest firmware processes.
informer/ ARM informer Hidden ARM service publishing active task / framebuffer / touch metadata via SysV SHM.
probes/arm/ ARM arm_probe Diagnostic ELF with send-event, wait-ready, task-info, task-list, mq-attr, audio-status, launch subcommands. Used by integration tests and manual debugging.
probes/host/ PC frame_dump, send_event Host-side helpers built alongside the viewer; consume informer SHM and emit /hwevent messages from a host shell.
viewer/ PC viewer Wayland client rendering the active task's framebuffer and forwarding pointer + keyboard input.
pbcore/ both libpbcore.a Cross-platform IPC helpers (informer SHM reader, /hwevent writer, surface→framebuffer mapping). Linked by viewer, arm_probe, and the host probes.
common/ both headers only Shared IPC contracts and SDK struct layouts.
dynsh/ ARM busybox (prebuilt) Drop-in dynamic-linked shell staged into the firmware tree.

Build #

./pbemu build [firmware]

Each component compiles into its own build-arm/ or build-pc/ directory (e.g. src/shim/build-arm/libshim.so, src/viewer/build-pc/viewer). ./pbemu build --clean wipes them first.

The ARM targets (shim, informer, arm_probe) link against the staged firmware's own ARM libraries (libinkview.so, libhwconfig.so, rootfs/lib/libc.so.6), so ./pbemu install <firmware.zip> must be run before the first build.

Component READMEs #

Each component has its own README with the source-file map and design notes:

The host probes do not have a separate README — see the per-file headers in probes/host/src/ and the integration-test usage in tests/support/.

Shared definitions (common/) #

Headers in common/ define the wire formats every other C component agrees on. They use explicit-width integer types so the same struct layout matches on ARM32 and x86-64.

Header Contents
common/pb_ipc.h HW_EVENT_QUEUE (/hwevent) name, TASK_STATE_DIR (/var/run/task), event codes (EVT_POINTERDOWN=30, EVT_POINTERUP=29, EVT_POINTERMOVE=31, EVT_MTSYNC=39).
common/pb_informer.h PB_INFORMER_SHM_KEY = 0x00A12303; pb_informer_state snapshot (active task/subtask ids, framebuffer key/size/geometry, touch matrix, task names); odd/even sequence seqlock protocol.
common/pb_repaint.h PB_REPAINT_SHM_KEY = 0x00A12304; pb_repaint_state (seqlocked flags + x/y/w/h; PB_REPAINT_FULL or PB_REPAINT_RECT).
common/inkinternal.h SDK struct reproductions: icanvas (canvas descriptor), iv_fbinfo (task SHM header with fb_y_offset at 0x8c).

Conventions #

  • C11 throughout. _GNU_SOURCE is defined via CMake.
  • All .c and .h changes go through clang-format -i --style=file (only available inside the pbdev image: podman run --rm -v "$PWD:/work:Z" -w /work pbdev clang-format -i --style=file <file...>).
  • ./pbemu lint --c-only runs clang-tidy over every build directory using their generated compile_commands.json.