FlashThing is a tool for quickly and easily flashing the Spotify Car Thing (Superbird). FlashThing is composed of four parts:
- FlashThing: Rust crate for flashing superbird.
- FlashThing CLI: Command line interface for FlashThing.
- FlashThing Node: N-API bindings for FlashThing.
- FlashThing Wasm: WebUSB bindings for FlashThing, for flashing from a browser.
FlashThing currently supports flashing the Stock partition tables as well as custom partition tables using a subset of the Terbium meta.json standard. Read more about that standard in the docs.
FlashThing can flash over two protocols: amlogic's vendor burn mode or fastboot against mainline u-boot.
cargo add flashthingcargo install flashthing-clinpm install flashthing
yarn add flashthing
pnpm add flashthing
bun add flashthingFlashThing requires libusb to be installed, and a udev rule must be set up to access the Car Thing. To install the udev rule, run the following command:
sudo flashthing-cli --udevFlashThing requires libusb to be installed. You can install it using Homebrew:
brew install libusbFlashThing may require special drivers (I don't have a Windows machine to test on). If you have issues, try running the Terbium driver script.
irm https://driver.terbium.app/get | iexSee docs.rs and the cli for more information.
Note: The documentation is very basic, sorry!
❯ flashthing-cli --help
cli for flashing the Spotify Car Thing
Usage: flashthing-cli [OPTIONS] [PATH]
Arguments:
[PATH] Path to a zip file or a directory. Defaults to the current working directory if omitted
Options:
-s, --stock Whether the directory or archive contains a stock dump with no `meta.json` file
--unbrick Whether to unbrick the device
--setup setup host - this currently only sets up udev rules on Linux
--bulkcmd <CMD> Send a single u-boot command to a device in USB burn mode and print its response
-f, --fastboot Flash over fastboot against mainline u-boot instead of amlogic burn mode
--console <CMD> Run a single u-boot command over fastboot's `oem console` and print its output
--sparse Treat every raw write as sparse, skipping all-zero chunks
-h, --help Print help
-V, --version Print versionimport { FlashThing, type FlashEvent } from 'flashthing';
const callback = (event: FlashEvent) => {
console.log('Flash event:', event);
};
await flasher.openArchive('path/to/archive.zip');
console.log(`Total flashing steps: ${flasher.getNumSteps()}`);
await flasher.flash();cd wasm && wasm-pack build --target webThe browser owns device permission and archive handling, so the page supplies them as callbacks. awaitGesture
resolves once the user has clicked and it is called again
after a BL2 boot resets the SoC. readAll and open resolve payload paths out of the flash archive, with open
returning { size, read(n) } for streaming.
import init, { FlashThing } from './pkg/flashthing_wasm.js';
await init();
const flasher = new FlashThing(event => console.log(event), {
readAll,
open,
awaitGesture,
fastboot: true,
});
await flasher.openJson(metaJson);
console.log(`Total flashing steps: ${flasher.getNumSteps()}`);
await flasher.flash();.
├── bindings # N-API bindings
├── cli # command line interface
├── lib # main library - has all the logic
└── wasm # WebUSB bindings