From bdab9570f22c7daf4a23810609267cecb18aa82c Mon Sep 17 00:00:00 2001 From: Florian Pose Date: Tue, 14 Mar 2023 16:48:48 +0100 Subject: [PATCH] Implemented SoE requests in user-space library. --- lib/slave_config.c | 81 ++++++++++ lib/slave_config.h | 5 +- lib/soe_request.c | 182 ++++++++++++++++++++++ lib/soe_request.h | 48 ++++++ master/ioctl.c | 347 +++++++++++++++++++++++++++++++++++++++++- master/ioctl.h | 81 ++++++---- master/slave_config.c | 22 +++ master/slave_config.h | 2 + 8 files changed, 733 insertions(+), 35 deletions(-) create mode 100644 lib/soe_request.c create mode 100644 lib/soe_request.h diff --git a/lib/slave_config.c b/lib/slave_config.c index ea28f75a..4e00fcf9 100644 --- a/lib/slave_config.c +++ b/lib/slave_config.c @@ -35,6 +35,7 @@ #include "slave_config.h" #include "domain.h" #include "sdo_request.h" +#include "soe_request.h" #include "reg_request.h" #include "voe_handler.h" #include "master.h" @@ -44,6 +45,7 @@ void ec_slave_config_clear(ec_slave_config_t *sc) { ec_sdo_request_t *r, *next_r; + ec_soe_request_t *s, *next_s; ec_reg_request_t *e, *next_e; ec_voe_handler_t *v, *next_v; @@ -56,6 +58,15 @@ void ec_slave_config_clear(ec_slave_config_t *sc) } sc->first_sdo_request = NULL; + s = sc->first_soe_request; + while (r) { + next_s = s->next; + ec_soe_request_clear(s); + free(s); + s = next_s; + } + sc->first_soe_request = NULL; + e = sc->first_reg_request; while (e) { next_e = e->next; @@ -607,6 +618,76 @@ 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, + ec_soe_request_t *req) +{ + if (sc->first_soe_request) { + ec_soe_request_t *r = sc->first_soe_request; + while (r->next) { + r = r->next; + } + r->next = req; + } else { + sc->first_soe_request = req; + } +} + +/*****************************************************************************/ + +ec_soe_request_t *ecrt_slave_config_create_soe_request(ec_slave_config_t *sc, + uint8_t drive_no, uint16_t idn, size_t size) +{ + ec_ioctl_soe_request_t data; + ec_soe_request_t *req; + int ret; + + req = malloc(sizeof(ec_soe_request_t)); + if (!req) { + fprintf(stderr, "Failed to allocate memory.\n"); + return 0; + } + + if (size) { + req->data = malloc(size); + if (!req->data) { + fprintf(stderr, "Failed to allocate %zu bytes of SoE data" + " memory.\n", size); + free(req); + return 0; + } + } else { + req->data = NULL; + } + + data.config_index = sc->index; + data.drive_no = drive_no; + data.idn = idn; + data.size = size; + + ret = ioctl(sc->master->fd, EC_IOCTL_SC_SOE_REQUEST, &data); + if (EC_IOCTL_IS_ERROR(ret)) { + fprintf(stderr, "Failed to create SoE request: %s\n", + strerror(EC_IOCTL_ERRNO(ret))); + ec_soe_request_clear(req); + free(req); + return NULL; + } + + req->next = NULL; + req->config = sc; + req->index = data.request_index; + req->drive_no = data.drive_no; + req->idn = data.idn; + req->data_size = size; + req->mem_size = size; + + ec_slave_config_add_soe_request(sc, req); + + return req; +} + +/*****************************************************************************/ + void ec_slave_config_add_reg_request(ec_slave_config_t *sc, ec_reg_request_t *reg) { diff --git a/lib/slave_config.h b/lib/slave_config.h index 7d855a5f..6e3a4355 100644 --- a/lib/slave_config.h +++ b/lib/slave_config.h @@ -1,8 +1,6 @@ /****************************************************************************** * - * $Id$ - * - * Copyright (C) 2006-2012 Florian Pose, Ingenieurgemeinschaft IgH + * Copyright (C) 2006-2023 Florian Pose, Ingenieurgemeinschaft IgH * * This file is part of the IgH EtherCAT master userspace library. * @@ -39,6 +37,7 @@ struct ec_slave_config { uint16_t alias; uint16_t position; ec_sdo_request_t *first_sdo_request; + ec_soe_request_t *first_soe_request; ec_reg_request_t *first_reg_request; ec_voe_handler_t *first_voe_handler; }; diff --git a/lib/soe_request.c b/lib/soe_request.c new file mode 100644 index 00000000..99bc311e --- /dev/null +++ b/lib/soe_request.c @@ -0,0 +1,182 @@ +/****************************************************************************** + * + * Copyright (C) 2006-2023 Florian Pose, Ingenieurgemeinschaft IgH + * + * This file is part of the IgH EtherCAT master userspace library. + * + * The IgH EtherCAT master userspace library is free software; you can + * redistribute it and/or modify it under the terms of the GNU Lesser General + * Public License as published by the Free Software Foundation; version 2.1 + * of the License. + * + * The IgH EtherCAT master userspace library is distributed in the hope that + * it will be useful, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with the IgH EtherCAT master userspace library. If not, see + * . + * + * --- + * + * The license mentioned above concerns the source code only. Using the + * EtherCAT technology and brand is only permitted in compliance with the + * industrial property and similar rights of Beckhoff Automation GmbH. + * + *****************************************************************************/ + +/** \file + * Canopen over EtherCAT SoE request functions. + */ + +/*****************************************************************************/ + +#include +#include + +#include "ioctl.h" +#include "soe_request.h" +#include "slave_config.h" +#include "master.h" + +/*****************************************************************************/ + +void ec_soe_request_clear(ec_soe_request_t *req) +{ + if (req->data) { + free(req->data); + req->data = NULL; + } +} + +/***************************************************************************** + * Application interface. + ****************************************************************************/ + +void ecrt_soe_request_idn(ec_soe_request_t *req, uint8_t drive_no, + uint16_t idn) +{ + ec_ioctl_soe_request_t data; + int ret; + + data.config_index = req->config->index; + data.request_index = req->index; + data.drive_no = drive_no; + data.idn = idn; + + ret = ioctl(req->config->master->fd, EC_IOCTL_SOE_REQUEST_IDN, &data); + if (EC_IOCTL_IS_ERROR(ret)) { + fprintf(stderr, "Failed to set SoE request IDN: %s\n", + strerror(EC_IOCTL_ERRNO(ret))); + } +} + +/*****************************************************************************/ + +void ecrt_soe_request_timeout(ec_soe_request_t *req, uint32_t timeout) +{ + ec_ioctl_soe_request_t data; + int ret; + + data.config_index = req->config->index; + data.request_index = req->index; + data.timeout = timeout; + + ret = ioctl(req->config->master->fd, EC_IOCTL_SOE_REQUEST_TIMEOUT, &data); + if (EC_IOCTL_IS_ERROR(ret)) { + fprintf(stderr, "Failed to set SoE request timeout: %s\n", + strerror(EC_IOCTL_ERRNO(ret))); + } +} + +/*****************************************************************************/ + +uint8_t *ecrt_soe_request_data(ec_soe_request_t *req) +{ + return req->data; +} + +/*****************************************************************************/ + +size_t ecrt_soe_request_data_size(const ec_soe_request_t *req) +{ + return req->data_size; +} + +/*****************************************************************************/ + +ec_request_state_t ecrt_soe_request_state(ec_soe_request_t *req) +{ + ec_ioctl_soe_request_t data; + int ret; + + data.config_index = req->config->index; + data.request_index = req->index; + + ret = ioctl(req->config->master->fd, EC_IOCTL_SOE_REQUEST_STATE, &data); + if (EC_IOCTL_IS_ERROR(ret)) { + fprintf(stderr, "Failed to get SoE request state: %s\n", + strerror(EC_IOCTL_ERRNO(ret))); + return EC_REQUEST_ERROR; + } + + if (data.size) { // new data waiting to be copied + if (req->mem_size < data.size) { + fprintf(stderr, "Received %zu bytes do not fit info SoE data" + " memory (%zu bytes)!\n", data.size, req->mem_size); + return EC_REQUEST_ERROR; + } + + data.data = req->data; + + ret = ioctl(req->config->master->fd, + EC_IOCTL_SOE_REQUEST_DATA, &data); + if (EC_IOCTL_IS_ERROR(ret)) { + fprintf(stderr, "Failed to get SoE data: %s\n", + strerror(EC_IOCTL_ERRNO(ret))); + return EC_REQUEST_ERROR; + } + req->data_size = data.size; + } + + return data.state; +} + +/*****************************************************************************/ + +void ecrt_soe_request_read(ec_soe_request_t *req) +{ + ec_ioctl_soe_request_t data; + int ret; + + data.config_index = req->config->index; + data.request_index = req->index; + + ret = ioctl(req->config->master->fd, EC_IOCTL_SOE_REQUEST_READ, &data); + if (EC_IOCTL_IS_ERROR(ret)) { + fprintf(stderr, "Failed to command an SoE read operation : %s\n", + strerror(EC_IOCTL_ERRNO(ret))); + } +} + +/*****************************************************************************/ + +void ecrt_soe_request_write(ec_soe_request_t *req) +{ + ec_ioctl_soe_request_t data; + int ret; + + data.config_index = req->config->index; + data.request_index = req->index; + data.data = req->data; + data.size = req->data_size; + + ret = ioctl(req->config->master->fd, EC_IOCTL_SOE_REQUEST_WRITE, &data); + if (EC_IOCTL_IS_ERROR(ret)) { + fprintf(stderr, "Failed to command an SDO write operation : %s\n", + strerror(EC_IOCTL_ERRNO(ret))); + } +} + +/*****************************************************************************/ diff --git a/lib/soe_request.h b/lib/soe_request.h new file mode 100644 index 00000000..43f8e72d --- /dev/null +++ b/lib/soe_request.h @@ -0,0 +1,48 @@ +/****************************************************************************** + * + * Copyright (C) 2006-2023 Florian Pose, Ingenieurgemeinschaft IgH + * + * This file is part of the IgH EtherCAT master userspace library. + * + * The IgH EtherCAT master userspace library is free software; you can + * redistribute it and/or modify it under the terms of the GNU Lesser General + * Public License as published by the Free Software Foundation; version 2.1 + * of the License. + * + * The IgH EtherCAT master userspace library is distributed in the hope that + * it will be useful, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with the IgH EtherCAT master userspace library. If not, see + * . + * + * --- + * + * The license mentioned above concerns the source code only. Using the + * EtherCAT technology and brand is only permitted in compliance with the + * industrial property and similar rights of Beckhoff Automation GmbH. + * + *****************************************************************************/ + +#include "include/ecrt.h" + +/*****************************************************************************/ + +struct ec_soe_request { + ec_soe_request_t *next; /**< List header. */ + ec_slave_config_t *config; /**< Parent slave configuration. */ + unsigned int index; /**< Request index (identifier). */ + uint8_t drive_no; /**< SoE drive number. */ + uint16_t idn; /**< SoE ID number. */ + uint8_t *data; /**< Pointer to SoE data. */ + size_t mem_size; /**< Size of SoE data memory. */ + size_t data_size; /**< Size of SoE data. */ +}; + +/*****************************************************************************/ + +void ec_soe_request_clear(ec_soe_request_t *); + +/*****************************************************************************/ diff --git a/master/ioctl.c b/master/ioctl.c index 43a98c1a..18c0cbdc 100644 --- a/master/ioctl.c +++ b/master/ioctl.c @@ -1,8 +1,6 @@ /****************************************************************************** * - * $Id$ - * - * Copyright (C) 2006-2012 Florian Pose, Ingenieurgemeinschaft IgH + * Copyright (C) 2006-2023 Florian Pose, Ingenieurgemeinschaft IgH * * This file is part of the IgH EtherCAT Master. * @@ -2819,6 +2817,59 @@ static ATTRIBUTES int ec_ioctl_sc_create_sdo_request( /*****************************************************************************/ +/** Create an SoE request. + * + * \return Zero on success, otherwise a negative error code. + */ +static ATTRIBUTES int ec_ioctl_sc_create_soe_request( + ec_master_t *master, /**< EtherCAT master. */ + void *arg, /**< ioctl() argument. */ + ec_ioctl_context_t *ctx /**< Private data structure of file handle. */ + ) +{ + ec_ioctl_soe_request_t data; + ec_slave_config_t *sc; + ec_soe_request_t *req; + + if (unlikely(!ctx->requested)) + return -EPERM; + + if (copy_from_user(&data, (void __user *) arg, sizeof(data))) { + return -EFAULT; + } + + data.request_index = 0; + + if (down_interruptible(&master->master_sem)) + return -EINTR; + + sc = ec_master_get_config(master, data.config_index); + if (!sc) { + up(&master->master_sem); + return -ENOENT; + } + + list_for_each_entry(req, &sc->soe_requests, list) { + data.request_index++; + } + + up(&master->master_sem); /** \todo sc could be invalidated */ + + req = ecrt_slave_config_create_soe_request_err(sc, data.drive_no, + data.idn, data.size); + if (IS_ERR(req)) { + return PTR_ERR(req); + } + + if (copy_to_user((void __user *) arg, &data, sizeof(data))) { + return -EFAULT; + } + + return 0; +} + +/*****************************************************************************/ + /** Create a register request. * * \return Zero on success, otherwise a negative error code. @@ -3482,6 +3533,255 @@ static ATTRIBUTES int ec_ioctl_sdo_request_data( /*****************************************************************************/ +/** Sets an SoE request's drive number and IDN. + * + * \return Zero on success, otherwise a negative error code. + */ +static ATTRIBUTES int ec_ioctl_soe_request_index( + ec_master_t *master, /**< EtherCAT master. */ + void *arg, /**< ioctl() argument. */ + ec_ioctl_context_t *ctx /**< Private data structure of file handle. */ + ) +{ + ec_ioctl_soe_request_t data; + ec_slave_config_t *sc; + ec_soe_request_t *req; + + if (unlikely(!ctx->requested)) + return -EPERM; + + if (copy_from_user(&data, (void __user *) arg, sizeof(data))) + return -EFAULT; + + /* no locking of master_sem needed, because neither sc nor req will not be + * deleted in the meantime. */ + + if (!(sc = ec_master_get_config(master, data.config_index))) { + return -ENOENT; + } + + if (!(req = ec_slave_config_find_soe_request(sc, data.request_index))) { + return -ENOENT; + } + + ecrt_soe_request_idn(req, data.drive_no, data.idn); + return 0; +} + +/*****************************************************************************/ + +/** Sets an CoE request's timeout. + * + * \return Zero on success, otherwise a negative error code. + */ +static ATTRIBUTES int ec_ioctl_soe_request_timeout( + ec_master_t *master, /**< EtherCAT master. */ + void *arg, /**< ioctl() argument. */ + ec_ioctl_context_t *ctx /**< Private data structure of file handle. */ + ) +{ + ec_ioctl_soe_request_t data; + ec_slave_config_t *sc; + ec_soe_request_t *req; + + if (unlikely(!ctx->requested)) + return -EPERM; + + if (copy_from_user(&data, (void __user *) arg, sizeof(data))) + return -EFAULT; + + /* no locking of master_sem needed, because neither sc nor req will not be + * deleted in the meantime. */ + + if (!(sc = ec_master_get_config(master, data.config_index))) { + return -ENOENT; + } + + if (!(req = ec_slave_config_find_soe_request(sc, data.request_index))) { + return -ENOENT; + } + + ecrt_soe_request_timeout(req, data.timeout); + return 0; +} + +/*****************************************************************************/ + +/** Gets an SoE request's state. + * + * \return Zero on success, otherwise a negative error code. + */ +static ATTRIBUTES int ec_ioctl_soe_request_state( + ec_master_t *master, /**< EtherCAT master. */ + void *arg, /**< ioctl() argument. */ + ec_ioctl_context_t *ctx /**< Private data structure of file handle. */ + ) +{ + ec_ioctl_soe_request_t data; + ec_slave_config_t *sc; + ec_soe_request_t *req; + + if (unlikely(!ctx->requested)) + return -EPERM; + + if (copy_from_user(&data, (void __user *) arg, sizeof(data))) + return -EFAULT; + + /* no locking of master_sem needed, because neither sc nor req will not be + * deleted in the meantime. */ + + if (!(sc = ec_master_get_config(master, data.config_index))) { + return -ENOENT; + } + + if (!(req = ec_slave_config_find_soe_request(sc, data.request_index))) { + return -ENOENT; + } + + data.state = ecrt_soe_request_state(req); + if (data.state == EC_REQUEST_SUCCESS && req->dir == EC_DIR_INPUT) { + data.size = ecrt_soe_request_data_size(req); + } + else { + data.size = 0; + } + + if (copy_to_user((void __user *) arg, &data, sizeof(data))) + return -EFAULT; + + return 0; +} + +/*****************************************************************************/ + +/** Starts an SoE IDN read operation. + * + * \return Zero on success, otherwise a negative error code. + */ +static ATTRIBUTES int ec_ioctl_soe_request_read( + ec_master_t *master, /**< EtherCAT master. */ + void *arg, /**< ioctl() argument. */ + ec_ioctl_context_t *ctx /**< Private data structure of file handle. */ + ) +{ + ec_ioctl_soe_request_t data; + ec_slave_config_t *sc; + ec_soe_request_t *req; + + if (unlikely(!ctx->requested)) + return -EPERM; + + if (copy_from_user(&data, (void __user *) arg, sizeof(data))) + return -EFAULT; + + /* no locking of master_sem needed, because neither sc nor req will not be + * deleted in the meantime. */ + + if (!(sc = ec_master_get_config(master, data.config_index))) { + return -ENOENT; + } + + if (!(req = ec_slave_config_find_soe_request(sc, data.request_index))) { + return -ENOENT; + } + + ecrt_soe_request_read(req); + return 0; +} + +/*****************************************************************************/ + +/** Starts an SoE IDN write operation. + * + * \return Zero on success, otherwise a negative error code. + */ +static ATTRIBUTES int ec_ioctl_soe_request_write( + ec_master_t *master, /**< EtherCAT master. */ + void *arg, /**< ioctl() argument. */ + ec_ioctl_context_t *ctx /**< Private data structure of file handle. */ + ) +{ + ec_ioctl_soe_request_t data; + ec_slave_config_t *sc; + ec_soe_request_t *req; + int ret; + + if (unlikely(!ctx->requested)) + return -EPERM; + + if (copy_from_user(&data, (void __user *) arg, sizeof(data))) + return -EFAULT; + + if (!data.size) { + EC_MASTER_ERR(master, "IDN write: Data size may not be zero!\n"); + return -EINVAL; + } + + /* no locking of master_sem needed, because neither sc nor req will not be + * deleted in the meantime. */ + + if (!(sc = ec_master_get_config(master, data.config_index))) { + return -ENOENT; + } + + if (!(req = ec_slave_config_find_soe_request(sc, data.request_index))) { + return -ENOENT; + } + + ret = ec_soe_request_alloc(req, data.size); + if (ret) + return ret; + + if (copy_from_user(req->data, (void __user *) data.data, data.size)) + return -EFAULT; + + req->data_size = data.size; + ecrt_soe_request_write(req); + return 0; +} + +/*****************************************************************************/ + +/** Read SoE IDN data. + * + * \return Zero on success, otherwise a negative error code. + */ +static ATTRIBUTES int ec_ioctl_soe_request_data( + ec_master_t *master, /**< EtherCAT master. */ + void *arg, /**< ioctl() argument. */ + ec_ioctl_context_t *ctx /**< Private data structure of file handle. */ + ) +{ + ec_ioctl_soe_request_t data; + ec_slave_config_t *sc; + ec_soe_request_t *req; + + if (unlikely(!ctx->requested)) + return -EPERM; + + if (copy_from_user(&data, (void __user *) arg, sizeof(data))) + return -EFAULT; + + /* no locking of master_sem needed, because neither sc nor req will not be + * deleted in the meantime. */ + + if (!(sc = ec_master_get_config(master, data.config_index))) { + return -ENOENT; + } + + if (!(req = ec_slave_config_find_soe_request(sc, data.request_index))) { + return -ENOENT; + } + + if (copy_to_user((void __user *) data.data, ecrt_soe_request_data(req), + ecrt_soe_request_data_size(req))) + return -EFAULT; + + return 0; +} + +/*****************************************************************************/ + /** Read register data. * * \return Zero on success, otherwise a negative error code. @@ -4616,6 +4916,13 @@ long EC_IOCTL( } ret = ec_ioctl_sc_create_sdo_request(master, arg, ctx); break; + case EC_IOCTL_SC_SOE_REQUEST: + if (!ctx->writable) { + ret = -EPERM; + break; + } + ret = ec_ioctl_sc_create_soe_request(master, arg, ctx); + break; case EC_IOCTL_SC_REG_REQUEST: if (!ctx->writable) { ret = -EPERM; @@ -4704,6 +5011,40 @@ long EC_IOCTL( case EC_IOCTL_SDO_REQUEST_DATA: ret = ec_ioctl_sdo_request_data(master, arg, ctx); break; + case EC_IOCTL_SOE_REQUEST_IDN: + if (!ctx->writable) { + ret = -EPERM; + break; + } + ret = ec_ioctl_soe_request_index(master, arg, ctx); + break; + case EC_IOCTL_SOE_REQUEST_TIMEOUT: + if (!ctx->writable) { + ret = -EPERM; + break; + } + ret = ec_ioctl_soe_request_timeout(master, arg, ctx); + break; + case EC_IOCTL_SOE_REQUEST_STATE: + ret = ec_ioctl_soe_request_state(master, arg, ctx); + break; + case EC_IOCTL_SOE_REQUEST_READ: + if (!ctx->writable) { + ret = -EPERM; + break; + } + ret = ec_ioctl_soe_request_read(master, arg, ctx); + break; + case EC_IOCTL_SOE_REQUEST_WRITE: + if (!ctx->writable) { + ret = -EPERM; + break; + } + ret = ec_ioctl_soe_request_write(master, arg, ctx); + break; + case EC_IOCTL_SOE_REQUEST_DATA: + ret = ec_ioctl_soe_request_data(master, arg, ctx); + break; case EC_IOCTL_REG_REQUEST_DATA: ret = ec_ioctl_reg_request_data(master, arg, ctx); break; diff --git a/master/ioctl.h b/master/ioctl.h index 3991e406..0bdae660 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 31 +#define EC_IOCTL_VERSION_MAGIC 32 // Command-line tool #define EC_IOCTL_MODULE EC_IOR(0x00, ec_ioctl_module_t) @@ -118,34 +118,41 @@ #define EC_IOCTL_SC_EMERG_CLEAR EC_IOW(0x3d, ec_ioctl_sc_emerg_t) #define EC_IOCTL_SC_EMERG_OVERRUNS EC_IOWR(0x3e, ec_ioctl_sc_emerg_t) #define EC_IOCTL_SC_SDO_REQUEST EC_IOWR(0x3f, ec_ioctl_sdo_request_t) -#define EC_IOCTL_SC_REG_REQUEST EC_IOWR(0x40, ec_ioctl_reg_request_t) -#define EC_IOCTL_SC_VOE EC_IOWR(0x41, ec_ioctl_voe_t) -#define EC_IOCTL_SC_STATE EC_IOWR(0x42, ec_ioctl_sc_state_t) -#define EC_IOCTL_SC_IDN EC_IOW(0x43, ec_ioctl_sc_idn_t) -#define EC_IOCTL_SC_FLAG EC_IOW(0x44, ec_ioctl_sc_flag_t) -#define EC_IOCTL_DOMAIN_SIZE EC_IO(0x45) -#define EC_IOCTL_DOMAIN_OFFSET EC_IO(0x46) -#define EC_IOCTL_DOMAIN_PROCESS EC_IO(0x47) -#define EC_IOCTL_DOMAIN_QUEUE EC_IO(0x48) -#define EC_IOCTL_DOMAIN_STATE EC_IOWR(0x49, ec_ioctl_domain_state_t) -#define EC_IOCTL_SDO_REQUEST_INDEX EC_IOWR(0x4a, ec_ioctl_sdo_request_t) -#define EC_IOCTL_SDO_REQUEST_TIMEOUT EC_IOWR(0x4b, ec_ioctl_sdo_request_t) -#define EC_IOCTL_SDO_REQUEST_STATE EC_IOWR(0x4c, ec_ioctl_sdo_request_t) -#define EC_IOCTL_SDO_REQUEST_READ EC_IOWR(0x4d, ec_ioctl_sdo_request_t) -#define EC_IOCTL_SDO_REQUEST_WRITE EC_IOWR(0x4e, ec_ioctl_sdo_request_t) -#define EC_IOCTL_SDO_REQUEST_DATA EC_IOWR(0x4f, ec_ioctl_sdo_request_t) -#define EC_IOCTL_REG_REQUEST_DATA EC_IOWR(0x50, ec_ioctl_reg_request_t) -#define EC_IOCTL_REG_REQUEST_STATE EC_IOWR(0x51, ec_ioctl_reg_request_t) -#define EC_IOCTL_REG_REQUEST_WRITE EC_IOWR(0x52, ec_ioctl_reg_request_t) -#define EC_IOCTL_REG_REQUEST_READ EC_IOWR(0x53, ec_ioctl_reg_request_t) -#define EC_IOCTL_VOE_SEND_HEADER EC_IOW(0x54, ec_ioctl_voe_t) -#define EC_IOCTL_VOE_REC_HEADER EC_IOWR(0x55, ec_ioctl_voe_t) -#define EC_IOCTL_VOE_READ EC_IOW(0x56, ec_ioctl_voe_t) -#define EC_IOCTL_VOE_READ_NOSYNC EC_IOW(0x57, ec_ioctl_voe_t) -#define EC_IOCTL_VOE_WRITE EC_IOWR(0x58, ec_ioctl_voe_t) -#define EC_IOCTL_VOE_EXEC EC_IOWR(0x59, ec_ioctl_voe_t) -#define EC_IOCTL_VOE_DATA EC_IOWR(0x5a, ec_ioctl_voe_t) -#define EC_IOCTL_SET_SEND_INTERVAL EC_IOW(0x5b, size_t) +#define EC_IOCTL_SC_SOE_REQUEST EC_IOWR(0x40, ec_ioctl_soe_request_t) +#define EC_IOCTL_SC_REG_REQUEST EC_IOWR(0x41, ec_ioctl_reg_request_t) +#define EC_IOCTL_SC_VOE EC_IOWR(0x42, ec_ioctl_voe_t) +#define EC_IOCTL_SC_STATE EC_IOWR(0x43, ec_ioctl_sc_state_t) +#define EC_IOCTL_SC_IDN EC_IOW(0x44, ec_ioctl_sc_idn_t) +#define EC_IOCTL_SC_FLAG EC_IOW(0x45, ec_ioctl_sc_flag_t) +#define EC_IOCTL_DOMAIN_SIZE EC_IO(0x46) +#define EC_IOCTL_DOMAIN_OFFSET EC_IO(0x47) +#define EC_IOCTL_DOMAIN_PROCESS EC_IO(0x48) +#define EC_IOCTL_DOMAIN_QUEUE EC_IO(0x49) +#define EC_IOCTL_DOMAIN_STATE EC_IOWR(0x4a, ec_ioctl_domain_state_t) +#define EC_IOCTL_SDO_REQUEST_INDEX EC_IOWR(0x4b, ec_ioctl_sdo_request_t) +#define EC_IOCTL_SDO_REQUEST_TIMEOUT EC_IOWR(0x4c, ec_ioctl_sdo_request_t) +#define EC_IOCTL_SDO_REQUEST_STATE EC_IOWR(0x4d, ec_ioctl_sdo_request_t) +#define EC_IOCTL_SDO_REQUEST_READ EC_IOWR(0x4e, ec_ioctl_sdo_request_t) +#define EC_IOCTL_SDO_REQUEST_WRITE EC_IOWR(0x4f, ec_ioctl_sdo_request_t) +#define EC_IOCTL_SDO_REQUEST_DATA EC_IOWR(0x50, ec_ioctl_sdo_request_t) +#define EC_IOCTL_SOE_REQUEST_IDN EC_IOWR(0x51, ec_ioctl_soe_request_t) +#define EC_IOCTL_SOE_REQUEST_TIMEOUT EC_IOWR(0x52, ec_ioctl_soe_request_t) +#define EC_IOCTL_SOE_REQUEST_STATE EC_IOWR(0x53, ec_ioctl_soe_request_t) +#define EC_IOCTL_SOE_REQUEST_READ EC_IOWR(0x54, ec_ioctl_soe_request_t) +#define EC_IOCTL_SOE_REQUEST_WRITE EC_IOWR(0x55, ec_ioctl_soe_request_t) +#define EC_IOCTL_SOE_REQUEST_DATA EC_IOWR(0x56, ec_ioctl_soe_request_t) +#define EC_IOCTL_REG_REQUEST_DATA EC_IOWR(0x57, ec_ioctl_reg_request_t) +#define EC_IOCTL_REG_REQUEST_STATE EC_IOWR(0x58, ec_ioctl_reg_request_t) +#define EC_IOCTL_REG_REQUEST_WRITE EC_IOWR(0x59, ec_ioctl_reg_request_t) +#define EC_IOCTL_REG_REQUEST_READ EC_IOWR(0x5a, ec_ioctl_reg_request_t) +#define EC_IOCTL_VOE_SEND_HEADER EC_IOW(0x5b, ec_ioctl_voe_t) +#define EC_IOCTL_VOE_REC_HEADER EC_IOWR(0x5c, ec_ioctl_voe_t) +#define EC_IOCTL_VOE_READ EC_IOW(0x5d, ec_ioctl_voe_t) +#define EC_IOCTL_VOE_READ_NOSYNC EC_IOW(0x5e, ec_ioctl_voe_t) +#define EC_IOCTL_VOE_WRITE EC_IOWR(0x5f, ec_ioctl_voe_t) +#define EC_IOCTL_VOE_EXEC EC_IOWR(0x60, ec_ioctl_voe_t) +#define EC_IOCTL_VOE_DATA EC_IOWR(0x61, ec_ioctl_voe_t) +#define EC_IOCTL_SET_SEND_INTERVAL EC_IOW(0x62, size_t) /*****************************************************************************/ @@ -730,6 +737,22 @@ typedef struct { /*****************************************************************************/ +typedef struct { + // inputs + uint32_t config_index; + + // inputs/outputs + uint32_t request_index; + uint8_t drive_no; + uint16_t idn; + size_t size; + uint8_t *data; + uint32_t timeout; + ec_request_state_t state; +} ec_ioctl_soe_request_t; + +/*****************************************************************************/ + typedef struct { // inputs uint32_t config_index; diff --git a/master/slave_config.c b/master/slave_config.c index 28dc7d35..2617ef49 100644 --- a/master/slave_config.c +++ b/master/slave_config.c @@ -535,6 +535,28 @@ ec_sdo_request_t *ec_slave_config_find_sdo_request( /*****************************************************************************/ +/** Finds a SoE request via its position in the list. + * + * \return Search result, or NULL. + */ +ec_soe_request_t *ec_slave_config_find_soe_request( + ec_slave_config_t *sc, /**< Slave configuration. */ + unsigned int pos /**< Position in the list. */ + ) +{ + ec_soe_request_t *req; + + list_for_each_entry(req, &sc->soe_requests, list) { + if (pos--) + continue; + return req; + } + + return NULL; +} + +/*****************************************************************************/ + /** Finds a register handler via its position in the list. * * \return Search result, or NULL. diff --git a/master/slave_config.h b/master/slave_config.h index 2d518c58..59cbecde 100644 --- a/master/slave_config.h +++ b/master/slave_config.h @@ -172,6 +172,8 @@ const ec_flag_t *ec_slave_config_get_flag_by_pos_const( const ec_slave_config_t *, unsigned int); ec_sdo_request_t *ec_slave_config_find_sdo_request(ec_slave_config_t *, unsigned int); +ec_soe_request_t *ec_slave_config_find_soe_request(ec_slave_config_t *, + unsigned int); ec_reg_request_t *ec_slave_config_find_reg_request(ec_slave_config_t *, unsigned int); ec_voe_handler_t *ec_slave_config_find_voe_handler(ec_slave_config_t *,