From 95a25495afb725b3f95b52bd6f10b359f1928ad2 Mon Sep 17 00:00:00 2001 From: Florian Pose Date: Wed, 22 May 2024 12:06:48 +0200 Subject: [PATCH] Added ecrt_slave_config_state_timeout() in user-space library. --- lib/libethercat.map | 1 + lib/slave_config.c | 24 +++++++++++++++ master/ioctl.c | 47 ++++++++++++++++++++++++++++++ master/ioctl.h | 71 ++++++++++++++++++++++++++------------------- 4 files changed, 113 insertions(+), 30 deletions(-) diff --git a/lib/libethercat.map b/lib/libethercat.map index 7a83f83b..759e6b58 100644 --- a/lib/libethercat.map +++ b/lib/libethercat.map @@ -110,4 +110,5 @@ LIBETHERCAT_1.6 { ecrt_slave_config_eoe_default_gateway; ecrt_slave_config_eoe_dns_address; ecrt_slave_config_eoe_hostname; + ecrt_slave_config_state_timeout; } LIBETHERCAT_1.5.3; diff --git a/lib/slave_config.c b/lib/slave_config.c index 7c3b8867..7bef3a99 100644 --- a/lib/slave_config.c +++ b/lib/slave_config.c @@ -1038,3 +1038,27 @@ int ecrt_slave_config_eoe_hostname(ec_slave_config_t *sc, #endif // EC_EOE /****************************************************************************/ + +int ecrt_slave_config_state_timeout(ec_slave_config_t *sc, + ec_al_state_t from_state, ec_al_state_t to_state, + unsigned int timeout_ms) +{ + ec_ioctl_sc_state_timeout_t io = {}; + int ret; + + io.config_index = sc->index; + io.from_state = from_state; + io.to_state = to_state; + io.timeout_ms = timeout_ms; + + ret = ioctl(sc->master->fd, EC_IOCTL_SC_STATE_TIMEOUT, &io); + if (EC_IOCTL_IS_ERROR(ret)) { + fprintf(stderr, "Failed to configure AL state timeout: %s\n", + strerror(EC_IOCTL_ERRNO(ret))); + return -EC_IOCTL_ERRNO(ret); + } + + return 0; +} + +/****************************************************************************/ diff --git a/master/ioctl.c b/master/ioctl.c index a3a7bcf1..ceceb83d 100644 --- a/master/ioctl.c +++ b/master/ioctl.c @@ -3332,6 +3332,46 @@ static ATTRIBUTES int ec_ioctl_sc_flag( /****************************************************************************/ +/** Sets an AL state transition timeout. + * + * \return Zero on success, otherwise a negative error code. + */ +static ATTRIBUTES int ec_ioctl_sc_state_timeout( + ec_master_t *master, /**< EtherCAT master. */ + void *arg, /**< ioctl() argument. */ + ec_ioctl_context_t *ctx /**< Private data structure of file handle. */ + ) +{ + ec_ioctl_sc_state_timeout_t ioctl; + ec_slave_config_t *sc; + int ret; + + if (unlikely(!ctx->requested)) { + return -EPERM; + } + + if (copy_from_user(&ioctl, (void __user *) arg, sizeof(ioctl))) { + return -EFAULT; + } + + if (down_interruptible(&master->master_sem)) { + return -EINTR; + } + + if (!(sc = ec_master_get_config(master, ioctl.config_index))) { + up(&master->master_sem); + return -ENOENT; + } + + up(&master->master_sem); /** \todo sc could be invalidated */ + + ret = ecrt_slave_config_state_timeout(sc, ioctl.from_state, + ioctl.to_state, ioctl.timeout_ms); + return ret; +} + +/****************************************************************************/ + #ifdef EC_EOE /** Configures EoE IP parameters. @@ -5493,6 +5533,13 @@ static long ec_ioctl_nrt } ret = ec_ioctl_sc_flag(master, arg, ctx); break; + case EC_IOCTL_SC_STATE_TIMEOUT: + if (!ctx->writable) { + ret = -EPERM; + break; + } + ret = ec_ioctl_sc_state_timeout(master, arg, ctx); + break; #ifdef EC_EOE case EC_IOCTL_SC_EOE_IP_PARAM: if (!ctx->writable) { diff --git a/master/ioctl.h b/master/ioctl.h index 2cb90103..0c51e638 100644 --- a/master/ioctl.h +++ b/master/ioctl.h @@ -47,7 +47,7 @@ * * Increment this when changing the ioctl interface! */ -#define EC_IOCTL_VERSION_MAGIC 36 +#define EC_IOCTL_VERSION_MAGIC 37 // Command-line tool #define EC_IOCTL_MODULE EC_IOR(0x00, ec_ioctl_module_t) @@ -131,35 +131,36 @@ #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) +#define EC_IOCTL_SC_STATE_TIMEOUT EC_IOW(0x49, ec_ioctl_sc_state_timeout_t) +#define EC_IOCTL_DOMAIN_SIZE EC_IO(0x4a) +#define EC_IOCTL_DOMAIN_OFFSET EC_IO(0x4b) +#define EC_IOCTL_DOMAIN_PROCESS EC_IO(0x4c) +#define EC_IOCTL_DOMAIN_QUEUE EC_IO(0x4d) +#define EC_IOCTL_DOMAIN_STATE EC_IOWR(0x4e, ec_ioctl_domain_state_t) +#define EC_IOCTL_SDO_REQUEST_INDEX EC_IOWR(0x4f, ec_ioctl_sdo_request_t) +#define EC_IOCTL_SDO_REQUEST_TIMEOUT EC_IOWR(0x50, ec_ioctl_sdo_request_t) +#define EC_IOCTL_SDO_REQUEST_STATE EC_IOWR(0x51, ec_ioctl_sdo_request_t) +#define EC_IOCTL_SDO_REQUEST_READ EC_IOWR(0x52, ec_ioctl_sdo_request_t) +#define EC_IOCTL_SDO_REQUEST_WRITE EC_IOWR(0x53, ec_ioctl_sdo_request_t) +#define EC_IOCTL_SDO_REQUEST_DATA EC_IOWR(0x54, ec_ioctl_sdo_request_t) +#define EC_IOCTL_SOE_REQUEST_IDN EC_IOWR(0x55, ec_ioctl_soe_request_t) +#define EC_IOCTL_SOE_REQUEST_TIMEOUT EC_IOWR(0x56, ec_ioctl_soe_request_t) +#define EC_IOCTL_SOE_REQUEST_STATE EC_IOWR(0x57, ec_ioctl_soe_request_t) +#define EC_IOCTL_SOE_REQUEST_READ EC_IOWR(0x58, ec_ioctl_soe_request_t) +#define EC_IOCTL_SOE_REQUEST_WRITE EC_IOWR(0x59, ec_ioctl_soe_request_t) +#define EC_IOCTL_SOE_REQUEST_DATA EC_IOWR(0x5a, ec_ioctl_soe_request_t) +#define EC_IOCTL_REG_REQUEST_DATA EC_IOWR(0x5b, ec_ioctl_reg_request_t) +#define EC_IOCTL_REG_REQUEST_STATE EC_IOWR(0x5c, ec_ioctl_reg_request_t) +#define EC_IOCTL_REG_REQUEST_WRITE EC_IOWR(0x5d, ec_ioctl_reg_request_t) +#define EC_IOCTL_REG_REQUEST_READ EC_IOWR(0x5e, ec_ioctl_reg_request_t) +#define EC_IOCTL_VOE_SEND_HEADER EC_IOW(0x5f, ec_ioctl_voe_t) +#define EC_IOCTL_VOE_REC_HEADER EC_IOWR(0x60, ec_ioctl_voe_t) +#define EC_IOCTL_VOE_READ EC_IOW(0x61, ec_ioctl_voe_t) +#define EC_IOCTL_VOE_READ_NOSYNC EC_IOW(0x62, ec_ioctl_voe_t) +#define EC_IOCTL_VOE_WRITE EC_IOWR(0x63, ec_ioctl_voe_t) +#define EC_IOCTL_VOE_EXEC EC_IOWR(0x64, ec_ioctl_voe_t) +#define EC_IOCTL_VOE_DATA EC_IOWR(0x65, ec_ioctl_voe_t) +#define EC_IOCTL_SET_SEND_INTERVAL EC_IOW(0x66, size_t) /****************************************************************************/ @@ -749,6 +750,16 @@ typedef struct { /****************************************************************************/ +typedef struct { + // inputs + uint32_t config_index; + ec_al_state_t from_state; + ec_al_state_t to_state; + uint32_t timeout_ms; +} ec_ioctl_sc_state_timeout_t; + +/****************************************************************************/ + typedef struct { // inputs uint32_t domain_index;