Expand description
§kobo-core
A reusable Kobo e-reader device SDK for Rust. Provides hardware abstractions, rendering primitives, audio infrastructure, and EPUB parsing for any Kobo e-ink application.
Part of the KoThok e-reader ecosystem:
| Repo | Role |
|---|---|
| KoThok (EReader) | E-reader app built on kobo-core |
| kobo-core (this) | Device SDK (framebuffer, touch, audio, EPUB) |
| kothok-edge-tts | Edge TTS client (re-exported via the audio feature) |
§Architecture
flowchart TD
APP["Your Kobo app"]
subgraph SDK["kobo-core"]
DEV["device<br/>framebuffer, touch, power, BT, WiFi"]
REND["rendering<br/>text, fonts, e-ink waveforms"]
AUD["audio<br/>A2DP sink, MP3, TTS"]
READ["formats<br/>EPUB parser"]
UTIL["utilities<br/>HTML text, clock, capabilities"]
end
APP --> DEV
APP --> REND
APP --> AUD
APP --> READ
APP --> UTIL
style APP fill:#dbeafe,stroke:#2563eb,stroke-width:2px
style SDK fill:#dcfce7,stroke:#16a34aFour feature-gated modules, pick what you need:
| Module | Feature | What it provides |
|---|---|---|
device | device | Framebuffer + e-ink refresh, touch input, power button, frontlight, wakelocks, battery, WiFi, Bluetooth, device detection |
rendering | rendering | Text engine (HarfBuzz + fontdue), e-ink waveform constants, dirty-region diffing, image decode (PNG/JPEG/GIF/BMP) |
audio | audio | A2DP sink, PCM player with paced writes, MP3 decode + resample, TTS synthesis orchestration (re-exports kothok-edge-tts; TTS needs WiFi) |
formats | reader | EPUB parsing: chapter extraction, cover image, metadata |
All enabled by default. Disable what you don’t need:
# A music player: device + audio only
kobo-core = { version = "0.2", default-features = false, features = ["device", "audio"] }§Install
cargo add kobo-core§Quick start
use kobo_core::device;
// Auto-detect which Kobo model is running
let cfg = device::detect::detect_device().expect("unknown Kobo");
println!("{} ({}dpi, {})", cfg.model, cfg.display_dpi, cfg.codename);
// Framebuffer + e-ink refresh
use kobo_core::device::fb::Fb;
use kobo_core::rendering::eink::WAVE_GC16;
if let Some(fb) = Fb::open() {
let rgb565_bytes = vec![0u8; fb.xres * fb.yres * 2];
fb.present(&rgb565_bytes, fb.xres, fb.yres, false, 0, fb.yres, WAVE_GC16);
}
// Frontlight brightness
use kobo_core::device::power;
if let Some(path) = power::frontlight_path(&cfg.frontlight) {
power::frontlight_set(&path, 50);
}
// Battery
let pct = device::battery::battery_pct();
println!("Battery: {pct}%");§Supported devices
| Model | Codename | SoC | Color | BT |
|---|---|---|---|---|
| Libra Colour | monza / monzaKobo | MTK | Yes | Yes |
| Clara Colour | spaColour | MTK | Yes | Yes |
| Clara BW | spaBW / spaKoboBW | MTK | No | Yes |
| Elipsa 2E | condor | MTK | No | Yes |
| Sage | cadmus | sunxi | No | Yes |
| Libra 2 | io | NXP | No | Yes |
| Clara 2E | goldfinch | NXP | No | Yes |
| Clara HD | nova | NXP | No | No |
| Forma | frost | NXP | No | No |
| Forma 32GB | storm | NXP | No | No |
| Nia | luna | NXP | No | No |
| Elipsa | elipsa | NXP | No | No |
| Aura ONE | pika | NXP | No | No |
| Aura H2O | dahlia | NXP | No | No |
| Glo HD | alyssum | NXP | No | No |
| Aura SE | star | NXP | No | No |
| Aura | snow | NXP | No | No |
| Aura HD | dragon | NXP | No | No |
| Glo | kraken | NXP | No | No |
| Mini | pixie | NXP | No | No |
| Touch | trilogy | NXP | No | No |
Device detection is automatic from /sys/devices/soc0/machine (codename).
§E-ink waveforms
use kobo_core::rendering::eink;
// Pick the right waveform for each scenario
let transition = eink::waveform_for(eink::RenderScenario::Transition); // GL16
let content = eink::waveform_for(eink::RenderScenario::Content); // GL16
let animation = eink::waveform_for(eink::RenderScenario::Animation); // A2| Constant | Value | Use case |
|---|---|---|
WAVE_INIT | 0 | Boot/clear |
WAVE_DU | 1 | Fast monochrome |
WAVE_GC16 | 2 | Full grayscale clearing |
WAVE_GL16 | 3 | Partial updates, less ghosting |
WAVE_A2 | 4 | Animation (fastest, monochrome) |
WAVE_GLR16 | 5 | MTK color optimized |
WAVE_GLD16 | 6 | MTK color dark |
§API reference
Complete alphabetical list of major public exports.
| Name | Kind | Module | Description |
|---|---|---|---|
battery_pct | fn | device::battery | Battery percentage (0-100) |
Capabilities | trait | capabilities | Query WiFi/BT/battery/clock state |
Chapter | struct | formats | EPUB chapter: title, XHTML content |
decode_image | fn | rendering::text_render | Decode PNG/JPEG/GIF/BMP to RGB565 |
detect_script | fn | rendering::text_render | Detect text script (Latin, Arabic, Bengali, CJK, etc.) |
detect_device | fn | device::detect | Auto-detect Kobo model from sysfs |
DeviceConfig | struct | device::config | Model name, codename, DPI, SoC, touch protocol |
diff_rows | fn | rendering::eink | Compare two buffers, return dirty row range |
EpubBook | struct | formats | Parsed EPUB: chapters, cover, metadata |
Fb | struct | device::fb | Framebuffer mmap + e-ink refresh ioctl |
frontlight_get | fn | device::power | Read current brightness (returns Option<u32>) |
frontlight_path | fn | device::power | Locate frontlight sysfs path from FrontlightConfig |
frontlight_set | fn | device::power | Set brightness (0-100) |
init_tls | fn | audio | Install rustls crypto provider (for TTS) |
install_font | fn | rendering::text_render::fonts | Register a font for a script |
MockCapabilities | struct | capabilities | Test mock for Capabilities trait |
Player | struct | audio::player | A2DP PCM player with paced writes |
Prepared | struct | audio::player | Decoded PCM + word boundaries |
set_rtl / is_rtl | fn | rendering::common | Set/read RTL text direction flag |
slice_as_bytes | fn | rendering::common | Reinterpret slice as &[u8] (generic) |
synthesize_prepared | fn | audio::synth | TTS synthesis with retry + gap baking |
waveform_for | fn | rendering::eink | Pick waveform by RenderScenario |
wifi_status | fn | device::wifi | Check if WiFi is connected |
wifi_toggle | fn | device::wifi | Turn WiFi on/off (manages wpa_supplicant) |
§Build
# Native (for tests)
cargo build
cargo test
# Cross-compile for Kobo (armv7)
cross build --target armv7-unknown-linux-musleabihf --release§Related projects
- KoThok (EReader): the e-reader app built on this SDK
- kothok-edge-tts: Microsoft
Edge TTS client (re-exported via the
audiofeature)
§License
MIT
Re-exports§
pub use capabilities::Capabilities;pub use capabilities::MockCapabilities;pub use clock::highlight_index;pub use formats::epub::Chapter;pub use formats::epub::EpubBook;pub use formats::epub::EpubError;pub use html_text::TextSegment;pub use html_text::lines;pub use html_text::lines;pub use html_text::sentence_index_at;pub use html_text::Line;pub use stub_player::StubPlayer;
Modules§
- audio
- capabilities
- Capability detection (plan S5): drives the read-aloud vs plain-reader state
machine.
MockCapabilitiesis for the desktop simulator; the real impl (KoboCapabilities) lives in thekobobackend crate (checks network reach - clock
SharedClock- the single playback time source (decision 2).- device
- Device module: hardware database, device I/O, and rendering primitives.
- formats
- Document formats. EPUB is the MVP format (PDF deferred - plan S8).
- html_
text - Chapter XHTML -> plain text + a char-offset->element map.
- logger
- rendering
- Rendering primitives: text engine, UI draw helpers, e-ink constants.
- stub_
player StubPlayer- a headless stub proving the control + shared-clock + highlight loop (decision 1 multi-thread + decision 2 single clock) WITHOUT real audio or a Slint window. The desktop sim drives it with fakeWordMarks; the real Player (kobo-audio) and the real Slint sim reuse the sameSharedClock+ control pattern once a build env with cc/display is available.