Skip to content

Commit 4090dba

Browse files
committed
Temporary checkin.
1 parent f409c9d commit 4090dba

16 files changed

+3690
-177
lines changed

examples/ethernet_ip_example.c

Lines changed: 408 additions & 0 deletions
Large diffs are not rendered by default.

examples/ethernet_ip_example.h

Lines changed: 223 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,223 @@
1+
#ifndef ETHERNET_IP_EXAMPLE_H
2+
#define ETHERNET_IP_EXAMPLE_H
3+
4+
#include "ptk_pdu_custom.h"
5+
#include <stdio.h>
6+
7+
/**
8+
* EtherNet/IP Protocol Example using Extended PDU System
9+
*
10+
* This demonstrates how to handle complex, variable-sized protocols
11+
* like EtherNet/IP with the extended PDU macro system.
12+
*/
13+
14+
/**
15+
* Custom types for EtherNet/IP
16+
*/
17+
18+
/* CIP Path - variable length routing path */
19+
typedef struct {
20+
uint8_t path_size; // Size in 16-bit words
21+
uint8_t* path_data; // Variable-length path data
22+
size_t capacity; // Allocated capacity
23+
} cip_path_t;
24+
25+
/* CIP Data - variable length application data */
26+
typedef struct {
27+
uint16_t data_length;
28+
uint8_t* data;
29+
size_t capacity;
30+
} cip_data_t;
31+
32+
/* CIP Service codes */
33+
typedef enum {
34+
CIP_SERVICE_GET_ATTRIBUTE_ALL = 0x01,
35+
CIP_SERVICE_SET_ATTRIBUTE_ALL = 0x02,
36+
CIP_SERVICE_GET_ATTRIBUTE_SINGLE = 0x0E,
37+
CIP_SERVICE_SET_ATTRIBUTE_SINGLE = 0x10,
38+
CIP_SERVICE_MULTIPLE_SERVICE_PACKET = 0x0A
39+
} cip_service_t;
40+
41+
/* CIP Status codes */
42+
typedef enum {
43+
CIP_STATUS_SUCCESS = 0x00,
44+
CIP_STATUS_CONNECTION_FAILURE = 0x01,
45+
CIP_STATUS_RESOURCE_UNAVAILABLE = 0x02,
46+
CIP_STATUS_INVALID_PARAMETER = 0x09,
47+
CIP_STATUS_PATH_SEGMENT_ERROR = 0x04
48+
} cip_status_t;
49+
50+
/**
51+
* EtherNet/IP Encapsulation Header
52+
*/
53+
#define PTK_PDU_FIELDS_enip_header(X) \
54+
X(PTK_PDU_U16, command) \
55+
X(PTK_PDU_U16, length) \
56+
X(PTK_PDU_U32, session_handle) \
57+
X(PTK_PDU_U32, status) \
58+
X(PTK_PDU_U64, sender_context) \
59+
X(PTK_PDU_U32, options)
60+
61+
PTK_DECLARE_PDU(enip_header)
62+
63+
/**
64+
* CIP Request - demonstrates custom types
65+
*/
66+
#define PTK_PDU_FIELDS_cip_request(X) \
67+
X(PTK_PDU_U8, service) \
68+
X(PTK_PDU_CUSTOM, path, cip_path_t) \
69+
X(PTK_PDU_CUSTOM, data, cip_data_t)
70+
71+
PTK_DECLARE_PDU_CUSTOM(cip_request)
72+
73+
/**
74+
* CIP Response with conditional error data
75+
*/
76+
#define PTK_PDU_FIELDS_cip_response(X) \
77+
X(PTK_PDU_U8, service) \
78+
X(PTK_PDU_U8, reserved) \
79+
X(PTK_PDU_U8, general_status) \
80+
X(PTK_PDU_U8, additional_status_size) \
81+
X(PTK_PDU_CONDITIONAL, general_status, 0x00, PTK_PDU_CUSTOM, response_data, cip_data_t) \
82+
X(PTK_PDU_CONDITIONAL, general_status, !0x00, PTK_PDU_U16, extended_status)
83+
84+
PTK_DECLARE_PDU_CUSTOM(cip_response)
85+
86+
/**
87+
* Multiple Service Packet - demonstrates arrays
88+
*/
89+
typedef struct {
90+
uint16_t service_offset;
91+
} service_offset_t;
92+
93+
#define PTK_PDU_FIELDS_multiple_service_packet(X) \
94+
X(PTK_PDU_U16, number_of_services) \
95+
X(PTK_PDU_ARRAY, service_offsets, service_offset_t, number_of_services) \
96+
/* Variable-length service data follows */
97+
98+
PTK_DECLARE_PDU_CUSTOM(multiple_service_packet)
99+
100+
/**
101+
* Forward/Open Request - complex EtherNet/IP example
102+
*/
103+
#define PTK_PDU_FIELDS_forward_open_request(X) \
104+
X(PTK_PDU_U8, priority_tick_time) \
105+
X(PTK_PDU_U8, timeout_ticks) \
106+
X(PTK_PDU_U32, originator_to_target_connection_id) \
107+
X(PTK_PDU_U32, target_to_originator_connection_id) \
108+
X(PTK_PDU_U16, connection_serial_number) \
109+
X(PTK_PDU_U16, originator_vendor_id) \
110+
X(PTK_PDU_U32, originator_serial_number) \
111+
X(PTK_PDU_U8, connection_timeout_multiplier) \
112+
X(PTK_PDU_U8, reserved1) \
113+
X(PTK_PDU_U8, reserved2) \
114+
X(PTK_PDU_U8, reserved3) \
115+
X(PTK_PDU_U32, originator_to_target_rpi) \
116+
X(PTK_PDU_U16, originator_to_target_connection_parameters) \
117+
X(PTK_PDU_U32, target_to_originator_rpi) \
118+
X(PTK_PDU_U16, target_to_originator_connection_parameters) \
119+
X(PTK_PDU_U8, transport_type_trigger) \
120+
X(PTK_PDU_U8, connection_path_size) \
121+
X(PTK_PDU_CUSTOM, connection_path, cip_path_t)
122+
123+
PTK_DECLARE_PDU_CUSTOM(forward_open_request)
124+
125+
/**
126+
* Identity Object Response - demonstrates nested structures
127+
*/
128+
typedef struct {
129+
uint16_t vendor_id;
130+
uint16_t device_type;
131+
uint16_t product_code;
132+
uint8_t major_revision;
133+
uint8_t minor_revision;
134+
uint16_t status;
135+
uint32_t serial_number;
136+
uint8_t product_name_length;
137+
char product_name[32];
138+
} identity_object_t;
139+
140+
#define PTK_PDU_FIELDS_identity_response(X) \
141+
X(PTK_PDU_CUSTOM, identity, identity_object_t)
142+
143+
PTK_DECLARE_PDU_CUSTOM(identity_response)
144+
145+
/**
146+
* Custom type implementations
147+
*/
148+
149+
/* CIP Path functions */
150+
ptk_status_t cip_path_serialize(ptk_slice_bytes_t* slice, const cip_path_t* path, ptk_endian_t endian);
151+
ptk_status_t cip_path_deserialize(ptk_slice_bytes_t* slice, cip_path_t* path, ptk_endian_t endian);
152+
size_t cip_path_size(const cip_path_t* path);
153+
void cip_path_init(cip_path_t* path, size_t capacity);
154+
void cip_path_destroy(cip_path_t* path);
155+
void cip_path_print(const cip_path_t* path);
156+
157+
/* CIP Data functions */
158+
ptk_status_t cip_data_serialize(ptk_slice_bytes_t* slice, const cip_data_t* data, ptk_endian_t endian);
159+
ptk_status_t cip_data_deserialize(ptk_slice_bytes_t* slice, cip_data_t* data, ptk_endian_t endian);
160+
size_t cip_data_size(const cip_data_t* data);
161+
void cip_data_init(cip_data_t* data, size_t capacity);
162+
void cip_data_destroy(cip_data_t* data);
163+
void cip_data_print(const cip_data_t* data);
164+
165+
/* Identity Object functions */
166+
ptk_status_t identity_object_serialize(ptk_slice_bytes_t* slice, const identity_object_t* obj, ptk_endian_t endian);
167+
ptk_status_t identity_object_deserialize(ptk_slice_bytes_t* slice, identity_object_t* obj, ptk_endian_t endian);
168+
size_t identity_object_size(const identity_object_t* obj);
169+
void identity_object_init(identity_object_t* obj);
170+
void identity_object_destroy(identity_object_t* obj);
171+
void identity_object_print(const identity_object_t* obj);
172+
173+
/**
174+
* Helper functions for EtherNet/IP protocols
175+
*/
176+
177+
/* Build a simple class/instance/attribute path */
178+
ptk_status_t cip_path_build_simple(cip_path_t* path, uint16_t class_id, uint16_t instance_id, uint16_t attribute_id);
179+
180+
/* Parse a CIP path and extract routing information */
181+
ptk_status_t cip_path_parse(const cip_path_t* path, uint16_t* class_id, uint16_t* instance_id, uint16_t* attribute_id);
182+
183+
/* Build CIP data from raw bytes */
184+
ptk_status_t cip_data_from_bytes(cip_data_t* data, const uint8_t* bytes, size_t length);
185+
186+
/* EtherNet/IP command constants */
187+
#define ENIP_CMD_NOP 0x0000
188+
#define ENIP_CMD_LIST_SERVICES 0x0004
189+
#define ENIP_CMD_LIST_IDENTITY 0x0063
190+
#define ENIP_CMD_LIST_INTERFACES 0x0064
191+
#define ENIP_CMD_REGISTER_SESSION 0x0065
192+
#define ENIP_CMD_UNREGISTER_SESSION 0x0066
193+
#define ENIP_CMD_SEND_RR_DATA 0x006F
194+
#define ENIP_CMD_SEND_UNIT_DATA 0x0070
195+
196+
/* EtherNet/IP status constants */
197+
#define ENIP_STATUS_SUCCESS 0x0000
198+
#define ENIP_STATUS_INVALID_COMMAND 0x0001
199+
#define ENIP_STATUS_INSUFFICIENT_MEMORY 0x0002
200+
#define ENIP_STATUS_INCORRECT_DATA 0x0003
201+
#define ENIP_STATUS_INVALID_SESSION 0x0064
202+
#define ENIP_STATUS_INVALID_LENGTH 0x0065
203+
#define ENIP_STATUS_UNSUPPORTED_PROTOCOL 0x0069
204+
205+
/**
206+
* Utility macros for common EtherNet/IP patterns
207+
*/
208+
209+
/* Create a Get Attribute All request */
210+
#define ENIP_CREATE_GET_ATTR_ALL_REQUEST(class_id, instance_id) \
211+
do { \
212+
cip_request_t request; \
213+
cip_request_init(&request); \
214+
request.service = CIP_SERVICE_GET_ATTRIBUTE_ALL; \
215+
cip_path_build_simple(&request.path, class_id, instance_id, 0); \
216+
cip_data_init(&request.data, 0); \
217+
} while(0)
218+
219+
/* Create an identity request */
220+
#define ENIP_CREATE_IDENTITY_REQUEST() \
221+
ENIP_CREATE_GET_ATTR_ALL_REQUEST(0x01, 0x01)
222+
223+
#endif /* ETHERNET_IP_EXAMPLE_H */

0 commit comments

Comments
 (0)