zvecr 3 years ago
parent
commit
1dbb4c0f96

+ 26 - 5
data/templates/xap/client/python/types.py.j2

@@ -2,10 +2,9 @@ from collections import namedtuple
 from enum import IntFlag, IntEnum
 from struct import Struct
 
-{% set type_definitions = [{'name':'XAPRequest', 'members': 'token length data', 'fmt':'<HB61s'}, {'name':'XAPResponse', 'members': 'token flags length data', 'fmt':'<HBB60s'}] %}
-{% for item in type_definitions -%}
-class {{ item.name }}(namedtuple('{{ item.name }}', '{{ item.members }}')):
-    fmt = Struct('{{ item.fmt }}')
+{% macro gen_struct(name, members, fmt) -%}
+class {{ name }}(namedtuple('{{ name }}', '{{ members }}')):
+    fmt = Struct('{{ fmt }}')
 
     def __new__(cls, *args):
         return super().__new__(cls, *args)
@@ -18,7 +17,29 @@ class {{ item.name }}(namedtuple('{{ item.name }}', '{{ item.members }}')):
         return self.fmt.pack(*list(self))
 
 
-{% endfor -%}
+{% endmacro -%}
+
+{% set type_definitions = [
+  {'name':'XAPRequest', 'members': 'token length data', 'fmt':'<HB61s'},
+  {'name':'XAPResponse', 'members': 'token flags length data', 'fmt':'<HBB60s'},
+  {'name':'XAPConfigRgblight', 'members': 'enable mode hue sat val speed', 'fmt':'<BBBBBB'}
+] %}
+{% for item in type_definitions -%}{{ gen_struct(item.name, item.members, item.fmt) }}{% endfor -%}
+
+# Spec structs
+{%- for item in xap.routes.values() recursive -%}
+    {%- if item.routes -%}
+        {{ loop(item.routes.values()) }}
+    {%- endif -%}
+    {% if item.request_struct_members %}
+# TODO: gen inbound object for {{ to_snake(item.define) }}
+    {%- endif -%}
+    {% if item.return_struct_members %}
+# TODO: gen outbound object for {{ to_snake(item.define) }}
+    {%- endif -%}
+{%- endfor %}
+
+
 class XAPSecureStatus(IntEnum):
     LOCKED = 0x00
     UNLOCKING = 0x01

+ 0 - 1
data/xap/xap_0.2.0.hjson

@@ -181,7 +181,6 @@
                 '''
                 This subsystem allows for control over the lighting subsystem.
                 '''
-            enable_if_preprocessor: defined(RGBLIGHT_ENABLE) || defined(RGB_MATRIX_ENABLE)
             routes: {
                 0x01: {
                     type: command

+ 78 - 0
data/xap/xap_0.3.0.hjson

@@ -0,0 +1,78 @@
+{
+    version: 0.3.0
+
+    routes: {
+
+        0x06: {
+            routes: {
+                0x03: {
+                    type: router
+                    name: rgblight
+                    define: RGBLIGHT
+                    description:
+                        '''
+                        This subsystem allows for control over the rgblight subsystem.
+                        '''
+                    enable_if_preprocessor: defined(RGBLIGHT_ENABLE)
+                    routes: {
+                        0x01: {
+                            type: command
+                            name: Capabilities Query
+                            define: CAPABILITIES_QUERY
+                            description:
+                                '''
+                                rgblight subsystem capabilities query. Each bit should be considered as a "usable" route within this subsystem.
+                                '''
+                            return_type: u32
+                            return_purpose: capabilities
+                            return_constant: XAP_ROUTE_LIGHTING_RGBLIGHT_CAPABILITIES
+                        }
+                        0x02: {
+                            type: command
+                            name: Get Enabled Effects
+                            define: GET_ENABLED_EFFECTS
+                            description: Each bit should be considered as a "usable" effect id
+                            return_type: u64
+                            return_constant: ENABLED_RGBLIGHT_EFFECTS
+                        }
+                        0x03: {
+                            type: command
+                            name: Get Config
+                            define: GET_CONFIG
+                            description: Query the current config.
+                            return_type: struct
+                            return_struct_length: 6
+                            return_struct_members: [
+                                {
+                                    type: u8
+                                    name: enable
+                                },
+                                {
+                                    type: u8
+                                    name: mode
+                                },
+                                {
+                                    type: u8
+                                    name: hue
+                                },
+                                {
+                                    type: u8
+                                    name: sat
+                                },
+                                {
+                                    type: u8
+                                    name: val
+                                },
+                                {
+                                    type: u8
+                                    name: speed
+                                },
+                            ]
+                            return_execute: get_rgblight_config
+                        }
+                    }
+                }
+            }
+        }
+    }
+}

+ 194 - 0
docs/xap_0.3.0.md

@@ -0,0 +1,194 @@
+# QMK Firmware XAP Specs
+
+This document describes the requirements of the QMK XAP ("extensible application protocol") API.
+
+## Types
+
+**All integral types are little-endian.**
+
+| Name | Definition |
+| -- | -- |
+| _struct{}_ | A structure of data, packing different objects together. Data is "compacted" -- there are no padding bytes between fields. Equivalent to a packed C-style `struct`. The order in which they're defined matches the order of the data in the response packet. |
+| _type[n]_ | An array of `type`, with array extent of `N` -- e.g. `u8[2]` signifies two consecutive octets. |
+| _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_. |
+| _u64_ | An unsigned 64-bit integral, commonly seen as `uint64_t` from _stdint.h_. |
+| _u8_ | An unsigned 8-bit integral (octet, or byte), commonly seen as `uint8_t` from _stdint.h_. |
+
+## Definitions
+
+This list defines the terms used across the entire set of XAP protocol documentation.
+
+| Name | Definition |
+| -- | -- |
+| _Capability_ | A way to determine if certain functionality is enabled in the firmware. Any _subsystem_ that provides build-time restriction of functionality must provide a _route_ for a _capabilities query_. |
+| _Handler_ | A piece of code that is executed when a specific _route_ is received. |
+| _Payload_ | Any received data appended to the _route_, which gets delivered to the _handler_ when received. |
+| _Response_ | The data sent back to the host during execution of a _handler_. |
+| _Route_ | A sequence of _IDs_ describing the route to invoke a _handler_. |
+| _Secure Route_ | A _route_ which has potentially destructive consequences, necessitating prior approval by the user before executing. |
+| _Subsystem_ | A high-level area of functionality within XAP. |
+| _Unlock sequence_ | A physical sequence initiated by the user to enable execution of  _secure routes_. |
+| _Broadcast Header_ | Packet format for broadcast messages. Takes the format:<br>`token` - token<br>`u8` - type<br>`u8` - length |
+| _ID_ | A single octet / 8-bit byte, representing Subsystem or Route index. |
+| _Request Header_ | Packet format for inbound data. Takes the format:<br>`token` - token<br>`u8` - length |
+| _Response Flags_ | An `u8` containing the status of the request. |
+| _Response Header_ | Packet format for outbound data. Takes the format:<br>`token` - token<br>`response_flags` - flags<br>`u8` - length |
+| _Token_ | A `u16` associated with a specific request as well as its corresponding response. Valid token values are within the range `0x0100`-`0xFFFF`. |
+
+## 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.
+This allows response 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.
+To ensure host interoperability, valid token values are within the range `0x0100`-`0xFFFF`.
+
+This token is followed by a `u8` signifying the length of data in the request.
+
+Two token values are reserved: `0xFFFE` and `0xFFFF`:
+* `0xFFFE`: A message sent by a host application may use this token if no response is to be sent -- a "fire and forget" message.
+* `0xFFFF`: Signifies a "broadcast" message sent by the firmware without prompting from the host application. Broadcast messages are defined later in this document.
+
+Any request will generate at least one corresponding response, with the exception of messages using reserved tokens. Maximum total message length is 128 bytes due to RAM constraints.
+
+Response messages will always be prefixed by the originating request _token_, directly followed by that request's _response flags_, then the response payload length:
+
+| Bit 7 | Bit 6 | Bit 5 | Bit 4 | Bit 3 | Bit 2 | Bit 1 | Bit 0 |
+| -- | -- | -- | -- | -- | -- | -- | -- |
+| `-` | `-` | `-` | `-` | `-` | `-` | `SECURE_FAILURE` | `SUCCESS` |
+
+* Bit 1 (`SECURE_FAILURE`): When this bit is set, the requested _route_ was marked _secure_ but an _unlock sequence_ has not completed.
+* Bit 0 (`SUCCESS`): 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).
+
+
+### 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 | Tags | Payloads | Description |
+| -- | -- | -- | -- | -- |
+| Version Query | `0x00 0x00` |  |__Response:__ `u32`| XAP protocol version query.<br><br>* Returns the BCD-encoded version in the format of XX.YY.ZZZZ => `0xXXYYZZZZ`<br>    * e.g. 3.2.115 will match `0x03020115`, or bytes {0x15,0x01,0x02,0x03}.|
+| Capabilities Query | `0x00 0x01` |  |__Response:__ `u32`| XAP subsystem capabilities query. Each bit should be considered as a "usable" route within this subsystem.|
+| Enabled subsystem query | `0x00 0x02` |  |__Response:__ `u32`| 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` |  |__Response:__ `u8`| Query secure route status<br><br>* 0 means secure routes are disabled<br>* 1 means unlock sequence initiated but incomplete<br>* 2 means secure routes are allowed<br>* any other value should be interpreted as disabled|
+| 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 | Tags | Payloads | Description |
+| -- | -- | -- | -- | -- |
+| Version Query | `0x01 0x00` |  |__Response:__ `u32`| QMK protocol version query.<br><br>* Returns the BCD-encoded version in the format of XX.YY.ZZZZ => `0xXXYYZZZZ`<br>    * e.g. 3.2.115 will match `0x03020115`, or bytes {0x15,0x01,0x02,0x03}.|
+| Capabilities Query | `0x01 0x01` |  |__Response:__ `u32`| QMK subsystem capabilities query. Each bit should be considered as a "usable" route within this subsystem.|
+| Board identifiers | `0x01 0x02` |  |__Response:__<br>&nbsp;&nbsp;&nbsp;&nbsp;* Vendor ID: `u16`<br>&nbsp;&nbsp;&nbsp;&nbsp;* Product ID: `u16`<br>&nbsp;&nbsp;&nbsp;&nbsp;* Product Version: `u16`<br>&nbsp;&nbsp;&nbsp;&nbsp;* QMK Unique Identifier: `u32`| Retrieves the set of identifying information for the board.|
+| Board Manufacturer | `0x01 0x03` |  |__Response:__ `string`| Retrieves the name of the manufacturer|
+| Product Name | `0x01 0x04` |  |__Response:__ `string`| Retrieves the product name|
+| Config Blob Length | `0x01 0x05` |  |__Response:__ `u16`| Retrieves the length of the configuration data bundled within the firmware|
+| Config Blob Chunk | `0x01 0x06` |  |__Request:__ `u16`<br><br>__Response:__ `u8[32]`| Retrieves a chunk of the configuration data bundled within the firmware|
+| Jump to bootloader | `0x01 0x07` | __Secure__ |__Response:__ `u8`| Jump to bootloader<br><br>May not be present – if QMK capabilities query returns “true”, then jump to bootloader is supported<br><br>* 0 means secure routes are disabled, and should be considered as a failure<br>* 1 means successful, board will jump to bootloader|
+| Hardware Identifier | `0x01 0x08` |  |__Response:__ `u32[4]`| Retrieves a unique identifier for the board.|
+
+### Keyboard - `0x02`
+This subsystem is always present, and reserved for vendor-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.
+
+
+### Keymap - `0x04`
+This subsystem allows for query of currently configured keycodes.
+
+
+| Name | Route | Tags | Payloads | Description |
+| -- | -- | -- | -- | -- |
+| Capabilities Query | `0x04 0x01` |  |__Response:__ `u32`| Keymap subsystem capabilities query. Each bit should be considered as a "usable" route within this subsystem.|
+| Get Layer Count | `0x04 0x02` |  |__Response:__ `u8`| Query maximum number of layers that can be addressed within the keymap.|
+| Get Keycode | `0x04 0x03` |  |__Request:__<br>&nbsp;&nbsp;&nbsp;&nbsp;* Layer: `u8`<br>&nbsp;&nbsp;&nbsp;&nbsp;* Row: `u8`<br>&nbsp;&nbsp;&nbsp;&nbsp;* Column: `u8`<br><br>__Response:__ `u16`| Query the Keycode at the requested location.|
+| Get Encoder Keycode | `0x04 0x04` |  |__Request:__<br>&nbsp;&nbsp;&nbsp;&nbsp;* Layer: `u8`<br>&nbsp;&nbsp;&nbsp;&nbsp;* Encoder: `u8`<br>&nbsp;&nbsp;&nbsp;&nbsp;* Clockwise: `u8`<br><br>__Response:__ `u16`| Query the Keycode at the requested location.|
+
+### Remapping - `0x05`
+This subsystem allows for live reassignment of keycodes without rebuilding the firmware.
+
+
+| Name | Route | Tags | Payloads | Description |
+| -- | -- | -- | -- | -- |
+| Capabilities Query | `0x05 0x01` |  |__Response:__ `u32`| Remapping subsystem capabilities query. Each bit should be considered as a "usable" route within this subsystem.|
+| Get Layer Count | `0x05 0x02` |  |__Response:__ `u8`| Query maximum number of layers that can be addressed within the keymap.|
+| Set Keycode | `0x05 0x03` | __Secure__ |__Request:__<br>&nbsp;&nbsp;&nbsp;&nbsp;* Layer: `u8`<br>&nbsp;&nbsp;&nbsp;&nbsp;* Row: `u8`<br>&nbsp;&nbsp;&nbsp;&nbsp;* Column: `u8`<br>&nbsp;&nbsp;&nbsp;&nbsp;* Keycode: `u16`| Modify the Keycode at the requested location.|
+| Set Encoder Keycode | `0x05 0x04` | __Secure__ |__Request:__<br>&nbsp;&nbsp;&nbsp;&nbsp;* Layer: `u8`<br>&nbsp;&nbsp;&nbsp;&nbsp;* Encoder: `u8`<br>&nbsp;&nbsp;&nbsp;&nbsp;* Clockwise: `u8`<br>&nbsp;&nbsp;&nbsp;&nbsp;* Keycode: `u16`| Modify the Keycode at the requested location.|
+
+### Lighting - `0x06`
+This subsystem allows for control over the lighting subsystem.
+
+
+| Name | Route | Tags | Payloads | Description |
+| -- | -- | -- | -- | -- |
+| Capabilities Query | `0x06 0x01` |  |__Response:__ `u32`| Lighting subsystem capabilities query. Each bit should be considered as a "usable" route within this subsystem.|
+
+#### rgblight - `0x06 0x03`
+This subsystem allows for control over the rgblight subsystem.
+
+| Name | Route | Tags | Payloads | Description |
+| -- | -- | -- | -- | -- |
+| Capabilities Query | `0x06 0x03 0x01` |  |__Response:__ `u32`| rgblight subsystem capabilities query. Each bit should be considered as a "usable" route within this subsystem.|
+| Get Enabled Effects | `0x06 0x03 0x02` |  |__Response:__ `u64`| Each bit should be considered as a "usable" effect id|
+| Get Config | `0x06 0x03 0x03` |  |__Response:__<br>&nbsp;&nbsp;&nbsp;&nbsp;* enable: `u8`<br>&nbsp;&nbsp;&nbsp;&nbsp;* mode: `u8`<br>&nbsp;&nbsp;&nbsp;&nbsp;* hue: `u8`<br>&nbsp;&nbsp;&nbsp;&nbsp;* sat: `u8`<br>&nbsp;&nbsp;&nbsp;&nbsp;* val: `u8`<br>&nbsp;&nbsp;&nbsp;&nbsp;* speed: `u8`| Query the current config.|
+
+
+## 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`(&nbsp;) | `0x51`(Q) | `0x4D`(M) | `0x4B`(K) | `0x21`(!) |
+### Secure Status - `0x01`
+Secure status has changed. Payloads include a `u8` matching a 'Secure Status' request.
+
+**Example Secure Status Broadcast** -- secure "Unlocking"
+
+| Byte | 0 | 1 | 2 | 3 |
+| --- | --- | --- | --- | --- |
+| **Purpose** | Token | Token | Broadcast Type | Secure Status |
+| **Value** | `0xFF` | `0xFF` | `0x01` | `0x01` |
+### Keyboard - `0x02`
+Reserved for vendor-specific functionality. No messages are defined by XAP.
+### User - `0x03`
+Reserved for user-specific functionality. No messages are defined by XAP.
+

+ 1 - 0
docs/xap_protocol.md

@@ -1,4 +1,5 @@
 <!-- This file is generated -->
+* [XAP Version 0.3.0](xap_0.3.0.md)
 * [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)

+ 9 - 1
lib/python/qmk/cli/xap/xap.py

@@ -7,7 +7,7 @@ from milc import cli
 from qmk.keyboard import render_layout
 from qmk.xap.common import get_xap_keycodes
 
-from xap_client import XAPClient, XAPEventType, XAPSecureStatus
+from xap_client import XAPClient, XAPEventType, XAPSecureStatus, XAPConfigRgblight
 
 KEYCODE_MAP = get_xap_keycodes('latest')
 
@@ -187,6 +187,14 @@ class XAPShell(cmd.Cmd):
             print('^C')
         return False
 
+    def do_dump(self, line):
+        ret = self.device.transaction(b'\x06\x03\x03')
+        ret = XAPConfigRgblight.from_bytes(ret)
+        print(ret)
+
+        ret = self.device.int_transaction(b'\x06\x03\x02')
+        print(f'XAPEffectRgblight(enabled={bin(ret)})')
+
 
 @cli.argument('-v', '--verbose', arg_only=True, action='store_true', help='Turns on verbose output.')
 @cli.argument('-d', '--device', help='device to select - uses format <pid>:<vid>.')

+ 2 - 1
lib/python/qmk/xap/common.py

@@ -7,6 +7,7 @@ from pathlib import Path
 from typing import OrderedDict
 from jinja2 import Environment, FileSystemLoader, select_autoescape
 
+from qmk.casing import to_snake
 from qmk.constants import QMK_FIRMWARE
 from qmk.json_schema import json_load, validate
 from qmk.decorators import lru_cache
@@ -24,7 +25,7 @@ def _get_jinja2_env(data_templates_xap_subdir: str):
 
 def render_xap_output(data_templates_xap_subdir, file_to_render, defs):
     j2 = _get_jinja2_env(data_templates_xap_subdir)
-    return j2.get_template(file_to_render).render(xap=defs, xap_str=hjson.dumps(defs))
+    return j2.get_template(file_to_render).render(xap=defs, xap_str=hjson.dumps(defs), to_snake=to_snake)
 
 
 def _find_kb_spec(kb):

+ 1 - 0
lib/python/xap_client/client.py

@@ -2,6 +2,7 @@
 # SPDX-License-Identifier: GPL-2.0-or-later
 from typing import List
 
+
 class XAPClient:
     """XAP device discovery
     """

+ 4 - 0
lib/python/xap_client/routes.py

@@ -61,3 +61,7 @@ class XAPRoutes():
     REMAPPING_SET_ENCODER_KEYCODE = b'\x05\x04'
     # LIGHTING
     LIGHTING_CAPABILITIES_QUERY = b'\x06\x01'
+    LIGHTING_RGBLIGHT = b'\x06\x03'
+    LIGHTING_RGBLIGHT_CAPABILITIES_QUERY = b'\x06\x03\x01'
+    LIGHTING_RGBLIGHT_GET_ENABLED_EFFECTS = b'\x06\x03\x02'
+    LIGHTING_RGBLIGHT_GET_CONFIG = b'\x06\x03\x03'

+ 23 - 0
lib/python/xap_client/types.py

@@ -59,6 +59,29 @@ class XAPResponse(namedtuple('XAPResponse', 'token flags length data')):
         return self.fmt.pack(*list(self))
 
 
+class XAPConfigRgblight(namedtuple('XAPConfigRgblight', 'enable mode hue sat val speed')):
+    fmt = Struct('<BBBBBB')
+
+    def __new__(cls, *args):
+        return super().__new__(cls, *args)
+
+    @classmethod
+    def from_bytes(cls, data):
+        return cls._make(cls.fmt.unpack(data))
+
+    def to_bytes(self):
+        return self.fmt.pack(*list(self))
+
+
+# Spec structs
+# TODO: gen outbound object for board_identifiers
+# TODO: gen inbound object for get_keymap_keycode
+# TODO: gen inbound object for get_encoder_keycode
+# TODO: gen inbound object for set_keymap_keycode
+# TODO: gen inbound object for set_encoder_keycode
+# TODO: gen outbound object for get_config
+
+
 class XAPSecureStatus(IntEnum):
     LOCKED = 0x00
     UNLOCKING = 0x01

+ 4 - 0
quantum/xap/xap.c

@@ -28,6 +28,10 @@ bool get_config_blob_chunk(uint16_t offset, uint8_t *data, uint8_t data_len) {
     return true;
 }
 
+// TODO: return actual values
+#define ENABLED_RGBLIGHT_EFFECTS 0xFFFFFFFF
+#define ENABLED_RGB_MATRIX_EFFECTS 0xFFFFFFFF
+
 #define QSTR2(z) #z
 #define QSTR(z) QSTR2(z)
 

+ 17 - 0
quantum/xap/xap_handlers.c

@@ -181,3 +181,20 @@ bool xap_respond_dynamic_encoder_set_keycode(xap_token_t token, const void *data
     return true;
 }
 #endif
+
+#if ((defined(RGBLIGHT_ENABLE)))
+extern rgblight_config_t rgblight_config;
+
+bool xap_respond_get_rgblight_config(xap_token_t token, const void *data, size_t length) {
+    xap_route_lighting_rgblight_get_config_t ret;
+
+    ret.enable = rgblight_config.enable;
+    ret.mode   = rgblight_config.mode;
+    ret.hue    = rgblight_config.hue;
+    ret.sat    = rgblight_config.sat;
+    ret.val    = rgblight_config.val;
+    ret.speed  = rgblight_config.speed;
+
+    return xap_respond_data(token, &ret, sizeof(ret));
+}
+#endif