From 2a21a925a6edfc74814b1a5e2847e557e74a8984 Mon Sep 17 00:00:00 2001 From: Florian Pose Date: Wed, 8 Apr 2009 14:10:34 +0000 Subject: [PATCH] reg_write with data types. --- tool/CommandReg.cpp | 70 +++++++++++++++++++++++++ tool/CommandReg.h | 54 ++++++++++++++++++++ tool/CommandRegRead.cpp | 44 +++------------- tool/CommandRegRead.h | 12 +---- tool/CommandRegWrite.cpp | 107 +++++++++++++++++++++++++++++++++------ tool/CommandRegWrite.h | 4 +- tool/Makefile.am | 2 + 7 files changed, 228 insertions(+), 65 deletions(-) create mode 100644 tool/CommandReg.cpp create mode 100644 tool/CommandReg.h diff --git a/tool/CommandReg.cpp b/tool/CommandReg.cpp new file mode 100644 index 00000000..0400b2f0 --- /dev/null +++ b/tool/CommandReg.cpp @@ -0,0 +1,70 @@ +/***************************************************************************** + * + * $Id$ + * + * Copyright (C) 2006-2009 Florian Pose, Ingenieurgemeinschaft IgH + * + * This file is part of the IgH EtherCAT Master. + * + * The IgH EtherCAT Master is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version 2, as + * published by the Free Software Foundation. + * + * The IgH EtherCAT Master is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with the IgH EtherCAT Master; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * --- + * + * The license mentioned above concerns the source code only. Using the + * EtherCAT technology and brand is only permitted in compliance with the + * industrial property and similar rights of Beckhoff Automation GmbH. + * + ****************************************************************************/ + +#include "CommandReg.h" + +/*****************************************************************************/ + +CommandReg::CommandReg(const string &name, const string &briefDesc): + Command(name, briefDesc) +{ +} + +/****************************************************************************/ + +const CommandReg::DataType *CommandReg::findDataType( + const string &str + ) +{ + const DataType *d; + + for (d = dataTypes; d->name; d++) + if (str == d->name) + return d; + + return NULL; +} + +/****************************************************************************/ + +const CommandReg::DataType CommandReg::dataTypes[] = { + {"int8", 1}, + {"int16", 2}, + {"int32", 4}, + {"int64", 8}, + {"uint8", 1}, + {"uint16", 2}, + {"uint32", 4}, + {"uint64", 8}, + {"string", 0}, + {"raw", 0}, + {} +}; + +/*****************************************************************************/ diff --git a/tool/CommandReg.h b/tool/CommandReg.h new file mode 100644 index 00000000..c2de58b3 --- /dev/null +++ b/tool/CommandReg.h @@ -0,0 +1,54 @@ +/***************************************************************************** + * + * $Id$ + * + * Copyright (C) 2006-2009 Florian Pose, Ingenieurgemeinschaft IgH + * + * This file is part of the IgH EtherCAT Master. + * + * The IgH EtherCAT Master is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version 2, as + * published by the Free Software Foundation. + * + * The IgH EtherCAT Master is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with the IgH EtherCAT Master; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * --- + * + * The license mentioned above concerns the source code only. Using the + * EtherCAT technology and brand is only permitted in compliance with the + * industrial property and similar rights of Beckhoff Automation GmbH. + * + ****************************************************************************/ + +#ifndef __COMMANDREG_H__ +#define __COMMANDREG_H__ + +#include "Command.h" + +/****************************************************************************/ + +class CommandReg: + public Command +{ + public: + CommandReg(const string &, const string &); + + protected: + struct DataType { + const char *name; + unsigned int byteSize; + }; + static const DataType dataTypes[]; + static const DataType *findDataType(const string &); +}; + +/****************************************************************************/ + +#endif diff --git a/tool/CommandRegRead.cpp b/tool/CommandRegRead.cpp index 067f4699..965d69e6 100644 --- a/tool/CommandRegRead.cpp +++ b/tool/CommandRegRead.cpp @@ -36,7 +36,7 @@ using namespace std; /*****************************************************************************/ CommandRegRead::CommandRegRead(): - Command("reg_read", "Output a slave's register contents.") + CommandReg("reg_read", "Output a slave's register contents.") { } @@ -63,7 +63,7 @@ string CommandRegRead::helpString() const << endl << "These are the valid data types:" << endl << " int8, int16, int32, int64, uint8, uint16, uint32," << endl - << " uint64, string, octet_string, raw." << endl + << " uint64, string, raw." << endl << endl << "Command-specific options:" << endl << " --alias -a " << endl @@ -159,13 +159,13 @@ void CommandRegRead::execute(MasterDevice &m, const StringVector &args) } cout << setfill('0'); - if (!dataType || - dataType->name == "string" || - dataType->name == "octet_string") { + if (!dataType || dataType->name == "string") { uint16_t i; for (i = 0; i < data.length; i++) { cout << data.data[i]; } + if (dataType) + cout << endl; } else if (dataType->name == "int8") { int sval = *(int8_t *) data.data; cout << sval << " 0x" << hex << setw(2) << sval << endl; @@ -190,7 +190,7 @@ void CommandRegRead::execute(MasterDevice &m, const StringVector &args) } else if (dataType->name == "uint64") { long long unsigned int uval = le32_to_cpup(data.data); cout << uval << " 0x" << hex << setw(8) << uval << endl; - } else { + } else { // raw uint8_t *d = data.data; unsigned int size = data.length; @@ -206,36 +206,4 @@ void CommandRegRead::execute(MasterDevice &m, const StringVector &args) delete [] data.data; } -/****************************************************************************/ - -const CommandRegRead::DataType *CommandRegRead::findDataType( - const string &str - ) -{ - const DataType *d; - - for (d = dataTypes; d->name; d++) - if (str == d->name) - return d; - - return NULL; -} - -/****************************************************************************/ - -const CommandRegRead::DataType CommandRegRead::dataTypes[] = { - {"int8", 1}, - {"int16", 2}, - {"int32", 4}, - {"int64", 8}, - {"uint8", 1}, - {"uint16", 2}, - {"uint32", 4}, - {"uint64", 8}, - {"string", 0}, - {"octet_string", 0}, - {"raw", 0}, - {} -}; - /*****************************************************************************/ diff --git a/tool/CommandRegRead.h b/tool/CommandRegRead.h index 0f232ad7..5969735c 100644 --- a/tool/CommandRegRead.h +++ b/tool/CommandRegRead.h @@ -30,26 +30,18 @@ #ifndef __COMMANDREGREAD_H__ #define __COMMANDREGREAD_H__ -#include "Command.h" +#include "CommandReg.h" /****************************************************************************/ class CommandRegRead: - public Command + public CommandReg { public: CommandRegRead(); string helpString() const; void execute(MasterDevice &, const StringVector &); - - private: - struct DataType { - const char *name; - unsigned int byteSize; - }; - static const DataType dataTypes[]; - static const DataType *findDataType(const string &); }; /****************************************************************************/ diff --git a/tool/CommandRegWrite.cpp b/tool/CommandRegWrite.cpp index fe09ee6e..4c8710b6 100644 --- a/tool/CommandRegWrite.cpp +++ b/tool/CommandRegWrite.cpp @@ -38,7 +38,7 @@ using namespace std; /*****************************************************************************/ CommandRegWrite::CommandRegWrite(): - Command("reg_write", "Write data to a slave's registers.") + CommandReg("reg_write", "Write data to a slave's registers.") { } @@ -48,21 +48,30 @@ string CommandRegWrite::helpString() const { stringstream str; - str << getName() << " [OPTIONS] " << endl + str << getName() << " [OPTIONS] " << endl << endl << getBriefDescription() << endl << endl << "This command requires a single slave to be selected." << endl << endl << "Arguments:" << endl - << " OFFSET must be the register address." << endl - << " FILENAME must be a path to a file with data to write." << endl - << " If it is '-', data are read from stdin." << endl + << " OFFSET is the register address to write to." << endl + << " DATA depends on whether a datatype was specified" << endl + << " with the --type option: If not, DATA must be" << endl + << " either a path to a file with data to write," << endl + << " or '-', which means, that data are read from" << endl + << " stdin. If a datatype was specified, VALUE is" << endl + << " interpreted respective to the given type." << endl << endl + << "These are the valid data types:" << endl + << " int8, int16, int32, int64, uint8, uint16, uint32," << endl + << " uint64, string." << endl + << endl << "Command-specific options:" << endl << " --alias -a " << endl << " --position -p Slave selection. See the help of" << endl << " the 'slaves' command." << endl + << " --type -t Data type (see above)." << endl << endl << numericInfo(); @@ -92,17 +101,85 @@ void CommandRegWrite::execute(MasterDevice &m, const StringVector &args) throwInvalidUsageException(err); } - if (args[1] == "-") { - loadRegData(&data, cin); - } else { - file.open(args[1].c_str(), ifstream::in | ifstream::binary); - if (file.fail()) { - err << "Failed to open '" << args[0] << "'!"; - throwCommandException(err); + if (getDataType().empty()) { + if (args[1] == "-") { + loadRegData(&data, cin); + } else { + file.open(args[1].c_str(), ifstream::in | ifstream::binary); + if (file.fail()) { + err << "Failed to open '" << args[1] << "'!"; + throwCommandException(err); + } + loadRegData(&data, file); + file.close(); + } + } else { + stringstream strValue; + const DataType *dataType = findDataType(getDataType()); + + if (!dataType) { + err << "Invalid data type '" << getDataType() << "'!"; + throwInvalidUsageException(err); } - loadRegData(&data, file); - file.close(); - } + + if (dataType->byteSize) { + data.length = dataType->byteSize; + data.data = new uint8_t[data.length]; + } + + strValue << args[1]; + strValue >> resetiosflags(ios::basefield); // guess base from prefix + strValue.exceptions(ios::failbit); + + try { + if (dataType->name == "int8") { + int16_t val; // uint8_t is interpreted as char + strValue >> val; + if (val > 127 || val < -128) + throw ios::failure("Value out of range"); + *data.data = (int8_t) val; + } else if (dataType->name == "int16") { + int16_t val; + strValue >> val; + *(int16_t *) data.data = cpu_to_le16(val); + } else if (dataType->name == "int32") { + int32_t val; + strValue >> val; + *(int32_t *) data.data = cpu_to_le32(val); + } else if (dataType->name == "uint8") { + uint16_t val; // uint8_t is interpreted as char + strValue >> val; + if (val > 0xff) + throw ios::failure("Value out of range"); + *data.data = (uint8_t) val; + } else if (dataType->name == "uint16") { + uint16_t val; + strValue >> val; + *(uint16_t *) data.data = cpu_to_le16(val); + } else if (dataType->name == "uint32") { + uint32_t val; + strValue >> val; + *(uint32_t *) data.data = cpu_to_le32(val); + } else if (dataType->name == "string" || + dataType->name == "octet_string") { + data.length = strValue.str().size(); + if (!data.length) { + err << "Zero-size string now allowed!"; + throwCommandException(err); + } + data.data = new uint8_t[data.length]; + strValue >> (char *) data.data; + } else { + err << "Invalid data type " << dataType->name; + throwCommandException(err); + } + } catch (ios::failure &e) { + delete [] data.data; + err << "Invalid value argument '" << args[1] + << "' for type '" << dataType->name << "'!"; + throwInvalidUsageException(err); + } + } if ((uint32_t) data.offset + data.length > 0xffff) { err << "Offset and length exceeding 64k!"; diff --git a/tool/CommandRegWrite.h b/tool/CommandRegWrite.h index 5908472e..0380d811 100644 --- a/tool/CommandRegWrite.h +++ b/tool/CommandRegWrite.h @@ -30,12 +30,12 @@ #ifndef __COMMANDREGWRITE_H__ #define __COMMANDREGWRITE_H__ -#include "Command.h" +#include "CommandReg.h" /****************************************************************************/ class CommandRegWrite: - public Command + public CommandReg { public: CommandRegWrite(); diff --git a/tool/Makefile.am b/tool/Makefile.am index fc484da6..84331d2d 100644 --- a/tool/Makefile.am +++ b/tool/Makefile.am @@ -45,6 +45,7 @@ ethercat_SOURCES = \ CommandFoeWrite.cpp \ CommandMaster.cpp \ CommandPdos.cpp \ + CommandReg.cpp \ CommandRegRead.cpp \ CommandRegWrite.cpp \ CommandSdos.cpp \ @@ -73,6 +74,7 @@ noinst_HEADERS = \ CommandFoeWrite.h \ CommandMaster.h \ CommandPdos.h \ + CommandReg.h \ CommandRegRead.h \ CommandRegWrite.h \ CommandSdos.h \