18static size_t write_segment(uint8_t *p,
size_t cap, uint8_t logical_type, uint16_t
id)
24 p[0] = (uint8_t)(CIP_SEG_LOGICAL | logical_type | CIP_SEG_8BIT);
30 p[0] = (uint8_t)(CIP_SEG_LOGICAL | logical_type | CIP_SEG_16BIT);
32 p[2] = (uint8_t)(
id & 0xFF);
33 p[3] = (uint8_t)(
id >> 8);
37size_t cip_build_epath(uint8_t *buf,
size_t cap, uint16_t class_id, uint16_t instance_id, uint16_t attribute_id,
43 size_t s = write_segment(buf + p, cap - p, CIP_SEG_CLASS, class_id);
47 s = write_segment(buf + p, cap - p, CIP_SEG_INSTANCE, instance_id);
53 s = write_segment(buf + p, cap - p, CIP_SEG_ATTRIBUTE, attribute_id);
61size_t cip_build_request(uint8_t *buf,
size_t cap, uint8_t service,
const uint8_t *epath,
size_t epath_len,
62 const uint8_t *data,
size_t data_len)
65 if (!buf || !epath || (epath_len & 1) || (epath_len / 2) > 0xFF || (data_len && !data))
67 size_t total = 2 + epath_len + data_len;
72 buf[p++] = (uint8_t)(epath_len / 2);
73 memcpy(buf + p, epath, epath_len);
77 memcpy(buf + p, data, data_len);
83size_t cip_build_get_attr_single(uint8_t *buf,
size_t cap, uint16_t class_id, uint16_t instance_id,
84 uint16_t attribute_id)
87 size_t elen = cip_build_epath(epath,
sizeof(epath), class_id, instance_id, attribute_id,
true);
91 return cip_build_request(buf, cap, CIP_SC_GET_ATTR_SINGLE, epath, elen,
nullptr, 0);
94bool cip_parse_response(
const uint8_t *buf,
size_t len, CipResponse *out)
96 if (!buf || !out || len < 4)
98 out->service = buf[0];
99 out->general_status = buf[2];
100 uint8_t addl_words = buf[3];
101 size_t data_start = 4 + (size_t)addl_words * 2;
102 if (data_start > len)
104 out->data = buf + data_start;
105 out->data_len = len - data_start;
CIP (Common Industrial Protocol) message codec (DETWS_ENABLE_CIP) - zero-heap request builder + respo...