Implemented SoE requests in user-space library.

This commit is contained in:
Florian Pose 2023-03-14 16:48:48 +01:00
parent 56c4556173
commit bdab9570f2
8 changed files with 733 additions and 35 deletions

View File

@ -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)
{

View File

@ -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;
};

182
lib/soe_request.c Normal file
View File

@ -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
* <http://www.gnu.org/licenses/>.
*
* ---
*
* 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 <stdio.h>
#include <string.h>
#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)));
}
}
/*****************************************************************************/

48
lib/soe_request.h Normal file
View File

@ -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
* <http://www.gnu.org/licenses/>.
*
* ---
*
* 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 *);
/*****************************************************************************/

View File

@ -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;

View File

@ -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;

View File

@ -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.

View File

@ -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 *,