11#if DETWS_ENABLE_PROFINET
15size_t detws_pn_dcp_header(uint16_t frame_id, uint8_t service_id, uint8_t service_type, uint32_t xid,
16 uint16_t data_length, uint8_t *out,
size_t cap)
18 if (!out || cap < Pn::PN_DCP_HDR_LEN)
20 out[0] = (uint8_t)(frame_id >> 8);
21 out[1] = (uint8_t)frame_id;
23 out[3] = service_type;
24 out[4] = (uint8_t)(xid >> 24);
25 out[5] = (uint8_t)(xid >> 16);
26 out[6] = (uint8_t)(xid >> 8);
27 out[7] = (uint8_t)xid;
29 out[8] = (uint8_t)(data_length >> 8);
30 out[9] = (uint8_t)data_length;
31 return Pn::PN_DCP_HDR_LEN;
34size_t detws_pn_dcp_block(uint8_t option, uint8_t suboption,
const uint8_t *value,
size_t value_len, uint8_t *out,
37 if (!out || (value_len && !value) || value_len > 0xFFFF)
39 bool pad = (value_len & 1) != 0;
40 size_t n = 4 + value_len + (pad ? 1 : 0);
45 out[2] = (uint8_t)(value_len >> 8);
46 out[3] = (uint8_t)value_len;
48 memcpy(out + 4, value, value_len);
50 out[4 + value_len] = 0x00;
54bool detws_pn_dcp_parse_header(
const uint8_t *frame,
size_t len, PnDcpHeader *out)
56 if (!frame || !out || len < Pn::PN_DCP_HDR_LEN)
58 out->frame_id = (uint16_t)((frame[0] << 8) | frame[1]);
59 out->service_id = frame[2];
60 out->service_type = frame[3];
61 out->xid = ((uint32_t)frame[4] << 24) | ((uint32_t)frame[5] << 16) | ((uint32_t)frame[6] << 8) | frame[7];
62 out->data_length = (uint16_t)((frame[8] << 8) | frame[9]);
66bool detws_pn_dcp_walk(
const uint8_t *blocks,
size_t len, DetwsPnDcpBlockCb cb,
void *arg)
69 while (off + 4 <= len)
71 uint8_t option = blocks[off];
72 uint8_t suboption = blocks[off + 1];
73 uint16_t blen = (uint16_t)((blocks[off + 2] << 8) | blocks[off + 3]);
74 if (off + 4 + blen > len)
77 cb(option, suboption, blen ? (blocks + off + 4) : nullptr, blen, arg);
78 size_t adv = 4 + blen + ((blen & 1) ? 1 : 0);
PROFINET DCP (Discovery and Configuration Protocol) frame codec (DETWS_ENABLE_PROFINET).