From f9887885fb0abc6540255820e6f3ad11c6ae501f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Radovan=20Bla=C5=BEek?= Date: Sat, 25 Apr 2026 21:12:35 +0200 Subject: [PATCH 1/2] Introduce new `CompostCtx` struct that is passed into all the handlers Allocator is now passed as part of the `ctx`. `ctx` also contains the rx and tx messages and `user_ctx` - a void pointer passed by the user to `compost_msg_process()` --- compost_rpc/compost_rpc.py | 67 ++++++++++++------------- compost_rpc/lib/c/header_template.py | 10 +++- compost_rpc/lib/c/source_template.py | 13 ++--- examples/pc_to_pc/main.c | 4 +- test/mock/main.c | 5 +- test/protocol_impl.c | 73 ++++++++++++++-------------- 6 files changed, 87 insertions(+), 85 deletions(-) diff --git a/compost_rpc/compost_rpc.py b/compost_rpc/compost_rpc.py index d15fcb3..a4afb80 100644 --- a/compost_rpc/compost_rpc.py +++ b/compost_rpc/compost_rpc.py @@ -656,7 +656,7 @@ def __init__(self, len_: int, txn: int, resp: bool, rpc_id: int) -> None: def __repr__(self) -> str: return f"Header(len={self.len}, txn={self.txn}, rpc_id={hex(self.rpc_id)}, resp={self.resp})" - + def payload_byte_len(self) -> int: """Returns the length of the payload in bytes.""" return 4 * self.len @@ -779,7 +779,7 @@ class Endpoint(Enum): LOCAL = 1 def is_call_outbound(self, call: Rpc): - return (call.direction == CallDirection.TO_LOCAL and self == Endpoint.REMOTE + return (call.direction == CallDirection.TO_LOCAL and self == Endpoint.REMOTE or call.direction == CallDirection.TO_REMOTE and self == Endpoint.LOCAL or call.direction == CallDirection.TWO_WAY) def is_call_inbound(self, call: Rpc): @@ -1286,7 +1286,7 @@ def __init__(self, protocol: type[Protocol]): # Public properties, common to all generators - with sensible defaults set self._filename: str = self._protocol.__name__ self._path: Path = Path(sys.path[0]) - + def _validate_endpoint(self, endpoint: Endpoint): for rpc in self._protocol._rpcs.values(): if rpc.is_notification: @@ -1300,9 +1300,9 @@ def _validate_endpoint(self, endpoint: Endpoint): elif endpoint.is_call_outbound(rpc) and self.features.outbound_rpc: continue msg = f"{self.name} generator cannot generate {self._protocol.__name__} for {'remote' if endpoint == Endpoint.REMOTE else 'local'} endpoint, because " - msg += f"{rpc.name} {'notification' if rpc.is_notification else 'RPC'} has unsupported call direction {rpc.direction.name}." + msg += f"{rpc.name} {'notification' if rpc.is_notification else 'RPC'} has unsupported call direction {rpc.direction.name}." raise ValueError(msg) - + @property def filename(self) -> str: """Filename used for generated source files.""" @@ -1339,7 +1339,7 @@ def name(cls) -> str: def short_name(cls) -> str: """Short name used for user input""" ... - + @property @abstractmethod def features(cls) -> CodeGeneratorFeatures: @@ -1405,7 +1405,7 @@ def path_source(self) -> Path: @path_source.setter def path_source(self, value: Path): self._path_source = value - + _primitive_type_map = { U8: "uint8_t", I8: "int8_t", @@ -1475,8 +1475,8 @@ def _member_default_value(cls, struct: type, member_annotation: tuple[str, type] @classmethod def _handler_signature(cls, rpc: Rpc, as_caller: bool = False) -> _String: sig = rpc.call_sig - call_site_params = [] - prototype_params = [] + call_site_params = ["ctx"] + prototype_params = ["struct CompostCtx *ctx"] parameters_items = rpc.get_param_items() for name, typ in parameters_items: prototype_params.append(f"{cls._type(typ.annotation)} {name}") @@ -1486,13 +1486,10 @@ def _handler_signature(cls, rpc: Rpc, as_caller: bool = False) -> _String: elif rpc.is_notification: raise TypeError("Notification return value must be None") else: - if _is_type_dynamic(sig.return_annotation): - prototype_params.append("struct CompostAlloc *alloc") - call_site_params.append("&alloc") return_type = cls._type(sig.return_annotation) result_assignment = f"{return_type} ret = " if return_type != "void" else "" call_site = f"{result_assignment}{rpc.name}_handler({', '.join(call_site_params)});" - prototype = f"{return_type} {rpc.name}_handler({', '.join(prototype_params) if prototype_params else 'void'});" + prototype = f"{return_type} {rpc.name}_handler({', '.join(prototype_params)});" return _String(call_site if as_caller else prototype) def _define_type_helper(self, t: type, helper: str) -> None: @@ -1638,7 +1635,7 @@ def _byte_align(code: _String, offset: MemUnit, ptr: str) -> tuple[_String, MemU code.add(f"{ptr} += {offset.bytes};") offset.bytes = 0 return code, offset - + def generate(self, endpoint: Endpoint = Endpoint.REMOTE) -> list[tuple[Path, str]]: self._validate_endpoint(endpoint) self._define_types() @@ -1713,11 +1710,8 @@ def generate(self, endpoint: Endpoint = Endpoint.REMOTE) -> list[tuple[Path, str sig = rpc.call_sig parameters_items = rpc.get_param_items() doc_prefix = "Deserialization/Serialization" - invoke_params = ["struct CompostMsg *tx"] if rpc.is_notification: doc_prefix = "Deserialization" - if parameters_items: - invoke_params.append("const struct CompostMsg rx") invoke_prototype = _String() invoke_prototype += f""" /** @@ -1730,32 +1724,32 @@ def generate(self, endpoint: Endpoint = Endpoint.REMOTE) -> list[tuple[Path, str /** * {doc_prefix} function for {rpc.name} function */ -void invoke_{rpc.name}({", ".join(invoke_params)}) +void invoke_{rpc.name}(struct CompostCtx *ctx) {{ """ invoke_fn.indent_inc() if parameters_items: - invoke_fn.add("const uint8_t *src = rx.payload_buf;") + invoke_fn.add("const uint8_t *src = ctx->rx.payload_buf;") for name, t in parameters_items: invoke_fn.add(self._load_call(t.annotation, dest = f"l_{name}", src = "&src")) if get_origin(sig.return_annotation) is list or _issubclass(sig.return_annotation, (bytes, str)): invoke_fn.add(( - "struct CompostAlloc alloc = compost_alloc_init(tx->payload_buf + 2, tx->payload_buf_size - 2);" + "ctx->alloc = compost_alloc_init(ctx->tx.payload_buf + 2, ctx->tx.payload_buf_size - 2);" )) elif _issubclass(sig.return_annotation, _CompostStruct): if sig.return_annotation.dynamic_members: invoke_fn.add(( - f"struct CompostAlloc alloc = {sig.return_annotation.__name__}_alloc_init(tx->payload_buf + {sig.return_annotation.layout[0].bytes}, tx->payload_buf_size - {sig.return_annotation.layout[0].bytes});", + f"ctx->alloc = {sig.return_annotation.__name__}_alloc_init(ctx->tx.payload_buf + {sig.return_annotation.layout[0].bytes}, ctx->tx.payload_buf_size - {sig.return_annotation.layout[0].bytes});", )) invoke_fn.add(f"{self._handler_signature(rpc, as_caller=True)}") if sig.return_annotation is not Signature.empty: - invoke_fn.add('uint8_t *dest = tx->payload_buf;') + invoke_fn.add('uint8_t *dest = ctx->tx.payload_buf;') invoke_fn.add(self._store_call(sig.return_annotation, "ret")) if sig.return_annotation is Signature.empty: - invoke_fn.add("tx->header.wlen = 0;") + invoke_fn.add("ctx->tx.header.wlen = 0;") else: - invoke_fn.add("tx->header.wlen = compost_bytes_to_words(dest - tx->payload_buf);") - invoke_fn.add(f"tx->header.rpc_id = {rpc.name.upper()};") + invoke_fn.add("ctx->tx.header.wlen = compost_bytes_to_words(dest - ctx->tx.payload_buf);") + invoke_fn.add(f"ctx->tx.header.rpc_id = {rpc.name.upper()};") invoke_fn += "}\n" protocol_header += invoke_prototype @@ -1763,22 +1757,21 @@ def generate(self, endpoint: Endpoint = Endpoint.REMOTE) -> list[tuple[Path, str rpc_id_fns = """ -void compost_unknown_msg(struct CompostMsg *tx) +void compost_unknown_msg(struct CompostCtx *ctx) { - tx->header.rpc_id = UNKNOWN_MSG; - tx->header.wlen = 0; + ctx->tx.header.rpc_id = UNKNOWN_MSG; + ctx->tx.header.wlen = 0; } -void compost_invoke_switch(struct CompostMsg *tx, const struct CompostMsg rx) +void compost_invoke_switch(struct CompostCtx *ctx) { - switch (rx.header.rpc_id) { + switch (ctx->rx.header.rpc_id) { """ for rpc in self._protocol._rpcs.values(): if rpc.is_notification and not endpoint.is_call_inbound(rpc): continue - params = "(tx, rx)" if rpc.get_param_items() else "(tx)" - rpc_id_fns += f" case {rpc.name.upper()}: invoke_{rpc.name}{params}; break;\n" - rpc_id_fns += """ default: compost_unknown_msg(tx); + rpc_id_fns += f" case {rpc.name.upper()}: invoke_{rpc.name}(ctx); break;\n" + rpc_id_fns += """ default: compost_unknown_msg(ctx); } } """ @@ -1822,7 +1815,7 @@ def name(cls) -> str: @property def short_name(cls) -> str: return "cs" - + @property def features(cls) -> CodeGeneratorFeatures: """Features that the generator supports""" @@ -2021,11 +2014,11 @@ class _OutputKey: def as_info_str (self, with_endpoint: bool = True) -> str: endpoint_str = f" (endpoint: {self.endpoint.name.lower()})" if with_endpoint else "" return f"{self.generator.name}{endpoint_str}" - + def as_typed_str (self, with_endpoint: bool = True) -> str: endpoint_str = f"_{self.endpoint.name.lower()}" if with_endpoint else "" return f"{self.generator.short_name}{endpoint_str}" - + def __init__(self, protocol: type[Protocol]): if _issubclass(protocol, Protocol): self._protocol_class = protocol @@ -2120,7 +2113,7 @@ def run(self): for path in existing: print(path) to_overwrite[lang] = existing - + langs_typed = [x.as_typed_str(verbose[x.generator.short_name]) for x in to_overwrite.keys()] overwrite_response = langs_typed if to_overwrite: diff --git a/compost_rpc/lib/c/header_template.py b/compost_rpc/lib/c/header_template.py index ad56476..445cd20 100644 --- a/compost_rpc/lib/c/header_template.py +++ b/compost_rpc/lib/c/header_template.py @@ -252,6 +252,13 @@ uint16_t alloc_ctr; }; +struct CompostCtx { + struct CompostMsg rx; //< Received message + struct CompostMsg tx; //< Message to be transmitted + struct CompostAlloc alloc; //< Allocator for the TX buffer + void* user_ctx; //< Pointer passed to compost_msg_process() +}; + /** * @brief Processes incoming Compost message and prepares the response. * Call this function for every Compost message you receive. @@ -259,10 +266,11 @@ * @param tx_buf_size Transmit buffer size in bytes * @param rx_buf Pointer to the buffer with incoming message * @param rx_buf_size Receive buffer valid data size in bytes + * @param user_ctx Pointer that is passed to the handler. Compost doesn't use it. * @return Size of valid data in bytes in the transmit buffer, or zero if there * is no message to send, or negative value if there was an error */ -int compost_msg_process(uint8_t *tx_buf, const size_t tx_buf_size, uint8_t *const rx_buf, const size_t rx_buf_size); +int compost_msg_process(uint8_t *tx_buf, const size_t tx_buf_size, uint8_t *const rx_buf, const size_t rx_buf_size, void *user_ctx); /** * @brief Loads the message header from the buffer. diff --git a/compost_rpc/lib/c/source_template.py b/compost_rpc/lib/c/source_template.py index fa9c22e..c12f1c2 100644 --- a/compost_rpc/lib/c/source_template.py +++ b/compost_rpc/lib/c/source_template.py @@ -50,7 +50,7 @@ class SourcePart: static void (*compost_assert_func)(uint32_t line) = NULL; -void compost_invoke_switch(struct CompostMsg *tx, const struct CompostMsg rx); +void compost_invoke_switch(struct CompostCtx *ctx); /******************************************************************************/ @@ -438,7 +438,7 @@ class SourcePart: } int compost_msg_process(uint8_t *tx_buf, const size_t tx_buf_size, uint8_t *const rx_buf, - const size_t rx_buf_size) + const size_t rx_buf_size, void *user_ctx) { if ((rx_buf_size < 4) || (tx_buf_size < 4) || tx_buf == NULL || rx_buf == NULL) { return COMPOST_EINVAL; @@ -465,14 +465,15 @@ class SourcePart: return COMPOST_ETXN; // We don't support sending RPC requests, so we can't get a response } - compost_invoke_switch(&tx, rx); + struct CompostCtx ctx = { .rx = rx, .tx = tx, .alloc = {0}, .user_ctx = user_ctx }; + compost_invoke_switch(&ctx); - if (tx.header.txn || tx.header.wlen) { - ret = compost_header_store(tx_buf, tx.header); + if (ctx.tx.header.txn || ctx.tx.header.wlen) { + ret = compost_header_store(tx_buf, ctx.tx.header); if (ret) { return ret; } - return 4 + (tx.header.wlen * 4); // Total message length is header (4 bytes) + payload + return 4 + (ctx.tx.header.wlen * 4); // Total message length is header (4 bytes) + payload } else { return 0; // Nothing to send } diff --git a/examples/pc_to_pc/main.c b/examples/pc_to_pc/main.c index fd73d09..84c36c4 100644 --- a/examples/pc_to_pc/main.c +++ b/examples/pc_to_pc/main.c @@ -100,7 +100,7 @@ int main(int argc, char *argv[]) // Process the request and prepare the response int16_t tx_msg_size = - compost_msg_process(tx_buf, sizeof(tx_buf), rx_buf, COMPOST_MSG_LEN(rx_buf)); + compost_msg_process(tx_buf, sizeof(tx_buf), rx_buf, COMPOST_MSG_LEN(rx_buf), NULL); // If the message size is negative, it indicates an error if (tx_msg_size > 0) { @@ -127,4 +127,4 @@ int main(int argc, char *argv[]) #endif return 0; -} \ No newline at end of file +} diff --git a/test/mock/main.c b/test/mock/main.c index 20fb557..25627cd 100644 --- a/test/mock/main.c +++ b/test/mock/main.c @@ -103,7 +103,7 @@ int main(int argc, char *argv[]) } size_t msg_len = COMPOST_MSG_LEN(rx_buf); log_msg(" mock <- ", rx_buf, msg_len); - int16_t tx_len = compost_msg_process(tx_buf, sizeof(tx_buf), rx_buf, msg_len); + int16_t tx_len = compost_msg_process(tx_buf, sizeof(tx_buf), rx_buf, msg_len, NULL); log_msg(" mock -> ", tx_buf, tx_len); if (tx_len) { @@ -119,7 +119,8 @@ int main(int argc, char *argv[]) switch (notif_request) { case 0x0e00: time(¤t_epoch); - struct MockDate date = epoch_to_date_handler(current_epoch, &alloc); + struct CompostCtx ctx = {.alloc = alloc}; + struct MockDate date = epoch_to_date_handler(&ctx, current_epoch); tx_len = notify_date_store(tx_buf, date); break; case 0x0e02: diff --git a/test/protocol_impl.c b/test/protocol_impl.c index 315e136..f13a6b5 100644 --- a/test/protocol_impl.c +++ b/test/protocol_impl.c @@ -52,7 +52,7 @@ void set_mock_date(struct MockDate* dest, time_t epoch) return; struct tm *timeinfo = gmtime(&epoch); dest->day = timeinfo->tm_mday; - dest->month = timeinfo->tm_mon + 1; + dest->month = timeinfo->tm_mon + 1; dest->year = timeinfo->tm_year + 1900; char tmp[dest->as_text.len+1]; snprintf(tmp, sizeof(tmp), "%02d%02d%04d", dest->day, dest->month, dest->year); @@ -65,17 +65,17 @@ void set_mock_date(struct MockDate* dest, time_t epoch) uint16_t notif_request = 0xFFFF; -void trigger_notification_handler(uint16_t msg_id) +void trigger_notification_handler(struct CompostCtx *ctx, uint16_t msg_id) { notif_request = msg_id; } -uint32_t add_int_handler(uint32_t a, uint32_t b) +uint32_t add_int_handler(struct CompostCtx *ctx, uint32_t a, uint32_t b) { return a + b; } -uint32_t sum_list_handler(struct CompostSliceU32 a) +uint32_t sum_list_handler(struct CompostCtx *ctx, struct CompostSliceU32 a) { int sum = 0; for (int i = 0; i < a.len; i++) @@ -83,33 +83,32 @@ uint32_t sum_list_handler(struct CompostSliceU32 a) return sum; } -void void_return_handler(int16_t x) +void void_return_handler(struct CompostCtx *ctx, int16_t x) { (void)x; } -void void_full_handler(void) +void void_full_handler(struct CompostCtx *ctx) { return; } -float divide_float_handler(float a, float b) +float divide_float_handler(struct CompostCtx *ctx, float a, float b) { return a / b; } -struct CompostSliceU8 caesar_cipher_handler(struct CompostSliceU8 str, uint8_t offset, - struct CompostAlloc *alloc) +struct CompostSliceU8 caesar_cipher_handler(struct CompostCtx *ctx, struct CompostSliceU8 str, uint8_t offset) { - struct CompostSliceU8 ciphertext = compost_slice_u8_new(alloc, str.len); + struct CompostSliceU8 ciphertext = compost_slice_u8_new(&ctx->alloc, str.len); for (int i = 0; i < str.len; i++) ciphertext.ptr[i] = str.ptr[i] + offset; return ciphertext; } -struct CompostSliceU8 sort_bytes_handler(struct CompostSliceU8 data, struct CompostAlloc *alloc) +struct CompostSliceU8 sort_bytes_handler(struct CompostCtx *ctx, struct CompostSliceU8 data) { - struct CompostSliceU8 sorted = compost_slice_u8_new(alloc, data.len); + struct CompostSliceU8 sorted = compost_slice_u8_new(&ctx->alloc, data.len); // Bubble sort algorithm for (int i = data.len - 1; i >= 0; i--) { for (int j = 0; j < data.len - 1; j++) { @@ -126,37 +125,37 @@ struct CompostSliceU8 sort_bytes_handler(struct CompostSliceU8 data, struct Comp return sorted; } -struct ListFirstAttr list_first_attr_handler(struct CompostSliceI16 data, struct CompostAlloc *alloc) +struct ListFirstAttr list_first_attr_handler(struct CompostCtx *ctx, struct CompostSliceI16 data) { - struct ListFirstAttr ret = ListFirstAttr_init(alloc, data.len); + struct ListFirstAttr ret = ListFirstAttr_init(&ctx->alloc, data.len); compost_slice_copy(ret.data, data); ret.min = slice_min(ret.data); ret.max = slice_max(ret.data); return ret; } -struct ListMidAttr list_mid_attr_handler(struct CompostSliceI16 data, struct CompostAlloc *alloc) +struct ListMidAttr list_mid_attr_handler(struct CompostCtx *ctx, struct CompostSliceI16 data) { - struct ListMidAttr ret = ListMidAttr_init(alloc, data.len); + struct ListMidAttr ret = ListMidAttr_init(&ctx->alloc, data.len); compost_slice_copy(ret.data, data); ret.min = slice_min(ret.data); ret.max = slice_max(ret.data); return ret; } -struct ListLastAttr list_last_attr_handler(struct CompostSliceI16 data, struct CompostAlloc *alloc) +struct ListLastAttr list_last_attr_handler(struct CompostCtx *ctx, struct CompostSliceI16 data) { - struct ListLastAttr ret = ListLastAttr_init(alloc, data.len); + struct ListLastAttr ret = ListLastAttr_init(&ctx->alloc, data.len); compost_slice_copy(ret.data, data); ret.min = slice_min(ret.data); ret.max = slice_max(ret.data); return ret; } -struct TwoListAttr two_list_attr_handler(struct CompostSliceI16 data_a, - struct CompostSliceI16 data_b, struct CompostAlloc *alloc) +struct TwoListAttr two_list_attr_handler(struct CompostCtx *ctx, struct CompostSliceI16 data_a, + struct CompostSliceI16 data_b) { - struct TwoListAttr ret = TwoListAttr_init(alloc, data_a.len, data_b.len); + struct TwoListAttr ret = TwoListAttr_init(&ctx->alloc, data_a.len, data_b.len); compost_slice_copy(ret.data_a, data_a); compost_slice_copy(ret.data_b, data_b); ret.avg_a = slice_avg(ret.data_a); @@ -165,28 +164,28 @@ struct TwoListAttr two_list_attr_handler(struct CompostSliceI16 data_a, return ret; } -struct MockDate epoch_to_date_handler(int32_t epoch, struct CompostAlloc *alloc) +struct MockDate epoch_to_date_handler(struct CompostCtx *ctx, int32_t epoch) { - struct MockDate ret = MockDate_init(alloc, MOCK_DATE_FMT_LEN, MOCK_DATE_FMT_LEN); + struct MockDate ret = MockDate_init(&ctx->alloc, MOCK_DATE_FMT_LEN, MOCK_DATE_FMT_LEN); set_mock_date(&ret, (time_t)epoch); return ret; } -struct CompostSliceU8 emoji_handler(struct CompostSliceU8 text, struct CompostAlloc *alloc) +struct CompostSliceU8 emoji_handler(struct CompostCtx *ctx, struct CompostSliceU8 text) { static uint8_t tmp[8]; struct CompostAlloc outside_alloc = compost_alloc_init(tmp, 8); if (strncmp((char *)text.ptr, "😘", text.len)) { return compost_str_new(&outside_alloc, "🤔"); // Returning slice outside of the TX buffer } else { - return compost_str_new(alloc, "🥰"); // Returning slice inside of the TX buffer + return compost_str_new(&ctx->alloc, "🥰"); // Returning slice inside of the TX buffer } } -struct CompostSliceU32 cat_lists_handler(struct CompostSliceU32 list_a, - struct CompostSliceU32 list_b, struct CompostAlloc *alloc) +struct CompostSliceU32 cat_lists_handler(struct CompostCtx *ctx, struct CompostSliceU32 list_a, + struct CompostSliceU32 list_b) { - struct CompostSliceU32 ret = compost_slice_u32_new(alloc, list_a.len + list_b.len); + struct CompostSliceU32 ret = compost_slice_u32_new(&ctx->alloc, list_a.len + list_b.len); for (int i = 0; i < list_a.len; i++) { compost_slice_set(ret, i, compost_slice_get(list_a, i)); } @@ -196,9 +195,9 @@ struct CompostSliceU32 cat_lists_handler(struct CompostSliceU32 list_a, return ret; } -struct MockLfsr get_random_number_handler(uint64_t seed, uint8_t iter, struct CompostAlloc *alloc) +struct MockLfsr get_random_number_handler(struct CompostCtx *ctx, uint64_t seed, uint8_t iter) { - struct MockLfsr lfsr = MockLfsr_init(alloc, MOCK_DATE_FMT_LEN, MOCK_DATE_FMT_LEN); + struct MockLfsr lfsr = MockLfsr_init(&ctx->alloc, MOCK_DATE_FMT_LEN, MOCK_DATE_FMT_LEN); lfsr.polynomial = 0xD800000000000000; //< Copy this value when reimplementing this test // LFSR does not work for seed=0 -> store any other value lfsr.value = seed == 0 ? 0x1F2E3D4C5B6A7988 : seed; @@ -221,12 +220,12 @@ struct MockLfsr get_random_number_handler(uint64_t seed, uint8_t iter, struct Co uint8_t tx_buf_notif[1024]; -void notify_date_handler(struct MockDate date) +void notify_date_handler(struct CompostCtx *ctx, struct MockDate date) { (void)date; // Unused } -void notify_motor_control_handler(struct MockMotorControl control) +void notify_motor_control_handler(struct CompostCtx *ctx, struct MockMotorControl control) { assert(control.state == MOTOR_STATE_ON); assert(control.direction == MOTOR_DIRECTION_UP); @@ -250,13 +249,13 @@ void notify_motor_control_handler(struct MockMotorControl control) } } -void notify_motor_report_handler(struct MockMotorReport report) +void notify_motor_report_handler(struct CompostCtx *ctx, struct MockMotorReport report) { assert(report.state == MOTOR_STATE_START); assert(report.direction == MOTOR_DIRECTION_UP); assert(report.voltage.len == 20); assert(report.current.len == 20); - + // Send back a notification as an async response struct MockMotorControl control = MockMotorControl_init(); control.state = MOTOR_STATE_STOP; @@ -271,14 +270,14 @@ void notify_motor_report_handler(struct MockMotorReport report) } } -void struct_in_param_handler(struct ListFirstAttr structure) +void struct_in_param_handler(struct CompostCtx *ctx, struct ListFirstAttr structure) { assert(structure.data.len == 10); assert(structure.min == 1); assert(structure.max == 10); } -void notify_bitfields_handler(struct BitfieldStruct config) +void notify_bitfields_handler(struct CompostCtx *ctx, struct BitfieldStruct config) { config.ccm = ~config.ccm; config.channel = ~config.channel; @@ -295,7 +294,7 @@ void notify_bitfields_handler(struct BitfieldStruct config) fflush(stdout); } -void notify_log_handler(struct MockLogMessage log) +void notify_log_handler(struct CompostCtx *ctx, struct MockLogMessage log) { (void)log; } From 59f0b8c9cbaeabfe0db6dcff6cece4cd6ea7e0f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Radovan=20Bla=C5=BEek?= Date: Mon, 4 May 2026 13:48:32 +0200 Subject: [PATCH 2/2] tests: Add `(void)` casts to avoid "unused parameter" warnings --- test/protocol_impl.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/test/protocol_impl.c b/test/protocol_impl.c index f13a6b5..608813d 100644 --- a/test/protocol_impl.c +++ b/test/protocol_impl.c @@ -67,16 +67,19 @@ uint16_t notif_request = 0xFFFF; void trigger_notification_handler(struct CompostCtx *ctx, uint16_t msg_id) { + (void)ctx; notif_request = msg_id; } uint32_t add_int_handler(struct CompostCtx *ctx, uint32_t a, uint32_t b) { + (void)ctx; return a + b; } uint32_t sum_list_handler(struct CompostCtx *ctx, struct CompostSliceU32 a) { + (void)ctx; int sum = 0; for (int i = 0; i < a.len; i++) sum += compost_slice_get(a, i); @@ -85,16 +88,19 @@ uint32_t sum_list_handler(struct CompostCtx *ctx, struct CompostSliceU32 a) void void_return_handler(struct CompostCtx *ctx, int16_t x) { + (void)ctx; (void)x; } void void_full_handler(struct CompostCtx *ctx) { + (void)ctx; return; } float divide_float_handler(struct CompostCtx *ctx, float a, float b) { + (void)ctx; return a / b; } @@ -222,11 +228,13 @@ uint8_t tx_buf_notif[1024]; void notify_date_handler(struct CompostCtx *ctx, struct MockDate date) { + (void)ctx; // Unused (void)date; // Unused } void notify_motor_control_handler(struct CompostCtx *ctx, struct MockMotorControl control) { + (void)ctx; assert(control.state == MOTOR_STATE_ON); assert(control.direction == MOTOR_DIRECTION_UP); assert(control.pwm_duty == 50); @@ -251,6 +259,7 @@ void notify_motor_control_handler(struct CompostCtx *ctx, struct MockMotorContro void notify_motor_report_handler(struct CompostCtx *ctx, struct MockMotorReport report) { + (void)ctx; assert(report.state == MOTOR_STATE_START); assert(report.direction == MOTOR_DIRECTION_UP); assert(report.voltage.len == 20); @@ -272,6 +281,7 @@ void notify_motor_report_handler(struct CompostCtx *ctx, struct MockMotorReport void struct_in_param_handler(struct CompostCtx *ctx, struct ListFirstAttr structure) { + (void)ctx; assert(structure.data.len == 10); assert(structure.min == 1); assert(structure.max == 10); @@ -279,6 +289,7 @@ void struct_in_param_handler(struct CompostCtx *ctx, struct ListFirstAttr struct void notify_bitfields_handler(struct CompostCtx *ctx, struct BitfieldStruct config) { + (void)ctx; config.ccm = ~config.ccm; config.channel = ~config.channel; config.clear = ~config.clear; @@ -296,5 +307,6 @@ void notify_bitfields_handler(struct CompostCtx *ctx, struct BitfieldStruct conf void notify_log_handler(struct CompostCtx *ctx, struct MockLogMessage log) { + (void)ctx; (void)log; }