Documentation
¶
Overview ¶
Package fileformat gives the PromptZero agent structural access to the Flipper file formats it already ships with — .sub, .nfc, .ir, .rfid. Raw `storage read` gives the LLM one giant string; these parsers surface the individual fields + blocks so the model can reason about them (change a frequency, blank a block, rename a signal) without string manipulation.
Every format follows the same shape:
- Parse<T>(data []byte) (*T, error) — tolerant line-oriented parser.
- (*T).Marshal() []byte — canonical serializer; round-trip equal under Parse(Marshal(Parse(x))) but not guaranteed byte-for-byte identical to the input.
- apply<T>Edits(*T, map[string]interface{}) error — validates and applies a top-level edit map; unknown keys fail loudly so the LLM cannot silently no-op.
Index ¶
- func ApplyEdits(format Format, model any, edits map[string]interface{}) error
- func BuildIR(p IRBuildParams) ([]byte, error)
- func BuildMousejackPayload(p MousejackPayloadParams) ([]byte, error)
- func BuildNFC(p NFCBuildParams) ([]byte, error)
- func BuildRFID(p RFIDBuildParams) ([]byte, error)
- func BuildSub(p SubBuildParams) ([]byte, error)
- func BuildSubBruteforce(p SubBruteforceParams) ([]byte, error)
- func BuildSubBruteforceSweep(p SubFreqSweepParams) (map[uint32][]byte, error)
- func SaveFile(format Format, model any) ([]byte, error)
- type DiffEntry
- type DiffResult
- type Format
- type IRBuildParams
- type IRFile
- type IRSignal
- type MousejackPayloadParams
- type NFCBuildParams
- type NFCFile
- type NRF24Target
- type RFIDBuildParams
- type RFIDFile
- type SubBruteforceParams
- type SubBuildParams
- type SubFile
- type SubFreqSweepParams
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func ApplyEdits ¶
ApplyEdits dispatches the edit map to the format-specific applier. Unknown edit keys return an error — never silently ignored.
func BuildIR ¶ added in v0.3.0
func BuildIR(p IRBuildParams) ([]byte, error)
BuildIR constructs a canonical .ir remote file. The IRSignal struct is shared with the parser, so callers can assemble a file programmatically and trust the round-trip.
func BuildMousejackPayload ¶ added in v0.3.1
func BuildMousejackPayload(p MousejackPayloadParams) ([]byte, error)
BuildMousejackPayload validates the DuckyScript and returns the canonical bytes ready to write to /ext/mousejacker/<name>.txt. Validation rules:
- non-empty after comment stripping
- every DELAY argument ≤ MaxDelayMS
- a sane target-OS string (for future per-OS transformations)
BuildMousejackPayload does not enforce DuckyScript syntax beyond the delay cap — the validator.Validate() pass (called separately on the bytes) handles destructive-pattern detection mirrored from BadUSB.
func BuildNFC ¶ added in v0.3.0
func BuildNFC(p NFCBuildParams) ([]byte, error)
BuildNFC constructs a canonical .nfc capture. The resulting file is suitable for nfc_emulate.
UID byte-length is validated against DeviceType so a 4-byte UID paired with "NTAG215" doesn't silently produce a file that would fail every reader probe. Allowed lengths per type follow the published ISO/IEC 14443 tag-family specs:
Mifare Classic 1K/4K/Mini 4 or 7 bytes Mifare Ultralight / NTAG21x 7 bytes NTAG215 / NTAG216 / NTAG213 7 bytes Other / unknown any non-empty hex passes (permissive)
func BuildRFID ¶ added in v0.3.0
func BuildRFID(p RFIDBuildParams) ([]byte, error)
BuildRFID constructs a canonical .rfid file. The resulting file is suitable for writing with the rfid_write tool to clone onto a T5577 blank.
func BuildSub ¶ added in v0.3.0
func BuildSub(p SubBuildParams) ([]byte, error)
BuildSub constructs a canonical .sub capture from parameters. Required: Frequency. Returns the file bytes; callers typically hand the result to Flipper.WriteFileCtx.
func BuildSubBruteforce ¶ added in v0.3.0
func BuildSubBruteforce(p SubBruteforceParams) ([]byte, error)
BuildSubBruteforce constructs a RAW .sub file that sweeps the integer key space [StartKey, EndKey] at BitCount bits. Each key is encoded MSB-first using Princeton-style OOK timing: a '1' bit as +3*TE / -1*TE, a '0' bit as +1*TE / -3*TE. A +1*TE / -31*TE sync gap separates adjacent keys — matches the pattern a PT2240 / SC5262 family decoder expects.
The tool is agnostic about which protocol actually authorises the target; it just produces a replayable sweep the operator can feed to subghz_transmit. Per-protocol encoding variants (Keeloq rolling codes, CAME 12-bit, Chamberlain) are not modelled — those need protocol-specific state machines and belong in a later enhancement.
func BuildSubBruteforceSweep ¶ added in v0.3.1
func BuildSubBruteforceSweep(p SubFreqSweepParams) (map[uint32][]byte, error)
BuildSubBruteforceSweep generates one .sub file per frequency in p.Frequencies, each covering the same key range. This is the "multi-band bruteforce" workflow the RF specialist audit flagged as missing — garage-door reconnaissance often cycles the same Princeton-family key space across 315 MHz, 433.92 MHz, 868 MHz, and 915 MHz before narrowing to one band.
Returns a map of frequency → raw bytes so the caller can choose its own filename scheme (typically sweep_<freq>.sub). All validation runs per-frequency; a single invalid entry fails the whole call rather than writing some files and leaving others unbuilt.
Types ¶
type DiffEntry ¶
type DiffEntry struct {
Field string `json:"field"`
AField string `json:"a"`
BField string `json:"b"`
Same bool `json:"same"`
}
DiffEntry is one field-level difference between two parsed files. AField / BField hold the rendered values; Same is true iff they match.
type DiffResult ¶
type DiffResult struct {
FormatA Format `json:"format_a"`
FormatB Format `json:"format_b"`
SameFormat bool `json:"same_format"`
Entries []DiffEntry `json:"entries"`
}
DiffResult is the structural comparison of two parsed models. Format mismatches surface as SameFormat=false and an empty Entries slice.
type Format ¶
type Format string
Format identifies one of the four supported file formats. Returned by DetectFormat and LoadFile so callers don't have to re-sniff extensions.
func DetectFormat ¶
DetectFormat inspects path's extension and returns the matching Format. Case-insensitive.
type IRBuildParams ¶ added in v0.3.0
type IRBuildParams struct {
// Name is a display label for the remote. Optional — defaults to
// "generated".
Name string
// Signals is the ordered list of IR entries. Each must have a
// Name plus either parsed fields or raw fields populated.
Signals []IRSignal
}
IRBuildParams carries inputs for BuildIR. A valid IR file needs at least one signal; parsed-type signals require Protocol + Address + Command; raw-type signals require Frequency + DutyCycle + Data.
type IRFile ¶
IRFile is a parsed .ir universal-remote / capture file — zero or more signals separated by "#" marker lines.
type IRSignal ¶
type IRSignal struct {
Name string
Type string
Protocol string
Address string
Command string
Frequency int
DutyCycle float64
Data []int
}
IRSignal is one button entry in a Flipper .ir remote file. Parsed-type entries carry Protocol/Address/Command; raw-type entries carry Frequency, DutyCycle, and a Data timing list (microseconds).
type MousejackPayloadParams ¶ added in v0.3.1
type MousejackPayloadParams struct {
// Script is the DuckyScript body. Lines are trimmed and
// empty/comment lines dropped. Whitespace-only input errors out.
Script string
// TargetOS hints the builder at expected key-combo conventions.
// Valid: "windows", "macos", "linux". Empty defaults to windows.
TargetOS string
// MaxDelayMS caps the argument to any DELAY line. Mousejack
// sessions are 2.4 GHz and flaky — very long delays often lose
// sync with the receiver. Defaults to 5000 (5s); passing 0
// applies the default.
MaxDelayMS int
}
MousejackPayloadParams carries inputs for BuildMousejackPayload. The script is a DuckyScript body — lines of STRING / DELAY / GUI combos etc. that the Mouse Jacker FAP replays at the remote keyboard.
type NFCBuildParams ¶ added in v0.3.0
type NFCBuildParams struct {
// DeviceType is one of "Mifare Classic", "Mifare Ultralight",
// "NTAG213", "NTAG215", "NTAG216", etc. Accepted verbatim.
DeviceType string
// UID hex, e.g. "AA BB CC DD". Spaces between bytes are tolerated.
UID string
// ATQA / SAK are the ISO/IEC 14443 response bytes. Optional —
// omitted for NTAG variants that don't expose them.
ATQA string
SAK string
// MifareType (e.g. "1K" / "4K") for Classic captures.
MifareType string
// Blocks maps block index → space-separated hex bytes. Optional
// — a bare UID capture with no Blocks still produces a valid
// file useful for UID-only emulation.
Blocks map[int]string
}
NFCBuildParams carries inputs for BuildNFC. DeviceType + UID are the minimum; for Mifare Classic the caller typically supplies ATQA, SAK, and a map of block contents.
type NFCFile ¶
type NFCFile struct {
Filetype string
Version int
DeviceType string
UID string
ATQA string
SAK string
MifareType string
Blocks map[int]string
Headers map[string]string
}
NFCFile is a parsed Flipper NFC capture. Block contents stay as the raw space-separated hex strings so a round-trip preserves exactly what came off the wire; block numbers are their integer position for easy edits.
type NRF24Target ¶ added in v0.3.1
type NRF24Target struct {
// Address is the 5-byte NRF24 pipe address, uppercase
// colon-separated (e.g. "A1:B2:C3:D4:E5"). The Mouse Jacker FAP
// matches bytes verbatim — whitespace or lowercase confuses it.
Address string
// Rate is the NRF24 data rate the sniffer observed the address at.
// 1 = 1 Mbps (most Microsoft peripherals), 2 = 2 Mbps (Logitech
// Unifying / MX family). A '250' value means 250 kbps, rare on
// modern peripherals.
Rate int
}
NRF24Target is one captured wireless-peripheral address.
func ParseNRF24Addresses ¶ added in v0.3.1
func ParseNRF24Addresses(src string) ([]NRF24Target, []string, error)
ParseNRF24Addresses parses the addresses.txt shape the NRF24 Sniffer FAP writes. Malformed lines are skipped with a non-fatal error aggregated in the returned slice — callers log the count and continue. Returns an error only when the whole file is empty / unparseable.
type RFIDBuildParams ¶ added in v0.3.0
type RFIDBuildParams struct {
// KeyType is the LF protocol name: EM4100, HIDProx, Indala,
// AWID, FDX-A, FDX-B, etc. Accepted verbatim — the caller is
// responsible for matching the protocol to the data.
KeyType string
// Data is the hex payload, e.g. "1A 2B 3C 4D 5E". Spaces
// between octets are tolerated; non-hex input is rejected.
Data string
}
RFIDBuildParams carries inputs for BuildRFID. Both KeyType and Data are required.
type RFIDFile ¶
type RFIDFile struct {
Filetype string
Version int
KeyType string
Data string
Headers map[string]string
}
RFIDFile is a parsed Flipper .rfid (125 kHz LF) capture.
type SubBruteforceParams ¶ added in v0.3.0
type SubBruteforceParams struct {
Frequency uint32 // Hz
BitCount int // typically 24 for Princeton-family protocols
StartKey uint64 // inclusive
EndKey uint64 // inclusive
TE int // microseconds (defaults to 400 — common Princeton TE)
Preset string // optional; defaulted per-band via defaultSubPreset
}
SubBruteforceParams carries the inputs for BuildSubBruteforce. Produces a RAW .sub file encoding Princeton-style OOK pulses for each key in [StartKey, EndKey]. Frequency + bit count + TE are required; the sweep is capped by maxBruteforceKeys to prevent the caller from generating a megabyte-sized file and thrashing the Flipper SD card.
type SubBuildParams ¶ added in v0.3.0
type SubBuildParams struct {
// Frequency in Hz (e.g. 433920000 for 433.92 MHz). Rejected if
// zero or outside the 1 MHz–1 GHz range the Flipper CC1101 can
// reach.
Frequency uint32
// Protocol name, e.g. "Princeton", "Keeloq", "RAW". Optional —
// omitted files default to the RAW / unrecognised path.
Protocol string
// Preset name understood by the Flipper firmware. Leave empty to
// have BuildSub pick a default from the frequency band.
Preset string
// Key is a space-separated hex byte string, e.g.
// "1A 2B 3C 4D 00 00 00 00". Produces the Key: line.
Key string
// Bit is the protocol's bit-length (e.g. 24 for Princeton,
// 32 for Came).
Bit int
// TE is the protocol's timing element in microseconds. Defaults
// to 400 (a common Princeton TE) when zero and Protocol is set.
TE int
// RawData produces a RAW file instead of a keyed one. When set,
// Protocol is overridden to "RAW".
RawData []int32
}
SubBuildParams carries the inputs for BuildSub. Frequency is the only required field; everything else is optional and falls back to sensible defaults (Preset = Ook650Async which matches the majority of ISM-band captures).
type SubFile ¶
type SubFile struct {
Filetype string
Version int
Frequency uint32
Preset string
Protocol string
Bit int
Key string
TE int
RawData []int32
Headers map[string]string
}
SubFile is a parsed Flipper Sub-GHz capture file. Both the structured key-file layout and the RAW capture layout share this struct; RawData is populated only when the file is a RAW capture (Filetype contains "RAW").
Headers preserves any key:value lines the parser did not promote into a strongly-typed field — keeps round-tripping lossless for firmware-fork extensions (e.g. Momentum's "Bit Raw Protocol" additions) we don't model.
func ParseSub ¶
ParseSub parses a Flipper .sub capture. Accepts CRLF, LF, trailing or missing final newline, and ignores # comments + blank lines. Unknown key:value lines are preserved in Headers so marshal round-trips.
type SubFreqSweepParams ¶ added in v0.3.1
type SubFreqSweepParams struct {
Frequencies []uint32 // Hz, one file produced per entry
BitCount int
StartKey uint64
EndKey uint64
TE int
Preset string
}
SubFreqSweepParams carries the inputs for BuildSubBruteforceSweep. Produces one RAW .sub byte stream per frequency in the list, each sweeping the same [StartKey, EndKey] range at BitCount bits. The caller pairs the returned byte streams with per-frequency filenames and writes them separately.