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