diff --git a/data/templates/xap/client/python/routes.py.j2 b/data/templates/xap/client/python/routes.py.j2
index 7eb6a5bde2e..3cd65912e76 100644
--- a/data/templates/xap/client/python/routes.py.j2
+++ b/data/templates/xap/client/python/routes.py.j2
@@ -9,6 +9,11 @@ class XAPRoutes():
# {{route.define}}
{%- for subid, subroute in route.routes | dictsort %}
{{route.define}}_{{subroute.define}} = b'\x{{ '%02d' % id|int(base=16) }}\x{{ '%02d' % subid|int(base=16) }}'
+{%- if subroute.routes %}
+{%- for subsubid, subsubroute in subroute.routes | dictsort %}
+ {{route.define}}_{{subroute.define}}_{{subsubroute.define}} = b'\x{{ '%02d' % id|int(base=16) }}\x{{ '%02d' % subid|int(base=16) }}\x{{ '%02d' % subsubid|int(base=16) }}'
+{%- endfor %}
+{%- endif %}
{%- endfor %}
{%- endif %}
{%- endfor %}
\ No newline at end of file
diff --git a/data/templates/xap/docs/route_request.md.j2 b/data/templates/xap/docs/route_request.md.j2
index fd8b81ee163..8d9c1fd37db 100644
--- a/data/templates/xap/docs/route_request.md.j2
+++ b/data/templates/xap/docs/route_request.md.j2
@@ -1,8 +1,8 @@
-{%- if subroute.request_type == 'struct' -%}
+{%- if route.request_type == 'struct' -%}
__Request:__
-{%- for member in subroute.request_struct_members -%}
+{%- for member in route.request_struct_members -%}
{{ " "|safe*4 }}* {{ member.name }}: `{{ member.type }}`
{%- endfor -%}
-{%- elif subroute.request_type -%}
-__Request:__ `{{ subroute.request_type }}`
+{%- elif route.request_type -%}
+__Request:__ `{{ route.request_type }}`
{%- endif -%}
\ No newline at end of file
diff --git a/data/templates/xap/docs/route_response.md.j2 b/data/templates/xap/docs/route_response.md.j2
index 58af87d4675..64f4e065e08 100644
--- a/data/templates/xap/docs/route_response.md.j2
+++ b/data/templates/xap/docs/route_response.md.j2
@@ -1,8 +1,8 @@
-{%- if subroute.return_type == 'struct' -%}
+{%- if route.return_type == 'struct' -%}
__Response:__
-{%- for member in subroute.return_struct_members -%}
+{%- for member in route.return_struct_members -%}
{{ " "|safe*4 }}* {{ member.name }}: `{{ member.type }}`
{%- endfor -%}
-{%- elif subroute.return_type -%}
-__Response:__ `{{ subroute.return_type }}`
+{%- elif route.return_type -%}
+__Response:__ `{{ route.return_type }}`
{%- endif -%}
\ No newline at end of file
diff --git a/data/templates/xap/docs/routes.md.j2 b/data/templates/xap/docs/routes.md.j2
index 791eaac5643..4c6edee210f 100644
--- a/data/templates/xap/docs/routes.md.j2
+++ b/data/templates/xap/docs/routes.md.j2
@@ -6,7 +6,29 @@
| Name | Route | Tags | Payloads | Description |
| -- | -- | -- | -- | -- |
{%- for subid, subroute in route.routes | dictsort %}
+{%- if not subroute.routes %}
+{%- with route=subroute %}
| {{ subroute.name }} | `{{ id }} {{ subid }}` | {% if 'secure' == subroute.permissions %}__Secure__{% endif %} | {%- include 'route_request.md.j2' -%}{%- if subroute.return_type and subroute.request_type -%}
{% endif %}{%- include 'route_response.md.j2' -%} | {{ subroute.description.replace('\n', '
') }}|
+{%- endwith %}
+{%- endif %}
+{%- endfor %}
+
+{%- for subid, subroute in route.routes | dictsort %}
+{%- if subroute.routes %}
+
+#### {{ subroute.name }} - `{{ id }} {{ subid }}`
+{{ subroute.description }}
+
+| Name | Route | Tags | Payloads | Description |
+| -- | -- | -- | -- | -- |
+{%- for subsubid, subsubroute in subroute.routes | dictsort %}
+{%- if not subsubroute.routes %}
+{%- with route=subsubroute %}
+| {{ subsubroute.name }} | `{{ id }} {{ subid }} {{ subsubid }}` | {% if 'secure' == subsubroute.permissions %}__Secure__{% endif %} | {%- include 'route_request.md.j2' -%}{%- if subsubroute.return_type and subsubroute.request_type -%}
{% endif %}{%- include 'route_response.md.j2' -%} | {{ subsubroute.description.replace('\n', '
') }}|
+{%- endwith %}
+{%- endif %}
+{%- endfor %}
+{%- endif %}
{%- endfor %}
{% endif %}
{%- endfor %}
diff --git a/lib/python/qmk/xap/gen_firmware/inline_generator.py b/lib/python/qmk/xap/gen_firmware/inline_generator.py
index f8291b5e06a..9d0a6ed54c9 100755
--- a/lib/python/qmk/xap/gen_firmware/inline_generator.py
+++ b/lib/python/qmk/xap/gen_firmware/inline_generator.py
@@ -53,6 +53,8 @@ def _get_route_type(container):
return 'XAP_CONST_MEM'
elif container['return_type'] == 'u32':
return 'XAP_CONST_MEM'
+ elif container['return_type'] == 'u64':
+ return 'XAP_CONST_MEM'
elif container['return_type'] == 'struct':
return 'XAP_CONST_MEM'
elif container['return_type'] == 'string':
@@ -98,6 +100,11 @@ def _append_routing_table_declaration(lines, container, container_id, route_stac
lines.append('')
lines.append(f'static const uint32_t {route_name}_data PROGMEM = {constant};')
+ elif container['return_type'] == 'u64':
+ constant = container['return_constant']
+ lines.append('')
+ lines.append(f'static const uint64_t {route_name}_data PROGMEM = {constant};')
+
elif container['return_type'] == 'struct':
lines.append('')
lines.append(f'static const {route_name}_t {route_name}_data PROGMEM = {{')
@@ -196,6 +203,8 @@ def _append_routing_table_entry(lines, container, container_id, route_stack):
_append_routing_table_entry_const_data(lines, container, container_id, route_stack)
elif container['return_type'] == 'u32':
_append_routing_table_entry_const_data(lines, container, container_id, route_stack)
+ elif container['return_type'] == 'u64':
+ _append_routing_table_entry_const_data(lines, container, container_id, route_stack)
elif container['return_type'] == 'struct':
_append_routing_table_entry_const_data(lines, container, container_id, route_stack)
elif container['return_type'] == 'string':
diff --git a/lib/python/xap_client/device.py b/lib/python/xap_client/device.py
index b26276251ba..8196b6517e4 100644
--- a/lib/python/xap_client/device.py
+++ b/lib/python/xap_client/device.py
@@ -147,8 +147,12 @@ class XAPDevice(XAPDeviceBase):
XAPRouteError: Access to invalid route attempted
"""
# TODO: Remove assumption that capability is always xx01
- (sub, rt) = route
- cap = bytes([sub, 1])
+ (remain, sub, rt) = (route[:-2], route[-2], route[-1])
+ cap = remain + bytes([sub, 1])
+
+ # recurse for nested routes
+ if remain:
+ self._ensure_route(remain + bytes([sub]))
if self.subsystems() & (1 << sub) == 0:
raise XAPRouteError("subsystem not available")