Skip to content

Commit

Permalink
Initial implementation of XAP protocol.
Browse files Browse the repository at this point in the history
  • Loading branch information
tzarc committed Aug 11, 2021
1 parent f4c447f commit eba91c6
Show file tree
Hide file tree
Showing 34 changed files with 1,934 additions and 4 deletions.
24 changes: 24 additions & 0 deletions build_keyboard.mk
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,30 @@ VPATH += $(KEYBOARD_PATHS)
VPATH += $(COMMON_VPATH)

include common_features.mk

# XAP embedded info.json
ifeq ($(strip $(XAP_ENABLE)), yes)

$(KEYMAP_OUTPUT)/src/info_json_gz.h: $(INFO_JSON_FILES)
mkdir -p $(KEYMAP_OUTPUT)/src
$(QMK_BIN) info -f json -kb $(KEYBOARD) -km $(KEYMAP) | gzip -c9 > $(KEYMAP_OUTPUT)/src/info.json.gz
cd $(KEYMAP_OUTPUT)/src >/dev/null 2>&1 \
&& xxd -i info.json.gz info_json_gz.h \
&& cd - >/dev/null 2>&1

XAP_FILES := $(shell ls -1 data/xap/* | sort | xargs echo)

$(KEYMAP_OUTPUT)/src/xap_generated.inl: $(XAP_FILES)
$(QMK_BIN) xap-generate-qmk-inc -o "$(KEYMAP_OUTPUT)/src/xap_generated.inl"

$(KEYMAP_OUTPUT)/src/xap_generated.h: $(XAP_FILES)
$(QMK_BIN) xap-generate-qmk-h -o "$(KEYMAP_OUTPUT)/src/xap_generated.h" -kb $(KEYBOARD)

generated-files: $(KEYMAP_OUTPUT)/src/info_json_gz.h $(KEYMAP_OUTPUT)/src/xap_generated.inl $(KEYMAP_OUTPUT)/src/xap_generated.h

VPATH += $(KEYMAP_OUTPUT)/src
endif

include $(TMK_PATH)/protocol.mk
include $(TMK_PATH)/common.mk
include bootloader.mk
Expand Down
12 changes: 12 additions & 0 deletions common_features.mk
Original file line number Diff line number Diff line change
Expand Up @@ -718,3 +718,15 @@ ifeq ($(strip $(USBPD_ENABLE)), yes)
endif
endif
endif

ifeq ($(strip $(XAP_ENABLE)), yes)
ifeq ($(strip $(VIA_ENABLE)), yes)
$(error 'XAP_ENABLE = $(XAP_ENABLE)' deprecates 'VIA_ENABLE = $(VIA_ENABLE)'. Please set 'VIA_ENABLE = no')
endif

OPT_DEFS += -DXAP_ENABLE
DYNAMIC_KEYMAP_ENABLE := yes
EMBED_INFO_JSON := yes
VPATH += $(QUANTUM_DIR)/xap
SRC += $(QUANTUM_DIR)/xap/xap.c $(QUANTUM_DIR)/xap/xap_handlers.c
endif
178 changes: 178 additions & 0 deletions data/xap/xap_0.0.1.hjson
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
{
version: 0.0.1

// Needed for table generation
define: XAP_ROUTE

// Documentation section is used purely for `qmk xap-generate-docs`.
documentation: {
order: [
page_header
type_docs
!type_docs!
term_definitions
!term_definitions!
request_response
reserved_tokens
response_flags
!response_flags!
example_conversation
]

page_header:
'''
# QMK Firmware XAP Specs

This document describes the requirements of the QMK XAP ("extensible application protocol") API.
'''

type_docs:
'''
## Types

**All integral types are little-endian.**
'''

term_definitions:
'''
## Definitions

This list defines the terms used across the entire set of XAP protocol documentation.
'''

request_response:
'''
## Requests and Responses

Communication generally follows a request/response pattern.

Each request needs to include a _token_ -- this `u16` value prefixes each outbound request from the host application and its corresponding response, allowing repsonse messages to be correlated with their request, even if multiple host applications are communicating with the firmware simultaneously. Host applications should randomly generate a token ID for **every** outbound request, unless using a reserved token defined below.

This token is followed by a `u8` signifying the length of data in the request.
'''

// This documentation section reserved for next version
reserved_tokens: ''

response_flags:
'''
Response messages will always be prefixed by the originating request _token_, directly followed by that request's _response flags_, then the response payload length:
'''

example_conversation:
'''
### 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` |
'''
}

type_docs: {
u8:
'''
An unsigned 8-bit integral (octet, or byte), commonly seen as `uint8_t` from _stdint.h_.
'''
u16:
'''
An unsigned 16-bit integral, commonly seen as `uint16_t` from _stdint.h_.
'''
u32:
'''
An unsigned 32-bit integral, commonly seen as `uint32_t` from _stdint.h_.
'''
"type[n]":
'''
An array of `type`, with array extent of `N` -- e.g. `u8[2]` signifies two consecutive octets.
'''
}

term_definitions: {
Subsystem:
'''
A high-level area of functionality within XAP.
'''
ID:
'''
A single octet / 8-bit byte.
'''
Route:
'''
A sequence of _IDs_ describing the route to invoke a _handler_.
'''
Handler:
'''
A piece of code that is executed when a specific _route_ is received.
'''
Token:
'''
A `u16` associated with a specific request as well as its corresponding response.
'''
Response:
'''
The data sent back to the host during execution of a _handler_.
'''
"Response Flags":
'''
An `u8` containing the status of the request.
'''
Payload:
'''
Any received data appended to the _route_, which gets delivered to the _handler_ when received.
'''
}

response_flags: {
define_prefix: XAP_RESP
bits: {
0: {
name: Success
define: SUCCESS
description:
'''
When this bit is set, the request was successfully handled. If not set, all payload data should be disregarded, and the request retried if appropriate (with a new token).
'''
}
}
}

routes: {
0x00: {
type: router
name: XAP
define: XAP
description:
'''
This subsystem is always present, and provides the ability to query information about the XAP protocol of the connected device.
'''
routes: {
0x00: {
type: command
name: Version Query
define: VERSION_QUERY
description:
'''
XAP protocol version query.

* Returns the BCD-encoded version in the format of XX.YY.ZZZZ => `0xXXYYZZZZ`
* e.g. 3.2.115 will match `0x03020115`, or bytes {0x15,0x01,0x02,0x03}.
* Response:
* `u32` value.
'''
return_type: u32
return_purpose: bcd-version
return_constant: XAP_BCD_VERSION
}
}
}
}
}
Loading

0 comments on commit eba91c6

Please sign in to comment.