Merge branch '84-api-call-for-eoe-set-ip-command' into 'devel-1.6'

API call for EoE Set-IP command

See merge request etherlab.org/ethercat!111
This commit is contained in:
Florian Pose 2024-05-21 13:58:03 +00:00
commit d717cfc1e6
24 changed files with 917 additions and 180 deletions

View File

@ -55,12 +55,28 @@ digraph slaveconf {
enter_sdo_conf [shape=point, label=""]
enter_sdo_conf -> enter_pdo_sync [label="No config\nattached"]
enter_sdo_conf -> enter_pdo_conf [label="No SDOs\nconfigured"]
enter_sdo_conf -> enter_soe_conf_preop [label="No SDOs\nconfigured"]
enter_sdo_conf -> sdo_conf [weight=10]
sdo_conf
sdo_conf -> reconfigure
sdo_conf -> enter_pdo_conf [weight=10]
sdo_conf -> enter_soe_conf_preop [weight=10]
enter_soe_conf_preop [shape=point, label=""]
enter_soe_conf_preop -> enter_pdo_sync [label="No config\nattached"]
enter_soe_conf_preop -> enter_eoe_ip_param [label="No IDNs\nconfigured"]
enter_soe_conf_preop -> soe_conf_preop [weight=10]
soe_conf_preop
soe_conf_preop -> reconfigure
soe_conf_preop -> enter_eoe_ip_param [weight=10]
enter_eoe_ip_param [shape=point, label=""]
enter_eoe_ip_param -> enter_pdo_conf [label="No IP parameters"]
enter_eoe_ip_param -> eoe_ip_param [weight=10]
eoe_ip_param
eoe_ip_param -> enter_pdo_conf [weight=10]
enter_pdo_conf [shape=point, label=""]
enter_pdo_conf -> pdo_conf [weight=10]

View File

@ -43,6 +43,12 @@
* - Added the ecrt_master_scan_progress() method, the
* ec_master_scan_progress_t structure and the EC_HAVE_SCAN_PROGRESS
* definition to check for its existence.
* - Added the EoE configuration methods ecrt_slave_config_eoe_mac_address(),
* ecrt_slave_config_eoe_ip_address(), ecrt_slave_config_eoe_subnet_mask(),
* ecrt_slave_config_eoe_default_gateway(),
* ecrt_slave_config_eoe_dns_address(),
* ecrt_slave_config_eoe_hostname() and the EC_HAVE_SET_IP
* definition to check for its existence.
*
* Changes since version 1.5.2:
*
@ -155,10 +161,12 @@
#include <asm/byteorder.h>
#include <linux/types.h>
#include <linux/time.h>
#include <linux/in.h> // struct in_addr
#else
#include <stdlib.h> // for size_t
#include <stdint.h>
#include <sys/time.h> // for struct timeval
#include <netinet/in.h> // struct in_addr
#endif
/*****************************************************************************
@ -239,6 +247,14 @@
*/
#define EC_HAVE_SCAN_PROGRESS
/** Defined, if the methods ecrt_slave_config_eoe_mac_address(),
* ecrt_slave_config_eoe_ip_address(), ecrt_slave_config_eoe_subnet_mask(),
* ecrt_slave_config_eoe_default_gateway(),
* ecrt_slave_config_eoe_dns_address(), ecrt_slave_config_eoe_hostname() are
* available.
*/
#define EC_HAVE_SET_IP
/****************************************************************************/
/** Symbol visibility control macro.
@ -1846,10 +1862,148 @@ EC_PUBLIC_API int ecrt_slave_config_idn(
*/
EC_PUBLIC_API int ecrt_slave_config_flag(
ec_slave_config_t *sc, /**< Slave configuration. */
const char *key, /**< Key as null-terminated ascii string. */
const char *key, /**< Key as null-terminated ASCII string. */
int32_t value /**< Value to store. */
);
/** Sets the link/MAC address for Ethernet-over-EtherCAT (EoE) operation.
*
* This method has to be called in non-realtime context before
* ecrt_master_activate().
*
* The MAC address is stored in the slave configuration object and will be
* written to the slave during the configuration process.
*
* \retval 0 Success.
* \retval <0 Error code.
*/
EC_PUBLIC_API int ecrt_slave_config_eoe_mac_address(
ec_slave_config_t *sc, /**< Slave configuration. */
const unsigned char *mac_address /**< MAC address. */
);
/** Sets the IP address for Ethernet-over-EtherCAT (EoE) operation.
*
* This method has to be called in non-realtime context before
* ecrt_master_activate().
*
* The IP address is stored in the slave configuration object and will be
* written to the slave during the configuration process.
*
* The IP address is passed by-value as a `struct in_addr`. This structure
* contains the 32-bit IPv4 address in network byte order (big endian).
*
* A string-represented IPv4 address can be converted to a `struct in_addr`
* for example via the POSIX function `inet_pton()` (see man 3 inet_pton):
*
* \code{.c}
* #include <arpa/inet.h>
* struct in_addr addr;
* if (inet_aton("192.168.0.1", &addr) == 0) {
* fprintf(stderr, "Failed to convert IP address.\n");
* return -1;
* }
* if (ecrt_slave_config_eoe_ip_address(sc, addr)) {
* fprintf(stderr, "Failed to set IP address.\n");
* return -1;
* }
* \endcode
*
*
* \retval 0 Success.
* \retval <0 Error code.
*/
EC_PUBLIC_API int ecrt_slave_config_eoe_ip_address(
ec_slave_config_t *sc, /**< Slave configuration. */
struct in_addr ip_address /**< IPv4 address. */
);
/** Sets the subnet mask for Ethernet-over-EtherCAT (EoE) operation.
*
* This method has to be called in non-realtime context before
* ecrt_master_activate().
*
* The subnet mask is stored in the slave configuration object and will be
* written to the slave during the configuration process.
*
* The subnet mask is passed by-value as a `struct in_addr`. This structure
* contains the 32-bit mask in network byte order (big endian).
*
* See ecrt_slave_config_eoe_ip_address() on how to convert string-coded masks
* to `struct in_addr`.
*
* \retval 0 Success.
* \retval <0 Error code.
*/
EC_PUBLIC_API int ecrt_slave_config_eoe_subnet_mask(
ec_slave_config_t *sc, /**< Slave configuration. */
struct in_addr subnet_mask /**< IPv4 subnet mask. */
);
/** Sets the gateway address for Ethernet-over-EtherCAT (EoE) operation.
*
* This method has to be called in non-realtime context before
* ecrt_master_activate().
*
* The gateway address is stored in the slave configuration object and will be
* written to the slave during the configuration process.
*
* The address is passed by-value as a `struct in_addr`. This structure
* contains the 32-bit IPv4 address in network byte order (big endian).
*
* See ecrt_slave_config_eoe_ip_address() on how to convert string-coded IPv4
* addresses to `struct in_addr`.
*
* \retval 0 Success.
* \retval <0 Error code.
*/
EC_PUBLIC_API int ecrt_slave_config_eoe_default_gateway(
ec_slave_config_t *sc, /**< Slave configuration. */
struct in_addr gateway_address /**< Gateway's IPv4 address. */
);
/** Sets the IPv4 address of the DNS server for Ethernet-over-EtherCAT (EoE)
* operation.
*
* This method has to be called in non-realtime context before
* ecrt_master_activate().
*
* The DNS server address is stored in the slave configuration object and will
* be written to the slave during the configuration process.
*
* The address is passed by-value as a `struct in_addr`. This structure
* contains the 32-bit IPv4 address in network byte order (big endian).
*
* See ecrt_slave_config_eoe_ip_address() on how to convert string-coded IPv4
* addresses to `struct in_addr`.
*
* \retval 0 Success.
* \retval <0 Error code.
*/
EC_PUBLIC_API int ecrt_slave_config_eoe_dns_address(
ec_slave_config_t *sc, /**< Slave configuration. */
struct in_addr dns_address /**< IPv4 address of the DNS server. */
);
/** Sets the host name for Ethernet-over-EtherCAT (EoE) operation.
*
* This method has to be called in non-realtime context before
* ecrt_master_activate().
*
* The host name is stored in the slave configuration object and will
* be written to the slave during the configuration process.
*
* The maximum size of the host name is 32 bytes (including the zero
* terminator).
*
* \retval 0 Success.
* \retval <0 Error code.
*/
EC_PUBLIC_API int ecrt_slave_config_eoe_hostname(
ec_slave_config_t *sc, /**< Slave configuration. */
const char *name /**< Zero-terminated host name. */
);
/*****************************************************************************
* Domain methods
****************************************************************************/

View File

@ -44,7 +44,11 @@ noinst_HEADERS = \
soe_request.h \
voe_handler.h
libethercat_la_CFLAGS = -fno-strict-aliasing -Wall -I$(top_srcdir) \
libethercat_la_CFLAGS = \
-fno-strict-aliasing \
-Wall \
-Wmissing-prototypes \
-I$(top_srcdir) \
-Dethercat_EXPORTS \
-fvisibility=hidden

View File

@ -104,4 +104,10 @@ LIBETHERCAT_1.5.3 {
LIBETHERCAT_1.6 {
global:
ecrt_master_scan_progress;
ecrt_slave_config_eoe_mac_address;
ecrt_slave_config_eoe_ip_address;
ecrt_slave_config_eoe_subnet_mask;
ecrt_slave_config_eoe_default_gateway;
ecrt_slave_config_eoe_dns_address;
ecrt_slave_config_eoe_hostname;
} LIBETHERCAT_1.5.3;

View File

@ -34,6 +34,13 @@
/****************************************************************************/
// prototypes for internal methods (avoid -Wmissing-prototype warning)
void ec_master_clear_config(ec_master_t *);
void ec_master_add_domain(ec_master_t *, ec_domain_t *);
void ec_master_add_slave_config(ec_master_t *, ec_slave_config_t *);
/****************************************************************************/
int ecrt_master_reserve(ec_master_t *master)
{
int ret = ioctl(master->fd, EC_IOCTL_REQUEST, NULL);

View File

@ -1,6 +1,6 @@
/*****************************************************************************
*
* Copyright (C) 2006-2019 Florian Pose, Ingenieurgemeinschaft IgH
* Copyright (C) 2006-2024 Florian Pose, Ingenieurgemeinschaft IgH
*
* This file is part of the IgH EtherCAT master userspace library.
*
@ -36,6 +36,13 @@
/****************************************************************************/
// prototypes for internal methods (avoid -Wmissing-prototype warning)
void ec_slave_config_add_sdo_request(ec_slave_config_t *, ec_sdo_request_t *);
void ec_slave_config_add_reg_request(ec_slave_config_t *, ec_reg_request_t *);
void ec_slave_config_add_voe_handler(ec_slave_config_t *, ec_voe_handler_t *);
/****************************************************************************/
void ec_slave_config_clear(ec_slave_config_t *sc)
{
ec_sdo_request_t *r, *next_r;
@ -618,7 +625,7 @@ ec_sdo_request_t *ecrt_slave_config_create_sdo_request(ec_slave_config_t *sc,
/****************************************************************************/
void ec_slave_config_add_soe_request(ec_slave_config_t *sc,
inline void ec_slave_config_add_soe_request(ec_slave_config_t *sc,
ec_soe_request_t *req)
{
if (sc->first_soe_request) {
@ -895,3 +902,139 @@ int ecrt_slave_config_flag(ec_slave_config_t *sc, const char *key,
}
/****************************************************************************/
#ifdef EC_EOE
int ecrt_slave_config_eoe_mac_address(ec_slave_config_t *sc,
const unsigned char *mac_address)
{
ec_ioctl_eoe_ip_t io = {};
int ret;
io.config_index = sc->index;
memcpy(io.mac_address, mac_address, EC_ETH_ALEN);
io.mac_address_included = 1;
ret = ioctl(sc->master->fd, EC_IOCTL_SC_EOE_IP_PARAM, &io);
if (EC_IOCTL_IS_ERROR(ret)) {
fprintf(stderr, "Failed to configure EoE MAC address: %s\n",
strerror(EC_IOCTL_ERRNO(ret)));
return -EC_IOCTL_ERRNO(ret);
}
return 0;
}
/****************************************************************************/
int ecrt_slave_config_eoe_ip_address(ec_slave_config_t *sc,
struct in_addr ip_address)
{
ec_ioctl_eoe_ip_t io = {};
int ret;
io.config_index = sc->index;
io.ip_address = ip_address;
io.ip_address_included = 1;
ret = ioctl(sc->master->fd, EC_IOCTL_SC_EOE_IP_PARAM, &io);
if (EC_IOCTL_IS_ERROR(ret)) {
fprintf(stderr, "Failed to configure EoE IP address: %s\n",
strerror(EC_IOCTL_ERRNO(ret)));
return -EC_IOCTL_ERRNO(ret);
}
return 0;
}
/****************************************************************************/
int ecrt_slave_config_eoe_subnet_mask(ec_slave_config_t *sc,
struct in_addr subnet_mask)
{
ec_ioctl_eoe_ip_t io = {};
int ret;
io.config_index = sc->index;
io.subnet_mask = subnet_mask;
io.subnet_mask_included = 1;
ret = ioctl(sc->master->fd, EC_IOCTL_SC_EOE_IP_PARAM, &io);
if (EC_IOCTL_IS_ERROR(ret)) {
fprintf(stderr, "Failed to configure EoE subnet mask: %s\n",
strerror(EC_IOCTL_ERRNO(ret)));
return -EC_IOCTL_ERRNO(ret);
}
return 0;
}
/****************************************************************************/
int ecrt_slave_config_eoe_default_gateway(ec_slave_config_t *sc,
struct in_addr gateway_address)
{
ec_ioctl_eoe_ip_t io = {};
int ret;
io.config_index = sc->index;
io.gateway = gateway_address;
io.gateway_included = 1;
ret = ioctl(sc->master->fd, EC_IOCTL_SC_EOE_IP_PARAM, &io);
if (EC_IOCTL_IS_ERROR(ret)) {
fprintf(stderr, "Failed to configure EoE default gateway: %s\n",
strerror(EC_IOCTL_ERRNO(ret)));
return -EC_IOCTL_ERRNO(ret);
}
return 0;
}
/****************************************************************************/
int ecrt_slave_config_eoe_dns_address(ec_slave_config_t *sc,
struct in_addr dns_address)
{
ec_ioctl_eoe_ip_t io = {};
int ret;
io.config_index = sc->index;
io.dns = dns_address;
io.dns_included = 1;
ret = ioctl(sc->master->fd, EC_IOCTL_SC_EOE_IP_PARAM, &io);
if (EC_IOCTL_IS_ERROR(ret)) {
fprintf(stderr, "Failed to configure EoE DNS address: %s\n",
strerror(EC_IOCTL_ERRNO(ret)));
return -EC_IOCTL_ERRNO(ret);
}
return 0;
}
/****************************************************************************/
int ecrt_slave_config_eoe_hostname(ec_slave_config_t *sc,
const char *name)
{
ec_ioctl_eoe_ip_t io = {};
int ret;
io.config_index = sc->index;
strncpy(io.name, (const char *) name, EC_MAX_HOSTNAME_SIZE - 1);
io.name_included = 1;
ret = ioctl(sc->master->fd, EC_IOCTL_SC_EOE_IP_PARAM, &io);
if (EC_IOCTL_IS_ERROR(ret)) {
fprintf(stderr, "Failed to configure EoE hostname: %s\n",
strerror(EC_IOCTL_ERRNO(ret)));
return -EC_IOCTL_ERRNO(ret);
}
return 0;
}
#endif // EC_EOE
/****************************************************************************/

View File

@ -1,6 +1,6 @@
/*****************************************************************************
*
* Copyright (C) 2006-2014 Florian Pose, Ingenieurgemeinschaft IgH
* Copyright (C) 2006-2024 Florian Pose, Ingenieurgemeinschaft IgH
*
* This file is part of the IgH EtherCAT Master.
*
@ -51,13 +51,30 @@ void ec_eoe_request_init(
req->name_included = 0;
memset(req->mac_address, 0x00, ETH_ALEN);
req->ip_address = 0;
req->subnet_mask = 0;
req->gateway = 0;
req->dns = 0;
req->ip_address.s_addr = 0;
req->subnet_mask.s_addr = 0;
req->gateway.s_addr = 0;
req->dns.s_addr = 0;
req->name[0] = 0x00;
req->result = 0x0000;
}
/****************************************************************************/
/** Checks if EoE request has something to set.
*/
int ec_eoe_request_valid(
const ec_eoe_request_t *req /**< EoE request. */
)
{
return
req->mac_address_included ||
req->ip_address_included ||
req->subnet_mask_included ||
req->gateway_included ||
req->dns_included ||
req->name_included;
}
/****************************************************************************/

View File

@ -51,10 +51,10 @@ typedef struct {
uint8_t name_included;
unsigned char mac_address[ETH_ALEN];
uint32_t ip_address;
uint32_t subnet_mask;
uint32_t gateway;
uint32_t dns;
struct in_addr ip_address;
struct in_addr subnet_mask;
struct in_addr gateway;
struct in_addr dns;
char name[EC_MAX_HOSTNAME_SIZE];
uint16_t result;
@ -63,6 +63,7 @@ typedef struct {
/****************************************************************************/
void ec_eoe_request_init(ec_eoe_request_t *);
int ec_eoe_request_valid(const ec_eoe_request_t *);
/****************************************************************************/

View File

@ -1,6 +1,6 @@
/*****************************************************************************
*
* Copyright (C) 2006-2008 Florian Pose, Ingenieurgemeinschaft IgH
* Copyright (C) 2006-2024 Florian Pose, Ingenieurgemeinschaft IgH
*
* This file is part of the IgH EtherCAT Master.
*
@ -48,6 +48,7 @@
# define SUSE_PATCHLEVEL 0
# endif
#endif
/****************************************************************************/
/** Defines the debug level of EoE processing.
@ -526,7 +527,7 @@ void ec_eoe_state_rx_fetch(ec_eoe_t *eoe /**< EoE handler */)
#if EOE_DEBUG_LEVEL >= 2
EC_SLAVE_DBG(eoe->slave, 0, "EoE %s RX fragment %u%s, offset %u,"
" frame %u%s, %u octets\n", eoe->dev->name, fragment_number,
" frame %u%s, %zu octets\n", eoe->dev->name, fragment_number,
last_fragment ? "" : "+", fragment_offset, frame_number,
time_appended ? ", + timestamp" : "",
time_appended ? rec_size - 8 : rec_size - 4);

View File

@ -33,6 +33,24 @@
/****************************************************************************/
/** Host-architecture-independent 32-bit swap function.
*
* The internal storage of struct in_addr is always big-endian.
* The mailbox protocol format to supply IPv4 adresses is little-endian
* (Yuck!). So we need a swap function, that is independent of the CPU
* architecture. ntohl()/htonl() can not be used, because they evaluate to
* NOPs if the host architecture matches the target architecture!
*/
void memcpy_swap32(void *dst, const void *src)
{
int i;
for (i = 0; i < 4; i++) {
((u8 *) dst)[i] = ((const u8 *) src)[3 - i];
}
}
/****************************************************************************/
/** Maximum time to wait for a set IP parameter response.
*/
#define EC_EOE_RESPONSE_TIMEOUT 3000 // [ms]
@ -61,6 +79,7 @@ void ec_fsm_eoe_init(
fsm->datagram = NULL;
fsm->jiffies_start = 0;
fsm->request = NULL;
fsm->frame_type_retries = 0;
}
/****************************************************************************/
@ -197,26 +216,22 @@ int ec_fsm_eoe_prepare_set(
cur += ETH_ALEN;
if (req->ip_address_included) {
uint32_t swapped = htonl(req->ip_address);
memcpy(cur, &swapped, 4);
memcpy_swap32(cur, &req->ip_address);
}
cur += 4;
if (req->subnet_mask_included) {
uint32_t swapped = htonl(req->subnet_mask);
memcpy(cur, &swapped, 4);
memcpy_swap32(cur, &req->subnet_mask);
}
cur += 4;
if (req->gateway_included) {
uint32_t swapped = htonl(req->gateway);
memcpy(cur, &swapped, 4);
memcpy_swap32(cur, &req->gateway);
}
cur += 4;
if (req->dns_included) {
uint32_t swapped = htonl(req->dns);
memcpy(cur, &swapped, 4);
memcpy_swap32(cur, &req->dns);
}
cur += 4;
@ -313,6 +328,7 @@ void ec_fsm_eoe_set_ip_request(
ec_slave_mbox_prepare_check(slave, datagram); // can not fail.
fsm->retries = EC_FSM_RETRIES;
fsm->state = ec_fsm_eoe_set_ip_check;
fsm->frame_type_retries = 10;
}
/****************************************************************************/
@ -431,14 +447,28 @@ void ec_fsm_eoe_set_ip_response(
frame_type = EC_READ_U8(data) & 0x0f;
if (frame_type != EC_EOE_FRAMETYPE_SET_IP_RES) {
EC_SLAVE_ERR(slave, "Received no set IP parameter response"
" (frame type %x).\n", frame_type);
ec_print_data(data, rec_size);
fsm->state = ec_fsm_eoe_error;
return;
if (master->debug_level) {
EC_SLAVE_DBG(slave, 0, "Received no set IP parameter response"
" (frame type %x).\n", frame_type);
ec_print_data(data, rec_size);
}
if (fsm->frame_type_retries--) {
// there may be an EoE segment left in the mailbox.
// discard it and receive again.
fsm->jiffies_start = fsm->datagram->jiffies_sent;
ec_slave_mbox_prepare_check(slave, datagram); // can not fail.
fsm->retries = EC_FSM_RETRIES;
fsm->state = ec_fsm_eoe_set_ip_check;
return;
}
else {
EC_SLAVE_ERR(slave, "Received no set IP parameter response.\n");
fsm->state = ec_fsm_eoe_error;
return;
}
}
req->result = EC_READ_U16(data + 2);
req->result = EC_READ_U16(data + 2); // result code 0x0000 means success
if (req->result) {
fsm->state = ec_fsm_eoe_error;

View File

@ -48,6 +48,7 @@ struct ec_fsm_eoe {
ec_datagram_t *datagram; /**< Datagram used in the previous step. */
unsigned long jiffies_start; /**< Timestamp. */
ec_eoe_request_t *request; /**< EoE request */
unsigned int frame_type_retries; /**< retries upon wrong frame type. */
};
/****************************************************************************/

View File

@ -92,9 +92,11 @@ void ec_fsm_master_init(
ec_fsm_coe_init(&fsm->fsm_coe);
ec_fsm_soe_init(&fsm->fsm_soe);
ec_fsm_pdo_init(&fsm->fsm_pdo, &fsm->fsm_coe);
ec_fsm_eoe_init(&fsm->fsm_eoe);
ec_fsm_change_init(&fsm->fsm_change, fsm->datagram);
ec_fsm_slave_config_init(&fsm->fsm_slave_config, fsm->datagram,
&fsm->fsm_change, &fsm->fsm_coe, &fsm->fsm_soe, &fsm->fsm_pdo);
&fsm->fsm_change, &fsm->fsm_coe, &fsm->fsm_soe, &fsm->fsm_pdo,
&fsm->fsm_eoe);
ec_fsm_slave_scan_init(&fsm->fsm_slave_scan, fsm->datagram,
&fsm->fsm_slave_config, &fsm->fsm_pdo);
ec_fsm_sii_init(&fsm->fsm_sii, fsm->datagram);
@ -112,6 +114,7 @@ void ec_fsm_master_clear(
ec_fsm_coe_clear(&fsm->fsm_coe);
ec_fsm_soe_clear(&fsm->fsm_soe);
ec_fsm_pdo_clear(&fsm->fsm_pdo);
ec_fsm_eoe_clear(&fsm->fsm_eoe);
ec_fsm_change_clear(&fsm->fsm_change);
ec_fsm_slave_config_clear(&fsm->fsm_slave_config);
ec_fsm_slave_scan_clear(&fsm->fsm_slave_scan);

View File

@ -85,6 +85,7 @@ struct ec_fsm_master {
ec_fsm_coe_t fsm_coe; /**< CoE state machine */
ec_fsm_soe_t fsm_soe; /**< SoE state machine */
ec_fsm_pdo_t fsm_pdo; /**< PDO configuration state machine. */
ec_fsm_eoe_t fsm_eoe; /**< EoE state machine */
ec_fsm_change_t fsm_change; /**< State change state machine */
ec_fsm_slave_config_t fsm_slave_config; /**< slave state machine */
ec_fsm_slave_scan_t fsm_slave_scan; /**< slave state machine */

View File

@ -1,6 +1,6 @@
/*****************************************************************************
*
* Copyright (C) 2006-2023 Florian Pose, Ingenieurgemeinschaft IgH
* Copyright (C) 2006-2024 Florian Pose, Ingenieurgemeinschaft IgH
*
* This file is part of the IgH EtherCAT Master.
*
@ -67,6 +67,7 @@ void ec_fsm_slave_config_state_assign_ethercat(ec_fsm_slave_config_t *);
#endif
void ec_fsm_slave_config_state_sdo_conf(ec_fsm_slave_config_t *);
void ec_fsm_slave_config_state_soe_conf_preop(ec_fsm_slave_config_t *);
void ec_fsm_slave_config_state_eoe_ip_param(ec_fsm_slave_config_t *);
void ec_fsm_slave_config_state_watchdog_divider(ec_fsm_slave_config_t *);
void ec_fsm_slave_config_state_watchdog(ec_fsm_slave_config_t *);
void ec_fsm_slave_config_state_pdo_sync(ec_fsm_slave_config_t *);
@ -91,6 +92,7 @@ void ec_fsm_slave_config_enter_assign_pdi(ec_fsm_slave_config_t *);
void ec_fsm_slave_config_enter_boot_preop(ec_fsm_slave_config_t *);
void ec_fsm_slave_config_enter_sdo_conf(ec_fsm_slave_config_t *);
void ec_fsm_slave_config_enter_soe_conf_preop(ec_fsm_slave_config_t *);
void ec_fsm_slave_config_enter_eoe_ip_param(ec_fsm_slave_config_t *);
void ec_fsm_slave_config_enter_pdo_conf(ec_fsm_slave_config_t *);
void ec_fsm_slave_config_enter_watchdog_divider(ec_fsm_slave_config_t *);
void ec_fsm_slave_config_enter_watchdog(ec_fsm_slave_config_t *);
@ -117,7 +119,8 @@ void ec_fsm_slave_config_init(
ec_fsm_change_t *fsm_change, /**< State change state machine to use. */
ec_fsm_coe_t *fsm_coe, /**< CoE state machine to use. */
ec_fsm_soe_t *fsm_soe, /**< SoE state machine to use. */
ec_fsm_pdo_t *fsm_pdo /**< PDO configuration state machine to use. */
ec_fsm_pdo_t *fsm_pdo, /**< PDO configuration state machine to use. */
ec_fsm_eoe_t *fsm_eoe /**< EoE state machine to use. */
)
{
ec_sdo_request_init(&fsm->request_copy);
@ -128,6 +131,7 @@ void ec_fsm_slave_config_init(
fsm->fsm_coe = fsm_coe;
fsm->fsm_soe = fsm_soe;
fsm->fsm_pdo = fsm_pdo;
fsm->fsm_eoe = fsm_eoe;
fsm->wait_ms = 0;
}
@ -901,7 +905,7 @@ void ec_fsm_slave_config_enter_soe_conf_preop(
}
// No SoE configuration to be applied in PREOP
ec_fsm_slave_config_enter_pdo_conf(fsm);
ec_fsm_slave_config_enter_eoe_ip_param(fsm);
}
/****************************************************************************/
@ -945,6 +949,56 @@ void ec_fsm_slave_config_state_soe_conf_preop(
}
// All PREOP IDNs are now configured.
ec_fsm_slave_config_enter_eoe_ip_param(fsm);
}
/****************************************************************************/
/** EOE_IP_PARAM entry function.
*/
void ec_fsm_slave_config_enter_eoe_ip_param(
ec_fsm_slave_config_t *fsm /**< slave state machine */
)
{
#if EC_EOE
ec_slave_t *slave = fsm->slave;
ec_eoe_request_t *request = &slave->config->eoe_ip_param_request;
if (ec_eoe_request_valid(request)) {
EC_SLAVE_DBG(slave, 1, "Setting EoE IP parameters...\n");
// Start EoE command
fsm->state = ec_fsm_slave_config_state_eoe_ip_param;
ec_fsm_eoe_set_ip_param(fsm->fsm_eoe, slave, request);
ec_fsm_eoe_exec(fsm->fsm_eoe, fsm->datagram); // execute immediately
return;
}
#endif
ec_fsm_slave_config_enter_pdo_conf(fsm);
}
/****************************************************************************/
/** Slave configuration state: EOE_IP_PARAM.
*/
void ec_fsm_slave_config_state_eoe_ip_param(
ec_fsm_slave_config_t *fsm /**< slave state machine */
)
{
ec_slave_t *slave = fsm->slave;
if (ec_fsm_eoe_exec(fsm->fsm_eoe, fsm->datagram)) {
return;
}
if (ec_fsm_eoe_success(fsm->fsm_eoe)) {
EC_SLAVE_DBG(slave, 1, "Finished setting EoE IP parameters.\n");
}
else {
EC_SLAVE_ERR(slave, "Failed to set EoE IP parameters.\n");
}
ec_fsm_slave_config_enter_pdo_conf(fsm);
}

View File

@ -1,6 +1,6 @@
/*****************************************************************************
*
* Copyright (C) 2006-2023 Florian Pose, Ingenieurgemeinschaft IgH
* Copyright (C) 2006-2024 Florian Pose, Ingenieurgemeinschaft IgH
*
* This file is part of the IgH EtherCAT Master.
*
@ -34,6 +34,7 @@
#include "fsm_change.h"
#include "fsm_coe.h"
#include "fsm_pdo.h"
#include "fsm_eoe.h"
/****************************************************************************/
@ -49,6 +50,7 @@ struct ec_fsm_slave_config
ec_fsm_coe_t *fsm_coe; /**< CoE state machine. */
ec_fsm_soe_t *fsm_soe; /**< SoE state machine. */
ec_fsm_pdo_t *fsm_pdo; /**< PDO configuration state machine. */
ec_fsm_eoe_t *fsm_eoe; /**< EoE state machine. */
ec_slave_t *slave; /**< Slave the FSM runs on. */
void (*state)(ec_fsm_slave_config_t *); /**< State function. */
@ -65,7 +67,8 @@ struct ec_fsm_slave_config
/****************************************************************************/
void ec_fsm_slave_config_init(ec_fsm_slave_config_t *, ec_datagram_t *,
ec_fsm_change_t *, ec_fsm_coe_t *, ec_fsm_soe_t *, ec_fsm_pdo_t *);
ec_fsm_change_t *, ec_fsm_coe_t *, ec_fsm_soe_t *, ec_fsm_pdo_t *,
ec_fsm_eoe_t *);
void ec_fsm_slave_config_clear(ec_fsm_slave_config_t *);
void ec_fsm_slave_config_start(ec_fsm_slave_config_t *, ec_slave_t *);

View File

@ -1584,6 +1584,74 @@ static ATTRIBUTES int ec_ioctl_config_flag(
#ifdef EC_EOE
/** Get configured EoE IP parameters for a given slave configuration.
*
* \return Zero on success, otherwise a negative error code.
*/
static ATTRIBUTES int ec_ioctl_config_ip(
ec_master_t *master, /**< EtherCAT master. */
void *arg /**< ioctl() argument. */
)
{
ec_ioctl_eoe_ip_t *ioctl;
const ec_slave_config_t *sc;
const ec_eoe_request_t *req;
if (!(ioctl = kmalloc(sizeof(*ioctl), GFP_KERNEL))) {
return -ENOMEM;
}
if (copy_from_user(ioctl, (void __user *) arg, sizeof(*ioctl))) {
kfree(ioctl);
return -EFAULT;
}
if (down_interruptible(&master->master_sem)) {
kfree(ioctl);
return -EINTR;
}
if (!(sc = ec_master_get_config_const(master, ioctl->config_index))) {
up(&master->master_sem);
EC_MASTER_ERR(master, "Slave config %u does not exist!\n",
ioctl->config_index);
kfree(ioctl);
return -EINVAL;
}
req = &sc->eoe_ip_param_request;
ioctl->mac_address_included = req->mac_address_included;
ioctl->ip_address_included = req->ip_address_included;
ioctl->subnet_mask_included = req->subnet_mask_included;
ioctl->gateway_included = req->gateway_included;
ioctl->dns_included = req->dns_included;
ioctl->name_included = req->name_included;
memcpy(ioctl->mac_address, req->mac_address, EC_ETH_ALEN);
ioctl->ip_address = req->ip_address;
ioctl->subnet_mask = req->subnet_mask;
ioctl->gateway = req->gateway;
ioctl->dns = req->dns;
strncpy(ioctl->name, req->name, EC_MAX_HOSTNAME_SIZE);
up(&master->master_sem);
if (copy_to_user((void __user *) arg, ioctl, sizeof(*ioctl))) {
kfree(ioctl);
return -EFAULT;
}
kfree(ioctl);
return 0;
}
#endif
/****************************************************************************/
#ifdef EC_EOE
/** Get EoE handler information.
*
* \return Zero on success, otherwise a negative error code.
@ -1646,7 +1714,7 @@ static ATTRIBUTES int ec_ioctl_slave_eoe_ip_param(
void *arg /**< ioctl() argument. */
)
{
ec_ioctl_slave_eoe_ip_t io;
ec_ioctl_eoe_ip_t io;
ec_eoe_request_t req;
ec_slave_t *slave;
@ -1664,7 +1732,7 @@ static ATTRIBUTES int ec_ioctl_slave_eoe_ip_param(
req.dns_included = io.dns_included;
req.name_included = io.name_included;
memcpy(req.mac_address, io.mac_address, ETH_ALEN);
memcpy(req.mac_address, io.mac_address, EC_ETH_ALEN);
req.ip_address = io.ip_address;
req.subnet_mask = io.subnet_mask;
req.gateway = io.gateway;
@ -3264,6 +3332,70 @@ static ATTRIBUTES int ec_ioctl_sc_flag(
/****************************************************************************/
#ifdef EC_EOE
/** Configures EoE IP parameters.
*
* \return Zero on success, otherwise a negative error code.
*/
static ATTRIBUTES int ec_ioctl_sc_ip(
ec_master_t *master, /**< EtherCAT master. */
void *arg, /**< ioctl() argument. */
ec_ioctl_context_t *ctx /**< Private data structure of file handle. */
)
{
ec_ioctl_eoe_ip_t io;
ec_slave_config_t *sc;
uint8_t *key;
if (unlikely(!ctx->requested)) {
return -EPERM;
}
if (copy_from_user(&io, (void __user *) arg, sizeof(io))) {
return -EFAULT;
}
if (down_interruptible(&master->master_sem)) {
kfree(key);
return -EINTR;
}
if (!(sc = ec_master_get_config(master, io.config_index))) {
up(&master->master_sem);
kfree(key);
return -ENOENT;
}
up(&master->master_sem); /** \todo sc could be invalidated */
/* the kernel versions of the EoE set IP methods never fail. */
if (io.mac_address_included) {
ecrt_slave_config_eoe_mac_address(sc, io.mac_address);
}
if (io.ip_address_included) {
ecrt_slave_config_eoe_ip_address(sc, io.ip_address);
}
if (io.subnet_mask_included) {
ecrt_slave_config_eoe_subnet_mask(sc, io.subnet_mask);
}
if (io.gateway_included) {
ecrt_slave_config_eoe_default_gateway(sc, io.gateway);
}
if (io.dns_included) {
ecrt_slave_config_eoe_dns_address(sc, io.dns);
}
if (io.name_included) {
ecrt_slave_config_eoe_hostname(sc, io.name);
}
return 0;
}
#endif
/****************************************************************************/
/** Gets the domain's data size.
*
* \return Domain size, or a negative error code.
@ -5190,6 +5322,9 @@ static long ec_ioctl_nrt
ret = ec_ioctl_config_flag(master, arg);
break;
#ifdef EC_EOE
case EC_IOCTL_CONFIG_EOE_IP_PARAM:
ret = ec_ioctl_config_ip(master, arg);
break;
case EC_IOCTL_EOE_HANDLER:
ret = ec_ioctl_eoe_handler(master, arg);
break;
@ -5358,6 +5493,15 @@ static long ec_ioctl_nrt
}
ret = ec_ioctl_sc_flag(master, arg, ctx);
break;
#ifdef EC_EOE
case EC_IOCTL_SC_EOE_IP_PARAM:
if (!ctx->writable) {
ret = -EPERM;
break;
}
ret = ec_ioctl_sc_ip(master, arg, ctx);
break;
#endif
case EC_IOCTL_DOMAIN_SIZE:
ret = ec_ioctl_domain_size(master, arg, ctx);
break;

View File

@ -1,6 +1,6 @@
/*****************************************************************************
*
* Copyright (C) 2006-2021 Florian Pose, Ingenieurgemeinschaft IgH
* Copyright (C) 2006-2024 Florian Pose, Ingenieurgemeinschaft IgH
*
* This file is part of the IgH EtherCAT master.
*
@ -47,7 +47,7 @@
*
* Increment this when changing the ioctl interface!
*/
#define EC_IOCTL_VERSION_MAGIC 35
#define EC_IOCTL_VERSION_MAGIC 36
// Command-line tool
#define EC_IOCTL_MODULE EC_IOR(0x00, ec_ioctl_module_t)
@ -75,7 +75,7 @@
#define EC_IOCTL_SLAVE_SOE_READ EC_IOWR(0x16, ec_ioctl_slave_soe_read_t)
#define EC_IOCTL_SLAVE_SOE_WRITE EC_IOWR(0x17, ec_ioctl_slave_soe_write_t)
#ifdef EC_EOE
#define EC_IOCTL_SLAVE_EOE_IP_PARAM EC_IOW(0x18, ec_ioctl_slave_eoe_ip_t)
#define EC_IOCTL_SLAVE_EOE_IP_PARAM EC_IOW(0x18, ec_ioctl_eoe_ip_t)
#endif
#define EC_IOCTL_CONFIG EC_IOWR(0x19, ec_ioctl_config_t)
#define EC_IOCTL_CONFIG_PDO EC_IOWR(0x1a, ec_ioctl_config_pdo_t)
@ -84,78 +84,82 @@
#define EC_IOCTL_CONFIG_IDN EC_IOWR(0x1d, ec_ioctl_config_idn_t)
#define EC_IOCTL_CONFIG_FLAG EC_IOWR(0x1e, ec_ioctl_config_flag_t)
#ifdef EC_EOE
#define EC_IOCTL_EOE_HANDLER EC_IOWR(0x1f, ec_ioctl_eoe_handler_t)
#define EC_IOCTL_CONFIG_EOE_IP_PARAM EC_IOWR(0x1f, ec_ioctl_eoe_ip_t)
#define EC_IOCTL_EOE_HANDLER EC_IOWR(0x20, ec_ioctl_eoe_handler_t)
#endif
// Application interface
#define EC_IOCTL_REQUEST EC_IO(0x20)
#define EC_IOCTL_CREATE_DOMAIN EC_IO(0x21)
#define EC_IOCTL_CREATE_SLAVE_CONFIG EC_IOWR(0x22, ec_ioctl_config_t)
#define EC_IOCTL_SELECT_REF_CLOCK EC_IOW(0x23, uint32_t)
#define EC_IOCTL_ACTIVATE EC_IOR(0x24, ec_ioctl_master_activate_t)
#define EC_IOCTL_DEACTIVATE EC_IO(0x25)
#define EC_IOCTL_SEND EC_IO(0x26)
#define EC_IOCTL_RECEIVE EC_IO(0x27)
#define EC_IOCTL_MASTER_STATE EC_IOR(0x28, ec_master_state_t)
#define EC_IOCTL_MASTER_LINK_STATE EC_IOWR(0x29, ec_ioctl_link_state_t)
#define EC_IOCTL_APP_TIME EC_IOW(0x2a, uint64_t)
#define EC_IOCTL_SYNC_REF EC_IO(0x2b)
#define EC_IOCTL_SYNC_REF_TO EC_IOW(0x2c, uint64_t)
#define EC_IOCTL_SYNC_SLAVES EC_IO(0x2d)
#define EC_IOCTL_REF_CLOCK_TIME EC_IOR(0x2e, uint32_t)
#define EC_IOCTL_SYNC_MON_QUEUE EC_IO(0x2f)
#define EC_IOCTL_SYNC_MON_PROCESS EC_IOR(0x30, uint32_t)
#define EC_IOCTL_RESET EC_IO(0x31)
#define EC_IOCTL_SC_SYNC EC_IOW(0x32, ec_ioctl_config_t)
#define EC_IOCTL_SC_WATCHDOG EC_IOW(0x33, ec_ioctl_config_t)
#define EC_IOCTL_SC_ADD_PDO EC_IOW(0x34, ec_ioctl_config_pdo_t)
#define EC_IOCTL_SC_CLEAR_PDOS EC_IOW(0x35, ec_ioctl_config_pdo_t)
#define EC_IOCTL_SC_ADD_ENTRY EC_IOW(0x36, ec_ioctl_add_pdo_entry_t)
#define EC_IOCTL_SC_CLEAR_ENTRIES EC_IOW(0x37, ec_ioctl_config_pdo_t)
#define EC_IOCTL_SC_REG_PDO_ENTRY EC_IOWR(0x38, ec_ioctl_reg_pdo_entry_t)
#define EC_IOCTL_SC_REG_PDO_POS EC_IOWR(0x39, ec_ioctl_reg_pdo_pos_t)
#define EC_IOCTL_SC_DC EC_IOW(0x3a, ec_ioctl_config_t)
#define EC_IOCTL_SC_SDO EC_IOW(0x3b, ec_ioctl_sc_sdo_t)
#define EC_IOCTL_SC_EMERG_SIZE EC_IOW(0x3c, ec_ioctl_sc_emerg_t)
#define EC_IOCTL_SC_EMERG_POP EC_IOWR(0x3d, ec_ioctl_sc_emerg_t)
#define EC_IOCTL_SC_EMERG_CLEAR EC_IOW(0x3e, ec_ioctl_sc_emerg_t)
#define EC_IOCTL_SC_EMERG_OVERRUNS EC_IOWR(0x3f, ec_ioctl_sc_emerg_t)
#define EC_IOCTL_SC_SDO_REQUEST EC_IOWR(0x40, ec_ioctl_sdo_request_t)
#define EC_IOCTL_SC_SOE_REQUEST EC_IOWR(0x41, ec_ioctl_soe_request_t)
#define EC_IOCTL_SC_REG_REQUEST EC_IOWR(0x42, ec_ioctl_reg_request_t)
#define EC_IOCTL_SC_VOE EC_IOWR(0x43, ec_ioctl_voe_t)
#define EC_IOCTL_SC_STATE EC_IOWR(0x44, ec_ioctl_sc_state_t)
#define EC_IOCTL_SC_IDN EC_IOW(0x45, ec_ioctl_sc_idn_t)
#define EC_IOCTL_SC_FLAG EC_IOW(0x46, ec_ioctl_sc_flag_t)
#define EC_IOCTL_DOMAIN_SIZE EC_IO(0x47)
#define EC_IOCTL_DOMAIN_OFFSET EC_IO(0x48)
#define EC_IOCTL_DOMAIN_PROCESS EC_IO(0x49)
#define EC_IOCTL_DOMAIN_QUEUE EC_IO(0x4a)
#define EC_IOCTL_DOMAIN_STATE EC_IOWR(0x4b, ec_ioctl_domain_state_t)
#define EC_IOCTL_SDO_REQUEST_INDEX EC_IOWR(0x4c, ec_ioctl_sdo_request_t)
#define EC_IOCTL_SDO_REQUEST_TIMEOUT EC_IOWR(0x4d, ec_ioctl_sdo_request_t)
#define EC_IOCTL_SDO_REQUEST_STATE EC_IOWR(0x4e, ec_ioctl_sdo_request_t)
#define EC_IOCTL_SDO_REQUEST_READ EC_IOWR(0x4f, ec_ioctl_sdo_request_t)
#define EC_IOCTL_SDO_REQUEST_WRITE EC_IOWR(0x50, ec_ioctl_sdo_request_t)
#define EC_IOCTL_SDO_REQUEST_DATA EC_IOWR(0x51, ec_ioctl_sdo_request_t)
#define EC_IOCTL_SOE_REQUEST_IDN EC_IOWR(0x52, ec_ioctl_soe_request_t)
#define EC_IOCTL_SOE_REQUEST_TIMEOUT EC_IOWR(0x53, ec_ioctl_soe_request_t)
#define EC_IOCTL_SOE_REQUEST_STATE EC_IOWR(0x54, ec_ioctl_soe_request_t)
#define EC_IOCTL_SOE_REQUEST_READ EC_IOWR(0x55, ec_ioctl_soe_request_t)
#define EC_IOCTL_SOE_REQUEST_WRITE EC_IOWR(0x56, ec_ioctl_soe_request_t)
#define EC_IOCTL_SOE_REQUEST_DATA EC_IOWR(0x57, ec_ioctl_soe_request_t)
#define EC_IOCTL_REG_REQUEST_DATA EC_IOWR(0x58, ec_ioctl_reg_request_t)
#define EC_IOCTL_REG_REQUEST_STATE EC_IOWR(0x59, ec_ioctl_reg_request_t)
#define EC_IOCTL_REG_REQUEST_WRITE EC_IOWR(0x5a, ec_ioctl_reg_request_t)
#define EC_IOCTL_REG_REQUEST_READ EC_IOWR(0x5b, ec_ioctl_reg_request_t)
#define EC_IOCTL_VOE_SEND_HEADER EC_IOW(0x5c, ec_ioctl_voe_t)
#define EC_IOCTL_VOE_REC_HEADER EC_IOWR(0x5d, ec_ioctl_voe_t)
#define EC_IOCTL_VOE_READ EC_IOW(0x5e, ec_ioctl_voe_t)
#define EC_IOCTL_VOE_READ_NOSYNC EC_IOW(0x5f, ec_ioctl_voe_t)
#define EC_IOCTL_VOE_WRITE EC_IOWR(0x60, ec_ioctl_voe_t)
#define EC_IOCTL_VOE_EXEC EC_IOWR(0x61, ec_ioctl_voe_t)
#define EC_IOCTL_VOE_DATA EC_IOWR(0x62, ec_ioctl_voe_t)
#define EC_IOCTL_SET_SEND_INTERVAL EC_IOW(0x63, size_t)
#define EC_IOCTL_REQUEST EC_IO(0x21)
#define EC_IOCTL_CREATE_DOMAIN EC_IO(0x22)
#define EC_IOCTL_CREATE_SLAVE_CONFIG EC_IOWR(0x23, ec_ioctl_config_t)
#define EC_IOCTL_SELECT_REF_CLOCK EC_IOW(0x24, uint32_t)
#define EC_IOCTL_ACTIVATE EC_IOR(0x25, ec_ioctl_master_activate_t)
#define EC_IOCTL_DEACTIVATE EC_IO(0x26)
#define EC_IOCTL_SEND EC_IO(0x27)
#define EC_IOCTL_RECEIVE EC_IO(0x28)
#define EC_IOCTL_MASTER_STATE EC_IOR(0x29, ec_master_state_t)
#define EC_IOCTL_MASTER_LINK_STATE EC_IOWR(0x2a, ec_ioctl_link_state_t)
#define EC_IOCTL_APP_TIME EC_IOW(0x2b, uint64_t)
#define EC_IOCTL_SYNC_REF EC_IO(0x2c)
#define EC_IOCTL_SYNC_REF_TO EC_IOW(0x2d, uint64_t)
#define EC_IOCTL_SYNC_SLAVES EC_IO(0x2e)
#define EC_IOCTL_REF_CLOCK_TIME EC_IOR(0x2f, uint32_t)
#define EC_IOCTL_SYNC_MON_QUEUE EC_IO(0x30)
#define EC_IOCTL_SYNC_MON_PROCESS EC_IOR(0x31, uint32_t)
#define EC_IOCTL_RESET EC_IO(0x32)
#define EC_IOCTL_SC_SYNC EC_IOW(0x33, ec_ioctl_config_t)
#define EC_IOCTL_SC_WATCHDOG EC_IOW(0x34, ec_ioctl_config_t)
#define EC_IOCTL_SC_ADD_PDO EC_IOW(0x35, ec_ioctl_config_pdo_t)
#define EC_IOCTL_SC_CLEAR_PDOS EC_IOW(0x36, ec_ioctl_config_pdo_t)
#define EC_IOCTL_SC_ADD_ENTRY EC_IOW(0x37, ec_ioctl_add_pdo_entry_t)
#define EC_IOCTL_SC_CLEAR_ENTRIES EC_IOW(0x38, ec_ioctl_config_pdo_t)
#define EC_IOCTL_SC_REG_PDO_ENTRY EC_IOWR(0x39, ec_ioctl_reg_pdo_entry_t)
#define EC_IOCTL_SC_REG_PDO_POS EC_IOWR(0x3a, ec_ioctl_reg_pdo_pos_t)
#define EC_IOCTL_SC_DC EC_IOW(0x3b, ec_ioctl_config_t)
#define EC_IOCTL_SC_SDO EC_IOW(0x3c, ec_ioctl_sc_sdo_t)
#define EC_IOCTL_SC_EMERG_SIZE EC_IOW(0x3d, ec_ioctl_sc_emerg_t)
#define EC_IOCTL_SC_EMERG_POP EC_IOWR(0x3e, ec_ioctl_sc_emerg_t)
#define EC_IOCTL_SC_EMERG_CLEAR EC_IOW(0x3f, ec_ioctl_sc_emerg_t)
#define EC_IOCTL_SC_EMERG_OVERRUNS EC_IOWR(0x40, ec_ioctl_sc_emerg_t)
#define EC_IOCTL_SC_SDO_REQUEST EC_IOWR(0x41, ec_ioctl_sdo_request_t)
#define EC_IOCTL_SC_SOE_REQUEST EC_IOWR(0x42, ec_ioctl_soe_request_t)
#define EC_IOCTL_SC_REG_REQUEST EC_IOWR(0x43, ec_ioctl_reg_request_t)
#define EC_IOCTL_SC_VOE EC_IOWR(0x44, ec_ioctl_voe_t)
#define EC_IOCTL_SC_STATE EC_IOWR(0x45, ec_ioctl_sc_state_t)
#define EC_IOCTL_SC_IDN EC_IOW(0x46, ec_ioctl_sc_idn_t)
#define EC_IOCTL_SC_FLAG EC_IOW(0x47, ec_ioctl_sc_flag_t)
#ifdef EC_EOE
#define EC_IOCTL_SC_EOE_IP_PARAM EC_IOW(0x48, ec_ioctl_eoe_ip_t)
#endif
#define EC_IOCTL_DOMAIN_SIZE EC_IO(0x49)
#define EC_IOCTL_DOMAIN_OFFSET EC_IO(0x4a)
#define EC_IOCTL_DOMAIN_PROCESS EC_IO(0x4b)
#define EC_IOCTL_DOMAIN_QUEUE EC_IO(0x4c)
#define EC_IOCTL_DOMAIN_STATE EC_IOWR(0x4d, ec_ioctl_domain_state_t)
#define EC_IOCTL_SDO_REQUEST_INDEX EC_IOWR(0x4e, ec_ioctl_sdo_request_t)
#define EC_IOCTL_SDO_REQUEST_TIMEOUT EC_IOWR(0x4f, ec_ioctl_sdo_request_t)
#define EC_IOCTL_SDO_REQUEST_STATE EC_IOWR(0x50, ec_ioctl_sdo_request_t)
#define EC_IOCTL_SDO_REQUEST_READ EC_IOWR(0x51, ec_ioctl_sdo_request_t)
#define EC_IOCTL_SDO_REQUEST_WRITE EC_IOWR(0x52, ec_ioctl_sdo_request_t)
#define EC_IOCTL_SDO_REQUEST_DATA EC_IOWR(0x53, ec_ioctl_sdo_request_t)
#define EC_IOCTL_SOE_REQUEST_IDN EC_IOWR(0x54, ec_ioctl_soe_request_t)
#define EC_IOCTL_SOE_REQUEST_TIMEOUT EC_IOWR(0x55, ec_ioctl_soe_request_t)
#define EC_IOCTL_SOE_REQUEST_STATE EC_IOWR(0x56, ec_ioctl_soe_request_t)
#define EC_IOCTL_SOE_REQUEST_READ EC_IOWR(0x57, ec_ioctl_soe_request_t)
#define EC_IOCTL_SOE_REQUEST_WRITE EC_IOWR(0x58, ec_ioctl_soe_request_t)
#define EC_IOCTL_SOE_REQUEST_DATA EC_IOWR(0x59, ec_ioctl_soe_request_t)
#define EC_IOCTL_REG_REQUEST_DATA EC_IOWR(0x5a, ec_ioctl_reg_request_t)
#define EC_IOCTL_REG_REQUEST_STATE EC_IOWR(0x5b, ec_ioctl_reg_request_t)
#define EC_IOCTL_REG_REQUEST_WRITE EC_IOWR(0x5c, ec_ioctl_reg_request_t)
#define EC_IOCTL_REG_REQUEST_READ EC_IOWR(0x5d, ec_ioctl_reg_request_t)
#define EC_IOCTL_VOE_SEND_HEADER EC_IOW(0x5e, ec_ioctl_voe_t)
#define EC_IOCTL_VOE_REC_HEADER EC_IOWR(0x5f, ec_ioctl_voe_t)
#define EC_IOCTL_VOE_READ EC_IOW(0x60, ec_ioctl_voe_t)
#define EC_IOCTL_VOE_READ_NOSYNC EC_IOW(0x61, ec_ioctl_voe_t)
#define EC_IOCTL_VOE_WRITE EC_IOWR(0x62, ec_ioctl_voe_t)
#define EC_IOCTL_VOE_EXEC EC_IOWR(0x63, ec_ioctl_voe_t)
#define EC_IOCTL_VOE_DATA EC_IOWR(0x64, ec_ioctl_voe_t)
#define EC_IOCTL_SET_SEND_INTERVAL EC_IOW(0x65, size_t)
/****************************************************************************/
@ -621,6 +625,7 @@ typedef struct {
typedef struct {
// input
uint16_t slave_position;
uint16_t config_index; // alternatively
uint8_t mac_address_included;
uint8_t ip_address_included;
@ -630,15 +635,15 @@ typedef struct {
uint8_t name_included;
unsigned char mac_address[EC_ETH_ALEN];
uint32_t ip_address;
uint32_t subnet_mask;
uint32_t gateway;
uint32_t dns;
struct in_addr ip_address;
struct in_addr subnet_mask;
struct in_addr gateway;
struct in_addr dns;
char name[EC_MAX_HOSTNAME_SIZE];
// output
uint16_t result;
} ec_ioctl_slave_eoe_ip_t;
} ec_ioctl_eoe_ip_t;
/*****************************************************************************/

View File

@ -1,6 +1,6 @@
/*****************************************************************************
*
* Copyright (C) 2006-2023 Florian Pose, Ingenieurgemeinschaft IgH
* Copyright (C) 2006-2024 Florian Pose, Ingenieurgemeinschaft IgH
*
* This file is part of the IgH EtherCAT Master.
*
@ -28,15 +28,20 @@
/****************************************************************************/
#include <linux/module.h>
#include <linux/slab.h>
#include "slave_config.h"
#include "globals.h"
#include "master.h"
#include "voe_handler.h"
#include "flag.h"
#include "ioctl.h"
#include "slave_config.h"
#ifdef EC_EOE
#include "eoe_request.h"
#endif
#include <linux/module.h>
#include <linux/slab.h>
/****************************************************************************/
@ -85,6 +90,10 @@ void ec_slave_config_init(
INIT_LIST_HEAD(&sc->soe_configs);
INIT_LIST_HEAD(&sc->flags);
#ifdef EC_EOE
ec_eoe_request_init(&sc->eoe_ip_param_request);
#endif
ec_coe_emerg_ring_init(&sc->emerg_ring, sc);
}
@ -1431,6 +1440,70 @@ int ecrt_slave_config_flag(ec_slave_config_t *sc, const char *key,
/****************************************************************************/
#ifdef EC_EOE
int ecrt_slave_config_eoe_mac_address(ec_slave_config_t *sc,
const unsigned char *mac_address)
{
memcpy(sc->eoe_ip_param_request.mac_address, mac_address, EC_ETH_ALEN);
sc->eoe_ip_param_request.mac_address_included = 1;
return 0;
}
/****************************************************************************/
int ecrt_slave_config_eoe_ip_address(ec_slave_config_t *sc,
struct in_addr ip_address)
{
sc->eoe_ip_param_request.ip_address = ip_address;
sc->eoe_ip_param_request.ip_address_included = 1;
return 0;
}
/****************************************************************************/
int ecrt_slave_config_eoe_subnet_mask(ec_slave_config_t *sc,
struct in_addr subnet_mask)
{
sc->eoe_ip_param_request.subnet_mask = subnet_mask;
sc->eoe_ip_param_request.subnet_mask_included = 1;
return 0;
}
/****************************************************************************/
int ecrt_slave_config_eoe_default_gateway(ec_slave_config_t *sc,
struct in_addr gateway_address)
{
sc->eoe_ip_param_request.gateway = gateway_address;
sc->eoe_ip_param_request.gateway_included = 1;
return 0;
}
/****************************************************************************/
int ecrt_slave_config_eoe_dns_address(ec_slave_config_t *sc,
struct in_addr dns_address)
{
sc->eoe_ip_param_request.dns = dns_address;
sc->eoe_ip_param_request.dns_included = 1;
return 0;
}
/****************************************************************************/
int ecrt_slave_config_eoe_hostname(ec_slave_config_t *sc,
const char *name)
{
strncpy(sc->eoe_ip_param_request.name, name, EC_MAX_HOSTNAME_SIZE - 1);
sc->eoe_ip_param_request.name_included = 1;
return 0;
}
#endif
/****************************************************************************/
/** \cond */
EXPORT_SYMBOL(ecrt_slave_config_sync_manager);
@ -1459,6 +1532,14 @@ EXPORT_SYMBOL(ecrt_slave_config_create_reg_request);
EXPORT_SYMBOL(ecrt_slave_config_state);
EXPORT_SYMBOL(ecrt_slave_config_idn);
EXPORT_SYMBOL(ecrt_slave_config_flag);
#ifdef EOE
EXPORT_SYMBOL(ecrt_slave_config_eoe_mac_address);
EXPORT_SYMBOL(ecrt_slave_config_eoe_ip_address);
EXPORT_SYMBOL(ecrt_slave_config_eoe_subnet_mask);
EXPORT_SYMBOL(ecrt_slave_config_eoe_default_gateway);
EXPORT_SYMBOL(ecrt_slave_config_eoe_dns_address);
EXPORT_SYMBOL(ecrt_slave_config_eoe_hostname);
#endif
/** \endcond */

View File

@ -1,6 +1,6 @@
/*****************************************************************************
*
* Copyright (C) 2006-2023 Florian Pose, Ingenieurgemeinschaft IgH
* Copyright (C) 2006-2024 Florian Pose, Ingenieurgemeinschaft IgH
*
* This file is part of the IgH EtherCAT Master.
*
@ -141,6 +141,10 @@ struct ec_slave_config {
struct list_head soe_configs; /**< List of SoE configurations. */
struct list_head flags; /**< List of feature flags. */
#ifdef EC_EOE
ec_eoe_request_t eoe_ip_param_request; /**< EoE IP parameters. */
#endif
ec_coe_emerg_ring_t emerg_ring; /**< CoE emergency ring buffer. */
};

View File

@ -1,6 +1,6 @@
/*****************************************************************************
*
* Copyright (C) 2006-2009 Florian Pose, Ingenieurgemeinschaft IgH
* Copyright (C) 2006-2024 Florian Pose, Ingenieurgemeinschaft IgH
*
* This file is part of the IgH EtherCAT Master.
*
@ -21,14 +21,16 @@
*
****************************************************************************/
#include "CommandConfig.h"
#include "MasterDevice.h"
#include <list>
#include <iostream>
#include <iomanip>
#include <sstream>
using namespace std;
#include "CommandConfig.h"
#include "MasterDevice.h"
#include <arpa/inet.h>
/****************************************************************************/
@ -147,6 +149,9 @@ void CommandConfig::showDetailedConfigs(
ec_ioctl_config_sdo_t sdo;
ec_ioctl_config_idn_t idn;
ec_ioctl_config_flag_t flag;
#ifdef EC_EOE
ec_ioctl_eoe_ip_t ip;
#endif
string indent(doIndent ? " " : "");
for (configIter = configList.begin();
@ -299,6 +304,45 @@ void CommandConfig::showDetailedConfigs(
cout << indent << " None." << endl;
}
#ifdef EC_EOE
m.getIpParam(&ip, configIter->config_index);
if (ip.mac_address_included or ip.ip_address_included or
ip.subnet_mask_included or ip.gateway_included or
ip.dns_included or ip.name_included) {
char addr[32];
cout << indent << "EoE IP parameters:" << endl;
if (ip.mac_address_included) {
cout << indent << " MAC address: "
<< hex << setfill('0') << setw(2)
<< ip.mac_address[0] << ":"
<< ip.mac_address[1] << ":"
<< ip.mac_address[2] << ":"
<< ip.mac_address[3] << ":"
<< ip.mac_address[4] << ":"
<< ip.mac_address[5] << dec << endl;
}
if (ip.ip_address_included) {
inet_ntop(AF_INET, &ip.ip_address, addr, sizeof(addr));
cout << indent << " IP address: " << addr << endl;
}
if (ip.subnet_mask_included) {
inet_ntop(AF_INET, &ip.subnet_mask, addr, sizeof(addr));
cout << indent << " Subnet mask: " << addr << endl;
}
if (ip.gateway_included) {
inet_ntop(AF_INET, &ip.gateway, addr, sizeof(addr));
cout << indent << " Default gateway: " << addr << endl;
}
if (ip.dns_included) {
inet_ntop(AF_INET, &ip.dns, addr, sizeof(addr));
cout << indent << " DNS server address: " << addr << endl;
}
if (ip.name_included) {
cout << indent << " Hostname: " << ip.name << endl;
}
}
#endif
if (configIter->dc_assign_activate) {
int i;

View File

@ -53,13 +53,14 @@ string CommandIp::helpString(const string &binaryBaseName) const
<< endl
<< "IP parameters can be appended as argument pairs:" << endl
<< endl
<< " addr <IPv4>[/prefix] IP address (optionally with" << endl
<< " decimal subnet prefix)" << endl
<< " link <MAC> Link-layer address (may contain" << endl
<< " colons or hyphens)" << endl
<< " default <IPv4> Default gateway" << endl
<< " dns <IPv4> DNS server" << endl
<< " name <hostname> Host name (max. 32 byte)" << endl
<< " ip_address <IPv4>[/prefix] IP address (optionally with" << endl
<< " decimal subnet prefix)" << endl
<< " mac_address <MAC> Link-layer address (may contain"
<< endl
<< " colons or hyphens)" << endl
<< " default_gateway <IPv4> Default gateway" << endl
<< " dns_address <IPv4> DNS server address" << endl
<< " hostname <hostname> Host name (max. 32 byte)" << endl
<< endl
<< "IPv4 adresses can be given either in dot notation or as" << endl
<< "hostnames, which will be automatically resolved." << endl
@ -88,30 +89,30 @@ void CommandIp::execute(const StringVector &args)
throwInvalidUsageException(err);
}
ec_ioctl_slave_eoe_ip_t io = {};
ec_ioctl_eoe_ip_t io = {};
for (unsigned int argIdx = 0; argIdx < args.size(); argIdx += 2) {
string arg = args[argIdx];
string val = args[argIdx + 1];
std::transform(arg.begin(), arg.end(), arg.begin(), ::tolower);
if (arg == "link") {
if (arg == "link" or arg == "mac_address") {
parseMac(io.mac_address, val);
io.mac_address_included = 1;
}
else if (arg == "addr") {
else if (arg == "addr" or arg == "ip_address") {
parseIpv4Prefix(&io, val);
io.ip_address_included = 1;
}
else if (arg == "default") {
else if (arg == "default" or arg == "default_gateway") {
resolveIpv4(&io.gateway, val);
io.gateway_included = 1;
}
else if (arg == "dns") {
else if (arg == "dns" or arg == "dns_adress") {
resolveIpv4(&io.dns, val);
io.dns_included = 1;
}
else if (arg == "name") {
else if (arg == "name" or arg == "hostname") {
if (val.size() > EC_MAX_HOSTNAME_SIZE - 1) {
stringstream err;
err << "Name too long!";
@ -182,7 +183,7 @@ void CommandIp::parseMac(unsigned char mac[EC_ETH_ALEN], const string &str)
/****************************************************************************/
void CommandIp::parseIpv4Prefix(ec_ioctl_slave_eoe_ip_t *io,
void CommandIp::parseIpv4Prefix(ec_ioctl_eoe_ip_t *io,
const string &str)
{
size_t pos = str.find('/');
@ -205,11 +206,8 @@ void CommandIp::parseIpv4Prefix(ec_ioctl_slave_eoe_ip_t *io,
err << "Invalid prefix '" << prefixStr << "'!";
throwInvalidUsageException(err);
}
uint32_t mask = 0;
for (unsigned int bit = 0; bit < prefix; bit++) {
mask |= (1 << (31 - bit));
}
io->subnet_mask = htonl(mask);
uint32_t mask = (0xFFFFFFFF << (32 - prefix)) & 0xFFFFFFFF;
io->subnet_mask.s_addr = htonl(mask);
}
resolveIpv4(&io->ip_address, host);
@ -217,7 +215,7 @@ void CommandIp::parseIpv4Prefix(ec_ioctl_slave_eoe_ip_t *io,
/****************************************************************************/
void CommandIp::resolveIpv4(uint32_t *addr, const string &str)
void CommandIp::resolveIpv4(struct in_addr *dst, const string &str)
{
struct addrinfo hints = {};
struct addrinfo *res;
@ -238,12 +236,9 @@ void CommandIp::resolveIpv4(uint32_t *addr, const string &str)
throwCommandException(err.str());
}
sockaddr_in *sin = (sockaddr_in *) res->ai_addr;
for (unsigned int i = 0; i < 4; i++) {
((unsigned char *) addr)[i] =
((unsigned char *) &sin->sin_addr.s_addr)[i];
}
const struct sockaddr_in *in_addr =
(const struct sockaddr_in *) res->ai_addr;
*dst = in_addr->sin_addr;
freeaddrinfo(res);
}

View File

@ -37,9 +37,8 @@ class CommandIp:
protected:
void parseMac(unsigned char [6], const string &);
void parseIpv4Prefix(ec_ioctl_slave_eoe_ip_t *,
const string &);
void resolveIpv4(uint32_t *, const string &);
void parseIpv4Prefix(ec_ioctl_eoe_ip_t *, const string &);
void resolveIpv4(struct in_addr *, const string &);
};
/****************************************************************************/

View File

@ -1,6 +1,6 @@
/*****************************************************************************
*
* Copyright (C) 2006-2023 Florian Pose, Ingenieurgemeinschaft IgH
* Copyright (C) 2006-2024 Florian Pose, Ingenieurgemeinschaft IgH
*
* This file is part of the IgH EtherCAT Master.
*
@ -553,26 +553,6 @@ void MasterDevice::requestState(
/****************************************************************************/
#ifdef EC_EOE
void MasterDevice::getEoeHandler(
ec_ioctl_eoe_handler_t *eoe,
uint16_t eoeHandlerIndex
)
{
eoe->eoe_index = eoeHandlerIndex;
if (ioctl(fd, EC_IOCTL_EOE_HANDLER, eoe)) {
stringstream err;
err << "Failed to get EoE handler: " << strerror(errno);
throw MasterDeviceException(err);
}
}
#endif
/****************************************************************************/
void MasterDevice::readSoe(ec_ioctl_slave_soe_read_t *data)
{
if (ioctl(fd, EC_IOCTL_SLAVE_SOE_READ, data) < 0) {
@ -604,7 +584,49 @@ void MasterDevice::writeSoe(ec_ioctl_slave_soe_write_t *data)
/****************************************************************************/
#ifdef EC_EOE
void MasterDevice::setIpParam(ec_ioctl_slave_eoe_ip_t *data)
void MasterDevice::getEoeHandler(
ec_ioctl_eoe_handler_t *eoe,
uint16_t eoeHandlerIndex
)
{
eoe->eoe_index = eoeHandlerIndex;
if (ioctl(fd, EC_IOCTL_EOE_HANDLER, eoe)) {
stringstream err;
err << "Failed to get EoE handler: " << strerror(errno);
throw MasterDeviceException(err);
}
}
#endif
/****************************************************************************/
#ifdef EC_EOE
void MasterDevice::getIpParam(ec_ioctl_eoe_ip_t *data, uint16_t config_index)
{
data->config_index = config_index;
if (ioctl(fd, EC_IOCTL_CONFIG_EOE_IP_PARAM, data) < 0) {
if (errno == EIO && data->result) {
throw MasterDeviceEoeException(data->result);
} else {
stringstream err;
err << "Failed to set IP parameters: " << strerror(errno);
throw MasterDeviceException(err);
}
}
}
#endif
/****************************************************************************/
#ifdef EC_EOE
void MasterDevice::setIpParam(ec_ioctl_eoe_ip_t *data)
{
if (ioctl(fd, EC_IOCTL_SLAVE_EOE_IP_PARAM, data) < 0) {
if (errno == EIO && data->result) {
@ -616,6 +638,7 @@ void MasterDevice::setIpParam(ec_ioctl_slave_eoe_ip_t *data)
}
}
}
#endif
/****************************************************************************/

View File

@ -1,6 +1,6 @@
/*****************************************************************************
*
* Copyright (C) 2006-2009 Florian Pose, Ingenieurgemeinschaft IgH
* Copyright (C) 2006-2024 Florian Pose, Ingenieurgemeinschaft IgH
*
* This file is part of the IgH EtherCAT Master.
*
@ -152,12 +152,13 @@ class MasterDevice
void requestState(uint16_t, uint8_t);
void readFoe(ec_ioctl_slave_foe_t *);
void writeFoe(ec_ioctl_slave_foe_t *);
#ifdef EC_EOE
void getEoeHandler(ec_ioctl_eoe_handler_t *, uint16_t);
#endif
void readSoe(ec_ioctl_slave_soe_read_t *);
void writeSoe(ec_ioctl_slave_soe_write_t *);
void setIpParam(ec_ioctl_slave_eoe_ip_t *);
#ifdef EC_EOE
void getEoeHandler(ec_ioctl_eoe_handler_t *, uint16_t);
void getIpParam(ec_ioctl_eoe_ip_t *, uint16_t);
void setIpParam(ec_ioctl_eoe_ip_t *);
#endif
unsigned int getMasterCount() const {return masterCount;}