diff --git a/data/templates/xap/docs/broadcast_messages.md.j2 b/data/templates/xap/docs/broadcast_messages.md.j2 new file mode 100644 index 00000000000..9e4ca953f1d --- /dev/null +++ b/data/templates/xap/docs/broadcast_messages.md.j2 @@ -0,0 +1,4 @@ +{%- for id, message in xap.broadcast_messages.messages | dictsort %} +### {{ message.name }} - `{{ id }}` +{{ message.description }} +{%- endfor %} diff --git a/data/templates/xap/docs/routes.md.j2 b/data/templates/xap/docs/routes.md.j2 new file mode 100644 index 00000000000..339d58e6168 --- /dev/null +++ b/data/templates/xap/docs/routes.md.j2 @@ -0,0 +1,12 @@ +{%- for id, route in xap.routes | dictsort %} +### {{ route.name }} - `{{ id }}` +{{ route.description }} + +{% if route.routes %} +| Name | Route | Definition | +| -- | -- | -- | +{%- for subid, subroute in route.routes | dictsort %} +| {{ subroute.name }} | `{{ id }} {{ subid }}` | {{ subroute.description.split('\n')[0] }} | +{%- endfor %} +{% endif %} +{%- endfor %} diff --git a/data/xap/xap_0.0.1.hjson b/data/xap/xap_0.0.1.hjson index 48325247bf6..d22c5428646 100755 --- a/data/xap/xap_0.0.1.hjson +++ b/data/xap/xap_0.0.1.hjson @@ -17,6 +17,8 @@ response_flags !response_flags.md.j2 example_conversation + routes + !routes.md.j2 ] page_header: @@ -64,17 +66,27 @@ ### Example "conversation": **Request** -- version query: + | Byte | 0 | 1 | 2 | 3 | 4 | | --- | --- | --- | --- | --- | --- | | **Purpose** | Token | Token | Payload Length | Route | Route | | **Value** | `0x43` | `0x2B` | `0x02` | `0x00` | `0x00` | **Response** -- matching token, successful flag, payload of `0x03170192` = 3.17.192: + | Byte | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | | --- | --- | --- | --- | --- | --- | --- | --- | --- | | **Purpose** | Token | Token | Response Flags | Payload Length | Payload | Payload | Payload | Payload | | **Value** | `0x43` | `0x2B` | `0x01` | `0x04` | `0x92` | `0x01` | `0x17` | `0x03` | ''' + + routes: + ''' + ## Routes + + Subsystem validity should be queried through the “Enabled-in-firmware subsystem query” under the QMK subsystem (route=0x00,0x01). + This is the primary method for determining if a subsystem has been enabled in the running firmware. + ''' } type_docs: { diff --git a/data/xap/xap_0.1.0.hjson b/data/xap/xap_0.1.0.hjson index 078997a0c54..fb5731d4bf3 100755 --- a/data/xap/xap_0.1.0.hjson +++ b/data/xap/xap_0.1.0.hjson @@ -8,6 +8,7 @@ documentation: { order: [ broadcast_messages + !broadcast_messages.md.j2 ] reserved_tokens: @@ -118,6 +119,7 @@ Log message payloads include a `u8` signifying the length of the text, followed by the `u8[Length]` containing the text itself. **Example Log Broadcast** -- log message "Hello QMK!" + | Byte | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | | **Purpose** | Token | Token | Broadcast Type | Length | Payload | Payload | Payload | Payload | Payload | Payload | Payload | Payload | Payload | Payload | diff --git a/docs/_summary.md b/docs/_summary.md index fed75196b4f..aa96e4c2e64 100644 --- a/docs/_summary.md +++ b/docs/_summary.md @@ -92,6 +92,7 @@ * [Unicode](feature_unicode.md) * [Userspace](feature_userspace.md) * [WPM Calculation](feature_wpm.md) + * [XAP](xap.md) * Hardware Features * Displays diff --git a/docs/xap.md b/docs/xap.md new file mode 100644 index 00000000000..340c42bca83 --- /dev/null +++ b/docs/xap.md @@ -0,0 +1,89 @@ +# XAP + +XAP (“extensible application protocol”) API intends to provide access to various QMK subsystems. + +## Overview + +TODO + +## Protocol Reference + +[protocol_versions](xap_protocol.md ':include') + +## Clients + +TODO + +## CLI + +The QMK CLI provides a few XAP specific commands for diagnosis purposes. + +### List Connected Devices +Simple +``` +$ qmk xap --list +Ψ Available devices: +Ψ 7844:8450 KPrepublic XD84 Pro [API:0.2.0] LOCKED +``` + +Verbose +``` +$ qmk --verbose xap --list +Ψ Available devices: +Ψ 7844:8450 KPrepublic XD84 Pro [API:0.2.0] LOCKED + _id: 553831323538150A2113000000000000 + backlight.pin: F5 + bootloader: atmel-dfu + community_layouts: 75_ansi, 75_iso + debounce: 5 + diode_direction: COL2ROW + features.audio: False + features.backlight: True + features.bootmagic: True + features.command: False + features.console: False + features.extrakey: True + features.mousekey: False + features.nkro: True + features.rgblight: True + indicators.caps_lock: B2 + keyboard_folder: xiudi/xd84pro + keyboard_name: XD84 Pro + layouts: LAYOUT_75_ansi, LAYOUT_75_iso, LAYOUT_all + maintainer: qmk + manufacturer: KPrepublic + matrix_pins.cols: B1, B3, B4, B5, B6, B7, C6, C7, D4, D6, D7, E6, F0, F1, F7 + matrix_pins.rows: D0, D1, D2, D3, D5, F4 + matrix_pins.unused: B0, E2 + matrix_size.cols: 15 + matrix_size.rows: 6 + mouse_key.enabled: False + platform: unknown + processor: atmega32u4 + processor_type: avr + protocol: LUFA + rgblight.animations.all: False + rgblight.led_count: 12 + rgblight.pin: F6 + rgblight.sleep: False + url: + usb.device_ver: 0x0001 + usb.device_version: 0.0.1 + usb.pid: 0x8450 + usb.vid: 0x7844 +``` + +### Interactive shell +``` +$ qmk xap -i +Ψ Connected to:7844:8450 KPrepublic XD84 Pro +Welcome to the XAP shell. Type help or ? to list commands. + +Ψ> help + +Documented commands (type help ): +======================================== +EOF about exit help keycode keymap layer listen unlock + +Ψ> +``` diff --git a/docs/xap_0.0.1.md b/docs/xap_0.0.1.md index 313ab9e488a..e8d165ef10e 100644 --- a/docs/xap_0.0.1.md +++ b/docs/xap_0.0.1.md @@ -52,14 +52,31 @@ Response messages will always be prefixed by the originating request _token_, di ### Example "conversation": **Request** -- version query: + | Byte | 0 | 1 | 2 | 3 | 4 | | --- | --- | --- | --- | --- | --- | | **Purpose** | Token | Token | Payload Length | Route | Route | | **Value** | `0x43` | `0x2B` | `0x02` | `0x00` | `0x00` | **Response** -- matching token, successful flag, payload of `0x03170192` = 3.17.192: + | Byte | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | | --- | --- | --- | --- | --- | --- | --- | --- | --- | | **Purpose** | Token | Token | Response Flags | Payload Length | Payload | Payload | Payload | Payload | | **Value** | `0x43` | `0x2B` | `0x01` | `0x04` | `0x92` | `0x01` | `0x17` | `0x03` | +## Routes + +Subsystem validity should be queried through the “Enabled-in-firmware subsystem query” under the QMK subsystem (route=0x00,0x01). +This is the primary method for determining if a subsystem has been enabled in the running firmware. + + +### XAP - `0x00` +This subsystem is always present, and provides the ability to query information about the XAP protocol of the connected device. + + +| Name | Route | Definition | +| -- | -- | -- | +| Version Query | `0x00 0x00` | XAP protocol version query. | + + diff --git a/docs/xap_0.1.0.md b/docs/xap_0.1.0.md index 73a76680c57..6e79158e3dc 100644 --- a/docs/xap_0.1.0.md +++ b/docs/xap_0.1.0.md @@ -65,18 +65,79 @@ Response messages will always be prefixed by the originating request _token_, di ### Example "conversation": **Request** -- version query: + | Byte | 0 | 1 | 2 | 3 | 4 | | --- | --- | --- | --- | --- | --- | | **Purpose** | Token | Token | Payload Length | Route | Route | | **Value** | `0x43` | `0x2B` | `0x02` | `0x00` | `0x00` | **Response** -- matching token, successful flag, payload of `0x03170192` = 3.17.192: + | Byte | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | | --- | --- | --- | --- | --- | --- | --- | --- | --- | | **Purpose** | Token | Token | Response Flags | Payload Length | Payload | Payload | Payload | Payload | | **Value** | `0x43` | `0x2B` | `0x01` | `0x04` | `0x92` | `0x01` | `0x17` | `0x03` | +## Routes + +Subsystem validity should be queried through the “Enabled-in-firmware subsystem query” under the QMK subsystem (route=0x00,0x01). +This is the primary method for determining if a subsystem has been enabled in the running firmware. + + +### XAP - `0x00` +This subsystem is always present, and provides the ability to query information about the XAP protocol of the connected device. + + +| Name | Route | Definition | +| -- | -- | -- | +| Version Query | `0x00 0x00` | XAP protocol version query. | +| Capabilities Query | `0x00 0x01` | XAP subsystem capabilities query. Each bit should be considered as a "usable" route within this subsystem. | +| Enabled subsystem query | `0x00 0x02` | XAP protocol subsystem query. Each bit should be considered as a "usable" subsystem. For example, checking `(value & (1 << XAP_ROUTE_QMK) != 0)` means the QMK subsystem is enabled and available for querying. | +| Secure Status | `0x00 0x03` | Query secure route status | +| Secure Unlock | `0x00 0x04` | Initiate secure route unlock sequence | +| Secure Lock | `0x00 0x05` | Disable secure routes | + +### QMK - `0x01` +This subsystem is always present, and provides the ability to address QMK-specific functionality. + + +| Name | Route | Definition | +| -- | -- | -- | +| Version Query | `0x01 0x00` | QMK protocol version query. | +| Capabilities Query | `0x01 0x01` | QMK subsystem capabilities query. Each bit should be considered as a "usable" route within this subsystem. | +| Board identifiers | `0x01 0x02` | Retrieves the set of identifying information for the board. | +| Board Manufacturer | `0x01 0x03` | Retrieves the name of the manufacturer | +| Product Name | `0x01 0x04` | Retrieves the product name | +| info.json length | `0x01 0x05` | Retrieves the length of info.json | +| info.json | `0x01 0x06` | Retrieves a chunk of info.json | +| Jump to bootloader | `0x01 0x07` | Jump to bootloader | +| info.json | `0x01 0x08` | Retrieves a unique identifier for the board. | + +### Keyboard - `0x02` +This subsystem is always present, and reserved for user-specific functionality. No routes are defined by XAP. + + +### User - `0x03` +This subsystem is always present, and reserved for user-specific functionality. No routes are defined by XAP. + + + ## Broadcast messages Broadcast messages may be sent by the firmware to the host, without a corresponding inbound request. Each broadcast message uses the token `0xFFFF`, and does not expect a response from the host. Tokens are followed by an _ID_ signifying the type of broadcast, with corresponding _payload_. + +### Log message - `0x00` +Replicates and replaces the same functionality as if using the standard QMK `CONSOLE_ENABLE = yes` in `rules.mk`. Normal prints within the firmware will manifest as log messages broadcast to the host. `hid_listen` will not be functional with XAP enabled. + +Log message payloads include a `u8` signifying the length of the text, followed by the `u8[Length]` containing the text itself. + +**Example Log Broadcast** -- log message "Hello QMK!" + +| Byte | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | +| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | +| **Purpose** | Token | Token | Broadcast Type | Length | Payload | Payload | Payload | Payload | Payload | Payload | Payload | Payload | Payload | Payload | +| **Value** | `0xFF` | `0xFF` | `0x00` | `0x0A`(10) | `0x48`(H) | `0x65`(e) | `0x6C`(l) | `0x6C`(l) | `0x6F`(o) | `0x20`( ) | `0x51`(Q) | `0x4D`(M) | `0x4B`(K) | `0x21`(!) | +### Secure Status - `0x01` +Secure status has changed. + diff --git a/docs/xap_0.2.0.md b/docs/xap_0.2.0.md index 73a76680c57..47115c5e365 100644 --- a/docs/xap_0.2.0.md +++ b/docs/xap_0.2.0.md @@ -65,18 +65,108 @@ Response messages will always be prefixed by the originating request _token_, di ### Example "conversation": **Request** -- version query: + | Byte | 0 | 1 | 2 | 3 | 4 | | --- | --- | --- | --- | --- | --- | | **Purpose** | Token | Token | Payload Length | Route | Route | | **Value** | `0x43` | `0x2B` | `0x02` | `0x00` | `0x00` | **Response** -- matching token, successful flag, payload of `0x03170192` = 3.17.192: + | Byte | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | | --- | --- | --- | --- | --- | --- | --- | --- | --- | | **Purpose** | Token | Token | Response Flags | Payload Length | Payload | Payload | Payload | Payload | | **Value** | `0x43` | `0x2B` | `0x01` | `0x04` | `0x92` | `0x01` | `0x17` | `0x03` | +## Routes + +Subsystem validity should be queried through the “Enabled-in-firmware subsystem query” under the QMK subsystem (route=0x00,0x01). +This is the primary method for determining if a subsystem has been enabled in the running firmware. + + +### XAP - `0x00` +This subsystem is always present, and provides the ability to query information about the XAP protocol of the connected device. + + +| Name | Route | Definition | +| -- | -- | -- | +| Version Query | `0x00 0x00` | XAP protocol version query. | +| Capabilities Query | `0x00 0x01` | XAP subsystem capabilities query. Each bit should be considered as a "usable" route within this subsystem. | +| Enabled subsystem query | `0x00 0x02` | XAP protocol subsystem query. Each bit should be considered as a "usable" subsystem. For example, checking `(value & (1 << XAP_ROUTE_QMK) != 0)` means the QMK subsystem is enabled and available for querying. | +| Secure Status | `0x00 0x03` | Query secure route status | +| Secure Unlock | `0x00 0x04` | Initiate secure route unlock sequence | +| Secure Lock | `0x00 0x05` | Disable secure routes | + +### QMK - `0x01` +This subsystem is always present, and provides the ability to address QMK-specific functionality. + + +| Name | Route | Definition | +| -- | -- | -- | +| Version Query | `0x01 0x00` | QMK protocol version query. | +| Capabilities Query | `0x01 0x01` | QMK subsystem capabilities query. Each bit should be considered as a "usable" route within this subsystem. | +| Board identifiers | `0x01 0x02` | Retrieves the set of identifying information for the board. | +| Board Manufacturer | `0x01 0x03` | Retrieves the name of the manufacturer | +| Product Name | `0x01 0x04` | Retrieves the product name | +| info.json length | `0x01 0x05` | Retrieves the length of info.json | +| info.json | `0x01 0x06` | Retrieves a chunk of info.json | +| Jump to bootloader | `0x01 0x07` | Jump to bootloader | +| info.json | `0x01 0x08` | Retrieves a unique identifier for the board. | + +### Keyboard - `0x02` +This subsystem is always present, and reserved for user-specific functionality. No routes are defined by XAP. + + +### User - `0x03` +This subsystem is always present, and reserved for user-specific functionality. No routes are defined by XAP. + + +### Dynamic Keymap - `0x04` +This subsystem allows for live modifications of the keymap, allowing keys to be reassigned without rebuilding the firmware. + + +| Name | Route | Definition | +| -- | -- | -- | +| Capabilities Query | `0x04 0x00` | Dynamic Keymap subsystem capabilities query. Each bit should be considered as a "usable" route within this subsystem. | +| Get Layer Count | `0x04 0x01` | TODO | +| Get Keycode | `0x04 0x02` | TODO | +| Set Keycode | `0x04 0x03` | TODO | + +### Dynamic Encoders - `0x05` +This subsystem allows for live modifications of the keymap, allowing encoder functionality to be reassigned without rebuilding the firmware. + + +| Name | Route | Definition | +| -- | -- | -- | +| Capabilities Query | `0x05 0x00` | Dynamic Encoders subsystem capabilities query. Each bit should be considered as a "usable" route within this subsystem. | +| Get Keycode | `0x05 0x02` | TODO | +| Set Keycode | `0x05 0x03` | TODO | + +### Lighting - `0x06` +This subsystem allows for control over the lighting subsystem. + + +| Name | Route | Definition | +| -- | -- | -- | +| Capabilities Query | `0x06 0x00` | Lighting subsystem capabilities query. Each bit should be considered as a "usable" route within this subsystem. | + + ## Broadcast messages Broadcast messages may be sent by the firmware to the host, without a corresponding inbound request. Each broadcast message uses the token `0xFFFF`, and does not expect a response from the host. Tokens are followed by an _ID_ signifying the type of broadcast, with corresponding _payload_. + +### Log message - `0x00` +Replicates and replaces the same functionality as if using the standard QMK `CONSOLE_ENABLE = yes` in `rules.mk`. Normal prints within the firmware will manifest as log messages broadcast to the host. `hid_listen` will not be functional with XAP enabled. + +Log message payloads include a `u8` signifying the length of the text, followed by the `u8[Length]` containing the text itself. + +**Example Log Broadcast** -- log message "Hello QMK!" + +| Byte | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | +| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | +| **Purpose** | Token | Token | Broadcast Type | Length | Payload | Payload | Payload | Payload | Payload | Payload | Payload | Payload | Payload | Payload | +| **Value** | `0xFF` | `0xFF` | `0x00` | `0x0A`(10) | `0x48`(H) | `0x65`(e) | `0x6C`(l) | `0x6C`(l) | `0x6F`(o) | `0x20`( ) | `0x51`(Q) | `0x4D`(M) | `0x4B`(K) | `0x21`(!) | +### Secure Status - `0x01` +Secure status has changed. + diff --git a/docs/xap_protocol.md b/docs/xap_protocol.md index 688d7dab3ea..08390580bbe 100644 --- a/docs/xap_protocol.md +++ b/docs/xap_protocol.md @@ -1,5 +1,4 @@ -# XAP Protocol Reference - + * [XAP Version 0.2.0](xap_0.2.0.md) * [XAP Version 0.1.0](xap_0.1.0.md) * [XAP Version 0.0.1](xap_0.0.1.md) diff --git a/lib/python/qmk/cli/xap/generate_docs.py b/lib/python/qmk/cli/xap/generate_docs.py index e399b6ddb12..ae1c9907b4a 100755 --- a/lib/python/qmk/cli/xap/generate_docs.py +++ b/lib/python/qmk/cli/xap/generate_docs.py @@ -30,8 +30,7 @@ def xap_generate_docs(cli): output_doc = QMK_FIRMWARE / "docs" / "xap_protocol.md" with open(output_doc, "w", encoding='utf-8') as out_file: out_file.write('''\ -# XAP Protocol Reference - + ''') for file in reversed(sorted(docs_list)):