Files
templates/c/set-protocol/include/set_protocol.h

203 lines
6.2 KiB
C

#ifndef SET_PROTOCOL_H
#define SET_PROTOCOL_H
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
#define SETP_VERSION 0x02U
#define SETP_SOF0 0xA5U
#define SETP_SOF1 0x5AU
#define SETP_HEADER_SIZE 14U
#define SETP_CRC_SIZE 4U
#ifndef SETP_MAX_PAYLOAD
#define SETP_MAX_PAYLOAD 512U
#endif
#define SETP_FRAME_MAX (SETP_HEADER_SIZE + SETP_MAX_PAYLOAD + SETP_CRC_SIZE)
#define SETP_NODE_LOCAL 0x0000U
#define SETP_NODE_BROADCAST 0xFFFFU
#define SETP_DEVICE_INFO_SCHEMA_VERSION 1U
#define SETP_DEVICE_INFO_FIXED_SIZE 25U
#define SETP_DEVICE_MODEL_MAX 63U
#define SETP_CAPABILITIES_SCHEMA_VERSION 1U
#define SETP_CAPABILITIES_SIZE 20U
/* Frame flags. Reserved bits must be transmitted as zero. */
#define SETP_FLAG_RESPONSE 0x01U
#define SETP_FLAG_EVENT 0x02U
#define SETP_FLAG_ERROR 0x04U
#define SETP_FLAG_ACK_REQUIRED 0x08U
#define SETP_FLAG_MORE 0x10U
#define SETP_FLAG_PRIORITY 0x20U
#define SETP_FLAG_KNOWN_MASK 0x3FU
#define SETP_FLAG_RESERVED_MASK 0xC0U
typedef enum {
SETP_IFACE_NONE = 0,
SETP_IFACE_RS232 = 1,
SETP_IFACE_RS485 = 2,
SETP_IFACE_CAN = 3,
SETP_IFACE_USB_CDC = 4,
SETP_IFACE_ETHERNET_TCP = 5,
SETP_IFACE_ETHERNET_UDP = 6
} setp_iface_t;
typedef enum {
SETP_MSG_PING = 0x0001,
SETP_MSG_DEVICE_INFO = 0x0002,
SETP_MSG_CAPABILITIES = 0x0003,
SETP_MSG_DIAGNOSTICS = 0x0008,
SETP_MSG_READ = 0x0009,
SETP_MSG_WRITE = 0x000A,
SETP_MSG_LOG_READ = 0x0010,
SETP_MSG_CATALOG = 0x0011,
SETP_MSG_SUBSCRIBE = 0x0012,
SETP_MSG_PUBLISH = 0x0013,
SETP_MSG_UNSUBSCRIBE = 0x0014,
SETP_MSG_FW_BEGIN = 0x0100,
SETP_MSG_FW_DATA = 0x0101,
SETP_MSG_FW_END = 0x0102,
SETP_MSG_FW_ABORT = 0x0103,
SETP_MSG_FW_STATUS = 0x0104,
SETP_MSG_FW_ACTIVATE = 0x0105,
SETP_MSG_DEVICE_BASE = 0x1000,
SETP_MSG_DEVICE_LAST = 0x7FFF
} setp_message_type_t;
typedef enum {
SETP_STATUS_OK = 0,
SETP_STATUS_INVALID_ARGUMENT = 1,
SETP_STATUS_INVALID_LENGTH = 2,
SETP_STATUS_NOT_FOUND = 3,
SETP_STATUS_ACCESS_DENIED = 4,
SETP_STATUS_BUSY = 5,
SETP_STATUS_NO_PROVIDER = 6,
SETP_STATUS_INTERNAL = 7,
SETP_STATUS_CRC = 8,
SETP_STATUS_SEQUENCE = 9,
SETP_STATUS_NO_SPACE = 10,
SETP_STATUS_UNSUPPORTED = 11,
SETP_STATUS_VERIFY_FAILED = 12,
SETP_STATUS_AUTH_FAILED = 13,
SETP_STATUS_TIMEOUT = 14,
SETP_STATUS_WRONG_STATE = 15
} setp_status_t;
/* CAPABILITIES feature_flags. */
#define SETP_FEATURE_READ (1UL << 0)
#define SETP_FEATURE_WRITE (1UL << 1)
#define SETP_FEATURE_CATALOG (1UL << 2)
#define SETP_FEATURE_SUBSCRIBE (1UL << 3)
#define SETP_FEATURE_LOG_READ (1UL << 4)
#define SETP_FEATURE_FIRMWARE (1UL << 5)
#define SETP_FEATURE_DIAGNOSTICS (1UL << 6)
/* CAPABILITIES interface_mask; bit index equals setp_iface_t. */
#define SETP_IFACE_MASK(iface) (1UL << (uint32_t)(iface))
typedef struct {
uint16_t schema_version;
uint16_t device_class;
uint32_t hardware_version;
uint32_t firmware_version;
uint32_t dictionary_version;
uint64_t serial_number;
uint8_t model_length;
const uint8_t *model;
} setp_device_info_t;
typedef struct {
uint16_t schema_version;
uint16_t max_payload;
uint32_t interface_mask;
uint32_t feature_flags;
uint16_t max_read_items;
uint16_t max_write_items;
uint16_t max_subscriptions;
uint16_t max_publish_items;
} setp_capabilities_t;
typedef struct {
uint8_t flags;
uint16_t message_type;
uint16_t source;
uint16_t destination;
uint16_t sequence;
uint16_t payload_length;
const uint8_t *payload;
} setp_frame_t;
typedef struct {
uint32_t frames;
uint32_t crc_errors;
uint32_t version_errors;
uint32_t length_errors;
uint32_t flag_errors;
uint32_t stray_bytes;
uint32_t overflows;
} setp_parser_stats_t;
typedef struct {
uint8_t buffer[SETP_FRAME_MAX];
uint16_t length;
setp_parser_stats_t stats;
} setp_parser_t;
typedef void (*setp_frame_fn)(const setp_frame_t *frame, void *user);
uint16_t setp_get_u16(const uint8_t *data);
uint32_t setp_get_u32(const uint8_t *data);
uint64_t setp_get_u64(const uint8_t *data);
void setp_put_u16(uint8_t *data, uint16_t value);
void setp_put_u32(uint8_t *data, uint32_t value);
void setp_put_u64(uint8_t *data, uint64_t value);
uint32_t setp_crc32(const uint8_t *data, size_t length);
/** Encode one complete stream/UDP frame. Returns zero on invalid arguments. */
size_t setp_frame_encode(const setp_frame_t *frame, uint8_t *out, size_t capacity);
/** Decode exactly one complete UDP/datagram frame; trailing bytes are rejected. */
bool setp_frame_decode_datagram(const uint8_t *data, size_t length, setp_frame_t *out);
void setp_parser_init(setp_parser_t *parser);
void setp_parser_reset(setp_parser_t *parser);
/** Feed an arbitrary stream chunk. Returns the number of delivered frames. */
size_t setp_parser_feed(setp_parser_t *parser, const uint8_t *data, size_t length,
setp_frame_fn callback, void *user);
/** Encode the common two-byte status prefix used by every response. */
size_t setp_status_encode(uint16_t status, uint8_t *out, size_t capacity);
/** Split a response payload into status and optional response body. */
bool setp_status_decode(const setp_frame_t *frame, uint16_t *status,
const uint8_t **body, uint16_t *body_length);
/** Encode/decode DEVICE_INFO response body (without the status prefix). */
size_t setp_device_info_encode(const setp_device_info_t *info,
uint8_t *out, size_t capacity);
bool setp_device_info_decode(const uint8_t *data, uint16_t length,
setp_device_info_t *out);
/** Encode/decode CAPABILITIES response body (without the status prefix). */
size_t setp_capabilities_encode(const setp_capabilities_t *capabilities,
uint8_t *out, size_t capacity);
bool setp_capabilities_decode(const uint8_t *data, uint16_t length,
setp_capabilities_t *out);
#ifdef __cplusplus
}
#endif
#endif /* SET_PROTOCOL_H */