fp@1255: /****************************************************************************** fp@2421: * fp@1326: * $Id$ fp@2421: * fp@2433: * Copyright (C) 2006-2012 Florian Pose, Ingenieurgemeinschaft IgH fp@2421: * fp@1326: * This file is part of the IgH EtherCAT master userspace library. fp@2421: * fp@1326: * The IgH EtherCAT master userspace library is free software; you can fp@1326: * redistribute it and/or modify it under the terms of the GNU Lesser General fp@1326: * Public License as published by the Free Software Foundation; version 2.1 fp@1326: * of the License. fp@1287: * fp@1326: * The IgH EtherCAT master userspace library is distributed in the hope that fp@1326: * it will be useful, but WITHOUT ANY WARRANTY; without even the implied fp@1326: * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the fp@1326: * GNU Lesser General Public License for more details. fp@1287: * fp@1326: * You should have received a copy of the GNU Lesser General Public License fp@1326: * along with the IgH EtherCAT master userspace library. If not, see fp@1326: * . fp@2421: * fp@1363: * --- fp@2421: * fp@1363: * The license mentioned above concerns the source code only. Using the fp@1363: * EtherCAT technology and brand is only permitted in compliance with the fp@1363: * industrial property and similar rights of Beckhoff Automation GmbH. fp@1255: * fp@1255: *****************************************************************************/ fp@1255: fp@1255: #include fp@1255: #include fp@1255: #include fp@2433: #include /* ENOENT */ fp@2433: fp@2433: #include "ioctl.h" fp@1255: #include "slave_config.h" fp@1255: #include "domain.h" fp@1352: #include "sdo_request.h" fp@2443: #include "reg_request.h" fp@1264: #include "voe_handler.h" fp@1255: #include "master.h" fp@1255: fp@1255: /*****************************************************************************/ fp@1255: fp@1959: void ec_slave_config_clear(ec_slave_config_t *sc) fp@1959: { fp@1959: ec_sdo_request_t *r, *next_r; fp@2443: ec_reg_request_t *e, *next_e; fp@1959: ec_voe_handler_t *v, *next_v; fp@1959: fp@1959: r = sc->first_sdo_request; fp@1959: while (r) { fp@1959: next_r = r->next; fp@1959: ec_sdo_request_clear(r); fp@1959: r = next_r; fp@1959: } fp@1959: fp@2443: e = sc->first_reg_request; fp@2443: while (e) { fp@2443: next_e = e->next; fp@2443: ec_reg_request_clear(e); fp@2443: e = next_e; fp@2443: } fp@1959: fp@1959: v = sc->first_voe_handler; fp@1959: while (v) { fp@1959: next_v = v->next; fp@1959: ec_voe_handler_clear(v); fp@1959: v = next_v; fp@1959: } fp@1959: } fp@1959: fp@1959: /*****************************************************************************/ fp@1959: fp@1255: int ecrt_slave_config_sync_manager(ec_slave_config_t *sc, uint8_t sync_index, fp@1509: ec_direction_t dir, ec_watchdog_mode_t watchdog_mode) fp@1255: { fp@1255: ec_ioctl_config_t data; fp@2433: int ret; fp@1255: fp@1255: if (sync_index >= EC_MAX_SYNC_MANAGERS) fp@1313: return -ENOENT; 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@1509: data.syncs[sync_index].watchdog_mode = watchdog_mode; fp@1509: data.syncs[sync_index].config_this = 1; fp@1255: fp@2433: ret = ioctl(sc->master->fd, EC_IOCTL_SC_SYNC, &data); fp@2433: if (EC_IOCTL_IS_ERROR(ret)) { fp@1255: fprintf(stderr, "Failed to config sync manager: %s\n", fp@2433: strerror(EC_IOCTL_ERRNO(ret))); fp@2433: return -EC_IOCTL_ERRNO(ret); fp@1255: } fp@2421: fp@1255: return 0; fp@1255: } fp@1255: fp@1255: /*****************************************************************************/ fp@1255: fp@1509: void ecrt_slave_config_watchdog(ec_slave_config_t *sc, fp@1509: uint16_t divider, uint16_t intervals) fp@1509: { fp@1509: ec_ioctl_config_t data; fp@2433: int ret; fp@1509: fp@1509: memset(&data, 0x00, sizeof(ec_ioctl_config_t)); fp@1509: data.config_index = sc->index; fp@1509: data.watchdog_divider = divider; fp@1509: data.watchdog_intervals = intervals; fp@1509: fp@2433: ret = ioctl(sc->master->fd, EC_IOCTL_SC_WATCHDOG, &data); fp@2433: if (EC_IOCTL_IS_ERROR(ret)) { fp@1509: fprintf(stderr, "Failed to config watchdog: %s\n", fp@2433: strerror(EC_IOCTL_ERRNO(ret))); fp@1509: } fp@1509: } fp@1509: fp@1509: /*****************************************************************************/ fp@1509: 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@2433: int ret; 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@2433: ret = ioctl(sc->master->fd, EC_IOCTL_SC_ADD_PDO, &data); fp@2433: if (EC_IOCTL_IS_ERROR(ret)) { fp@1327: fprintf(stderr, "Failed to add PDO: %s\n", fp@2433: strerror(EC_IOCTL_ERRNO(ret))); fp@2433: return -EC_IOCTL_ERRNO(ret); fp@1255: } fp@2421: 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@2433: int ret; fp@1255: fp@1255: data.config_index = sc->index; fp@1255: data.sync_index = sync_index; fp@1255: fp@2433: ret = ioctl(sc->master->fd, EC_IOCTL_SC_CLEAR_PDOS, &data); fp@2433: if (EC_IOCTL_IS_ERROR(ret)) { fp@1327: fprintf(stderr, "Failed to clear PDOs: %s\n", fp@2433: strerror(EC_IOCTL_ERRNO(ret))); 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@2433: int ret; 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@2433: ret = ioctl(sc->master->fd, EC_IOCTL_SC_ADD_ENTRY, &data); fp@2433: if (EC_IOCTL_IS_ERROR(ret)) { fp@1327: fprintf(stderr, "Failed to add PDO entry: %s\n", fp@2433: strerror(EC_IOCTL_ERRNO(ret))); fp@2433: return -EC_IOCTL_ERRNO(ret); fp@1255: } fp@2421: 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@2433: int ret; fp@1255: fp@1255: data.config_index = sc->index; fp@1255: data.index = pdo_index; fp@1255: fp@2433: ret = ioctl(sc->master->fd, EC_IOCTL_SC_CLEAR_ENTRIES, &data); fp@2433: if (EC_IOCTL_IS_ERROR(ret)) { fp@1327: fprintf(stderr, "Failed to clear PDO entries: %s\n", fp@2433: strerror(EC_IOCTL_ERRNO(ret))); 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@1313: int ret; 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@1313: return -ENOENT; fp@1255: } fp@1255: fp@1509: ret = ecrt_slave_config_sync_manager(sc, sync_info->index, fp@1509: sync_info->dir, sync_info->watchdog_mode); fp@1313: if (ret) fp@1313: return ret; fp@1255: fp@2653: ecrt_slave_config_pdo_assign_clear(sc, sync_info->index); fp@2653: fp@1255: if (sync_info->n_pdos && sync_info->pdos) { fp@1255: fp@1255: for (j = 0; j < sync_info->n_pdos; j++) { fp@1255: pdo_info = &sync_info->pdos[j]; fp@1255: fp@1313: ret = ecrt_slave_config_pdo_assign_add( fp@1313: sc, sync_info->index, pdo_info->index); fp@1313: if (ret) fp@1313: return ret; fp@1255: fp@2655: ecrt_slave_config_pdo_mapping_clear(sc, pdo_info->index); fp@2655: fp@1255: if (pdo_info->n_entries && pdo_info->entries) { fp@1255: for (k = 0; k < pdo_info->n_entries; k++) { fp@1255: entry_info = &pdo_info->entries[k]; fp@1255: fp@1313: ret = ecrt_slave_config_pdo_mapping_add(sc, fp@1313: pdo_info->index, entry_info->index, fp@1313: entry_info->subindex, fp@1313: entry_info->bit_length); fp@1313: if (ret) fp@1313: return ret; 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@2433: if (EC_IOCTL_IS_ERROR(ret)) { fp@1327: fprintf(stderr, "Failed to register PDO entry: %s\n", fp@2433: strerror(EC_IOCTL_ERRNO(ret))); fp@2433: return -EC_IOCTL_ERRNO(ret); 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@1327: 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@2433: return -EFAULT; fp@1255: } fp@1255: } fp@1255: fp@1255: return ret; fp@1255: } fp@1255: fp@1255: /*****************************************************************************/ fp@1255: fp@2505: int ecrt_slave_config_reg_pdo_entry_pos( fp@2505: ec_slave_config_t *sc, fp@2505: uint8_t sync_index, fp@2505: unsigned int pdo_pos, fp@2505: unsigned int entry_pos, fp@2505: ec_domain_t *domain, fp@2505: unsigned int *bit_position fp@2505: ) fp@2505: { fp@2505: ec_ioctl_reg_pdo_pos_t io; fp@2505: int ret; fp@2505: fp@2505: io.config_index = sc->index; fp@2505: io.sync_index = sync_index; fp@2505: io.pdo_pos = pdo_pos; fp@2505: io.entry_pos = entry_pos; fp@2505: io.domain_index = domain->index; fp@2505: fp@2505: ret = ioctl(sc->master->fd, EC_IOCTL_SC_REG_PDO_POS, &io); fp@2505: if (EC_IOCTL_IS_ERROR(ret)) { fp@2505: fprintf(stderr, "Failed to register PDO entry: %s\n", fp@2505: strerror(EC_IOCTL_ERRNO(ret))); fp@2505: return -EC_IOCTL_ERRNO(ret); fp@2505: } fp@2505: fp@2505: if (bit_position) { fp@2505: *bit_position = io.bit_position; fp@2505: } else { fp@2505: if (io.bit_position) { fp@2505: fprintf(stderr, "PDO entry %u/%u/%u does not byte-align " fp@2505: "in config %u:%u.\n", sync_index, pdo_pos, entry_pos, fp@2505: sc->alias, sc->position); fp@2505: return -EFAULT; fp@2505: } fp@2505: } fp@2505: fp@2505: return ret; fp@2505: } fp@2505: fp@2505: /*****************************************************************************/ fp@2505: fp@1448: void ecrt_slave_config_dc(ec_slave_config_t *sc, uint16_t assign_activate, fp@2449: uint32_t sync0_cycle_time, int32_t sync0_shift_time, fp@2449: uint32_t sync1_cycle_time, int32_t sync1_shift_time) fp@1413: { fp@1455: ec_ioctl_config_t data; fp@2433: int ret; fp@1455: fp@1455: data.config_index = sc->index; fp@1455: data.dc_assign_activate = assign_activate; fp@1508: data.dc_sync[0].cycle_time = sync0_cycle_time; fp@1508: data.dc_sync[0].shift_time = sync0_shift_time; fp@1508: data.dc_sync[1].cycle_time = sync1_cycle_time; fp@1508: data.dc_sync[1].shift_time = sync1_shift_time; fp@1438: fp@2433: ret = ioctl(sc->master->fd, EC_IOCTL_SC_DC, &data); fp@2433: if (EC_IOCTL_IS_ERROR(ret)) { fp@2449: fprintf(stderr, "Failed to set DC parameters: %s\n", fp@2433: strerror(EC_IOCTL_ERRNO(ret))); fp@1413: } fp@1413: } fp@1413: fp@1413: /*****************************************************************************/ fp@1413: 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@2433: int ret; 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@1526: data.complete_access = 0; fp@1526: fp@2433: ret = ioctl(sc->master->fd, EC_IOCTL_SC_SDO, &data); fp@2433: if (EC_IOCTL_IS_ERROR(ret)) { fp@2433: fprintf(stderr, "Failed to configure SDO: %s\n", fp@2433: strerror(EC_IOCTL_ERRNO(ret))); fp@2433: return -EC_IOCTL_ERRNO(ret); fp@1526: } fp@1526: fp@1526: return 0; fp@1526: } fp@1526: fp@1526: /*****************************************************************************/ fp@1526: fp@1526: int ecrt_slave_config_complete_sdo(ec_slave_config_t *sc, uint16_t index, fp@1526: const uint8_t *sdo_data, size_t size) fp@1526: { fp@1526: ec_ioctl_sc_sdo_t data; fp@2433: int ret; fp@1526: fp@1526: data.config_index = sc->index; fp@1526: data.index = index; fp@1526: data.subindex = 0; fp@1526: data.data = sdo_data; fp@1526: data.size = size; fp@1526: data.complete_access = 1; fp@1255: fp@2433: ret = ioctl(sc->master->fd, EC_IOCTL_SC_SDO, &data); fp@2433: if (EC_IOCTL_IS_ERROR(ret)) { fp@2433: fprintf(stderr, "Failed to configure SDO: %s\n", fp@2433: strerror(EC_IOCTL_ERRNO(ret))); fp@2433: return -EC_IOCTL_ERRNO(ret); 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@2438: int ecrt_slave_config_emerg_size(ec_slave_config_t *sc, size_t elements) fp@2438: { fp@2438: ec_ioctl_sc_emerg_t io; fp@2438: int ret; fp@2438: fp@2438: io.config_index = sc->index; fp@2438: io.size = elements; fp@2438: fp@2438: ret = ioctl(sc->master->fd, EC_IOCTL_SC_EMERG_SIZE, &io); fp@2438: if (EC_IOCTL_IS_ERROR(ret)) { fp@2438: fprintf(stderr, "Failed to set emergency ring size: %s\n", fp@2438: strerror(EC_IOCTL_ERRNO(ret))); fp@2438: return -EC_IOCTL_ERRNO(ret); fp@2438: } fp@2438: fp@2438: return 0; fp@2438: } fp@2438: fp@2438: /*****************************************************************************/ fp@2438: fp@2438: int ecrt_slave_config_emerg_pop(ec_slave_config_t *sc, uint8_t *target) fp@2438: { fp@2438: ec_ioctl_sc_emerg_t io; fp@2438: int ret; fp@2438: fp@2438: io.config_index = sc->index; fp@2438: io.target = target; fp@2438: fp@2438: ret = ioctl(sc->master->fd, EC_IOCTL_SC_EMERG_POP, &io); fp@2438: if (EC_IOCTL_IS_ERROR(ret)) { fp@2507: if (EC_IOCTL_ERRNO(ret) != ENOENT) { fp@2507: fprintf(stderr, "Failed to get emergency message: %s\n", fp@2507: strerror(EC_IOCTL_ERRNO(ret))); fp@2507: } fp@2438: return -EC_IOCTL_ERRNO(ret); fp@2438: } fp@2438: fp@2438: return 0; fp@2438: } fp@2438: fp@2438: /*****************************************************************************/ fp@2438: fp@2438: int ecrt_slave_config_emerg_clear(ec_slave_config_t *sc) fp@2438: { fp@2438: ec_ioctl_sc_emerg_t io; fp@2438: int ret; fp@2438: fp@2438: io.config_index = sc->index; fp@2438: fp@2438: ret = ioctl(sc->master->fd, EC_IOCTL_SC_EMERG_CLEAR, &io); fp@2438: if (EC_IOCTL_IS_ERROR(ret)) { fp@2438: fprintf(stderr, "Failed to clear emergency ring: %s\n", fp@2438: strerror(EC_IOCTL_ERRNO(ret))); fp@2438: return -EC_IOCTL_ERRNO(ret); fp@2438: } fp@2438: fp@2438: return 0; fp@2438: } fp@2438: fp@2438: /*****************************************************************************/ fp@2438: fp@2438: int ecrt_slave_config_emerg_overruns(ec_slave_config_t *sc) fp@2438: { fp@2438: ec_ioctl_sc_emerg_t io; fp@2438: int ret; fp@2438: fp@2438: io.config_index = sc->index; fp@2438: fp@2438: ret = ioctl(sc->master->fd, EC_IOCTL_SC_EMERG_OVERRUNS, &io); fp@2438: if (EC_IOCTL_IS_ERROR(ret)) { fp@2438: fprintf(stderr, "Failed to get emergency overruns: %s\n", fp@2438: strerror(EC_IOCTL_ERRNO(ret))); fp@2438: return -EC_IOCTL_ERRNO(ret); fp@2438: } fp@2438: fp@2438: return io.overruns; fp@2438: } fp@2438: fp@2438: /*****************************************************************************/ fp@2438: fp@1959: void ec_slave_config_add_sdo_request(ec_slave_config_t *sc, fp@1959: ec_sdo_request_t *req) fp@1959: { fp@1959: if (sc->first_sdo_request) { fp@1959: ec_sdo_request_t *r = sc->first_sdo_request; fp@1959: while (r->next) { fp@1959: r = r->next; fp@1959: } fp@1959: r->next = req; fp@1959: } else { fp@1959: sc->first_sdo_request = req; fp@1959: } fp@1959: } fp@1959: fp@1959: /*****************************************************************************/ fp@1959: 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@1352: ec_ioctl_sdo_request_t data; fp@1352: ec_sdo_request_t *req; fp@2433: int ret; fp@1352: fp@1352: req = malloc(sizeof(ec_sdo_request_t)); fp@1352: if (!req) { fp@1352: fprintf(stderr, "Failed to allocate memory.\n"); fp@1352: return 0; fp@1352: } fp@1352: fp@1352: if (size) { fp@1352: req->data = malloc(size); fp@1352: if (!req->data) { fp@2480: fprintf(stderr, "Failed to allocate %zu bytes of SDO data" fp@1352: " memory.\n", size); fp@1352: free(req); fp@1352: return 0; fp@1352: } fp@1352: } else { fp@1352: req->data = NULL; fp@1352: } fp@1352: fp@1352: data.config_index = sc->index; fp@1352: data.sdo_index = index; fp@1352: data.sdo_subindex = subindex; fp@1352: data.size = size; fp@2421: fp@2433: ret = ioctl(sc->master->fd, EC_IOCTL_SC_SDO_REQUEST, &data); fp@2433: if (EC_IOCTL_IS_ERROR(ret)) { fp@1352: fprintf(stderr, "Failed to create SDO request: %s\n", fp@2433: strerror(EC_IOCTL_ERRNO(ret))); fp@1959: ec_sdo_request_clear(req); fp@1352: free(req); fp@2421: return NULL; fp@1352: } fp@1352: fp@1959: req->next = NULL; fp@1352: req->config = sc; fp@1352: req->index = data.request_index; fp@1352: req->sdo_index = data.sdo_index; fp@1352: req->sdo_subindex = data.sdo_subindex; fp@1352: req->data_size = size; fp@1352: req->mem_size = size; fp@1959: fp@1959: ec_slave_config_add_sdo_request(sc, req); fp@1959: fp@1352: return req; fp@1255: } fp@1255: fp@1255: /*****************************************************************************/ fp@1255: fp@2443: void ec_slave_config_add_reg_request(ec_slave_config_t *sc, fp@2443: ec_reg_request_t *reg) fp@2443: { fp@2443: if (sc->first_reg_request) { fp@2443: ec_reg_request_t *r = sc->first_reg_request; fp@2443: while (r->next) { fp@2443: r = r->next; fp@2443: } fp@2443: r->next = reg; fp@2443: } else { fp@2443: sc->first_reg_request = reg; fp@2443: } fp@2443: } fp@2443: fp@2443: /*****************************************************************************/ fp@2443: fp@2443: ec_reg_request_t *ecrt_slave_config_create_reg_request(ec_slave_config_t *sc, fp@2443: size_t size) fp@2443: { fp@2443: ec_ioctl_reg_request_t io; fp@2443: ec_reg_request_t *reg; fp@2443: int ret; fp@2443: fp@2443: reg = malloc(sizeof(ec_reg_request_t)); fp@2443: if (!reg) { fp@2443: fprintf(stderr, "Failed to allocate memory.\n"); fp@2443: return NULL; fp@2443: } fp@2443: fp@2443: if (size) { fp@2443: reg->data = malloc(size); fp@2443: if (!reg->data) { fp@2480: fprintf(stderr, "Failed to allocate %zu bytes of register data" fp@2443: " memory.\n", size); fp@2443: free(reg); fp@2443: return 0; fp@2443: } fp@2443: } else { fp@2443: reg->data = NULL; fp@2443: } fp@2443: fp@2443: io.config_index = sc->index; fp@2443: io.mem_size = size; fp@2443: fp@2443: ret = ioctl(sc->master->fd, EC_IOCTL_SC_REG_REQUEST, &io); fp@2443: if (EC_IOCTL_IS_ERROR(ret)) { fp@2443: fprintf(stderr, "Failed to create register request: %s\n", fp@2443: strerror(EC_IOCTL_ERRNO(ret))); fp@2443: ec_reg_request_clear(reg); fp@2443: free(reg); fp@2443: return NULL; fp@2443: } fp@2443: fp@2443: reg->next = NULL; fp@2443: reg->config = sc; fp@2443: reg->index = io.request_index; fp@2443: reg->mem_size = size; fp@2443: fp@2443: ec_slave_config_add_reg_request(sc, reg); fp@2443: fp@2443: return reg; fp@2443: } fp@2443: fp@2443: /*****************************************************************************/ fp@2443: fp@1959: void ec_slave_config_add_voe_handler(ec_slave_config_t *sc, fp@1959: ec_voe_handler_t *voe) fp@1959: { fp@1959: if (sc->first_voe_handler) { fp@1959: ec_voe_handler_t *v = sc->first_voe_handler; fp@1959: while (v->next) { fp@1959: v = v->next; fp@1959: } fp@1959: v->next = voe; fp@1959: } else { fp@1959: sc->first_voe_handler = voe; fp@1959: } fp@1959: } fp@1959: fp@1959: /*****************************************************************************/ fp@1959: 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@2433: int ret; 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@2480: fprintf(stderr, "Failed to allocate %zu 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@2421: fp@2433: ret = ioctl(sc->master->fd, EC_IOCTL_SC_VOE, &data); fp@2433: if (EC_IOCTL_IS_ERROR(ret)) { fp@1264: fprintf(stderr, "Failed to create VoE handler: %s\n", fp@2433: strerror(EC_IOCTL_ERRNO(ret))); fp@1959: ec_voe_handler_clear(voe); fp@1264: free(voe); fp@2421: return NULL; fp@1264: } fp@1264: fp@1959: voe->next = NULL; 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@1959: fp@1959: ec_slave_config_add_voe_handler(sc, voe); fp@1959: 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@2433: int ret; fp@1259: fp@1259: data.config_index = sc->index; fp@1259: data.state = state; fp@2421: fp@2433: ret = ioctl(sc->master->fd, EC_IOCTL_SC_STATE, &data); fp@2433: if (EC_IOCTL_IS_ERROR(ret)) { fp@1259: fprintf(stderr, "Failed to get slave configuration state: %s\n", fp@2433: strerror(EC_IOCTL_ERRNO(ret))); fp@1259: } fp@1259: } fp@1259: fp@1259: /*****************************************************************************/ fp@1862: fp@1952: int ecrt_slave_config_idn(ec_slave_config_t *sc, uint8_t drive_no, fp@1952: uint16_t idn, ec_al_state_t al_state, const uint8_t *data, size_t size) fp@1862: { fp@1862: ec_ioctl_sc_idn_t io; fp@2433: int ret; fp@1862: fp@1862: io.config_index = sc->index; fp@1952: io.drive_no = drive_no; fp@1862: io.idn = idn; fp@1945: io.al_state = al_state; fp@1862: io.data = data; fp@1862: io.size = size; fp@1862: fp@2433: ret = ioctl(sc->master->fd, EC_IOCTL_SC_IDN, &io); fp@2433: if (EC_IOCTL_IS_ERROR(ret)) { fp@2433: fprintf(stderr, "Failed to configure IDN: %s\n", fp@2433: strerror(EC_IOCTL_ERRNO(ret))); fp@2433: return -EC_IOCTL_ERRNO(ret); fp@2433: } fp@2433: fp@2433: return 0; fp@2433: } fp@2433: fp@2433: /*****************************************************************************/