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/09/14 07:15:41 UTC
[plc4x] 02/02: - Working on the C 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
commit 7991d4a8cab84fead0e4902fe1ce8acd099a5b4c
Author: Christofer Dutz <ch...@c-ware.de>
AuthorDate: Mon Sep 14 09:15:30 2020 +0200
- Working on the C S7 driver
---
.../s7/readwrite/protocol/S7ProtocolLogic.java | 13 ++-
sandbox/plc4c/api/include/plc4c/connection.h | 10 +-
sandbox/plc4c/api/include/plc4c/types.h | 1 +
.../drivers/modbus/src/driver_modbus_packets.c | 7 +-
.../drivers/modbus/src/driver_modbus_sm_connect.c | 1 +
sandbox/plc4c/drivers/s7/include/plc4c/driver_s7.h | 4 +-
sandbox/plc4c/drivers/s7/src/driver_s7.c | 25 +++++
.../plc4c/drivers/s7/src/driver_s7_encode_decode.c | 5 +-
sandbox/plc4c/drivers/s7/src/driver_s7_packets.c | 35 +++++--
.../plc4c/drivers/s7/src/driver_s7_sm_connect.c | 14 ++-
.../s7/src/s7_payload_user_data_item.c | 4 +-
.../plc4c/spi/include/plc4c/spi/types_private.h | 13 ++-
sandbox/plc4c/spi/src/connection.c | 5 +
sandbox/plc4c/spi/src/system.c | 17 +++-
sandbox/plc4c/spi/src/utils/list.c | 2 +-
.../plc4c/transports/serial/src/transport_serial.c | 3 +-
.../transports/tcp/include/plc4c/transport_tcp.h | 8 ++
sandbox/plc4c/transports/tcp/src/transport_tcp.c | 103 ++++++++++++++++++++-
18 files changed, 240 insertions(+), 30 deletions(-)
diff --git a/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/protocol/S7ProtocolLogic.java b/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/protocol/S7ProtocolLogic.java
index e0d5b0d..0b6e4ec 100644
--- a/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/protocol/S7ProtocolLogic.java
+++ b/plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/protocol/S7ProtocolLogic.java
@@ -297,11 +297,14 @@ public class S7ProtocolLogic extends Plc4xProtocolBase<TPKTPacket> {
}
private TPKTPacket createIdentifyRemoteMessage() {
- S7MessageUserData identifyRemoteMessage = new S7MessageUserData(1, new S7ParameterUserData(new S7ParameterUserDataItem[]{
- new S7ParameterUserDataItemCPUFunctions((short) 0x11, (byte) 0x4, (byte) 0x4, (short) 0x01, (short) 0x00, null, null, null)
- }), new S7PayloadUserData(new S7PayloadUserDataItem[]{
- new S7PayloadUserDataItemCpuFunctionReadSzlRequest(DataTransportErrorCode.OK, DataTransportSize.OCTET_STRING, new SzlId(SzlModuleTypeClass.CPU, (byte) 0x00, SzlSublist.MODULE_IDENTIFICATION), 0x0000)
- }));
+ S7MessageUserData identifyRemoteMessage = new S7MessageUserData(1,
+ new S7ParameterUserData(new S7ParameterUserDataItem[]{
+ new S7ParameterUserDataItemCPUFunctions((short) 0x11, (byte) 0x4, (byte) 0x4, (short) 0x01, (short) 0x00, null, null, null)
+ }),
+ new S7PayloadUserData(new S7PayloadUserDataItem[]{
+ new S7PayloadUserDataItemCpuFunctionReadSzlRequest(DataTransportErrorCode.OK, DataTransportSize.OCTET_STRING, new SzlId(SzlModuleTypeClass.CPU, (byte) 0x00, SzlSublist.MODULE_IDENTIFICATION), 0x0000)
+ })
+ );
COTPPacketData cotpPacketData = new COTPPacketData(null, identifyRemoteMessage, true, (short) 2);
return new TPKTPacket(cotpPacketData);
}
diff --git a/sandbox/plc4c/api/include/plc4c/connection.h b/sandbox/plc4c/api/include/plc4c/connection.h
index c1e8e47..2818add 100644
--- a/sandbox/plc4c/api/include/plc4c/connection.h
+++ b/sandbox/plc4c/api/include/plc4c/connection.h
@@ -186,12 +186,20 @@ plc4c_driver *plc4c_connection_get_driver(plc4c_connection *connection);
/**
* Sets a plc4c_driver for a given connection
* @param connection plc4c_connection
- * @param plc4c_driver
+ * @param plc4c_driver driver
*/
void plc4c_connection_set_driver(plc4c_connection *connection,
plc4c_driver *driver);
/**
+ * Sets the configuration for a given connection.
+ *
+ * @param connection plc4c connection
+ * @param configuration configuration
+ */
+void plc4c_connection_set_configuration(plc4c_connection *connection,
+ void *configuration);
+/**
* Check if an error occurred while connecting.
*
* @param connection the connection.
diff --git a/sandbox/plc4c/api/include/plc4c/types.h b/sandbox/plc4c/api/include/plc4c/types.h
index e364753..cc2157f 100644
--- a/sandbox/plc4c/api/include/plc4c/types.h
+++ b/sandbox/plc4c/api/include/plc4c/types.h
@@ -54,6 +54,7 @@ typedef enum plc4c_return_code {
PARSE_ERROR,
UNKNOWN_ERROR,
+ CONNECTION_ERROR,
INTERNAL_ERROR,
NOT_IMPLEMENTED
} plc4c_return_code;
diff --git a/sandbox/plc4c/drivers/modbus/src/driver_modbus_packets.c b/sandbox/plc4c/drivers/modbus/src/driver_modbus_packets.c
index 54ce4cc..af50cbe 100644
--- a/sandbox/plc4c/drivers/modbus/src/driver_modbus_packets.c
+++ b/sandbox/plc4c/drivers/modbus/src/driver_modbus_packets.c
@@ -68,7 +68,8 @@ plc4c_return_code plc4c_driver_modbus_send_packet(plc4c_connection* connection,
plc4c_modbus_read_write_modbus_tcp_adu_serialize(write_buffer, packet);
// Now send this to the recipient.
- return_code = connection->transport->send_message(write_buffer);
+ return_code = connection->transport->send_message(
+ connection->transport_configuration, write_buffer);
if (return_code != OK) {
return return_code;
}
@@ -82,7 +83,9 @@ plc4c_return_code plc4c_driver_modbus_receive_packet(plc4c_connection* connectio
// If it is, get a read_buffer for reading it.
plc4c_spi_read_buffer* read_buffer;
plc4c_return_code return_code = connection->transport->select_message(
- plc4c_driver_modbus_select_message_function, &read_buffer);
+ connection->transport_configuration,
+ 6, plc4c_driver_modbus_select_message_function,
+ &read_buffer);
// OK is only returned if a packet is available.
if (return_code != OK) {
return return_code;
diff --git a/sandbox/plc4c/drivers/modbus/src/driver_modbus_sm_connect.c b/sandbox/plc4c/drivers/modbus/src/driver_modbus_sm_connect.c
index 9ecbb66..a093567 100644
--- a/sandbox/plc4c/drivers/modbus/src/driver_modbus_sm_connect.c
+++ b/sandbox/plc4c/drivers/modbus/src/driver_modbus_sm_connect.c
@@ -37,6 +37,7 @@ plc4c_return_code plc4c_driver_modbus_connect_machine_function(
plc4c_return_code plc4c_driver_modbus_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 = -1;
diff --git a/sandbox/plc4c/drivers/s7/include/plc4c/driver_s7.h b/sandbox/plc4c/drivers/s7/include/plc4c/driver_s7.h
index 78bd46d..a0cb706 100644
--- a/sandbox/plc4c/drivers/s7/include/plc4c/driver_s7.h
+++ b/sandbox/plc4c/drivers/s7/include/plc4c/driver_s7.h
@@ -25,6 +25,8 @@ extern "C" {
#include <plc4c/types.h>
#include <stdint.h>
+#include "../../../../generated-sources/s7/includes/cotp_tpdu_size.h"
+
enum plc4c_driver_s7_controller_type {
PLC4C_DRIVER_S7_CONTROLLER_TYPE_ANY = 0,
PLC4C_DRIVER_S7_CONTROLLER_TYPE_S7_300 = 1,
@@ -49,7 +51,7 @@ struct plc4c_driver_s7_config {
uint8_t remote_slot;
uint16_t calling_tsap_id;
uint16_t called_tsap_id;
- uint16_t cotp_tpdu_size;
+ plc4c_s7_read_write_cotp_tpdu_size cotp_tpdu_size;
uint16_t pdu_size;
uint8_t max_amq_caller;
uint8_t max_amq_callee;
diff --git a/sandbox/plc4c/drivers/s7/src/driver_s7.c b/sandbox/plc4c/drivers/s7/src/driver_s7.c
index d4f9862..2fe21e2 100644
--- a/sandbox/plc4c/drivers/s7/src/driver_s7.c
+++ b/sandbox/plc4c/drivers/s7/src/driver_s7.c
@@ -17,14 +17,39 @@
under the License.
*/
+#include "plc4c/driver_s7.h"
#include "plc4c/driver_s7_sm.h"
+plc4c_return_code plc4c_driver_s7_configure_function(
+ plc4c_list* parameters, void** configuration) {
+ plc4c_driver_s7_config* s7_config = malloc(sizeof(plc4c_driver_s7_config));
+ if(s7_config == NULL) {
+ return NO_MEMORY;
+ }
+
+ // Initialize the parts that the user can influence.
+ s7_config->local_rack = 1;
+ s7_config->local_slot = 1;
+ s7_config->remote_rack = 0;
+ s7_config->remote_slot = 0;
+ s7_config->pdu_size = 1024;
+ s7_config->max_amq_caller = 8;
+ s7_config->max_amq_callee = 8;
+ s7_config->controller_type = PLC4C_DRIVER_S7_CONTROLLER_TYPE_ANY;
+
+ // TODO: Apply the values from the parameters.
+
+ *configuration = s7_config;
+ return OK;
+}
+
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";
driver->parse_address_function = NULL;
+ driver->configure_function = &plc4c_driver_s7_configure_function;
driver->connect_function = &plc4c_driver_s7_connect_function;
driver->disconnect_function = &plc4c_driver_s7_disconnect_function;
driver->read_function = &plc4c_driver_s7_read_function;
diff --git a/sandbox/plc4c/drivers/s7/src/driver_s7_encode_decode.c b/sandbox/plc4c/drivers/s7/src/driver_s7_encode_decode.c
index 95a4880..27972ea 100644
--- a/sandbox/plc4c/drivers/s7/src/driver_s7_encode_decode.c
+++ b/sandbox/plc4c/drivers/s7/src/driver_s7_encode_decode.c
@@ -35,9 +35,10 @@ uint16_t plc4c_driver_s7_encode_tsap_id(
uint16_t plc4c_driver_s7_get_nearest_matching_tpdu_size(uint16_t pdu_size) {
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);
+ plc4c_s7_read_write_cotp_tpdu_size_get_size_in_bytes(
+ plc4c_s7_read_write_cotp_tpdu_size_value_for_index(i));
if (cur_value >= pdu_size) {
- return cur_value;
+ return plc4c_s7_read_write_cotp_tpdu_size_value_for_index(i);
}
}
return 0;
diff --git a/sandbox/plc4c/drivers/s7/src/driver_s7_packets.c b/sandbox/plc4c/drivers/s7/src/driver_s7_packets.c
index c79a053..2fb06c5 100644
--- a/sandbox/plc4c/drivers/s7/src/driver_s7_packets.c
+++ b/sandbox/plc4c/drivers/s7/src/driver_s7_packets.c
@@ -62,8 +62,8 @@ int16_t plc4c_driver_s7_select_message_function(uint8_t* buffer_data,
// The length information is located in bytes 3 and 4
if (buffer_length >= 4) {
uint16_t packet_length =
- ((uint16_t) (buffer_data + 2) << 8) |
- ((uint16_t) (buffer_data + 3));
+ ((uint16_t) *(buffer_data + 2) << 8) |
+ ((uint16_t) *(buffer_data + 3));
if (buffer_length >= packet_length) {
return packet_length;
}
@@ -79,6 +79,7 @@ int16_t plc4c_driver_s7_select_message_function(uint8_t* buffer_data,
}
return -(buffer_length - 1);
}
+ return packet_length;
}
// In all other cases, we'll just have to wait for the next time.
return 0;
@@ -97,10 +98,13 @@ plc4c_return_code plc4c_driver_s7_send_packet(plc4c_connection* connection,
if (return_code != OK) {
return return_code;
}
- plc4c_s7_read_write_tpkt_packet_serialize(write_buffer, packet);
+ return_code = plc4c_s7_read_write_tpkt_packet_serialize(write_buffer, packet);
+ if(return_code != OK) {
+ return return_code;
+ }
// Now send this to the recipient.
- return_code = connection->transport->send_message(write_buffer);
+ return_code = connection->transport->send_message(connection->transport_configuration, write_buffer);
if (return_code != OK) {
return return_code;
}
@@ -114,7 +118,9 @@ plc4c_return_code plc4c_driver_s7_receive_packet(plc4c_connection* connection,
// If it is, get a read_buffer for reading it.
plc4c_spi_read_buffer* read_buffer;
plc4c_return_code return_code = connection->transport->select_message(
- plc4c_driver_s7_select_message_function, &read_buffer);
+ connection->transport_configuration,
+ 4, plc4c_driver_s7_select_message_function,
+ &read_buffer);
// OK is only returned if a packet is available.
if (return_code != OK) {
return return_code;
@@ -295,18 +301,19 @@ plc4c_return_code plc4c_driver_s7_create_s7_identify_remote_request(
}
(*s7_identify_remote_request_packet)->payload->payload->_type =
plc4c_s7_read_write_s7_message_type_plc4c_s7_read_write_s7_message_user_data;
+
+ // Create a Parameter
(*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) {
+ 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));
+ // Create the Parameter Item
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 =
@@ -331,9 +338,17 @@ plc4c_return_code plc4c_driver_s7_create_s7_identify_remote_request(
->payload->payload->parameter->s7_parameter_user_data_items,
parameter_item);
+ // Create the Payload
+ (*s7_identify_remote_request_packet)->payload->payload->payload = malloc(sizeof(plc4c_s7_read_write_s7_payload));
+ if ((*s7_identify_remote_request_packet)->payload->payload->parameter == NULL) {
+ return NO_MEMORY;
+ }
+ (*s7_identify_remote_request_packet)->payload->payload->payload->_type =
+ plc4c_s7_read_write_s7_payload_type_plc4c_s7_read_write_s7_payload_user_data;
plc4c_utils_list_create(
&((*s7_identify_remote_request_packet)
->payload->payload->payload->s7_payload_user_data_items));
+ // Create the Payload Item
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 =
@@ -351,6 +366,10 @@ plc4c_return_code plc4c_driver_s7_create_s7_identify_remote_request(
payload_item->szl_id->sublist_extract = 0x00;
payload_item->szl_id->sublist_list =
plc4c_s7_read_write_szl_sublist_MODULE_IDENTIFICATION;
+ plc4c_utils_list_insert_head_value(
+ (*s7_identify_remote_request_packet)
+ ->payload->payload->payload->s7_payload_user_data_items,
+ payload_item);
return OK;
}
diff --git a/sandbox/plc4c/drivers/s7/src/driver_s7_sm_connect.c b/sandbox/plc4c/drivers/s7/src/driver_s7_sm_connect.c
index eb53967..a54c6e8 100644
--- a/sandbox/plc4c/drivers/s7/src/driver_s7_sm_connect.c
+++ b/sandbox/plc4c/drivers/s7/src/driver_s7_sm_connect.c
@@ -30,6 +30,7 @@
enum plc4c_driver_s7_connect_states {
PLC4C_DRIVER_S7_CONNECT_INIT,
+ PLC4C_DRIVER_S7_CONNECT_TRANSPORT_CONNECT,
PLC4C_DRIVER_S7_CONNECT_SEND_COTP_CONNECT_REQUEST,
PLC4C_DRIVER_S7_CONNECT_RECEIVE_COTP_CONNECT_RESPONSE,
PLC4C_DRIVER_S7_CONNECT_SEND_S7_CONNECT_REQUEST,
@@ -75,6 +76,15 @@ plc4c_return_code plc4c_driver_s7_connect_machine_function(
configuration->pdu_size);
configuration->pdu_size = configuration->cotp_tpdu_size - 16;
+ task->state_id = PLC4C_DRIVER_S7_CONNECT_TRANSPORT_CONNECT;
+ break;
+ }
+ case PLC4C_DRIVER_S7_CONNECT_TRANSPORT_CONNECT: {
+ plc4c_return_code return_code = connection->transport->open(connection->transport_configuration);
+ if(return_code != OK) {
+ return return_code;
+ }
+
task->state_id = PLC4C_DRIVER_S7_CONNECT_SEND_COTP_CONNECT_REQUEST;
break;
}
@@ -192,7 +202,7 @@ plc4c_return_code plc4c_driver_s7_connect_machine_function(
return INTERNAL_ERROR;
}
if (s7_connect_response_packet->payload->payload->_type !=
- plc4c_s7_read_write_s7_message_type_plc4c_s7_read_write_s7_message_response) {
+ plc4c_s7_read_write_s7_message_type_plc4c_s7_read_write_s7_message_response_data) {
return INTERNAL_ERROR;
}
if (s7_connect_response_packet->payload->payload->parameter->_type !=
@@ -213,7 +223,7 @@ plc4c_return_code plc4c_driver_s7_connect_machine_function(
->s7_parameter_setup_communication_max_amq_callee;
// If no controller is explicitly selected, detect it.
- if (configuration->controller_type !=
+ if (configuration->controller_type ==
PLC4C_DRIVER_S7_CONTROLLER_TYPE_ANY) {
task->state_id = PLC4C_DRIVER_S7_CONNECT_SEND_S7_IDENTIFICATION_REQUEST;
}
diff --git a/sandbox/plc4c/generated-sources/s7/src/s7_payload_user_data_item.c b/sandbox/plc4c/generated-sources/s7/src/s7_payload_user_data_item.c
index ca75fb1..9ff710a 100644
--- a/sandbox/plc4c/generated-sources/s7/src/s7_payload_user_data_item.c
+++ b/sandbox/plc4c/generated-sources/s7/src/s7_payload_user_data_item.c
@@ -120,7 +120,7 @@ plc4c_return_code plc4c_s7_read_write_s7_payload_user_data_item_parse(plc4c_spi_
}
-
+
// Implicit Field (szlItemCount) (Used for parsing, but it's value is not stored as it's implicitly given by the objects content)
uint16_t szlItemCount = 0;
_res = plc4c_spi_read_unsigned_short(buf, 16, (uint16_t*) &szlItemCount);
@@ -141,7 +141,7 @@ plc4c_return_code plc4c_s7_read_write_s7_payload_user_data_item_parse(plc4c_spi_
uint8_t itemCount = szlItemCount;
for(int curItem = 0; curItem < itemCount; curItem++) {
bool lastItem = curItem == (itemCount - 1);
- plc4c_list* _value = NULL;
+ plc4c_list* _value = NULL;
_res = plc4c_s7_read_write_szl_data_tree_item_parse(buf, (void*) &_value);
if(_res != OK) {
return _res;
diff --git a/sandbox/plc4c/spi/include/plc4c/spi/types_private.h b/sandbox/plc4c/spi/include/plc4c/spi/types_private.h
index af4a762..b2cb006 100644
--- a/sandbox/plc4c/spi/include/plc4c/spi/types_private.h
+++ b/sandbox/plc4c/spi/include/plc4c/spi/types_private.h
@@ -38,6 +38,9 @@ typedef struct plc4c_response_item_t plc4c_response_item;
typedef struct plc4c_response_subscription_item_t plc4c_response_subscription_item;
typedef struct plc4c_response_unsubscription_item_t plc4c_response_unsubscription_item;
+typedef plc4c_return_code *(*plc4c_connection_configure_function)(
+ plc4c_list* parameters, void** configuration);
+
typedef plc4c_item *(*plc4c_connection_parse_address_item)(
char *address_string);
@@ -83,6 +86,9 @@ typedef void (*plc4c_connect_free_subscription_response_function)(
typedef void (*plc4c_connect_free_unsubscription_response_function)(
plc4c_unsubscription_response *response);
+typedef plc4c_return_code (*plc4c_transport_configure_function)(
+ plc4c_list* parameters, void** configuration);
+
// TODO: Implement the argument.
typedef plc4c_return_code (*plc4c_transport_open_function)(void* config);
@@ -90,7 +96,7 @@ typedef plc4c_return_code (*plc4c_transport_open_function)(void* config);
typedef plc4c_return_code (*plc4c_transport_close_function)(void* config);
typedef plc4c_return_code (*plc4c_transport_send_message_function)(
- plc4c_spi_write_buffer* message);
+ void* transport_configuration, plc4c_spi_write_buffer* message);
// Helper function that tells the transport what to do with the current input
// on positive return value: a read-buffer with given number of bytes is
@@ -104,7 +110,7 @@ typedef int16_t (*accept_message_function)(
uint8_t* data, uint16_t length);
typedef plc4c_return_code (*plc4c_transport_select_message_function)(
- accept_message_function accept_message, plc4c_spi_read_buffer** message);
+ void* transport_configuration, uint8_t min_size, accept_message_function accept_message, plc4c_spi_read_buffer** message);
struct plc4c_system_t {
/* drivers */
@@ -137,6 +143,7 @@ struct plc4c_driver_t {
char *protocol_code;
char *protocol_name;
char *default_transport_code;
+ plc4c_connection_configure_function configure_function;
plc4c_connection_parse_address_item parse_address_function;
plc4c_connection_connect_function connect_function;
plc4c_connection_disconnect_function disconnect_function;
@@ -164,6 +171,7 @@ struct plc4c_transport_t {
char *transport_code;
char* transport_name;
+ plc4c_transport_configure_function configure;
plc4c_transport_open_function open;
plc4c_transport_close_function close;
plc4c_transport_send_message_function send_message;
@@ -183,6 +191,7 @@ struct plc4c_connection_t {
char *protocol_code;
char *transport_code;
char *transport_connect_information;
+ void *transport_configuration;
char *parameters;
void *configuration;
diff --git a/sandbox/plc4c/spi/src/connection.c b/sandbox/plc4c/spi/src/connection.c
index f3a1a53..370cefa 100644
--- a/sandbox/plc4c/spi/src/connection.c
+++ b/sandbox/plc4c/spi/src/connection.c
@@ -154,6 +154,11 @@ void plc4c_connection_set_driver(plc4c_connection *connection,
connection->driver = driver;
}
+void plc4c_connection_set_configuration(plc4c_connection *connection,
+ void *configuration) {
+ connection->configuration = configuration;
+}
+
bool plc4c_connection_has_error(plc4c_connection *connection) { return false; }
plc4c_return_code plc4c_connection_disconnect(plc4c_connection *connection) {
diff --git a/sandbox/plc4c/spi/src/system.c b/sandbox/plc4c/spi/src/system.c
index 3d8a147..c4744c4 100644
--- a/sandbox/plc4c/spi/src/system.c
+++ b/sandbox/plc4c/spi/src/system.c
@@ -435,9 +435,22 @@ plc4c_return_code plc4c_system_connect(plc4c_system *system,
// Initialize a new connection task and schedule that.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ plc4c_driver* driver = plc4c_connection_get_driver(new_connection);
+
+ // Configure the driver configuration first.
+ void* configuration = NULL;
+ // TODO: Pass in the configuration options ...
+ driver->configure_function(NULL, &configuration);
+ plc4c_connection_set_configuration(new_connection, configuration);
+
+ // TODO: Somehow let the driver inject default values which the transport can then pickup ...
+
+ // Prepare a configuration data structure for the current transport.
+ new_connection->transport->configure(NULL, &new_connection->transport_configuration);
+
+ // Create a new connection task.
plc4c_system_task *new_connection_task = NULL;
- result = plc4c_connection_get_driver(new_connection)
- ->connect_function(new_connection, &new_connection_task);
+ result = driver->connect_function(new_connection, &new_connection_task);
if (result != OK) {
return -1;
}
diff --git a/sandbox/plc4c/spi/src/utils/list.c b/sandbox/plc4c/spi/src/utils/list.c
index 5d81dbb..f6ceab7 100644
--- a/sandbox/plc4c/spi/src/utils/list.c
+++ b/sandbox/plc4c/spi/src/utils/list.c
@@ -28,7 +28,7 @@ void plc4c_utils_list_create(plc4c_list **list) {
}
size_t plc4c_utils_list_size(plc4c_list *list) {
- if (list->tail == NULL) {
+ if ((list == NULL) || (list->tail == NULL)) {
return 0;
}
plc4c_list_element *cur_element = list->tail;
diff --git a/sandbox/plc4c/transports/serial/src/transport_serial.c b/sandbox/plc4c/transports/serial/src/transport_serial.c
index 38222ef..2b1d073 100644
--- a/sandbox/plc4c/transports/serial/src/transport_serial.c
+++ b/sandbox/plc4c/transports/serial/src/transport_serial.c
@@ -35,7 +35,8 @@ plc4c_return_code plc4c_transport_serial_send_message_function(
}
plc4c_return_code plc4c_transport_serial_select_message_function(
- accept_message_function accept_message, plc4c_spi_read_buffer** message) {
+ void* transport_configuration, accept_message_function accept_message,
+ plc4c_spi_read_buffer** message) {
return OK;
}
diff --git a/sandbox/plc4c/transports/tcp/include/plc4c/transport_tcp.h b/sandbox/plc4c/transports/tcp/include/plc4c/transport_tcp.h
index fb57734..18998b1 100644
--- a/sandbox/plc4c/transports/tcp/include/plc4c/transport_tcp.h
+++ b/sandbox/plc4c/transports/tcp/include/plc4c/transport_tcp.h
@@ -24,6 +24,14 @@ extern "C" {
#include <plc4c/types.h>
+struct plc4c_transport_tcp_config {
+ char* address;
+ uint16_t port;
+
+ int sockfd;
+};
+typedef struct plc4c_transport_tcp_config plc4c_transport_tcp_config;
+
plc4c_transport *plc4c_transport_tcp_create();
#ifdef __cplusplus
diff --git a/sandbox/plc4c/transports/tcp/src/transport_tcp.c b/sandbox/plc4c/transports/tcp/src/transport_tcp.c
index 3d049cc..0bc0a79 100644
--- a/sandbox/plc4c/transports/tcp/src/transport_tcp.c
+++ b/sandbox/plc4c/transports/tcp/src/transport_tcp.c
@@ -20,22 +20,122 @@
#include <plc4c/spi/types_private.h>
#include <plc4c/transport_tcp.h>
#include <stdlib.h>
+#include <stdio.h>
+#include <netdb.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <string.h>
+#include <errno.h>
+
+extern int errno;
+
+plc4c_return_code plc4c_transport_tcp_configure_function(
+ plc4c_list* parameters, void** configuration) {
+ plc4c_transport_tcp_config* tcp_configuration = malloc(sizeof(plc4c_transport_tcp_config));
+ if(tcp_configuration == NULL) {
+ return NO_MEMORY;
+ }
+ // TODO: Implement this ...
+ tcp_configuration->address = "192.168.23.30";
+ tcp_configuration->port = 102;
+
+ *configuration = tcp_configuration;
+ return OK;
+}
plc4c_return_code plc4c_transport_tcp_open_function(void* config) {
+ int sockfd;
+ int connfd;
+ struct sockaddr_in servaddr;
+
+ plc4c_transport_tcp_config* tcp_config = config;
+
+ tcp_config->sockfd = socket(AF_INET, SOCK_STREAM, 0);
+ if (tcp_config->sockfd < 0) {
+ return CONNECTION_ERROR;
+ }
+
+ // Configure where to connect to.
+ bzero(&servaddr, sizeof(struct sockaddr_in));
+ servaddr.sin_family = AF_INET;
+ servaddr.sin_addr.s_addr = inet_addr(tcp_config->address);
+ servaddr.sin_port = htons(tcp_config->port);
+
+ int result = connect(tcp_config->sockfd, (struct sockaddr*) &servaddr,
+ sizeof(servaddr));
+ if(result != 0) {
+ char* error_msg = strerror(errno);
+ printf(error_msg);
+ return CONNECTION_ERROR;
+ }
return OK;
}
plc4c_return_code plc4c_transport_tcp_close_function(void* config) {
+ plc4c_transport_tcp_config* tcp_config = config;
+
+ // If the sockfd is zero we're not really connected.
+ if(tcp_config->sockfd == 0) {
+ return INTERNAL_ERROR;
+ }
+
+ // Stop receiving as well as sending.
+ shutdown(tcp_config->sockfd, 2);
return OK;
}
plc4c_return_code plc4c_transport_tcp_send_message_function(
- plc4c_spi_write_buffer* message) {
+ void* transport_configuration, plc4c_spi_write_buffer* message) {
+ plc4c_transport_tcp_config* tcp_config = transport_configuration;
+
+ ssize_t bytes_sent = send(tcp_config->sockfd, message->data, message->length, MSG_DONTWAIT);
+ if(bytes_sent < 0) {
+ return CONNECTION_ERROR;
+ }
+
return OK;
}
plc4c_return_code plc4c_transport_tcp_select_message_function(
+ void* transport_configuration, uint8_t min_size,
accept_message_function accept_message, plc4c_spi_read_buffer** message) {
+ plc4c_transport_tcp_config* tcp_config = transport_configuration;
+
+ // First try to read the minimum number of bytes the driver needs to know
+ // how big a packet is.
+ uint8_t* size_buffer = malloc(sizeof(uint8_t) * min_size);
+ if(size_buffer == NULL) {
+ return NO_MEMORY;
+ }
+ int received_bytes = recv(tcp_config->sockfd, size_buffer, min_size, 0);
+ // TODO: if the value is negative, it's more a "please remove this much of corrupt data" ...
+ if(received_bytes < 0) {
+ return CONNECTION_ERROR;
+ }
+
+ // Now that we have enough data to find out how many bytes we need, have
+ // the accept_message function find out how many
+ int16_t message_size = accept_message(size_buffer, min_size);
+ if(message_size < 0) {
+ return INTERNAL_ERROR;
+ }
+ uint8_t* message_buffer = malloc(sizeof(uint8_t) * message_size);
+ if(message_size < 0) {
+ return NO_MEMORY;
+ }
+
+ // Copy the size_buffer to the start of the new buffer.
+ memcpy(message_buffer, size_buffer, min_size);
+ free(size_buffer);
+
+ // Read the rest of the packet.
+ received_bytes = recv(tcp_config->sockfd, message_buffer + min_size, message_size - min_size, 0);
+ if(received_bytes != message_size - min_size) {
+ return CONNECTION_ERROR;
+ }
+
+ // Create a new read-buffer with the read message data.
+ plc4c_spi_read_buffer_create(message_buffer, message_size, message);
return OK;
}
@@ -44,6 +144,7 @@ plc4c_transport *plc4c_transport_tcp_create() {
(plc4c_transport *)malloc(sizeof(plc4c_transport));
transport->transport_code = "tcp";
transport->transport_name = "TCP transport";
+ transport->configure = &plc4c_transport_tcp_configure_function;
transport->open = &plc4c_transport_tcp_open_function;
transport->close = &plc4c_transport_tcp_close_function;
transport->send_message = &plc4c_transport_tcp_send_message_function;