Skip to content

Commit

Permalink
refactor: Move studio RPC to nanopb messages.
Browse files Browse the repository at this point in the history
* Protocol Buffers are way more widely supported CBOR with CDDL,
  so switch to that message encoding.
  • Loading branch information
petejohanson committed Mar 13, 2024
1 parent 03011e7 commit a55de93
Show file tree
Hide file tree
Showing 14 changed files with 246 additions and 103 deletions.
15 changes: 13 additions & 2 deletions app/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,19 @@ target_sources(app PRIVATE src/main.c)

add_subdirectory(src/display/)

add_subdirectory(proto/)
if(CONFIG_ZMK_STUDIO)
if (CONFIG_ZMK_STUDIO)
# For some reason this is failing if run from a different sub-file.
list(APPEND CMAKE_MODULE_PATH ${ZEPHYR_BASE}/modules/nanopb)

include(nanopb)

zephyr_nanopb_sources(app
proto/zmk/studio.proto
proto/zmk/core.proto
proto/zmk/behaviors.proto
proto/zmk/keymap.proto
)

add_subdirectory(src/studio)
endif()

Expand Down
59 changes: 33 additions & 26 deletions app/include/zmk/studio/rpc.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@
#pragma once

#include <zephyr/sys/iterable_sections.h>
#include <studio-msgs_types.h>

#include <proto/zmk/studio-msgs.pb.h>

struct zmk_rpc_subsystem;

typedef struct response_r(subsystem_func)(const struct zmk_rpc_subsystem *subsys,
const struct request *req);
typedef zmk_Response(subsystem_func)(const struct zmk_rpc_subsystem *subsys,
const zmk_Request *req);

typedef struct response_r(rpc_func)(const struct request *req);
typedef zmk_Response(rpc_func)(const zmk_Request *neq);

struct zmk_rpc_subsystem {
subsystem_func *func;
Expand All @@ -25,48 +26,54 @@ struct zmk_rpc_subsystem_handler {
};

#define ZMK_RPC_SUBSYSTEM(prefix) \
struct response_r subsystem_func_##prefix(const struct zmk_rpc_subsystem *subsys, \
const struct request *req) { \
uint8_t choice = req->prefix##_subsystem_m.prefix##_request_m.prefix##_request_choice; \
zmk_Response subsystem_func_##prefix(const struct zmk_rpc_subsystem *subsys, \
const zmk_Request *req) { \
uint8_t which_req = req->subsystem.prefix.which_request_type; \
LOG_DBG("Got subsystem func for %d", subsys->subsystem_choice); \
\
for (int i = subsys->handlers_start_index; i <= subsys->handlers_end_index; i++) { \
struct zmk_rpc_subsystem_handler *sub_handler; \
STRUCT_SECTION_GET(zmk_rpc_subsystem_handler, i, &sub_handler); \
if (sub_handler->request_choice == choice) { \
if (sub_handler->request_choice == which_req) { \
return sub_handler->func(req); \
} \
} \
LOG_ERR("No handler func found for %d", choice); \
return (struct response_r){}; \
LOG_ERR("No handler func found for %d", which_req); \
zmk_Response fallback_resp = zmk_Response_init_zero; \
return fallback_resp; \
} \
STRUCT_SECTION_ITERABLE(zmk_rpc_subsystem, prefix##_subsystem) = { \
.func = subsystem_func_##prefix, \
.subsystem_choice = request_union_##prefix##_subsystem_m_c, \
.subsystem_choice = zmk_Request_##prefix##_tag, \
};

#define ZMK_RPC_SUBSYSTEM_HANDLER(prefix, request_choice_val, func_val) \
#define ZMK_RPC_SUBSYSTEM_HANDLER(prefix, request_id) \
STRUCT_SECTION_ITERABLE(zmk_rpc_subsystem_handler, \
prefix##_subsystem_handler_##request_choice_val) = { \
.func = func_val, \
.subsystem_choice = request_union_##prefix##_subsystem_m_c, \
.request_choice = request_choice_val, \
prefix##_subsystem_handler_##request_id) = { \
.func = request_id, \
.subsystem_choice = zmk_Request_##prefix##_tag, \
.request_choice = zmk_##prefix##_response_##request_id##_tag, \
};

#define ZMK_RPC_RESPONSE(subsys, type, ...) \
((struct response_r){ \
.response_choice = request_response_m_c, \
.request_response_m = \
#define ZMK_RPC_RESPONSE(subsys, _type, ...) \
((zmk_Response){ \
.which_type = zmk_Response_request_response_tag, \
.type = \
{ \
.response_payload_m = \
.request_response = \
{ \
.response_payload_choice = response_payload_##subsys##_response_m_c, \
.subsys##_response_m = \
.which_subsystem = zmk_RequestResponse_##subsys##_tag, \
.subsystem = \
{ \
.union_choice = subsys##_response_union_##type##_m_c, \
.type##_m = __VA_ARGS__, \
.subsys = \
{ \
.which_response_type = \
zmk_##subsys##_response_##_type##_tag, \
.response_type = {._type = __VA_ARGS__}, \
}, \
}, \
}, \
}, \
})

struct response_r zmk_rpc_handle_request(const struct request *req);
zmk_Response zmk_rpc_handle_request(const zmk_Request *req);
6 changes: 0 additions & 6 deletions app/proto/CMakeLists.txt

This file was deleted.

2 changes: 2 additions & 0 deletions app/proto/zmk/behaviors.options
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
zmk.behaviors.list_all_behaviors_response.behaviors max_count:20
zmk.behaviors.get_behavior_details_response.friendly_name max_size:20
43 changes: 43 additions & 0 deletions app/proto/zmk/behaviors.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
syntax = "proto3";

package zmk.behaviors;

message request {
oneof request_type {
bool list_all_behaviors = 1;
get_behavior_details_request get_behavior_details = 2;
}
}

message get_behavior_details_request {
uint32 behavior_id = 1;
}

message response {
oneof response_type {
list_all_behaviors_response list_all_behaviors = 1;
get_behavior_details_response get_behavior_details = 2;
}
}

message list_all_behaviors_response {
repeated uint32 behaviors = 1;
}

message get_behavior_details_response {
uint32 id = 1;
string friendly_name = 2;
behavior_binding_parameter_details param1 = 3;
behavior_binding_parameter_details param2 = 4;
}

message behavior_binding_parameter_details {
behavior_binding_parameter_domain domain = 1;
string name = 2;
}

enum behavior_binding_parameter_domain {
Nil = 0;
HIDUsage = 1;
LayerIndex = 2;
}
21 changes: 21 additions & 0 deletions app/proto/zmk/core.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
syntax = "proto3";

package zmk.core;

message request {
oneof request_type {
bool get_lock_status = 1;
bool unlock_request = 2;
bool lock_request = 3;
}
}

message get_lock_status_response {
bool locked = 1;
}

message response {
oneof response_type {
get_lock_status_response get_lock_status = 1;
}
}
9 changes: 9 additions & 0 deletions app/proto/zmk/keymap.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
syntax = "proto3";

package zmk.keymap;

message request {
oneof request_type {
bool get_layer_summaries = 1;
}
}
33 changes: 0 additions & 33 deletions app/proto/zmk/studio-msgs.cmake

This file was deleted.

55 changes: 55 additions & 0 deletions app/proto/zmk/studio.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// Requests
syntax = "proto3";

package zmk;

import "core.proto";
import "behaviors.proto";
import "keymap.proto";

message Request {
uint32 request_id = 1;

oneof subsystem {
zmk.core.request core = 2;
zmk.keymap.request keymap = 3;
zmk.behaviors.request behaviors = 4;
}
}


// keymap_request = {
// (0: get_layers_summary)
// }

// behavior_request = {
// (0: list_all_behaviors) /
// (1: get_behavior_details)
// }

// get_layers_summary = nil

// list_all_behaviors = nil
// get_behavior_details = [ behavior_id: uint ]

// ; Responses

message Response {
oneof type {
RequestResponse request_response = 1;
Notification notification = 2;
}
}

message RequestResponse {
uint32 request_id = 1;
oneof subsystem {
zmk.core.response core = 2;
zmk.behaviors.response behaviors = 4;
}
}

message Notification {
uint32 notification_type = 1;

}
9 changes: 7 additions & 2 deletions app/src/studio/Kconfig
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@

menuconfig ZMK_STUDIO
bool "Studio Support"
select NANOPB
help
Add firmware support for realtime keymap updates (ZMK Studio

Expand All @@ -10,12 +11,16 @@ menu "Interfaces"

config ZMK_STUDIO_INTERFACE_UART
bool "Serial"
select SERIAL
select NET_BUF
default y if ZMK_USB

config ZMK_STUDIO_INTERFACE_BLE
bool "BLE (GATT)"
default ZMK_BLE
select NET_BUF
depends on ZMK_BLE
default y

endmenu

endif
endif
11 changes: 6 additions & 5 deletions app/src/studio/core_subsystem.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,11 @@ ZMK_RPC_SUBSYSTEM(core)

#define CORE_RESPONSE(type, ...) ZMK_RPC_RESPONSE(core, type, __VA_ARGS__)

struct response_r get_lock_status(const struct request *req) {
return CORE_RESPONSE(get_lock_state_response, {
.locked = false,
});
zmk_Response get_lock_status(const zmk_Request *req) {
zmk_core_get_lock_status_response resp = zmk_core_get_lock_status_response_init_zero;
resp.locked = true;

return CORE_RESPONSE(get_lock_status, resp);
}

ZMK_RPC_SUBSYSTEM_HANDLER(core, core_request_get_lock_state_m_c, get_lock_status);
ZMK_RPC_SUBSYSTEM_HANDLER(core, get_lock_status);
Loading

0 comments on commit a55de93

Please sign in to comment.