DeterministicESPAsyncWebServer v6.27.1
Zero-allocation, bounded-execution async HTTP server for ESP32
Loading...
Searching...
No Matches
cip.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 cip.h
6 * @brief CIP (Common Industrial Protocol) message codec (DETWS_ENABLE_CIP) - zero-heap
7 * request builder + response parser for the message that rides inside an EtherNet/IP
8 * Unconnected Data item (services/enip). Together they form a working CIP read path.
9 *
10 * A CIP message request is:
11 * @code
12 * Service(1) RequestPathSize(1, in 16-bit words) RequestPath(EPATH) ServiceData
13 * @endcode
14 * The EPATH addresses an object with logical segments. A logical segment byte is
15 * `0x20 | logical-type | format`, where logical-type is class (0x00), instance (0x04), or
16 * attribute (0x10), and format is 8-bit (0x00, then a 1-octet id) or 16-bit (0x01, then a
17 * pad octet and a little-endian 2-octet id). A response is `Service|0x80 reserved(0)
18 * GeneralStatus(1) AdditionalStatusSize(1, words) [additional status] ServiceData`.
19 *
20 * Service codes + the logical-segment encoding are verified against the Wireshark CIP
21 * dissector. This codec is the CIP message; wrap it with `eip_build_send_rr_data`.
22 *
23 * @author Douglas Quigg (dstroy0)
24 * @date 2026
25 */
26
27#ifndef DETERMINISTICESPASYNCWEBSERVER_CIP_H
28#define DETERMINISTICESPASYNCWEBSERVER_CIP_H
29
30#include "ServerConfig.h"
31
32#if DETWS_ENABLE_CIP
33
34#include <stddef.h>
35#include <stdint.h>
36
37// Common service codes.
38#define CIP_SC_GET_ATTR_ALL 0x01
39#define CIP_SC_GET_ATTR_LIST 0x03
40#define CIP_SC_SET_ATTR_LIST 0x04
41#define CIP_SC_GET_ATTR_SINGLE 0x0E
42#define CIP_SC_SET_ATTR_SINGLE 0x10
43#define CIP_REPLY_FLAG 0x80 ///< OR'd into the service code in a reply
44
45// Logical-segment EPATH encoding (segment byte = base | logical-type | format).
46#define CIP_SEG_LOGICAL 0x20 ///< logical segment, segment-type bits
47#define CIP_SEG_CLASS 0x00 ///< logical type: class id
48#define CIP_SEG_INSTANCE 0x04 ///< logical type: instance id
49#define CIP_SEG_ATTRIBUTE 0x10 ///< logical type: attribute id
50#define CIP_SEG_8BIT 0x00 ///< format: an 8-bit id follows
51#define CIP_SEG_16BIT 0x01 ///< format: a pad octet then a 16-bit (LE) id follows
52
53#define CIP_STATUS_SUCCESS 0x00 ///< General Status: success
54
55/**
56 * @brief Build a class/instance[/attribute] EPATH (logical segments) into @p buf.
57 * @param with_attribute include the attribute segment.
58 * @return EPATH length in octets (always even / word-aligned), or 0 on overflow.
59 */
60size_t cip_build_epath(uint8_t *buf, size_t cap, uint16_t class_id, uint16_t instance_id, uint16_t attribute_id,
61 bool with_attribute);
62
63/** @brief Build a CIP request: service + path size (words) + EPATH + service data. */
64size_t cip_build_request(uint8_t *buf, size_t cap, uint8_t service, const uint8_t *epath, size_t epath_len,
65 const uint8_t *data, size_t data_len);
66
67/** @brief Build a Get_Attribute_Single request for class/instance/attribute. */
68size_t cip_build_get_attr_single(uint8_t *buf, size_t cap, uint16_t class_id, uint16_t instance_id,
69 uint16_t attribute_id);
70
71/** @brief A parsed CIP response. @ref data points INTO the source buffer. */
72struct CipResponse
73{
74 uint8_t service; ///< reply service (the 0x80 reply bit is set)
75 uint8_t general_status; ///< CIP_STATUS_SUCCESS on success
76 const uint8_t *data; ///< service data (the attribute value on a read)
77 size_t data_len;
78};
79
80/** @brief Parse a CIP response (service + status + additional status + data). */
81bool cip_parse_response(const uint8_t *buf, size_t len, CipResponse *out);
82
83#endif // DETWS_ENABLE_CIP
84
85#endif // DETERMINISTICESPASYNCWEBSERVER_CIP_H
User-facing configuration for DeterministicESPAsyncWebServer.