Files
dwarf_protocol/02_ble_protocol.md
Jacquin Antoine be87e8a4ca Add complete DWARFLAB protocol documentation
- Architecture overview, BLE and WebSocket protocols
- All 19 modules with command IDs validated against smali source
- BLE packet format with CRC-16/MODBUS pseudocode
- Complete WsCmd index (~300 commands)
- Connection flow with pseudocode examples
- Methodology section explaining APK decompilation process
2026-06-13 00:21:19 +02:00

5.6 KiB

BLE Protocol

GATT Architecture

The device exposes a single BLE service with multiple characteristics:

UUID Type Role
0000180A-0000-1000-8000-00805F9B34FB Service Device Information (standard)
0000DAF2-0000-1000-8000-00805f9b34fb Service DWARF Primary Service
0000DAF3-0000-1000-8000-00805f9b34fb Characteristic Write — Send protobuf requests
0000DAF4-0000-1000-8000-00805F9B34FB Characteristic Notify — Receive protobuf responses
0000DAF5-0000-1000-8000-00805F9B34FB Characteristic Write — STA mode configuration
0000DAF6-0000-1000-8000-00805F9B34FB Characteristic Notify — STA mode responses
0000DAF7-0000-1000-8000-00805F9B34FB Characteristic Write — AP mode configuration
00009999-0000-1000-8000-00805F9B34FB Characteristic Notify — AP mode responses

Note

: UUIDs DAF2/DAF3 use lowercase 00805f9b34fb while DAF4-DAF7/9999 use uppercase 00805F9B34FB. This is as-is in the source code (cg1.smali).

BLE Packet Format (BluetoothPacket)

All BLE data is framed in a custom packet format before being sent over GATT characteristics.

Binary Layout

Offset  Size  Field              Description
------  ----  -----------------  -------------------------------------------
0       1     magic              0xAA (constant)
1       1     protocolVersion    Protocol version (typically 1)
2       1     cmdInstruction     Command type (0-7, see below)
3       1     packageSequence    Current packet sequence number (0-based)
4       1     totalPackages      Total number of packets for this message
5       2     extendedProtocol   Extended protocol field (big-endian, usually 0)
7       2     validDataLength    Length of protobuf payload (big-endian)
9       N     dataPayload        Protobuf-encoded BleProto message
9+N     2     crc                CRC-16/MODBUS (poly=0x8005, init=0xFFFF, reflected, XOR=0x0000)
11+N    1     endMarker           0x0D (constant)

Total packet size = validDataLength + 12

Pseudocode: Building a BLE Packet

import struct

def build_ble_packet(cmd: int, protobuf_data: bytes, seq: int = 0, total: int = 1) -> bytes:
    """Build a BLE packet from protobuf data."""
    header = struct.pack('>BBBH',  # big-endian: B=cmd, B=seq, B=total, H=extended
        0xAA,        # magic byte
        1,           # protocolVersion
        cmd,         # cmdInstruction
        seq,         # packageSequence
        total,       # totalPackages
        0            # extendedProtocol (reserved)
    )
    # validDataLength
    length_bytes = struct.pack('>H', len(protobuf_data))
    # CRC over header + length + data
    crc_input = header + length_bytes + protobuf_data
    crc = crc16_modbus(crc_input)
    crc_bytes = struct.pack('>H', crc)
    # Assemble: header(7B) + length(2B) + data(NB) + crc(2B) + end(1B)
    return header + length_bytes + protobuf_data + crc_bytes + b'\x0D'

Pseudocode: CRC-16/MODBUS

def crc16_modbus(data: bytes) -> int:
    """CRC-16/MODBUS: poly=0x8005, init=0xFFFF, reflected=True, XOR_out=0x0000"""
    crc = 0xFFFF
    for byte in data:
        crc ^= byte
        for _ in range(8):
            if crc & 0x0001:
                crc = (crc >> 1) ^ 0xA001  # reflected poly
            else:
                crc >>= 1
    return crc & 0xFFFF

Fragmentation

When a protobuf message exceeds the BLE MTU, it is split across multiple packets:

  • packageSequence starts at 0, increments per packet
  • totalPackages indicates total number of packets for the message
  • Each packet contains a fragment of the protobuf payload
  • isLastPacket = (packageSequence == totalPackages - 1)

BLE Commands

cmdInstruction Name Description
0 Unknown Reserved
1 GetWiFiConfig Authenticate and get device config
2 SetApMode Configure device as WiFi hotspot (AP)
3 SetSTAMode Configure device to connect to WiFi (STA)
4 SetNamePwd Set BLE/WiFi name and password
5 Reset Factory reset
6 GetWiFiList Scan available WiFi networks
7 GetDeviceInfo Get system info (protocol version, MAC, firmware)

Authentication Flow

App                                     Device
 │                                        │
 │  BLE SCAN: discover "DWARF*"          │
 │  GATT CONNECT to service DAF2          │
 │                                        │
 │  ReqGetconfig {blePsd, clientId}       │
 │  ──── DAF3 (write) ────────────────►  │
 │                                        │
 │  ResGetconfig {code, ip, ssid, ...}    │
 │  ◄──── DAF4 (notify) ──────────────  │
 │                                        │
 │  [Optional] ReqSta/ReqAp               │
 │  ──── DAF5/DAF7 ───────────────────►  │
 │                                        │
 │  Connect to ws://<ip>:9900            │
 │                                        │

Connection States

State Description
Loading Connecting
Success Connected
PwdError Authentication failed
DeviceError Device error
Disconnecting Disconnecting
Disconnected Disconnected

BLE Error Types

Error Description
BluetoothConnection BLE connection failure
MTU MTU negotiation failure
Communication Communication error
ConfigFailed Configuration failed