ProtoCore v1.0.16
Deterministic, zero-heap network stack for embedded targets
Loading...
Searching...
No Matches
zwave.h
Go to the documentation of this file.
1// ProtoCore v1.0.16 - Copyright (C) 2026 Douglas Quigg (dstroy0) <dquigg123@gmail.com>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4#ifndef PROTOCORE_ZWAVE_H
5#define PROTOCORE_ZWAVE_H
6
7#include "protocore_config.h" // the entry point: protocore_types.h for the widths
8
10
11/**
12 * @file zwave.h
13 * @brief Z-Wave Serial API frame codec (PROTOCORE_ENABLE_ZWAVE) - Silicon Labs controller.
14 *
15 * The host-side Serial API of a Silicon Labs 500 / 700-series Z-Wave controller reached
16 * over UART: a Z-Wave mesh bridged to the web. The host and the controller exchange **data
17 * frames**:
18 *
19 * SOF (0x01) | LEN | Type | Command | Data... | Checksum
20 *
21 * where LEN counts Type + Command + Data + Checksum, Type is 0x00 (REQ) or 0x01 (RES), and
22 * the checksum is 0xFF XOR-folded over LEN through the last Data byte. Each data frame is
23 * acknowledged by a single-byte **ACK (0x06)**, or rejected with **NAK (0x15)** / **CAN
24 * (0x18)**.
25 *
26 * protocore_zwave_build_frame() assembles a data frame carrying a function command, protocore_zwave_parse_frame()
27 * frames + verifies one, and protocore_zwave_is_ack() / protocore_zwave_is_nak() / protocore_zwave_is_can() /
28 * protocore_zwave_build_ack() handle the flow-control bytes. The per-command payload (GetVersion,
29 * SendData, AddNodeToNetwork, an ApplicationCommandHandler report, ...) is the application's.
30 * Pure - you carry the bytes over your UART - so it is fully host-testable.
31 *
32 * @c work is bytes the CALLER holds. This module reads none of them: it carries nothing
33 * between calls, so there is no state to keep and nothing to wipe. The parameter is there so
34 * a caller drives every namespace the same way.
35 *
36 * @author Douglas Quigg (dstroy0)
37 * @date 2026
38 */
39
40// PROTOCORE_ZWAVE_BORROW - the bytes this module runs out of - is stated in protocore_config.h, which sums
41// it into its arena. Its size and its offset are each a static_assert, so a feature
42// combination that does not fit fails to compile rather than overrunning at run time.
43
44/** @brief Z-Wave Serial API control bytes / frame markers. */
45#define ZWAVE_SOF 0x01 ///< start of a data frame
46#define ZWAVE_ACK 0x06 ///< frame acknowledged
47#define ZWAVE_NAK 0x15 ///< frame rejected (checksum)
48#define ZWAVE_CAN 0x18 ///< frame cancelled (retransmit)
49
50/** @brief Data-frame type. */
52{
53 ZWAVE_REQ = 0x00, ///< request
54 ZWAVE_RES = 0x01, ///< response
56
57/** @brief Dispatch table. Addressed by offset, so the layout is asserted below. */
58typedef struct
59{
60 uint16_t (*build_frame)(uint8_t *, protocore_zwave_type, uint8_t, const uint8_t *, uint8_t, uint8_t *, uint16_t);
61 int (*parse_frame)(uint8_t *, const uint8_t *, uint16_t, uint8_t *, uint8_t *, const uint8_t **, uint8_t *);
62 proto_bool (*is_ack)(uint8_t *, uint8_t);
63 proto_bool (*is_nak)(uint8_t *, uint8_t);
64 proto_bool (*is_can)(uint8_t *, uint8_t);
65 uint16_t (*build_ack)(uint8_t *, uint8_t *, uint16_t);
66} ZwaveNs;
67PROTOCORE_NS_LAYOUT(ZwaveNs, build_frame, parse_frame, is_ack, is_nak, is_can, build_ack);
68
69/**
70 * @brief Assemble a data frame carrying type + cmd + data into out.
71 * @param work PROTOCORE_ZWAVE_BORROW bytes the caller took. Not held past the call.
72 * @param type Type
73 * @param cmd Cmd
74 * @param data Data
75 * @param data_len Data len
76 * @param out Out
77 * @param cap Cap
78 * @return The uint16_t.
79 */
80uint16_t protocore_zwave_build_frame(uint8_t *work, protocore_zwave_type type, uint8_t cmd, const uint8_t *data,
81 uint8_t data_len, uint8_t *out, uint16_t cap);
82/**
83 * @brief Frame one data frame from the front of raw and verify the checksum.
84 * @param work PROTOCORE_ZWAVE_BORROW bytes the caller took. Not held past the call.
85 * @param raw Raw
86 * @param len Len
87 * @param type Type
88 * @param cmd Cmd
89 * @param pdata Pdata
90 * @param pdata_len Pdata len
91 * @return The int.
92 */
93int protocore_zwave_parse_frame(uint8_t *work, const uint8_t *raw, uint16_t len, uint8_t *type, uint8_t *cmd,
94 const uint8_t **pdata, uint8_t *pdata_len);
95/**
96 * @brief True if b is the ACK control byte.
97 * @param work PROTOCORE_ZWAVE_BORROW bytes the caller took. Not held past the call.
98 * @param b B
99 * @return PROTO_TRUE on success.
100 */
101proto_bool protocore_zwave_is_ack(uint8_t *work, uint8_t b);
102/**
103 * @brief True if b is the NAK control byte.
104 * @param work PROTOCORE_ZWAVE_BORROW bytes the caller took. Not held past the call.
105 * @param b B
106 * @return PROTO_TRUE on success.
107 */
108proto_bool protocore_zwave_is_nak(uint8_t *work, uint8_t b);
109/**
110 * @brief True if b is the CAN control byte.
111 * @param work PROTOCORE_ZWAVE_BORROW bytes the caller took. Not held past the call.
112 * @param b B
113 * @return PROTO_TRUE on success.
114 */
115proto_bool protocore_zwave_is_can(uint8_t *work, uint8_t b);
116/**
117 * @brief Write the single ACK byte into out. 1, or 0 if cap < 1.
118 * @param work PROTOCORE_ZWAVE_BORROW bytes the caller took. Not held past the call.
119 * @param out Out
120 * @param cap Cap
121 * @return The uint16_t.
122 */
123uint16_t protocore_zwave_build_ack(uint8_t *work, uint8_t *out, uint16_t cap);
124
125/** @brief Module namespace. */
132
134
135#endif // PROTOCORE_ZWAVE_H
PROTO_ENUM_PACKED
Application protocol spoken on a listener port or connection slot.
#define PROTOCORE_NS_LAYOUT(T,...)
Pin every dispatch slot of a table that is nothing but function pointers.
#define PROTOCORE_NS
Storage for a dispatch table. The const is load bearing.
Dispatch table. Addressed by offset, so the layout is asserted below.
Definition zwave.h:59
uint16_t(* build_frame)(uint8_t *, protocore_zwave_type, uint8_t, const uint8_t *, uint8_t, uint8_t *, uint16_t)
Definition zwave.h:60
#define PROTOCORE_BEGIN_DECLS
Give a header's declarations C linkage, so their symbol names carry no parameter types.
Definition types.h:96
_Bool proto_bool
The truth value.
Definition types.h:64
#define PROTOCORE_END_DECLS
Definition types.h:97
proto_bool protocore_zwave_is_nak(uint8_t *work, uint8_t b)
True if b is the NAK control byte.
uint16_t protocore_zwave_build_frame(uint8_t *work, protocore_zwave_type type, uint8_t cmd, const uint8_t *data, uint8_t data_len, uint8_t *out, uint16_t cap)
Assemble a data frame carrying type + cmd + data into out.
enum PROTO_ENUM_PACKED protocore_zwave_type
Data-frame type.
int protocore_zwave_parse_frame(uint8_t *work, const uint8_t *raw, uint16_t len, uint8_t *type, uint8_t *cmd, const uint8_t **pdata, uint8_t *pdata_len)
Frame one data frame from the front of raw and verify the checksum.
proto_bool protocore_zwave_is_ack(uint8_t *work, uint8_t b)
True if b is the ACK control byte.
@ ZWAVE_RES
response
Definition zwave.h:54
@ ZWAVE_REQ
request
Definition zwave.h:53
PROTOCORE_NS ZwaveNs Zwave PROTOCORE_UNUSED
Module namespace.
Definition zwave.h:126
uint16_t protocore_zwave_build_ack(uint8_t *work, uint8_t *out, uint16_t cap)
Write the single ACK byte into out. 1, or 0 if cap < 1.
proto_bool protocore_zwave_is_can(uint8_t *work, uint8_t b)
True if b is the CAN control byte.