fp@1255: /****************************************************************************** fp@1255: * fp@1255: * $Id$ fp@1255: * fp@1255: * Copyright (C) 2006 Florian Pose, Ingenieurgemeinschaft IgH fp@1255: * fp@1255: * This file is part of the IgH EtherCAT Master. fp@1255: * fp@1255: * The IgH EtherCAT Master is free software; you can redistribute it fp@1255: * and/or modify it under the terms of the GNU General Public License fp@1255: * as published by the Free Software Foundation; either version 2 of the fp@1255: * License, or (at your option) any later version. fp@1255: * fp@1255: * The IgH EtherCAT Master is distributed in the hope that it will be fp@1255: * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of fp@1255: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the fp@1255: * GNU General Public License for more details. fp@1255: * fp@1255: * You should have received a copy of the GNU General Public License fp@1255: * along with the IgH EtherCAT Master; if not, write to the Free Software fp@1255: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA fp@1255: * fp@1255: * The right to use EtherCAT Technology is granted and comes free of fp@1255: * charge under condition of compatibility of product made by fp@1255: * Licensee. People intending to distribute/sell products based on the fp@1255: * code, have to sign an agreement to guarantee that products using fp@1255: * software based on IgH EtherCAT master stay compatible with the actual fp@1255: * EtherCAT specification (which are released themselves as an open fp@1255: * standard) as the (only) precondition to have the right to use EtherCAT fp@1255: * 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: /*****************************************************************************/