Connect Bluetooth in this order: advertise → connect → transfer bytes → pair. The SDK handles the secure protocol; your driver handles BLE.
Create the Bluetooth service
GATT is Bluetooth’s service-and-characteristic interface. Create one service with these two characteristics:
| Item | UUID | Direction |
|---|---|---|
| Service | 6d4d0001-5239-4f5e-9ca0-941181196587 |
— |
| RX | 6d4d0002-5239-4f5e-9ca0-941181196587 |
Phone writes to the board (Write With Response) |
| TX | 6d4d0003-5239-4f5e-9ca0-941181196587 |
Board notifies the phone (Notify + CCCD) |
Call moto_terminal_advertising(terminal, advertisement) with a buffer of at least 31 bytes. Publish the returned advertisement unchanged: it already contains Flags and Service Data. Put an optional device name in the scan response rather than adding another Flags field.
Forward connection events
Start the SDK before enabling Bluetooth input. On connection, ask it for a connection number and save that number in the driver’s connection context:
uint64_t connection = 0;
moto_result rc = moto_terminal_connected(terminal, &connection);
Use this saved number for all received bytes and the eventual disconnect:
moto_terminal_disconnected(terminal, connection);
The number changes after reconnecting, so old callbacks cannot affect a new phone connection. Support one active phone connection at a time.
Forward received bytes
Send incoming RX bytes to:
moto_result rc = moto_terminal_receive(
terminal, connection, bytes, size);
Each call accepts 1–512 bytes. Keep byte order unchanged.
| Result | Driver action |
|---|---|
MOTO_OK |
All bytes were copied; release your input buffer |
MOTO_FULL |
No bytes were accepted; retain and retry the same bytes in order |
MOTO_STATE |
This connection is no longer valid; stop forwarding its data |
Call from a task, not an interrupt. If your Bluetooth callback cannot wait, copy data into a bounded driver queue and forward it from a task.
Send data to the phone
Provide this callback in config.port:
int ble_send(void *user, uint64_t connection,
const uint8_t *bytes, size_t size);
Copy accepted bytes before returning. Return the number actually accepted, 0 when temporarily busy, or a negative value when the connection has failed. Split notifications according to the negotiated MTU—the maximum size of one Bluetooth transfer. Do not retain the SDK’s input pointer.
ble_close requests closure of the specified connection and returns promptly. Notify the SDK when the physical disconnect occurs.
Display the pairing code
Keep taking events with moto_terminal_next_event:
| Event | What the instrument does |
|---|---|
MOTO_EVENT_PAIRING_PIN |
Display e.value as four digits, including leading zeros; e.target is its validity in seconds |
MOTO_EVENT_PAIRING_CLEARED |
Remove the code |
MOTO_EVENT_PAIR |
Update the paired state |
MOTO_EVENT_UNPAIR |
Update the unpaired state |
MOTO_EVENT_CLOSED |
Clear the code and temporary session UI |
READY means the encrypted channel is ready. AUTHENTICATED means the phone owner is authenticated. Product features still depend on the device model’s configuration.
Verify pairing survives a restart
Pair once, disconnect, and reconnect. Then restart the board and connect again without pairing from scratch. If the record is lost, check storage using SDK & device setup. For discovery or PIN problems, see Troubleshooting.
