You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@plc4x.apache.org by cd...@apache.org on 2020/08/19 11:07:06 UTC
[plc4x] branch feature/plc4c updated: - Continued implementing the
S7 driver
This is an automated email from the ASF dual-hosted git repository.
cdutz pushed a commit to branch feature/plc4c
in repository https://gitbox.apache.org/repos/asf/plc4x.git
The following commit(s) were added to refs/heads/feature/plc4c by this push:
new 6aa844c - Continued implementing the S7 driver
6aa844c is described below
commit 6aa844c3d2608f2ef3da725e73000075826b62dd
Author: Christofer Dutz <ch...@c-ware.de>
AuthorDate: Wed Aug 19 13:04:54 2020 +0200
- Continued implementing the S7 driver
---
.../resources/templates/c/enum-template-c.ftlh | 4 +
.../resources/templates/c/enum-template-h.ftlh | 2 +
sandbox/plc4c/drivers/s7/src/driver_s7.c | 761 ++++++++++++---------
.../s7/includes/cotp_protocol_class.h | 2 +
.../generated-sources/s7/includes/cotp_tpdu_size.h | 2 +
.../s7/includes/data_transport_error_code.h | 2 +
.../s7/includes/data_transport_size.h | 2 +
.../generated-sources/s7/includes/device_group.h | 2 +
.../generated-sources/s7/includes/memory_area.h | 2 +
.../s7/includes/szl_module_type_class.h | 2 +
.../generated-sources/s7/includes/szl_sublist.h | 2 +
.../generated-sources/s7/includes/transport_size.h | 2 +
.../generated-sources/s7/src/cotp_protocol_class.c | 4 +
.../generated-sources/s7/src/cotp_tpdu_size.c | 4 +
.../s7/src/data_transport_error_code.c | 4 +
.../generated-sources/s7/src/data_transport_size.c | 4 +
.../plc4c/generated-sources/s7/src/device_group.c | 4 +
.../plc4c/generated-sources/s7/src/memory_area.c | 4 +
.../s7/src/szl_module_type_class.c | 4 +
.../plc4c/generated-sources/s7/src/szl_sublist.c | 4 +
.../generated-sources/s7/src/transport_size.c | 4 +
sandbox/plc4c/spi/src/utils/list.c | 1 +
22 files changed, 483 insertions(+), 339 deletions(-)
diff --git a/build-utils/language-c/src/main/resources/templates/c/enum-template-c.ftlh b/build-utils/language-c/src/main/resources/templates/c/enum-template-c.ftlh
index 647a63d..6445cbd 100644
--- a/build-utils/language-c/src/main/resources/templates/c/enum-template-c.ftlh
+++ b/build-utils/language-c/src/main/resources/templates/c/enum-template-c.ftlh
@@ -54,6 +54,10 @@ ${helper.getCTypeName(type.name)} ${helper.getCTypeName(type.name)}_null() {
return ${helper.getCTypeName(type.name)}_null_const;
}
+int ${helper.getCTypeName(type.name)}_num_values() {
+ return ${type.enumValues?size};
+}
+
<#--
If this enum also defines constant values, output one function for each.
Each of these functions consist of a simple switch statement using the enum as switch-value
diff --git a/build-utils/language-c/src/main/resources/templates/c/enum-template-h.ftlh b/build-utils/language-c/src/main/resources/templates/c/enum-template-h.ftlh
index 65e6b2e..a3fc892 100644
--- a/build-utils/language-c/src/main/resources/templates/c/enum-template-h.ftlh
+++ b/build-utils/language-c/src/main/resources/templates/c/enum-template-h.ftlh
@@ -68,6 +68,8 @@ typedef enum ${helper.getCTypeName(type.name)} ${helper.getCTypeName(type.name)}
// Get an empty NULL-struct
${helper.getCTypeName(type.name)} ${helper.getCTypeName(type.name)}_null();
+int ${helper.getCTypeName(type.name)}_num_values();
+
<#--
If this enum also defines constant values, output one function for each.
Each of these functions consist of a simple switch statement using the enum as switch-value
diff --git a/sandbox/plc4c/drivers/s7/src/driver_s7.c b/sandbox/plc4c/drivers/s7/src/driver_s7.c
index 80fad4a..622369b 100644
--- a/sandbox/plc4c/drivers/s7/src/driver_s7.c
+++ b/sandbox/plc4c/drivers/s7/src/driver_s7.c
@@ -17,13 +17,13 @@
under the License.
*/
+#include <cotp_protocol_class.h>
#include <plc4c/driver_s7.h>
#include <plc4c/plc4c.h>
#include <plc4c/spi/types_private.h>
#include <stdlib.h>
#include <string.h>
#include <tpkt_packet.h>
-#include <cotp_protocol_class.h>
// State definitions
enum plc4c_driver_s7_connect_states {
@@ -53,18 +53,18 @@ enum plc4c_driver_s7_write_states {
PLC4C_DRIVER_S7_WRITE_FINISHED
};
-int16_t plc4c_driver_s7_select_message_function(
- uint8_t* buffer_data, uint16_t buffer_length) {
+int16_t plc4c_driver_s7_select_message_function(uint8_t* buffer_data,
+ uint16_t buffer_length) {
// If the packet doesn't start with 0x03, it's a corrupt package.
- if(buffer_length >= 1) {
+ if (buffer_length >= 1) {
// The buffer seems to be corrupt, try to find a sequence of 0x03 0x00
// and return the negative number of bytes needed to find that or the
// number of bytes in the buffer so it will simply clean the buffer
// completely.
- if(*buffer_data != 0x03) {
- for(int i = 1; i < (buffer_length - 1); i++) {
+ if (*buffer_data != 0x03) {
+ for (int i = 1; i < (buffer_length - 1); i++) {
buffer_data++;
- if((*buffer_data == 0x03) && (*(buffer_data + 1) == 0x00)) {
+ if ((*buffer_data == 0x03) && (*(buffer_data + 1) == 0x00)) {
// We've found a potential new packet start.
return -(i - 1);
}
@@ -76,19 +76,19 @@ int16_t plc4c_driver_s7_select_message_function(
}
}
// The length information is located in bytes 3 and 4
- if(buffer_length >= 4) {
+ if (buffer_length >= 4) {
uint16_t packet_length =
- (((uint16_t) *(buffer_data + (uint8_t) 2)) << (uint16_t) 8) |
- ((uint16_t) *(buffer_data + 3));
- if(buffer_length >= packet_length) {
+ (((uint16_t) * (buffer_data + (uint8_t)2)) << (uint16_t)8) |
+ ((uint16_t) * (buffer_data + 3));
+ if (buffer_length >= packet_length) {
return packet_length;
}
// 8192 is the maximum pdu size, so if the value is larger, the packet is
// probably corrupt.
- if(packet_length > 8192) {
- for(int i = 1; i < (buffer_length - 1); i++) {
+ if (packet_length > 8192) {
+ for (int i = 1; i < (buffer_length - 1); i++) {
buffer_data++;
- if((*buffer_data == 0x03) && (*(buffer_data + 1) == 0x00)) {
+ if ((*buffer_data == 0x03) && (*(buffer_data + 1) == 0x00)) {
// We've found a potential new packet start.
return -(i - 1);
}
@@ -102,20 +102,24 @@ int16_t plc4c_driver_s7_select_message_function(
uint16_t plc4c_driver_s7_encode_tsap_id(
plc4c_driver_s7_device_group device_group, uint8_t rack, uint8_t slot) {
- return (((uint16_t) device_group) << 8) |
- (((uint16_t) rack & 0x000F) << 4) |
- ((uint16_t) slot & 0x000F);
+ return (((uint16_t)device_group) << 8) | (((uint16_t)rack & 0x000F) << 4) |
+ ((uint16_t)slot & 0x000F);
}
uint16_t plc4c_driver_s7_get_nearest_matching_tpdu_size(uint16_t pdu_size) {
- // TODO: Implement ...
+ for(int i = 0; i < plc4c_s7_read_write_cotp_tpdu_size_num_values(); i++) {
+ uint16_t cur_value = plc4c_s7_read_write_cotp_tpdu_size_get_size_in_bytes(i);
+ if(cur_value >= pdu_size) {
+ return cur_value;
+ }
+ }
return 0;
}
plc4c_driver_s7_controller_type decode_controller_type(char* article_number) {
char* prefix = "6ES7 ";
// If this article-number doesn't start with this prefix, we can't decode it.
- if(strncmp(prefix, article_number, strlen(prefix)) != 0) {
+ if (strncmp(prefix, article_number, strlen(prefix)) != 0) {
return PLC4C_DRIVER_S7_CONTROLLER_TYPE_ANY;
}
char model = *(article_number + 5);
@@ -133,14 +137,69 @@ plc4c_driver_s7_controller_type decode_controller_type(char* article_number) {
}
}
+plc4c_return_code send_packet(plc4c_connection* connection,
+ plc4c_s7_read_write_tpkt_packet* packet) {
+ // Get the size required to contain the serialized form of this packet.
+ uint16_t packet_size =
+ plc4c_s7_read_write_tpkt_packet_length_in_bytes(packet);
+
+ // Serialize this message to a byte-array.
+ plc4c_spi_write_buffer* write_buffer;
+ plc4c_return_code return_code =
+ plc4c_spi_write_buffer_create(packet_size, &write_buffer);
+ if (return_code != OK) {
+ return return_code;
+ }
+ plc4c_s7_read_write_tpkt_packet_serialize(write_buffer, packet);
+
+ // Now send this to the recipient.
+ return_code = connection->transport->send_message(write_buffer);
+ if (return_code != OK) {
+ return return_code;
+ }
+
+ return OK;
+}
+
+plc4c_return_code receive_packet(plc4c_connection* connection,
+ plc4c_s7_read_write_tpkt_packet** packet) {
+ // Get a response from the transport.
+ plc4c_spi_read_buffer* read_buffer;
+ plc4c_return_code return_code = connection->transport->select_message(
+ plc4c_driver_s7_select_message_function, &read_buffer);
+ if (return_code != OK) {
+ return return_code;
+ }
+
+ // Parse the given data.
+ *packet = NULL;
+ return_code = plc4c_s7_read_write_tpkt_packet_parse(
+ read_buffer, packet);
+ if (return_code != OK) {
+ return return_code;
+ }
+
+ return OK;
+}
+
+// Declare the functions for which the definition will come later ...
+plc4c_return_code createCOTPConnectionRequest(
+ plc4c_driver_s7_config* configuration,
+ plc4c_s7_read_write_tpkt_packet** cotp_connect_request_packet);
+plc4c_return_code createS7ConnectionRequest(
+ plc4c_driver_s7_config* configuration,
+ plc4c_s7_read_write_tpkt_packet** s7_connect_request_packet);
+plc4c_return_code createS7IdentifyRemoteRequest(
+ plc4c_s7_read_write_tpkt_packet** s7_identify_remote_request_packet);
+
/**
* State machine function for establishing a connection to a remote S7 device.
* @param task the current system task
* @return return code of the current state machine step execution
*/
plc4c_return_code plc4c_driver_s7_connect_machine_function(
- plc4c_system_task *task) {
- plc4c_connection *connection = task->context;
+ plc4c_system_task* task) {
+ plc4c_connection* connection = task->context;
if (connection == NULL) {
return INTERNAL_ERROR;
}
@@ -153,137 +212,68 @@ plc4c_return_code plc4c_driver_s7_connect_machine_function(
switch (task->state_id) {
// Initialize some internal data-structures.
case PLC4C_DRIVER_S7_CONNECT_INIT: {
+ // Calculate some internal settings from the values provided in the
+ // configuration.
configuration->calling_tsap_id = plc4c_driver_s7_encode_tsap_id(
- PLC4C_DRIVER_S7_DEVICE_GROUP_OTHERS,
- configuration->local_rack, configuration->local_slot);
+ PLC4C_DRIVER_S7_DEVICE_GROUP_OTHERS, configuration->local_rack,
+ configuration->local_slot);
configuration->called_tsap_id = plc4c_driver_s7_encode_tsap_id(
- PLC4C_DRIVER_S7_DEVICE_GROUP_PG_OR_PC,
- configuration->remote_rack, configuration->remote_slot);
+ PLC4C_DRIVER_S7_DEVICE_GROUP_PG_OR_PC, configuration->remote_rack,
+ configuration->remote_slot);
configuration->cotp_tpdu_size =
- plc4c_driver_s7_get_nearest_matching_tpdu_size(configuration->pdu_size);
+ plc4c_driver_s7_get_nearest_matching_tpdu_size(
+ configuration->pdu_size);
configuration->pdu_size = configuration->cotp_tpdu_size - 16;
+
task->state_id = PLC4C_DRIVER_S7_CONNECT_SEND_COTP_CONNECT_REQUEST;
break;
}
// Send a COTP connection request.
case PLC4C_DRIVER_S7_CONNECT_SEND_COTP_CONNECT_REQUEST: {
- plc4c_s7_read_write_tpkt_packet* cotp_connect_request_packet =
- malloc(sizeof(plc4c_s7_read_write_tpkt_packet));
- if(cotp_connect_request_packet == NULL) {
- return NO_MEMORY;
- }
- cotp_connect_request_packet->payload = malloc(sizeof(plc4c_s7_read_write_cotp_packet));
- if(cotp_connect_request_packet->payload == NULL) {
- return NO_MEMORY;
- }
- cotp_connect_request_packet->payload->_type =
- plc4c_s7_read_write_cotp_packet_type_plc4c_s7_read_write_cotp_packet_connection_request;
- cotp_connect_request_packet->payload->cotp_packet_connection_request_destination_reference =
- 0x0000;
- cotp_connect_request_packet->payload->cotp_packet_connection_request_source_reference =
- 0x000F;
- cotp_connect_request_packet->payload->cotp_packet_connection_request_protocol_class =
- plc4c_s7_read_write_cotp_protocol_class_CLASS_0;
-
- // Add the COTP parameters: Called TSAP, Calling TSAP and TPDU Size.
- plc4c_utils_list_create(&(cotp_connect_request_packet->payload->parameters));
- plc4c_s7_read_write_cotp_parameter* called_tsap_parameter =
- malloc(sizeof(plc4c_s7_read_write_cotp_parameter));
- if(called_tsap_parameter == NULL) {
- return NO_MEMORY;
+ // Get a COTP connection response for the settings in the config.
+ plc4c_s7_read_write_tpkt_packet* cotp_connect_request_packet;
+ plc4c_return_code return_code = createCOTPConnectionRequest(
+ configuration, &cotp_connect_request_packet);
+ if(return_code != OK) {
+ return return_code;
}
- called_tsap_parameter->_type =
- plc4c_s7_read_write_cotp_parameter_type_plc4c_s7_read_write_cotp_parameter_called_tsap;
- called_tsap_parameter->cotp_parameter_called_tsap_tsap_id =
- configuration->called_tsap_id;
-
- plc4c_utils_list_insert_head_value(
- cotp_connect_request_packet->payload->parameters, called_tsap_parameter);
- plc4c_s7_read_write_cotp_parameter* calling_tsap_parameter =
- malloc(sizeof(plc4c_s7_read_write_cotp_parameter));
- if(calling_tsap_parameter == NULL) {
- return NO_MEMORY;
- }
- calling_tsap_parameter->_type =
- plc4c_s7_read_write_cotp_parameter_type_plc4c_s7_read_write_cotp_parameter_calling_tsap;
- calling_tsap_parameter->cotp_parameter_calling_tsap_tsap_id =
- configuration->calling_tsap_id;
-
- plc4c_utils_list_insert_head_value(
- cotp_connect_request_packet->payload->parameters, calling_tsap_parameter);
- plc4c_s7_read_write_cotp_parameter* tpdu_size_parameter =
- malloc(sizeof(plc4c_s7_read_write_cotp_parameter));
- if(tpdu_size_parameter == NULL) {
- return NO_MEMORY;
- }
- tpdu_size_parameter->_type =
- plc4c_s7_read_write_cotp_parameter_type_plc4c_s7_read_write_cotp_parameter_tpdu_size;
- tpdu_size_parameter->cotp_parameter_tpdu_size_tpdu_size =
- configuration->cotp_tpdu_size;
-
- plc4c_utils_list_insert_head_value(
- cotp_connect_request_packet->payload->parameters, tpdu_size_parameter);
-
- // For a COTP connection request, there is no payload.
- cotp_connect_request_packet->payload->payload = NULL;
-
- // Get the size required to contain the serialized form of this packet.
- uint16_t packet_size =
- plc4c_s7_read_write_tpkt_packet_length_in_bytes(
- cotp_connect_request_packet);
-
- // Serialize this message to a byte-array.
- plc4c_spi_write_buffer* write_buffer;
- plc4c_return_code return_code =
- plc4c_spi_write_buffer_create(packet_size, &write_buffer);
- if (return_code != OK) {
- return INTERNAL_ERROR;
- }
- plc4c_s7_read_write_tpkt_packet_serialize(write_buffer, cotp_connect_request_packet);
- // Now send this to the recipient.
- return_code = connection->transport->send_message(write_buffer);
- if (return_code != OK) {
- return INTERNAL_ERROR;
+ // Send the packet to the remote.
+ return_code = send_packet(
+ connection, cotp_connect_request_packet);
+ if(return_code != OK) {
+ return return_code;
}
task->state_id = PLC4C_DRIVER_S7_CONNECT_RECEIVE_COTP_CONNECT_RESPONSE;
break;
}
- // Receive a tpkt connection response.
+ // Receive a COTP connection response.
case PLC4C_DRIVER_S7_CONNECT_RECEIVE_COTP_CONNECT_RESPONSE: {
- // Get a response from the transport.
- plc4c_spi_read_buffer* read_buffer;
- plc4c_return_code return_code = connection->transport->select_message(
- plc4c_driver_s7_select_message_function, &read_buffer);
- if (return_code != OK) {
- // If UNFINISHED was returned, the buffer hasn't received enough
- // data for a full packet. Just return and come back later.
- if(return_code == UNFINISHED) {
- return OK;
- }
- return INTERNAL_ERROR;
- }
-
- // Parse the given data.
- plc4c_s7_read_write_tpkt_packet* cotp_connect_response_packet = NULL;
- return_code = plc4c_s7_read_write_tpkt_packet_parse(
- read_buffer, &cotp_connect_response_packet);
- if (return_code != OK) {
- return INTERNAL_ERROR;
+ // Read a response packet.
+ plc4c_s7_read_write_tpkt_packet* cotp_connect_response_packet;
+ plc4c_return_code return_code = receive_packet(connection, &cotp_connect_response_packet);
+ // If we haven't read enough to process a full message, just try again
+ // next time.
+ if(return_code == UNFINISHED) {
+ return OK;
+ } else if(return_code != OK) {
+ return return_code;
}
// Check if the packet has the right type
- if(cotp_connect_response_packet->payload->_type !=
+ if (cotp_connect_response_packet->payload->_type !=
plc4c_s7_read_write_cotp_packet_type_plc4c_s7_read_write_cotp_packet_connection_response) {
return INTERNAL_ERROR;
}
- // Extract the information for: called-tsap-id, calling-tsap-id and tpdu-size.
+ // Extract the information for: called-tsap-id, calling-tsap-id and
+ // tpdu-size.
plc4c_list_element* parameter_element =
cotp_connect_response_packet->payload->parameters->tail;
do {
- plc4c_s7_read_write_cotp_parameter* parameter = parameter_element->value;
+ plc4c_s7_read_write_cotp_parameter* parameter =
+ parameter_element->value;
switch (parameter->_type) {
case plc4c_s7_read_write_cotp_parameter_type_plc4c_s7_read_write_cotp_parameter_tpdu_size: {
configuration->cotp_tpdu_size =
@@ -313,61 +303,18 @@ plc4c_return_code plc4c_driver_s7_connect_machine_function(
}
// Send a S7 connection request.
case PLC4C_DRIVER_S7_CONNECT_SEND_S7_CONNECT_REQUEST: {
- plc4c_s7_read_write_tpkt_packet* s7_connect_request_packet =
- malloc(sizeof(plc4c_s7_read_write_tpkt_packet));
- if(s7_connect_request_packet == NULL) {
- return NO_MEMORY;
- }
- s7_connect_request_packet->payload =
- malloc(sizeof(plc4c_s7_read_write_cotp_packet));
- if(s7_connect_request_packet->payload == NULL) {
- return NO_MEMORY;
+ plc4c_s7_read_write_tpkt_packet* s7_connect_request_packet;
+ plc4c_return_code return_code = createS7ConnectionRequest(
+ configuration, &s7_connect_request_packet);
+ if(return_code != OK) {
+ return return_code;
}
- s7_connect_request_packet->payload->_type =
- plc4c_s7_read_write_cotp_packet_type_plc4c_s7_read_write_cotp_packet_data;
- s7_connect_request_packet->payload->parameters = NULL;
- s7_connect_request_packet->payload->cotp_packet_data_eot = true;
- s7_connect_request_packet->payload->cotp_packet_data_tpdu_ref = 1;
-
- s7_connect_request_packet->payload->payload =
- malloc(sizeof(plc4c_s7_read_write_s7_message));
- if(s7_connect_request_packet->payload->payload == NULL) {
- return NO_MEMORY;
- }
- s7_connect_request_packet->payload->payload->_type =
- plc4c_s7_read_write_s7_message_type_plc4c_s7_read_write_s7_message_request;
- s7_connect_request_packet->payload->payload->parameter =
- malloc(sizeof(plc4c_s7_read_write_s7_parameter));
- if(s7_connect_request_packet->payload->payload->parameter == NULL) {
- return NO_MEMORY;
- }
- s7_connect_request_packet->payload->payload->parameter->_type =
- plc4c_s7_read_write_s7_parameter_type_plc4c_s7_read_write_s7_parameter_setup_communication;
- s7_connect_request_packet->payload->payload->parameter->s7_parameter_setup_communication_max_amq_callee =
- configuration->max_amq_callee;
- s7_connect_request_packet->payload->payload->parameter->s7_parameter_setup_communication_max_amq_caller =
- configuration->max_amq_caller;
- s7_connect_request_packet->payload->payload->parameter->s7_parameter_setup_communication_pdu_length =
- configuration->pdu_size;
-
- // Get the size required to contain the serialized form of this packet.
- uint16_t packet_size =
- plc4c_s7_read_write_tpkt_packet_length_in_bytes(
- s7_connect_request_packet);
-
- // Serialize this message to a byte-array.
- plc4c_spi_write_buffer* write_buffer;
- plc4c_return_code return_code =
- plc4c_spi_write_buffer_create(packet_size, &write_buffer);
- if (return_code != OK) {
- return INTERNAL_ERROR;
- }
- plc4c_s7_read_write_tpkt_packet_serialize(write_buffer, s7_connect_request_packet);
- // Now send this to the recipient.
- return_code = connection->transport->send_message(write_buffer);
- if (return_code != OK) {
- return INTERNAL_ERROR;
+ // Send the packet to the remote.
+ return_code = send_packet(
+ connection, s7_connect_request_packet);
+ if(return_code != OK) {
+ return return_code;
}
task->state_id = PLC4C_DRIVER_S7_CONNECT_RECEIVE_S7_CONNECT_RESPONSE;
@@ -375,37 +322,28 @@ plc4c_return_code plc4c_driver_s7_connect_machine_function(
}
// Receive a S7 connection response.
case PLC4C_DRIVER_S7_CONNECT_RECEIVE_S7_CONNECT_RESPONSE: {
- // Get a response from the transport.
- plc4c_spi_read_buffer* read_buffer;
- plc4c_return_code return_code = connection->transport->select_message(
- plc4c_driver_s7_select_message_function, &read_buffer);
- if (return_code != OK) {
- // If UNFINISHED was returned, the buffer hasn't received enough
- // data for a full packet. Just return and come back later.
- if(return_code == UNFINISHED) {
- return OK;
- }
- return INTERNAL_ERROR;
- }
-
- // Parse the given data.
- plc4c_s7_read_write_tpkt_packet* cotp_connect_response_packet = NULL;
- return_code = plc4c_s7_read_write_tpkt_packet_parse(
- read_buffer, &cotp_connect_response_packet);
- if (return_code != OK) {
- return INTERNAL_ERROR;
+ // Read a response packet.
+ plc4c_s7_read_write_tpkt_packet* s7_connect_response_packet;
+ plc4c_return_code return_code = receive_packet(
+ connection, &s7_connect_response_packet);
+ // If we haven't read enough to process a full message, just try again
+ // next time.
+ if(return_code == UNFINISHED) {
+ return OK;
+ } else if(return_code != OK) {
+ return return_code;
}
// Check if the packet has the right type
- if(cotp_connect_response_packet->payload->_type !=
+ if (s7_connect_response_packet->payload->_type !=
plc4c_s7_read_write_cotp_packet_type_plc4c_s7_read_write_cotp_packet_data) {
return INTERNAL_ERROR;
}
- if(cotp_connect_response_packet->payload->payload->_type !=
+ if (s7_connect_response_packet->payload->payload->_type !=
plc4c_s7_read_write_s7_message_type_plc4c_s7_read_write_s7_message_response) {
return INTERNAL_ERROR;
}
- if(cotp_connect_response_packet->payload->payload->parameter->_type !=
+ if (s7_connect_response_packet->payload->payload->parameter->_type !=
plc4c_s7_read_write_s7_parameter_type_plc4c_s7_read_write_s7_parameter_setup_communication) {
return INTERNAL_ERROR;
}
@@ -413,14 +351,18 @@ plc4c_return_code plc4c_driver_s7_connect_machine_function(
// Extract and save the information for:
// max-amq-caller, max-amq-callee, pdu-size.
configuration->pdu_size =
- cotp_connect_response_packet->payload->payload->parameter->s7_parameter_setup_communication_pdu_length;
+ s7_connect_response_packet->payload->payload->parameter
+ ->s7_parameter_setup_communication_pdu_length;
configuration->max_amq_caller =
- cotp_connect_response_packet->payload->payload->parameter->s7_parameter_setup_communication_max_amq_caller;
+ s7_connect_response_packet->payload->payload->parameter
+ ->s7_parameter_setup_communication_max_amq_caller;
configuration->max_amq_callee =
- cotp_connect_response_packet->payload->payload->parameter->s7_parameter_setup_communication_max_amq_callee;
+ s7_connect_response_packet->payload->payload->parameter
+ ->s7_parameter_setup_communication_max_amq_callee;
// If no controller is explicitly selected, detect it.
- if(configuration->controller_type != PLC4C_DRIVER_S7_CONTROLLER_TYPE_ANY) {
+ if (configuration->controller_type !=
+ PLC4C_DRIVER_S7_CONTROLLER_TYPE_ANY) {
task->state_id = PLC4C_DRIVER_S7_CONNECT_SEND_S7_IDENTIFICATION_REQUEST;
}
// If a controller is explicitly selected, we're done connecting.
@@ -431,137 +373,74 @@ plc4c_return_code plc4c_driver_s7_connect_machine_function(
}
// Send a S7 identification request.
case PLC4C_DRIVER_S7_CONNECT_SEND_S7_IDENTIFICATION_REQUEST: {
- plc4c_s7_read_write_tpkt_packet* s7_identify_remote_request_packet =
- malloc(sizeof(plc4c_s7_read_write_tpkt_packet));
- if(s7_identify_remote_request_packet == NULL) {
- return NO_MEMORY;
+ plc4c_s7_read_write_tpkt_packet* s7_identify_remote_request_packet;
+ plc4c_return_code return_code = createS7IdentifyRemoteRequest(
+ &s7_identify_remote_request_packet);
+ if(return_code != OK) {
+ return return_code;
}
- s7_identify_remote_request_packet->payload = malloc(sizeof(plc4c_s7_read_write_cotp_packet));
- if(s7_identify_remote_request_packet->payload == NULL) {
- return NO_MEMORY;
- }
- s7_identify_remote_request_packet->payload->_type =
- plc4c_s7_read_write_cotp_packet_type_plc4c_s7_read_write_cotp_packet_data;
- s7_identify_remote_request_packet->payload->parameters = NULL;
- s7_identify_remote_request_packet->payload->cotp_packet_data_eot = true;
- s7_identify_remote_request_packet->payload->cotp_packet_data_tpdu_ref = 2;
-
- s7_identify_remote_request_packet->payload->payload =
- malloc(sizeof(plc4c_s7_read_write_s7_message));
- if(s7_identify_remote_request_packet->payload->payload == NULL) {
- return NO_MEMORY;
- }
- s7_identify_remote_request_packet->payload->payload->_type =
- plc4c_s7_read_write_s7_message_type_plc4c_s7_read_write_s7_message_user_data;
- s7_identify_remote_request_packet->payload->payload->parameter =
- malloc(sizeof(plc4c_s7_read_write_s7_parameter));
- if(s7_identify_remote_request_packet->payload->payload->parameter == NULL) {
- return NO_MEMORY;
- }
- s7_identify_remote_request_packet->payload->payload->parameter->_type =
- plc4c_s7_read_write_s7_parameter_type_plc4c_s7_read_write_s7_parameter_user_data;
-
- plc4c_utils_list_create(&(s7_identify_remote_request_packet->payload->payload->parameter->s7_parameter_user_data_items));
- plc4c_s7_read_write_s7_parameter_user_data_item* parameter_item = malloc(sizeof(plc4c_s7_read_write_s7_parameter_user_data_item));
- parameter_item->_type = plc4c_s7_read_write_s7_parameter_user_data_item_type_plc4c_s7_read_write_s7_parameter_user_data_item_cpu_functions;
- parameter_item->s7_parameter_user_data_item_cpu_functions_method = 0x11;
- parameter_item->s7_parameter_user_data_item_cpu_functions_cpu_function_type = 0x4;
- parameter_item->s7_parameter_user_data_item_cpu_functions_cpu_function_group = 0x4;
- parameter_item->s7_parameter_user_data_item_cpu_functions_cpu_subfunction = 0x01;
- parameter_item->s7_parameter_user_data_item_cpu_functions_sequence_number = 0x00;
- parameter_item->s7_parameter_user_data_item_cpu_functions_data_unit_reference_number = NULL;
- parameter_item->s7_parameter_user_data_item_cpu_functions_last_data_unit = NULL;
- parameter_item->s7_parameter_user_data_item_cpu_functions_error_code = NULL;
- plc4c_utils_list_insert_head_value(s7_identify_remote_request_packet->payload->payload->parameter->s7_parameter_user_data_items, parameter_item);
-
- plc4c_utils_list_create(&(s7_identify_remote_request_packet->payload->payload->payload->s7_payload_user_data_items));
- plc4c_s7_read_write_s7_payload_user_data_item* payload_item = malloc(sizeof(plc4c_s7_read_write_s7_payload_user_data_item));
- payload_item->_type = plc4c_s7_read_write_s7_payload_user_data_item_type_plc4c_s7_read_write_s7_payload_user_data_item_cpu_function_read_szl_request;
- payload_item->return_code = plc4c_s7_read_write_data_transport_error_code_OK;
- payload_item->transport_size = plc4c_s7_read_write_data_transport_size_OCTET_STRING;
- payload_item->szl_index = 0x0000;
- payload_item->szl_id = malloc(sizeof(plc4c_s7_read_write_szl_id));
- if(payload_item->szl_id == NULL) {
- return NO_MEMORY;
- }
- payload_item->szl_id->type_class = plc4c_s7_read_write_szl_module_type_class_CPU;
- payload_item->szl_id->sublist_extract = 0x00;
- payload_item->szl_id->sublist_list = plc4c_s7_read_write_szl_sublist_MODULE_IDENTIFICATION;
-
- // Get the size required to contain the serialized form of this packet.
- uint16_t packet_size =
- plc4c_s7_read_write_tpkt_packet_length_in_bytes(
- s7_identify_remote_request_packet);
-
- // Serialize this message to a byte-array.
- plc4c_spi_write_buffer* write_buffer;
- plc4c_return_code return_code =
- plc4c_spi_write_buffer_create(packet_size, &write_buffer);
- if (return_code != OK) {
- return INTERNAL_ERROR;
- }
- plc4c_s7_read_write_tpkt_packet_serialize(write_buffer, s7_identify_remote_request_packet);
- // Now send this to the recipient.
- return_code = connection->transport->send_message(write_buffer);
- if (return_code != OK) {
- return INTERNAL_ERROR;
+ // Send the packet to the remote.
+ return_code = send_packet(
+ connection, s7_identify_remote_request_packet);
+ if(return_code != OK) {
+ return return_code;
}
- task->state_id = PLC4C_DRIVER_S7_CONNECT_RECEIVE_S7_IDENTIFICATION_RESPONSE;
+ task->state_id =
+ PLC4C_DRIVER_S7_CONNECT_RECEIVE_S7_IDENTIFICATION_RESPONSE;
break;
}
// Receive a S7 identification response.
case PLC4C_DRIVER_S7_CONNECT_RECEIVE_S7_IDENTIFICATION_RESPONSE: {
- // Get a response from the transport.
- plc4c_spi_read_buffer* read_buffer;
- plc4c_return_code return_code = connection->transport->select_message(
- plc4c_driver_s7_select_message_function, &read_buffer);
- if (return_code != OK) {
- // If UNFINISHED was returned, the buffer hasn't received enough
- // data for a full packet. Just return and come back later.
- if(return_code == UNFINISHED) {
- return OK;
- }
- return INTERNAL_ERROR;
- }
-
- // Parse the given data.
- plc4c_s7_read_write_tpkt_packet* cotp_connect_response_packet = NULL;
- return_code = plc4c_s7_read_write_tpkt_packet_parse(
- read_buffer, &cotp_connect_response_packet);
- if (return_code != OK) {
- return INTERNAL_ERROR;
+ // Read a response packet.
+ plc4c_s7_read_write_tpkt_packet* s7_identify_remote_response_packet;
+ plc4c_return_code return_code = receive_packet(
+ connection, &s7_identify_remote_response_packet);
+ // If we haven't read enough to process a full message, just try again
+ // next time.
+ if(return_code == UNFINISHED) {
+ return OK;
+ } else if(return_code != OK) {
+ return return_code;
}
// Check if the packet has the right type
- if(cotp_connect_response_packet->payload->_type !=
- plc4c_s7_read_write_cotp_packet_type_plc4c_s7_read_write_cotp_packet_data) {
+ if (s7_identify_remote_response_packet->payload->_type !=
+ plc4c_s7_read_write_cotp_packet_type_plc4c_s7_read_write_cotp_packet_data) {
return INTERNAL_ERROR;
}
- if(cotp_connect_response_packet->payload->payload->_type !=
+ if (s7_identify_remote_response_packet->payload->payload->_type !=
plc4c_s7_read_write_s7_message_type_plc4c_s7_read_write_s7_message_user_data) {
return INTERNAL_ERROR;
}
- if(cotp_connect_response_packet->payload->payload->payload->_type !=
+ if (s7_identify_remote_response_packet->payload->payload->payload->_type !=
plc4c_s7_read_write_s7_payload_type_plc4c_s7_read_write_s7_payload_user_data) {
return INTERNAL_ERROR;
}
- plc4c_list_element* cur_item = cotp_connect_response_packet->payload->payload->payload->s7_payload_user_data_items->tail;
- while(cur_item != NULL) {
+ plc4c_list_element* cur_item =
+ s7_identify_remote_response_packet->payload->payload->payload
+ ->s7_payload_user_data_items->tail;
+ while (cur_item != NULL) {
plc4c_s7_read_write_s7_payload_user_data_item* item = cur_item->value;
- if(item->_type == plc4c_s7_read_write_s7_payload_user_data_item_type_plc4c_s7_read_write_s7_payload_user_data_item_cpu_function_read_szl_response) {
- plc4c_list_element* szl_item = item->s7_payload_user_data_item_cpu_function_read_szl_response_items->head;
- while(szl_item != NULL) {
- plc4c_s7_read_write_szl_data_tree_item* data_tree_item = szl_item->value;
- if(data_tree_item->item_index == 0x0001) {
+ if (item->_type ==
+ plc4c_s7_read_write_s7_payload_user_data_item_type_plc4c_s7_read_write_s7_payload_user_data_item_cpu_function_read_szl_response) {
+ plc4c_list_element* szl_item =
+ item->s7_payload_user_data_item_cpu_function_read_szl_response_items
+ ->head;
+ while (szl_item != NULL) {
+ plc4c_s7_read_write_szl_data_tree_item* data_tree_item =
+ szl_item->value;
+ if (data_tree_item->item_index == 0x0001) {
char* article_number = list_to_string(data_tree_item->mlfb);
- if(article_number != NULL) {
- configuration->controller_type = decode_controller_type(article_number);
+ if (article_number != NULL) {
+ configuration->controller_type =
+ decode_controller_type(article_number);
free(article_number);
} else {
- configuration->controller_type = PLC4C_DRIVER_S7_CONTROLLER_TYPE_ANY;
+ configuration->controller_type =
+ PLC4C_DRIVER_S7_CONTROLLER_TYPE_ANY;
}
}
szl_item = szl_item->next;
@@ -591,8 +470,8 @@ plc4c_return_code plc4c_driver_s7_connect_machine_function(
}
plc4c_return_code plc4c_driver_s7_disconnect_machine_function(
- plc4c_system_task *task) {
- plc4c_connection *connection = task->context;
+ plc4c_system_task* task) {
+ plc4c_connection* connection = task->context;
if (connection == NULL) {
return INTERNAL_ERROR;
}
@@ -624,8 +503,8 @@ plc4c_return_code plc4c_driver_s7_disconnect_machine_function(
}
plc4c_return_code plc4c_driver_s7_read_machine_function(
- plc4c_system_task *task) {
- plc4c_read_request_execution *read_request_execution = task->context;
+ plc4c_system_task* task) {
+ plc4c_read_request_execution* read_request_execution = task->context;
if (read_request_execution == NULL) {
return INTERNAL_ERROR;
}
@@ -648,8 +527,8 @@ plc4c_return_code plc4c_driver_s7_read_machine_function(
}
plc4c_return_code plc4c_driver_s7_write_machine_function(
- plc4c_system_task *task) {
- plc4c_write_request_execution *write_request_execution = task->context;
+ plc4c_system_task* task) {
+ plc4c_write_request_execution* write_request_execution = task->context;
if (write_request_execution == NULL) {
return INTERNAL_ERROR;
}
@@ -671,9 +550,9 @@ plc4c_return_code plc4c_driver_s7_write_machine_function(
return OK;
}
-plc4c_return_code plc4c_driver_s7_connect_function(
- plc4c_connection *connection, plc4c_system_task **task) {
- plc4c_system_task *new_task = malloc(sizeof(plc4c_system_task));
+plc4c_return_code plc4c_driver_s7_connect_function(plc4c_connection* connection,
+ plc4c_system_task** task) {
+ plc4c_system_task* new_task = malloc(sizeof(plc4c_system_task));
// There's nothing to do here, so no need for a state-machine.
new_task->state_id = PLC4C_DRIVER_S7_CONNECT_INIT;
new_task->state_machine_function = &plc4c_driver_s7_connect_machine_function;
@@ -685,8 +564,8 @@ plc4c_return_code plc4c_driver_s7_connect_function(
}
plc4c_return_code plc4c_driver_s7_disconnect_function(
- plc4c_connection *connection, plc4c_system_task **task) {
- plc4c_system_task *new_task = malloc(sizeof(plc4c_system_task));
+ plc4c_connection* connection, plc4c_system_task** task) {
+ plc4c_system_task* new_task = malloc(sizeof(plc4c_system_task));
new_task->state_id = PLC4C_DRIVER_S7_DISCONNECT_INIT;
new_task->state_machine_function =
&plc4c_driver_s7_disconnect_machine_function;
@@ -698,9 +577,9 @@ plc4c_return_code plc4c_driver_s7_disconnect_function(
}
plc4c_return_code plc4c_driver_s7_read_function(
- plc4c_read_request_execution *read_request_execution,
- plc4c_system_task **task) {
- plc4c_system_task *new_task = malloc(sizeof(plc4c_system_task));
+ plc4c_read_request_execution* read_request_execution,
+ plc4c_system_task** task) {
+ plc4c_system_task* new_task = malloc(sizeof(plc4c_system_task));
new_task->state_id = PLC4C_DRIVER_S7_READ_INIT;
new_task->state_machine_function = &plc4c_driver_s7_read_machine_function;
new_task->completed = false;
@@ -711,23 +590,23 @@ plc4c_return_code plc4c_driver_s7_read_function(
}
void plc4c_driver_s7_free_read_response_item(
- plc4c_list_element *read_item_element) {
- plc4c_response_value_item *value_item =
- (plc4c_response_value_item *)read_item_element->value;
+ plc4c_list_element* read_item_element) {
+ plc4c_response_value_item* value_item =
+ (plc4c_response_value_item*)read_item_element->value;
plc4c_data_destroy(value_item->value);
value_item->value = NULL;
}
-void plc4c_driver_s7_free_read_response(plc4c_read_response *response) {
+void plc4c_driver_s7_free_read_response(plc4c_read_response* response) {
// the request will be cleaned up elsewhere
plc4c_utils_list_delete_elements(response->items,
&plc4c_driver_s7_free_read_response_item);
}
plc4c_return_code plc4c_driver_s7_write_function(
- plc4c_write_request_execution *write_request_execution,
- plc4c_system_task **task) {
- plc4c_system_task *new_task = malloc(sizeof(plc4c_system_task));
+ plc4c_write_request_execution* write_request_execution,
+ plc4c_system_task** task) {
+ plc4c_system_task* new_task = malloc(sizeof(plc4c_system_task));
new_task->state_id = PLC4C_DRIVER_S7_WRITE_INIT;
new_task->state_machine_function = &plc4c_driver_s7_write_machine_function;
new_task->completed = false;
@@ -738,9 +617,9 @@ plc4c_return_code plc4c_driver_s7_write_function(
}
void plc4c_driver_s7_free_write_response_item(
- plc4c_list_element *write_item_element) {
- plc4c_response_value_item *value_item =
- (plc4c_response_value_item *)write_item_element->value;
+ plc4c_list_element* write_item_element) {
+ plc4c_response_value_item* value_item =
+ (plc4c_response_value_item*)write_item_element->value;
// do not delete the plc4c_item
// we also, in THIS case don't delete the random value which isn't really
// a pointer
@@ -748,15 +627,14 @@ void plc4c_driver_s7_free_write_response_item(
value_item->value = NULL;
}
-void plc4c_driver_s7_free_write_response(
- plc4c_write_response *response) {
+void plc4c_driver_s7_free_write_response(plc4c_write_response* response) {
// the request will be cleaned up elsewhere
plc4c_utils_list_delete_elements(response->response_items,
&plc4c_driver_s7_free_write_response_item);
}
-plc4c_driver *plc4c_driver_s7_create() {
- plc4c_driver *driver = (plc4c_driver *)malloc(sizeof(plc4c_driver));
+plc4c_driver* plc4c_driver_s7_create() {
+ plc4c_driver* driver = (plc4c_driver*)malloc(sizeof(plc4c_driver));
driver->protocol_code = "s7";
driver->protocol_name = "Siemens S7 (Basic)";
driver->default_transport_code = "tcp";
@@ -773,3 +651,208 @@ plc4c_driver *plc4c_driver_s7_create() {
driver->free_unsubscription_response_function = NULL;
return driver;
}
+
+////////////////////////////////////////////////////////////////////////////////
+// Helpers for preparing the different packets
+////////////////////////////////////////////////////////////////////////////////
+
+plc4c_return_code createCOTPConnectionRequest(
+ plc4c_driver_s7_config* configuration,
+ plc4c_s7_read_write_tpkt_packet** cotp_connect_request_packet) {
+ *cotp_connect_request_packet =
+ malloc(sizeof(plc4c_s7_read_write_tpkt_packet));
+ if (*cotp_connect_request_packet == NULL) {
+ return NO_MEMORY;
+ }
+ (*cotp_connect_request_packet)->payload =
+ malloc(sizeof(plc4c_s7_read_write_cotp_packet));
+ if ((*cotp_connect_request_packet)->payload == NULL) {
+ return NO_MEMORY;
+ }
+ (*cotp_connect_request_packet)->payload->_type =
+ plc4c_s7_read_write_cotp_packet_type_plc4c_s7_read_write_cotp_packet_connection_request;
+ (*cotp_connect_request_packet)->payload
+ ->cotp_packet_connection_request_destination_reference = 0x0000;
+ (*cotp_connect_request_packet)->payload
+ ->cotp_packet_connection_request_source_reference = 0x000F;
+ (*cotp_connect_request_packet)->payload
+ ->cotp_packet_connection_request_protocol_class =
+ plc4c_s7_read_write_cotp_protocol_class_CLASS_0;
+
+ // Add the COTP parameters: Called TSAP, Calling TSAP and TPDU Size.
+ plc4c_utils_list_create(&((*cotp_connect_request_packet)->payload->parameters));
+ plc4c_s7_read_write_cotp_parameter* called_tsap_parameter =
+ malloc(sizeof(plc4c_s7_read_write_cotp_parameter));
+ if (called_tsap_parameter == NULL) {
+ return NO_MEMORY;
+ }
+ called_tsap_parameter->_type =
+ plc4c_s7_read_write_cotp_parameter_type_plc4c_s7_read_write_cotp_parameter_called_tsap;
+ called_tsap_parameter->cotp_parameter_called_tsap_tsap_id =
+ configuration->called_tsap_id;
+
+ plc4c_utils_list_insert_head_value(
+ (*cotp_connect_request_packet)->payload->parameters, called_tsap_parameter);
+ plc4c_s7_read_write_cotp_parameter* calling_tsap_parameter =
+ malloc(sizeof(plc4c_s7_read_write_cotp_parameter));
+ if (calling_tsap_parameter == NULL) {
+ return NO_MEMORY;
+ }
+ calling_tsap_parameter->_type =
+ plc4c_s7_read_write_cotp_parameter_type_plc4c_s7_read_write_cotp_parameter_calling_tsap;
+ calling_tsap_parameter->cotp_parameter_calling_tsap_tsap_id =
+ configuration->calling_tsap_id;
+
+ plc4c_utils_list_insert_head_value(
+ (*cotp_connect_request_packet)->payload->parameters, calling_tsap_parameter);
+ plc4c_s7_read_write_cotp_parameter* tpdu_size_parameter =
+ malloc(sizeof(plc4c_s7_read_write_cotp_parameter));
+ if (tpdu_size_parameter == NULL) {
+ return NO_MEMORY;
+ }
+ tpdu_size_parameter->_type =
+ plc4c_s7_read_write_cotp_parameter_type_plc4c_s7_read_write_cotp_parameter_tpdu_size;
+ tpdu_size_parameter->cotp_parameter_tpdu_size_tpdu_size =
+ configuration->cotp_tpdu_size;
+
+ plc4c_utils_list_insert_head_value(
+ (*cotp_connect_request_packet)->payload->parameters, tpdu_size_parameter);
+
+ // For a COTP connection request, there is no payload.
+ (*cotp_connect_request_packet)->payload->payload = NULL;
+
+ return OK;
+}
+
+plc4c_return_code createS7ConnectionRequest(
+ plc4c_driver_s7_config* configuration,
+ plc4c_s7_read_write_tpkt_packet** s7_connect_request_packet) {
+ *s7_connect_request_packet = malloc(sizeof(plc4c_s7_read_write_tpkt_packet));
+ if (*s7_connect_request_packet == NULL) {
+ return NO_MEMORY;
+ }
+ (*s7_connect_request_packet)->payload =
+ malloc(sizeof(plc4c_s7_read_write_cotp_packet));
+ if ((*s7_connect_request_packet)->payload == NULL) {
+ return NO_MEMORY;
+ }
+ (*s7_connect_request_packet)->payload->_type =
+ plc4c_s7_read_write_cotp_packet_type_plc4c_s7_read_write_cotp_packet_data;
+ (*s7_connect_request_packet)->payload->parameters = NULL;
+ (*s7_connect_request_packet)->payload->cotp_packet_data_eot = true;
+ (*s7_connect_request_packet)->payload->cotp_packet_data_tpdu_ref = 1;
+
+ (*s7_connect_request_packet)->payload->payload =
+ malloc(sizeof(plc4c_s7_read_write_s7_message));
+ if ((*s7_connect_request_packet)->payload->payload == NULL) {
+ return NO_MEMORY;
+ }
+ (*s7_connect_request_packet)->payload->payload->_type =
+ plc4c_s7_read_write_s7_message_type_plc4c_s7_read_write_s7_message_request;
+ (*s7_connect_request_packet)->payload->payload->parameter =
+ malloc(sizeof(plc4c_s7_read_write_s7_parameter));
+ if ((*s7_connect_request_packet)->payload->payload->parameter == NULL) {
+ return NO_MEMORY;
+ }
+ (*s7_connect_request_packet)->payload->payload->parameter->_type =
+ plc4c_s7_read_write_s7_parameter_type_plc4c_s7_read_write_s7_parameter_setup_communication;
+ (*s7_connect_request_packet)->payload->payload->parameter
+ ->s7_parameter_setup_communication_max_amq_callee =
+ configuration->max_amq_callee;
+ (*s7_connect_request_packet)->payload->payload->parameter
+ ->s7_parameter_setup_communication_max_amq_caller =
+ configuration->max_amq_caller;
+ (*s7_connect_request_packet)->payload->payload->parameter
+ ->s7_parameter_setup_communication_pdu_length =
+ configuration->pdu_size;
+
+ return OK;
+}
+
+plc4c_return_code createS7IdentifyRemoteRequest(
+ plc4c_s7_read_write_tpkt_packet** s7_identify_remote_request_packet) {
+
+ *s7_identify_remote_request_packet =
+ malloc(sizeof(plc4c_s7_read_write_tpkt_packet));
+ if (*s7_identify_remote_request_packet == NULL) {
+ return NO_MEMORY;
+ }
+ (*s7_identify_remote_request_packet)->payload =
+ malloc(sizeof(plc4c_s7_read_write_cotp_packet));
+ if ((*s7_identify_remote_request_packet)->payload == NULL) {
+ return NO_MEMORY;
+ }
+ (*s7_identify_remote_request_packet)->payload->_type =
+ plc4c_s7_read_write_cotp_packet_type_plc4c_s7_read_write_cotp_packet_data;
+ (*s7_identify_remote_request_packet)->payload->parameters = NULL;
+ (*s7_identify_remote_request_packet)->payload->cotp_packet_data_eot = true;
+ (*s7_identify_remote_request_packet)->payload->cotp_packet_data_tpdu_ref = 2;
+
+ (*s7_identify_remote_request_packet)->payload->payload =
+ malloc(sizeof(plc4c_s7_read_write_s7_message));
+ if ((*s7_identify_remote_request_packet)->payload->payload == NULL) {
+ return NO_MEMORY;
+ }
+ (*s7_identify_remote_request_packet)->payload->payload->_type =
+ plc4c_s7_read_write_s7_message_type_plc4c_s7_read_write_s7_message_user_data;
+ (*s7_identify_remote_request_packet)->payload->payload->parameter =
+ malloc(sizeof(plc4c_s7_read_write_s7_parameter));
+ if ((*s7_identify_remote_request_packet)->payload->payload->parameter ==
+ NULL) {
+ return NO_MEMORY;
+ }
+ (*s7_identify_remote_request_packet)->payload->payload->parameter->_type =
+ plc4c_s7_read_write_s7_parameter_type_plc4c_s7_read_write_s7_parameter_user_data;
+
+ plc4c_utils_list_create(
+ &((*s7_identify_remote_request_packet)->payload->payload->parameter
+ ->s7_parameter_user_data_items));
+ plc4c_s7_read_write_s7_parameter_user_data_item* parameter_item =
+ malloc(sizeof(plc4c_s7_read_write_s7_parameter_user_data_item));
+ parameter_item->_type =
+ plc4c_s7_read_write_s7_parameter_user_data_item_type_plc4c_s7_read_write_s7_parameter_user_data_item_cpu_functions;
+ parameter_item->s7_parameter_user_data_item_cpu_functions_method = 0x11;
+ parameter_item
+ ->s7_parameter_user_data_item_cpu_functions_cpu_function_type = 0x4;
+ parameter_item
+ ->s7_parameter_user_data_item_cpu_functions_cpu_function_group = 0x4;
+ parameter_item
+ ->s7_parameter_user_data_item_cpu_functions_cpu_subfunction = 0x01;
+ parameter_item
+ ->s7_parameter_user_data_item_cpu_functions_sequence_number = 0x00;
+ parameter_item
+ ->s7_parameter_user_data_item_cpu_functions_data_unit_reference_number =
+ NULL;
+ parameter_item->s7_parameter_user_data_item_cpu_functions_last_data_unit =
+ NULL;
+ parameter_item->s7_parameter_user_data_item_cpu_functions_error_code =
+ NULL;
+ plc4c_utils_list_insert_head_value(
+ (*s7_identify_remote_request_packet)->payload->payload->parameter
+ ->s7_parameter_user_data_items,
+ parameter_item);
+
+ plc4c_utils_list_create(
+ &((*s7_identify_remote_request_packet)->payload->payload->payload
+ ->s7_payload_user_data_items));
+ plc4c_s7_read_write_s7_payload_user_data_item* payload_item =
+ malloc(sizeof(plc4c_s7_read_write_s7_payload_user_data_item));
+ payload_item->_type =
+ plc4c_s7_read_write_s7_payload_user_data_item_type_plc4c_s7_read_write_s7_payload_user_data_item_cpu_function_read_szl_request;
+ payload_item->return_code =
+ plc4c_s7_read_write_data_transport_error_code_OK;
+ payload_item->transport_size =
+ plc4c_s7_read_write_data_transport_size_OCTET_STRING;
+ payload_item->szl_index = 0x0000;
+ payload_item->szl_id = malloc(sizeof(plc4c_s7_read_write_szl_id));
+ if (payload_item->szl_id == NULL) {
+ return NO_MEMORY;
+ }
+ payload_item->szl_id->type_class =
+ plc4c_s7_read_write_szl_module_type_class_CPU;
+ payload_item->szl_id->sublist_extract = 0x00;
+ payload_item->szl_id->sublist_list =
+ plc4c_s7_read_write_szl_sublist_MODULE_IDENTIFICATION;
+
+ return OK;
+}
diff --git a/sandbox/plc4c/generated-sources/s7/includes/cotp_protocol_class.h b/sandbox/plc4c/generated-sources/s7/includes/cotp_protocol_class.h
index 2efcff7..33db7a7 100644
--- a/sandbox/plc4c/generated-sources/s7/includes/cotp_protocol_class.h
+++ b/sandbox/plc4c/generated-sources/s7/includes/cotp_protocol_class.h
@@ -39,6 +39,8 @@ typedef enum plc4c_s7_read_write_cotp_protocol_class plc4c_s7_read_write_cotp_pr
// Get an empty NULL-struct
plc4c_s7_read_write_cotp_protocol_class plc4c_s7_read_write_cotp_protocol_class_null();
+int plc4c_s7_read_write_cotp_protocol_class_num_values();
+
#ifdef __cplusplus
}
diff --git a/sandbox/plc4c/generated-sources/s7/includes/cotp_tpdu_size.h b/sandbox/plc4c/generated-sources/s7/includes/cotp_tpdu_size.h
index 38f156d..a5b9961 100644
--- a/sandbox/plc4c/generated-sources/s7/includes/cotp_tpdu_size.h
+++ b/sandbox/plc4c/generated-sources/s7/includes/cotp_tpdu_size.h
@@ -41,6 +41,8 @@ typedef enum plc4c_s7_read_write_cotp_tpdu_size plc4c_s7_read_write_cotp_tpdu_si
// Get an empty NULL-struct
plc4c_s7_read_write_cotp_tpdu_size plc4c_s7_read_write_cotp_tpdu_size_null();
+int plc4c_s7_read_write_cotp_tpdu_size_num_values();
+
uint16_t plc4c_s7_read_write_cotp_tpdu_size_get_size_in_bytes(plc4c_s7_read_write_cotp_tpdu_size value);
diff --git a/sandbox/plc4c/generated-sources/s7/includes/data_transport_error_code.h b/sandbox/plc4c/generated-sources/s7/includes/data_transport_error_code.h
index 94bc081..c85e236 100644
--- a/sandbox/plc4c/generated-sources/s7/includes/data_transport_error_code.h
+++ b/sandbox/plc4c/generated-sources/s7/includes/data_transport_error_code.h
@@ -40,6 +40,8 @@ typedef enum plc4c_s7_read_write_data_transport_error_code plc4c_s7_read_write_d
// Get an empty NULL-struct
plc4c_s7_read_write_data_transport_error_code plc4c_s7_read_write_data_transport_error_code_null();
+int plc4c_s7_read_write_data_transport_error_code_num_values();
+
#ifdef __cplusplus
}
diff --git a/sandbox/plc4c/generated-sources/s7/includes/data_transport_size.h b/sandbox/plc4c/generated-sources/s7/includes/data_transport_size.h
index cbfc150..943a42d 100644
--- a/sandbox/plc4c/generated-sources/s7/includes/data_transport_size.h
+++ b/sandbox/plc4c/generated-sources/s7/includes/data_transport_size.h
@@ -41,6 +41,8 @@ typedef enum plc4c_s7_read_write_data_transport_size plc4c_s7_read_write_data_tr
// Get an empty NULL-struct
plc4c_s7_read_write_data_transport_size plc4c_s7_read_write_data_transport_size_null();
+int plc4c_s7_read_write_data_transport_size_num_values();
+
bool plc4c_s7_read_write_data_transport_size_get_size_in_bits(plc4c_s7_read_write_data_transport_size value);
diff --git a/sandbox/plc4c/generated-sources/s7/includes/device_group.h b/sandbox/plc4c/generated-sources/s7/includes/device_group.h
index 9f8af73..2c0cb64 100644
--- a/sandbox/plc4c/generated-sources/s7/includes/device_group.h
+++ b/sandbox/plc4c/generated-sources/s7/includes/device_group.h
@@ -37,6 +37,8 @@ typedef enum plc4c_s7_read_write_device_group plc4c_s7_read_write_device_group;
// Get an empty NULL-struct
plc4c_s7_read_write_device_group plc4c_s7_read_write_device_group_null();
+int plc4c_s7_read_write_device_group_num_values();
+
#ifdef __cplusplus
}
diff --git a/sandbox/plc4c/generated-sources/s7/includes/memory_area.h b/sandbox/plc4c/generated-sources/s7/includes/memory_area.h
index d172543..311b43d 100644
--- a/sandbox/plc4c/generated-sources/s7/includes/memory_area.h
+++ b/sandbox/plc4c/generated-sources/s7/includes/memory_area.h
@@ -43,6 +43,8 @@ typedef enum plc4c_s7_read_write_memory_area plc4c_s7_read_write_memory_area;
// Get an empty NULL-struct
plc4c_s7_read_write_memory_area plc4c_s7_read_write_memory_area_null();
+int plc4c_s7_read_write_memory_area_num_values();
+
char* plc4c_s7_read_write_memory_area_get_short_name(plc4c_s7_read_write_memory_area value);
diff --git a/sandbox/plc4c/generated-sources/s7/includes/szl_module_type_class.h b/sandbox/plc4c/generated-sources/s7/includes/szl_module_type_class.h
index 0af468c..be1fef7 100644
--- a/sandbox/plc4c/generated-sources/s7/includes/szl_module_type_class.h
+++ b/sandbox/plc4c/generated-sources/s7/includes/szl_module_type_class.h
@@ -38,6 +38,8 @@ typedef enum plc4c_s7_read_write_szl_module_type_class plc4c_s7_read_write_szl_m
// Get an empty NULL-struct
plc4c_s7_read_write_szl_module_type_class plc4c_s7_read_write_szl_module_type_class_null();
+int plc4c_s7_read_write_szl_module_type_class_num_values();
+
#ifdef __cplusplus
}
diff --git a/sandbox/plc4c/generated-sources/s7/includes/szl_sublist.h b/sandbox/plc4c/generated-sources/s7/includes/szl_sublist.h
index 4aa623e..626bfae 100644
--- a/sandbox/plc4c/generated-sources/s7/includes/szl_sublist.h
+++ b/sandbox/plc4c/generated-sources/s7/includes/szl_sublist.h
@@ -53,6 +53,8 @@ typedef enum plc4c_s7_read_write_szl_sublist plc4c_s7_read_write_szl_sublist;
// Get an empty NULL-struct
plc4c_s7_read_write_szl_sublist plc4c_s7_read_write_szl_sublist_null();
+int plc4c_s7_read_write_szl_sublist_num_values();
+
#ifdef __cplusplus
}
diff --git a/sandbox/plc4c/generated-sources/s7/includes/transport_size.h b/sandbox/plc4c/generated-sources/s7/includes/transport_size.h
index 9601b8c..a2c1f12 100644
--- a/sandbox/plc4c/generated-sources/s7/includes/transport_size.h
+++ b/sandbox/plc4c/generated-sources/s7/includes/transport_size.h
@@ -60,6 +60,8 @@ typedef enum plc4c_s7_read_write_transport_size plc4c_s7_read_write_transport_si
// Get an empty NULL-struct
plc4c_s7_read_write_transport_size plc4c_s7_read_write_transport_size_null();
+int plc4c_s7_read_write_transport_size_num_values();
+
bool plc4c_s7_read_write_transport_size_get_supported__s7_300(plc4c_s7_read_write_transport_size value);
diff --git a/sandbox/plc4c/generated-sources/s7/src/cotp_protocol_class.c b/sandbox/plc4c/generated-sources/s7/src/cotp_protocol_class.c
index 4f46d34..8dfa8de 100644
--- a/sandbox/plc4c/generated-sources/s7/src/cotp_protocol_class.c
+++ b/sandbox/plc4c/generated-sources/s7/src/cotp_protocol_class.c
@@ -27,3 +27,7 @@ plc4c_s7_read_write_cotp_protocol_class plc4c_s7_read_write_cotp_protocol_class_
return plc4c_s7_read_write_cotp_protocol_class_null_const;
}
+int plc4c_s7_read_write_cotp_protocol_class_num_values() {
+ return 5;
+}
+
diff --git a/sandbox/plc4c/generated-sources/s7/src/cotp_tpdu_size.c b/sandbox/plc4c/generated-sources/s7/src/cotp_tpdu_size.c
index b6cfa78..3f02d05 100644
--- a/sandbox/plc4c/generated-sources/s7/src/cotp_tpdu_size.c
+++ b/sandbox/plc4c/generated-sources/s7/src/cotp_tpdu_size.c
@@ -27,6 +27,10 @@ plc4c_s7_read_write_cotp_tpdu_size plc4c_s7_read_write_cotp_tpdu_size_null() {
return plc4c_s7_read_write_cotp_tpdu_size_null_const;
}
+int plc4c_s7_read_write_cotp_tpdu_size_num_values() {
+ return 7;
+}
+
uint16_t plc4c_s7_read_write_cotp_tpdu_size_get_size_in_bytes(plc4c_s7_read_write_cotp_tpdu_size value) {
switch(value) {
diff --git a/sandbox/plc4c/generated-sources/s7/src/data_transport_error_code.c b/sandbox/plc4c/generated-sources/s7/src/data_transport_error_code.c
index 7baf834..9756535 100644
--- a/sandbox/plc4c/generated-sources/s7/src/data_transport_error_code.c
+++ b/sandbox/plc4c/generated-sources/s7/src/data_transport_error_code.c
@@ -27,3 +27,7 @@ plc4c_s7_read_write_data_transport_error_code plc4c_s7_read_write_data_transport
return plc4c_s7_read_write_data_transport_error_code_null_const;
}
+int plc4c_s7_read_write_data_transport_error_code_num_values() {
+ return 6;
+}
+
diff --git a/sandbox/plc4c/generated-sources/s7/src/data_transport_size.c b/sandbox/plc4c/generated-sources/s7/src/data_transport_size.c
index dcea90b..8e57457 100644
--- a/sandbox/plc4c/generated-sources/s7/src/data_transport_size.c
+++ b/sandbox/plc4c/generated-sources/s7/src/data_transport_size.c
@@ -27,6 +27,10 @@ plc4c_s7_read_write_data_transport_size plc4c_s7_read_write_data_transport_size_
return plc4c_s7_read_write_data_transport_size_null_const;
}
+int plc4c_s7_read_write_data_transport_size_num_values() {
+ return 7;
+}
+
bool plc4c_s7_read_write_data_transport_size_get_size_in_bits(plc4c_s7_read_write_data_transport_size value) {
switch(value) {
diff --git a/sandbox/plc4c/generated-sources/s7/src/device_group.c b/sandbox/plc4c/generated-sources/s7/src/device_group.c
index 91bca89..3a1cf5f 100644
--- a/sandbox/plc4c/generated-sources/s7/src/device_group.c
+++ b/sandbox/plc4c/generated-sources/s7/src/device_group.c
@@ -27,3 +27,7 @@ plc4c_s7_read_write_device_group plc4c_s7_read_write_device_group_null() {
return plc4c_s7_read_write_device_group_null_const;
}
+int plc4c_s7_read_write_device_group_num_values() {
+ return 3;
+}
+
diff --git a/sandbox/plc4c/generated-sources/s7/src/memory_area.c b/sandbox/plc4c/generated-sources/s7/src/memory_area.c
index 503ba73..e6574ad 100644
--- a/sandbox/plc4c/generated-sources/s7/src/memory_area.c
+++ b/sandbox/plc4c/generated-sources/s7/src/memory_area.c
@@ -27,6 +27,10 @@ plc4c_s7_read_write_memory_area plc4c_s7_read_write_memory_area_null() {
return plc4c_s7_read_write_memory_area_null_const;
}
+int plc4c_s7_read_write_memory_area_num_values() {
+ return 9;
+}
+
char* plc4c_s7_read_write_memory_area_get_short_name(plc4c_s7_read_write_memory_area value) {
switch(value) {
diff --git a/sandbox/plc4c/generated-sources/s7/src/szl_module_type_class.c b/sandbox/plc4c/generated-sources/s7/src/szl_module_type_class.c
index fe5ec8f..b042166 100644
--- a/sandbox/plc4c/generated-sources/s7/src/szl_module_type_class.c
+++ b/sandbox/plc4c/generated-sources/s7/src/szl_module_type_class.c
@@ -27,3 +27,7 @@ plc4c_s7_read_write_szl_module_type_class plc4c_s7_read_write_szl_module_type_cl
return plc4c_s7_read_write_szl_module_type_class_null_const;
}
+int plc4c_s7_read_write_szl_module_type_class_num_values() {
+ return 4;
+}
+
diff --git a/sandbox/plc4c/generated-sources/s7/src/szl_sublist.c b/sandbox/plc4c/generated-sources/s7/src/szl_sublist.c
index e33f462..3dcd087 100644
--- a/sandbox/plc4c/generated-sources/s7/src/szl_sublist.c
+++ b/sandbox/plc4c/generated-sources/s7/src/szl_sublist.c
@@ -27,3 +27,7 @@ plc4c_s7_read_write_szl_sublist plc4c_s7_read_write_szl_sublist_null() {
return plc4c_s7_read_write_szl_sublist_null_const;
}
+int plc4c_s7_read_write_szl_sublist_num_values() {
+ return 19;
+}
+
diff --git a/sandbox/plc4c/generated-sources/s7/src/transport_size.c b/sandbox/plc4c/generated-sources/s7/src/transport_size.c
index 026a73f..a772d87 100644
--- a/sandbox/plc4c/generated-sources/s7/src/transport_size.c
+++ b/sandbox/plc4c/generated-sources/s7/src/transport_size.c
@@ -29,6 +29,10 @@ plc4c_s7_read_write_transport_size plc4c_s7_read_write_transport_size_null() {
return plc4c_s7_read_write_transport_size_null_const;
}
+int plc4c_s7_read_write_transport_size_num_values() {
+ return 24;
+}
+
bool plc4c_s7_read_write_transport_size_get_supported__s7_300(plc4c_s7_read_write_transport_size value) {
switch(value) {
diff --git a/sandbox/plc4c/spi/src/utils/list.c b/sandbox/plc4c/spi/src/utils/list.c
index d570cc3..5d81dbb 100644
--- a/sandbox/plc4c/spi/src/utils/list.c
+++ b/sandbox/plc4c/spi/src/utils/list.c
@@ -20,6 +20,7 @@
#include <plc4c/utils/list.h>
void plc4c_utils_list_create(plc4c_list **list) {
+ // TODO: Add a NULL-Check ...
plc4c_list *new_list = malloc(sizeof(plc4c_list));
new_list->head = NULL;
new_list->tail = NULL;