11 #include "opener_user_conf.h"
78 struct sockaddr *originator_address,
79 const int encapsulation_session) {
88 instance_number == 0 ?
" (class object)" :
"");
102 message_router_request,
103 message_router_response,
105 encapsulation_session);
112 message_router_request->
service);
127 | message_router_request->
service);
133 const int number_of_instances) {
138 cip_class->class_name);
140 next_instance = &cip_class->instances;
141 while (*next_instance)
143 next_instance = &(*next_instance)->
next;
154 cip_class->number_of_instances += number_of_instances;
156 for (
size_t i = 0; i < number_of_instances; i++)
158 *next_instance = current_instance;
163 if (cip_class->number_of_attributes)
166 cip_class->number_of_attributes,
170 next_instance = ¤t_instance->
next;
175 return first_instance;
182 if (NULL == instance) {
190 const int number_of_class_attributes,
191 const EipUint32 highest_class_attribute_number,
192 const int number_of_class_services,
193 const int number_of_instance_attributes,
194 const EipUint32 highest_instance_attribute_number,
195 const int number_of_instance_services,
196 const int number_of_instances,
219 class->number_of_instances = 0;
220 class->instances = 0;
221 class->number_of_attributes = number_of_instance_attributes;
222 class->highest_attribute_number = highest_instance_attribute_number;
223 class->number_of_services = number_of_instance_services;
225 class->class_name = name;
226 meta_class->class_id = 0xffffffff;
227 meta_class->number_of_instances = 1;
229 meta_class->number_of_attributes = number_of_class_attributes + 7;
230 meta_class->highest_attribute_number = highest_class_attribute_number;
231 meta_class->number_of_services = number_of_class_services;
232 meta_class->class_name = (
char *)
CipCalloc(1, strlen(name) + 6);
233 snprintf(meta_class->class_name, strlen(name) + 6,
"meta-%s", name);
236 class->class_instance.instance_number = 0;
237 class->class_instance.attributes = 0;
238 class->class_instance.cip_class = meta_class;
239 class->class_instance.next = 0;
241 meta_class->class_instance.instance_number = 0xffffffff;
242 meta_class->class_instance.attributes = 0;
243 meta_class->class_instance.cip_class = 0;
244 meta_class->class_instance.next = 0;
258 if (number_of_instances > 0) {
273 (
void *) &class->number_of_instances,
276 (
void *) &class->number_of_instances,
283 (
void *) &meta_class->highest_attribute_number,
286 (
void *) &class->highest_attribute_number,
293 if (number_of_class_services > 0) {
294 if (number_of_class_services > 1) {
299 "GetAttributeSingle");
311 CipClass *
class = instance->cip_class;
316 if (attribute->
data == NULL) {
318 attribute->
type = cip_type;
320 attribute->
data = data;
322 OPENER_ASSERT(attribute_number <= class->highest_attribute_number)
326 class->get_single_bit_mask[index] |=
328 1 << (attribute_number) % 8 : 0;
329 class->get_all_bit_mask[index] |=
330 (cip_flags &
kGetableAll) ? 1 << (attribute_number) % 8 : 0;
331 class->set_bit_mask[index] |= ( (cip_flags &
kSetable) ? 1 : 0 )
332 << ( (attribute_number) % 8 );
339 "Tried to insert to many attributes into class: %" PRIu32
", instance %" PRIu32
"\n",
349 char *
const service_name) {
353 class->class_name, class->number_of_services,
357 for (
int i = 0; i <
class->number_of_services; i++)
364 service->
name = service_name;
394 struct sockaddr *originator_address,
395 const int encapsulation_session) {
404 | message_router_request->
service);
411 if ( (NULL != attribute) && (NULL != attribute->
data) ) {
412 uint8_t get_bit_mask = 0;
423 if (0 != (get_bit_mask & (1 << (attribute_number % 8) ) ) ) {
433 && instance->cip_class->class_id == kCipAssemblyClassCode) {
451 const void *
const cip_data,
478 #ifdef OPENER_SUPPORT_64BIT_DATATYPES
483 counter = AddLintToMessage(*(EipUint64 *) (cip_data), cip_message);
497 *cip_message +=
string->length;
499 counter =
string->length + 2;
500 if (counter & 0x01) {
518 **cip_message = short_string->
length;
521 memcpy(*cip_message, short_string->
string, short_string->
length);
522 *cip_message += short_string->
length;
524 counter = short_string->
length + 1;
552 tcp_ip_network_interface_configuration =
555 ntohl(tcp_ip_network_interface_configuration->
ip_address),
558 ntohl(tcp_ip_network_interface_configuration->
network_mask),
561 ntohl(tcp_ip_network_interface_configuration->
gateway),
564 ntohl(tcp_ip_network_interface_configuration->
name_server),
567 ntohl(tcp_ip_network_interface_configuration->
name_server_2),
570 &(tcp_ip_network_interface_configuration->
578 memcpy(*cip_message, p, 6);
589 memcpy(*cip_message, cip_byte_array->
data, cip_byte_array->
length);
590 *cip_message += cip_byte_array->
length;
591 counter = cip_byte_array->
length;
617 void *
const cip_data,
618 const EipUint8 **
const cip_message) {
619 int number_of_decoded_bytes = -1;
621 switch (cip_data_type)
628 *(
EipUint8 *) (cip_data) = **cip_message;
630 number_of_decoded_bytes = 1;
637 number_of_decoded_bytes = 2;
645 number_of_decoded_bytes = 4;
648 #ifdef OPENER_SUPPORT_64BIT_DATATYPES
652 (*(EipUint64 *) (cip_data) ) = GetLintFromMessage(cip_message);
653 number_of_decoded_bytes = 8;
662 *cip_message +=
string->length;
664 number_of_decoded_bytes =
string->length + 2;
665 if (number_of_decoded_bytes & 0x01) {
668 number_of_decoded_bytes++;
675 short_string->
length = **cip_message;
678 memcpy(short_string->
string, *cip_message, short_string->
length);
679 *cip_message += short_string->
length;
681 number_of_decoded_bytes = short_string->
length + 1;
689 return number_of_decoded_bytes;
707 struct sockaddr *originator_address,
708 const int encapsulation_session) {
714 if(NULL == service) {
730 (1 << (attribute_number % 8) ) )) {
734 message_router_response->
data = reply;
741 message_router_response->
data_length = message_router_response->
data - reply;
742 message_router_response->
data = reply;
806 unsigned int number_of_decoded_elements = 0;
807 const EipUint8 *message_runner = *message;
816 for (number_of_decoded_elements = 0;
817 number_of_decoded_elements < epath->
path_size;
818 number_of_decoded_elements++) {
825 switch (*message_runner) {
836 number_of_decoded_elements++;
849 number_of_decoded_elements++;
862 number_of_decoded_elements++;
872 number_of_decoded_elements++;
881 *message = message_runner;
882 return number_of_decoded_elements * 2 + 1;
888 ">>> Allocate memory for %s %lu bytes times 3 for masks\n",
896 size_t index = attribute_number / 8;
901 size_t data_type_size = 0;
902 switch (attribute_struct->
type) {
904 data_type_size =
sizeof(
CipBool);
907 data_type_size =
sizeof(
CipSint);
910 data_type_size =
sizeof(
CipInt);
913 data_type_size =
sizeof(
CipDint);
919 data_type_size =
sizeof(
CipUint);
925 data_type_size =
sizeof(
CipReal);
927 #ifdef OPENER_SUPPORT_64BIT_DATATYPES
932 data_type_size =
sizeof(CipUlint);
935 data_type_size =
sizeof(CipLint);
938 data_type_size =
sizeof(CipLword);
941 data_type_size =
sizeof(CipLint);
946 data_type_size =
sizeof(
CipDint);
949 data_type_size =
sizeof(
CipUint);
963 data_type_size =
sizeof(
CipByte);
966 data_type_size =
sizeof(
CipWord);
977 data_type_size =
sizeof(
CipDint);
980 data_type_size =
sizeof(
CipInt);
985 + (
size_t) (data->
length) * (
size_t) (data->
size);
994 data_type_size =
sizeof(
CipDint);
1002 data_type_size =
sizeof(
CipUint);
1005 data_type_size = 2 *
sizeof(
CipUsint);
1015 data_type_size = 6 *
sizeof(
CipUsint);
1026 data_type_size = 6 *
sizeof(
CipUint);
1032 return data_type_size;
EipStatus ApplicationInitialization(void)
Callback for the application initialization.
void InsertAttribute(CipInstance *const instance, const EipUint16 attribute_number, const EipUint8 cip_type, void *const data, const EipByte cip_flags)
Insert an attribute in an instance of a CIP class.
Struct for padded EPATHs.
EipStatus ConnectionManagerInit(EipUint16 unique_connection_id)
Initialize the data of the connection manager object.
struct cip_service_struct * services
EipUint16 attribute_number
Tracing infrastructure for OpENer.
EipUint16 number_of_attributes
#define LOGICAL_SEGMENT_TYPE_INSTANCE_ID
int DecodePaddedEPath(CipEpath *epath, const EipUint8 **message)
Decodes padded EPath.
void(* InitializeCipClass)(CipClass *)
CipAttributeStruct * attributes
EipStatus(* CipServiceFunction)(CipInstance *const instance, CipMessageRouterRequest *const message_router_request, CipMessageRouterResponse *const message_router_response, struct sockaddr *originator_address, const int encapsulation_session)
Signature definition for the implementation of CIP services.
CIP Message Router Request.
#define OPENER_MESSAGE_DATA_REPLY_BUFFER
The number of bytes used for the buffer that will be used for generating any reply data of messages...
Class is a subclass of Instance.
#define OPENER_ASSERT(assertion)
EipStatus NotifyClass(const CipClass *RESTRICT const cip_class, CipMessageRouterRequest *const message_router_request, CipMessageRouterResponse *const message_router_response, struct sockaddr *originator_address, const int encapsulation_session)
Check if requested service present in class/instance and call appropriate service.
EipUint32 GetDintFromMessage(const EipUint8 **const buffer)
Reads EIP_UINT32 from *buffer and converts little endian to host.
CipServiceFunction service_function
Responsible for Endianess conversion.
size_t CalculateIndex(EipUint16 attribute_number)
Calculates Byte-Index of Attribute.
#define OPENER_TRACE_ERR(...)
CipInstance * AddCIPInstance(CipClass *RESTRICT const class, const EipUint32 instance_id)
Create one instance of a given class with a certain instance number.
Public interface of the QoS Object.
#define SEGMENT_TYPE_LOGICAL_SEGMENT
EipStatus CipAssemblyInitialize(void)
create the CIP Assembly object with zero instances
EipUint8 g_message_data_reply_buffer[OPENER_MESSAGE_DATA_REPLY_BUFFER]
uint8_t * get_single_bit_mask
EipStatus CipEthernetLinkInit()
Initialize the Ethernet Link Objects data.
CIPAttributeFlag attribute_flags
void * CipCalloc(size_t number_of_elements, size_t size_of_element)
Allocate memory for the CIP stack.
CipClass * CreateCipClass(const EipUint32 class_id, const int number_of_class_attributes, const EipUint32 highest_class_attribute_number, const int number_of_class_services, const int number_of_instance_attributes, const EipUint32 highest_instance_attribute_number, const int number_of_instance_services, const int number_of_instances, char *name, const EipUint16 revision, void(*InitializeCipClass)(CipClass *))
uint8_t CipOctet
Data types as defined in the CIP Specification Vol 1 Appendix C.
void DeleteAllClasses(void)
Free all data allocated by the classes created in the CIP stack.
#define LOGICAL_SEGMENT_TYPE_CLASS_ID
int AddIntToMessage(const EipUint16 data, EipUint8 **const buffer)
converts UINT16 data from host to little endian an writes it to buffer.
EipStatus
EIP stack status enum.
#define LOGICAL_SEGMENT_FORMAT_SIXTEEN_BIT
void InsertService(const CipClass *const class, const EipUint8 service_number, const CipServiceFunction service_function, char *const service_name)
Insert a service in an instance of a CIP object.
EipStatus RegisterCipClass(CipClass *cip_class)
Register a CIP Class to the message router.
CipInstance class_instance
EipStatus GetAttributeAll(CipInstance *instance, CipMessageRouterRequest *message_router_request, CipMessageRouterResponse *message_router_response, struct sockaddr *originator_address, const int encapsulation_session)
Generic implementation of the GetAttributeAll CIP service.
struct cip_instance * next
int AddDintToMessage(const EipUint32 data, EipUint8 **const buffer)
Converts UINT32 data from host to little endian and writes it to buffer.
EipStatus CipMessageRouterInit()
Initialize the data structures of the message router.
CipServiceStruct * GetCipService(const CipInstance *const instance, CipUsint service_number)
void ShutdownAssemblies(void)
clean up the data allocated in the assembly object instances
#define OPENER_TRACE_INFO(...)
int AddSintToMessage(const EipUint8 data, EipUint8 **const buffer)
converts UINT8 data from host to little endian an writes it to buffer.
int DecodeData(const EipUint8 cip_data_type, void *const cip_data, const EipUint8 **const cip_message)
Retrieve the given data according to CIP encoding from the message buffer.
void EncapsulationShutDown(void)
Shutdown the encapsulation layer.
EipStatus GetAttributeSingle(CipInstance *RESTRICT const instance, CipMessageRouterRequest *const message_router_request, CipMessageRouterResponse *const message_router_response, struct sockaddr *originator_address, const int encapsulation_session)
Generic implementation of the GetAttributeSingle CIP service.
int EncodeData(const EipUint8 cip_type, const void *const cip_data, EipUint8 **cip_message)
Produce the data according to CIP encoding onto the message buffer.
void CipStackInit(const EipUint16 unique_connection_id)
Initialize and setup the CIP-stack.
#define LOGICAL_SEGMENT_TYPE_ATTRIBUTE_ID
CipInstance * GetCipInstance(const CipClass *RESTRICT const cip_class, EipUint32 instance_number)
Get a pointer to an instance.
CipClass * GetCipClass(const EipUint32 class_id)
Get a pointer to a CIP object with given class code.
EipStatus CipIdentityInit()
CIP Identity object constructor.
CipAttributeStruct * GetCipAttribute(const CipInstance *const instance, const EipUint16 attribute_number)
Get a pointer to an instance's attribute.
Public interface of the TCP/IP Interface Object.
Service descriptor. These are stored in an array.
Struct for saving TCP/IP interface information.
void CloseAllConnections(void)
EipUint16 instance_number
EipUint16 number_of_services
EipUint16 attribute_number
uint8_t EipByte
EIP Data type definitions.
int EncodeEPath(CipEpath *epath, EipUint8 **message)
void EncapsulationInit(void)
Initialize the encapsulation layer.
#define OPENER_TRACE_WARN(...)
void ShutdownCipStack(void)
Shutdown of the CIP stack.
This file contains the public interface of the encapsulation layer.
size_t GetSizeOfAttribute(const CipAttributeStruct *const attribute_struct)
EipUint16 highest_attribute_number
EipUint16 GetIntFromMessage(const EipUint8 **const buffer)
Reads EIP_UINT16 from *buffer and converts little endian to host.
Struct storing the CIP revision.
CIP Message Router Response.
struct cip_class * cip_class
void ShutdownTcpIpInterface(void)
Clean up the allocated data of the TCP/IP interface object.
void AllocateAttributeMasks(CipClass *target_class)
Allocates Attribute bitmasks.
CipInstance * AddCipInstances(CipClass *RESTRICT const cip_class, const int number_of_instances)
Add a number of CIP instances to a given CIP class.
EipBool8 BeforeAssemblyDataSend(CipInstance *instance)
Inform the application that the data of an assembly object will be sent.
EipUint32 instance_number
EipStatus CipTcpIpInterfaceInit()
Initializing the data structures of the TCP/IP interface object.
#define LOGICAL_SEGMENT_TYPE_MEMBER_ID
#define LOGICAL_SEGMENT_FORMAT_EIGHT_BIT
uint8_t * get_all_bit_mask
CipUsint size_of_additional_status