docs: refresh cache formats and web server workflows (#2233)

## Summary

* **What is the goal of this PR?** Update project documentation to match
the current master implementation for cache formats, i18n, file
transfer/web server workflows, SD-card fonts, and root user-facing docs.
* **What changes are included?** Refreshes `book.bin`/`section.bin` docs
for v6/v25, updates File Transfer/Calibre/WebDAV/API docs, documents 24
UI languages and JSON language persistence, updates root
README/USER_GUIDE cache and network details, and syncs the tracked
CLAUDE skill doc cache-version notes.

## Additional Context

* Docs-only change. Verified with `git diff --check origin/master..HEAD`
and stale-reference greps for old cache versions, removed i18n APIs, old
WiFi screen wording, and raw `Serial.printf` examples. No firmware build
was run.

---

### AI Usage

While CrossPoint doesn't have restrictions on AI tools in contributing,
please be transparent about their usage as it
helps set the right context for reviewers.

Did you use AI tools to help write this code? _**NO**_
This commit is contained in:
Leopoldo Pla Sempere
2026-06-07 15:47:44 -04:00
committed by GitHub
parent 3a1e9f3023
commit 7f01eab62e
12 changed files with 789 additions and 594 deletions
+4 -4
View File
@@ -896,8 +896,8 @@ rm -rf /path/to/sd/.crosspoint/epub_<hash>/sections/
**Source**: `lib/Epub/Epub/Section.cpp`, `lib/Epub/Epub/BookMetadataCache.cpp` **Source**: `lib/Epub/Epub/Section.cpp`, `lib/Epub/Epub/BookMetadataCache.cpp`
**Current Versions** (as of docs/file-formats.md): **Current Versions** (as of docs/file-formats.md):
- `book.bin`: **Version 5** (metadata structure) - `book.bin`: **Version 7** (metadata structure)
- `section.bin`: **Version 24** (layout structure) - `section.bin`: **Version 25** (layout structure)
**Version Increment Rules**: **Version Increment Rules**:
1. **ALWAYS increment version** BEFORE changing binary structure 1. **ALWAYS increment version** BEFORE changing binary structure
@@ -907,7 +907,7 @@ rm -rf /path/to/sd/.crosspoint/epub_<hash>/sections/
**Example** (incrementing section format version): **Example** (incrementing section format version):
```cpp ```cpp
// lib/Epub/Epub/Section.cpp // lib/Epub/Epub/Section.cpp
static constexpr uint8_t SECTION_FILE_VERSION = 25; // Was 24, now 25 static constexpr uint8_t SECTION_FILE_VERSION = 26; // Was 25, now 26
// Add new field to structure // Add new field to structure
struct PageLine { struct PageLine {
@@ -918,4 +918,4 @@ struct PageLine {
--- ---
Philosophy: We are building a dedicated e-reader, not a Swiss Army knife. If a feature adds RAM pressure without significantly improving the reading experience, it is Out of Scope. Philosophy: We are building a dedicated e-reader, not a Swiss Army knife. If a feature adds RAM pressure without significantly improving the reading experience, it is Out of Scope.
+8 -3
View File
@@ -29,7 +29,7 @@ CrossPoint is open-source e-reader firmware - community-built, fully hackable, f
- Web settings UI/API (edit many device settings from browser) - Web settings UI/API (edit many device settings from browser)
- WebSocket fast uploads - WebSocket fast uploads
- WebDAV handler - WebDAV handler
- AP mode (hotspot) and STA mode (join existing WiFi), both with QR helpers - AP mode (hotspot) and STA mode (join existing Wi-Fi), both with QR helpers
- Calibre wireless connect flow - Calibre wireless connect flow
- OPDS browser with saved servers (up to 8), search, pagination, and direct download - OPDS browser with saved servers (up to 8), search, pagination, and direct download
- OTA update checks and installs from GitHub releases - OTA update checks and installs from GitHub releases
@@ -207,7 +207,7 @@ CrossPoint Reader is pretty aggressive about caching data down to the SD card to
### Data caching ### Data caching
The first time chapters of a book are loaded, they are cached to the SD card. Subsequent loads are served from the The first time chapters of a book are loaded, they are cached to the SD card. Subsequent loads are served from the
cache. This cache directory exists at `.crosspoint` on the SD card. The structure is as follows: cache. This cache directory exists at `.crosspoint` on the SD card. The structure is as follows:
```text ```text
@@ -216,13 +216,18 @@ cache. This cache directory exists at `.crosspoint` on the SD card. The structur
│ ├── progress.bin # reading position (chapter, page, etc.) │ ├── progress.bin # reading position (chapter, page, etc.)
│ ├── cover.bmp # generated cover image │ ├── cover.bmp # generated cover image
│ ├── book.bin # metadata: title, author, spine, TOC │ ├── book.bin # metadata: title, author, spine, TOC
│ ├── css_rules.cache # parsed CSS rule cache
│ ├── img_* # rendered image cache files
│ └── sections/ # per-chapter layout cache │ └── sections/ # per-chapter layout cache
│ ├── 0.bin │ ├── 0.bin
│ ├── 1.bin │ ├── 1.bin
│ └── ... │ └── ...
├── settings.json # device settings
├── state.json # resume/runtime state
└── recent.json # recent books list
``` ```
Removing `/.crosspoint` clears all cached metadata and forces a full regeneration on next open. Note: the cache isn't cleared automatically when you delete a book, and moving a file to a new path resets its reading progress. Removing `/.crosspoint` clears all cached metadata and forces a full regeneration on next open. Book deletes, overwrites, and moves done through the firmware or web UI clear or re-key matching caches; manual SD-card edits may leave stale cache directories behind.
For more details on the internal file structures, see the [file formats document](./docs/file-formats.md). For more details on the internal file structures, see the [file formats document](./docs/file-formats.md).
+21 -21
View File
@@ -21,7 +21,7 @@ Welcome to the **CrossPoint** firmware. This guide outlines the hardware control
- [3.6.3 Controls](#363-controls) - [3.6.3 Controls](#363-controls)
- [3.6.4 System](#364-system) - [3.6.4 System](#364-system)
- [3.6.5 OPDS Servers (Multiple Libraries)](#365-opds-servers-multiple-libraries) - [3.6.5 OPDS Servers (Multiple Libraries)](#365-opds-servers-multiple-libraries)
- [3.6.6 Web Settings (WiFi + OPDS)](#366-web-settings-wifi--opds) - [3.6.6 Web Settings (Wi-Fi + OPDS)](#366-web-settings-wi-fi--opds)
- [3.6.7 KOReader Sync Quick Setup](#367-koreader-sync-quick-setup) - [3.6.7 KOReader Sync Quick Setup](#367-koreader-sync-quick-setup)
- [3.7 Sleep Screen](#37-sleep-screen) - [3.7 Sleep Screen](#37-sleep-screen)
- [3.8 Custom Fonts (SD Card)](#38-custom-fonts-sd-card) - [3.8 Custom Fonts (SD Card)](#38-custom-fonts-sd-card)
@@ -103,18 +103,18 @@ The Recent Books screen lists the most recently opened books in a chronological
### 3.5 File Transfer Screen ### 3.5 File Transfer Screen
The File Transfer screen allows you to upload new e-books to the device. When you enter the screen, you'll be prompted with a WiFi selection dialog and then your X4 will start hosting a web server. The File Transfer screen allows you to upload and manage files on the device. When you enter the screen, choose **Join a Network**, **Calibre Wireless**, or **Create Hotspot**. The reader then starts the web server for the selected mode.
See the [webserver docs](./docs/webserver.md) for more information on how to connect to the web server and upload files. See the [web server docs](./docs/webserver.md) for more information on how to connect to the web server and upload files.
The web interface also supports **WebDAV**, allowing you to mount the device as a network drive and manage files directly from your computer's file manager. The web interface also supports **WebDAV**, allowing you to mount the device as a network drive and manage files directly from your computer's file manager.
Download links for files already on the device are available in the web interface, so you can retrieve books or screenshots over WiFi without connecting a cable. Download links for files already on the device are available in the web interface, so you can retrieve books or screenshots over Wi-Fi without connecting a cable.
A **WiFi signal strength indicator** (dBm) is displayed on-screen during web server sessions. A **Wi-Fi signal strength indicator** (dBm) is displayed on-screen during joined-network web server sessions.
> [!TIP] > [!TIP]
> Advanced users can also manage files programmatically or via the command line using `curl`. See the [webserver docs](./docs/webserver.md) for details. > Advanced users can also manage files programmatically or via the command line using `curl`. See the [web server docs](./docs/webserver.md) for details.
> [!TIP] > [!TIP]
> If your EPUBs have compatibility issues, you can run the built-in **EPUB Optimizer** directly from the device to clean up and reprocess books for better rendering. > If your EPUBs have compatibility issues, you can run the built-in **EPUB Optimizer** directly from the device to clean up and reprocess books for better rendering.
@@ -130,9 +130,9 @@ CrossPoint supports sending books from Calibre using the CrossPoint Reader devic
- Open Calibre → Preferences → Plugins → Load plugin from file → Select the zip file. - Open Calibre → Preferences → Plugins → Load plugin from file → Select the zip file.
2. On the device: File Transfer → Connect to Calibre → Join a network. 2. On the device: File Transfer -> Calibre Wireless, then join a network.
3. Make sure your computer is on the same WiFi network. 3. Make sure your computer is on the same Wi-Fi network.
4. In Calibre, click "Send to device" to transfer books. 4. In Calibre, click "Send to device" to transfer books.
@@ -253,7 +253,7 @@ The Settings screen allows you to configure the device's behavior. There are a f
- **Time to Sleep**: Set the duration of inactivity before the device automatically goes to sleep; options are 1, 3, 5, 10 (default), 15 or 30 minutes. - **Time to Sleep**: Set the duration of inactivity before the device automatically goes to sleep; options are 1, 3, 5, 10 (default), 15 or 30 minutes.
- **WiFi Networks**: Connect to WiFi networks for file transfers and firmware updates. - **Wi-Fi Networks**: Connect to Wi-Fi networks for file transfers and firmware updates.
- **KOReader Sync**: Options for setting up KOReader for syncing book progress. - **KOReader Sync**: Options for setting up KOReader for syncing book progress.
@@ -261,9 +261,9 @@ The Settings screen allows you to configure the device's behavior. There are a f
- **Clear Reading Cache**: Clear the internal SD card cache. - **Clear Reading Cache**: Clear the internal SD card cache.
- **Check for updates**: Check for Crosspoint firmware updates over WiFi. Firmware can also be updated without a USB connection by placing a `firmware.bin` file on the SD card. - **Check for updates**: Check for Crosspoint firmware updates over Wi-Fi. Firmware can also be updated without a USB connection by placing a `firmware.bin` file on the SD card.
- **Language**: Set the UI language. CrossPoint supports 22 languages including English, Spanish, French, German, Czech, Portuguese, Russian, Swedish, Turkish, Danish, Finnish, Polish, Dutch, Belarusian, Italian, Ukrainian, Romanian, Catalan, Vietnamese, Kazakh, Slovenian, and more. - **Language**: Set the UI language. CrossPoint supports 24 languages: English, Spanish, French, German, Czech, Brazilian Portuguese, Russian, Swedish, Romanian, Catalan, Ukrainian, Belarusian, Italian, Polish, Finnish, Danish, Dutch, Turkish, Kazakh, Hungarian, Lithuanian, Slovenian, Valencian, and Hebrew.
- **Manage Fonts**: Browse, download, and manage custom font families installed from the SD card. See [Custom Fonts (SD Card)](#38-custom-fonts-sd-card) for more information. - **Manage Fonts**: Browse, download, and manage custom font families installed from the SD card. See [Custom Fonts (SD Card)](#38-custom-fonts-sd-card) for more information.
@@ -296,22 +296,22 @@ You can also manage OPDS servers from the web interface while in File Transfer m
2. Open `http://<device-ip>/settings`. 2. Open `http://<device-ip>/settings`.
3. Use the **OPDS Servers** card to add, edit, or delete entries. 3. Use the **OPDS Servers** card to add, edit, or delete entries.
For web-based WiFi network management, see [Web Settings (WiFi + OPDS)](#366-web-settings-wifi--opds). For web-based Wi-Fi network management, see [Web Settings (Wi-Fi + OPDS)](#366-web-settings-wi-fi--opds).
#### 3.6.6 Web Settings (WiFi + OPDS) #### 3.6.6 Web Settings (Wi-Fi + OPDS)
While in **File Transfer** mode, the web settings page includes management cards for both **WiFi Networks** and **OPDS Servers**. While in **File Transfer** mode, the web settings page includes management cards for both **Wi-Fi Networks** and **OPDS Servers**.
1. On device: open **File Transfer** and connect to WiFi. 1. On device: open **File Transfer** and connect through **Join a Network** or **Create Hotspot**.
2. In a browser, open `http://<device-ip>/settings` or `http://crosspoint.local`. 2. In a browser, open `http://<device-ip>/settings` or `http://crosspoint.local`.
3. In **WiFi Networks**, add, edit, or delete saved network entries (SSID + optional password). 3. In **Wi-Fi Networks**, add, edit, or delete saved network entries (SSID + optional password).
4. In **OPDS Servers**, add, edit, or delete OPDS catalogs. 4. In **OPDS Servers**, add, edit, or delete OPDS catalogs.
Behavior notes: Behavior notes:
- Passwords are never shown back in the web UI after saving. - Passwords are never shown back in the web UI after saving.
- Leaving Password blank while editing keeps the existing saved password unchanged. - Leaving Password blank while editing keeps the existing saved password unchanged.
- The web UI can save hidden-network SSIDs, but connecting to hidden networks still depends on device-side WiFi connection flow. - The web UI can save hidden-network SSIDs, but connecting to hidden networks still depends on the device-side Wi-Fi connection flow.
#### 3.6.7 KOReader Sync Quick Setup #### 3.6.7 KOReader Sync Quick Setup
@@ -477,7 +477,7 @@ CrossPoint supports loading additional fonts from the SD card, extending beyond
There are three ways to install fonts: There are three ways to install fonts:
1. **Download from device (recommended):** Go to **Settings System Manage Fonts**, browse the available font families, and select one to download over WiFi. 1. **Download from device (recommended):** Go to **Settings -> System -> Manage Fonts**, browse the available font families, and select one to download over Wi-Fi.
2. **Upload via web interface:** While in **File Transfer** mode, open the web UI in a browser and navigate to the **Fonts** tab to upload `.cpfont` files. 2. **Upload via web interface:** While in **File Transfer** mode, open the web UI in a browser and navigate to the **Fonts** tab to upload `.cpfont` files.
3. **Manual SD card copy:** Download font files from the [crosspoint-fonts repository](https://github.com/crosspoint-reader/crosspoint-fonts) and copy them to `/.fonts/` (preferred) or `/fonts/` on your SD card. 3. **Manual SD card copy:** Download font files from the [crosspoint-fonts repository](https://github.com/crosspoint-reader/crosspoint-fonts) and copy them to `/.fonts/` (preferred) or `/fonts/` on your SD card.
@@ -533,9 +533,9 @@ CrossPoint renders text using the following Unicode character blocks, enabling s
* **Latin Script (Basic, Supplement, Extended-A/B):** Covers English, German, French, Spanish, Portuguese, Italian, Dutch, Swedish, Norwegian, Danish, Finnish, Polish, Czech, Hungarian, Romanian, Slovak, Slovenian, Turkish, Catalan, and others. * **Latin Script (Basic, Supplement, Extended-A/B):** Covers English, German, French, Spanish, Portuguese, Italian, Dutch, Swedish, Norwegian, Danish, Finnish, Polish, Czech, Hungarian, Romanian, Slovak, Slovenian, Turkish, Catalan, and others.
* **Cyrillic Script (Standard and Extended):** Covers Russian, Ukrainian, Belarusian, Bulgarian, Serbian, Macedonian, Kazakh, Kyrgyz, Mongolian, and others. * **Cyrillic Script (Standard and Extended):** Covers Russian, Ukrainian, Belarusian, Bulgarian, Serbian, Macedonian, Kazakh, Kyrgyz, Mongolian, and others.
* **Vietnamese:** Supported via extended Latin glyph coverage in the built-in fonts. * **Vietnamese:** Supported via extended Latin glyph coverage in the built-in reader fonts.
What is not supported with built-in fonts: Chinese, Japanese, Korean, Hebrew, Arabic, Greek, and Farsi. However, **CJK and other extended scripts can be enabled by installing custom SD card fonts** — see [Custom Fonts (SD Card)](#38-custom-fonts-sd-card). What is not supported with built-in reader fonts: Chinese, Japanese, Korean, Arabic, Greek, Hebrew, and Farsi. However, **CJK, Hebrew, Greek, and other extended scripts can be enabled by installing custom SD card fonts** — see [Custom Fonts (SD Card)](#38-custom-fonts-sd-card).
--- ---
@@ -638,4 +638,4 @@ Press **Ctrl-C** or close the graph window to exit.
If the device is stuck in a bootloop, press and release the Reset button. Then, press and hold on to the configured Back button and the Power Button to boot to the Home Screen. If the device is stuck in a bootloop, press and release the Reset button. Then, press and hold on to the configured Back button and the Power Button to boot to the Home Screen.
There can be issues with broken cache or config. In this case, delete the `.crosspoint` directory on your SD card (or consider deleting only `settings.bin`, `state.bin`, or `epub_*` cache directories in the `.crosspoint/` folder). There can be issues with broken cache or config. In this case, delete the `.crosspoint` directory on your SD card (or consider deleting only `settings.json`, `state.json`, or `epub_*` cache directories in the `.crosspoint/` folder).
+39 -22
View File
@@ -8,17 +8,18 @@ At a high level, it is firmware that uses an activity-driven application archite
```mermaid ```mermaid
graph TD graph TD
A[Hardware: ESP32-C3 + SD + E-ink + Buttons] --> B[open-x4-sdk HAL] A[Hardware: ESP32-C3 + SD + E-ink + Buttons] --> B[open-x4-sdk]
B --> C[src/main.cpp runtime loop] B --> C[lib/hal wrappers]
C --> D[Activities layer] C --> D[src/main.cpp runtime loop]
C --> E[State and settings] D --> E[Activities layer]
D --> F[Reader flows] D --> F[State and settings]
D --> G[Home/Library/Settings flows] E --> G[Reader flows]
D --> H[Network/Web server flows] E --> H[Home/Library/Settings flows]
F --> I[lib/Epub parsing + layout + hyphenation] E --> I[Network/Web server flows]
I --> J[SD cache in .crosspoint] G --> J[lib/Epub parsing + layout + hyphenation]
D --> K[GfxRenderer] J --> K[SD cache in .crosspoint]
K --> L[E-ink display buffer] E --> L[GfxRenderer]
L --> M[E-ink display buffer]
``` ```
## Runtime lifecycle ## Runtime lifecycle
@@ -58,7 +59,7 @@ Top-level activity groups:
- `src/activities/home/`: home and library navigation - `src/activities/home/`: home and library navigation
- `src/activities/reader/`: EPUB/XTC/TXT reading flows - `src/activities/reader/`: EPUB/XTC/TXT reading flows
- `src/activities/settings/`: settings menus and configuration - `src/activities/settings/`: settings menus and configuration
- `src/activities/network/`: WiFi selection, AP/STA mode, file transfer server - `src/activities/network/`: Wi-Fi selection, AP/STA mode, file transfer server
- `src/activities/boot_sleep/`: boot and sleep transitions - `src/activities/boot_sleep/`: boot and sleep transitions
## Reader and content pipeline ## Reader and content pipeline
@@ -73,10 +74,11 @@ flowchart LR
C -->|EPUB| D[lib/Epub/Epub] C -->|EPUB| D[lib/Epub/Epub]
C -->|XTC| E[lib/Xtc reader] C -->|XTC| E[lib/Xtc reader]
C -->|TXT| F[lib/Txt reader] C -->|TXT| F[lib/Txt reader]
D --> G[Parse OPF/TOC/CSS] D --> G[Parse OPF/TOC and collect CSS refs]
G --> H[Layout pages/sections] G --> H[Build/load book.bin and css_rules.cache]
H --> I[Write section and metadata caches] H --> I[Layout pages/sections]
I --> J[Render current page via GfxRenderer] I --> J[Write section cache]
J --> K[Render current page via GfxRenderer]
``` ```
Why caching matters: Why caching matters:
@@ -98,7 +100,7 @@ flowchart TD
D --> E[Locate container and OPF] D --> E[Locate container and OPF]
E --> F[Build or load BookMetadataCache] E --> F[Build or load BookMetadataCache]
F --> G[Load TOC and spine] F --> G[Load TOC and spine]
G --> H[Load or parse CSS rules] G --> H[Load CSS cache or parse manifest/base-dir CSS]
H --> I[EpubReaderActivity] H --> I[EpubReaderActivity]
I --> J{Section cache exists for current settings?} I --> J{Section cache exists for current settings?}
@@ -121,7 +123,12 @@ flowchart TD
Notes: Notes:
- "section cache exists" depends on cache-busting parameters such as font and layout-related settings - CSS files are collected from the OPF manifest and, when needed, discovered by
streaming ZIP paths under the OPF content base directory; the firmware avoids
preloading the full ZIP central directory for large books.
- "section cache exists" depends on cache-busting parameters such as font,
viewport size, paragraph alignment, hyphenation, embedded CSS, image rendering,
and Focus Reading settings
- rendering favors reusing precomputed layout data to keep page turns responsive on constrained hardware - rendering favors reusing precomputed layout data to keep page turns responsive on constrained hardware
- progress/session state is persisted so the reader can reopen at the last position after reboot/sleep - progress/session state is persisted so the reader can reopen at the last position after reboot/sleep
@@ -138,14 +145,18 @@ Typical persisted areas on SD:
/.crosspoint/ /.crosspoint/
epub_<hash>/ epub_<hash>/
book.bin book.bin
css_rules.cache
progress.bin progress.bin
cover.bmp cover.bmp
sections/*.bin sections/*.bin
settings.bin img_* cache files
state.bin settings.json
state.json
``` ```
For binary cache formats, see `docs/file-formats.md`. `sections/*.bin` contains rendered pages plus anchor, paragraph, and list-item
lookup tables used for TOC/footnote jumps and KOReader sync refinement. For
binary cache formats, see `docs/file-formats.md`.
## Networking architecture ## Networking architecture
@@ -153,14 +164,18 @@ Network file transfer is controlled by `src/activities/network/CrossPointWebServ
Modes: Modes:
- STA: join existing WiFi network - STA: join existing Wi-Fi network
- AP: create hotspot - AP: create hotspot
- Calibre Wireless: STA flow specialized for Calibre plugin uploads
Server behavior: Server behavior:
- HTTP server on port 80 - HTTP server on port 80
- WebSocket upload server on port 81 - WebSocket upload server on port 81
- WebDAV handler on the HTTP server
- UDP discovery listener for upload clients
- file operations backed by SD storage - file operations backed by SD storage
- browser APIs for file management, settings, fonts, OPDS servers, and saved Wi-Fi networks
- activity requests faster loop responsiveness while server is running - activity requests faster loop responsiveness while server is running
Endpoint reference: `docs/webserver-endpoints.md`. Endpoint reference: `docs/webserver-endpoints.md`.
@@ -170,6 +185,7 @@ Endpoint reference: `docs/webserver-endpoints.md`.
Some sources are generated and should not be edited manually. Some sources are generated and should not be edited manually.
- `scripts/build_html.py` generates `src/network/html/*.generated.h` from HTML files - `scripts/build_html.py` generates `src/network/html/*.generated.h` from HTML files
- `scripts/gen_i18n.py` generates `lib/I18n/I18nKeys.h`, `I18nStrings.h`, and `I18nStrings.cpp`
- `scripts/generate_hyphenation_trie.py` generates hyphenation headers under `lib/Epub/Epub/hyphenation/generated/` - `scripts/generate_hyphenation_trie.py` generates hyphenation headers under `lib/Epub/Epub/hyphenation/generated/`
When editing related source assets, regenerate via normal build steps/scripts. When editing related source assets, regenerate via normal build steps/scripts.
@@ -179,6 +195,7 @@ When editing related source assets, regenerate via normal build steps/scripts.
- `src/`: app orchestration, settings/state, and activity implementations - `src/`: app orchestration, settings/state, and activity implementations
- `src/network/`: web server and OTA/update networking - `src/network/`: web server and OTA/update networking
- `src/components/`: theming and shared UI components - `src/components/`: theming and shared UI components
- `lib/hal/`: hardware abstraction wrappers around open-x4-sdk
- `lib/Epub/`: EPUB parser, layout, CSS handling, and hyphenation - `lib/Epub/`: EPUB parser, layout, CSS handling, and hyphenation
- `lib/`: supporting libraries (fonts, text, filesystem helpers, etc.) - `lib/`: supporting libraries (fonts, text, filesystem helpers, etc.)
- `open-x4-sdk/`: hardware SDK submodule (display, input, storage, battery) - `open-x4-sdk/`: hardware SDK submodule (display, input, storage, battery)
+152 -87
View File
@@ -1,22 +1,26 @@
# File Formats # File Formats
These formats describe the SD-card cache files under `/.crosspoint/epub_<hash>/`.
All POD fields are written in the ESP32 little-endian representation used by
`Serialization.h`; strings are length-prefixed UTF-8.
## `book.bin` ## `book.bin`
### Version 5 ### Version 7
ImHex Pattern: `book.bin` stores EPUB metadata plus lookup tables for spine and TOC entries.
The current firmware writes this version from `BookMetadataCache`.
ImHex pattern:
```c++ ```c++
import std.mem; import std.mem;
import std.string; import std.string;
import std.core; import std.core;
// === Configuration === #define EXPECTED_VERSION 7
#define EXPECTED_VERSION 5
#define MAX_STRING_LENGTH 65535 #define MAX_STRING_LENGTH 65535
// === String Structure ===
struct String { struct String {
u32 length [[hidden, comment("String byte length")]]; u32 length [[hidden, comment("String byte length")]];
if (length > MAX_STRING_LENGTH) { if (length > MAX_STRING_LENGTH) {
@@ -29,75 +33,56 @@ fn format_string(String s) {
return s.data; return s.data;
}; };
// === Metadata Structure ===
struct Metadata { struct Metadata {
String title [[comment("Book title")]]; String title [[comment("Book title")]];
String author [[comment("Book author")]]; String author [[comment("Book author")]];
String language [[comment("Book language code")]]; String language [[comment("Book language code")]];
String coverItemHref [[comment("Path to cover image")]]; String coverItemHref [[comment("Path to cover image")]];
String textReferenceHref [[comment("Path to guided first text reference")]]; String textReferenceHref [[comment("Path to guided first text reference")]];
} [[comment("Book metadata information")]]; };
// === Spine Entry Structure ===
struct SpineEntry { struct SpineEntry {
String href [[comment("Resource path")]]; String href [[comment("Resource path")]];
u32 cumulativeSize [[comment("Cumulative size in bytes"), color("FF6B6B")]]; u32 cumulativeSize [[comment("Cumulative uncompressed spine size through this entry")]];
s16 tocIndex [[comment("Index into TOC (-1 if none)"), color("4ECDC4")]]; s16 tocIndex [[comment("Index into TOC, or inherited/previous TOC index when no direct entry exists")]];
} [[comment("Spine entry defining reading order")]]; };
// === TOC Entry Structure ===
struct TocEntry { struct TocEntry {
String title [[comment("Chapter/section title")]]; String title [[comment("Chapter/section title")]];
String href [[comment("Resource path")]]; String href [[comment("Resource path")]];
String anchor [[comment("Fragment identifier")]]; String anchor [[comment("Fragment identifier")]];
u8 level [[comment("Nesting level (0-255)"), color("95E1D3")]]; u8 level [[comment("Nesting level")]];
s16 spineIndex [[comment("Index into spine (-1 if none)"), color("F38181")]]; s16 spineIndex [[comment("Index into spine (-1 if none)")]];
} [[comment("Table of contents entry")]]; };
// === Book Bin Structure ===
struct BookBin { struct BookBin {
// Header u8 version;
u8 version [[comment("Format version"), color("FFD93D")]];
// Version validation
if (version != EXPECTED_VERSION) { if (version != EXPECTED_VERSION) {
std::error(std::format("Unsupported version: {} (expected {})", version, EXPECTED_VERSION)); std::error(std::format("Unsupported version: {} (expected {})", version, EXPECTED_VERSION));
} }
u32 lutOffset [[comment("Offset to lookup tables"), color("6BCB77")]]; u32 lutOffset [[comment("Offset to lookup tables")]];
u16 spineCount [[comment("Number of spine entries"), color("4D96FF")]]; u16 spineCount;
u16 tocCount [[comment("Number of TOC entries"), color("FF6B9D")]]; u16 tocCount;
// Metadata section Metadata metadata;
Metadata metadata [[comment("Book metadata")]];
// Validate LUT offset alignment
u32 currentOffset = $; u32 currentOffset = $;
if (currentOffset != lutOffset) { if (currentOffset != lutOffset) {
std::warning(std::format("LUT offset mismatch: expected 0x{:X}, got 0x{:X}", lutOffset, currentOffset)); std::warning(std::format("LUT offset mismatch: expected 0x{:X}, got 0x{:X}", lutOffset, currentOffset));
} }
// Lookup Tables u32 spineLut[spineCount] [[comment("Spine entry offsets")]];
u32 spineLut[spineCount] [[comment("Spine entry offsets"), color("4D96FF")]]; u32 tocLut[tocCount] [[comment("TOC entry offsets")]];
u32 tocLut[tocCount] [[comment("TOC entry offsets"), color("FF6B9D")]];
// Data Entries SpineEntry spines[spineCount];
SpineEntry spines[spineCount] [[comment("Spine entries (reading order)")]]; TocEntry toc[tocCount];
TocEntry toc[tocCount] [[comment("Table of contents entries")]];
}; };
// === File Parsing ===
BookBin book @ 0x00; BookBin book @ 0x00;
// Validate we've consumed the entire file
u32 fileSize = std::mem::size(); u32 fileSize = std::mem::size();
u32 parsedSize = $; u32 parsedSize = $;
if (parsedSize != fileSize) { if (parsedSize != fileSize) {
std::warning(std::format("Unparsed data detected: {} bytes remaining at offset 0x{:X}", fileSize - parsedSize, parsedSize)); std::warning(std::format("Unparsed data detected: {} bytes remaining at offset 0x{:X}", fileSize - parsedSize, parsedSize));
} }
@@ -105,20 +90,33 @@ if (parsedSize != fileSize) {
## `section.bin` ## `section.bin`
### Version 24 ### Version 25
ImHex Pattern: Each file in `sections/*.bin` stores one laid-out spine section. The header is
also the cache-busting key: if any layout-affecting setting differs from the
current reader settings, the section is discarded and rebuilt.
Version 25 includes:
- cache-busting fields for paragraph alignment, hyphenation, embedded CSS,
image rendering mode, and Focus Reading
- page offset LUT
- anchor-to-page map for fragment and footnote navigation
- paragraph and list-item LUTs used by KOReader sync page refinement
- optional per-word Focus Reading split metadata
- per-page footnote entries
ImHex pattern:
```c++ ```c++
import std.mem; import std.mem;
import std.string; import std.string;
import std.core; import std.core;
// === Configuration === #define EXPECTED_VERSION 25
#define EXPECTED_VERSION 24
#define MAX_STRING_LENGTH 65535 #define MAX_STRING_LENGTH 65535
#define FOOTNOTE_NUMBER_LEN 32
// === String Structure === #define FOOTNOTE_HREF_LEN 96
struct String { struct String {
u32 length [[hidden, comment("String byte length")]]; u32 length [[hidden, comment("String byte length")]];
@@ -132,44 +130,79 @@ fn format_string(String s) {
return s.data; return s.data;
}; };
// === Page Structure ===
enum PageElementTag : u8 { enum PageElementTag : u8 {
PageLine = 1, TAG_PageLine = 1,
PageImage = 2, TAG_PageImage = 2,
PageHorizontalRule = 3 TAG_PageHorizontalRule = 3
}; };
enum WordStyle : u8 { enum WordStyle : u8 {
REGULAR = 0, REGULAR = 0,
BOLD = 1, BOLD = 1,
ITALIC = 2, ITALIC = 2,
BOLD_ITALIC = 3 BOLD_ITALIC = 3,
UNDERLINE = 4,
STRIKETHROUGH = 8,
SUP = 16,
SUB = 32
}; };
enum BlockStyle : u8 { enum TextAlign : u8 {
JUSTIFIED = 0, JUSTIFIED = 0,
LEFT_ALIGN = 1, LEFT_ALIGN = 1,
CENTER_ALIGN = 2, CENTER_ALIGN = 2,
RIGHT_ALIGN = 3, RIGHT_ALIGN = 3,
NONE = 4
};
struct BlockStyle {
TextAlign alignment;
bool textAlignDefined;
s16 marginTop;
s16 marginBottom;
s16 marginLeft;
s16 marginRight;
s16 paddingTop;
s16 paddingBottom;
s16 paddingLeft;
s16 paddingRight;
s16 textIndent;
bool textIndentDefined;
bool isRtl;
bool directionDefined;
};
struct TextBlock {
u16 wordCount;
String words[wordCount];
s16 wordXPos[wordCount];
WordStyle wordStyle[wordCount];
u8 hasFocus;
if (hasFocus != 0) {
u8 wordFocusBoundary[wordCount] [[comment("UTF-8 byte boundary between bold prefix and suffix")]];
u16 wordFocusSuffixX[wordCount] [[comment("Suffix x offset from word start")]];
}
BlockStyle blockStyle;
};
struct ImageBlock {
String imagePath;
s16 width;
s16 height;
}; };
struct PageLine { struct PageLine {
s16 xPos; s16 xPos;
s16 yPos; s16 yPos;
u16 wordCount; TextBlock block;
String words[wordCount];
u16 wordXPos[wordCount];
WordStyle wordStyle[wordCount];
BlockStyle blockStyle;
}; };
struct PageImage { struct PageImage {
s16 xPos; s16 xPos;
s16 yPos; s16 yPos;
String imagePath; ImageBlock image;
s16 width;
s16 height;
}; };
struct PageHorizontalRule { struct PageHorizontalRule {
@@ -180,63 +213,95 @@ struct PageHorizontalRule {
}; };
struct PageElement { struct PageElement {
u8 pageElementType; PageElementTag pageElementType;
if (pageElementType == 1) { if (pageElementType == TAG_PageLine) {
PageLine pageLine [[inline]]; PageLine pageLine [[inline]];
} else if (pageElementType == 2) { } else if (pageElementType == TAG_PageImage) {
PageImage pageImage [[inline]]; PageImage pageImage [[inline]];
} else if (pageElementType == 3) { } else if (pageElementType == TAG_PageHorizontalRule) {
PageHorizontalRule horizontalRule [[inline]]; PageHorizontalRule horizontalRule [[inline]];
} else { } else {
std::error(std::format("Unknown page element type: {}", pageElementType)); std::error(std::format("Unknown page element type: {}", pageElementType));
} }
}; };
struct FootnoteEntry {
char number[FOOTNOTE_NUMBER_LEN];
char href[FOOTNOTE_HREF_LEN];
};
struct Page { struct Page {
u16 elementCount; u16 elementCount;
PageElement elements[elementCount] [[inline]]; PageElement elements[elementCount] [[inline]];
u16 footnoteCount;
FootnoteEntry footnotes[footnoteCount];
}; };
// === Section Bin Structure === struct AnchorEntry {
String anchor;
u16 page;
};
struct AnchorMap {
u16 count;
AnchorEntry entries[count];
};
struct ParagraphLut {
u16 count;
u16 paragraphIndex[count];
};
struct SectionBin { struct SectionBin {
// Header u8 version;
u8 version [[comment("Format version"), color("FFD93D")]];
// Version validation
if (version != EXPECTED_VERSION) { if (version != EXPECTED_VERSION) {
std::error(std::format("Unsupported version: {} (expected {})", version, EXPECTED_VERSION)); std::error(std::format("Unsupported version: {} (expected {})", version, EXPECTED_VERSION));
} }
// Cache busting parameters
s32 fontId; s32 fontId;
float lineCompression; float lineCompression;
bool extraParagraphSpacing; bool extraParagraphSpacing;
u8 paragraphAlignment;
u16 viewportWidth; u16 viewportWidth;
u16 vieportHeight; u16 viewportHeight;
bool hyphenationEnabled;
bool embeddedStyle;
u8 imageRendering;
bool focusReadingEnabled;
u16 pageCount; u16 pageCount;
u32 lutOffset; u32 pageLutOffset;
u32 anchorMapOffset;
u32 paragraphLutOffset;
u32 listItemLutOffset;
Page page[pageCount]; Page pages[pageCount];
// Validate LUT offset alignment
u32 currentOffset = $; u32 currentOffset = $;
if (currentOffset != lutOffset) { if (currentOffset != pageLutOffset) {
std::warning(std::format("LUT offset mismatch: expected 0x{:X}, got 0x{:X}", lutOffset, currentOffset)); std::warning(std::format("Page LUT offset mismatch: expected 0x{:X}, got 0x{:X}", pageLutOffset, currentOffset));
} }
// Lookup Tables u32 pageLut[pageCount] [[comment("Page data offsets")]];
u32 lut[pageCount];
if (anchorMapOffset != 0) {
AnchorMap anchorMap @ anchorMapOffset;
}
if (paragraphLutOffset != 0) {
ParagraphLut paragraphLut @ paragraphLutOffset;
}
if (listItemLutOffset != 0 && paragraphLutOffset != 0) {
u16 listItemIndex[paragraphLut.count] @ listItemLutOffset;
}
}; };
// === File Parsing === SectionBin section @ 0x00;
SectionBin book @ 0x00;
// Validate we've consumed the entire file
u32 fileSize = std::mem::size(); u32 fileSize = std::mem::size();
u32 parsedSize = $; u32 parsedSize = $;
if (parsedSize != fileSize) { if (parsedSize != fileSize) {
std::warning(std::format("Unparsed data detected: {} bytes remaining at offset 0x{:X}", fileSize - parsedSize, parsedSize)); std::warning(std::format("Unparsed data detected: {} bytes remaining at offset 0x{:X}", fileSize - parsedSize, parsedSize));
} }
+1 -1
View File
@@ -11,7 +11,7 @@ Focus Reading is a reading aid that bolds the first portion of each word, guidin
1. Open **Settings > Reader** 1. Open **Settings > Reader**
2. Toggle **Focus Reading** on 2. Toggle **Focus Reading** on
Toggling the setting will trigger a re-index of your current book, the same as when changing font settings. Once indexing is complete, page turns proceed as normal. No changes are made to your EPUB files. Toggling the setting invalidates affected EPUB section caches for the current layout, the same as changing font settings. Sections are rebuilt on demand, then page turns proceed as normal. No changes are made to your EPUB files.
## Examples ## Examples
+42 -23
View File
@@ -5,17 +5,29 @@ This guide explains the multi-language support system in CrossPoint Reader.
## Supported Languages ## Supported Languages
- English - English
- French - Español
- German - Français
- Portuguese - Deutsch
- Spanish - Čeština
- Swedish - Português (Brasil)
- Czech - Русский
- Russian - Svenska
- Ukrainian - Română
- Polish - Català
- Danish - Українська
- Turkish - Беларуская
- Italiano
- Polski
- Suomi
- Dansk
- Nederlands
- Türkçe
- Қазақша
- Magyar
- Lietuvių
- Slovenščina
- Valencià
- עברית
--- ---
@@ -108,7 +120,9 @@ This automatically:
#### 3. Use in code #### 3. Use in code
```cpp ```cpp
#include <CrossPointSettings.h>
#include <I18n.h> #include <I18n.h>
#include <Logging.h>
// Using the tr() macro (recommended) // Using the tr() macro (recommended)
renderer.drawText(font, x, y, tr(STR_MY_NEW_STRING)); renderer.drawText(font, x, y, tr(STR_MY_NEW_STRING));
@@ -175,7 +189,7 @@ The YAML files use UTF-8 encoding. Special characters are automatically converte
// tr(id) - Get translated string without StrId:: prefix // tr(id) - Get translated string without StrId:: prefix
const char* text = tr(STR_SETTINGS_TITLE); const char* text = tr(STR_SETTINGS_TITLE);
renderer.drawText(font, x, y, tr(STR_BROWSE_FILES)); renderer.drawText(font, x, y, tr(STR_BROWSE_FILES));
Serial.printf("Status: %s\n", tr(STR_CONNECTED)); LOG_INF("I18N", "Status: %s", tr(STR_CONNECTED));
// I18N - Shorthand for I18n::getInstance() // I18N - Shorthand for I18n::getInstance()
I18N.setLanguage(Language::ES); I18N.setLanguage(Language::ES);
@@ -191,34 +205,39 @@ const char* text = tr(STR_SETTINGS_TITLE); // Macro (recommended)
const char* text = I18N.get(StrId::STR_SETTINGS_TITLE); // Direct call const char* text = I18N.get(StrId::STR_SETTINGS_TITLE); // Direct call
const char* text = I18N[StrId::STR_SETTINGS_TITLE]; // Operator overload const char* text = I18N[StrId::STR_SETTINGS_TITLE]; // Operator overload
// Set language // Set runtime language
I18N.setLanguage(Language::ES); I18N.setLanguage(Language::ES);
// Get current language // Get current language
Language lang = I18N.getLanguage(); Language lang = I18N.getLanguage();
// Save language setting to file
I18N.saveSettings();
// Load language setting from file
I18N.loadSettings();
// Get character set for font subsetting (static method) // Get character set for font subsetting (static method)
const char* chars = I18n::getCharacterSet(Language::FR); const char* chars = I18n::getCharacterSet(Language::FR);
// Persist a user language choice
SETTINGS.language = static_cast<uint8_t>(Language::ES);
SETTINGS.saveToFile();
``` ```
--- ---
## File Storage ## File Storage
Language settings are stored in: The selected language is stored with the rest of the device settings in:
```text
/.crosspoint/settings.json
``` ```
The JSON field is `language`, stored as a stable language code string such as
`"EN"`, `"DE"`, or `"HE"` rather than a raw enum value.
Older firmware versions used:
```text
/.crosspoint/language.bin /.crosspoint/language.bin
``` ```
This file contains: On load, current firmware migrates that legacy file into `settings.json` and
- Version byte renames it to `language.bin.bak`.
- Current language selection (1 byte)
--- ---
+6 -5
View File
@@ -9,15 +9,15 @@ There are three ways to install fonts:
### Option 1: Download from device (recommended) ### Option 1: Download from device (recommended)
1. Connect your CrossPoint reader to WiFi 1. Connect your CrossPoint reader to Wi-Fi
2. Go to **Settings > System > Manage Fonts** 2. Go to **Settings > System > Manage Fonts**
3. Browse available font families and tap to download 3. Browse available font families and tap to download
4. Downloaded fonts appear immediately in **Settings > Reader > Font Family** 4. Downloaded fonts appear immediately in **Settings > Reader > Font Family**
### Option 2: Upload via web browser ### Option 2: Upload via web browser
1. Connect your CrossPoint reader to WiFi 1. Start **File Transfer** and connect through **Join Network** or **Create Hotspot**
2. Open the web interface in your browser (shown on the WiFi screen) 2. Open the web interface URL shown on the reader
3. Navigate to the **Fonts** tab 3. Navigate to the **Fonts** tab
4. Upload `.cpfont` files using the upload form 4. Upload `.cpfont` files using the upload form
@@ -96,6 +96,7 @@ To convert your own TrueType/OpenType fonts:
| `latin-ext` | European languages (Latin + Extended-A/B + punctuation + ligatures) | | `latin-ext` | European languages (Latin + Extended-A/B + punctuation + ligatures) |
| `greek` | Greek + Extended Greek | | `greek` | Greek + Extended Greek |
| `cyrillic` | Cyrillic + Supplement | | `cyrillic` | Cyrillic + Supplement |
| `hebrew` | Hebrew + Alphabetic Presentation Forms |
| `georgian` | Georgian + Georgian Supplement | | `georgian` | Georgian + Georgian Supplement |
| `armenian` | Armenian | | `armenian` | Armenian |
| `ethiopic` | Ethiopic + Extended | | `ethiopic` | Ethiopic + Extended |
@@ -107,7 +108,7 @@ To convert your own TrueType/OpenType fonts:
| `tifinagh` | Tifinagh | | `tifinagh` | Tifinagh |
| `symbols` | Math, currency, arrows, box-drawing, misc symbols, dingbats | | `symbols` | Math, currency, arrows, box-drawing, misc symbols, dingbats |
| `reading` | Literary fiction coverage: Latin, Greek, Cyrillic, math/symbol blocks, supplemental punctuation, and CJK quote marks | | `reading` | Literary fiction coverage: Latin, Greek, Cyrillic, math/symbol blocks, supplemental punctuation, and CJK quote marks |
| `builtin` | Matches built-in Bookerly coverage exactly | | `builtin` | Matches the firmware's built-in font conversion intervals |
Combine presets with commas: `--intervals latin-ext,greek,cyrillic` Combine presets with commas: `--intervals latin-ext,greek,cyrillic`
@@ -122,4 +123,4 @@ To list all presets with codepoint counts:
`--force-autohint` — force FreeType's auto-hinter instead of the font's native hinting (useful when a font's built-in hints produce poor results at small sizes). `--force-autohint` — force FreeType's auto-hinter instead of the font's native hinting (useful when a font's built-in hints produce poor results at small sizes).
Install custom fonts via WiFi upload or manual SD card copy. Install custom fonts via the web interface or manual SD card copy.
+6 -2
View File
@@ -1,7 +1,9 @@
# Translators # Translators
Below is a list of users and languages CrossPoint may support in the future. Below is a list of translator credits for languages with known contributors.
Note because a language is below does not mean there is official support for the language at this time. Official UI language support is determined by the YAML files in
`lib/I18n/translations/`; see [i18n.md](./i18n.md) for the current supported
language list.
## Contributing ## Contributing
@@ -37,6 +39,7 @@ If you'd like to add your name to this list, please open a PR adding yourself an
- [Skrzakk](https://github.com/Skrzakk) - [Skrzakk](https://github.com/Skrzakk)
- [pablohc](https://github.com/pablohc) - [pablohc](https://github.com/pablohc)
- [DaniPhii](https://github.com/DaniPhii) - [DaniPhii](https://github.com/DaniPhii)
- [lpla](https://github.com/lpla)
## Swedish ## Swedish
- [dawiik](https://github.com/dawiik) - [dawiik](https://github.com/dawiik)
@@ -47,6 +50,7 @@ If you'd like to add your name to this list, please open a PR adding yourself an
## Catalan ## Catalan
- [angeldenom](https://github.com/angeldenom) - [angeldenom](https://github.com/angeldenom)
- [lpla](https://github.com/lpla)
## Finnish ## Finnish
- [plahteenlahti](https://github.com/plahteenlahti) - [plahteenlahti](https://github.com/plahteenlahti)
+13 -10
View File
@@ -1,6 +1,6 @@
# Troubleshooting # Troubleshooting
This document show most common issues and possible solutions while using the device features. This document shows common issues and possible solutions while using the device features.
- [Troubleshooting](#troubleshooting) - [Troubleshooting](#troubleshooting)
- [Cannot See the Device on the Network](#cannot-see-the-device-on-the-network) - [Cannot See the Device on the Network](#cannot-see-the-device-on-the-network)
@@ -14,25 +14,27 @@ This document show most common issues and possible solutions while using the dev
**Solutions:** **Solutions:**
1. Verify both devices are on the **same WiFi network** 1. Verify both devices are on the correct network
- Check your computer/phone WiFi settings - Check your computer/phone Wi-Fi settings
- Confirm the CrossPoint Reader shows "Connected" status - In **Join Network** mode, your computer/phone and CrossPoint Reader must be on the same Wi-Fi network
- In **Create Hotspot** mode, your computer/phone must be connected to the `CrossPoint-Reader` hotspot
2. Double-check the IP address 2. Double-check the IP address
- Make sure you typed it correctly - Make sure you typed it correctly
- Include `http://` at the beginning - Include `http://` at the beginning
- Try the displayed IP address if `http://crosspoint.local/` does not resolve
3. Try disabling VPN if you're using one 3. Try disabling VPN if you're using one
4. Some networks have "client isolation" enabled - check with your network administrator 4. Some networks have "client isolation" enabled - use Create Hotspot mode or check with your network administrator
### Connection Drops or Times Out ### Connection Drops or Times Out
**Problem:** WiFi connection is unstable **Problem:** Wi-Fi connection is unstable
**Solutions:** **Solutions:**
1. Move closer to the WiFi router 1. Move closer to the Wi-Fi router, or use Create Hotspot mode for a direct connection
2. Check signal strength on the device (should be at least `||` or better) 2. Check signal strength on the device (should be at least `||` or better)
3. Avoid interference from other devices 3. Avoid interference from other devices
4. Try a different WiFi network if available 4. Try a different Wi-Fi network if available
### Upload Fails ### Upload Fails
@@ -40,10 +42,11 @@ This document show most common issues and possible solutions while using the dev
**Solutions:** **Solutions:**
1. Ensure the file is a valid `.epub` file 1. Check that the SD card has enough free space
2. Check that the SD card has enough free space 2. Check that the filename is valid for the SD card filesystem
3. Try uploading a smaller file first to test 3. Try uploading a smaller file first to test
4. Refresh the browser page and try again 4. Refresh the browser page and try again
5. If WebSocket upload fails repeatedly, refresh the page and retry with the HTTP fallback path
### Saved Password Not Working ### Saved Password Not Working
+399 -231
View File
@@ -1,72 +1,36 @@
# Webserver Endpoints # Webserver Endpoints
This document describes all HTTP and WebSocket endpoints available on the CrossPoint Reader webserver. This document describes the HTTP, WebSocket, WebDAV, and discovery endpoints
available while CrossPoint Reader is in File Transfer or Calibre Wireless mode.
- [Webserver Endpoints](#webserver-endpoints) - HTTP server: port 80
- [Overview](#overview) - WebSocket upload server: port 81
- [HTTP Endpoints](#http-endpoints) - UDP discovery listener: port 8134
- [GET `/` - Home Page](#get----home-page) - WebDAV: port 80, handled by the same HTTP server
- [GET `/files` - File Browser Page](#get-files---file-browser-page)
- [GET `/api/status` - Device Status](#get-apistatus---device-status)
- [GET `/api/files` - List Files](#get-apifiles---list-files)
- [POST `/upload` - Upload File](#post-upload---upload-file)
- [POST `/mkdir` - Create Folder](#post-mkdir---create-folder)
- [POST `/delete` - Delete File or Folder](#post-delete---delete-file-or-folder)
- [WebSocket Endpoint](#websocket-endpoint)
- [Port 81 - Fast Binary Upload](#port-81---fast-binary-upload)
- [Network Modes](#network-modes)
- [Station Mode (STA)](#station-mode-sta)
- [Access Point Mode (AP)](#access-point-mode-ap)
- [Notes](#notes)
Examples use `crosspoint.local`. If mDNS does not resolve on your network, use
the IP address shown on the device screen.
## Overview ## HTTP Pages
The CrossPoint Reader exposes a webserver for file management and device monitoring: | Method | Path | Purpose |
|--------|------|---------|
| `GET` | `/` | Home/status page |
| `GET` | `/files` | File manager page |
| `GET` | `/settings` | Web settings page |
| `GET` | `/fonts` | SD-card font manager page |
| `GET` | `/js/jszip.min.js` | JavaScript asset used by the file manager |
- **HTTP Server**: Port 80 ## Device Status
- **WebSocket Server**: Port 81 (for fast binary uploads)
--- ### `GET /api/status`
## HTTP Endpoints
### GET `/` - Home Page
Serves the home page HTML interface.
**Request:**
```bash
curl http://crosspoint.local/
```
**Response:** HTML page (200 OK)
---
### GET `/files` - File Browser Page
Serves the file browser HTML interface.
**Request:**
```bash
curl http://crosspoint.local/files
```
**Response:** HTML page (200 OK)
---
### GET `/api/status` - Device Status
Returns JSON with device status information.
**Request:**
```bash ```bash
curl http://crosspoint.local/api/status curl http://crosspoint.local/api/status
``` ```
**Response (200 OK):** Response:
```json ```json
{ {
"version": "1.0.0", "version": "1.0.0",
@@ -74,259 +38,463 @@ curl http://crosspoint.local/api/status
"mode": "STA", "mode": "STA",
"rssi": -45, "rssi": -45,
"freeHeap": 123456, "freeHeap": 123456,
"uptime": 3600 "uptime": 3600,
"device": "X4"
} }
``` ```
| Field | Type | Description | | Field | Type | Description |
| ---------- | ------ | --------------------------------------------------------- | |-------|------|-------------|
| `version` | string | CrossPoint firmware version | | `version` | string | Firmware version |
| `ip` | string | Device IP address | | `ip` | string | Device IP address |
| `mode` | string | `"STA"` (connected to WiFi) or `"AP"` (access point mode) | | `mode` | string | `"STA"` for joined Wi-Fi or `"AP"` for hotspot mode |
| `rssi` | number | WiFi signal strength in dBm (0 in AP mode) | | `rssi` | number | Wi-Fi RSSI in dBm; `0` in AP mode |
| `freeHeap` | number | Free heap memory in bytes | | `freeHeap` | number | Free heap in bytes |
| `uptime` | number | Seconds since device boot | | `uptime` | number | Seconds since boot |
| `device` | string | `"X3"` or `"X4"` hardware detection |
--- ## File Management
### GET `/api/files` - List Files ### `GET /api/files`
Returns a JSON array of files and folders in the specified directory. Lists files and folders under a directory.
**Request:**
```bash ```bash
# List root directory
curl http://crosspoint.local/api/files
# List specific directory
curl "http://crosspoint.local/api/files?path=/Books" curl "http://crosspoint.local/api/files?path=/Books"
``` ```
**Query Parameters:** Query parameters:
| Parameter | Required | Default | Description | | Parameter | Required | Default | Description |
| --------- | -------- | ------- | ---------------------- | |-----------|----------|---------|-------------|
| `path` | No | `/` | Directory path to list | | `path` | No | `/` | Directory to list |
Response:
**Response (200 OK):**
```json ```json
[ [
{"name": "MyBook.epub", "size": 1234567, "isDirectory": false, "isEpub": true}, {"name":"MyBook.epub","size":1234567,"isDirectory":false,"isEpub":true},
{"name": "Notes", "size": 0, "isDirectory": true, "isEpub": false}, {"name":"Notes","size":0,"isDirectory":true,"isEpub":false}
{"name": "document.pdf", "size": 54321, "isDirectory": false, "isEpub": false}
] ]
``` ```
| Field | Type | Description | Hidden dotfiles are omitted unless the device setting `showHiddenFiles` is
| ------------- | ------- | ---------------------------------------- | enabled. `System Volume Information` and `XTCache` are always hidden/protected.
| `name` | string | File or folder name |
| `size` | number | Size in bytes (0 for directories) |
| `isDirectory` | boolean | `true` if the item is a folder |
| `isEpub` | boolean | `true` if the file has `.epub` extension |
**Notes:** ### `GET /download`
- Hidden files (starting with `.`) are automatically filtered out
- System folders (`System Volume Information`, `XTCache`) are hidden
--- Downloads a file from the SD card.
### POST `/upload` - Upload File
Uploads a file to the SD card via multipart form data.
**Request:**
```bash ```bash
# Upload to root directory curl -OJ "http://crosspoint.local/download?path=/Books/MyBook.epub"
curl -X POST -F "file=@mybook.epub" http://crosspoint.local/upload ```
# Upload to specific directory Query parameters:
| Parameter | Required | Description |
|-----------|----------|-------------|
| `path` | Yes | File path to download |
Protected dotfiles, `System Volume Information`, and `XTCache` cannot be
downloaded. EPUB files are served as `application/epub+zip`; other files use
`application/octet-stream`.
### `POST /upload`
Uploads a file with HTTP multipart form data.
```bash
curl -X POST -F "file=@mybook.epub" "http://crosspoint.local/upload?path=/Books" curl -X POST -F "file=@mybook.epub" "http://crosspoint.local/upload?path=/Books"
``` ```
**Query Parameters:** Query parameters:
| Parameter | Required | Default | Description | | Parameter | Required | Default | Description |
| --------- | -------- | ------- | ------------------------------- | |-----------|----------|---------|-------------|
| `path` | No | `/` | Target directory for the upload | | `path` | No | `/` | Destination directory |
**Response (200 OK):** Successful response:
```
```text
File uploaded successfully: mybook.epub File uploaded successfully: mybook.epub
``` ```
**Error Responses:** Notes:
| Status | Body | Cause | - Existing files with the same name are overwritten.
| ------ | ----------------------------------------------- | --------------------------- | - EPUB cache data for the uploaded path is cleared after a successful upload.
| 400 | `Failed to create file on SD card` | Cannot create file | - HTTP upload uses a 4 KB write buffer before flushing to the SD card.
| 400 | `Failed to write to SD card - disk may be full` | Write error during upload |
| 400 | `Failed to write final data to SD card` | Error flushing final buffer |
| 400 | `Upload aborted` | Client aborted the upload |
| 400 | `Unknown error during upload` | Unspecified error |
**Notes:** ### `POST /mkdir`
- Existing files with the same name will be overwritten
- Uses a 4KB buffer for efficient SD card writes
--- Creates a folder.
### POST `/mkdir` - Create Folder
Creates a new folder on the SD card.
**Request:**
```bash ```bash
curl -X POST -d "name=NewFolder&path=/" http://crosspoint.local/mkdir curl -X POST -d "name=NewFolder&path=/" http://crosspoint.local/mkdir
``` ```
**Form Parameters:** Form parameters:
| Parameter | Required | Default | Description | | Parameter | Required | Default | Description |
| --------- | -------- | ------- | ---------------------------- | |-----------|----------|---------|-------------|
| `name` | Yes | - | Name of the folder to create | | `name` | Yes | - | New folder name |
| `path` | No | `/` | Parent directory path | | `path` | No | `/` | Parent folder |
**Response (200 OK):** ### `POST /rename`
```
Folder created: NewFolder
```
**Error Responses:** Renames a file.
```bash
curl -X POST -d "path=/Books/old.epub&name=new.epub" http://crosspoint.local/rename
```
Form parameters:
| Parameter | Required | Description |
|-----------|----------|-------------|
| `path` | Yes | Existing file path |
| `name` | Yes | New file name, not a path |
Only files can be renamed through this endpoint. The old EPUB cache path is
cleared before the rename.
### `POST /move`
Moves a file into an existing folder.
```bash
curl -X POST -d "path=/Books/mybook.epub&dest=/Read" http://crosspoint.local/move
```
Form parameters:
| Parameter | Required | Description |
|-----------|----------|-------------|
| `path` | Yes | Existing file path |
| `dest` | Yes | Existing destination folder |
Only files can be moved through this endpoint. The old EPUB cache path is
cleared before the move.
### `POST /delete`
Deletes one or more files or empty folders.
| Status | Body | Cause |
| ------ | ----------------------------- | ----------------------------- |
| 400 | `Missing folder name` | `name` parameter not provided |
| 400 | `Folder name cannot be empty` | Empty folder name |
| 400 | `Folder already exists` | Folder with same name exists |
| 500 | `Failed to create folder` | SD card error |
---
### POST `/delete` - Delete File or Folder
Deletes one or more files or empty folders from the SD card.
**Request:**
```bash ```bash
# Delete a file
curl -X POST -d "path=/Books/mybook.epub" http://crosspoint.local/delete curl -X POST -d "path=/Books/mybook.epub" http://crosspoint.local/delete
# Delete an empty folder
curl -X POST -d "path=/OldFolder" http://crosspoint.local/delete
# Delete multiple items
curl -X POST -d 'paths=["/Books/old.epub","/OldFolder"]' http://crosspoint.local/delete curl -X POST -d 'paths=["/Books/old.epub","/OldFolder"]' http://crosspoint.local/delete
``` ```
**Form Parameters:** Form parameters:
| Parameter | Required | Default | Description | | Parameter | Required | Description |
| --------- | -------- | ------- | ----------- | |-----------|----------|-------------|
| `path` | Yes, unless `paths` is provided | - | Path to one item to delete | | `path` | Yes, unless `paths` is provided | Single path to delete |
| `paths` | Yes, unless `path` is provided | - | JSON array of paths to delete | | `paths` | Yes, unless `path` is provided | JSON array of paths to delete |
Protected items cannot be deleted. Non-empty folders are rejected. EPUB cache
data for deleted files is cleared.
## Settings API
### `GET /api/settings`
Returns a streamed JSON array of editable settings. Each item contains common
fields plus type-specific fields.
```bash
curl http://crosspoint.local/api/settings
```
Example item:
```json
{
"key": "fontSize",
"name": "Font Size",
"category": "Reader",
"type": "enum",
"value": 1,
"options": ["Small", "Medium", "Large"]
}
```
Types:
| Type | Extra fields |
|------|--------------|
| `toggle` | `value` (`0` or `1`) |
| `enum` | `value`, `options` |
| `value` | `value`, `min`, `max`, `step` |
| `string` | `value` |
The font-family setting includes SD-card font families when they are installed.
### `POST /api/settings`
Applies a partial settings update from a JSON object.
```bash
curl -X POST \
-H "Content-Type: application/json" \
-d '{"fontSize":2,"showHiddenFiles":1}' \
http://crosspoint.local/api/settings
```
Successful response:
**Response (200 OK):**
```text ```text
All items deleted successfully Applied 2 setting(s)
``` ```
**Error Responses:** ## Font Management API
| Status | Body | Cause | ### `GET /api/fonts`
| ------ | ------------------------------------------- | ---------------------------------- |
| 400 | `Missing "path" or "paths" argument` | Neither parameter was provided |
| 400 | `Provide either 'path' or 'paths', not both` | Both delete parameters were sent |
| 400 | `Invalid paths format` | `paths` was not valid JSON |
| 400 | `No paths provided` | `paths` was an empty JSON array |
| 500 | `Failed to delete some items: ...` | One or more paths could not be deleted |
**Protected Items:** Lists installed SD-card font families.
- Files/folders starting with `.`
- `System Volume Information`
- `XTCache`
--- ```bash
curl http://crosspoint.local/api/fonts
## WebSocket Endpoint
### Port 81 - Fast Binary Upload
A WebSocket endpoint for high-speed binary file uploads. More efficient than HTTP multipart for large files.
**Connection:**
``` ```
Response:
```json
{
"maxFamilies": 128,
"families": [
{
"name": "Literata",
"sizes": [12, 14, 16, 18],
"files": [
{"name": "Literata_12.cpfont", "size": 123456}
]
}
]
}
```
### `POST /api/fonts/upload`
Uploads one `.cpfont` file into a family folder.
```bash
curl -X POST \
-F "family=Literata" \
-F "file=@Literata_12.cpfont" \
http://crosspoint.local/api/fonts/upload
```
The handler validates the family name, `.cpfont` filename, and `CPFONT` magic
bytes before accepting the file.
Successful response:
```json
{"ok":true}
```
### `POST /api/fonts/delete`
Deletes an installed font family.
```bash
curl -X POST \
-H "Content-Type: application/json" \
-d '{"family":"Literata"}' \
http://crosspoint.local/api/fonts/delete
```
Successful response:
```json
{"ok":true}
```
## OPDS Server API
### `GET /api/opds`
Lists saved OPDS servers. Passwords are never returned.
```bash
curl http://crosspoint.local/api/opds
```
Response:
```json
[
{
"index": 0,
"name": "My Catalog",
"url": "http://calibre.local:8080/opds",
"username": "reader",
"hasPassword": true
}
]
```
### `POST /api/opds`
Adds or updates an OPDS server. Include `index` to update an existing entry.
If `password` is omitted during an update, the existing password is preserved.
```bash
curl -X POST \
-H "Content-Type: application/json" \
-d '{"name":"My Catalog","url":"http://calibre.local:8080/opds","username":"reader","password":"secret"}' \
http://crosspoint.local/api/opds
```
### `POST /api/opds/delete`
Deletes an OPDS server by index.
```bash
curl -X POST \
-H "Content-Type: application/json" \
-d '{"index":0}' \
http://crosspoint.local/api/opds/delete
```
## Wi-Fi Credential API
### `GET /api/wifi`
Lists saved Wi-Fi networks. Passwords are never returned.
```bash
curl http://crosspoint.local/api/wifi
```
Response:
```json
[
{
"index": 0,
"ssid": "HomeWiFi",
"hasPassword": true,
"isLastConnected": true
}
]
```
### `POST /api/wifi`
Adds or updates a saved Wi-Fi network. Include `index` to update an existing
entry. If `password` is omitted during an update, the existing password is
preserved.
```bash
curl -X POST \
-H "Content-Type: application/json" \
-d '{"ssid":"HomeWiFi","password":"secret"}' \
http://crosspoint.local/api/wifi
```
### `POST /api/wifi/delete`
Deletes a saved Wi-Fi network by index.
```bash
curl -X POST \
-H "Content-Type: application/json" \
-d '{"index":0}' \
http://crosspoint.local/api/wifi/delete
```
## WebSocket Upload
### Port 81
The WebSocket path is used for fast binary uploads from the file manager and
Calibre plugin workflows.
Connection:
```text
ws://crosspoint.local:81/ ws://crosspoint.local:81/
``` ```
**Protocol:** Protocol:
1. **Client** sends TEXT message: `START:<filename>:<size>:<path>` 1. Client sends text: `START:<filename>:<size>:<path>`
2. **Server** responds with TEXT: `READY` 2. Server replies `READY`
3. **Client** sends BINARY messages with file data chunks 3. Client sends binary chunks
4. **Server** sends TEXT progress updates: `PROGRESS:<received>:<total>` 4. Server sends `PROGRESS:<received>:<total>` every 64 KB or at completion
5. **Server** sends TEXT when complete: `DONE` or `ERROR:<message>` 5. Server sends `DONE` when complete or `ERROR:<message>` on failure
**Example Session:** Example session:
``` ```text
Client -> "START:mybook.epub:1234567:/Books" Client -> START:mybook.epub:1234567:/Books
Server -> "READY" Server -> READY
Client -> [binary chunk 1] Client -> [binary chunk]
Client -> [binary chunk 2] Server -> PROGRESS:65536:1234567
Server -> "PROGRESS:65536:1234567"
Client -> [binary chunk 3]
... ...
Server -> "PROGRESS:1234567:1234567" Server -> DONE
Server -> "DONE"
``` ```
**Error Messages:** Error messages include:
| Message | Cause | | Message | Cause |
| --------------------------------- | ---------------------------------- | |---------|-------|
| `ERROR:Failed to create file` | Cannot create file on SD card | | `ERROR:Upload already in progress` | A second upload was started before the first completed |
| `ERROR:Invalid START format` | Malformed START message | | `ERROR:Invalid START format` | Malformed START message or invalid size token |
| `ERROR:No upload in progress` | Binary data received without START | | `ERROR:Failed to create file` | Destination file could not be opened |
| `ERROR:Write failed - disk full?` | SD card write error | | `ERROR:No upload in progress` | Binary data arrived without a matching START |
| `ERROR:Upload overflow` | Client sent more bytes than declared |
| `ERROR:Write failed - disk full?` | SD write failed |
**Example with `websocat`:** Incomplete WebSocket uploads are deleted on disconnect or error.
```bash
# Interactive session
websocat ws://crosspoint.local:81
# Then type: ## WebDAV
START:mybook.epub:1234567:/Books
# Wait for READY, then send binary data The same HTTP server registers a WebDAV-compatible handler for file manager clients.
Supported methods:
```text
OPTIONS, GET, HEAD, PUT, DELETE, PROPFIND, MKCOL, MOVE, COPY, LOCK, UNLOCK
``` ```
**Notes:** Notes:
- Progress updates are sent every 64KB or at completion
- Disconnection during upload will delete the incomplete file
- Existing files with the same name will be overwritten
--- - `PUT` writes to a temporary `.davtmp` file first, then renames it into place.
- Protected paths are rejected.
- `LOCK` and `UNLOCK` are accepted for client compatibility only. The server
does not implement full WebDAV Class 2 locking semantics such as persistent
locks or lock discovery.
## UDP Discovery
The server listens on UDP port `8134`. When it receives the text payload
`hello`, it replies to the sender with:
```text
crosspoint (on <hostname>);81
```
The final field is the WebSocket upload port.
## Network Modes ## Network Modes
The device can operate in two network modes:
### Station Mode (STA) ### Station Mode (STA)
- Device connects to an existing WiFi network
- IP address assigned by router/DHCP - Device joins an existing 2.4 GHz Wi-Fi network.
- `mode` field in `/api/status` returns `"STA"` - `crosspoint.local` is advertised with mDNS when available.
- `rssi` field shows signal strength - `/api/status` returns `"mode": "STA"` and RSSI in dBm.
### Access Point Mode (AP) ### Access Point Mode (AP)
- Device creates its own WiFi hotspot
- Default IP is typically `192.168.4.1`
- `mode` field in `/api/status` returns `"AP"`
- `rssi` field returns `0`
--- - Device creates an open hotspot named `CrossPoint-Reader`.
- The device shows a Wi-Fi QR code and URL QR code.
- The fallback IP is typically `192.168.4.1`.
- `/api/status` returns `"mode": "AP"` and `"rssi": 0`.
## Notes ### Calibre Wireless
- These examples use `crosspoint.local`. If your network does not support mDNS or the address does not resolve, replace it with the specific **IP Address** displayed on your device screen (e.g., `http://192.168.1.102/`). Calibre Wireless starts the same web server in STA mode and displays setup
- All paths on the SD card start with `/` instructions plus WebSocket upload progress on the device screen.
- Trailing slashes are automatically stripped (except for root `/`)
- The webserver uses chunked transfer encoding for file listings
+98 -185
View File
@@ -1,235 +1,148 @@
# Web Server Guide # Web Server Guide
This guide explains how to connect your CrossPoint Reader to WiFi and use the built-in web server to upload files from your computer or phone. This guide explains how to use CrossPoint Reader's built-in web server for file
transfer, device settings, Wi-Fi/OPDS management, and SD-card font management.
## Overview ## Overview
CrossPoint Reader includes a built-in web server that allows you to: The web server is available while the device is in **File Transfer** or
**Calibre Wireless** mode. It can:
- Upload files wirelessly from any device on the same WiFi network - Upload, download, rename, move, and delete files on the SD card
- Browse and manage files on your device's SD card - Create folders
- Create folders to organize your library - Edit many device settings from a browser
- Delete files and folders - Manage saved Wi-Fi networks and OPDS servers
- Upload and delete `.cpfont` SD-card font families
- Accept WebDAV clients and Calibre wireless uploads
## Prerequisites The server does not require authentication. Use it only on trusted private
networks or in hotspot mode when you control who is connected.
- Your CrossPoint Reader device ## Starting File Transfer
- A WiFi network
- A computer, phone, or tablet connected to the **same WiFi network**
--- 1. From the Home screen, select **File Transfer**.
2. Choose one of the available modes:
## Step 1: Accessing the WiFi Screen | Mode | Use when |
|------|----------|
| **Join Network** | You want the reader to join an existing Wi-Fi network. |
| **Calibre Wireless** | You want to receive books from the CrossPoint Calibre plugin workflow. |
| **Create Hotspot** | You want the reader to create its own open Wi-Fi network. |
1. From the main menu or file browser, navigate to the **Settings** screen ## Join Network Mode
2. Select the **WiFi** option
3. The device will automatically start scanning for available networks
--- 1. Select **Join Network**.
2. Pick a 2.4 GHz Wi-Fi network from the scan results.
3. Enter the password if prompted.
4. Save credentials if you want the reader to reconnect automatically next time.
## Step 2: Connecting to WiFi After connection, the reader shows:
### Viewing Available Networks - The connected SSID
- A QR code for the web URL
- The direct IP URL, for example `http://192.168.1.102/`
- The mDNS fallback URL, usually `http://crosspoint.local/`
Once the scan completes, you'll see a list of available WiFi networks with the following indicators: Use either URL from a phone, tablet, or computer on the same network.
- **Signal strength bars** (`||||`, `|||`, `||`, `|`) - Shows connection quality ## Create Hotspot Mode
- **`*` symbol** - Indicates the network is password-protected (encrypted)
- **`+` symbol** - Indicates you have previously saved credentials for this network
<img src="./images/wifi/wifi_networks.jpeg" height="500"> 1. Select **Create Hotspot**.
2. Connect your phone or computer to the open Wi-Fi network:
### Selecting a Network ```text
CrossPoint-Reader
```
1. Use the **Left/Right** (or **Volume Up/Down**) buttons to navigate through the network list 3. Open the URL shown on the reader. `http://crosspoint.local/` is preferred
2. Press **Confirm** to select the highlighted network when supported; the fallback IP is typically `http://192.168.4.1/`.
### Entering Password (for encrypted networks) The reader displays one QR code for joining the hotspot and another QR code for
opening the web interface.
If the network requires a password: ## Calibre Wireless Mode
1. An on-screen keyboard will appear Calibre Wireless starts the same web server in station mode, then displays setup
2. Use the navigation buttons to select characters instructions and upload progress on the reader. Use this mode with the
3. Press **Confirm** to enter each character CrossPoint Calibre plugin or other clients that speak the documented WebSocket
4. When complete, select the **Done** option on the keyboard upload protocol.
<img src="./images/wifi/wifi_password.jpeg" height="500"> For Calibre OPDS browsing, add `/opds` to the catalog URL when configuring an
OPDS server.
**Note:** If you've previously connected to this network, the saved password will be used automatically. ## Web Interface
### Connection Process The browser UI has four primary pages.
The device will display "Connecting..." while establishing the connection. This typically takes 5-10 seconds. ### Home
### Saving Credentials The Home page shows firmware status, network mode, IP address, device type,
uptime, and free heap.
If this is a new network, you'll be prompted to save the password:
- Select **Yes** to save credentials for automatic connection next time (NOTE: These are stored in plaintext on the device's SD card. Do not use this for sensitive networks.)
- Select **No** to connect without saving
---
## Step 3: Connection Success
Once connected, the screen will display:
- **Network name** (SSID)
- **IP Address** (e.g., `192.168.1.102`)
- **Web server URL** (e.g., `http://192.168.1.102/`)
<img src="./images/wifi/wifi_connected.jpeg" height="500">
**Important:** Make note of the IP address - you'll need this to access the web interface from your computer or phone.
---
## Step 4: Accessing the Web Interface
### From a Computer
1. Ensure your computer is connected to the **same WiFi network** as your CrossPoint Reader
2. Open any web browser (Chrome is recommended)
3. Type the IP address shown on your device into the browser's address bar
- Example: `http://192.168.1.102/`
4. Press Enter
### From a Phone or Tablet
1. Ensure your phone/tablet is connected to the **same WiFi network** as your CrossPoint Reader
2. Open your mobile browser (Safari, Chrome, etc.)
3. Type the IP address into the address bar
- Example: `http://192.168.1.102/`
4. Tap Go
---
## Step 5: Using the Web Interface
### Home Page
The home page displays:
- Device status and version information
- WiFi connection status
- Current IP address
- Available memory
Navigation links:
- **Home** - Returns to the status page
- **File Manager** - Access file management features
<img src="./images/wifi/webserver_homepage.png" width="600">
### File Manager ### File Manager
Click **File Manager** to access file management features. The File Manager page can:
#### Browsing Files - Browse SD-card folders
- Upload files, using WebSocket upload when available and HTTP upload as a fallback
- Create folders
- Download files
- Rename files
- Move files into existing folders
- Delete one or more selected files or empty folders
- The file manager displays all files and folders on your SD card Existing files with the same name are overwritten by uploads. When EPUB files
- **Folders** are highlighted in yellow and indicated with a 📁 icon are overwritten, moved, renamed, or deleted through the web server, the matching
- **EPUB Files** are highlighted in green and indicated with a 📗 icon book cache is cleared so stale metadata is not reused.
- **All Other Files** are not highlighted and indicated with a 📄 icon
- Click on a folder name to navigate into it
- Use the breadcrumb navigation at the top to go back to parent folders
<img src="./images/wifi/webserver_files.png" width="600"> ### Settings
#### Uploading Files The Settings page exposes many firmware settings in the browser. It also has
cards for:
1. Click the **📤 Upload** button in the top-right corner - Saved Wi-Fi networks
2. Click **Choose File** and select a file from your device - OPDS servers
3. Click **Upload**
4. A progress bar will show the upload status
5. The page will automatically refresh when the upload is complete
<img src="./images/wifi/webserver_upload.png" width="600"> Passwords are accepted when adding or editing entries, but saved passwords are
not returned by the API.
#### Creating Folders ### Fonts
1. Click the **📁 New Folder** button in the top-right corner The Fonts page lists installed SD-card font families and lets you upload
2. Enter a folder name (must not contain characters \" * : < > ? / \\ | and must not be . or ..) `.cpfont` files. Upload files from one font family at a time. The server validates
3. Click **Create Folder** the font family name, filename, and `.cpfont` magic bytes before accepting the
upload.
This is useful for organizing your library by genre, author, series or file type. Installed fonts appear in **Settings > Reader > Font Family** after the font
registry refreshes.
#### Deleting Files and Folders ## Command Line Use
1. Click the **🗑️** (trash) icon next to any file or folder Power users can use `curl`, WebDAV clients, or WebSocket clients while the web
2. Confirm the deletion in the popup dialog server is running.
3. Click **Delete** to permanently remove the item
**Warning:** Deletion is permanent and cannot be undone! Endpoint details are documented in [webserver-endpoints.md](./webserver-endpoints.md).
**Note:** Folders must be empty before they can be deleted.
#### Moving Files
1. Click the **📂** (folder) icon next to any file
2. Enter a folder name or select one from the dropdown
3. Click **Move** to relocate the file
**Note:** Typing in a nonexistent folder name will result in the following error: "Failed to move: Destination not found"
#### Renaming Files
1. Click the **✏️** (pencil) icon next to any file
2. Enter a file name (must not contain characters \" * : < > ? / \\ | and must not be . or ..)
3. Click **Rename** to permanently rename the file
---
## Command Line File Management
For power users, you can manage files directly from your terminal using `curl` while the device is in File Upload mode. Detailed documentation can be found [here](./webserver-endpoints.md).
## Security Notes ## Security Notes
- The web server runs on port 80 (standard HTTP) - The HTTP server runs on port 80.
- **No authentication is required** - anyone on the same network can access the interface - The WebSocket upload server runs on port 81.
- The web server is only accessible while the WiFi screen shows "Connected" - There is no authentication.
- The web server automatically stops when you exit the WiFi screen - Anyone on the same network can access the web interface while it is running.
- For security, only use on trusted private networks - The server stops when you exit File Transfer or Calibre Wireless mode.
- Hotspot mode creates an open network for connectivity fallback; disconnect when done.
--- ## Tips
## Technical Details 1. Use **Create Hotspot** when no trusted network is available.
2. Prefer `crosspoint.local` when available, but keep the displayed IP address as a fallback.
- **Supported WiFi:** 2.4GHz networks (802.11 b/g/n) 3. Move closer to the router if upload progress stalls in Join Network mode.
- **Web Server Port:** 80 (HTTP) 4. Upload custom fonts through the Fonts page or copy them to `/.fonts/` or `/fonts/` on the SD card.
- **Maximum Upload Size:** Limited by available SD card space 5. Exit File Transfer mode when finished to conserve battery.
- **Browser Compatibility:** All modern browsers (Chrome, Firefox, Safari, Edge)
---
## Tips and Best Practices
1. **Organize with folders** - Create folders before uploading to keep your library organized
2. **Check signal strength** - Stronger signals (`|||` or `||||`) provide faster, more reliable uploads
3. **Upload multiple files** - You can select and upload multiple files at once; the manager will queue them and refresh when the batch is finished
4. **Use descriptive names** - Name your folders clearly (e.g., "SciFi", "Mystery", "Non-Fiction")
5. **Keep credentials saved** - Save your WiFi password for quick reconnection in the future
6. **Exit when done** - Press **Back** to exit the WiFi screen and save battery
---
## Exiting WiFi Mode
When you're finished uploading files:
1. Press the **Back** button on your CrossPoint Reader
2. The web server will automatically stop
3. WiFi will disconnect to conserve battery
4. You'll return to the previous screen
Your uploaded files will be immediately available in the file browser!
---
## Related Documentation ## Related Documentation
- [User Guide](../USER_GUIDE.md) - General device operation - [User Guide](../USER_GUIDE.md)
- [Troubleshooting](./troubleshooting.md) - Troubleshooting - [Webserver Endpoints](./webserver-endpoints.md)
- [README](../README.md) - Project overview and features - [SD Card Fonts](./sd-card-fonts.md)
- [Troubleshooting](./troubleshooting.md)