tool/CommandDownload.cpp
changeset 1142 59be91dfcbe1
child 1144 7dbfdd61812c
equal deleted inserted replaced
1141:7ffbca63fc72 1142:59be91dfcbe1
       
     1 /*****************************************************************************
       
     2  *
       
     3  * $Id$
       
     4  *
       
     5  ****************************************************************************/
       
     6 
       
     7 #include <iostream>
       
     8 #include <iomanip>
       
     9 using namespace std;
       
    10 
       
    11 #include "CommandDownload.h"
       
    12 #include "coe_datatypes.h"
       
    13 #include "byteorder.h"
       
    14 
       
    15 /*****************************************************************************/
       
    16 
       
    17 CommandDownload::CommandDownload():
       
    18     Command("download", "Write an Sdo entry to a slave.")
       
    19 {
       
    20 }
       
    21 
       
    22 /*****************************************************************************/
       
    23 
       
    24 string CommandDownload::helpString() const
       
    25 {
       
    26     stringstream str;
       
    27 
       
    28     str << getName() << " [OPTIONS] <INDEX> <SUBINDEX> <VALUE>" << endl
       
    29     	<< endl
       
    30     	<< getBriefDescription() << endl
       
    31     	<< endl
       
    32     	<< "The data type of the Sdo entry is taken from the Sdo" << endl
       
    33 		<< "dictionary by default. It can be overridden with the" << endl
       
    34 		<< "--type option. If the slave does not support the Sdo" << endl
       
    35 		<< "information service or the Sdo is not in the dictionary," << endl
       
    36 		<< "the --type option is mandatory." << endl
       
    37     	<< endl
       
    38     	<< "These are the valid Sdo entry data types:" << endl
       
    39     	<< "  int8, int16, int32, uint8, uint16, uint32, string." << endl
       
    40     	<< endl
       
    41     	<< "Arguments:"
       
    42     	<< "  INDEX    is the Sdo index and must be an unsigned" << endl
       
    43 		<< "           16 bit number." << endl
       
    44     	<< "  SUBINDEX is the Sdo entry subindex and must be an" << endl
       
    45 		<< "           unsigned 8 bit number." << endl
       
    46     	<< "  VALUE    is the value to download and must correspond" << endl
       
    47 		<< "           to the Sdo entry datatype (see above)." << endl
       
    48     	<< endl
       
    49     	<< "Command-specific options:" << endl
       
    50     	<< "  --slave -s <index>  Positive numerical ring position" << endl
       
    51 		<< "                      (mandatory)." << endl
       
    52     	<< "  --type  -t <type>   Forced Sdo entry data type (see" << endl
       
    53 		<< "                      above)." << endl
       
    54     	<< endl
       
    55 		<< numericInfo();
       
    56 
       
    57 	return str.str();
       
    58 }
       
    59 
       
    60 /****************************************************************************/
       
    61 
       
    62 void CommandDownload::execute(MasterDevice &m, const StringVector &args)
       
    63 {
       
    64     stringstream strIndex, strSubIndex, strValue, err;
       
    65     ec_ioctl_slave_sdo_download_t data;
       
    66     unsigned int number;
       
    67     const CoEDataType *dataType = NULL;
       
    68 
       
    69     if (slavePosition < 0) {
       
    70         err << "'" << getName() << "' requires a slave! "
       
    71             << "Please specify --slave.";
       
    72         throwInvalidUsageException(err);
       
    73     }
       
    74     data.slave_position = slavePosition;
       
    75 
       
    76     if (args.size() != 3) {
       
    77         err << "'" << getName() << "' takes 3 arguments!";
       
    78         throwInvalidUsageException(err);
       
    79     }
       
    80 
       
    81     strIndex << args[0];
       
    82     strIndex
       
    83         >> resetiosflags(ios::basefield) // guess base from prefix
       
    84         >> data.sdo_index;
       
    85     if (strIndex.fail()) {
       
    86         err << "Invalid Sdo index '" << args[0] << "'!";
       
    87         throwInvalidUsageException(err);
       
    88     }
       
    89 
       
    90     strSubIndex << args[1];
       
    91     strSubIndex
       
    92         >> resetiosflags(ios::basefield) // guess base from prefix
       
    93         >> number;
       
    94     if (strSubIndex.fail() || number > 0xff) {
       
    95         err << "Invalid Sdo subindex '" << args[1] << "'!";
       
    96         throwInvalidUsageException(err);
       
    97     }
       
    98     data.sdo_entry_subindex = number;
       
    99 
       
   100     if (dataTypeStr != "") { // data type specified
       
   101         if (!(dataType = findDataType(dataTypeStr))) {
       
   102             err << "Invalid data type '" << dataTypeStr << "'!";
       
   103             throwInvalidUsageException(err);
       
   104         }
       
   105     } else { // no data type specified: fetch from dictionary
       
   106         ec_ioctl_slave_sdo_entry_t entry;
       
   107 
       
   108         m.open(MasterDevice::ReadWrite);
       
   109 
       
   110         try {
       
   111             m.getSdoEntry(&entry, slavePosition,
       
   112                     data.sdo_index, data.sdo_entry_subindex);
       
   113         } catch (MasterDeviceException &e) {
       
   114             err << "Failed to determine Sdo entry data type. "
       
   115                 << "Please specify --type.";
       
   116             throwCommandException(err);
       
   117         }
       
   118         if (!(dataType = findDataType(entry.data_type))) {
       
   119             err << "Pdo entry has unknown data type 0x"
       
   120                 << hex << setfill('0') << setw(4) << entry.data_type << "!"
       
   121                 << " Please specify --type.";
       
   122             throwCommandException(err);
       
   123         }
       
   124     }
       
   125 
       
   126     if (dataType->byteSize) {
       
   127         data.data_size = dataType->byteSize;
       
   128     } else {
       
   129         data.data_size = DefaultBufferSize;
       
   130     }
       
   131 
       
   132     data.data = new uint8_t[data.data_size + 1];
       
   133 
       
   134     strValue << args[2];
       
   135     strValue >> resetiosflags(ios::basefield); // guess base from prefix
       
   136     strValue.exceptions(ios::failbit);
       
   137 
       
   138     try {
       
   139         switch (dataType->coeCode) {
       
   140             case 0x0002: // int8
       
   141                 {
       
   142                     int16_t val; // uint8_t is interpreted as char
       
   143                     strValue >> val;
       
   144                     if (val > 127 || val < -128)
       
   145                         throw ios::failure("Value out of range");
       
   146                     *data.data = val;
       
   147                     break;
       
   148                 }
       
   149             case 0x0003: // int16
       
   150                 {
       
   151                     int16_t val;
       
   152                     strValue >> val;
       
   153                     *(int16_t *) data.data = cputole16(val);
       
   154                     break;
       
   155                 }
       
   156             case 0x0004: // int32
       
   157                 {
       
   158                     int32_t val;
       
   159                     strValue >> val;
       
   160                     *(int32_t *) data.data = cputole32(val);
       
   161                     break;
       
   162                 }
       
   163             case 0x0005: // uint8
       
   164                 {
       
   165                     uint16_t val; // uint8_t is interpreted as char
       
   166                     strValue >> val;
       
   167                     if (val > 0xff)
       
   168                         throw ios::failure("Value out of range");
       
   169                     *data.data = val;
       
   170                     break;
       
   171                 }
       
   172             case 0x0006: // uint16
       
   173                 {
       
   174                     uint16_t val;
       
   175                     strValue >> val;
       
   176                     *(uint16_t *) data.data = cputole16(val);
       
   177                     break;
       
   178                 }
       
   179             case 0x0007: // uint32
       
   180                 {
       
   181                     uint32_t val;
       
   182                     strValue >> val;
       
   183                     *(uint32_t *) data.data = cputole32(val);
       
   184                     break;
       
   185                 }
       
   186             case 0x0009: // string
       
   187                 if (strValue.str().size() >= data.data_size) {
       
   188                     err << "String too large";
       
   189                     throwCommandException(err);
       
   190                 }
       
   191                 data.data_size = strValue.str().size();
       
   192                 strValue >> (char *) data.data;
       
   193                 break;
       
   194 
       
   195             default:
       
   196                 delete [] data.data;
       
   197                 err << "Unknown data type 0x" << hex << dataType->coeCode;
       
   198                 throwCommandException(err);
       
   199         }
       
   200     } catch (ios::failure &e) {
       
   201         delete [] data.data;
       
   202         err << "Invalid value argument '" << args[2]
       
   203             << "' for type '" << dataType->name << "'!";
       
   204         throwInvalidUsageException(err);
       
   205     }
       
   206 
       
   207     m.open(MasterDevice::ReadWrite);
       
   208 
       
   209 	try {
       
   210 			m.sdoDownload(&data);
       
   211 	} catch(MasterDeviceException &e) {
       
   212         delete [] data.data;
       
   213         throw e;
       
   214     }
       
   215 
       
   216     delete [] data.data;
       
   217 }
       
   218 
       
   219 /*****************************************************************************/