Documentation
¶
Overview ¶
Package ble decodes BLE advertisement payloads — currently just Apple Continuity manufacturer-data — into operator-facing structures. Pure offline parser; no transport, no hardware.
Wrap-vs-native judgement: the Apple Continuity format is a reverse-engineered public spec — furiousMAC's project, hexway's AppleJuice writeups, AppleBleee and AppleAir-style scanners all document the same TLV layout. The dissector is a short walker (~150 LoC of bytes-to-field) over a byte slice. Wrapping a FAP for this would require an SD-card install + a firmware-fork dependency for a pure parser. Native delivers host-side analysis (paste a captured Apple manufacturer-data hex from a forum post or a Wireshark capture and decode without a Flipper attached), inline test coverage against published vectors, and a table the operator can extend without rebuilding firmware.
What this package covers:
- Apple Continuity TLV walker (with separator-tolerant hex intake; auto-strip of optional 4C00 manufacturer prefix and full AD-structure prefix).
- Named action types per furiousMAC's catalog (0x02 iBeacon through 0x12 Find My).
- Per-type field decoding for the well-documented action types — Nearby Info, Nearby Action, Handoff, Tethering, Proximity Pairing, AirDrop, Magic Switch.
What this package does NOT cover (deliberately out of scope):
- Decryption of encrypted bodies (Handoff, ProximityPairing past the public prefix) — Apple's session keys are not publicly recoverable.
- Tag-name lookup for the 0xDF range or any vendor-private types beyond Apple's set.
- Round-trip re-encode — happy to add if a caller materialises.
Index ¶
Constants ¶
const AppleManufacturerID = 0x004C
AppleManufacturerID is Apple's Bluetooth SIG company identifier. See https://www.bluetooth.com/specifications/assigned-numbers/.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type ActionTLV ¶
type ActionTLV struct {
// Type is the Action Type byte — 0x05 (AirDrop), 0x10 (Nearby
// Info), etc. Stored as an int rather than byte so JSON renders
// as a plain integer.
Type int `json:"type"`
// TypeHex is the operator-facing form of Type — uppercase,
// always 2 chars, no 0x prefix ("05", "10"). Matches every
// public reference's format.
TypeHex string `json:"type_hex"`
// Name is the canonical name for the action type, or
// "Unknown" when the type isn't in our catalog. The walker
// still records and returns unknown types so operators can
// flag novel signatures.
Name string `json:"name"`
// Length is the declared payload length in bytes (the L byte
// of the TLV).
Length int `json:"length"`
// Hex is the operator-facing hex rendering of Value — always
// uppercase, no separators.
Hex string `json:"hex"`
// Value is the raw payload bytes.
Value []byte `json:"-"`
// Fields carries documented-action-type field decodes, keyed
// by short snake_case names. Nil for unknown types or for
// types whose body we don't dissect further.
Fields map[string]any `json:"fields,omitempty"`
// DecodeWarning is non-empty when the per-type decoder hit a
// recoverable shape issue (e.g. payload shorter than the
// documented minimum for that action). The TLV is still
// returned so the operator can see the raw bytes; the warning
// flags that Fields may be partial or missing.
DecodeWarning string `json:"decode_warning,omitempty"`
}
ActionTLV is one decoded Continuity TLV entry. For documented action types Fields carries the parsed sub-fields by name; for unknown types Fields is nil and the operator has Hex.
type Continuity ¶
type Continuity struct {
// TLVs is the ordered list of action-type entries pulled from
// the payload. May be empty when the payload is empty after
// prefix-stripping (legal but unusual — an empty 0x004C
// manufacturer record).
TLVs []ActionTLV `json:"tlvs"`
// Count is len(TLVs) — surfaced for callers that consume the
// JSON directly without needing to compute it.
Count int `json:"count"`
// StrippedPrefix records what the parser stripped from the
// front of the input before walking ("none", "manufacturer",
// "ad_structure"). Useful to confirm the parser interpreted
// the input as the operator expected.
StrippedPrefix string `json:"stripped_prefix"`
}
Continuity is the top-level decode result.
func Decode ¶
func Decode(hexBlob string) (Continuity, error)
Decode parses a hex-encoded Apple Continuity payload. Three input shapes are accepted; the parser strips any prefix it recognises:
- Bare TLVs: 10 02 1B 00
- With manufacturer ID: 4C 00 10 02 1B 00
- Full AD structure: 06 FF 4C 00 10 02 1B 00
Separators (':' '-' '_' whitespace) are tolerated so callers can paste hex from Wireshark, btmon, etc., without preprocessing.
func DecodeBytes ¶
func DecodeBytes(b []byte) (Continuity, error)
DecodeBytes is the byte-slice variant of Decode for callers that already have raw bytes. Same prefix-detection and walking logic.