oc2r-rust
Thin Rust bindings for the OC2R HLAPI controller. The crate mirrors the
behaviour of the Lua devices.lua helper: it speaks JSON over the first
VirtIO console (/dev/hvc0) and exposes ergonomic helpers for enumerating
devices, inspecting their methods, and invoking them.
Status
- ✅ mirrors
devices.lua:list,get,find,find_all,methods,invoke - ✅
Devicewrapper with lazy method cache - ✅
JsonValuealias you can use to build invocation parameters - ⏳ event subscription (
subscribe/unsubscribe) not exposed yet
The low-level framing logic follows the Java implementation in
RPCDeviceBusAdapter: messages are framed with leading/trailing NUL bytes and
the console is switched into raw mode before use.
Using the library
Add the crate to your workspace and interact with it directly:
use oc2r_rust::{DeviceBus, Result, DEFAULT_DEVICE_PATH};
fn main() -> Result<()> {
let mut bus = DeviceBus::connect(DEFAULT_DEVICE_PATH)?;
for device in bus.list()? {
println!("deviceId: {}", device.device_id);
println!(" types: {}", device.type_names.join(", "));
}
// Invoke a method on the first device as an example.
if let Some(mut device) = bus.device("some-device-id")? {
let response = device.call("help", ())?;
println!("help(): {response:?}");
}
Ok(())
}
Dynamic method calls
Device::call (and the matching DeviceBus::call) accept anything that
implements IntoJsonArgs,
so you can stay close to the Lua ergonomics:
device.call("setRedstoneOutput", ("east", 15_u8))?;
device.call("getRedstoneInput", ("north",))?;
Typed helpers
For common peripherals you can rely on typed wrappers. The redstone helper
mirrors the behaviour of redstone.lua and performs basic clamping/parsing:
use oc2r_rust::devices::redstone::{Redstone, Side};
use oc2r_rust::{DeviceBus, Result, DEFAULT_DEVICE_PATH};
fn main() -> Result<()> {
let mut bus = DeviceBus::connect(DEFAULT_DEVICE_PATH)?;
let mut redstone = Redstone::attach(&mut bus)?
.expect("no redstone interface attached");
redstone.set_output_state(Side::East, true)?;
println!("in: {}", redstone.input(Side::East)?);
Ok(())
}
Building the examples
Two runnable examples live in examples/:
list-devices– enumerate devices and pretty-print their metadatainvoke-method– list available methods for the first device and invoke oneredstone– toggle/query a redstone interface, mirroringredstone.lua
The OC2R VM does not ship a Rust toolchain, so build the binaries on your host and copy them into the VM:
# once
cargo install cross --git https://github.com/cross-rs/cross
# build release binaries
cross build --release --example list-devices
cross build --release --example invoke-method
cross build --release --example redstone
The resulting executables live under
target/<triple>/release/examples/. Copy them into Minux using your preferred
workflow—an Import/Export card in Minecraft works well if you drop the binary
onto the card outside the VM. Once the file is on disk (e.g. /usr/bin/), you
can execute it from the shell.
Architecture overview
bus.rs– high-levelDeviceBus/Devicehelperstransport.rs– POSIX plumbing (termios, poll, read/write)rpc.rs– miniserde data structures for OC2R messageserror.rs– shared error type andResult<T>alias
DeviceBus flushes the descriptor before sending each request, matching the
behaviour of both Lua and Java implementations and preventing stale replies
from leaking into new invocations.