fp@1122: /***************************************************************************** fp@1122: * fp@1363: * $Id$ fp@1363: * fp@1363: * Copyright (C) 2006-2009 Florian Pose, Ingenieurgemeinschaft IgH fp@1363: * fp@1363: * This file is part of the IgH EtherCAT Master. fp@1363: * fp@1363: * The IgH EtherCAT Master is free software; you can redistribute it and/or fp@1363: * modify it under the terms of the GNU General Public License version 2, as fp@1363: * published by the Free Software Foundation. fp@1363: * fp@1363: * The IgH EtherCAT Master is distributed in the hope that it will be useful, fp@1363: * but WITHOUT ANY WARRANTY; without even the implied warranty of fp@1363: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General fp@1363: * Public License for more details. fp@1363: * fp@1363: * You should have received a copy of the GNU General Public License along fp@1363: * with the IgH EtherCAT Master; if not, write to the Free Software fp@1363: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA fp@1363: * fp@1363: * --- fp@1363: * 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@1122: * fp@1122: ****************************************************************************/ fp@1122: fp@1122: #include fp@1122: #include fp@1122: #include fp@1122: #include fp@1222: #include fp@1238: #include fp@1122: fp@1122: #include fp@1126: #include fp@1122: using namespace std; fp@1122: fp@1122: #include "MasterDevice.h" fp@1122: fp@1122: /****************************************************************************/ fp@1122: fp@1826: MasterDevice::MasterDevice(unsigned int index): fp@1826: index(index), fp@1826: masterCount(0U), fp@1826: fd(-1) fp@1826: { fp@1122: } fp@1122: fp@1122: /****************************************************************************/ fp@1122: fp@1122: MasterDevice::~MasterDevice() fp@1122: { fp@1122: close(); fp@1122: } fp@1122: fp@1122: /****************************************************************************/ fp@1122: fp@1122: void MasterDevice::setIndex(unsigned int i) fp@1122: { fp@1122: index = i; fp@1122: } fp@1122: fp@1122: /****************************************************************************/ fp@1122: fp@1122: void MasterDevice::open(Permissions perm) fp@1122: { fp@1122: stringstream deviceName; fp@1122: fp@1126: if (fd == -1) { // not already open fp@1826: ec_ioctl_module_t module_data; fp@1804: deviceName << "/dev/EtherCAT" << index; fp@1804: fp@1804: if ((fd = ::open(deviceName.str().c_str(), fp@1804: perm == ReadWrite ? O_RDWR : O_RDONLY)) == -1) { fp@1804: stringstream err; fp@1804: err << "Failed to open master device " << deviceName.str() << ": " fp@1804: << strerror(errno); fp@1804: throw MasterDeviceException(err); fp@1804: } fp@1826: fp@1826: getModule(&module_data); fp@1826: if (module_data.ioctl_version_magic != EC_IOCTL_VERSION_MAGIC) { fp@1826: stringstream err; fp@1826: err << "ioctl() version magic is differing: " fp@1850: << deviceName.str() << ": " << module_data.ioctl_version_magic fp@1826: << ", ethercat tool: " << EC_IOCTL_VERSION_MAGIC; fp@1826: throw MasterDeviceException(err); fp@1826: } fp@1826: masterCount = module_data.master_count; fp@1122: } fp@1122: } fp@1122: fp@1122: /****************************************************************************/ fp@1122: fp@1122: void MasterDevice::close() fp@1122: { fp@1126: if (fd != -1) { fp@1804: ::close(fd); fp@1804: fd = -1; fp@1804: } fp@1126: } fp@1126: fp@1122: /****************************************************************************/ fp@1122: fp@1826: void MasterDevice::getModule(ec_ioctl_module_t *data) fp@1826: { fp@1826: if (ioctl(fd, EC_IOCTL_MODULE, data) < 0) { fp@1826: stringstream err; fp@1826: err << "Failed to get module information: " << strerror(errno); fp@1826: throw MasterDeviceException(err); fp@1826: } fp@1826: } fp@1826: fp@1826: /****************************************************************************/ fp@1826: fp@1122: void MasterDevice::getMaster(ec_ioctl_master_t *data) fp@1122: { fp@1122: if (ioctl(fd, EC_IOCTL_MASTER, data) < 0) { fp@1122: stringstream err; fp@1122: err << "Failed to get master information: " << strerror(errno); fp@1136: throw MasterDeviceException(err); fp@1122: } fp@1122: } fp@1122: fp@1122: /****************************************************************************/ fp@1122: fp@1122: void MasterDevice::getConfig(ec_ioctl_config_t *data, unsigned int index) fp@1122: { fp@1122: data->config_index = index; fp@1122: fp@1122: if (ioctl(fd, EC_IOCTL_CONFIG, data) < 0) { fp@1122: stringstream err; fp@1122: err << "Failed to get slave configuration: " << strerror(errno); fp@1136: throw MasterDeviceException(err); fp@1122: } fp@1122: } fp@1122: fp@1122: /****************************************************************************/ fp@1122: fp@1122: void MasterDevice::getConfigPdo( fp@1122: ec_ioctl_config_pdo_t *data, fp@1122: unsigned int index, fp@1122: uint8_t sync_index, fp@1122: uint16_t pdo_pos fp@1122: ) fp@1122: { fp@1122: data->config_index = index; fp@1122: data->sync_index = sync_index; fp@1122: data->pdo_pos = pdo_pos; fp@1122: fp@1122: if (ioctl(fd, EC_IOCTL_CONFIG_PDO, data) < 0) { fp@1122: stringstream err; fp@1327: err << "Failed to get slave config PDO: " << strerror(errno); fp@1136: throw MasterDeviceException(err); fp@1122: } fp@1122: } fp@1122: fp@1122: /****************************************************************************/ fp@1122: fp@1122: void MasterDevice::getConfigPdoEntry( fp@1122: ec_ioctl_config_pdo_entry_t *data, fp@1122: unsigned int index, fp@1122: uint8_t sync_index, fp@1122: uint16_t pdo_pos, fp@1122: uint8_t entry_pos fp@1122: ) fp@1122: { fp@1122: data->config_index = index; fp@1122: data->sync_index = sync_index; fp@1122: data->pdo_pos = pdo_pos; fp@1122: data->entry_pos = entry_pos; fp@1122: fp@1122: if (ioctl(fd, EC_IOCTL_CONFIG_PDO_ENTRY, data) < 0) { fp@1122: stringstream err; fp@1327: err << "Failed to get slave config PDO entry: " << strerror(errno); fp@1136: throw MasterDeviceException(err); fp@1122: } fp@1122: } fp@1122: fp@1122: /****************************************************************************/ fp@1122: fp@1122: void MasterDevice::getConfigSdo( fp@1122: ec_ioctl_config_sdo_t *data, fp@1122: unsigned int index, fp@1122: unsigned int sdo_pos fp@1122: ) fp@1122: { fp@1122: data->config_index = index; fp@1122: data->sdo_pos = sdo_pos; fp@1122: fp@1122: if (ioctl(fd, EC_IOCTL_CONFIG_SDO, data) < 0) { fp@1122: stringstream err; fp@1327: err << "Failed to get slave config SDO: " << strerror(errno); fp@1136: throw MasterDeviceException(err); fp@1122: } fp@1122: } fp@1122: fp@1122: /****************************************************************************/ fp@1122: fp@1966: void MasterDevice::getConfigIdn( fp@1966: ec_ioctl_config_idn_t *data, fp@1966: unsigned int index, fp@1966: unsigned int pos fp@1966: ) fp@1966: { fp@1966: data->config_index = index; fp@1966: data->idn_pos = pos; fp@1966: fp@1966: if (ioctl(fd, EC_IOCTL_CONFIG_IDN, data) < 0) { fp@1966: stringstream err; fp@1966: err << "Failed to get slave config IDN: " << strerror(errno); fp@1966: throw MasterDeviceException(err); fp@1966: } fp@1966: } fp@1966: fp@1966: /****************************************************************************/ fp@1966: fp@1122: void MasterDevice::getDomain(ec_ioctl_domain_t *data, unsigned int index) fp@1122: { fp@1122: data->index = index; fp@1122: fp@1122: if (ioctl(fd, EC_IOCTL_DOMAIN, data)) { fp@1122: stringstream err; fp@1122: err << "Failed to get domain: "; fp@1122: if (errno == EINVAL) fp@1122: err << "Domain " << index << " does not exist!"; fp@1122: else fp@1122: err << strerror(errno); fp@1136: throw MasterDeviceException(err); fp@1122: } fp@1122: } fp@1122: fp@1122: /****************************************************************************/ fp@1122: fp@1126: void MasterDevice::getData(ec_ioctl_domain_data_t *data, fp@1126: unsigned int domainIndex, unsigned int dataSize, unsigned char *mem) fp@1122: { fp@1122: data->domain_index = domainIndex; fp@1122: data->data_size = dataSize; fp@1122: data->target = mem; fp@1122: fp@1122: if (ioctl(fd, EC_IOCTL_DOMAIN_DATA, data) < 0) { fp@1122: stringstream err; fp@1122: err << "Failed to get domain data: " << strerror(errno); fp@1136: throw MasterDeviceException(err); fp@1122: } fp@1122: } fp@1122: fp@1122: /****************************************************************************/ fp@1122: fp@1122: void MasterDevice::getSlave(ec_ioctl_slave_t *slave, uint16_t slaveIndex) fp@1122: { fp@1122: slave->position = slaveIndex; fp@1122: fp@1122: if (ioctl(fd, EC_IOCTL_SLAVE, slave)) { fp@1122: stringstream err; fp@1122: err << "Failed to get slave: "; fp@1122: if (errno == EINVAL) fp@1122: err << "Slave " << slaveIndex << " does not exist!"; fp@1122: else fp@1122: err << strerror(errno); fp@1136: throw MasterDeviceException(err); fp@1122: } fp@1122: } fp@1122: fp@1122: /****************************************************************************/ fp@1122: fp@1122: void MasterDevice::getFmmu( fp@1122: ec_ioctl_domain_fmmu_t *fmmu, fp@1122: unsigned int domainIndex, fp@1122: unsigned int fmmuIndex fp@1122: ) fp@1122: { fp@1122: fmmu->domain_index = domainIndex; fp@1122: fmmu->fmmu_index = fmmuIndex; fp@1122: fp@1122: if (ioctl(fd, EC_IOCTL_DOMAIN_FMMU, fmmu)) { fp@1122: stringstream err; fp@1126: err << "Failed to get domain FMMU: " << strerror(errno); fp@1136: throw MasterDeviceException(err); fp@1122: } fp@1122: } fp@1122: fp@1122: /****************************************************************************/ fp@1122: fp@1122: void MasterDevice::getSync( fp@1122: ec_ioctl_slave_sync_t *sync, fp@1122: uint16_t slaveIndex, fp@1122: uint8_t syncIndex fp@1122: ) fp@1122: { fp@1122: sync->slave_position = slaveIndex; fp@1122: sync->sync_index = syncIndex; fp@1122: fp@1122: if (ioctl(fd, EC_IOCTL_SLAVE_SYNC, sync)) { fp@1122: stringstream err; fp@1126: err << "Failed to get sync manager: " << strerror(errno); fp@1136: throw MasterDeviceException(err); fp@1122: } fp@1122: } fp@1122: fp@1122: /****************************************************************************/ fp@1122: fp@1122: void MasterDevice::getPdo( fp@1122: ec_ioctl_slave_sync_pdo_t *pdo, fp@1122: uint16_t slaveIndex, fp@1122: uint8_t syncIndex, fp@1122: uint8_t pdoPos fp@1122: ) fp@1122: { fp@1122: pdo->slave_position = slaveIndex; fp@1122: pdo->sync_index = syncIndex; fp@1122: pdo->pdo_pos = pdoPos; fp@1122: fp@1122: if (ioctl(fd, EC_IOCTL_SLAVE_SYNC_PDO, pdo)) { fp@1122: stringstream err; fp@1327: err << "Failed to get PDO: " << strerror(errno); fp@1136: throw MasterDeviceException(err); fp@1122: } fp@1122: } fp@1122: fp@1122: /****************************************************************************/ fp@1122: fp@1122: void MasterDevice::getPdoEntry( fp@1122: ec_ioctl_slave_sync_pdo_entry_t *entry, fp@1122: uint16_t slaveIndex, fp@1122: uint8_t syncIndex, fp@1122: uint8_t pdoPos, fp@1122: uint8_t entryPos fp@1122: ) fp@1122: { fp@1122: entry->slave_position = slaveIndex; fp@1122: entry->sync_index = syncIndex; fp@1122: entry->pdo_pos = pdoPos; fp@1122: entry->entry_pos = entryPos; fp@1122: fp@1122: if (ioctl(fd, EC_IOCTL_SLAVE_SYNC_PDO_ENTRY, entry)) { fp@1122: stringstream err; fp@1327: err << "Failed to get PDO entry: " << strerror(errno); fp@1136: throw MasterDeviceException(err); fp@1122: } fp@1122: } fp@1122: fp@1122: /****************************************************************************/ fp@1122: fp@1122: void MasterDevice::getSdo( fp@1122: ec_ioctl_slave_sdo_t *sdo, fp@1122: uint16_t slaveIndex, fp@1122: uint16_t sdoPosition fp@1122: ) fp@1122: { fp@1122: sdo->slave_position = slaveIndex; fp@1122: sdo->sdo_position = sdoPosition; fp@1122: fp@1122: if (ioctl(fd, EC_IOCTL_SLAVE_SDO, sdo)) { fp@1122: stringstream err; fp@1327: err << "Failed to get SDO: " << strerror(errno); fp@1136: throw MasterDeviceException(err); fp@1122: } fp@1122: } fp@1122: fp@1122: /****************************************************************************/ fp@1122: fp@1122: void MasterDevice::getSdoEntry( fp@1122: ec_ioctl_slave_sdo_entry_t *entry, fp@1122: uint16_t slaveIndex, fp@1122: int sdoSpec, fp@1122: uint8_t entrySubindex fp@1122: ) fp@1122: { fp@1122: entry->slave_position = slaveIndex; fp@1122: entry->sdo_spec = sdoSpec; fp@1122: entry->sdo_entry_subindex = entrySubindex; fp@1122: fp@1122: if (ioctl(fd, EC_IOCTL_SLAVE_SDO_ENTRY, entry)) { fp@1122: stringstream err; fp@1327: err << "Failed to get SDO entry: " << strerror(errno); fp@1136: throw MasterDeviceException(err); fp@1122: } fp@1122: } fp@1122: fp@1122: /****************************************************************************/ fp@1122: fp@1122: void MasterDevice::readSii( fp@1122: ec_ioctl_slave_sii_t *data fp@1122: ) fp@1122: { fp@1122: if (ioctl(fd, EC_IOCTL_SLAVE_SII_READ, data) < 0) { fp@1122: stringstream err; fp@1122: err << "Failed to read SII: " << strerror(errno); fp@1136: throw MasterDeviceException(err); fp@1122: } fp@1122: } fp@1122: fp@1122: /****************************************************************************/ fp@1122: fp@1122: void MasterDevice::writeSii( fp@1122: ec_ioctl_slave_sii_t *data fp@1122: ) fp@1122: { fp@1122: if (ioctl(fd, EC_IOCTL_SLAVE_SII_WRITE, data) < 0) { fp@1122: stringstream err; fp@1122: err << "Failed to write SII: " << strerror(errno); fp@1136: throw MasterDeviceException(err); fp@1122: } fp@1122: } fp@1122: fp@1122: /****************************************************************************/ fp@1122: fp@1388: void MasterDevice::readReg( fp@1388: ec_ioctl_slave_reg_t *data fp@1388: ) fp@1388: { fp@1388: if (ioctl(fd, EC_IOCTL_SLAVE_REG_READ, data) < 0) { fp@1388: stringstream err; fp@1388: err << "Failed to read register: " << strerror(errno); fp@1388: throw MasterDeviceException(err); fp@1388: } fp@1388: } fp@1388: fp@1388: /****************************************************************************/ fp@1388: fp@1388: void MasterDevice::writeReg( fp@1388: ec_ioctl_slave_reg_t *data fp@1388: ) fp@1388: { fp@1388: if (ioctl(fd, EC_IOCTL_SLAVE_REG_WRITE, data) < 0) { fp@1388: stringstream err; fp@1388: err << "Failed to write register: " << strerror(errno); fp@1200: throw MasterDeviceException(err); fp@1200: } fp@1200: } fp@1200: fp@1200: /****************************************************************************/ fp@1200: fp@1335: void MasterDevice::readFoe( fp@1335: ec_ioctl_slave_foe_t *data fp@1335: ) fp@1335: { fp@1335: if (ioctl(fd, EC_IOCTL_SLAVE_FOE_READ, data) < 0) { fp@1335: stringstream err; fp@1335: err << "Failed to read via FoE: " << strerror(errno); fp@1335: throw MasterDeviceException(err); fp@1335: } fp@1335: } fp@1335: fp@1335: /****************************************************************************/ fp@1335: fp@1335: void MasterDevice::writeFoe( fp@1335: ec_ioctl_slave_foe_t *data fp@1335: ) fp@1335: { fp@1335: if (ioctl(fd, EC_IOCTL_SLAVE_FOE_WRITE, data) < 0) { fp@1335: stringstream err; fp@1335: err << "Failed to write via FoE: " << strerror(errno); fp@1335: throw MasterDeviceException(err); fp@1335: } fp@1335: } fp@1335: fp@1335: /****************************************************************************/ fp@1335: fp@1126: void MasterDevice::setDebug(unsigned int debugLevel) fp@1126: { fp@1126: if (ioctl(fd, EC_IOCTL_MASTER_DEBUG, debugLevel) < 0) { fp@1126: stringstream err; fp@1126: err << "Failed to set debug level: " << strerror(errno); fp@1136: throw MasterDeviceException(err); fp@1804: } fp@1126: } fp@1126: fp@1126: /****************************************************************************/ fp@1126: fp@1961: void MasterDevice::rescan() fp@1961: { fp@1961: if (ioctl(fd, EC_IOCTL_MASTER_RESCAN, 0) < 0) { fp@1961: stringstream err; fp@1961: err << "Failed to command rescan: " << strerror(errno); fp@1961: throw MasterDeviceException(err); fp@1961: } fp@1961: } fp@1961: fp@1961: /****************************************************************************/ fp@1961: fp@1126: void MasterDevice::sdoDownload(ec_ioctl_slave_sdo_download_t *data) fp@1126: { fp@1126: if (ioctl(fd, EC_IOCTL_SLAVE_SDO_DOWNLOAD, data) < 0) { fp@1126: stringstream err; fp@1126: if (errno == EIO && data->abort_code) { fp@1184: throw MasterDeviceSdoAbortException(data->abort_code); fp@1126: } else { fp@1327: err << "Failed to download SDO: " << strerror(errno); fp@1184: throw MasterDeviceException(err); fp@1126: } fp@1804: } fp@1126: } fp@1126: fp@1126: /****************************************************************************/ fp@1126: fp@1126: void MasterDevice::sdoUpload(ec_ioctl_slave_sdo_upload_t *data) fp@1126: { fp@1135: if (ioctl(fd, EC_IOCTL_SLAVE_SDO_UPLOAD, data) < 0) { fp@1126: stringstream err; fp@1126: if (errno == EIO && data->abort_code) { fp@1184: throw MasterDeviceSdoAbortException(data->abort_code); fp@1126: } else { fp@1327: err << "Failed to upload SDO: " << strerror(errno); fp@1184: throw MasterDeviceException(err); fp@1126: } fp@1126: } fp@1126: } fp@1126: fp@1126: /****************************************************************************/ fp@1126: fp@1122: void MasterDevice::requestState( fp@1122: uint16_t slavePosition, fp@1122: uint8_t state fp@1122: ) fp@1122: { fp@1122: ec_ioctl_slave_state_t data; fp@1122: fp@1122: data.slave_position = slavePosition; fp@1148: data.al_state = state; fp@2421: fp@1122: if (ioctl(fd, EC_IOCTL_SLAVE_STATE, &data)) { fp@1122: stringstream err; fp@1122: err << "Failed to request slave state: "; fp@1122: if (errno == EINVAL) fp@1122: err << "Slave " << slavePosition << " does not exist!"; fp@1122: else fp@1122: err << strerror(errno); fp@1136: throw MasterDeviceException(err); fp@1122: } fp@1122: } fp@1122: fp@1485: /****************************************************************************/ fp@1485: fp@1516: #ifdef EC_EOE fp@1516: fp@1485: void MasterDevice::getEoeHandler( fp@1485: ec_ioctl_eoe_handler_t *eoe, fp@1485: uint16_t eoeHandlerIndex fp@1485: ) fp@1485: { fp@1485: eoe->eoe_index = eoeHandlerIndex; fp@1485: fp@1485: if (ioctl(fd, EC_IOCTL_EOE_HANDLER, eoe)) { fp@1485: stringstream err; fp@1485: err << "Failed to get EoE handler: " << strerror(errno); fp@1485: throw MasterDeviceException(err); fp@1485: } fp@1485: } fp@1485: fp@1516: #endif fp@1516: fp@1831: /****************************************************************************/ fp@1831: fp@1837: void MasterDevice::readSoe(ec_ioctl_slave_soe_read_t *data) fp@1831: { fp@1831: if (ioctl(fd, EC_IOCTL_SLAVE_SOE_READ, data) < 0) { fp@1831: if (errno == EIO && data->error_code) { fp@1831: throw MasterDeviceSoeException(data->error_code); fp@1831: } else { fp@1835: stringstream err; fp@1835: err << "Failed to read IDN: " << strerror(errno); fp@1835: throw MasterDeviceException(err); fp@1835: } fp@1831: } fp@1831: } fp@1831: fp@1837: /****************************************************************************/ fp@1837: fp@1837: void MasterDevice::writeSoe(ec_ioctl_slave_soe_write_t *data) fp@1837: { fp@1837: if (ioctl(fd, EC_IOCTL_SLAVE_SOE_WRITE, data) < 0) { fp@1837: if (errno == EIO && data->error_code) { fp@1837: throw MasterDeviceSoeException(data->error_code); fp@1837: } else { fp@1837: stringstream err; fp@1837: err << "Failed to write IDN: " << strerror(errno); fp@1837: throw MasterDeviceException(err); fp@1837: } fp@1837: } fp@1837: } fp@1837: fp@1122: /*****************************************************************************/