Configurator API Doc
ClickUp export may have caused formatting errors
The configurator interface uses an HID output interrupt endpoint over USB to communicate with the host. 64-byte raw reports are sent from the host over the output endpoint, and the firmware responds by returning the same 64-byte report, but with some bytes changed as appropriate for returning results.
Conventions
- All reports are 64 bytes long. If fewer bytes are required, the remainder of the report must be zero-padded to 64 bytes.
- Byte ordering is little-endian unless otherwise specified, and values are unsigned unless otherwise specified.
- Errors are usually indicated by replacing some or all bytes in the response report with
0xFF
. Though there are legitimate uses of0xFF
bytes in responses, if unexpected fields in the response are replaced with0xFF
, the sender should assume the report generated an error.
Constructing Reports
Currently (may change; this interface is under active development and suggestions are welcome), all interactions in raw reports are initiated by the host.
Reports are of the form:
command byte
- argument bytes
- zero-padding
Command bytes currently implemented:
0x01
- Get Interface Version (no args)0x02
- Set LED (two args - LED number, LED state)0x03
- Get Keymap Length (no args) - returns number of physical keys0x04
- Get Layers (see below)0x05
- Get Behaviors0x06
- Remap Key0x07
- Get Map for Key0x08
- Get number of keymaps0x09
- switch active keymap
API should match the functional spec:
- Device Settings
- Layers and Keymaps
- Macros
- Lighting
- Reserved
Example
To get the interface version supported by the attached keyboard, the host would
send a report containing the following bytes:
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
And the keyboard would respond with this report:
01 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
…indicating that the version supported is Version 01.
Similarly, the following report would tell the keyboard to set led 7 to on
(0x01
):
02 07 01 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
In this case, the command is 0x02
, the first arg (LED number) is 0x07
, and
the second arg (state) is 0x01
- the rest of the bytes are ignored. The keyboard
should respond with the exact same report:
02 07 01 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
…and switch on LED 7. NOTE: the LED mapping of the keyboard for this test
command is strictly according to how the LED matrix chip is wired, and does not
correspond to any particular key. LED “7” in this case, for the V3 keyboard,
turns out to be the Blue LED on the key in the lower left-hand corner.
Command documentation
Command | Arguments | response | Notes |
---|---|---|---|
0x01 | none | byte 1 changed - version number | This command guaranteed not to change |
0x02 | 2 bytes | unchanged report | byte 1 == LED, byte 2 == state |
0x03 | none | byte 1 changed - number of keys | |
0x04 | 1 byte | 1+ bytes | see below |
0x05 | 1 byte | 1+ bytes | see below |
0x06 | 11 bytes | position, layer, behavior index, param1 (4), param2 (4) | |
0x07 | 1 byte | 1 byte + (num layers * 10) bytes | see below |
0x08 | none | 1 byte | number of keymaps supported |
0x09 | 1 byte | byte unchanged or 0xFF | switch active keymap |
Device Settings
0x01 - GET protocol version
Description:
This command takes no arguments, and returns a version number. Right now,
that will be a single byte representing what version of this interface the caller
should expect to deal with. Version 1 is currently the ONLY version, but that
may change in the future. The returned report will be identical to the sent
report, except for byte 1, which will be the version number.
Arguments: none
Response Format:
Request Example:
0xXX - GET model SKU
Description: Returns the device’s model number
Arguments: none
Response Format:
Example:
Riven Non-Split Non-RGB v0 Black: 00-00-00-FF
Riven Split RGB v2 White: 00-32-01-FF
0xXX - GET serial number
Description: Returns the device’s serial number
Arguments: none
Response Format:
Example:
00-32-01-FF-00-00-0B-44-22-11-85-51-57-F8-A1
0xXX - GET firmware version
Description: Returns the currently running firmware version
Arguments: none
Response Format:
Example:
1.0.1 non split: 01-00-01
Left 1.0.1 Right 1.0.2 01-00-01-01-00-02
0xXX - GET battery info
Description: Returns battery charge status and voltage in millivolts
Arguments:
Response Format: x bytes - ADC value
Example:
Full battery at 4.05V 0x01-0x00-0x00-0x0F-0xD2
Good battery at 3.98V 0x01-0x00-0x00-0x0F-0x8C
Layers and Keymaps
User Cases: in each of these cases, we demonstrate the Web Configurator querying the Keyboard for which version of the interface it supports. In reality, this only needs to be done once per session, or if the Web Configurator has some reason to believe it has changed since the last time. Same with queries for the number of physical keys, or the number of layers, or the number of keymaps.
User Case 1: When the Keyboard is connected to the Web Configurator, the Web Configurator is able to set the current active keymap
Configurator sends:
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Keyboard returns:
01 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[Version 1 of protocol - update this doc for version 2]
Configurator sends:
08 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Keyboard returns:
08 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[4 keymaps supported]
Configurator sends:
09 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Keyboard returns:
09 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[Keymap 02 is active]
User Case 2: When the Keyboard is connected to the Web Configurator, the Web Configurator is able to set the active layer of the active keymap
“Active layer” does not make sense - multiple layers can be active at a time. Not clear that this is a thing (which layers are active) which needs to be communicated to configurator. I’m currently thinking this one through
User Case 3: When the Keyboard is connected to the Web Configurator, the Web Configurator is able to display the key bindings (behaviors) of a specific key for each layer
Configurator sends:
01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Keyboard returns:
01 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[Version 1 of protocol - update this doc for version 2]
Configurator sends:
03 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Keyboard returns:
03 48 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[0x48 physical keys - 72 keys. This is a V3 prototype board]
Configurator sends:
04 FF 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Keyboard returns:
04 05 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[keymaps have 5 layers]
Configurator sends:
05 FF 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Keyboard returns:
05 06 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[firmware supports 6 behaviors]
Configurator sends:
05 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Keyboard returns:
05 00 4B 45 59 5F 50 52 45 53 53 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[behavior 0 is “KEY_PRESS”]
05 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
05 01 54 52 41 4E 53 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[behavior 1 is “TRANS”]
05 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
05 02 4D 4F 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[behavior 2 is “MO”]
05 03 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
05 03 54 4F 47 47 4C 45 5F 4C 41 59 45 52 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[behavior 3 - “TOGGLE_LAYER”]
05 04 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
05 04 42 4C 55 45 54 4F 4F 54 48 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[behavior 4 - “BLUETOOTH”]
05 05 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
05 05 4C 45 44 5F 54 4F 47 47 4C 45 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[behavior 5 - “LED_TOGGLE”]
Configurator sends:
07 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[“get map for physical key 0”]
Keyboard returns:
07 00 00 03 01 00 00 00 00 00 00 00 01 01 00 00 00 00 00 00 00 00 02 01 00 00 00 00 00 00 00 00 03 01 00 00 00 00 00 00 00 00 04 05 63 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
[07 00 - answer for “get map” “key 0”
NOTE: “param0” and “param1” are 32-bit (4 byte) little-endian values.
00 03 01 00 00 00 00 00 00 00 - layer=0, behavior=3, param0=1, param1=0
01 01 00 00 00 00 00 00 00 00 - layer=1, behavior=1, param0=0, param1=0
02 01 00 00 00 00 00 00 00 00 - layer=2, behavior=1, param0=0, param1=0
03 01 00 00 00 00 00 00 00 00 - layer=3, behavior=1, param0=0, param1=0
04 05 63 00 00 00 00 00 00 00 - layer=4, behavior=5, param0=99, param1=0
00 00 00 00 00 00 00 00 00 00 00 00 - PADDING
]
User Case 4: When the Keyboard is connected to the Web Configurator, the Web Configurator is able to remap the current key binding (behavior) to another key code
0xXX - GET keymap name based on index
Description: Returns keymap name string based on index
Arguments: index
Response Format:
Request Example:
0xXX - GET keymap
Description: Returns keymap data object by ID
Arguments:
Response Format:
Request Example:
0x03 - get keymap length
This command returns the number of physical key positions in the keymap in the
first byte. All other byte positions left unchanged.
0x04 - get layers
Depending on the contents of byte 1, this command returns either the number
of layers built into the firmware (if byte 1 is 0xFF
, byte 1 gets replaced
with the number of layers) or a null-terminated string representing the
name of the layer of that index. If there is no such layer, the report
is returned unchanged. XXX - this is currently broken - the number
of layers gets returned, but the layer names don’t
0x05 - get behaviors
Depending on the contents of byte 1, this command returns either the number
of ZMK “behaviors” built into
the firmware (if byte 1 is 0xFF
, byte 1 is replaced with the number of
behaviors) or a null-terminated string representing the name of the behavior
at that index number.
0x06 - remap key
Note: key remapping affects the currently-active map.
This command affects the active keymap, and takes the following arguments:
- byte 1: key position to remap
- byte 2: layer of map to change for position
- byte 3: index of behavior to assign to key
- byte 4-7: little-endian 32-bit value for
param1
of behavior - byte 8-11: little-ending 32-bit value for
param2
of behavior
See ZMK behavior documentation for
more information on behaviors and values for the parameters.
If any parameters are invalid (bad position, layer, or index value), the
report returned will have all 11 bytes replaced with 0xFF
. Otherwise,
the report is returned unchanged.
0x07 - get key map
Note: this can only retrieve info for the currently-active map
This command takes one byte as input - the key position to retrieve mapping information from. If the key position is invalid, a report with all bytes except the command replaced with
0xFF
is returned. Otherwise, 10 bytes per layer is returned (keeping the key position in byte 1):
- 1 byte for layer number
- 1 byte for behavior index number
- 4 bytes for little-endian 32-bit
param1
value - 4 bytes for little-endian 32-bit
param2
value
To know how many layers to expect, use command 0x04
- “get layers”.
0x08 - get maps
This command takes no arguments, and returns the number of keymaps supported
by this firmware in byte 1.
0x09 - switch active keymap
This command expects the number of the map to make active in byte 1. If
the map number supplied is invalid, it is replaced with 0xFF
, otherwise
the report is returned unchanged.
0xXX - SET keymap definition
Description: Set keymap definition
Arguments: keymap data object
Response Format:
Request Example:
0xXX - SET active keymap
Description: Set active keymap by ID
Arguments:
Response Format:
Request Example:
Macros
Definition of Macro Behavior
0xXX - GET list of macros
Description: Returns list of macro IDs
Arguments:
Response Format:
Request Example:
0xXX - GET macro definition
Description: Returns macro data object by ID
Arguments:
Response Format:
Request Example:
0xXX - SET macro definition
Description: Persist macro definition, returns macro ID
Arguments:
Response Format:
Request Example:
0xXX - DELETE macro definition
Description: Remove macro by ID
Arguments:
Response Format:
Request Example:
Lighting
RGB LED behavior
0x30 - GET list of lighting patterns
Description: Returns list of lighting patterns IDs
Arguments:
Response Format:
Request Example:
0x31 - SET lighting pattern
Description: Persist lighting pattern and return pattern ID
Arguments:
Response Format:
Request Example:
0x32 - SET active lighting pattern
Description: Set active lighting pattern
Arguments:
Response Format:
Request Example:
0x02 - set led
This is primarily an example, testing-only command. You can turn individual LEDs
off or on by setting the state to zero or non-zero, respectively. The returned
report will ALWAYS be identical to the sent report.