diff --git a/Readme.md b/Readme.md index 0d50e1f..73454fe 100644 --- a/Readme.md +++ b/Readme.md @@ -57,6 +57,65 @@ If no Tap is already connected at the OS level, `run()` will scan and wait for a Also make sure that you have updated your Tap device to the latest version. +### BLE GATT reference + +Verified against firmware `tap_rd/ble-mcu-hw-v3-sdk-14.0` branch **`TAP_XR_develop`** (`ble_tap_service.c`, `services_init`, Nordic `ble_nus`). Also matches the other official Tap SDKs and [Tap BLE API Documentation](https://tapwithus.atlassian.net/wiki/spaces/FIR/pages/426803201/Tap+BLE+API+Documentation). + +Tap base UUID: `c3ff0000-1d8b-40fd-a56f-c7bd5d0f3370` (16-bit offsets below). NUS is the standard Nordic UART base `6e400000-b5a3-f393-e0a9-e50e24dcca9e`. + +**Advertising:** primary adv carries HID (`0x1812`); Tap service UUID is in the **scan response**. Active scan (or OS-paired reconnect) is needed to see `c3ff0001-…` in advertised service lists. + +#### Services the firmware always registers + +From `services_init()` / device mediator on `TAP_XR_develop`: + +| Service | UUID | Role | +| --- | --- | --- | +| HID | `00001812-0000-1000-8000-00805f9b34fb` | Keyboard / mouse HID over GATT | +| Battery | `0000180f-0000-1000-8000-00805f9b34fb` | Battery Level | +| Device Information | `0000180a-0000-1000-8000-00805f9b34fb` | FW / HW / serial strings | +| Buttonless DFU | Nordic DFU | FOTA bootloader trigger | +| **Tap** | `c3ff0001-1d8b-40fd-a56f-c7bd5d0f3370` | Proprietary events / commands | +| **NUS** | `6e400001-b5a3-f393-e0a9-e50e24dcca9e` | Mode / raw-sensor channel | + +#### Required by this Python SDK + +Minimum used for discovery, mode control, and tap events (Windows SDK similarly requires Tap Data + NUS RX): + +| Role | UUID | FW properties | Purpose | +| --- | --- | --- | --- | +| Tap service | `c3ff0001-…` | (service; scan response) | Find / filter Tap | +| Tap data | `c3ff0005-…` | Notify | Tap codes (`register_tap_events`) | +| NUS service | `6e400001-…` | (service) | Mode channel | +| NUS RX | `6e400002-…` | Write | Input mode / type (`set_input_mode`, `set_input_type`); refresh ~every 10s in controller/raw | + +#### Used optionally by this SDK + +Notify setup is best-effort if a characteristic is missing on older devices. + +| Characteristic | UUID | FW properties | Purpose | +| --- | --- | --- | --- | +| Mouse data | `c3ff0006-…` | Notify, Write, WriteWithoutResponse | Surface mouse (`register_mouse_events`) | +| UI / haptic | `c3ff0009-…` | Write, WriteWithoutResponse | Vibration (`send_vibration_sequence`) | +| Air gesture | `c3ff000a-…` | Notify, WriteWithoutResponse, Read | Air gestures / mouse-mode state (`register_air_gesture_*`) | +| NUS TX | `6e400003-…` | Notify | Raw sensors (`register_raw_data_events`; Developer mode) | + +#### Other Tap-service characteristics (on device; unused here) + +Registered in `ble_tap_init()` on `TAP_XR_develop`: + +| Char | UUID | FW properties | Notes | +| --- | --- | --- | --- | +| Settings | `c3ff0002-…` | Read, Write | Device settings | +| Name | `c3ff0003-…` | Read, Write | BLE name (Android SDK) | +| Mapping RX | `c3ff0007-…` | Write, WriteWithoutResponse | Custom map upload | +| Mapping TX | `c3ff0008-…` | Notify | Custom map download | +| Data request | `c3ff000b-…` | Notify, WriteWithoutResponse, Read | State queries (Android SDK) | +| Kneron model ver | `c3ff000c-…` | Notify, Read | TapXR NPU model | +| Kneron FW ver | `c3ff000d-…` | Notify, Read | TapXR NPU firmware | + +Constants: [`tapsdk/tap.py`](tapsdk/tap.py). + ### Features This SDK implements two basic interfaces with a Tap device. diff --git a/tapsdk/tap.py b/tapsdk/tap.py index 255d6c6..bbe0afd 100644 --- a/tapsdk/tap.py +++ b/tapsdk/tap.py @@ -11,14 +11,18 @@ logger = logging.getLogger(__name__) +# BLE GATT UUIDs — verified against tap_rd/ble-mcu-hw-v3-sdk-14.0 @ TAP_XR_develop +# (ble_tap_service.c / Nordic ble_nus). Required for this SDK: Tap service (scan +# response filter), Tap data (notify), NUS service, NUS RX (write input mode). +# See README "BLE GATT reference". tap_service = 'c3ff0001-1d8b-40fd-a56f-c7bd5d0f3370' nus_service = '6e400001-b5a3-f393-e0a9-e50e24dcca9e' tap_data_characteristic = 'c3ff0005-1d8b-40fd-a56f-c7bd5d0f3370' mouse_data_characteristic = 'c3ff0006-1d8b-40fd-a56f-c7bd5d0f3370' ui_cmd_characteristic = 'c3ff0009-1d8b-40fd-a56f-c7bd5d0f3370' air_gesture_data_characteristic = 'c3ff000a-1d8b-40fd-a56f-c7bd5d0f3370' -tap_mode_characteristic = '6e400002-b5a3-f393-e0a9-e50e24dcca9e' # nus rx -raw_sensors_characteristic = '6e400003-b5a3-f393-e0a9-e50e24dcca9e' # nus tx +tap_mode_characteristic = '6e400002-b5a3-f393-e0a9-e50e24dcca9e' # NUS RX (write) +raw_sensors_characteristic = '6e400003-b5a3-f393-e0a9-e50e24dcca9e' # NUS TX (notify) if platform.system() == "Darwin":