DeterministicESPAsyncWebServer v6.28.0
Zero-allocation, bounded-execution async HTTP server for ESP32
Loading...
Searching...
No Matches
profinet.h
Go to the documentation of this file.
1// Copyright (C) 2026 Douglas Quigg (dstroy0) <dquigg123@gmail.com>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4/**
5 * @file profinet.h
6 * @brief PROFINET DCP (Discovery and Configuration Protocol) frame codec (DETWS_ENABLE_PROFINET).
7 *
8 * DCP is how PROFINET IO-Devices are discovered and named on the wire before an IO connection exists.
9 * It rides raw L2 (ethertype 0x8892, PROFINET RT; see services/rawl2) with a fixed 10-octet frame header
10 * followed by DCP blocks:
11 *
12 * Header: frameID(2) serviceID(1) serviceType(1) xid(4) responseDelay/reserved(2) dataLength(2)
13 * Block: option(1) suboption(1) blockLength(2) [blockInfo(2) for Set/Get responses] value...
14 *
15 * FrameIDs: 0xFEFE Identify-request (multicast), 0xFEFF Identify-response, 0xFEFD Get/Set. This builds
16 * the DCP header + blocks and parses them (walking each block via a callback), so a device answers
17 * Identify (with its NameOfStation / IP / device id) and handles Set (assign name/IP). Pure, zero heap,
18 * host-testable; the raw-L2 transmit is the device step.
19 */
20
21#ifndef DETERMINISTICESPASYNCWEBSERVER_PROFINET_H
22#define DETERMINISTICESPASYNCWEBSERVER_PROFINET_H
23
24#include "ServerConfig.h"
25#include <stddef.h>
26#include <stdint.h>
27
28#if DETWS_ENABLE_PROFINET
29
30struct Pn
31{
32 static constexpr uint16_t PN_FRAMEID_DCP_HELLO = 0xFEFC;
33 static constexpr uint16_t PN_FRAMEID_DCP_GETSET = 0xFEFD;
34 static constexpr uint16_t PN_FRAMEID_DCP_IDENT_REQ = 0xFEFE;
35 static constexpr uint16_t PN_FRAMEID_DCP_IDENT_RES = 0xFEFF;
36 static constexpr uint16_t PN_DCP_SERVICE_GET = 0x03;
37 static constexpr uint16_t PN_DCP_SERVICE_SET = 0x04;
38 static constexpr uint16_t PN_DCP_SERVICE_IDENTIFY = 0x05;
39 static constexpr uint16_t PN_DCP_TYPE_REQUEST = 0x00;
40 static constexpr uint16_t PN_DCP_TYPE_RESPONSE_SUCCESS = 0x01;
41 static constexpr uint16_t PN_DCP_OPT_IP = 0x01;
42 static constexpr uint16_t PN_DCP_SUB_IP_PARAM = 0x02; ///< IP address / subnet / gateway.
43 static constexpr uint16_t PN_DCP_OPT_DEVICE = 0x02;
44 static constexpr uint16_t PN_DCP_SUB_DEV_NAME_OF_STATION = 0x02;
45 static constexpr uint16_t PN_DCP_SUB_DEV_ID = 0x03;
46 static constexpr uint16_t PN_DCP_OPT_ALL = 0xFF;
47 static constexpr uint16_t PN_DCP_SUB_ALL = 0xFF;
48 static constexpr uint16_t PN_DCP_HDR_LEN = 10;
49};
50
51/**
52 * @brief Build a DCP frame header into @p out (>= 10 bytes). @return 10, or 0 if it will not fit.
53 * @param data_length the total length of the DCP blocks that follow (filled into the header).
54 */
55size_t detws_pn_dcp_header(uint16_t frame_id, uint8_t service_id, uint8_t service_type, uint32_t xid,
56 uint16_t data_length, uint8_t *out, size_t cap);
57
58/**
59 * @brief Append a DCP block `[option][suboption][blockLength][value...]` (no blockInfo).
60 * @return the block length written (4 + value_len, padded to even per DCP), or 0 on overflow.
61 *
62 * DCP blocks are padded to an even length with a 0x00 filler octet that is NOT counted in blockLength.
63 */
64size_t detws_pn_dcp_block(uint8_t option, uint8_t suboption, const uint8_t *value, size_t value_len, uint8_t *out,
65 size_t cap);
66
67/** @brief A parsed DCP frame header. */
68struct PnDcpHeader
69{
70 uint16_t frame_id;
71 uint8_t service_id;
72 uint8_t service_type;
73 uint32_t xid;
74 uint16_t data_length;
75};
76
77/** @brief Parse the 10-octet DCP header. @return true if @p len >= 10. */
78bool detws_pn_dcp_parse_header(const uint8_t *frame, size_t len, PnDcpHeader *out);
79
80/** @brief One DCP block surfaced by detws_pn_dcp_walk. */
81typedef void (*DetwsPnDcpBlockCb)(uint8_t option, uint8_t suboption, const uint8_t *value, size_t value_len, void *arg);
82
83/**
84 * @brief Walk the DCP blocks after the header (@p blocks points at header+10, @p len = dataLength).
85 * @return true if every block fits; invokes @p cb per block (value excludes the even-pad filler).
86 */
87bool detws_pn_dcp_walk(const uint8_t *blocks, size_t len, DetwsPnDcpBlockCb cb, void *arg);
88
89#endif // DETWS_ENABLE_PROFINET
90#endif // DETERMINISTICESPASYNCWEBSERVER_PROFINET_H
User-facing configuration for DeterministicESPAsyncWebServer.