15size_t pc_pn_dcp_header(uint16_t frame_id, uint8_t service_id, uint8_t service_type, uint32_t xid, uint16_t data_length,
16 uint8_t *out,
size_t cap)
18 if (!out || cap < Pn::PN_DCP_HDR_LEN)
22 out[0] = (uint8_t)(frame_id >> 8);
23 out[1] = (uint8_t)frame_id;
25 out[3] = service_type;
26 out[4] = (uint8_t)(xid >> 24);
27 out[5] = (uint8_t)(xid >> 16);
28 out[6] = (uint8_t)(xid >> 8);
29 out[7] = (uint8_t)xid;
31 out[8] = (uint8_t)(data_length >> 8);
32 out[9] = (uint8_t)data_length;
33 return Pn::PN_DCP_HDR_LEN;
36size_t pc_pn_dcp_block(uint8_t option, uint8_t suboption,
const uint8_t *value,
size_t value_len, uint8_t *out,
39 if (!out || (value_len && !value) || value_len > 0xFFFF)
43 bool pad = (value_len & 1) != 0;
44 size_t n = 4 + value_len + (pad ? 1 : 0);
51 out[2] = (uint8_t)(value_len >> 8);
52 out[3] = (uint8_t)value_len;
55 memcpy(out + 4, value, value_len);
59 out[4 + value_len] = 0x00;
64bool pc_pn_dcp_parse_header(
const uint8_t *frame,
size_t len, PnDcpHeader *out)
66 if (!frame || !out || len < Pn::PN_DCP_HDR_LEN)
70 out->frame_id = (uint16_t)((frame[0] << 8) | frame[1]);
71 out->service_id = frame[2];
72 out->service_type = frame[3];
73 out->xid = ((uint32_t)frame[4] << 24) | ((uint32_t)frame[5] << 16) | ((uint32_t)frame[6] << 8) | frame[7];
74 out->data_length = (uint16_t)((frame[8] << 8) | frame[9]);
78bool pc_pn_dcp_walk(
const uint8_t *blocks,
size_t len, pc_pn_dcp_block_cb cb,
void *arg)
81 while (off + 4 <= len)
83 uint8_t option = blocks[off];
84 uint8_t suboption = blocks[off + 1];
85 uint16_t blen = (uint16_t)((blocks[off + 2] << 8) | blocks[off + 3]);
86 if (off + 4 + blen > len)
92 cb(option, suboption, blen ? (blocks + off + 4) : nullptr, blen, arg);
94 size_t adv = 4 + blen + ((blen & 1) ? 1 : 0);
PROFINET DCP (Discovery and Configuration Protocol) frame codec (PC_ENABLE_PROFINET).