mirror of
https://github.com/qmk/qmk_firmware.git
synced 2025-07-27 11:31:13 +00:00
switch
-based handlers.
This commit is contained in:
parent
0d6dbe4a5f
commit
e1202569ce
@ -106,61 +106,49 @@ static const {{ data.return_type | type_to_c_before }} {{ this_prefix_lc }}_data
|
|||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// Routes
|
// Routes
|
||||||
|
|
||||||
{% macro append_routing_table(prefix, container, route_stack) %}
|
{% macro append_routing_function(prefix, container, route_stack) %}
|
||||||
{% set this_route_stack = route_stack.copy() %}
|
{% set this_route_stack = route_stack.copy() %}
|
||||||
{{ this_route_stack.append(container) or '' }}
|
{{ this_route_stack.append(container) or '' }}
|
||||||
{% if 'routes' in container %}
|
{% if 'routes' in container %}
|
||||||
{% for route, data in container.routes | dictsort %}
|
{% for route, data in container.routes | dictsort %}
|
||||||
{% set this_prefix_uc = (prefix + '_' + data.define) | upper %}
|
{% set this_prefix_uc = (prefix + '_' + data.define) | upper %}
|
||||||
{% set this_prefix_lc = this_prefix_uc | lower %}
|
{% set this_prefix_lc = this_prefix_uc | lower %}
|
||||||
{{ append_routing_table(this_prefix_lc, data, this_route_stack) }}
|
{{ append_routing_function(this_prefix_lc, data, this_route_stack) }}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% call route_conditions(this_route_stack) %}
|
{% call route_conditions(this_route_stack) %}
|
||||||
static const xap_route_t {{ prefix | lower}}_table[] PROGMEM = {
|
bool {{ prefix | lower }}_route_handler(xap_token_t token, const uint8_t *data, size_t data_len) {
|
||||||
|
switch (data[0]) {
|
||||||
{% for route, data in container.routes | dictsort %}
|
{% for route, data in container.routes | dictsort %}
|
||||||
{% set inner_route_stack = this_route_stack.copy() %}
|
{% set inner_route_stack = this_route_stack.copy() %}
|
||||||
{{ inner_route_stack.append(data) or '' }}
|
{{ inner_route_stack.append(data) or '' }}
|
||||||
{% if 'permissions' in data %}
|
|
||||||
{% set secure_status = 'ROUTE_PERMISSIONS_SECURE' %}
|
|
||||||
{% else %}
|
|
||||||
{% set secure_status = 'ROUTE_PERMISSIONS_INSECURE' %}
|
|
||||||
{% endif %}
|
|
||||||
{% call route_conditions(inner_route_stack) %}
|
{% call route_conditions(inner_route_stack) %}
|
||||||
[{{ prefix | upper }}_{{ data.define }}] = {
|
case {{ prefix | upper }}_{{ data.define }}:
|
||||||
{% if 'routes' in data %}
|
{
|
||||||
.flags = {
|
{% if 'permissions' in data %}
|
||||||
.type = XAP_ROUTE,
|
if(xap_ensure_unlocked(token)) { return true; } // Route requires secure unlock
|
||||||
.secure = {{ secure_status }},
|
{% else %}
|
||||||
},
|
secure_activity_event();
|
||||||
.child_routes = {{ prefix | lower }}_{{ data.define | lower }}_table,
|
{% endif %}
|
||||||
.child_routes_len = sizeof({{ prefix | lower }}_{{ data.define | lower }}_table)/sizeof(xap_route_t),
|
{% if 'routes' in data %}
|
||||||
{% elif 'return_execute' in data %}
|
extern bool {{ prefix | lower }}_{{ data.define | lower }}_route_handler(xap_token_t token, const uint8_t *data, size_t data_len);
|
||||||
.flags = {
|
return {{ prefix | lower }}_{{ data.define | lower }}_route_handler(token, &data[1], data_len - 1);
|
||||||
.type = XAP_EXECUTE,
|
{% elif 'return_execute' in data %}
|
||||||
.secure = {{ secure_status }},
|
return xap_respond_{{ data.return_execute | lower }}(token, &data[1], data_len - 1);
|
||||||
},
|
{% elif 'return_constant' in data and data.return_type == 'string' %}
|
||||||
.handler = xap_respond_{{ data.return_execute | lower }},
|
return xap_respond_data_P(token, {{ prefix | lower }}_{{ data.define | lower }}_str, sizeof({{ prefix | lower }}_{{ data.define | lower }}_str) - 1);
|
||||||
{% elif 'return_constant' in data and data.return_type == 'string' %}
|
{% elif 'return_constant' in data %}
|
||||||
.flags = {
|
return xap_respond_data(token, &{{ prefix | lower }}_{{ data.define | lower }}_data, sizeof({{ prefix | lower }}_{{ data.define | lower }}_data));
|
||||||
.type = XAP_CONST_MEM,
|
{% endif %}
|
||||||
.secure = {{ secure_status }},
|
}
|
||||||
},
|
|
||||||
.const_data = {{ prefix | lower }}_{{ data.define | lower }}_str,
|
|
||||||
.const_data_len = sizeof({{ prefix | lower }}_{{ data.define | lower }}_str) - 1,
|
|
||||||
{% elif 'return_constant' in data %}
|
|
||||||
.flags = {
|
|
||||||
.type = XAP_CONST_MEM,
|
|
||||||
.secure = {{ secure_status }},
|
|
||||||
},
|
|
||||||
.const_data = &{{ prefix | lower }}_{{ data.define | lower }}_data,
|
|
||||||
.const_data_len = sizeof({{ prefix | lower }}_{{ data.define | lower }}_data),
|
|
||||||
{% endif %}
|
|
||||||
},
|
|
||||||
{% endcall %}
|
{% endcall %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
};
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
{% endcall %}
|
{% endcall %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endmacro %}
|
{% endmacro %}
|
||||||
|
|
||||||
{{ append_routing_table("xap_route", xap, []) }}
|
{{ append_routing_function("xap_route", xap, []) }}
|
||||||
|
@ -49,61 +49,9 @@ bool get_config_blob_chunk(uint16_t offset, uint8_t *data, uint8_t data_len) {
|
|||||||
# define ENABLED_BACKLIGHT_EFFECTS 0b00000000
|
# define ENABLED_BACKLIGHT_EFFECTS 0b00000000
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define QSTR2(z) #z
|
bool xap_ensure_unlocked(xap_token_t token) {
|
||||||
#define QSTR(z) QSTR2(z)
|
|
||||||
|
|
||||||
typedef enum xap_route_type_t {
|
|
||||||
XAP_UNUSED = 0, // "Unused" needs to be zero -- undefined routes (through preprocessor) will be skipped
|
|
||||||
XAP_ROUTE,
|
|
||||||
XAP_EXECUTE,
|
|
||||||
XAP_VALUE,
|
|
||||||
XAP_CONST_MEM,
|
|
||||||
TOTAL_XAP_ROUTE_TYPES
|
|
||||||
} xap_route_type_t;
|
|
||||||
|
|
||||||
#define XAP_ROUTE_TYPE_BIT_COUNT 3
|
|
||||||
|
|
||||||
typedef enum xap_route_secure_t {
|
|
||||||
ROUTE_PERMISSIONS_INSECURE,
|
|
||||||
ROUTE_PERMISSIONS_SECURE,
|
|
||||||
} xap_route_secure_t;
|
|
||||||
|
|
||||||
#define XAP_ROUTE_SECURE_BIT_COUNT 2
|
|
||||||
|
|
||||||
typedef struct __attribute__((packed)) xap_route_flags_t {
|
|
||||||
xap_route_type_t type : XAP_ROUTE_TYPE_BIT_COUNT;
|
|
||||||
xap_route_secure_t secure : XAP_ROUTE_SECURE_BIT_COUNT;
|
|
||||||
} xap_route_flags_t;
|
|
||||||
|
|
||||||
_Static_assert(TOTAL_XAP_ROUTE_TYPES <= (1 << (XAP_ROUTE_TYPE_BIT_COUNT)), "Number of XAP route types is too large for XAP_ROUTE_TYPE_BITS.");
|
|
||||||
_Static_assert(sizeof(xap_route_flags_t) == 1, "xap_route_flags_t is not length of 1");
|
|
||||||
|
|
||||||
typedef struct xap_route_t xap_route_t;
|
|
||||||
struct __attribute__((packed)) xap_route_t {
|
|
||||||
const xap_route_flags_t flags;
|
|
||||||
union {
|
|
||||||
// XAP_ROUTE
|
|
||||||
struct {
|
|
||||||
const xap_route_t *child_routes;
|
|
||||||
const uint8_t child_routes_len;
|
|
||||||
};
|
|
||||||
|
|
||||||
// XAP_EXECUTE
|
|
||||||
bool (*handler)(xap_token_t token, const uint8_t *data, size_t data_len);
|
|
||||||
|
|
||||||
// XAP_VALUE / XAP_CONST_MEM
|
|
||||||
struct {
|
|
||||||
const void * const_data;
|
|
||||||
const uint8_t const_data_len;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
#include <xap_generated.inl>
|
|
||||||
|
|
||||||
bool xap_pre_execute_route(xap_token_t token, const xap_route_t *route) {
|
|
||||||
#ifdef SECURE_ENABLE
|
#ifdef SECURE_ENABLE
|
||||||
if (!secure_is_unlocked() && (route->flags.secure == ROUTE_PERMISSIONS_SECURE)) {
|
if (!secure_is_unlocked()) {
|
||||||
xap_respond_failure(token, XAP_RESPONSE_FLAG_SECURE_FAILURE);
|
xap_respond_failure(token, XAP_RESPONSE_FLAG_SECURE_FAILURE);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -114,50 +62,15 @@ bool xap_pre_execute_route(xap_token_t token, const xap_route_t *route) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void xap_execute_route(xap_token_t token, const xap_route_t *routes, size_t max_routes, const uint8_t *data, size_t data_len) {
|
#define QSTR2(z) #z
|
||||||
if (data_len == 0) return;
|
#define QSTR(z) QSTR2(z)
|
||||||
xap_identifier_t id = data[0];
|
|
||||||
|
|
||||||
if (id < max_routes) {
|
#include <xap_generated.inl>
|
||||||
xap_route_t route;
|
|
||||||
memcpy_P(&route, &routes[id], sizeof(xap_route_t));
|
|
||||||
|
|
||||||
if (xap_pre_execute_route(token, &route)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (route.flags.type) {
|
|
||||||
case XAP_ROUTE:
|
|
||||||
if (route.child_routes != NULL && route.child_routes_len > 0 && data_len > 0) {
|
|
||||||
xap_execute_route(token, route.child_routes, route.child_routes_len, &data[1], data_len - 1);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case XAP_EXECUTE:
|
|
||||||
if (route.handler != NULL) {
|
|
||||||
bool ok = (route.handler)(token, data_len == 1 ? NULL : &data[1], data_len - 1);
|
|
||||||
if (ok) return;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case XAP_VALUE:
|
|
||||||
xap_respond_data(token, route.const_data, route.const_data_len);
|
|
||||||
return;
|
|
||||||
|
|
||||||
case XAP_CONST_MEM:
|
|
||||||
xap_respond_data_P(token, route.const_data, route.const_data_len);
|
|
||||||
return;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Nothing got handled, so we respond with failure.
|
|
||||||
xap_respond_failure(token, XAP_RESPONSE_FLAG_FAILED);
|
|
||||||
}
|
|
||||||
|
|
||||||
void xap_receive(xap_token_t token, const uint8_t *data, size_t length) {
|
void xap_receive(xap_token_t token, const uint8_t *data, size_t length) {
|
||||||
xap_execute_route(token, xap_route_table, sizeof(xap_route_table) / sizeof(xap_route_t), data, length);
|
extern bool xap_route_route_handler(xap_token_t token, const uint8_t *data, size_t data_len);
|
||||||
|
if (!xap_route_route_handler(token, data, length)) {
|
||||||
|
// Nothing got handled, so we respond with failure.
|
||||||
|
xap_respond_failure(token, XAP_RESPONSE_FLAG_FAILED);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user