fp@1255: /******************************************************************************
fp@1266: *
fp@1266: * $Id$
fp@1266: *
fp@1266: * Copyright (C) 2006-2008 Florian Pose, Ingenieurgemeinschaft IgH
fp@1266: *
fp@1266: * This file is part of the IgH EtherCAT master userspace library.
fp@1266: *
fp@1266: * The IgH EtherCAT master userspace library is free software: you can
fp@1266: * redistribute it and/or modify it under the terms of the GNU Lesser General
fp@1266: * Public License as published by the Free Software Foundation, version 2 of
fp@1266: * the License.
fp@1266: *
fp@1266: * The IgH EtherCAT master userspace library is distributed in the hope that
fp@1266: * it will be useful, but WITHOUT ANY WARRANTY; without even the implied
fp@1266: * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
fp@1266: * GNU Lesser General Public License for more details.
fp@1266: *
fp@1266: * You should have received a copy of the GNU Lesser General Public License
fp@1266: * along with the IgH EtherCAT master userspace library. If not, see
fp@1266: * .
fp@1266: *
fp@1266: * The right to use EtherCAT Technology is granted and comes free of charge
fp@1266: * under condition of compatibility of product made by Licensee. People
fp@1266: * intending to distribute/sell products based on the code, have to sign an
fp@1266: * agreement to guarantee that products using software based on IgH EtherCAT
fp@1266: * master stay compatible with the actual EtherCAT specification (which are
fp@1266: * released themselves as an open standard) as the (only) precondition to have
fp@1266: * the right to use EtherCAT Technology, IP and trade marks.
fp@1255: *
fp@1255: *****************************************************************************/
fp@1255:
fp@1255: #include
fp@1255: #include
fp@1255: #include
fp@1255: #include
fp@1255: #include
fp@1255:
fp@1255: #include "slave_config.h"
fp@1255: #include "domain.h"
fp@1264: #include "voe_handler.h"
fp@1255: #include "master.h"
fp@1255: #include "master/ioctl.h"
fp@1255:
fp@1255: /*****************************************************************************/
fp@1255:
fp@1255: int ecrt_slave_config_sync_manager(ec_slave_config_t *sc, uint8_t sync_index,
fp@1255: ec_direction_t dir)
fp@1255: {
fp@1255: ec_ioctl_config_t data;
fp@1255: unsigned int i;
fp@1255:
fp@1255: if (sync_index >= EC_MAX_SYNC_MANAGERS)
fp@1255: return -1;
fp@1255:
fp@1255: memset(&data, 0x00, sizeof(ec_ioctl_config_t));
fp@1255: data.config_index = sc->index;
fp@1255: data.syncs[sync_index].dir = dir;
fp@1255:
fp@1255: if (ioctl(sc->master->fd, EC_IOCTL_SC_SYNC, &data) == -1) {
fp@1255: fprintf(stderr, "Failed to config sync manager: %s\n",
fp@1255: strerror(errno));
fp@1255: return -1;
fp@1255: }
fp@1255:
fp@1255: return 0;
fp@1255: }
fp@1255:
fp@1255: /*****************************************************************************/
fp@1255:
fp@1255: int ecrt_slave_config_pdo_assign_add(ec_slave_config_t *sc,
fp@1255: uint8_t sync_index, uint16_t pdo_index)
fp@1255: {
fp@1255: ec_ioctl_config_pdo_t data;
fp@1255:
fp@1255: data.config_index = sc->index;
fp@1255: data.sync_index = sync_index;
fp@1255: data.index = pdo_index;
fp@1255:
fp@1255: if (ioctl(sc->master->fd, EC_IOCTL_SC_ADD_PDO, &data) == -1) {
fp@1255: fprintf(stderr, "Failed to add Pdo: %s\n",
fp@1255: strerror(errno));
fp@1255: return -1;
fp@1255: }
fp@1255:
fp@1255: return 0;
fp@1255: }
fp@1255:
fp@1255: /*****************************************************************************/
fp@1255:
fp@1255: void ecrt_slave_config_pdo_assign_clear(ec_slave_config_t *sc,
fp@1255: uint8_t sync_index)
fp@1255: {
fp@1255: ec_ioctl_config_pdo_t data;
fp@1255:
fp@1255: data.config_index = sc->index;
fp@1255: data.sync_index = sync_index;
fp@1255:
fp@1255: if (ioctl(sc->master->fd, EC_IOCTL_SC_CLEAR_PDOS, &data) == -1) {
fp@1255: fprintf(stderr, "Failed to clear Pdos: %s\n",
fp@1255: strerror(errno));
fp@1255: }
fp@1255: }
fp@1255:
fp@1255: /*****************************************************************************/
fp@1255:
fp@1255: int ecrt_slave_config_pdo_mapping_add(ec_slave_config_t *sc,
fp@1255: uint16_t pdo_index, uint16_t entry_index, uint8_t entry_subindex,
fp@1255: uint8_t entry_bit_length)
fp@1255: {
fp@1255: ec_ioctl_add_pdo_entry_t data;
fp@1255:
fp@1255: data.config_index = sc->index;
fp@1255: data.pdo_index = pdo_index;
fp@1255: data.entry_index = entry_index;
fp@1255: data.entry_subindex = entry_subindex;
fp@1255: data.entry_bit_length = entry_bit_length;
fp@1255:
fp@1255: if (ioctl(sc->master->fd, EC_IOCTL_SC_ADD_ENTRY, &data) == -1) {
fp@1255: fprintf(stderr, "Failed to add Pdo entry: %s\n",
fp@1255: strerror(errno));
fp@1255: return -1;
fp@1255: }
fp@1255:
fp@1255: return 0;
fp@1255: }
fp@1255:
fp@1255: /*****************************************************************************/
fp@1255:
fp@1255: void ecrt_slave_config_pdo_mapping_clear(ec_slave_config_t *sc,
fp@1255: uint16_t pdo_index)
fp@1255: {
fp@1255: ec_ioctl_config_pdo_t data;
fp@1255:
fp@1255: data.config_index = sc->index;
fp@1255: data.index = pdo_index;
fp@1255:
fp@1255: if (ioctl(sc->master->fd, EC_IOCTL_SC_CLEAR_ENTRIES, &data) == -1) {
fp@1255: fprintf(stderr, "Failed to clear Pdo entries: %s\n",
fp@1255: strerror(errno));
fp@1255: }
fp@1255: }
fp@1255:
fp@1255: /*****************************************************************************/
fp@1255:
fp@1255: int ecrt_slave_config_pdos(ec_slave_config_t *sc,
fp@1255: unsigned int n_syncs, const ec_sync_info_t syncs[])
fp@1255: {
fp@1255: unsigned int i, j, k;
fp@1255: const ec_sync_info_t *sync_info;
fp@1255: const ec_pdo_info_t *pdo_info;
fp@1255: const ec_pdo_entry_info_t *entry_info;
fp@1255:
fp@1255: if (!syncs)
fp@1255: return 0;
fp@1255:
fp@1255: for (i = 0; i < n_syncs; i++) {
fp@1255: sync_info = &syncs[i];
fp@1255:
fp@1255: if (sync_info->index == (uint8_t) EC_END)
fp@1255: break;
fp@1255:
fp@1255: if (sync_info->index >= EC_MAX_SYNC_MANAGERS) {
fp@1255: fprintf(stderr, "Invalid sync manager index %u!\n",
fp@1255: sync_info->index);
fp@1255: return -1;
fp@1255: }
fp@1255:
fp@1255: if (ecrt_slave_config_sync_manager(
fp@1255: sc, sync_info->index, sync_info->dir))
fp@1255: return -1;
fp@1255:
fp@1255: if (sync_info->n_pdos && sync_info->pdos) {
fp@1255: ecrt_slave_config_pdo_assign_clear(sc, sync_info->index);
fp@1255:
fp@1255: for (j = 0; j < sync_info->n_pdos; j++) {
fp@1255: pdo_info = &sync_info->pdos[j];
fp@1255:
fp@1255: if (ecrt_slave_config_pdo_assign_add(
fp@1255: sc, sync_info->index, pdo_info->index))
fp@1255: return -1;
fp@1255:
fp@1255: if (pdo_info->n_entries && pdo_info->entries) {
fp@1255: ecrt_slave_config_pdo_mapping_clear(sc, pdo_info->index);
fp@1255:
fp@1255: for (k = 0; k < pdo_info->n_entries; k++) {
fp@1255: entry_info = &pdo_info->entries[k];
fp@1255:
fp@1255: if (ecrt_slave_config_pdo_mapping_add(sc,
fp@1255: pdo_info->index, entry_info->index,
fp@1255: entry_info->subindex,
fp@1255: entry_info->bit_length))
fp@1255: return -1;
fp@1255: }
fp@1255: }
fp@1255: }
fp@1255: }
fp@1255: }
fp@1255:
fp@1255: return 0;
fp@1255: }
fp@1255:
fp@1255: /*****************************************************************************/
fp@1255:
fp@1255: int ecrt_slave_config_reg_pdo_entry(
fp@1255: ec_slave_config_t *sc,
fp@1255: uint16_t index,
fp@1255: uint8_t subindex,
fp@1255: ec_domain_t *domain,
fp@1255: unsigned int *bit_position
fp@1255: )
fp@1255: {
fp@1255: ec_ioctl_reg_pdo_entry_t data;
fp@1255: int ret;
fp@1255:
fp@1255: data.config_index = sc->index;
fp@1255: data.entry_index = index;
fp@1255: data.entry_subindex = subindex;
fp@1255: data.domain_index = domain->index;
fp@1255:
fp@1255: ret = ioctl(sc->master->fd, EC_IOCTL_SC_REG_PDO_ENTRY, &data);
fp@1255: if (ret == -1) {
fp@1255: fprintf(stderr, "Failed to register Pdo entry: %s\n",
fp@1255: strerror(errno));
fp@1255: return -2;
fp@1255: }
fp@1255:
fp@1255: if (bit_position) {
fp@1255: *bit_position = data.bit_position;
fp@1255: } else {
fp@1255: if (data.bit_position) {
fp@1255: fprintf(stderr, "Pdo entry 0x%04X:%02X does not byte-align "
fp@1255: "in config %u:%u.\n", index, subindex,
fp@1255: sc->alias, sc->position);
fp@1255: return -3;
fp@1255: }
fp@1255: }
fp@1255:
fp@1255: return ret;
fp@1255: }
fp@1255:
fp@1255: /*****************************************************************************/
fp@1255:
fp@1255: int ecrt_slave_config_sdo(ec_slave_config_t *sc, uint16_t index,
fp@1255: uint8_t subindex, const uint8_t *sdo_data, size_t size)
fp@1255: {
fp@1255: ec_ioctl_sc_sdo_t data;
fp@1255:
fp@1255: data.config_index = sc->index;
fp@1255: data.index = index;
fp@1255: data.subindex = subindex;
fp@1255: data.data = sdo_data;
fp@1255: data.size = size;
fp@1255:
fp@1255: if (ioctl(sc->master->fd, EC_IOCTL_SC_REG_PDO_ENTRY, &data) == -1) {
fp@1255: fprintf(stderr, "Failed to configure Sdo.\n");
fp@1255: return -1;
fp@1255: }
fp@1255:
fp@1255: return 0;
fp@1255: }
fp@1255:
fp@1255: /*****************************************************************************/
fp@1255:
fp@1255: int ecrt_slave_config_sdo8(ec_slave_config_t *sc, uint16_t index,
fp@1255: uint8_t subindex, uint8_t value)
fp@1255: {
fp@1255: uint8_t data[1];
fp@1255:
fp@1255: EC_WRITE_U8(data, value);
fp@1255: return ecrt_slave_config_sdo(sc, index, subindex, data, 1);
fp@1255: }
fp@1255:
fp@1255: /*****************************************************************************/
fp@1255:
fp@1255: int ecrt_slave_config_sdo16(ec_slave_config_t *sc, uint16_t index,
fp@1255: uint8_t subindex, uint16_t value)
fp@1255: {
fp@1255: uint8_t data[2];
fp@1255:
fp@1255: EC_WRITE_U16(data, value);
fp@1255: return ecrt_slave_config_sdo(sc, index, subindex, data, 2);
fp@1255: }
fp@1255:
fp@1255: /*****************************************************************************/
fp@1255:
fp@1255: int ecrt_slave_config_sdo32(ec_slave_config_t *sc, uint16_t index,
fp@1255: uint8_t subindex, uint32_t value)
fp@1255: {
fp@1255: uint8_t data[4];
fp@1255:
fp@1255: EC_WRITE_U32(data, value);
fp@1255: return ecrt_slave_config_sdo(sc, index, subindex, data, 4);
fp@1255: }
fp@1255:
fp@1255: /*****************************************************************************/
fp@1255:
fp@1255: ec_sdo_request_t *ecrt_slave_config_create_sdo_request(ec_slave_config_t *sc,
fp@1255: uint16_t index, uint8_t subindex, size_t size)
fp@1255: {
fp@1259: return 0; // TODO
fp@1255: }
fp@1255:
fp@1255: /*****************************************************************************/
fp@1255:
fp@1255: ec_voe_handler_t *ecrt_slave_config_create_voe_handler(ec_slave_config_t *sc,
fp@1255: size_t size)
fp@1255: {
fp@1264: ec_ioctl_voe_t data;
fp@1264: ec_voe_handler_t *voe;
fp@1264: unsigned int index;
fp@1264:
fp@1264: voe = malloc(sizeof(ec_voe_handler_t));
fp@1264: if (!voe) {
fp@1264: fprintf(stderr, "Failed to allocate memory.\n");
fp@1264: return 0;
fp@1264: }
fp@1264:
fp@1264: if (size) {
fp@1264: voe->data = malloc(size);
fp@1264: if (!voe->data) {
fp@1264: fprintf(stderr, "Failed to allocate %u bytes of VoE data"
fp@1264: " memory.\n", size);
fp@1264: free(voe);
fp@1264: return 0;
fp@1264: }
fp@1264: } else {
fp@1264: voe->data = NULL;
fp@1264: }
fp@1264:
fp@1264: data.config_index = sc->index;
fp@1264: data.size = size;
fp@1264:
fp@1264: if (ioctl(sc->master->fd, EC_IOCTL_SC_VOE, &data) == -1) {
fp@1264: fprintf(stderr, "Failed to create VoE handler: %s\n",
fp@1264: strerror(errno));
fp@1264: if (voe->data)
fp@1264: free(voe->data);
fp@1264: free(voe);
fp@1264: return NULL;
fp@1264: }
fp@1264:
fp@1264: voe->config = sc;
fp@1264: voe->index = data.voe_index;
fp@1264: voe->data_size = size;
fp@1264: voe->mem_size = size;
fp@1264: return voe;
fp@1255: }
fp@1255:
fp@1255: /*****************************************************************************/
fp@1255:
fp@1255: void ecrt_slave_config_state(const ec_slave_config_t *sc,
fp@1255: ec_slave_config_state_t *state)
fp@1255: {
fp@1259: ec_ioctl_sc_state_t data;
fp@1259:
fp@1259: data.config_index = sc->index;
fp@1259: data.state = state;
fp@1259:
fp@1259: if (ioctl(sc->master->fd, EC_IOCTL_SC_STATE, &data) == -1) {
fp@1259: fprintf(stderr, "Failed to get slave configuration state: %s\n",
fp@1259: strerror(errno));
fp@1259: }
fp@1259: }
fp@1259:
fp@1259: /*****************************************************************************/