Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

System commands

brick.system() has one method per system command, the protocol commands for files, firmware modules, settings and firmware updates (Bluetooth Developer Kit, appendix 1).

Commands

OpcodeMethodReply
0x80open_read(&name)OpenedFile { handle, size }
0x81open_write(&name, size)FileHandle
0x82read(handle, len)Chunk (≤ 58 bytes)
0x83write(handle, data)u16 bytes written (≤ 61 per call)
0x84close(handle)()
0x85delete(&name)()
0x86find_first(&pattern)FoundFile { handle, name, size }
0x87find_next(handle)FoundFile
0x88get_firmware_version()FirmwareVersion
0x89open_write_linear(&name, size)FileHandle
0x8Aopen_read_linear(&name)u32 flash address
0x8Bopen_write_data(&name, size)FileHandle
0x8Copen_append_data(&name)OpenedFile (size = space left)
0x90boot()(), USB only
0x91set_brick_name(&name)()
0x94get_device_info()DeviceInfo
0x97delete_user_flash()(): deletes all files
0x98poll_command_length(buffer)u8
0x99poll(buffer, len)Chunk
0x9Abluetooth_factory_reset()(), USB only
0xA0request_first_module(&pattern)ModuleInfo
0xA1request_next_module(handle)ModuleInfo
0xA2close_module_handle(handle)()
0xA3read_io_map(module, offset, len)Chunk (≤ 55 bytes)
0xA4write_io_map(module, offset, data)u16 (≤ 54 bytes per call)
—read_io_map_all(module, offset, len)Vec<u8>, as many requests as needed
—write_io_map_all(module, offset, data)(), as many requests as needed

Files with raw handles

Unlike the high-level API, nothing is closed for you here. Every handle you open, you close:

nxt_rs::doc_example(|brick| async move {
use nxt_rs::protocol::FileName;

let s = brick.system();
let name = FileName::new("raw.txt")?;

let h = s.open_write(&name, 5).await?;
s.write(h, b"hello").await?;
s.close(h).await?;

let file = s.open_read(&name).await?;
let data = s.read(file.handle, 5).await?;
s.close(file.handle).await?;
assert_eq!(&*data, b"hello");
Ok(()) });

A search handle from find_first must also be closed, unless the search ended with Status::NoMoreFiles.

In Drop implementations, which can’t .await, use brick.close_file_later(handle) or brick.close_module_later(handle). The close is then sent just before the next command. The high-level file types work this way.

Firmware modules and I/O maps

The firmware is made of modules (Display.mod, Output.mod, …). Each one exposes an I/O map, a block of memory you can read and write. That gives access to internals no command covers.

nxt_rs::doc_example(|brick| async move {
use nxt_rs::protocol::{FileName, ModuleId};

let s = brick.system();
let mut module = s.request_first_module(&FileName::new("*.*")?).await?;
loop {
    println!("{:<14} id {:#010x}, I/O map {} bytes", module.name, module.id.0, module.io_map_size);
    match s.request_next_module(module.handle).await {
        Ok(next) => module = next,
        Err(_) => break,
    }
}
s.close_module_handle(module.handle).await?;

// The screen buffer: 800 bytes at offset 119 of the display module.
let screen = s.read_io_map_all(ModuleId::DISPLAY, 119, 800).await?;
Ok(()) });

ModuleId has constants for the modules of LEGO’s standard firmware. Look the IDs up with request_first_module if you run a different firmware.

USB-only commands

boot (reboot into the SAM-BA firmware-update mode) and bluetooth_factory_reset are only accepted over USB. They only exist on a brick whose transport supports them:

async fn f(brick: nxt_rs::Brick<nxt_rs::transport::AnyTransport>) -> nxt_rs::Result<()> {
brick.system().bluetooth_factory_reset().await?;   // error: not available over AnyTransport
Ok(()) }

Brick<Usb>::boot_sam_ba(self) consumes the brick, because the connection is gone afterwards.

Warning: after boot, the brick ticks and does nothing until new firmware is flashed with a tool such as LEGO’s firmware updater or libnxt. Don’t call it by accident.