RDM  HEAD (unstable)
Implementation of ANSI E1.31 (Streaming ACN)
View other versions:
message.h
Go to the documentation of this file.
1 /******************************************************************************
2  * Copyright 2020 ETC Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  ******************************************************************************
16  * This file is a part of RDM. For more information, go to:
17  * https://github.com/ETCLabs/RDM
18  *****************************************************************************/
19 
25 #ifndef RDM_MESSAGE_H_
26 #define RDM_MESSAGE_H_
27 
28 #include <stdbool.h>
29 #include <stddef.h>
30 #include <stdint.h>
31 #include "etcpal/error.h"
32 #include "rdm/uid.h"
33 #include "rdm/defs.h"
34 
43 #ifdef __cplusplus
44 extern "C" {
45 #endif
46 
48 #define RDM_MAX_BYTES 257
49 
51 #define RDM_MIN_BYTES 26
52 
54 #define RDM_MAX_PDL 231
55 
57 #define RDM_HEADER_SIZE 24
58 
63 #define RDM_OFFSET_STARTCODE 0
64 #define RDM_OFFSET_SUBSTART 1
65 #define RDM_OFFSET_LENGTH 2
66 #define RDM_OFFSET_DEST_MANUFACTURER 3
67 #define RDM_OFFSET_DEST_DEVICE 5
68 #define RDM_OFFSET_SRC_MANUFACTURER 9
69 #define RDM_OFFSET_SRC_DEVICE 11
70 #define RDM_OFFSET_TRANSACTION 15
71 #define RDM_OFFSET_PORTID_RESPTYPE 16
72 #define RDM_OFFSET_MSGCOUNT 17
73 #define RDM_OFFSET_SUBDEVICE 18
74 #define RDM_OFFSET_COMMAND_CLASS 20
75 #define RDM_OFFSET_PARAM_ID 21
76 #define RDM_OFFSET_PARAM_DATA_LEN 23
77 #define RDM_OFFSET_PARAM_DATA 24
83 typedef enum
84 {
86  kRdmCCDiscoveryCommand = E120_DISCOVERY_COMMAND,
88  kRdmCCDiscoveryCommandResponse = E120_DISCOVERY_COMMAND_RESPONSE,
90  kRdmCCGetCommand = E120_GET_COMMAND,
92  kRdmCCGetCommandResponse = E120_GET_COMMAND_RESPONSE,
94  kRdmCCSetCommand = E120_SET_COMMAND,
96  kRdmCCSetCommandResponse = E120_SET_COMMAND_RESPONSE
97  // No "num command classes" placeholder here, because the command class values are not contiguous
99 
101 typedef enum
102 {
104  kRdmResponseTypeAck = E120_RESPONSE_TYPE_ACK,
109  kRdmResponseTypeAckTimer = E120_RESPONSE_TYPE_ACK_TIMER,
114  kRdmResponseTypeNackReason = E120_RESPONSE_TYPE_NACK_REASON,
119  kRdmResponseTypeAckOverflow = E120_RESPONSE_TYPE_ACK_OVERFLOW,
121 
123 typedef enum
124 {
126  kRdmNRUnknownPid = E120_NR_UNKNOWN_PID,
128  kRdmNRFormatError = E120_NR_FORMAT_ERROR,
130  kRdmNRHardwareFault = E120_NR_HARDWARE_FAULT,
132  // TODO: Change "line master" to different terminology once it's changed in the standard.
133  kRdmNRProxyReject = E120_NR_PROXY_REJECT,
135  kRdmNRWriteProtect = E120_NR_WRITE_PROTECT,
137  kRdmNRUnsupportedCommandClass = E120_NR_UNSUPPORTED_COMMAND_CLASS,
139  kRdmNRDataOutOfRange = E120_NR_DATA_OUT_OF_RANGE,
141  kRdmNRBufferFull = E120_NR_BUFFER_FULL,
143  kRdmNRPacketSizeUnsupported = E120_NR_PACKET_SIZE_UNSUPPORTED,
145  kRdmNRSubDeviceOutOfRange = E120_NR_SUB_DEVICE_OUT_OF_RANGE,
147  kRdmNRProxyBufferFull = E120_NR_PROXY_BUFFER_FULL,
149  kRdmNRActionNotSupported = E137_2_NR_ACTION_NOT_SUPPORTED,
151  kRdmNREndpointNumberInvalid = E137_7_NR_ENDPOINT_NUMBER_INVALID,
153  kRdmNRInvalidEndpointMode = E137_7_NR_INVALID_ENDPOINT_MODE,
155  kRdmNRUnknownUid = E137_7_NR_UNKNOWN_UID,
157  kRdmNRUnknownScope = E133_NR_UNKNOWN_SCOPE,
159  kRdmNRInvalidStaticConfigType = E133_NR_INVALID_STATIC_CONFIG_TYPE,
161  kRdmNRInvalidIpv4Address = E133_NR_INVALID_IPV4_ADDRESS,
163  kRdmNRInvalidIpv6Address = E133_NR_INVALID_IPV6_ADDRESS,
165  kRdmNRInvalidPort = E133_NR_INVALID_PORT,
166 
167  /****************************************************************************
168  * UPDATE THE DEFINE BELOW IF ADDING ENUM VALUES
169  ***************************************************************************/
171 
173 #define RDM_NUM_STANDARD_NR_CODES 20
174 
176 typedef struct RdmBuffer
177 {
178  uint8_t data[RDM_MAX_BYTES];
179  size_t data_len;
181 
187 #define RDM_GET_COMMAND_CLASS(rdmbufptr) ((rdmbufptr)->data[RDM_OFFSET_COMMAND_CLASS])
188 
194 #define RDM_GET_TRANSACTION_NUM(rdmbufptr) ((rdmbufptr)->data[RDM_OFFSET_TRANSACTION])
195 
200 typedef struct RdmCommandHeader
201 {
209  uint8_t port_id;
211  uint16_t subdevice;
218  uint16_t param_id;
220 
225 typedef struct RdmResponseHeader
226 {
236  uint8_t msg_count;
238  uint16_t subdevice;
245  uint16_t param_id;
247 
253 #define RDM_PACKED_SIZE(data_len) (RDM_HEADER_SIZE + (data_len) + 2u)
254 
255 void rdm_pack_checksum(uint8_t* buffer, size_t data_len_without_checksum);
256 bool rdm_validate_msg(const RdmBuffer* buffer);
257 
258 bool rdm_command_header_is_valid(const RdmCommandHeader* cmd_header);
259 bool rdm_response_header_is_valid(const RdmResponseHeader* resp_header);
260 
262  const uint8_t* cmd_data,
263  uint8_t cmd_data_len,
264  RdmBuffer* buffer);
266  const uint8_t* cmd_data,
267  uint8_t cmd_data_len,
268  uint8_t* buf,
269  size_t buf_len);
270 
272  uint8_t msg_count,
273  const uint8_t* response_data,
274  uint8_t response_data_len,
275  RdmBuffer* buffer);
277  const uint8_t* response_data,
278  uint8_t response_data_len,
279  RdmBuffer* buffer);
281  uint8_t msg_count,
282  rdm_nack_reason_t nack_reason,
283  RdmBuffer* buffer);
285  uint8_t msg_count,
286  unsigned int delay_time_ms,
287  RdmBuffer* buffer);
288 etcpal_error_t rdm_pack_dub_response(const RdmUid* responder_uid, RdmBuffer* buffer);
289 
290 size_t rdm_get_num_responses_needed(uint16_t param_id, size_t response_data_len);
292  const uint8_t* response_data,
293  size_t response_data_len,
294  RdmBuffer* buffers,
295  size_t num_buffers);
296 
298  const uint8_t* additional_data,
299  uint8_t additional_data_len);
300 
302  RdmCommandHeader* cmd_header,
303  const uint8_t** param_data,
304  uint8_t* param_data_len);
306  RdmResponseHeader* resp_header,
307  const uint8_t** param_data,
308  uint8_t* param_data_len);
309 etcpal_error_t rdm_unpack_dub_response(const RdmBuffer* buffer, RdmUid* responder_uid);
310 
311 unsigned int rdm_get_ack_timer_delay(const uint8_t* param_data);
312 rdm_nack_reason_t rdm_get_nack_reason_code(const uint8_t* param_data);
313 
314 const char* rdm_command_class_to_string(rdm_command_class_t command_class);
315 const char* rdm_response_type_to_string(rdm_response_type_t resp_type);
316 const char* rdm_nack_reason_to_string(rdm_nack_reason_t reason_code);
317 
318 #ifdef __cplusplus
319 }
320 #endif
321 
326 #endif /* RDM_MESSAGE_H_ */
etcpal_error_t
struct RdmCommandHeader RdmCommandHeader
etcpal_error_t rdm_pack_command(const RdmCommandHeader *cmd_header, const uint8_t *cmd_data, uint8_t cmd_data_len, RdmBuffer *buffer)
Convert an RDM command header and data to the RDM wire format.
Definition: message.c:181
#define RDM_MAX_BYTES
Definition: message.h:48
struct RdmResponseHeader RdmResponseHeader
const char * rdm_nack_reason_to_string(rdm_nack_reason_t reason_code)
Get a string representation of an RDM NACK reason code.
Definition: message.c:786
struct RdmBuffer RdmBuffer
void rdm_pack_checksum(uint8_t *buffer, size_t data_len_without_checksum)
Calculate and pack an RDM checksum at the end of an RDM message.
Definition: message.c:97
etcpal_error_t rdm_unpack_command(const RdmBuffer *buffer, RdmCommandHeader *cmd_header, const uint8_t **param_data, uint8_t *param_data_len)
Deserialize an RDM command from its wire format.
Definition: message.c:553
etcpal_error_t rdm_pack_nack_response(const RdmCommandHeader *cmd_header, uint8_t msg_count, rdm_nack_reason_t nack_reason, RdmBuffer *buffer)
Serialize an RDM NACK response to a previously-received command.
Definition: message.c:325
rdm_response_type_t
Definition: message.h:102
size_t rdm_get_num_responses_needed(uint16_t param_id, size_t response_data_len)
Get the number of RDM responses needed to send the given response data.
Definition: message.c:445
etcpal_error_t rdm_pack_full_response(const RdmCommandHeader *cmd_header, const uint8_t *response_data, size_t response_data_len, RdmBuffer *buffers, size_t num_buffers)
Serialize a full RDM ACK response, splitting ACK_OVERFLOW responses if necessary.
Definition: message.c:470
const char * rdm_command_class_to_string(rdm_command_class_t command_class)
Get a string representation of an RDM command class.
Definition: message.c:714
const char * rdm_response_type_to_string(rdm_response_type_t resp_type)
Get a string representation of an RDM response type.
Definition: message.c:740
bool rdm_response_header_is_valid(const RdmResponseHeader *resp_header)
Determine whether the values contained in a response header are valid for an RDM response.
Definition: message.c:153
rdm_nack_reason_t
Definition: message.h:124
rdm_nack_reason_t rdm_get_nack_reason_code(const uint8_t *param_data)
Get the NACK reason code from a NACK_REASON message.
Definition: message.c:700
etcpal_error_t rdm_pack_command_with_custom_buf(const RdmCommandHeader *cmd_header, const uint8_t *cmd_data, uint8_t cmd_data_len, uint8_t *buf, size_t buf_len)
Convert an RDM command header and data to the RDM wire format in a user-provided buffer.
Definition: message.c:209
etcpal_error_t rdm_pack_overflow_response(const RdmCommandHeader *cmd_header, const uint8_t *response_data, uint8_t response_data_len, RdmBuffer *buffer)
Serialize an RDM ACK_OVERFLOW response to a previously-received command.
Definition: message.c:290
unsigned int rdm_get_ack_timer_delay(const uint8_t *param_data)
Get the ACK_TIMER delay in milliseconds from an ACK_TIMER message.
Definition: message.c:686
etcpal_error_t rdm_pack_dub_response(const RdmUid *responder_uid, RdmBuffer *buffer)
Serialize an RDM DISC_UNIQUE_BRANCH response.
Definition: message.c:396
etcpal_error_t rdm_pack_response(const RdmCommandHeader *cmd_header, uint8_t msg_count, const uint8_t *response_data, uint8_t response_data_len, RdmBuffer *buffer)
Serialize an RDM ACK response to a previously-received command.
Definition: message.c:251
etcpal_error_t rdm_unpack_response(const RdmBuffer *buffer, RdmResponseHeader *resp_header, const uint8_t **param_data, uint8_t *param_data_len)
Deserialize an RDM response from its wire format.
Definition: message.c:602
etcpal_error_t rdm_append_parameter_data(RdmBuffer *buffer, const uint8_t *additional_data, uint8_t additional_data_len)
Add additional parameter data to an already-serialized RDM command.
Definition: message.c:524
bool rdm_command_header_is_valid(const RdmCommandHeader *cmd_header)
Determine whether the values contained in a command header are valid for an RDM command.
Definition: message.c:137
etcpal_error_t rdm_unpack_dub_response(const RdmBuffer *buffer, RdmUid *responder_uid)
Deserialize an RDM DISC_UNIQUE_BRANCH from its wire format.
Definition: message.c:652
bool rdm_validate_msg(const RdmBuffer *buffer)
Perform basic validation of a packed RDM message.
Definition: message.c:115
etcpal_error_t rdm_pack_timer_response(const RdmCommandHeader *cmd_header, uint8_t msg_count, unsigned int delay_time_ms, RdmBuffer *buffer)
Serialize an RDM ACK_TIMER response to a previously-received command.
Definition: message.c:358
rdm_command_class_t
Definition: message.h:84
@ kRdmResponseTypeAck
Definition: message.h:104
@ kRdmResponseTypeNackReason
Definition: message.h:114
@ kRdmResponseTypeAckTimer
Definition: message.h:109
@ kRdmResponseTypeAckOverflow
Definition: message.h:119
@ kRdmNRInvalidEndpointMode
Definition: message.h:153
@ kRdmNRHardwareFault
Definition: message.h:130
@ kRdmNRUnsupportedCommandClass
Definition: message.h:137
@ kRdmNRProxyBufferFull
Definition: message.h:147
@ kRdmNRUnknownScope
Definition: message.h:157
@ kRdmNRInvalidStaticConfigType
Definition: message.h:159
@ kRdmNRInvalidIpv6Address
Definition: message.h:163
@ kRdmNRInvalidPort
Definition: message.h:165
@ kRdmNRWriteProtect
Definition: message.h:135
@ kRdmNRFormatError
Definition: message.h:128
@ kRdmNRUnknownUid
Definition: message.h:155
@ kRdmNRDataOutOfRange
Definition: message.h:139
@ kRdmNRUnknownPid
Definition: message.h:126
@ kRdmNRInvalidIpv4Address
Definition: message.h:161
@ kRdmNREndpointNumberInvalid
Definition: message.h:151
@ kRdmNRProxyReject
Definition: message.h:133
@ kRdmNRPacketSizeUnsupported
Definition: message.h:143
@ kRdmNRBufferFull
Definition: message.h:141
@ kRdmNRSubDeviceOutOfRange
Definition: message.h:145
@ kRdmNRActionNotSupported
Definition: message.h:149
@ kRdmCCSetCommandResponse
Definition: message.h:96
@ kRdmCCDiscoveryCommand
Definition: message.h:86
@ kRdmCCGetCommand
Definition: message.h:90
@ kRdmCCDiscoveryCommandResponse
Definition: message.h:88
@ kRdmCCGetCommandResponse
Definition: message.h:92
@ kRdmCCSetCommand
Definition: message.h:94
Definition: message.h:177
uint8_t data[RDM_MAX_BYTES]
Definition: message.h:178
size_t data_len
Definition: message.h:179
Definition: message.h:201
uint16_t subdevice
Definition: message.h:211
RdmUid source_uid
Definition: message.h:203
uint16_t param_id
Definition: message.h:218
rdm_command_class_t command_class
Definition: message.h:213
uint8_t transaction_num
Definition: message.h:207
RdmUid dest_uid
Definition: message.h:205
uint8_t port_id
Definition: message.h:209
Definition: message.h:226
uint16_t subdevice
Definition: message.h:238
RdmUid source_uid
Definition: message.h:228
uint16_t param_id
Definition: message.h:245
uint8_t msg_count
Definition: message.h:236
rdm_command_class_t command_class
Definition: message.h:240
rdm_response_type_t resp_type
Definition: message.h:234
uint8_t transaction_num
Definition: message.h:232
RdmUid dest_uid
Definition: message.h:230
Definition: uid.h:65
A type and helper functions for the Unique ID (UID) used in the RDM family of protocols.