18static size_t write_segment(uint8_t *p,
size_t cap, uint8_t logical_type, uint16_t
id)
26 p[0] = (uint8_t)(CIP_SEG_LOGICAL | logical_type | CIP_SEG_8BIT);
34 p[0] = (uint8_t)(CIP_SEG_LOGICAL | logical_type | CIP_SEG_16BIT);
36 p[2] = (uint8_t)(
id & 0xFF);
37 p[3] = (uint8_t)(
id >> 8);
41size_t pc_cip_build_epath(uint8_t *buf,
size_t cap, uint16_t class_id, uint16_t instance_id, uint16_t attribute_id,
49 size_t s = write_segment(buf + p, cap - p, CIP_SEG_CLASS, class_id);
55 s = write_segment(buf + p, cap - p, CIP_SEG_INSTANCE, instance_id);
63 s = write_segment(buf + p, cap - p, CIP_SEG_ATTRIBUTE, attribute_id);
73size_t pc_cip_build_request(uint8_t *buf,
size_t cap, uint8_t service,
const uint8_t *epath,
size_t epath_len,
74 const uint8_t *data,
size_t data_len)
77 if (!buf || !epath || (epath_len & 1) || (epath_len / 2) > 0xFF || (data_len && !data))
81 size_t total = 2 + epath_len + data_len;
88 buf[p++] = (uint8_t)(epath_len / 2);
89 memcpy(buf + p, epath, epath_len);
93 memcpy(buf + p, data, data_len);
99size_t pc_cip_build_get_attr_single(uint8_t *buf,
size_t cap, uint16_t class_id, uint16_t instance_id,
100 uint16_t attribute_id)
103 size_t elen = pc_cip_build_epath(epath,
sizeof(epath), class_id, instance_id, attribute_id,
true);
111 return pc_cip_build_request(buf, cap, CIP_SC_GET_ATTR_SINGLE, epath, elen,
nullptr, 0);
114size_t pc_cip_build_get_attr_all(uint8_t *buf,
size_t cap, uint16_t class_id, uint16_t instance_id)
117 size_t elen = pc_cip_build_epath(epath,
sizeof(epath), class_id, instance_id, 0,
false);
125 return pc_cip_build_request(buf, cap, CIP_SC_GET_ATTR_ALL, epath, elen,
nullptr, 0);
128size_t pc_cip_build_set_attr_single(uint8_t *buf,
size_t cap, uint16_t class_id, uint16_t instance_id,
129 uint16_t attribute_id,
const uint8_t *value,
size_t value_len)
132 size_t elen = pc_cip_build_epath(epath,
sizeof(epath), class_id, instance_id, attribute_id,
true);
140 return pc_cip_build_request(buf, cap, CIP_SC_SET_ATTR_SINGLE, epath, elen, value, value_len);
143bool pc_cip_parse_response(
const uint8_t *buf,
size_t len, CipResponse *out)
145 if (!buf || !out || len < 4)
149 out->service = buf[0];
150 out->general_status = buf[2];
151 uint8_t addl_words = buf[3];
152 size_t data_start = 4 + (size_t)addl_words * 2;
153 if (data_start > len)
157 out->data = buf + data_start;
158 out->data_len = len - data_start;
CIP (Common Industrial Protocol) message codec (PC_ENABLE_CIP) - zero-heap request builder + response...