Rewrite README around the full-stack BLE firmware, detail every app
Recentre the README on Flipper Blue++ as a custom full-stack Bluetooth firmware plus its app suite, rather than a single BT Inspector app that grew extra sections. New structure: intro, build/install (with the env-var table), a detailed per-app section for all ten apps (what each does, controls, logs), then the firmware internals (full stack, exported API + flash table, extra exports, sub-GHz unlock), how the BLE apps work, limitations, troubleshooting and repo layout.
This commit is contained in:
@@ -1,92 +1,40 @@
|
|||||||
# Flipper Zero BLE tools
|
# Flipper Blue++
|
||||||
|
|
||||||
A suite of BLE, sub-GHz and power tools for the Flipper Zero. The BLE apps
|
A custom Flipper Zero firmware build that turns the Bluetooth radio from an
|
||||||
share one central/GATT layer (`libble/`).
|
advertise-only peripheral into a full Bluetooth Low Energy platform, plus a
|
||||||
|
suite of apps that use it.
|
||||||
|
|
||||||
**Bluetooth (need the `build.sh` firmware)**
|
Stock Flipper firmware runs ST's "BLE Light" coprocessor stack, which can only
|
||||||
|
advertise. Flipper Blue++ swaps in ST's **full** BLE stack (observer + central +
|
||||||
|
GATT client), **exports the ST BLE command API to apps** so ordinary `.fap`
|
||||||
|
files can scan, connect and run GATT, and throws in a few related unlocks
|
||||||
|
(selected firmware internals, and the sub-GHz region gate). On top of that
|
||||||
|
firmware it ships ten apps: a BLE scanner/explorer, a HID host, a sensor
|
||||||
|
dashboard, a tracker detector, a GATT fuzzer, a beacon broadcaster, a GATT
|
||||||
|
server, two sub-GHz tools and a battery monitor.
|
||||||
|
|
||||||
* **BT Inspector** — BLE scanner and GATT explorer, in the spirit of
|
Repo: `github.com/andydixon/flipper-bluepp` (the slug drops the `++` because
|
||||||
BTInspector for iOS: discover devices, decode everything they broadcast, then
|
GitHub repo names cannot contain `+`).
|
||||||
connect and inspect/read/write/subscribe, and log it all.
|
|
||||||
* **BLE HID Host** — connect a Bluetooth keyboard or mouse and watch its input
|
|
||||||
reports decoded live.
|
|
||||||
* **BLE Sensor Dashboard** — connect a sensor and watch its known-service
|
|
||||||
readings (battery, heart rate, temperature, humidity, pressure, ...) decoded
|
|
||||||
and updating live.
|
|
||||||
* **BLE Tracker Detector** — passively flag nearby item trackers (Apple Find
|
|
||||||
My / AirTag, Tile, Samsung SmartTag) with a "following you" warning.
|
|
||||||
* **BLE GATT Fuzzer** — enumerate a peripheral's whole GATT database, read every
|
|
||||||
readable value, and fuzz writable characteristics with boundary payloads,
|
|
||||||
logging every response. For authorised testing of devices you own.
|
|
||||||
* **BLE Beacon Toolkit** — broadcast an iBeacon or a raw advertising payload
|
|
||||||
with a chosen random MAC.
|
|
||||||
* **BLE GATT Server** — advertise the Flipper as a connectable serial GATT
|
|
||||||
peripheral and echo whatever a central writes.
|
|
||||||
|
|
||||||
**Sub-GHz (need the region unlock, on by default)**
|
> **Read this first.** These apps do **not** run on stock Flipper firmware. They
|
||||||
|
> need the firmware `build.sh` produces (full BLE stack + exported command API,
|
||||||
|
> and for the sub-GHz tools the region unlock). Battery Health is the only app
|
||||||
|
> that would also run on stock firmware. Flashing this firmware also installs a
|
||||||
|
> different radio stack; going back to official firmware restores the stock one.
|
||||||
|
|
||||||
* **Sub-GHz Scanner** — sweep RSSI across the full CC1101 range and log active
|
---
|
||||||
frequencies.
|
|
||||||
* **Sub-GHz Spectrum** — live spectrum bar graph and waterfall over a tunable
|
|
||||||
centre/span window.
|
|
||||||
|
|
||||||
**Tools**
|
## Contents
|
||||||
|
|
||||||
* **Battery Health** — live fuel-gauge readings (voltage, current, temperature,
|
- [Building and installing](#building-and-installing)
|
||||||
capacity, health, wear) with a voltage graph. Read-only.
|
- [The apps](#the-apps) — detailed per-app docs
|
||||||
|
- [The firmware](#the-firmware) — full stack, exported APIs, sub-GHz unlock
|
||||||
|
- [How the BLE apps work](#how-the-ble-apps-work)
|
||||||
|
- [Limitations](#limitations)
|
||||||
|
- [Troubleshooting](#troubleshooting)
|
||||||
|
- [Repository layout](#repository-layout)
|
||||||
|
|
||||||
> **Read this first.** These apps do not run on stock Flipper firmware. The
|
---
|
||||||
> Flipper's radio coprocessor ships with ST's "BLE Light" stack (advertise-only:
|
|
||||||
> it cannot scan or connect), and the sub-GHz region check blocks transmit
|
|
||||||
> off-region. They are delivered as a **custom firmware build** that swaps in
|
|
||||||
> ST's full BLE stack, exports the BLE command API to apps, and unlocks the
|
|
||||||
> sub-GHz region; the apps themselves are ordinary `.fap` files. `build.sh` does
|
|
||||||
> all of this. See [Why a custom firmware build](#why-a-custom-firmware-build).
|
|
||||||
> Battery Health is the only one that would also run on stock firmware.
|
|
||||||
|
|
||||||
## Features
|
|
||||||
|
|
||||||
* **Live scan list.** Every BLE advertiser in range, sorted by RSSI, refreshed
|
|
||||||
every 300 ms as you move around. Shows name (or "(no name)"), RSSI in dBm
|
|
||||||
with signal bars, address and vendor. Devices unseen for 60 s drop off.
|
|
||||||
* **Device page.** Address and address type, current/best RSSI and packet
|
|
||||||
count, advertising type (connectable or not), flags, advertised service UUIDs
|
|
||||||
(16/32/128-bit, named when known), service data, Tx power, appearance,
|
|
||||||
manufacturer data and raw advertisement / scan-response bytes. Updates live.
|
|
||||||
* **Identification.** Manufacturer IDs map to vendor names. Decoders for:
|
|
||||||
* Apple Continuity: iBeacon (UUID/major/minor/Tx), Proximity Pairing with
|
|
||||||
AirPods/Beats **model name** and **left / right / case battery** and
|
|
||||||
charging state, Nearby Info (device activity), Nearby Action, Find My,
|
|
||||||
AirDrop, Handoff, AirPlay, tethering.
|
|
||||||
* Microsoft Connected Devices beacon: device type (Windows desktop/laptop,
|
|
||||||
Xbox, Surface Hub, Android, iPhone, ...).
|
|
||||||
* Google Fast Pair model ID, Eddystone UID/URL/TLM (URL decoded), COVID
|
|
||||||
Exposure Notification.
|
|
||||||
* **Connect and interrogate.** OK on a connectable device connects (MTU is
|
|
||||||
negotiated), discovers all primary services, then characteristics with their
|
|
||||||
properties (`R`ead, `W`rite, `w`rite-without-response, `N`otify, `I`ndicate,
|
|
||||||
`B`roadcast).
|
|
||||||
* **Read device info** (first item in the service list): reads every readable
|
|
||||||
characteristic of the Generic Access, Device Information and Battery services
|
|
||||||
in one go: device name, appearance, model number, serial number, firmware /
|
|
||||||
hardware / software revision, manufacturer name, PnP ID, battery level.
|
|
||||||
* **Characteristic page.** Read any characteristic, including custom 128-bit
|
|
||||||
ones. Values are shown as hex plus decoded forms: printable string, u8/i8,
|
|
||||||
u16, u32, and SIG-specific formats (battery %, appearance, preferred
|
|
||||||
connection parameters, PnP ID, heart rate, temperature, humidity, pressure,
|
|
||||||
Tx power, date/time). Long values are fetched with read-long.
|
|
||||||
* **Write** a value back as text, hex bytes or a number (little-endian, sized to
|
|
||||||
the current value or the magnitude). Uses write-with-response when the
|
|
||||||
characteristic supports it, otherwise write-without-response. A readable
|
|
||||||
characteristic is re-read after a write.
|
|
||||||
* **Subscribe** to notifications / indications (the CCCD is located
|
|
||||||
automatically). Incoming values update the page and the history.
|
|
||||||
* **Value history.** Each value seen for the open characteristic (reads and
|
|
||||||
notifications) is kept with a timestamp, newest first.
|
|
||||||
* **Session log.** Every event is written with a date/time stamp to
|
|
||||||
`SD:/apps_data/bt_inspector/bti_YYYYMMDD_HHMMSS.log`: devices found (and
|
|
||||||
renamed), connects, services, characteristics, reads, writes, notifications,
|
|
||||||
errors. Copy it off the SD card (or via qFlipper) for analysis.
|
|
||||||
|
|
||||||
## Building and installing
|
## Building and installing
|
||||||
|
|
||||||
@@ -94,29 +42,32 @@ Requirements: Linux or macOS with `git`, `python3` and a few GB of disk. The
|
|||||||
firmware build system downloads its own ARM toolchain.
|
firmware build system downloads its own ARM toolchain.
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
./build.sh # clone firmware 1.4.3, export the BLE API, build firmware + .fap
|
./build.sh # clone firmware 1.4.3, apply the patches, build firmware + apps
|
||||||
./build.sh flash # same, then flash over USB (Flipper connected, qFlipper closed)
|
./build.sh flash # same, then flash over USB (Flipper connected, qFlipper closed)
|
||||||
./build.sh fap # rebuild only the .fap after editing the app
|
./build.sh fap # rebuild only the apps (firmware already built once)
|
||||||
```
|
```
|
||||||
|
|
||||||
Options via environment variables: `FW_TAG` (firmware tag, default `1.4.3`),
|
Environment variables:
|
||||||
`FW_DIR` (where to clone), `JOBS` (parallel compile jobs, default 4),
|
|
||||||
`BLE_API` (which ST API to export, see below).
|
| Var | Default | Effect |
|
||||||
|
|---|---|---|
|
||||||
|
| `BLE_API` | `hci,gatt` | Which ST command groups to export (`min`, `all`, or any comma list of `hci,gap,gatt,hal,l2cap`). |
|
||||||
|
| `EXPORT_FLASH` | `1` | Export the raw flash / option-byte API (set `0` to omit). |
|
||||||
|
| `SUBGHZ_UNLOCK` | `1` | Remove the sub-GHz region gate (set `0` to keep it). |
|
||||||
|
| `FW_TAG` | `1.4.3` | Firmware tag to clone. |
|
||||||
|
| `FW_DIR` | `./flipperzero-firmware` | Where to clone. |
|
||||||
|
| `JOBS` | `4` | Parallel compile jobs. |
|
||||||
|
|
||||||
The result is a standard update package in
|
The result is a standard update package in
|
||||||
`flipperzero-firmware/dist/f7-C/f7-update-local/`. It contains the firmware,
|
`flipperzero-firmware/dist/f7-C/f7-update-local/`, containing the firmware, the
|
||||||
the **full radio stack**, and the app as `apps/Bluetooth/bt_inspector.fap` in
|
**full radio stack**, and every app under `apps/` in its resources. To install
|
||||||
its resources. To install without USB flashing, copy that folder to the SD card
|
without USB flashing, copy that folder to the SD card (e.g. `SD:/update/`) and
|
||||||
(for example `SD:/update/`) and open it in the Flipper's file browser.
|
open it in the Flipper's file browser. The individual `.fap` files are in
|
||||||
Installing an official firmware later restores the light stack the same way.
|
`flipperzero-firmware/build/f7-firmware-C/.extapps/`; once the firmware is
|
||||||
|
installed, app updates are just a file copy to the SD card.
|
||||||
|
|
||||||
The `.fap` alone is at `flipperzero-firmware/build/f7-firmware-C/.extapps/`;
|
To iterate on an app with `ufbt` instead of the whole firmware tree, point it at
|
||||||
after the firmware is installed once, app updates are just a file copy to
|
the SDK the build emits:
|
||||||
`SD:/apps/Bluetooth/`. It only loads on this firmware (API version 87.2 with
|
|
||||||
the exported symbols); the stock loader rejects it with an API mismatch.
|
|
||||||
|
|
||||||
To build the app with `ufbt` instead of the firmware tree, point `ufbt` at the
|
|
||||||
SDK the build produces:
|
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
ufbt update --local=flipperzero-firmware/dist/f7-C/flipper-z-f7-sdk-local.zip
|
ufbt update --local=flipperzero-firmware/dist/f7-C/flipper-z-f7-sdk-local.zip
|
||||||
@@ -125,307 +76,379 @@ cd bt_inspector && ufbt # -> dist/bt_inspector.fap ; `ufbt launch` instal
|
|||||||
|
|
||||||
The first build takes 5-15 minutes; later builds are incremental.
|
The first build takes 5-15 minutes; later builds are incremental.
|
||||||
|
|
||||||
## Using the app
|
While any BLE app runs, the Flipper's own advertising is stopped (and any phone
|
||||||
|
link dropped), then restored on exit. Only one app owns the radio at a time.
|
||||||
|
|
||||||
BT Inspector appears in the Flipper's main menu. While it runs, the Flipper's
|
---
|
||||||
own BLE advertising is stopped (and any phone connection dropped); it is
|
|
||||||
restored on exit.
|
## The apps
|
||||||
|
|
||||||
|
All ten install to the Flipper's app menu. The BLE apps share one
|
||||||
|
central/GATT-client layer (`libble/`) and follow the same pattern: a live scan
|
||||||
|
list you pick a device from, then a per-app action. On the scan list, **Up/Down**
|
||||||
|
move the selection, **OK** acts on the highlighted device, **Back** exits.
|
||||||
|
|
||||||
|
### BT Inspector
|
||||||
|
|
||||||
|
A full BLE scanner and GATT explorer, in the spirit of BTInspector for iOS.
|
||||||
|
|
||||||
|
- **Scan list** — every advertiser in range, sorted by RSSI and refreshed every
|
||||||
|
300 ms, showing name (or "(no name)"), RSSI in dBm with signal bars, address
|
||||||
|
and vendor. Devices unseen for 60 s drop off.
|
||||||
|
- **Device page** (OK on a device) — address and address type, current and best
|
||||||
|
RSSI, packet count, advertising type (and whether it is connectable), and a
|
||||||
|
decode of everything in the advertisement and scan response:
|
||||||
|
- flags; advertised service UUIDs (16/32/128-bit, named when known); service
|
||||||
|
data; Tx power; appearance;
|
||||||
|
- manufacturer data, with decoders for **Apple Continuity** (iBeacon
|
||||||
|
UUID/major/minor/Tx; Proximity Pairing with AirPods/Beats **model name** and
|
||||||
|
**left / right / case battery** and charging state; Nearby Info and Action;
|
||||||
|
Find My; AirDrop; Handoff; AirPlay; tethering), **Microsoft CDP** device
|
||||||
|
type, **Google Fast Pair**, **Eddystone** (UID/URL/TLM, URL expanded), and
|
||||||
|
**Exposure Notification**;
|
||||||
|
- the raw advertisement and scan-response bytes.
|
||||||
|
- **Connect** (OK on a connectable device) — negotiates MTU, discovers all
|
||||||
|
primary services, and lists them. The first entry, **Read device info**, reads
|
||||||
|
every readable characteristic of the Generic Access, Device Information and
|
||||||
|
Battery services at once (name, appearance, model/serial numbers, firmware /
|
||||||
|
hardware / software revisions, manufacturer, PnP ID, battery level).
|
||||||
|
- **Characteristics** — each service opens to its characteristics with property
|
||||||
|
flags: `R`ead, `W`rite, `w`rite-without-response, `N`otify, `I`ndicate,
|
||||||
|
`B`roadcast.
|
||||||
|
- **Characteristic page** — Read (OK), including custom 128-bit characteristics
|
||||||
|
and long values (read-long). Values show as hex plus decoded forms: printable
|
||||||
|
string, u8/i8, u16, u32, and SIG formats (battery %, appearance, preferred
|
||||||
|
connection parameters, PnP ID, heart rate, temperature, humidity, pressure, Tx
|
||||||
|
power, date/time). **Write** (Right) a value as text, hex bytes, or a number;
|
||||||
|
**Notify/Unsub** (Left) subscribes to notifications/indications, locating the
|
||||||
|
CCCD automatically. A timestamped **history** of every value seen for the open
|
||||||
|
characteristic is kept, newest first.
|
||||||
|
- **Log** — everything is written with timestamps to
|
||||||
|
`SD:/apps_data/bt_inspector/bti_<date>_<time>.log`: devices, connects,
|
||||||
|
services, characteristics, reads, writes, notifications, errors.
|
||||||
|
|
||||||
| Screen | Up/Down | OK | Left | Right | Back |
|
| Screen | Up/Down | OK | Left | Right | Back |
|
||||||
|---|---|---|---|---|---|
|
|---|---|---|---|---|---|
|
||||||
| Scan list | select device | device page | | | exit app |
|
| Scan list | select | device page | | | exit |
|
||||||
| Device page | scroll | Connect (if connectable) | | | scan list |
|
| Device page | scroll | Connect (if connectable) | | | scan list |
|
||||||
| Services | select | open service / read device info | | | disconnect, device page |
|
| Services | select | open / read device info | | | disconnect |
|
||||||
| Characteristics | select | open characteristic (auto-read) | | | services |
|
| Characteristics | select | open (auto-read) | | | services |
|
||||||
| Characteristic | scroll | Read | Notify/Unsub | Write | characteristics |
|
| Characteristic | scroll | Read | Notify/Unsub | Write | characteristics |
|
||||||
| Write menu | select | Text / Hex bytes / Number | | | characteristic |
|
|
||||||
|
|
||||||
Status messages ("Read OK (5 B)", "Write failed: Write not permitted",
|
### BLE HID Host
|
||||||
"Notifications on", ...) appear on the characteristic page.
|
|
||||||
|
|
||||||
On stock firmware the app opens with an explanation instead of scanning.
|
Connect a Bluetooth keyboard or mouse and watch its input decoded live.
|
||||||
|
|
||||||
## Log format
|
Pick a device; the app connects, finds the HID service (0x1812), sets the
|
||||||
|
protocol mode (Boot when the device offers boot reports, otherwise Report),
|
||||||
|
subscribes to the input-report characteristics, and keeps the device out of
|
||||||
|
suspend. Keyboard reports decode to modifier names plus key names (common USB
|
||||||
|
HID usage page; media/vendor keys show as raw `[XX]`); mouse reports decode to
|
||||||
|
button state and dx/dy/wheel. Events scroll on screen (Up/Down reviews history)
|
||||||
|
and are logged with the raw bytes to `SD:/apps_data/ble_hid_host/`. Back
|
||||||
|
disconnects and returns to scanning.
|
||||||
|
|
||||||
One event per line:
|
It cannot pair, so keyboards that require an encrypted link before sending
|
||||||
|
reports connect but stay silent; open keyboards and most mice work.
|
||||||
|
|
||||||
```
|
### BLE Sensor Dashboard
|
||||||
[2026-09-11 09:12:03] START stack=full advertising_was=1
|
|
||||||
[2026-09-11 09:12:04] DEVICE 5C:F3:70:9A:11:20 ADV_IND rssi=-58 name="Living Room" vendor=Apple adv=02 01 1A 0B FF 4C 00 ...
|
|
||||||
[2026-09-11 09:12:20] CONNECTING Living Room
|
|
||||||
[2026-09-11 09:12:21] CONNECTED Living Room mtu=247
|
|
||||||
[2026-09-11 09:12:21] SERVICE 180A Device Information handles 0x0010-0x001C
|
|
||||||
[2026-09-11 09:12:25] CHAR 2A26 handle 0x0016 props 0x02
|
|
||||||
[2026-09-11 09:12:26] READ 0x0016 = 31 2E 32 2E 30
|
|
||||||
[2026-09-11 09:12:40] WRITE 0x0021 = 01
|
|
||||||
[2026-09-11 09:12:41] NOTIFY 0x0024 = 64
|
|
||||||
[2026-09-11 09:13:00] DISCONNECT
|
|
||||||
```
|
|
||||||
|
|
||||||
A `DEVICE` line is written when a device is first seen and again when its name
|
Connect a sensor and watch its readings decoded and updating live.
|
||||||
changes. `INFO` lines come from "Read device info".
|
|
||||||
|
|
||||||
## Why a custom firmware build
|
On connect it discovers all services, then picks out the characteristics with a
|
||||||
|
known SIG meaning that are readable or notifying, reads each once, and subscribes
|
||||||
|
to the notifying ones. The readings screen shows each as `Name: value`, decoded
|
||||||
|
by the shared value decoders — battery %, heart rate, temperature, humidity,
|
||||||
|
pressure, Tx power, time, appearance, PnP ID and more — and updates as
|
||||||
|
notifications arrive. Up to 12 readings; Up/Down scrolls, Back disconnects.
|
||||||
|
Unknown or vendor-specific characteristics are ignored (use BT Inspector for
|
||||||
|
those).
|
||||||
|
|
||||||
Three facts about the Flipper Zero drive the design:
|
### BLE Tracker Detector
|
||||||
|
|
||||||
1. The STM32WB55's second core runs a prebuilt ST BLE stack. Flipper ships
|
Passively flag nearby item trackers and warn if one seems to be following you.
|
||||||
`stm32wb5x_BLE_Stack_light_fw.bin` (peripheral + broadcaster only). ST's
|
|
||||||
`stm32wb5x_BLE_Stack_full_fw.bin` adds observer and central roles. The
|
|
||||||
firmware build system already supports it (`COPRO_STACK_TYPE=ble_full`) and
|
|
||||||
the firmware recognises it at runtime (`FuriHalBtStackFull`).
|
|
||||||
2. External `.fap` apps can only call functions listed in the firmware's API
|
|
||||||
table. The ST `aci_*` / `hci_*` command functions are not in it, so a stock
|
|
||||||
`.fap` cannot start a scan or a connection. `build.sh` adds ST's command
|
|
||||||
headers to the SDK (`lib/stm32wb.scons`), adds `extern "C"` guards to them
|
|
||||||
(the API table is C++), lets `fbt` regenerate `api_symbols.csv`, and enables
|
|
||||||
the selected functions. The API minor version becomes 87.2.
|
|
||||||
3. Every exported function is kept in the firmware image, so `BLE_API` trades
|
|
||||||
generality for flash. The full stack loads at 0x080CE000 (light: 0x080D7000);
|
|
||||||
the space between the firmware and the stack is the Flipper's internal
|
|
||||||
storage:
|
|
||||||
|
|
||||||
| `BLE_API` | exported | firmware | pages left, full stack | pages left, extended stack |
|
It scans continuously and classifies advertisers by signature: Apple Find My /
|
||||||
|
AirTag (manufacturer-data type), Tile and Samsung SmartTag (service UUIDs). The
|
||||||
|
list shows each suspected tracker with its type, address and RSSI, sorted by
|
||||||
|
signal. A tracker seen repeatedly over roughly two minutes gets a `!` "following"
|
||||||
|
flag. Everything is logged to `SD:/apps_data/ble_tracker/` with first-seen and
|
||||||
|
follow events. It never connects to a tracker — detection only — and it does not
|
||||||
|
de-anonymise or disable anything.
|
||||||
|
|
||||||
|
### BLE GATT Fuzzer
|
||||||
|
|
||||||
|
Enumerate, read and (optionally) fuzz a peripheral's GATT database, logging
|
||||||
|
every response. **For authorised testing of devices you own.**
|
||||||
|
|
||||||
|
Pick a device; it connects and walks every service and characteristic, reading
|
||||||
|
each readable value and logging the service/characteristic UUIDs, handles,
|
||||||
|
properties, and read results (or ATT errors). Press **OK** on the report screen
|
||||||
|
to run a fuzz pass: for every writable characteristic it writes a small fixed set
|
||||||
|
of boundary payloads (empty, `0x00`, `0xFF`, twenty `0x41` bytes) and logs
|
||||||
|
whether each was accepted or rejected. The running report scrolls on screen
|
||||||
|
(Up/Down) and the full detail goes to `SD:/apps_data/ble_gattfuzz/`. Back
|
||||||
|
disconnects.
|
||||||
|
|
||||||
|
### BLE Beacon Toolkit
|
||||||
|
|
||||||
|
Broadcast a BLE advertisement with a chosen random MAC.
|
||||||
|
|
||||||
|
Two modes. **iBeacon** takes 21 entered bytes (16-byte UUID + 2 major + 2 minor +
|
||||||
|
1 Tx) and wraps them in the Apple manufacturer AD. **Raw** sends the entered
|
||||||
|
bytes verbatim as the advertising payload (up to 31). The menu lets you toggle
|
||||||
|
the mode, edit the MAC (six little-endian bytes) and the payload via the byte
|
||||||
|
editor, and Start/Stop the beacon; the header shows RUNNING or stopped. Uses the
|
||||||
|
firmware's extra-beacon API, so it advertises alongside the normal stack.
|
||||||
|
Changing a field stops the beacon; press Start again to re-broadcast.
|
||||||
|
|
||||||
|
### BLE GATT Server
|
||||||
|
|
||||||
|
Turn the Flipper into a connectable BLE peripheral you can talk to.
|
||||||
|
|
||||||
|
It brings up the firmware's serial GATT service (a 128-bit service with RX and TX
|
||||||
|
characteristics) via the BT service's profile API and echoes back whatever a
|
||||||
|
central writes, as a TX notification. Connect from a phone (e.g. nRF Connect) to
|
||||||
|
see the service, write to RX and receive the echo. The screen shows connection
|
||||||
|
state and running RX/TX byte counters and the last received text; **OK** toggles
|
||||||
|
echo on/off; **Back** restores the default (phone/RPC) profile and exits. It
|
||||||
|
exposes this fixed service rather than an arbitrary schema, because building
|
||||||
|
custom services from a `.fap` is not supported by the exported API.
|
||||||
|
|
||||||
|
### Sub-GHz Scanner
|
||||||
|
|
||||||
|
Sweep RSSI across the CC1101's range and log active frequencies. Needs the
|
||||||
|
sub-GHz region unlock (default on).
|
||||||
|
|
||||||
|
It tunes across a band in 250 kHz steps, drawing a live spectrum bar graph and
|
||||||
|
tracking the peak. Any frequency whose RSSI crosses the threshold is logged with
|
||||||
|
a timestamp to `SD:/apps_data/subghz_scan/`. **Left/Right** cycle between the
|
||||||
|
three hardware bands and an all-bands sweep; **OK** pauses; **Back** exits. RSSI
|
||||||
|
is read one frequency at a time, so a sweep is not instantaneous and can miss
|
||||||
|
very brief transmissions.
|
||||||
|
|
||||||
|
### Sub-GHz Spectrum
|
||||||
|
|
||||||
|
A live spectrum and waterfall over a tunable window. Needs the region unlock.
|
||||||
|
|
||||||
|
It sweeps a centre frequency ± span, drawing a spectrum bar graph on top and a
|
||||||
|
scrolling intensity waterfall below, so you can watch activity over time.
|
||||||
|
**Left/Right** retune the centre by a quarter-span; **Up/Down** widen or narrow
|
||||||
|
the span (250 kHz to 8 MHz); **Back** exits. Same one-frequency-at-a-time
|
||||||
|
sampling caveat as the scanner.
|
||||||
|
|
||||||
|
### Battery Health
|
||||||
|
|
||||||
|
Live fuel-gauge readings with a voltage graph. Read-only; the one app that also
|
||||||
|
runs on stock firmware.
|
||||||
|
|
||||||
|
It polls the gauge every two seconds and shows charge percentage and state,
|
||||||
|
voltage, current, temperature, remaining/full/design capacity, health, a derived
|
||||||
|
wear estimate, and USB (VBUS) voltage, with a rolling voltage graph across the
|
||||||
|
bottom. It never changes charge settings. Back exits.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## The firmware
|
||||||
|
|
||||||
|
The whole suite rests on three firmware changes `build.sh` applies to a clean
|
||||||
|
clone of official firmware 1.4.3.
|
||||||
|
|
||||||
|
### 1. The full BLE stack
|
||||||
|
|
||||||
|
The STM32WB55's second core runs a prebuilt ST BLE stack. Flipper ships
|
||||||
|
`stm32wb5x_BLE_Stack_light_fw.bin` (peripheral / broadcaster only). ST's
|
||||||
|
`stm32wb5x_BLE_Stack_full_fw.bin` adds the observer and central roles and the
|
||||||
|
GATT client. The firmware build system already supports it
|
||||||
|
(`COPRO_STACK_TYPE=ble_full`) and the firmware recognises it at runtime
|
||||||
|
(`FuriHalBtStackFull`); `build.sh` selects it and also widens the GAP roles the
|
||||||
|
firmware initialises to `PERIPHERAL | CENTRAL | OBSERVER`.
|
||||||
|
|
||||||
|
### 2. The BLE command API, exported to apps
|
||||||
|
|
||||||
|
External `.fap` apps can only call functions in the firmware's API table, and
|
||||||
|
the ST `aci_*` / `hci_*` command functions are not in it — so a stock `.fap`
|
||||||
|
cannot start a scan or a connection. `build.sh` adds ST's command headers to the
|
||||||
|
SDK, gives them `extern "C"` guards (the API table is compiled as C++), lets
|
||||||
|
`fbt` regenerate `api_symbols.csv`, and enables the selected functions. This
|
||||||
|
bumps the API minor version, which is why these apps load only on this firmware.
|
||||||
|
|
||||||
|
Every exported function stays in the firmware image, so `BLE_API` trades reach
|
||||||
|
for flash. The full stack loads at `0x080CE000` (light: `0x080D7000`); the gap
|
||||||
|
between the firmware and the stack is the Flipper's internal storage:
|
||||||
|
|
||||||
|
| `BLE_API` | exported | firmware | pages free, full stack | pages free, extended stack |
|
||||||
|---|---|---|---|---|
|
|---|---|---|---|---|
|
||||||
| `min` (app's own 15 imports) | 15 | 770 KB | 18 | 9 |
|
| `min` (only what the apps import) | 15 | 770 KB | 18 | 9 |
|
||||||
| `hci,gatt` (default) | 127 | 779 KB | 15 | 6 |
|
| `hci,gatt` (default) | 127 | 779 KB | 15 | 6 |
|
||||||
| `all` | 211 | ~788 KB | 13 | 4 |
|
| `all` | 211 | ~788 KB | 13 | 4 |
|
||||||
| stock light-stack firmware | 0 | 768 KB | 27 | n/a |
|
| stock light-stack firmware | 0 | 768 KB | 27 | n/a |
|
||||||
|
|
||||||
Any comma list of `hci,gap,gatt,hal,l2cap` works. `extended` refers to
|
`extended` refers to `stm32wb5x_BLE_Stack_full_extended_fw.bin` (BLE 5 extended
|
||||||
`stm32wb5x_BLE_Stack_full_extended_fw.bin` (BLE 5 extended advertising,
|
advertising, Coded PHY) at `0x080C5000`; it is not selected by this script.
|
||||||
Coded PHY), which loads at 0x080C5000; it is not selected by this script.
|
|
||||||
|
|
||||||
### Extra firmware APIs exported to apps
|
Beyond the ST BLE commands, `build.sh` also exports a set of firmware functions
|
||||||
|
that stock firmware keeps internal (the list lives in `EXPORT_ENABLE`):
|
||||||
|
|
||||||
Beyond the ST BLE commands, `build.sh` enables a set of firmware functions that
|
- **BLE peripheral internals** (`gap_*`, safe `ble_glue_*`, `furi_hal_bt_init`) —
|
||||||
stock firmware keeps internal, so any `.fap` on this firmware can use them. The
|
drive GAP directly, run a custom GATT server, set the advertised name and the
|
||||||
set is a list of name patterns in `build.sh` (`EXPORT_ENABLE`); each enabled
|
extra-beacon config, read connection and radio-stack status. The coprocessor
|
||||||
symbol costs one API-table entry. Only
|
firmware-update calls (`ble_glue_fus_stack_delete/install`) stay disabled, as
|
||||||
symbols named in `EXPORT_ENABLE` (plus the selected ST BLE commands) are
|
they can erase the radio stack.
|
||||||
exported; headers added for their types do not drag in every function they
|
- **Power / battery internals** — the gauge readings are already exported by
|
||||||
declare.
|
stock firmware; this adds `furi_hal_power_insomnia_level`.
|
||||||
|
`furi_hal_power_init` stays disabled.
|
||||||
|
- **Flash + option-byte internals** (`furi_hal_flash_*`) — geometry, free-page
|
||||||
|
info, and raw program / erase / write / option-byte access. **This can brick
|
||||||
|
the device or wipe storage;** enabled for research, `EXPORT_FLASH=0` opts out.
|
||||||
|
No app in this repo uses it.
|
||||||
|
- **RPC + loader** — the public `rpc_*` / `loader_*` APIs are already exported by
|
||||||
|
stock firmware; the internal loader headers are added so apps can use the
|
||||||
|
internal types, but the internal helper *functions* stay unexported (they are
|
||||||
|
not in the API-table link).
|
||||||
|
|
||||||
* **BLE peripheral internals** (`gap_*`, safe `ble_glue_*`, `furi_hal_bt_init`):
|
### 3. The sub-GHz region unlock
|
||||||
drive GAP directly, run a custom GATT server, change the advertised name and
|
|
||||||
the extra-beacon config, read connection state and radio-stack status,
|
|
||||||
without going through the firmware's serial profile. The coprocessor
|
|
||||||
firmware-update calls (`ble_glue_fus_stack_delete/install`) are deliberately
|
|
||||||
left disabled, since they can erase the radio stack.
|
|
||||||
* **Power / battery internals**: the gas-gauge readings (voltage, current,
|
|
||||||
temperature, remaining/full/design capacity, health, charge state) are
|
|
||||||
already exported by stock firmware. This build also enables
|
|
||||||
`furi_hal_power_insomnia_level`; `furi_hal_power_init` stays disabled.
|
|
||||||
* **Flash + option-byte internals** (`furi_hal_flash_*`): flash geometry,
|
|
||||||
free-page info, and raw program / erase / dword-write / option-byte access.
|
|
||||||
An app can read and modify internal flash directly. **This can brick the
|
|
||||||
device or wipe storage.** Enabled here for research; build with
|
|
||||||
`EXPORT_FLASH=0 ./build.sh` to leave these disabled.
|
|
||||||
* **RPC + loader internals**: the public `rpc_*` and `loader_*` APIs (RPC
|
|
||||||
session open/feed/close, app data exchange, launching and enqueuing apps,
|
|
||||||
lock/unlock, showing the app menu) are already exported by stock firmware and
|
|
||||||
are the supported way to script the Flipper from a host or launch other apps.
|
|
||||||
This build also adds the internal loader headers (`loader_i.h`,
|
|
||||||
`loader_menu.h`, `loader_queue.h`, `loader_applications.h`) so apps can use
|
|
||||||
the internal Loader types. The internal helper *functions* stay unexported:
|
|
||||||
they are not in the firmware's API-table link, so exporting them would break
|
|
||||||
the firmware build; only the public API is callable. `rpc_i.h` is not added
|
|
||||||
because it depends on the protobuf headers, which are not in the SDK.
|
|
||||||
|
|
||||||
`build.sh` also widens the GAP roles the firmware initialises
|
`build.sh` patches the region gate (`furi_hal_region_is_frequency_allowed` and
|
||||||
(`GAP_PERIPHERAL_ROLE | GAP_CENTRAL_ROLE | GAP_OBSERVER_ROLE`) in
|
`furi_hal_region_is_provisioned` forced true) so transmit is allowed on any
|
||||||
`targets/f7/ble_glue/gap.c`. The app itself uses HCI-level scan and connect
|
frequency the CC1101 can tune, regardless of the device's provisioned region —
|
||||||
commands, so this is belt-and-braces.
|
what most "unlocked" Flipper firmwares do. The CC1101 PLL bands (about 300-348,
|
||||||
|
387-464 and 779-928 MHz) remain, as they are a hardware limit, not a regulatory
|
||||||
|
one.
|
||||||
|
|
||||||
## How it works
|
> **Transmitting outside the frequencies and power levels allocated to you may be
|
||||||
|
> illegal where you are. This is for research and authorised testing only; you
|
||||||
|
> are responsible for operating within the law.** `SUBGHZ_UNLOCK=0` keeps the
|
||||||
|
> region limits in place.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## How the BLE apps work
|
||||||
|
|
||||||
```
|
```
|
||||||
bt_inspector.c UI (ViewDispatcher: scan list, text page, menus, inputs),
|
libble/
|
||||||
worker thread for blocking BLE operations, session log
|
ble_central.[ch] scan / connect / GATT client on top of the ST stack:
|
||||||
ble_central.c scan / connect / GATT client on top of the ST stack.
|
registers a handler with the firmware's BLE event
|
||||||
Registers a handler with the firmware's BLE event dispatcher,
|
dispatcher, consumes its own events (advertising reports,
|
||||||
acknowledges its own events (advertising reports, our
|
its connection's events) so the firmware's peripheral GAP
|
||||||
connection's events) so the firmware's peripheral GAP never
|
never sees them, and turns async ATT events into
|
||||||
sees them, and turns async ATT events into synchronous calls
|
synchronous calls behind a worker thread.
|
||||||
ble_names.c vendor / UUID / appearance tables and value decoders
|
ble_names.[ch] vendor / UUID / appearance tables, advertisement decoders
|
||||||
|
(Apple/Microsoft/Fast Pair/Eddystone), and characteristic
|
||||||
|
value decoders.
|
||||||
```
|
```
|
||||||
|
|
||||||
The app registers for BLE events, stops the Flipper's own advertising, then
|
Each BLE app registers for BLE events, stops the Flipper's own advertising, then
|
||||||
issues `hci_le_set_scan_*`, `hci_le_create_connection` and `aci_gatt_*`
|
issues `hci_le_set_scan_*`, `hci_le_create_connection` and `aci_gatt_*` commands
|
||||||
commands directly. Connection-complete events are distinguished from the
|
directly. Its own connection-complete events are told apart from the firmware's
|
||||||
firmware's peripheral connections by the role field. Advertising reports are
|
peripheral connections by the role field. Advertising reports are parsed from the
|
||||||
parsed from the raw HCI payload (the ST header's `Advertising_Report_t` is not a
|
raw HCI payload. `build.sh` copies `libble/*.{c,h}` into each app that includes
|
||||||
wire overlay).
|
`ble_central.h` at build time, so every app compiles against one source of truth.
|
||||||
|
|
||||||
## Sub-GHz region unlock (research)
|
---
|
||||||
|
|
||||||
`build.sh` also patches the firmware's sub-GHz region gate so transmit is
|
|
||||||
allowed on any frequency the CC1101 can tune, regardless of the device's
|
|
||||||
provisioned region: `furi_hal_region_is_frequency_allowed` and
|
|
||||||
`furi_hal_region_is_provisioned` are forced true. This is what most "unlocked"
|
|
||||||
Flipper firmwares do. The CC1101 PLL bands (about 300-348, 387-464 and
|
|
||||||
779-928 MHz) remain, because they are a hardware limit, not a regulatory one.
|
|
||||||
|
|
||||||
**Transmitting outside the frequencies and power levels allocated to you may be
|
|
||||||
illegal in your country. This is provided for research and authorised testing
|
|
||||||
only; you are responsible for operating within the law.** Build with
|
|
||||||
`SUBGHZ_UNLOCK=0 ./build.sh` to leave the region limits in place.
|
|
||||||
|
|
||||||
## Limitations
|
## Limitations
|
||||||
|
|
||||||
**Shared / hardware**
|
**Shared / hardware**
|
||||||
|
|
||||||
* **BLE only.** The STM32WB55 has no Bluetooth Classic (BR/EDR), so classic
|
- **BLE only.** The STM32WB55 has no Bluetooth Classic (BR/EDR), so classic
|
||||||
devices cannot be seen or connected from any Flipper.
|
devices cannot be seen or connected from any Flipper.
|
||||||
* **No pairing or bonding as central.** None of the central apps pair, so
|
- **No pairing or bonding as central.** None of the central apps pair, so
|
||||||
anything gated behind an encrypted link is out of reach: encrypted
|
anything gated behind an encrypted link is out of reach: encrypted
|
||||||
characteristics report "Insufficient auth" / "Insufficient encryption", and
|
characteristics report "Insufficient auth" / "Insufficient encryption", and
|
||||||
keyboards that only send reports after bonding stay silent.
|
keyboards that only send reports after bonding stay silent.
|
||||||
* At most two concurrent links (the firmware's BLE config), and while a BLE app
|
- At most two concurrent links (the firmware's BLE config); a BLE app stops the
|
||||||
runs the Flipper's own advertising is stopped and any phone link dropped, then
|
Flipper's advertising and drops any phone link while it runs, restoring both on
|
||||||
restored on exit.
|
exit. Only one app owns the radio at a time.
|
||||||
* The apps do not run at the same time; each one owns the radio while open.
|
- Built and checked against firmware 1.4.3 as `.fap` apps. On-device behaviour
|
||||||
* Built and checked against firmware 1.4.3 as `.fap` apps; on-device behaviour
|
needs a Flipper running the `build.sh` firmware; the apps will not load on
|
||||||
needs a Flipper running the firmware from `build.sh` (full stack + exported
|
stock firmware (missing exported symbols). Everything here is compile-verified,
|
||||||
API). The apps will not load on stock firmware (missing exported symbols).
|
not yet exercised on hardware.
|
||||||
|
|
||||||
**BT Inspector**
|
**BT Inspector** — Apple battery levels come from what AirPods/Beats broadcast;
|
||||||
|
iPhone/Mac battery is only exposed to paired Apple devices. Vendor, UUID and
|
||||||
|
Apple model tables are curated subsets (unknown IDs shown as hex) and Continuity
|
||||||
|
layouts are community-documented. Value history is per open characteristic; the
|
||||||
|
log has all of it. iOS-only BTInspector features (Shortcuts, Live Activities,
|
||||||
|
location-mapped background scanning) have no Flipper equivalent.
|
||||||
|
|
||||||
* Apple battery levels come from what AirPods/Beats broadcast. Battery of
|
**BLE HID Host** — report-mode devices are classified heuristically (8+ byte
|
||||||
iPhones/Macs is only exposed to paired Apple devices.
|
reports as keyboard, shorter as mouse), not by parsing the Report Map, so unusual
|
||||||
* Vendor, UUID and Apple model tables are curated subsets; unknown IDs are
|
layouts (consumer keys, multi-touch, gamepads) may decode oddly. Keyboard
|
||||||
shown as hex. Apple Continuity layouts are community-documented and may drift.
|
decoding covers the common usage page; other usages show as raw `[XX]`. Only
|
||||||
* Value history is kept for the open characteristic; the log file has all of it.
|
input reports are shown; output (LEDs) and feature reports are not driven.
|
||||||
* iOS-only BTInspector features (Shortcuts, Live Activities, background scanning
|
|
||||||
mapped by location) have no Flipper equivalent.
|
|
||||||
|
|
||||||
**BLE HID Host**
|
**BLE Sensor Dashboard** — only known-SIG characteristics are shown; each is a
|
||||||
|
single decoded field (no graphs or extra unit conversion), up to 12.
|
||||||
|
|
||||||
* Report-mode devices are decoded heuristically (8+ byte reports as keyboard,
|
**BLE Tracker Detector** — signature-based, so trackers using other schemes or
|
||||||
shorter as mouse) rather than by parsing the Report Map; unusual layouts
|
rotating their advertising identity may be missed; an address change counts as a
|
||||||
(consumer-control keys, multi-touch, gamepads) may decode oddly or not at all.
|
new device. The "following" flag is a heuristic, not proof. Passive only.
|
||||||
* Keyboard decoding covers the common USB HID usage page; media/consumer keys
|
|
||||||
and vendor usages show as raw `[XX]`. No key-repeat or text reconstruction,
|
|
||||||
just the reports as they arrive.
|
|
||||||
* Only input reports are shown; output reports (LEDs) and feature reports are
|
|
||||||
not driven.
|
|
||||||
|
|
||||||
**BLE Sensor Dashboard**
|
**BLE GATT Fuzzer** — a fixed set of boundary payloads, not a coverage-guided or
|
||||||
|
mutation fuzzer. **Writing arbitrary values can misconfigure or brick the
|
||||||
|
target;** authorised use only. Reads reflect what the peripheral returns; the
|
||||||
|
on-screen feed shows the first bytes, the log has the run.
|
||||||
|
|
||||||
* Only characteristics with a known SIG UUID are shown, decoded by the shared
|
**BLE Beacon Toolkit** — iBeacon expects exactly 21 bytes; Raw payloads are not
|
||||||
value decoders (battery, heart rate, temperature, humidity, pressure, Tx
|
validated as well-formed AD. Legacy advertising only (no extended / BLE 5 long
|
||||||
power, time, appearance, PnP ID). Vendor-specific/custom sensor
|
range). Config changes apply on the next Start.
|
||||||
characteristics are ignored, and each reading is a single field (no graphs or
|
|
||||||
unit conversions beyond what the decoder prints). Up to 12 readings.
|
|
||||||
|
|
||||||
**BLE Tracker Detector**
|
**BLE GATT Server** — exposes the fixed serial GATT service and echoes writes;
|
||||||
|
not an arbitrary user-defined schema. It takes over the BLE profile while open
|
||||||
|
and restores the default on exit.
|
||||||
|
|
||||||
* Detection is signature-based (Apple Find My/AirTag manufacturer data, Tile and
|
**Sub-GHz Scanner / Spectrum** — RSSI is read one frequency at a time with a
|
||||||
Samsung SmartTag service UUIDs). Trackers using other schemes, or ones that
|
fixed OOK preset and a short settle delay, so sweeps are slow and can miss brief
|
||||||
rotate their advertising identity, may be missed; a device that changes its
|
bursts; the reading reflects that preset's bandwidth, not a true FFT.
|
||||||
random address is counted as new. The "following" flag is a heuristic (seen
|
Frequencies are limited to the CC1101 PLL bands. Do not run alongside the stock
|
||||||
repeatedly over ~2 minutes), not proof, and there is no de-anonymisation.
|
Sub-GHz app (both drive the shared radio). Neither transmits; see the region
|
||||||
* Passive scan only; it never connects to or interacts with a tracker.
|
unlock note on legality.
|
||||||
|
|
||||||
**BLE GATT Fuzzer**
|
**Battery Health** — figures come straight from the gauge IC; "wear" is a rough
|
||||||
|
full-vs-design estimate. Read-only.
|
||||||
|
|
||||||
* The fuzz pass writes a small fixed set of boundary payloads (empty, 0x00,
|
**Exported firmware APIs (unlocks)** — every exported function costs flash and
|
||||||
0xFF, 20 bytes of 'A') to writable characteristics; it is not a coverage-
|
shrinks internal storage (see the table above). Flash / option-byte access is
|
||||||
guided or mutation fuzzer and does not chase crashes. **Writing arbitrary
|
raw and unguarded (brick/wipe risk); RPC/loader expose internal types only, not
|
||||||
values can misconfigure or brick the target.** Use only on devices you own or
|
the internal helper functions. The sub-GHz unlock removes the region check only;
|
||||||
are authorised to test.
|
the PLL bands and the law still apply. All of this is compile-verified, not
|
||||||
* Reads are truncated to the value length the peripheral returns; the on-screen
|
hardware-tested.
|
||||||
feed shows the first bytes, the log has the run.
|
|
||||||
|
|
||||||
**BLE Beacon Toolkit**
|
---
|
||||||
|
|
||||||
* iBeacon mode expects exactly 21 entered bytes (16 UUID + 2 major + 2 minor +
|
|
||||||
1 Tx) and wraps them in the Apple manufacturer AD; Raw mode sends the entered
|
|
||||||
bytes verbatim, up to 31. There is no validation that a raw payload is
|
|
||||||
well-formed AD. Config changes take effect on the next Start (Stop first).
|
|
||||||
* Legacy advertising only (no extended advertising / BLE 5 long range).
|
|
||||||
|
|
||||||
**BLE GATT Server**
|
|
||||||
|
|
||||||
* It exposes the firmware's fixed serial GATT service (a 128-bit service with RX
|
|
||||||
and TX characteristics) and echoes writes; it is not an arbitrary
|
|
||||||
user-defined GATT schema. Building custom services from a `.fap` is not
|
|
||||||
supported by the exported API. It takes over the BLE profile while open and
|
|
||||||
restores the default (phone/RPC) profile on exit.
|
|
||||||
|
|
||||||
**Sub-GHz Scanner / Spectrum**
|
|
||||||
|
|
||||||
* RSSI is read one frequency at a time through the CC1101 with a fixed OOK
|
|
||||||
preset and a short settle delay, so a sweep is slow and can miss brief
|
|
||||||
transmissions between steps; the reading reflects that preset's bandwidth, not
|
|
||||||
a true FFT. Frequencies are limited to the CC1101 PLL bands.
|
|
||||||
* These use the shared radio directly; do not run them alongside the stock
|
|
||||||
Sub-GHz app. Transmitting is not performed, but see the sub-GHz unlock note
|
|
||||||
below regarding legality.
|
|
||||||
|
|
||||||
**Battery Health**
|
|
||||||
|
|
||||||
* All figures come straight from the fuel-gauge IC; "wear" is derived from
|
|
||||||
full-vs-design capacity and is only a rough estimate. Read-only: it never
|
|
||||||
changes charge settings. It is the one app that also runs on stock firmware.
|
|
||||||
|
|
||||||
**Exported firmware APIs (unlocks)**
|
|
||||||
|
|
||||||
* Every exported function stays in the firmware image, so larger `BLE_API`
|
|
||||||
settings and the extra exports cost flash and shrink internal storage (see the
|
|
||||||
table above). `EXPORT_FLASH=0` and `SUBGHZ_UNLOCK=0` opt out.
|
|
||||||
* Flash / option-byte access is raw and unguarded: a misbehaving app can wipe
|
|
||||||
storage or brick the device. Nothing in these apps uses it; it is exposed for
|
|
||||||
other apps built against this SDK.
|
|
||||||
* RPC/loader internals expose only the internal *types*; the internal helper
|
|
||||||
functions are not exported (they are not in the firmware API-table link). The
|
|
||||||
public RPC and loader APIs remain the supported surface.
|
|
||||||
* **Sub-GHz unlock removes the region check only.** The CC1101 PLL bands
|
|
||||||
(~300-348 / 387-464 / 779-928 MHz) still bound what the radio can tune, and
|
|
||||||
transmitting outside your local allocation may be illegal. Research and
|
|
||||||
authorised testing only; you are responsible for legal operation.
|
|
||||||
* The exported ST BLE command API and these unlocks are compile-verified, not
|
|
||||||
exercised on hardware.
|
|
||||||
|
|
||||||
## Troubleshooting
|
## Troubleshooting
|
||||||
|
|
||||||
* **"Radio stack has no scanning"** on launch: the light stack is installed.
|
- **"Radio stack has no scanning" / an app says it needs the full stack** — the
|
||||||
Install the package produced by `build.sh`, which includes `radio.bin` with
|
light stack is installed. Install the package from `build.sh`, which includes
|
||||||
the full stack.
|
the full `radio.bin`.
|
||||||
* **Build killed / out of memory**: `JOBS=2 ./build.sh`.
|
- **App refuses to load ("API mismatch" / unresolved symbol)** — the device
|
||||||
* **App refuses to load ("API mismatch" / unresolved symbol)**: the firmware on
|
isn't running the `build.sh` firmware, or it was built with a smaller
|
||||||
the device is not the one from `build.sh`, or it was built with a smaller
|
|
||||||
`BLE_API` than the app needs. Reinstall the update package.
|
`BLE_API` than the app needs. Reinstall the update package.
|
||||||
* **"API version is still WIP"** during a build: `fbt` found symbols the script
|
- **Build killed / out of memory** — `JOBS=2 ./build.sh`.
|
||||||
did not classify. Open `targets/f7/api_symbols.csv`, replace the remaining
|
- **"API version is still WIP" during a build** — `fbt` found symbols the script
|
||||||
`?` marks with `+` or `-`, rerun.
|
did not classify; open `targets/f7/api_symbols.csv`, change any remaining `?`
|
||||||
* **Connect failed: Timeout**: the device may not be connectable (see the
|
to `+` or `-`, and rerun.
|
||||||
advertising type on the device page), or it is out of range. Random-address
|
- **Connect failed: Timeout** — the device may not be connectable (check the
|
||||||
devices that rotate their address may need re-selecting from the list.
|
advertising type on BT Inspector's device page) or is out of range; a
|
||||||
|
rotating-address device may need re-selecting from the list.
|
||||||
|
|
||||||
## The BLE HID Host app
|
---
|
||||||
|
|
||||||
Select a device from the scan list; the app connects, finds the HID service
|
## Repository layout
|
||||||
(0x1812), sets the protocol mode (boot when the device offers boot reports,
|
|
||||||
otherwise report mode), and subscribes to its input-report characteristics.
|
|
||||||
Keyboard reports are decoded to modifier + key names, mouse reports to button
|
|
||||||
state and dx/dy/wheel. Events scroll on screen (Up/Down to review history) and
|
|
||||||
are logged to `SD:/apps_data/ble_hid_host/hid_*.log` with the raw bytes. Back
|
|
||||||
disconnects and returns to scanning.
|
|
||||||
|
|
||||||
It cannot pair, so keyboards that require an encrypted link before sending
|
|
||||||
reports will connect but stay silent; open ones and most mice work.
|
|
||||||
|
|
||||||
## Layout
|
|
||||||
|
|
||||||
```
|
```
|
||||||
libble/ shared BLE central / GATT client + name & value decoders
|
libble/ shared BLE central / GATT client + name & value decoders
|
||||||
bt_inspector/ BT Inspector app (application.fam, icon.png, bt_inspector.c)
|
bt_inspector/ BT Inspector ble_beacon/ BLE Beacon Toolkit
|
||||||
ble_hid_host/ BLE HID Host app (HID-over-GATT setup + report decoding)
|
ble_hid_host/ BLE HID Host ble_gattsrv/ BLE GATT Server
|
||||||
build.sh firmware build / flash script (stages libble into each app)
|
ble_sensor/ BLE Sensor Dashboard subghz_scan/ Sub-GHz Scanner
|
||||||
|
ble_tracker/ BLE Tracker Detector subghz_spectrum/ Sub-GHz Spectrum
|
||||||
|
ble_gattfuzz/ BLE GATT Fuzzer battery_health/ Battery Health
|
||||||
|
build.sh firmware patch + build + flash script
|
||||||
flipperzero-firmware/ created by build.sh (git-ignored)
|
flipperzero-firmware/ created by build.sh (git-ignored)
|
||||||
```
|
```
|
||||||
|
|
||||||
`build.sh` copies `libble/*.{c,h}` into each app directory at build time, so
|
Each app directory holds its `application.fam`, `icon.png` and sources. To add
|
||||||
both apps compile against one source of truth. Add an app by dropping its
|
an app, drop a directory next to these and add its name to `APPS=(...)` in
|
||||||
directory next to these and adding its name to `APPS=(...)` in `build.sh`.
|
`build.sh`; if it includes `ble_central.h`, `build.sh` stages `libble` into it
|
||||||
|
automatically.
|
||||||
|
|||||||
Reference in New Issue
Block a user