Added feature flags to API.
This commit is contained in:
parent
f2e838a664
commit
2ee65b6387
|
|
@ -39,6 +39,11 @@
|
|||
* request a master, to map process data, to communicate with slaves via CoE
|
||||
* and to configure and activate the bus.
|
||||
*
|
||||
* Changes since version 1.5.2:
|
||||
*
|
||||
* - Added the ecrt_slave_config_flag() method and the EC_HAVE_FLAGS
|
||||
* definition to check for its existence.
|
||||
*
|
||||
* Changes in version 1.5.2:
|
||||
*
|
||||
* - Added redundancy_active flag to ec_domain_state_t.
|
||||
|
|
@ -191,6 +196,10 @@
|
|||
*/
|
||||
#define EC_HAVE_SYNC_TO
|
||||
|
||||
/** Defined if the method ecrt_slave_config_flag() is available.
|
||||
*/
|
||||
#define EC_HAVE_FLAGS
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** End of list marker.
|
||||
|
|
@ -1647,6 +1656,31 @@ int ecrt_slave_config_idn(
|
|||
size_t size /**< Size of the \a data. */
|
||||
);
|
||||
|
||||
/** Adds a feature flag to a slave configuration.
|
||||
*
|
||||
* Feature flags are a generic way to configure slave-specific behavior.
|
||||
*
|
||||
* Multiple calls with the same slave configuration and key will overwrite the
|
||||
* configuration.
|
||||
*
|
||||
* The following flags may be available:
|
||||
* - AssignToPdi: Zero (default) keeps the slave information interface (SII)
|
||||
* assigned to EtherCAT (except during transition to PREOP). Non-zero
|
||||
* assigns the SII to the slave controller side before going to PREOP and
|
||||
* leaves it there until a write command happens.
|
||||
*
|
||||
* This method has to be called in non-realtime context before
|
||||
* ecrt_master_activate().
|
||||
*
|
||||
* \retval 0 Success.
|
||||
* \retval <0 Error code.
|
||||
*/
|
||||
int ecrt_slave_config_flag(
|
||||
ec_slave_config_t *sc, /**< Slave configuration. */
|
||||
const char *key, /**< Key as null-terminated ascii string. */
|
||||
int32_t value /**< Value to store. */
|
||||
);
|
||||
|
||||
/******************************************************************************
|
||||
* Domain methods
|
||||
*****************************************************************************/
|
||||
|
|
|
|||
|
|
@ -797,3 +797,37 @@ int ecrt_slave_config_idn(ec_slave_config_t *sc, uint8_t drive_no,
|
|||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
int ecrt_slave_config_flag(ec_slave_config_t *sc, const char *key,
|
||||
int32_t value)
|
||||
{
|
||||
ec_ioctl_sc_flag_t io;
|
||||
int ret;
|
||||
|
||||
io.config_index = sc->index;
|
||||
io.key_size = strlen(key);
|
||||
if (io.key_size <= 0) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
io.key = malloc(io.key_size + 1);
|
||||
if (!io.key) {
|
||||
fprintf(stderr, "Failed to allocate %zu bytes of flag key memory.\n",
|
||||
io.key_size);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
strcpy(io.key, key);
|
||||
io.value = value;
|
||||
|
||||
ret = ioctl(sc->master->fd, EC_IOCTL_SC_FLAG, &io);
|
||||
if (EC_IOCTL_IS_ERROR(ret)) {
|
||||
fprintf(stderr, "Failed to configure feature flag: %s\n",
|
||||
strerror(EC_IOCTL_ERRNO(ret)));
|
||||
return -EC_IOCTL_ERRNO(ret);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ ec_master-objs := \
|
|||
device.o \
|
||||
domain.o \
|
||||
eoe_request.o \
|
||||
flag.o \
|
||||
fmmu_config.o \
|
||||
foe_request.o \
|
||||
fsm_change.o \
|
||||
|
|
|
|||
|
|
@ -0,0 +1,69 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* Copyright (C) 2021 Florian Pose, Ingenieurgemeinschaft IgH
|
||||
*
|
||||
* This file is part of the IgH EtherCAT Master.
|
||||
*
|
||||
* The IgH EtherCAT Master is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* The IgH EtherCAT Master 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 General
|
||||
* Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with the IgH EtherCAT Master; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/** \file
|
||||
* Slave Configuration Feature Flag.
|
||||
*/
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
#include <linux/slab.h>
|
||||
|
||||
#include "flag.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** SDO request constructor.
|
||||
*/
|
||||
int ec_flag_init(
|
||||
ec_flag_t *flag, /**< Feature flag. */
|
||||
const char *key, /**< Feature key. */
|
||||
int32_t value /**< Feature value. */
|
||||
)
|
||||
{
|
||||
if (!key || strlen(key) == 0) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!(flag->key = (uint8_t *) kmalloc(strlen(key) + 1, GFP_KERNEL))) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
strncpy(flag->key, key, strlen(key));
|
||||
flag->value = value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** SDO request destructor.
|
||||
*/
|
||||
void ec_flag_clear(
|
||||
ec_flag_t *flag /**< Feature flag. */
|
||||
)
|
||||
{
|
||||
if (flag->key) {
|
||||
kfree(flag->key);
|
||||
flag->key = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* Copyright (C) 2021 Florian Pose, Ingenieurgemeinschaft IgH
|
||||
*
|
||||
* This file is part of the IgH EtherCAT Master.
|
||||
*
|
||||
* The IgH EtherCAT Master is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License version 2, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* The IgH EtherCAT Master 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 General
|
||||
* Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with the IgH EtherCAT Master; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/**
|
||||
\file
|
||||
EtherCAT Slave Configuration Feature Flag.
|
||||
*/
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
#ifndef __EC_FLAG_H__
|
||||
#define __EC_FLAG_H__
|
||||
|
||||
#include <linux/list.h>
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
/** Slave configutation feature flag.
|
||||
*/
|
||||
typedef struct {
|
||||
struct list_head list; /**< List item. */
|
||||
char *key; /**< Flag key (null-terminated ASCII string. */
|
||||
int32_t value; /**< Flag value (meaning depends on key). */
|
||||
} ec_flag_t;
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
int ec_flag_init(ec_flag_t *, const char *, int32_t);
|
||||
void ec_flag_clear(ec_flag_t *);
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
#endif
|
||||
130
master/ioctl.c
130
master/ioctl.c
|
|
@ -1232,6 +1232,7 @@ static ATTRIBUTES int ec_ioctl_config(
|
|||
data.watchdog_intervals = sc->watchdog_intervals;
|
||||
data.sdo_count = ec_slave_config_sdo_count(sc);
|
||||
data.idn_count = ec_slave_config_idn_count(sc);
|
||||
data.flag_count = ec_slave_config_flag_count(sc);
|
||||
data.slave_position = sc->slave ? sc->slave->ring_position : -1;
|
||||
data.dc_assign_activate = sc->dc_assign_activate;
|
||||
for (i = 0; i < EC_SYNC_SIGNAL_COUNT; i++) {
|
||||
|
|
@ -1497,6 +1498,69 @@ static ATTRIBUTES int ec_ioctl_config_idn(
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** Get slave configuration feature flag information.
|
||||
*
|
||||
* \return Zero on success, otherwise a negative error code.
|
||||
*/
|
||||
static ATTRIBUTES int ec_ioctl_config_flag(
|
||||
ec_master_t *master, /**< EtherCAT master. */
|
||||
void *arg /**< ioctl() argument. */
|
||||
)
|
||||
{
|
||||
ec_ioctl_config_flag_t *ioctl;
|
||||
const ec_slave_config_t *sc;
|
||||
const ec_flag_t *flag;
|
||||
size_t size;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if (!(flag = ec_slave_config_get_flag_by_pos_const(
|
||||
sc, ioctl->flag_pos))) {
|
||||
up(&master->master_sem);
|
||||
EC_MASTER_ERR(master, "Invalid flag position!\n");
|
||||
kfree(ioctl);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
size = min((u32) strlen(flag->key), (u32) EC_MAX_FLAG_KEY_SIZE - 1);
|
||||
memcpy(ioctl->key, flag->key, size);
|
||||
ioctl->key[size] = 0x00;
|
||||
ioctl->value = flag->value;
|
||||
|
||||
up(&master->master_sem);
|
||||
|
||||
if (copy_to_user((void __user *) arg, ioctl, sizeof(*ioctl))) {
|
||||
kfree(ioctl);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
kfree(ioctl);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifdef EC_EOE
|
||||
|
||||
/** Get EoE handler information.
|
||||
|
|
@ -3071,6 +3135,62 @@ static ATTRIBUTES int ec_ioctl_sc_idn(
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** Configures a feature flag.
|
||||
*
|
||||
* \return Zero on success, otherwise a negative error code.
|
||||
*/
|
||||
static ATTRIBUTES int ec_ioctl_sc_flag(
|
||||
ec_master_t *master, /**< EtherCAT master. */
|
||||
void *arg, /**< ioctl() argument. */
|
||||
ec_ioctl_context_t *ctx /**< Private data structure of file handle. */
|
||||
)
|
||||
{
|
||||
ec_ioctl_sc_flag_t ioctl;
|
||||
ec_slave_config_t *sc;
|
||||
uint8_t *key;
|
||||
int ret;
|
||||
|
||||
if (unlikely(!ctx->requested)) {
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
if (copy_from_user(&ioctl, (void __user *) arg, sizeof(ioctl))) {
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
if (!ioctl.key_size) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!(key = kmalloc(ioctl.key_size + 1, GFP_KERNEL))) {
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
if (copy_from_user(key, (void __user *) ioctl.key, ioctl.key_size)) {
|
||||
kfree(key);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
if (down_interruptible(&master->master_sem)) {
|
||||
kfree(key);
|
||||
return -EINTR;
|
||||
}
|
||||
|
||||
if (!(sc = ec_master_get_config(master, ioctl.config_index))) {
|
||||
up(&master->master_sem);
|
||||
kfree(key);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
up(&master->master_sem); /** \todo sc could be invalidated */
|
||||
|
||||
ret = ecrt_slave_config_flag(sc, key, ioctl.value);
|
||||
kfree(key);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** Gets the domain's data size.
|
||||
*
|
||||
* \return Domain size, or a negative error code.
|
||||
|
|
@ -4392,6 +4512,9 @@ long EC_IOCTL(
|
|||
case EC_IOCTL_CONFIG_IDN:
|
||||
ret = ec_ioctl_config_idn(master, arg);
|
||||
break;
|
||||
case EC_IOCTL_CONFIG_FLAG:
|
||||
ret = ec_ioctl_config_flag(master, arg);
|
||||
break;
|
||||
#ifdef EC_EOE
|
||||
case EC_IOCTL_EOE_HANDLER:
|
||||
ret = ec_ioctl_eoe_handler(master, arg);
|
||||
|
|
@ -4647,6 +4770,13 @@ long EC_IOCTL(
|
|||
}
|
||||
ret = ec_ioctl_sc_idn(master, arg, ctx);
|
||||
break;
|
||||
case EC_IOCTL_SC_FLAG:
|
||||
if (!ctx->writable) {
|
||||
ret = -EPERM;
|
||||
break;
|
||||
}
|
||||
ret = ec_ioctl_sc_flag(master, arg, ctx);
|
||||
break;
|
||||
case EC_IOCTL_DOMAIN_SIZE:
|
||||
ret = ec_ioctl_domain_size(master, arg, ctx);
|
||||
break;
|
||||
|
|
|
|||
155
master/ioctl.h
155
master/ioctl.h
|
|
@ -47,7 +47,7 @@
|
|||
*
|
||||
* Increment this when changing the ioctl interface!
|
||||
*/
|
||||
#define EC_IOCTL_VERSION_MAGIC 30
|
||||
#define EC_IOCTL_VERSION_MAGIC 31
|
||||
|
||||
// Command-line tool
|
||||
#define EC_IOCTL_MODULE EC_IOR(0x00, ec_ioctl_module_t)
|
||||
|
|
@ -80,72 +80,74 @@
|
|||
#define EC_IOCTL_CONFIG_PDO_ENTRY EC_IOWR(0x1b, ec_ioctl_config_pdo_entry_t)
|
||||
#define EC_IOCTL_CONFIG_SDO EC_IOWR(0x1c, ec_ioctl_config_sdo_t)
|
||||
#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(0x1e, ec_ioctl_eoe_handler_t)
|
||||
#define EC_IOCTL_EOE_HANDLER EC_IOWR(0x1f, ec_ioctl_eoe_handler_t)
|
||||
#endif
|
||||
|
||||
// Application interface
|
||||
#define EC_IOCTL_REQUEST EC_IO(0x1f)
|
||||
#define EC_IOCTL_CREATE_DOMAIN EC_IO(0x20)
|
||||
#define EC_IOCTL_CREATE_SLAVE_CONFIG EC_IOWR(0x21, ec_ioctl_config_t)
|
||||
#define EC_IOCTL_SELECT_REF_CLOCK EC_IOW(0x22, uint32_t)
|
||||
#define EC_IOCTL_ACTIVATE EC_IOR(0x23, ec_ioctl_master_activate_t)
|
||||
#define EC_IOCTL_DEACTIVATE EC_IO(0x24)
|
||||
#define EC_IOCTL_SEND EC_IO(0x25)
|
||||
#define EC_IOCTL_RECEIVE EC_IO(0x26)
|
||||
#define EC_IOCTL_MASTER_STATE EC_IOR(0x27, ec_master_state_t)
|
||||
#define EC_IOCTL_MASTER_LINK_STATE EC_IOWR(0x28, ec_ioctl_link_state_t)
|
||||
#define EC_IOCTL_APP_TIME EC_IOW(0x29, uint64_t)
|
||||
#define EC_IOCTL_SYNC_REF EC_IO(0x2a)
|
||||
#define EC_IOCTL_SYNC_REF_TO EC_IOW(0x2b, uint64_t)
|
||||
#define EC_IOCTL_SYNC_SLAVES EC_IO(0x2c)
|
||||
#define EC_IOCTL_REF_CLOCK_TIME EC_IOR(0x2d, uint32_t)
|
||||
#define EC_IOCTL_SYNC_MON_QUEUE EC_IO(0x2e)
|
||||
#define EC_IOCTL_SYNC_MON_PROCESS EC_IOR(0x2f, uint32_t)
|
||||
#define EC_IOCTL_RESET EC_IO(0x30)
|
||||
#define EC_IOCTL_SC_SYNC EC_IOW(0x31, ec_ioctl_config_t)
|
||||
#define EC_IOCTL_SC_WATCHDOG EC_IOW(0x32, ec_ioctl_config_t)
|
||||
#define EC_IOCTL_SC_ADD_PDO EC_IOW(0x33, ec_ioctl_config_pdo_t)
|
||||
#define EC_IOCTL_SC_CLEAR_PDOS EC_IOW(0x34, ec_ioctl_config_pdo_t)
|
||||
#define EC_IOCTL_SC_ADD_ENTRY EC_IOW(0x35, ec_ioctl_add_pdo_entry_t)
|
||||
#define EC_IOCTL_SC_CLEAR_ENTRIES EC_IOW(0x36, ec_ioctl_config_pdo_t)
|
||||
#define EC_IOCTL_SC_REG_PDO_ENTRY EC_IOWR(0x37, ec_ioctl_reg_pdo_entry_t)
|
||||
#define EC_IOCTL_SC_REG_PDO_POS EC_IOWR(0x38, ec_ioctl_reg_pdo_pos_t)
|
||||
#define EC_IOCTL_SC_DC EC_IOW(0x39, ec_ioctl_config_t)
|
||||
#define EC_IOCTL_SC_SDO EC_IOW(0x3a, ec_ioctl_sc_sdo_t)
|
||||
#define EC_IOCTL_SC_EMERG_SIZE EC_IOW(0x3b, ec_ioctl_sc_emerg_t)
|
||||
#define EC_IOCTL_SC_EMERG_POP EC_IOWR(0x3c, ec_ioctl_sc_emerg_t)
|
||||
#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_DOMAIN_SIZE EC_IO(0x44)
|
||||
#define EC_IOCTL_DOMAIN_OFFSET EC_IO(0x45)
|
||||
#define EC_IOCTL_DOMAIN_PROCESS EC_IO(0x46)
|
||||
#define EC_IOCTL_DOMAIN_QUEUE EC_IO(0x47)
|
||||
#define EC_IOCTL_DOMAIN_STATE EC_IOWR(0x48, ec_ioctl_domain_state_t)
|
||||
#define EC_IOCTL_SDO_REQUEST_INDEX EC_IOWR(0x49, ec_ioctl_sdo_request_t)
|
||||
#define EC_IOCTL_SDO_REQUEST_TIMEOUT EC_IOWR(0x4a, ec_ioctl_sdo_request_t)
|
||||
#define EC_IOCTL_SDO_REQUEST_STATE EC_IOWR(0x4b, ec_ioctl_sdo_request_t)
|
||||
#define EC_IOCTL_SDO_REQUEST_READ EC_IOWR(0x4c, ec_ioctl_sdo_request_t)
|
||||
#define EC_IOCTL_SDO_REQUEST_WRITE EC_IOWR(0x4d, ec_ioctl_sdo_request_t)
|
||||
#define EC_IOCTL_SDO_REQUEST_DATA EC_IOWR(0x4e, ec_ioctl_sdo_request_t)
|
||||
#define EC_IOCTL_REG_REQUEST_DATA EC_IOWR(0x4f, ec_ioctl_reg_request_t)
|
||||
#define EC_IOCTL_REG_REQUEST_STATE EC_IOWR(0x50, ec_ioctl_reg_request_t)
|
||||
#define EC_IOCTL_REG_REQUEST_WRITE EC_IOWR(0x51, ec_ioctl_reg_request_t)
|
||||
#define EC_IOCTL_REG_REQUEST_READ EC_IOWR(0x52, ec_ioctl_reg_request_t)
|
||||
#define EC_IOCTL_VOE_SEND_HEADER EC_IOW(0x53, ec_ioctl_voe_t)
|
||||
#define EC_IOCTL_VOE_REC_HEADER EC_IOWR(0x54, ec_ioctl_voe_t)
|
||||
#define EC_IOCTL_VOE_READ EC_IOW(0x55, ec_ioctl_voe_t)
|
||||
#define EC_IOCTL_VOE_READ_NOSYNC EC_IOW(0x56, ec_ioctl_voe_t)
|
||||
#define EC_IOCTL_VOE_WRITE EC_IOWR(0x57, ec_ioctl_voe_t)
|
||||
#define EC_IOCTL_VOE_EXEC EC_IOWR(0x58, ec_ioctl_voe_t)
|
||||
#define EC_IOCTL_VOE_DATA EC_IOWR(0x59, ec_ioctl_voe_t)
|
||||
#define EC_IOCTL_SET_SEND_INTERVAL EC_IOW(0x5a, size_t)
|
||||
#define EC_IOCTL_SC_OVERLAPPING_IO EC_IOW(0x5b, ec_ioctl_config_t)
|
||||
#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_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(0x40, ec_ioctl_sdo_request_t)
|
||||
#define EC_IOCTL_REG_REQUEST_DATA EC_IOWR(0x41, ec_ioctl_reg_request_t)
|
||||
#define EC_IOCTL_REG_REQUEST_STATE EC_IOWR(0x52, ec_ioctl_reg_request_t)
|
||||
#define EC_IOCTL_REG_REQUEST_WRITE EC_IOWR(0x53, ec_ioctl_reg_request_t)
|
||||
#define EC_IOCTL_REG_REQUEST_READ EC_IOWR(0x54, ec_ioctl_reg_request_t)
|
||||
#define EC_IOCTL_VOE_SEND_HEADER EC_IOW(0x55, ec_ioctl_voe_t)
|
||||
#define EC_IOCTL_VOE_REC_HEADER EC_IOWR(0x56, ec_ioctl_voe_t)
|
||||
#define EC_IOCTL_VOE_READ EC_IOW(0x57, ec_ioctl_voe_t)
|
||||
#define EC_IOCTL_VOE_READ_NOSYNC EC_IOW(0x58, ec_ioctl_voe_t)
|
||||
#define EC_IOCTL_VOE_WRITE EC_IOWR(0x59, ec_ioctl_voe_t)
|
||||
#define EC_IOCTL_VOE_EXEC EC_IOWR(0x5a, ec_ioctl_voe_t)
|
||||
#define EC_IOCTL_VOE_DATA EC_IOWR(0x5b, ec_ioctl_voe_t)
|
||||
#define EC_IOCTL_SET_SEND_INTERVAL EC_IOW(0x5c, size_t)
|
||||
#define EC_IOCTL_SC_OVERLAPPING_IO EC_IOW(0x5d, ec_ioctl_config_t)
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
|
|
@ -486,6 +488,7 @@ typedef struct {
|
|||
uint16_t watchdog_intervals;
|
||||
uint32_t sdo_count;
|
||||
uint32_t idn_count;
|
||||
uint32_t flag_count;
|
||||
int32_t slave_position;
|
||||
uint16_t dc_assign_activate;
|
||||
ec_sync_signal_t dc_sync[EC_SYNC_SIGNAL_COUNT];
|
||||
|
|
@ -564,6 +567,22 @@ typedef struct {
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** Maximum size for key.
|
||||
*/
|
||||
#define EC_MAX_FLAG_KEY_SIZE 128
|
||||
|
||||
typedef struct {
|
||||
// inputs
|
||||
uint32_t config_index;
|
||||
uint32_t flag_pos;
|
||||
|
||||
// outputs
|
||||
char key[EC_MAX_FLAG_KEY_SIZE];
|
||||
int32_t value;
|
||||
} ec_ioctl_config_flag_t;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifdef EC_EOE
|
||||
|
||||
typedef struct {
|
||||
|
|
@ -709,6 +728,16 @@ typedef struct {
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef struct {
|
||||
// inputs
|
||||
uint32_t config_index;
|
||||
size_t key_size;
|
||||
char *key;
|
||||
int32_t value;
|
||||
} ec_ioctl_sc_flag_t;
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef struct {
|
||||
// inputs
|
||||
uint32_t domain_index;
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@
|
|||
#include "globals.h"
|
||||
#include "master.h"
|
||||
#include "voe_handler.h"
|
||||
#include "flag.h"
|
||||
|
||||
#include "slave_config.h"
|
||||
|
||||
|
|
@ -90,6 +91,7 @@ void ec_slave_config_init(
|
|||
INIT_LIST_HEAD(&sc->reg_requests);
|
||||
INIT_LIST_HEAD(&sc->voe_handlers);
|
||||
INIT_LIST_HEAD(&sc->soe_configs);
|
||||
INIT_LIST_HEAD(&sc->flags);
|
||||
|
||||
ec_coe_emerg_ring_init(&sc->emerg_ring, sc);
|
||||
}
|
||||
|
|
@ -109,6 +111,7 @@ void ec_slave_config_clear(
|
|||
ec_voe_handler_t *voe, *next_voe;
|
||||
ec_reg_request_t *reg, *next_reg;
|
||||
ec_soe_request_t *soe, *next_soe;
|
||||
ec_flag_t *flag, *next_flag;
|
||||
|
||||
ec_slave_config_detach(sc);
|
||||
|
||||
|
|
@ -151,6 +154,13 @@ void ec_slave_config_clear(
|
|||
kfree(soe);
|
||||
}
|
||||
|
||||
// free all flags
|
||||
list_for_each_entry_safe(flag, next_flag, &sc->flags, list) {
|
||||
list_del(&flag->list);
|
||||
ec_flag_clear(flag);
|
||||
kfree(flag);
|
||||
}
|
||||
|
||||
ec_coe_emerg_ring_clear(&sc->emerg_ring);
|
||||
}
|
||||
|
||||
|
|
@ -489,6 +499,50 @@ const ec_soe_request_t *ec_slave_config_get_idn_by_pos_const(
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** Get the number of feature flags.
|
||||
*
|
||||
* \return Number of feature flags.
|
||||
*/
|
||||
unsigned int ec_slave_config_flag_count(
|
||||
const ec_slave_config_t *sc /**< Slave configuration. */
|
||||
)
|
||||
{
|
||||
const ec_flag_t *flag;
|
||||
unsigned int count = 0;
|
||||
|
||||
list_for_each_entry(flag, &sc->flags, list) {
|
||||
count++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** Finds a flag via its position in the list.
|
||||
*
|
||||
* Const version.
|
||||
*
|
||||
* \return Search result, or NULL.
|
||||
*/
|
||||
const ec_flag_t *ec_slave_config_get_flag_by_pos_const(
|
||||
const ec_slave_config_t *sc, /**< Slave configuration. */
|
||||
unsigned int pos /**< Position in the list. */
|
||||
)
|
||||
{
|
||||
const ec_flag_t *flag;
|
||||
|
||||
list_for_each_entry(flag, &sc->flags, list) {
|
||||
if (pos--)
|
||||
continue;
|
||||
return flag;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** Finds a CoE handler via its position in the list.
|
||||
*
|
||||
* \return Search result, or NULL.
|
||||
|
|
@ -564,12 +618,15 @@ void ec_slave_config_expire_disconnected_requests(
|
|||
ec_sdo_request_t *sdo_req;
|
||||
ec_reg_request_t *reg_req;
|
||||
|
||||
if (sc->slave) { return; }
|
||||
if (sc->slave) {
|
||||
return;
|
||||
}
|
||||
|
||||
list_for_each_entry(sdo_req, &sc->sdo_requests, list) {
|
||||
if (sdo_req->state == EC_INT_REQUEST_QUEUED ||
|
||||
sdo_req->state == EC_INT_REQUEST_BUSY) {
|
||||
EC_CONFIG_DBG(sc, 1, "Aborting SDO request; no slave attached.\n");
|
||||
EC_CONFIG_DBG(sc, 1,
|
||||
"Aborting SDO request; no slave attached.\n");
|
||||
sdo_req->state = EC_INT_REQUEST_FAILURE;
|
||||
}
|
||||
}
|
||||
|
|
@ -577,12 +634,35 @@ void ec_slave_config_expire_disconnected_requests(
|
|||
list_for_each_entry(reg_req, &sc->reg_requests, list) {
|
||||
if (reg_req->state == EC_INT_REQUEST_QUEUED ||
|
||||
reg_req->state == EC_INT_REQUEST_BUSY) {
|
||||
EC_CONFIG_DBG(sc, 1, "Aborting register request; no slave attached.\n");
|
||||
EC_CONFIG_DBG(sc, 1,
|
||||
"Aborting register request; no slave attached.\n");
|
||||
reg_req->state = EC_INT_REQUEST_FAILURE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** Finds a flag.
|
||||
*
|
||||
* \return Search result, or NULL.
|
||||
*/
|
||||
ec_flag_t *ec_slave_config_find_flag(
|
||||
ec_slave_config_t *sc, /**< Slave configuration. */
|
||||
const uint8_t *key /**< Flag key. */
|
||||
)
|
||||
{
|
||||
ec_flag_t *flag;
|
||||
|
||||
list_for_each_entry(flag, &sc->flags, list) {
|
||||
if (!strcmp(flag->key, key)) {
|
||||
return flag;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Application interface
|
||||
*****************************************************************************/
|
||||
|
|
@ -1315,6 +1395,42 @@ int ecrt_slave_config_idn(ec_slave_config_t *sc, uint8_t drive_no,
|
|||
|
||||
/*****************************************************************************/
|
||||
|
||||
int ecrt_slave_config_flag(ec_slave_config_t *sc, const char *key,
|
||||
int32_t value)
|
||||
{
|
||||
ec_flag_t *flag;
|
||||
|
||||
EC_CONFIG_DBG(sc, 1, "%s(sc = 0x%p, key = %s, value = %i)\n",
|
||||
__func__, sc, key, value);
|
||||
|
||||
|
||||
flag = ec_slave_config_find_flag(sc, key);
|
||||
if (flag) {
|
||||
flag->value = value; // overwrite value
|
||||
}
|
||||
else { // new flag
|
||||
int ret;
|
||||
|
||||
if (!(flag = (ec_flag_t *) kmalloc(sizeof(ec_flag_t), GFP_KERNEL))) {
|
||||
EC_CONFIG_ERR(sc, "Failed to allocate memory for flag!\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ret = ec_flag_init(flag, key, value);
|
||||
if (ret) {
|
||||
kfree(flag);
|
||||
return ret;
|
||||
}
|
||||
|
||||
down(&sc->master->master_sem);
|
||||
list_add_tail(&flag->list, &sc->flags);
|
||||
up(&sc->master->master_sem);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/** \cond */
|
||||
|
||||
EXPORT_SYMBOL(ecrt_slave_config_sync_manager);
|
||||
|
|
@ -1341,6 +1457,7 @@ EXPORT_SYMBOL(ecrt_slave_config_create_voe_handler);
|
|||
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);
|
||||
|
||||
/** \endcond */
|
||||
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@
|
|||
#include "sync_config.h"
|
||||
#include "fmmu_config.h"
|
||||
#include "coe_emerg_ring.h"
|
||||
#include "flag.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
|
|
@ -147,6 +148,7 @@ struct ec_slave_config {
|
|||
struct list_head voe_handlers; /**< List of VoE handlers. */
|
||||
struct list_head reg_requests; /**< List of register requests. */
|
||||
struct list_head soe_configs; /**< List of SoE configurations. */
|
||||
struct list_head flags; /**< List of feature flags. */
|
||||
|
||||
ec_coe_emerg_ring_t emerg_ring; /**< CoE emergency ring buffer. */
|
||||
};
|
||||
|
|
@ -168,6 +170,9 @@ const ec_sdo_request_t *ec_slave_config_get_sdo_by_pos_const(
|
|||
unsigned int ec_slave_config_idn_count(const ec_slave_config_t *);
|
||||
const ec_soe_request_t *ec_slave_config_get_idn_by_pos_const(
|
||||
const ec_slave_config_t *, unsigned int);
|
||||
unsigned int ec_slave_config_flag_count(const ec_slave_config_t *);
|
||||
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_reg_request_t *ec_slave_config_find_reg_request(ec_slave_config_t *,
|
||||
|
|
|
|||
|
|
@ -154,6 +154,7 @@ void CommandConfig::showDetailedConfigs(
|
|||
ec_ioctl_config_pdo_entry_t entry;
|
||||
ec_ioctl_config_sdo_t sdo;
|
||||
ec_ioctl_config_idn_t idn;
|
||||
ec_ioctl_config_flag_t flag;
|
||||
string indent(doIndent ? " " : "");
|
||||
|
||||
for (configIter = configList.begin();
|
||||
|
|
@ -293,6 +294,19 @@ void CommandConfig::showDetailedConfigs(
|
|||
} else {
|
||||
cout << indent << " None." << endl;
|
||||
}
|
||||
|
||||
cout << indent << "Feature flags:" << endl;
|
||||
if (configIter->flag_count) {
|
||||
for (j = 0; j < configIter->flag_count; j++) {
|
||||
m.getConfigFlag(&flag, configIter->config_index, j);
|
||||
|
||||
cout << indent << " " << flag.key
|
||||
<< ": " << flag.value << endl;
|
||||
}
|
||||
} else {
|
||||
cout << indent << " None." << endl;
|
||||
}
|
||||
|
||||
if (configIter->dc_assign_activate) {
|
||||
int i;
|
||||
|
||||
|
|
|
|||
|
|
@ -218,6 +218,24 @@ void MasterDevice::getConfigIdn(
|
|||
|
||||
/****************************************************************************/
|
||||
|
||||
void MasterDevice::getConfigFlag(
|
||||
ec_ioctl_config_flag_t *data,
|
||||
unsigned int index,
|
||||
unsigned int pos
|
||||
)
|
||||
{
|
||||
data->config_index = index;
|
||||
data->flag_pos = pos;
|
||||
|
||||
if (ioctl(fd, EC_IOCTL_CONFIG_FLAG, data) < 0) {
|
||||
stringstream err;
|
||||
err << "Failed to get slave config flag: " << strerror(errno);
|
||||
throw MasterDeviceException(err);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
|
||||
void MasterDevice::getDomain(ec_ioctl_domain_t *data, unsigned int index)
|
||||
{
|
||||
data->index = index;
|
||||
|
|
|
|||
|
|
@ -134,6 +134,8 @@ class MasterDevice
|
|||
uint8_t, uint16_t, uint8_t);
|
||||
void getConfigSdo(ec_ioctl_config_sdo_t *, unsigned int, unsigned int);
|
||||
void getConfigIdn(ec_ioctl_config_idn_t *, unsigned int, unsigned int);
|
||||
void getConfigFlag(ec_ioctl_config_flag_t *, unsigned int,
|
||||
unsigned int);
|
||||
void getDomain(ec_ioctl_domain_t *, unsigned int);
|
||||
void getFmmu(ec_ioctl_domain_fmmu_t *, unsigned int, unsigned int);
|
||||
void getData(ec_ioctl_domain_data_t *, unsigned int, unsigned int,
|
||||
|
|
|
|||
Loading…
Reference in New Issue