fp@922: /***************************************************************************** fp@922: * fp@922: * $Id$ fp@922: * fp@922: ****************************************************************************/ fp@922: fp@922: #include fp@922: #include fp@922: #include fp@922: #include fp@922: #include fp@922: fp@922: #include fp@922: #include fp@922: #include fp@960: #include // toupper() fp@922: using namespace std; fp@922: fp@922: #include "Master.h" fp@922: fp@974: #define swap16(x) \ fp@968: ((uint16_t)( \ fp@968: (((uint16_t)(x) & 0x00ffU) << 8) | \ fp@968: (((uint16_t)(x) & 0xff00U) >> 8) )) fp@974: #define swap32(x) \ fp@968: ((uint32_t)( \ fp@968: (((uint32_t)(x) & 0x000000ffUL) << 24) | \ fp@968: (((uint32_t)(x) & 0x0000ff00UL) << 8) | \ fp@968: (((uint32_t)(x) & 0x00ff0000UL) >> 8) | \ fp@968: (((uint32_t)(x) & 0xff000000UL) >> 24) )) fp@968: fp@974: #if __BYTE_ORDER == __LITTLE_ENDIAN fp@974: fp@974: #define le16tocpu(x) x fp@974: #define le32tocpu(x) x fp@974: fp@974: #define cputole16(x) x fp@974: #define cputole32(x) x fp@974: fp@974: #elif __BYTE_ORDER == __BIG_ENDIAN fp@974: fp@974: #define le16tocpu(x) swap16(x) fp@974: #define le32tocpu(x) swap32(x) fp@974: fp@974: #define cputole16(x) swap16(x) fp@974: #define cputole32(x) swap32(x) fp@974: fp@968: #endif fp@968: fp@968: /****************************************************************************/ fp@968: fp@968: struct CoEDataType { fp@968: const char *name; fp@968: uint16_t coeCode; fp@968: unsigned int byteSize; fp@968: }; fp@968: fp@968: static const CoEDataType dataTypes[] = { fp@968: {"int8", 0x0002, 1}, fp@968: {"int16", 0x0003, 2}, fp@968: {"int32", 0x0004, 4}, fp@968: {"uint8", 0x0005, 1}, fp@968: {"uint16", 0x0006, 2}, fp@968: {"uint32", 0x0007, 4}, fp@968: {"string", 0x0009, 0}, fp@968: {"raw", 0xffff, 0}, fp@968: {} fp@968: }; fp@968: fp@968: /****************************************************************************/ fp@968: fp@968: const CoEDataType *findDataType(const string &str) fp@968: { fp@968: const CoEDataType *d; fp@968: fp@968: for (d = dataTypes; d->name; d++) fp@968: if (str == d->name) fp@968: return d; fp@968: fp@968: return NULL; fp@968: } fp@968: fp@968: /****************************************************************************/ fp@968: fp@968: const CoEDataType *findDataType(uint16_t code) fp@968: { fp@968: const CoEDataType *d; fp@968: fp@968: for (d = dataTypes; d->name; d++) fp@968: if (code == d->coeCode) fp@968: return d; fp@968: fp@968: return NULL; fp@968: } fp@968: fp@922: /****************************************************************************/ fp@922: fp@922: Master::Master() fp@922: { fp@922: index = 0; fp@922: fd = -1; fp@972: currentPermissions = Read; fp@922: } fp@922: fp@922: /****************************************************************************/ fp@922: fp@922: Master::~Master() fp@922: { fp@922: close(); fp@922: } fp@922: fp@922: /****************************************************************************/ fp@922: fp@972: void Master::setIndex(unsigned int i) fp@972: { fp@972: index = i; fp@922: } fp@922: fp@922: /****************************************************************************/ fp@922: fp@949: void Master::outputData(int domainIndex) fp@949: { fp@972: open(Read); fp@972: fp@949: if (domainIndex == -1) { fp@949: unsigned int numDomains = domainCount(), i; fp@949: fp@949: for (i = 0; i < numDomains; i++) { fp@949: outputDomainData(i); fp@949: } fp@949: } else { fp@949: outputDomainData(domainIndex); fp@949: } fp@949: } fp@949: fp@949: /****************************************************************************/ fp@949: fp@956: void Master::setDebug(const vector &commandArgs) fp@956: { fp@956: stringstream str; fp@956: int debugLevel; fp@956: fp@956: if (commandArgs.size() != 1) { fp@956: stringstream err; fp@956: err << "'debug' takes exactly one argument!"; fp@956: throw MasterException(err.str()); fp@956: } fp@956: fp@956: str << commandArgs[0]; fp@956: str >> debugLevel; fp@956: fp@956: if (str.fail()) { fp@956: stringstream err; fp@956: err << "Invalid debug level '" << commandArgs[0] << "'!"; fp@956: throw MasterException(err.str()); fp@956: } fp@956: fp@972: open(ReadWrite); fp@972: fp@957: if (ioctl(fd, EC_IOCTL_SET_DEBUG, debugLevel) < 0) { fp@956: stringstream err; fp@956: err << "Failed to set debug level: " << strerror(errno); fp@956: throw MasterException(err.str()); fp@956: } fp@956: } fp@956: fp@956: /****************************************************************************/ fp@956: fp@948: void Master::showDomains(int domainIndex) fp@948: { fp@972: open(Read); fp@972: fp@948: if (domainIndex == -1) { fp@948: unsigned int numDomains = domainCount(), i; fp@948: fp@948: for (i = 0; i < numDomains; i++) { fp@948: showDomain(i); fp@948: } fp@948: } else { fp@948: showDomain(domainIndex); fp@948: } fp@948: } fp@948: fp@948: /****************************************************************************/ fp@948: fp@922: void Master::listSlaves() fp@922: { fp@972: unsigned int numSlaves, i; fp@935: ec_ioctl_slave_t slave; fp@922: uint16_t lastAlias, aliasIndex; fp@922: fp@972: open(Read); fp@972: fp@972: numSlaves = slaveCount(); fp@972: fp@922: lastAlias = 0; fp@922: aliasIndex = 0; fp@922: for (i = 0; i < numSlaves; i++) { fp@935: getSlave(&slave, i); fp@935: cout << setw(2) << i << " "; fp@935: fp@935: if (slave.alias) { fp@935: lastAlias = slave.alias; fp@922: aliasIndex = 0; fp@922: } fp@922: if (lastAlias) { fp@922: cout << setw(10) << "#" << lastAlias << ":" << aliasIndex; fp@922: } fp@922: fp@935: cout << " " << slaveState(slave.state) << " "; fp@935: fp@935: if (strlen(slave.name)) { fp@935: cout << slave.name; fp@922: } else { fp@935: cout << "0x" << hex << setfill('0') << slave.vendor_id fp@935: << ":0x" << slave.product_code; fp@922: } fp@922: fp@922: cout << endl; fp@922: } fp@935: } fp@935: fp@935: /****************************************************************************/ fp@935: fp@957: void Master::showMaster() fp@957: { fp@957: ec_ioctl_master_t data; fp@957: stringstream err; fp@957: unsigned int i; fp@957: fp@972: open(Read); fp@957: getMaster(&data); fp@957: fp@957: cout fp@957: << "Master" << index << endl fp@957: << " State: "; fp@957: fp@957: switch (data.mode) { fp@957: case 0: cout << "Waiting for device..."; break; fp@957: case 1: cout << "Idle"; break; fp@957: case 2: cout << "Operation"; break; fp@957: default: fp@957: err << "Invalid master state " << data.mode; fp@957: throw MasterException(err.str()); fp@957: } fp@957: fp@957: cout << endl fp@957: << " Slaves: " << data.slave_count << endl; fp@957: fp@957: for (i = 0; i < 2; i++) { fp@957: cout << " Device" << i << ": "; fp@957: if (data.devices[i].address[0] == 0x00 fp@957: && data.devices[i].address[1] == 0x00 fp@957: && data.devices[i].address[2] == 0x00 fp@957: && data.devices[i].address[3] == 0x00 fp@957: && data.devices[i].address[4] == 0x00 fp@957: && data.devices[i].address[5] == 0x00) { fp@957: cout << "None."; fp@957: } else { fp@957: cout << hex << setfill('0') fp@957: << setw(2) << (unsigned int) data.devices[i].address[0] << ":" fp@957: << setw(2) << (unsigned int) data.devices[i].address[1] << ":" fp@957: << setw(2) << (unsigned int) data.devices[i].address[2] << ":" fp@957: << setw(2) << (unsigned int) data.devices[i].address[3] << ":" fp@957: << setw(2) << (unsigned int) data.devices[i].address[4] << ":" fp@957: << setw(2) << (unsigned int) data.devices[i].address[5] << " (" fp@957: << (data.devices[i].attached ? "attached" : "waiting...") fp@957: << ")" << endl << dec fp@957: << " Tx count: " << data.devices[i].tx_count << endl fp@957: << " Rx count: " << data.devices[i].rx_count; fp@957: } fp@957: cout << endl; fp@957: } fp@957: } fp@957: fp@957: /****************************************************************************/ fp@957: fp@966: void Master::listPdos(int slavePosition, bool quiet) fp@935: { fp@972: open(Read); fp@972: fp@936: if (slavePosition == -1) { fp@936: unsigned int numSlaves = slaveCount(), i; fp@936: fp@936: for (i = 0; i < numSlaves; i++) { fp@966: listSlavePdos(i, quiet, true); fp@936: } fp@936: } else { fp@966: listSlavePdos(slavePosition, quiet, false); fp@966: } fp@966: } fp@966: fp@966: /****************************************************************************/ fp@966: fp@966: void Master::listSdos(int slavePosition, bool quiet) fp@965: { fp@972: open(Read); fp@972: fp@965: if (slavePosition == -1) { fp@965: unsigned int numSlaves = slaveCount(), i; fp@965: fp@965: for (i = 0; i < numSlaves; i++) { fp@966: listSlaveSdos(i, quiet, true); fp@965: } fp@965: } else { fp@966: listSlaveSdos(slavePosition, quiet, false); fp@965: } fp@965: } fp@965: fp@965: /****************************************************************************/ fp@965: fp@974: void Master::sdoDownload( fp@974: int slavePosition, fp@974: const string &dataTypeStr, fp@974: const vector &commandArgs fp@974: ) fp@974: { fp@974: stringstream strIndex, strSubIndex, strValue, err; fp@974: int number, sval; fp@974: ec_ioctl_sdo_download_t data; fp@974: unsigned int i, uval; fp@974: const CoEDataType *dataType = NULL; fp@974: fp@974: if (slavePosition < 0) { fp@974: err << "'sdo_download' requires a slave! Please specify --slave."; fp@974: throw MasterException(err.str()); fp@974: } fp@974: data.slave_position = slavePosition; fp@974: fp@974: if (commandArgs.size() != 3) { fp@974: err << "'sdo_download' takes 3 arguments!"; fp@974: throw MasterException(err.str()); fp@974: } fp@974: fp@974: strIndex << commandArgs[0]; fp@974: strIndex >> hex >> number; fp@974: if (strIndex.fail() || number < 0x0000 || number > 0xffff) { fp@974: err << "Invalid Sdo index '" << commandArgs[0] << "'!"; fp@974: throw MasterException(err.str()); fp@974: } fp@974: data.sdo_index = number; fp@974: fp@974: strSubIndex << commandArgs[1]; fp@974: strSubIndex >> hex >> number; fp@974: if (strSubIndex.fail() || number < 0x00 || number > 0xff) { fp@974: err << "Invalid Sdo subindex '" << commandArgs[1] << "'!"; fp@974: throw MasterException(err.str()); fp@974: } fp@974: data.sdo_entry_subindex = number; fp@974: fp@974: if (dataTypeStr != "") { // data type specified fp@974: if (!(dataType = findDataType(dataTypeStr))) { fp@974: err << "Invalid data type '" << dataTypeStr << "'!"; fp@974: throw MasterException(err.str()); fp@974: } fp@974: } else { // no data type specified: fetch from dictionary fp@974: ec_ioctl_sdo_entry_t entry; fp@974: unsigned int entryByteSize; fp@974: fp@974: open(Read); fp@974: fp@974: try { fp@974: getSdoEntry(&entry, slavePosition, fp@974: data.sdo_index, data.sdo_entry_subindex); fp@974: } catch (MasterException &e) { fp@974: err << "Failed to determine Sdo entry data type. " fp@974: << "Please specify --type."; fp@974: throw MasterException(err.str()); fp@974: } fp@974: if (!(dataType = findDataType(entry.data_type))) { fp@974: err << "Pdo entry has unknown data type 0x" fp@974: << hex << setfill('0') << setw(4) << entry.data_type << "!" fp@974: << " Please specify --type."; fp@974: throw MasterException(err.str()); fp@974: } fp@974: } fp@974: fp@974: if (dataType->byteSize) { fp@974: data.data_size = dataType->byteSize; fp@974: } else { fp@974: data.data_size = DefaultBufferSize; fp@974: } fp@974: fp@974: data.data = new uint8_t[data.data_size + 1]; fp@974: fp@974: strValue << commandArgs[2]; fp@974: fp@974: switch (dataType->coeCode) { fp@974: case 0x0002: // int8 fp@974: strValue >> sval; fp@974: if ((uint32_t) sval > 0xff) { fp@974: delete [] data.data; fp@974: err << "Invalid value for type '" fp@974: << dataType->name << "'!"; fp@974: throw MasterException(err.str()); fp@974: } fp@974: *data.data = (int8_t) sval; fp@974: break; fp@974: case 0x0003: // int16 fp@974: strValue >> sval; fp@974: if ((uint32_t) sval > 0xffff) { fp@974: delete [] data.data; fp@974: err << "Invalid value for type '" fp@974: << dataType->name << "'!"; fp@974: throw MasterException(err.str()); fp@974: } fp@974: *(int16_t *) data.data = cputole16(sval); fp@974: break; fp@974: case 0x0004: // int32 fp@974: strValue >> sval; fp@974: *(int32_t *) data.data = cputole32(sval); fp@974: break; fp@974: case 0x0005: // uint8 fp@974: strValue >> uval; fp@974: if ((uint32_t) uval > 0xff) { fp@974: delete [] data.data; fp@974: err << "Invalid value for type '" fp@974: << dataType->name << "'!"; fp@974: throw MasterException(err.str()); fp@974: } fp@974: *data.data = (uint8_t) uval; fp@974: break; fp@974: case 0x0006: // uint16 fp@974: strValue >> uval; fp@974: if ((uint32_t) uval > 0xffff) { fp@974: delete [] data.data; fp@974: err << "Invalid value for type '" fp@974: << dataType->name << "'!"; fp@974: throw MasterException(err.str()); fp@974: } fp@974: *(uint16_t *) data.data = cputole16(uval); fp@974: break; fp@974: case 0x0007: // uint32 fp@974: strValue >> uval; fp@974: *(uint32_t *) data.data = cputole32(uval); fp@974: break; fp@974: case 0x0009: // string fp@974: if (strValue.str().size() >= data.data_size) { fp@974: err << "String too big"; fp@974: throw MasterException(err.str()); fp@974: } fp@974: data.data_size = strValue.str().size(); fp@974: strValue >> (char *) data.data; fp@974: break; fp@974: default: fp@974: break; fp@974: } fp@974: fp@974: if (strValue.fail()) { fp@974: err << "Invalid value argument '" << commandArgs[2] << "'!"; fp@974: throw MasterException(err.str()); fp@974: } fp@974: fp@974: open(ReadWrite); fp@974: fp@974: if (ioctl(fd, EC_IOCTL_SDO_DOWNLOAD, &data) < 0) { fp@974: stringstream err; fp@974: err << "Failed to download Sdo: " << strerror(errno); fp@974: delete [] data.data; fp@974: throw MasterException(err.str()); fp@974: } fp@974: fp@974: delete [] data.data; fp@974: } fp@974: fp@974: /****************************************************************************/ fp@974: fp@968: void Master::sdoUpload( fp@968: int slavePosition, fp@968: const string &dataTypeStr, fp@968: const vector &commandArgs fp@968: ) fp@968: { fp@968: stringstream strIndex, strSubIndex; fp@968: int number, sval; fp@968: ec_ioctl_sdo_upload_t data; fp@968: unsigned int i, uval; fp@968: const CoEDataType *dataType = NULL; fp@968: fp@968: if (slavePosition < 0) { fp@968: stringstream err; fp@968: err << "'sdo_upload' requires a slave! Please specify --slave."; fp@968: throw MasterException(err.str()); fp@968: } fp@968: data.slave_position = slavePosition; fp@968: fp@968: if (commandArgs.size() != 2) { fp@968: stringstream err; fp@968: err << "'sdo_upload' takes two arguments!"; fp@968: throw MasterException(err.str()); fp@968: } fp@968: fp@968: strIndex << commandArgs[0]; fp@968: strIndex >> hex >> number; fp@968: if (strIndex.fail() || number < 0x0000 || number > 0xffff) { fp@968: stringstream err; fp@968: err << "Invalid Sdo index '" << commandArgs[0] << "'!"; fp@968: throw MasterException(err.str()); fp@968: } fp@968: data.sdo_index = number; fp@968: fp@968: strSubIndex << commandArgs[1]; fp@968: strSubIndex >> hex >> number; fp@968: if (strSubIndex.fail() || number < 0x00 || number > 0xff) { fp@968: stringstream err; fp@968: err << "Invalid Sdo subindex '" << commandArgs[1] << "'!"; fp@968: throw MasterException(err.str()); fp@968: } fp@968: data.sdo_entry_subindex = number; fp@968: fp@968: if (dataTypeStr != "") { // data type specified fp@968: if (!(dataType = findDataType(dataTypeStr))) { fp@968: stringstream err; fp@968: err << "Invalid data type '" << dataTypeStr << "'!"; fp@968: throw MasterException(err.str()); fp@968: } fp@968: } else { // no data type specified: fetch from dictionary fp@968: ec_ioctl_sdo_entry_t entry; fp@968: unsigned int entryByteSize; fp@972: fp@972: open(Read); fp@972: fp@968: try { fp@968: getSdoEntry(&entry, slavePosition, fp@968: data.sdo_index, data.sdo_entry_subindex); fp@968: } catch (MasterException &e) { fp@968: stringstream err; fp@968: err << "Failed to determine Sdo entry data type. " fp@968: << "Please specify --type."; fp@968: throw MasterException(err.str()); fp@968: } fp@968: if (!(dataType = findDataType(entry.data_type))) { fp@968: stringstream err; fp@968: err << "Pdo entry has unknown data type 0x" fp@968: << hex << setfill('0') << setw(4) << entry.data_type << "!" fp@968: << " Please specify --type."; fp@968: throw MasterException(err.str()); fp@968: } fp@968: } fp@968: fp@968: if (dataType->byteSize) { fp@968: data.target_size = dataType->byteSize; fp@968: } else { fp@974: data.target_size = DefaultBufferSize; fp@968: } fp@968: fp@968: data.target = new uint8_t[data.target_size + 1]; fp@968: fp@972: open(Read); fp@972: fp@968: if (ioctl(fd, EC_IOCTL_SDO_UPLOAD, &data) < 0) { fp@968: stringstream err; fp@968: err << "Failed to upload Sdo: " << strerror(errno); fp@968: delete [] data.target; fp@972: close(); fp@972: throw MasterException(err.str()); fp@972: } fp@972: fp@972: close(); fp@968: fp@968: if (dataType->byteSize && data.data_size != dataType->byteSize) { fp@968: stringstream err; fp@968: err << "Data type mismatch. Expected " << dataType->name fp@970: << " with " << dataType->byteSize << " byte, but got " fp@970: << data.data_size << " byte."; fp@968: throw MasterException(err.str()); fp@968: } fp@968: fp@968: cout << setfill('0'); fp@968: switch (dataType->coeCode) { fp@968: case 0x0002: // int8 fp@968: sval = *(int8_t *) data.target; fp@968: cout << sval << " 0x" << hex << setw(2) << sval << endl; fp@968: break; fp@968: case 0x0003: // int16 fp@968: sval = le16tocpu(*(int16_t *) data.target); fp@968: cout << sval << " 0x" << hex << setw(4) << sval << endl; fp@968: break; fp@968: case 0x0004: // int32 fp@968: sval = le32tocpu(*(int32_t *) data.target); fp@968: cout << sval << " 0x" << hex << setw(8) << sval << endl; fp@968: break; fp@968: case 0x0005: // uint8 fp@968: uval = (unsigned int) *(uint8_t *) data.target; fp@968: cout << uval << " 0x" << hex << setw(2) << uval << endl; fp@968: break; fp@968: case 0x0006: // uint16 fp@968: uval = le16tocpu(*(uint16_t *) data.target); fp@968: cout << uval << " 0x" << hex << setw(4) << uval << endl; fp@968: break; fp@968: case 0x0007: // uint32 fp@968: uval = le32tocpu(*(uint32_t *) data.target); fp@968: cout << uval << " 0x" << hex << setw(8) << uval << endl; fp@968: break; fp@968: case 0x0009: // string fp@968: cout << string((const char *) data.target, data.data_size) fp@968: << endl; fp@968: break; fp@968: default: fp@968: printRawData(data.target, data.data_size); fp@968: break; fp@968: } fp@968: fp@968: delete [] data.target; fp@968: } fp@968: fp@968: /****************************************************************************/ fp@968: fp@960: void Master::requestStates( fp@960: int slavePosition, fp@960: const vector &commandArgs fp@960: ) fp@960: { fp@960: string stateStr; fp@960: uint8_t state; fp@960: fp@960: if (commandArgs.size() != 1) { fp@960: stringstream err; fp@960: err << "'state' takes exactly one argument!"; fp@960: throw MasterException(err.str()); fp@960: } fp@960: fp@960: stateStr = commandArgs[0]; fp@960: transform(stateStr.begin(), stateStr.end(), fp@960: stateStr.begin(), (int (*) (int)) std::toupper); fp@960: fp@960: if (stateStr == "INIT") { fp@960: state = 0x01; fp@960: } else if (stateStr == "PREOP") { fp@960: state = 0x02; fp@960: } else if (stateStr == "SAFEOP") { fp@960: state = 0x04; fp@960: } else if (stateStr == "OP") { fp@960: state = 0x08; fp@960: } else { fp@960: stringstream err; fp@960: err << "Invalid state '" << commandArgs[0] << "'!"; fp@960: throw MasterException(err.str()); fp@960: } fp@960: fp@972: open(ReadWrite); fp@972: fp@960: if (slavePosition == -1) { fp@960: unsigned int i, numSlaves = slaveCount(); fp@960: for (i = 0; i < numSlaves; i++) fp@960: requestState(i, state); fp@960: } else { fp@960: requestState(slavePosition, state); fp@960: } fp@960: } fp@960: fp@960: /****************************************************************************/ fp@960: fp@938: void Master::generateXml(int slavePosition) fp@938: { fp@972: open(Read); fp@972: fp@938: if (slavePosition == -1) { fp@938: unsigned int numSlaves = slaveCount(), i; fp@938: fp@938: for (i = 0; i < numSlaves; i++) { fp@938: generateSlaveXml(i); fp@938: } fp@938: } else { fp@938: generateSlaveXml(slavePosition); fp@938: } fp@938: } fp@938: fp@938: /****************************************************************************/ fp@938: fp@972: void Master::open(Permissions perm) fp@972: { fp@972: stringstream deviceName; fp@972: fp@972: if (fd != -1) { // already open fp@972: if (currentPermissions < perm) { // more permissions required fp@972: close(); fp@972: } else { fp@972: return; fp@972: } fp@972: } fp@972: fp@972: deviceName << "/dev/EtherCAT" << index; fp@972: fp@972: if ((fd = ::open(deviceName.str().c_str(), fp@972: perm == ReadWrite ? O_RDWR : O_RDONLY)) == -1) { fp@972: stringstream err; fp@972: err << "Failed to open master device " << deviceName.str() << ": " fp@972: << strerror(errno); fp@972: throw MasterException(err.str()); fp@972: } fp@972: fp@972: currentPermissions = perm; fp@972: } fp@972: fp@972: /****************************************************************************/ fp@972: fp@972: void Master::close() fp@972: { fp@972: if (fd == -1) fp@972: return; fp@972: fp@972: ::close(fd); fp@972: } fp@972: fp@972: /****************************************************************************/ fp@972: fp@949: void Master::outputDomainData(unsigned int domainIndex) fp@949: { fp@949: ec_ioctl_domain_t domain; fp@949: ec_ioctl_data_t data; fp@949: unsigned char *processData; fp@949: unsigned int i; fp@949: fp@949: getDomain(&domain, domainIndex); fp@949: fp@950: if (!domain.data_size) fp@950: return; fp@950: fp@949: processData = new unsigned char[domain.data_size]; fp@949: fp@950: try { fp@950: getData(&data, domainIndex, domain.data_size, processData); fp@950: } catch (MasterException &e) { fp@949: delete [] processData; fp@950: throw e; fp@949: } fp@949: fp@949: for (i = 0; i < data.data_size; i++) fp@949: cout << processData[i]; fp@949: cout.flush(); fp@949: fp@949: delete [] processData; fp@949: } fp@949: fp@949: /****************************************************************************/ fp@949: fp@948: void Master::showDomain(unsigned int domainIndex) fp@948: { fp@950: ec_ioctl_domain_t domain; fp@950: unsigned char *processData; fp@950: ec_ioctl_data_t data; fp@950: unsigned int i, j; fp@950: ec_ioctl_domain_fmmu_t fmmu; fp@950: unsigned int dataOffset; fp@948: fp@950: getDomain(&domain, domainIndex); fp@948: fp@948: cout << "Domain" << domainIndex << ":" fp@948: << " LogBaseAddr 0x" fp@950: << hex << setfill('0') << setw(8) << domain.logical_base_address fp@950: << ", Size " << dec << setfill(' ') << setw(3) << domain.data_size fp@948: << ", WorkingCounter " fp@951: << dec << domain.working_counter << "/" fp@951: << domain.expected_working_counter << endl; fp@950: fp@950: if (!domain.data_size) fp@950: return; fp@950: fp@950: processData = new unsigned char[domain.data_size]; fp@950: fp@950: try { fp@950: getData(&data, domainIndex, domain.data_size, processData); fp@950: } catch (MasterException &e) { fp@950: delete [] processData; fp@950: throw e; fp@950: } fp@950: fp@950: for (i = 0; i < domain.fmmu_count; i++) { fp@950: getFmmu(&fmmu, domainIndex, i); fp@950: fp@951: cout << " SlaveConfig " fp@951: << fmmu.slave_config_alias << ":" << fmmu.slave_config_position fp@951: << ", Dir " fp@951: << setfill(' ') << setw(3) << (fmmu.fmmu_dir ? "In" : "Out") fp@950: << ", LogAddr 0x" fp@950: << hex << setfill('0') << setw(8) << fmmu.logical_address fp@951: << ", Size " << dec << fmmu.data_size << endl; fp@950: fp@950: dataOffset = fmmu.logical_address - domain.logical_base_address; fp@950: if (dataOffset + fmmu.data_size > domain.data_size) { fp@950: stringstream err; fp@950: err << "Fmmu information corrupted!"; fp@950: delete [] processData; fp@950: throw MasterException(err.str()); fp@950: } fp@950: fp@950: cout << " " << hex << setfill('0'); fp@950: for (j = 0; j < fmmu.data_size; j++) { fp@950: cout << setw(2) fp@950: << (unsigned int) *(processData + dataOffset + j) << " "; fp@950: } fp@950: cout << endl; fp@950: } fp@950: fp@950: delete [] processData; fp@948: } fp@948: fp@948: /****************************************************************************/ fp@948: fp@966: void Master::listSlavePdos( fp@966: uint16_t slavePosition, fp@966: bool quiet, fp@966: bool withHeader fp@966: ) fp@936: { fp@935: ec_ioctl_slave_t slave; fp@935: ec_ioctl_sync_t sync; fp@935: ec_ioctl_pdo_t pdo; fp@935: ec_ioctl_pdo_entry_t entry; fp@935: unsigned int i, j, k; fp@935: fp@935: getSlave(&slave, slavePosition); fp@935: fp@965: if (withHeader) fp@936: cout << "=== Slave " << slavePosition << " ===" << endl; fp@936: fp@935: for (i = 0; i < slave.sync_count; i++) { fp@935: getSync(&sync, slavePosition, i); fp@935: fp@935: cout << "SM" << i << ":" fp@935: << " PhysAddr 0x" fp@935: << hex << setfill('0') << setw(4) << sync.physical_start_address fp@935: << ", DefaultSize " fp@935: << dec << setfill(' ') << setw(4) << sync.default_size fp@935: << ", ControlRegister 0x" fp@935: << hex << setfill('0') << setw(2) fp@935: << (unsigned int) sync.control_register fp@935: << ", Enable " << dec << (unsigned int) sync.enable fp@935: << endl; fp@935: fp@935: for (j = 0; j < sync.pdo_count; j++) { fp@935: getPdo(&pdo, slavePosition, i, j); fp@935: fp@935: cout << " " << (pdo.dir ? "T" : "R") << "xPdo 0x" fp@935: << hex << setfill('0') << setw(4) << pdo.index fp@935: << " \"" << pdo.name << "\"" << endl; fp@935: fp@966: if (quiet) fp@966: continue; fp@966: fp@935: for (k = 0; k < pdo.entry_count; k++) { fp@935: getPdoEntry(&entry, slavePosition, i, j, k); fp@935: fp@935: cout << " Pdo entry 0x" fp@935: << hex << setfill('0') << setw(4) << entry.index fp@935: << ":" << hex << setfill('0') << setw(2) fp@935: << (unsigned int) entry.subindex fp@935: << ", " << dec << (unsigned int) entry.bit_length fp@935: << " bit, \"" << entry.name << "\"" << endl; fp@935: } fp@935: } fp@935: } fp@935: } fp@935: fp@935: /****************************************************************************/ fp@935: fp@966: void Master::listSlaveSdos( fp@966: uint16_t slavePosition, fp@966: bool quiet, fp@966: bool withHeader fp@966: ) fp@965: { fp@965: ec_ioctl_slave_t slave; fp@965: ec_ioctl_sdo_t sdo; fp@965: ec_ioctl_sdo_entry_t entry; fp@965: unsigned int i, j, k; fp@970: const CoEDataType *d; fp@965: fp@965: getSlave(&slave, slavePosition); fp@965: fp@965: if (withHeader) fp@965: cout << "=== Slave " << slavePosition << " ===" << endl; fp@965: fp@965: for (i = 0; i < slave.sdo_count; i++) { fp@965: getSdo(&sdo, slavePosition, i); fp@965: fp@970: cout << "Sdo " fp@965: << hex << setfill('0') << setw(4) << sdo.sdo_index fp@965: << ", \"" << sdo.name << "\"" << endl; fp@965: fp@966: if (quiet) fp@966: continue; fp@966: fp@965: for (j = 0; j <= sdo.max_subindex; j++) { fp@968: getSdoEntry(&entry, slavePosition, -i, j); fp@965: fp@970: cout << " " << hex << setfill('0') << setw(2) fp@965: << (unsigned int) entry.sdo_entry_subindex fp@970: << ", "; fp@970: fp@970: if ((d = findDataType(entry.data_type))) { fp@970: cout << d->name; fp@970: } else { fp@970: cout << "type " << setw(4) << entry.data_type; fp@970: } fp@970: fp@970: cout << ", " << dec << entry.bit_length << " bit, \"" fp@965: << entry.description << "\"" << endl; fp@965: } fp@965: } fp@965: } fp@965: fp@965: /****************************************************************************/ fp@965: fp@938: void Master::generateSlaveXml(uint16_t slavePosition) fp@938: { fp@938: ec_ioctl_slave_t slave; fp@938: ec_ioctl_sync_t sync; fp@938: ec_ioctl_pdo_t pdo; fp@938: ec_ioctl_pdo_entry_t entry; fp@938: unsigned int i, j, k; fp@938: fp@938: getSlave(&slave, slavePosition); fp@938: fp@938: cout fp@938: << "" << endl fp@938: << " " << endl fp@938: << " " << endl fp@938: << " " << endl fp@938: << " " << slave.vendor_id << "" << endl fp@938: << " " << endl fp@938: << " " << endl fp@938: << " " << endl fp@938: << " " << endl fp@938: << " " << endl; fp@938: fp@938: for (i = 0; i < slave.sync_count; i++) { fp@938: getSync(&sync, slavePosition, i); fp@938: fp@938: for (j = 0; j < sync.pdo_count; j++) { fp@938: getPdo(&pdo, slavePosition, i, j); fp@938: fp@938: cout fp@938: << " <" << (pdo.dir ? "T" : "R") << "xPdo>" << endl fp@938: << " #x" fp@938: << hex << setfill('0') << setw(4) << pdo.index fp@938: << "" << endl fp@938: << " " << pdo.name << "" << endl; fp@938: fp@938: for (k = 0; k < pdo.entry_count; k++) { fp@938: getPdoEntry(&entry, slavePosition, i, j, k); fp@938: fp@938: cout fp@938: << " " << endl fp@938: << " #x" fp@938: << hex << setfill('0') << setw(4) << entry.index fp@938: << "" << endl; fp@938: if (entry.index) fp@938: cout fp@938: << " " fp@938: << dec << (unsigned int) entry.subindex fp@938: << "" << endl; fp@938: fp@938: cout fp@938: << " " fp@938: << (unsigned int) entry.bit_length fp@938: << "" << endl; fp@938: fp@938: if (entry.index) { fp@938: cout fp@938: << " " << entry.name fp@938: << "" << endl fp@938: << " "; fp@938: fp@938: if (entry.bit_length == 1) { fp@938: cout << "BOOL"; fp@938: } else if (!(entry.bit_length % 8)) { fp@938: if (entry.bit_length <= 64) fp@938: cout << "UINT" << (unsigned int) entry.bit_length; fp@938: else fp@938: cout << "STRING(" fp@938: << (unsigned int) (entry.bit_length / 8) fp@938: << ")"; fp@938: } else { fp@938: cerr << "Invalid bit length " fp@938: << (unsigned int) entry.bit_length << endl; fp@938: } fp@938: fp@938: cout << "" << endl; fp@938: } fp@938: fp@938: cout << " " << endl; fp@938: } fp@938: fp@938: cout fp@938: << " " << endl; fp@938: } fp@938: } fp@938: fp@938: cout fp@938: << " " << endl fp@938: << " " << endl fp@938: << " " << endl fp@938: << "" << endl; fp@938: } fp@938: fp@938: /****************************************************************************/ fp@938: fp@948: unsigned int Master::domainCount() fp@948: { fp@948: int ret; fp@948: fp@948: if ((ret = ioctl(fd, EC_IOCTL_DOMAIN_COUNT, 0)) < 0) { fp@948: stringstream err; fp@948: err << "Failed to get number of domains: " << strerror(errno); fp@948: throw MasterException(err.str()); fp@948: } fp@948: fp@948: return ret; fp@948: } fp@948: fp@948: /****************************************************************************/ fp@948: fp@935: unsigned int Master::slaveCount() fp@935: { fp@957: ec_ioctl_master_t data; fp@957: fp@957: getMaster(&data); fp@957: return data.slave_count; fp@957: } fp@957: fp@957: /****************************************************************************/ fp@957: fp@957: void Master::getMaster(ec_ioctl_master_t *data) fp@957: { fp@957: if (ioctl(fd, EC_IOCTL_MASTER, data) < 0) { fp@957: stringstream err; fp@957: err << "Failed to get master information: " << strerror(errno); fp@957: throw MasterException(err.str()); fp@957: } fp@935: } fp@935: fp@935: /****************************************************************************/ fp@935: fp@948: void Master::getDomain(ec_ioctl_domain_t *data, unsigned int index) fp@948: { fp@948: data->index = index; fp@948: fp@948: if (ioctl(fd, EC_IOCTL_DOMAIN, data)) { fp@948: stringstream err; fp@948: err << "Failed to get domain: "; fp@948: if (errno == EINVAL) fp@948: err << "Domain " << index << " does not exist!"; fp@948: else fp@948: err << strerror(errno); fp@948: throw MasterException(err.str()); fp@948: } fp@948: } fp@948: fp@948: /****************************************************************************/ fp@948: fp@950: void Master::getData(ec_ioctl_data_t *data, unsigned int domainIndex, fp@950: unsigned int dataSize, unsigned char *mem) fp@950: { fp@950: data->domain_index = domainIndex; fp@950: data->data_size = dataSize; fp@950: data->target = mem; fp@950: fp@950: if (ioctl(fd, EC_IOCTL_DATA, data) < 0) { fp@950: stringstream err; fp@950: err << "Failed to get domain data: " << strerror(errno); fp@950: throw MasterException(err.str()); fp@950: } fp@950: } fp@950: fp@950: /****************************************************************************/ fp@950: fp@935: void Master::getSlave(ec_ioctl_slave_t *slave, uint16_t slaveIndex) fp@935: { fp@935: slave->position = slaveIndex; fp@935: fp@935: if (ioctl(fd, EC_IOCTL_SLAVE, slave)) { fp@935: stringstream err; fp@935: err << "Failed to get slave: "; fp@935: if (errno == EINVAL) fp@935: err << "Slave " << slaveIndex << " does not exist!"; fp@935: else fp@935: err << strerror(errno); fp@935: throw MasterException(err.str()); fp@935: } fp@935: } fp@935: fp@935: /****************************************************************************/ fp@935: fp@950: void Master::getFmmu( fp@950: ec_ioctl_domain_fmmu_t *fmmu, fp@950: unsigned int domainIndex, fp@950: unsigned int fmmuIndex fp@950: ) fp@950: { fp@950: fmmu->domain_index = domainIndex; fp@950: fmmu->fmmu_index = fmmuIndex; fp@950: fp@950: if (ioctl(fd, EC_IOCTL_DOMAIN_FMMU, fmmu)) { fp@950: stringstream err; fp@950: err << "Failed to get domain FMMU: "; fp@950: if (errno == EINVAL) fp@950: err << "Either domain " << domainIndex << " does not exist, " fp@950: << "or it contains less than " << (unsigned int) fmmuIndex + 1 fp@950: << " FMMus!"; fp@950: else fp@950: err << strerror(errno); fp@950: throw MasterException(err.str()); fp@950: } fp@950: } fp@950: fp@950: /****************************************************************************/ fp@950: fp@935: void Master::getSync( fp@935: ec_ioctl_sync_t *sync, fp@935: uint16_t slaveIndex, fp@935: uint8_t syncIndex fp@935: ) fp@935: { fp@935: sync->slave_position = slaveIndex; fp@935: sync->sync_index = syncIndex; fp@935: fp@935: if (ioctl(fd, EC_IOCTL_SYNC, sync)) { fp@935: stringstream err; fp@935: err << "Failed to get sync manager: "; fp@935: if (errno == EINVAL) fp@935: err << "Either slave " << slaveIndex << " does not exist, " fp@950: << "or it contains less than " << (unsigned int) syncIndex + 1 fp@935: << " sync managers!"; fp@935: else fp@935: err << strerror(errno); fp@935: throw MasterException(err.str()); fp@935: } fp@935: } fp@935: fp@935: /****************************************************************************/ fp@935: fp@935: void Master::getPdo( fp@935: ec_ioctl_pdo_t *pdo, fp@935: uint16_t slaveIndex, fp@935: uint8_t syncIndex, fp@935: uint8_t pdoPos fp@935: ) fp@935: { fp@935: pdo->slave_position = slaveIndex; fp@935: pdo->sync_index = syncIndex; fp@935: pdo->pdo_pos = pdoPos; fp@935: fp@935: if (ioctl(fd, EC_IOCTL_PDO, pdo)) { fp@935: stringstream err; fp@935: err << "Failed to get Pdo: "; fp@935: if (errno == EINVAL) fp@935: err << "Either slave " << slaveIndex << " does not exist, " fp@950: << "or it contains less than " << (unsigned int) syncIndex + 1 fp@935: << " sync managers, or sync manager " fp@935: << (unsigned int) syncIndex << " contains less than " fp@935: << pdoPos + 1 << " Pdos!" << endl; fp@935: else fp@935: err << strerror(errno); fp@935: throw MasterException(err.str()); fp@935: } fp@935: } fp@935: fp@935: /****************************************************************************/ fp@935: fp@935: void Master::getPdoEntry( fp@935: ec_ioctl_pdo_entry_t *entry, fp@935: uint16_t slaveIndex, fp@935: uint8_t syncIndex, fp@935: uint8_t pdoPos, fp@935: uint8_t entryPos fp@935: ) fp@935: { fp@935: entry->slave_position = slaveIndex; fp@935: entry->sync_index = syncIndex; fp@935: entry->pdo_pos = pdoPos; fp@935: entry->entry_pos = entryPos; fp@935: fp@935: if (ioctl(fd, EC_IOCTL_PDO_ENTRY, entry)) { fp@935: stringstream err; fp@935: err << "Failed to get Pdo entry: "; fp@935: if (errno == EINVAL) fp@935: err << "Either slave " << slaveIndex << " does not exist, " fp@950: << "or it contains less than " << (unsigned int) syncIndex + 1 fp@935: << " sync managers, or sync manager " fp@935: << (unsigned int) syncIndex << " contains less than " fp@935: << pdoPos + 1 << " Pdos, or the Pdo at position " << pdoPos fp@935: << " contains less than " << (unsigned int) entryPos + 1 fp@935: << " entries!" << endl; fp@935: else fp@935: err << strerror(errno); fp@935: throw MasterException(err.str()); fp@935: } fp@935: } fp@935: fp@935: /****************************************************************************/ fp@935: fp@965: void Master::getSdo( fp@965: ec_ioctl_sdo_t *sdo, fp@965: uint16_t slaveIndex, fp@965: uint16_t sdoPosition fp@965: ) fp@965: { fp@965: sdo->slave_position = slaveIndex; fp@965: sdo->sdo_position = sdoPosition; fp@965: fp@965: if (ioctl(fd, EC_IOCTL_SDO, sdo)) { fp@965: stringstream err; fp@965: err << "Failed to get Sdo: "; fp@965: if (errno == EINVAL) fp@965: err << "Either slave " << slaveIndex << " does not exist, " fp@965: << "or it contains less than " << sdoPosition + 1 << " Sdos!" fp@965: << endl; fp@965: else fp@965: err << strerror(errno); fp@965: throw MasterException(err.str()); fp@965: } fp@965: } fp@965: fp@965: /****************************************************************************/ fp@965: fp@965: void Master::getSdoEntry( fp@965: ec_ioctl_sdo_entry_t *entry, fp@965: uint16_t slaveIndex, fp@968: int sdoSpec, fp@965: uint8_t entrySubindex fp@965: ) fp@965: { fp@965: entry->slave_position = slaveIndex; fp@968: entry->sdo_spec = sdoSpec; fp@965: entry->sdo_entry_subindex = entrySubindex; fp@965: fp@965: if (ioctl(fd, EC_IOCTL_SDO_ENTRY, entry)) { fp@965: stringstream err; fp@965: err << "Failed to get Sdo entry: "; fp@968: err << strerror(errno); fp@965: throw MasterException(err.str()); fp@965: } fp@965: } fp@965: fp@965: /****************************************************************************/ fp@965: fp@960: void Master::requestState( fp@960: uint16_t slavePosition, fp@960: uint8_t state fp@960: ) fp@960: { fp@960: ec_ioctl_slave_state_t data; fp@960: fp@960: data.slave_position = slavePosition; fp@960: data.requested_state = state; fp@960: fp@960: if (ioctl(fd, EC_IOCTL_SLAVE_STATE, &data)) { fp@960: stringstream err; fp@960: err << "Failed to request slave state: "; fp@960: if (errno == EINVAL) fp@960: err << "Slave " << slavePosition << " does not exist!"; fp@960: else fp@960: err << strerror(errno); fp@960: throw MasterException(err.str()); fp@960: } fp@960: } fp@960: fp@960: /****************************************************************************/ fp@960: fp@935: string Master::slaveState(uint8_t state) fp@922: { fp@922: switch (state) { fp@922: case 1: return "INIT"; fp@922: case 2: return "PREOP"; fp@922: case 4: return "SAFEOP"; fp@922: case 8: return "OP"; fp@922: default: return "???"; fp@922: } fp@922: } fp@922: fp@922: /****************************************************************************/ fp@968: fp@968: void Master::printRawData( fp@968: const uint8_t *data, fp@968: unsigned int size) fp@968: { fp@968: cout << hex << setfill('0'); fp@968: while (size--) { fp@968: cout << "0x" << setw(2) << (unsigned int) *data++; fp@968: if (size) fp@968: cout << " "; fp@968: } fp@968: cout << endl; fp@968: } fp@968: fp@968: /****************************************************************************/