# How OpenLogi's Hardware Probe Cache Stores Device Identities on Disk

> OpenLogi's hardware probe cache stores device identities to disk using JSON and serde serialization. Benefit from warm starts and cached device metadata across restarts.

- Repository: [Xuan Zhang/OpenLogi](https://github.com/AprilNEA/OpenLogi)
- Tags: internals
- Published: 2026-09-05

---

**OpenLogi persists discovered HID device identities to a JSON file using serde serialization, enabling warm starts across application restarts by caching device capabilities and metadata to platform-specific user data directories.**

The hardware probe cache in OpenLogi eliminates redundant hardware enumeration by maintaining a persistent record of discovered HID devices. This system stores device identities—including vendor IDs, product IDs, and serial numbers—to disk as structured JSON, allowing the application to resume operation with cached device knowledge after restarts. According to the OpenLogi source code, this mechanism is implemented in the `openlogi-hid` crate to provide reliable device persistence.

## Storage Location and File Format

### Platform-Specific Data Directories

OpenLogi uses the **dirs** crate to determine the appropriate user data directory for the current platform. On Linux systems, the cache file resides at `$XDG_DATA_HOME/openlogi/probe_cache.json`, while macOS and Windows utilize their equivalent standard directories. This approach guarantees a writable location that persists across user sessions without requiring administrator privileges.

### JSON Structure and Serialization

The cache stores a map from unique HID identifiers to lightweight metadata structs. Each entry maps a composite key of **vendor ID**, **product ID**, and **serial number** to a **`ProbeInfo`** struct containing device capabilities and cached metadata. The **serde** library handles serialization, converting the in-memory map to human-readable JSON for disk storage.

## Persistence Mechanism and Error Handling

### Write-Through Cache Updates

When the HID enumerator completes a device scan, it invokes **`ProbeCache::save()`** to persist the current state. This method serializes the in-memory map and writes it atomically to the fixed JSON path. According to [`crates/openlogi-hid/src/probe_cache.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-hid/src/probe_cache.rs), if the data directory is inaccessible, the system logs a warning and falls back to **memory-only mode**, continuing operation without disk persistence.

### Read-Through Initialization

During startup, **`ProbeCache::load()`** attempts to read the existing JSON file from the determined path. If the file is missing or unreadable, the cache initializes as empty and emits a warning, effectively performing a cold start. As implemented in [`probe_cache.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/probe_cache.rs), this resilient approach ensures the application remains functional even when the cache file has been deleted or corrupted.

## Source Code Implementation

The core implementation resides in **[`crates/openlogi-hid/src/probe_cache.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-hid/src/probe_cache.rs)**, where the module header explicitly states it "Keeps the probe cache as JSON at a fixed path." Key behaviors include:

- Logging a warning when the data directory cannot be located (line 33)
- Gracefully handling JSON parse errors by starting with an empty cache (line 52)
- Providing atomic save operations to prevent cache corruption

The HID host enumerator in **[`crates/openlogi-hid/src/host.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-hid/src/host.rs)** (line 208) consumes this cache to provide a persistent view of devices across runs. Additionally, **[`crates/openlogi-device/src/inventory/persist.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/crates/openlogi-device/src/inventory/persist.rs)** defines the persistent representation used by the device crate for immutable cache storage.

## Working with the Probe Cache

Loading the cache during initialization:

```rust
let cache = ProbeCache::load()?;  // reads JSON from the fixed path

```

Persisting after device enumeration:

```rust
let mut cache = ProbeCache::new();
// populate cache with discovered devices...
cache.save()?;  // writes JSON atomically

```

Inspecting the cache manually for debugging:

```bash

# Linux path example:

cat $XDG_DATA_HOME/openlogi/probe_cache.json

```

## Summary

- OpenLogi's hardware probe cache stores HID device identities as JSON in platform-specific user data directories determined by the dirs crate
- The cache uses **serde** to serialize a map of device identifiers to `ProbeInfo` structs containing capabilities and metadata
- `ProbeCache::load()` and `ProbeCache::save()` provide read-through and write-through semantics with atomic writes
- Error handling ensures graceful degradation to memory-only operation when disk access fails, logging appropriate warnings
- The implementation in [`probe_cache.rs`](https://github.com/AprilNEA/OpenLogi/blob/main/probe_cache.rs) ensures device persistence across application restarts while maintaining compatibility with the HID host enumerator

## Frequently Asked Questions

### What file format does OpenLogi use for the hardware probe cache?

OpenLogi uses **JSON** format for the probe cache, serialized with the serde library. The file contains a mapping of HID device identifiers (vendor ID, product ID, serial number) to `ProbeInfo` structs that store device capabilities and cached metadata.

### Where is the hardware probe cache stored on Linux systems?

On Linux, the cache file is located at `$XDG_DATA_HOME/openlogi/probe_cache.json`, which typically resolves to `~/.local/share/openlogi/probe_cache.json`. OpenLogi uses the dirs crate to determine this path according to XDG Base Directory specifications.

### What happens if OpenLogi cannot write to the probe cache file?

If the application cannot access the data directory or write the JSON file, it logs a warning and operates in memory-only mode. The hardware probe cache continues functioning temporarily in RAM, but device identities will not persist across application restarts until file system access is restored.

### How does OpenLogi handle corrupted or missing cache files?

When `ProbeCache::load()` encounters a missing file or invalid JSON, it initializes a fresh empty cache and logs a warning. The application proceeds with a cold start, repopulating the cache through hardware enumeration during the next device scan cycle.