tool/cmd_alias.cpp
changeset 1122 ee305a780a02
child 1125 9976f7b9fe66
equal deleted inserted replaced
1121:52a005ffd011 1122:ee305a780a02
       
     1 /*****************************************************************************
       
     2  *
       
     3  * $Id$
       
     4  *
       
     5  ****************************************************************************/
       
     6 
       
     7 #include <iostream>
       
     8 #include <iomanip>
       
     9 #include <sstream>
       
    10 using namespace std;
       
    11 
       
    12 #include "globals.h"
       
    13 
       
    14 /*****************************************************************************/
       
    15 
       
    16 const char *help_alias =
       
    17     "[OPTIONS] <ALIAS>\n"
       
    18     "\n"
       
    19     "Write the secondary slave address (alias) for either\n"
       
    20     "one or for multiple slaves.\n"
       
    21     "\n"
       
    22     "Arguments:\n"
       
    23     "  ALIAS must be a 16 bit unsigned integer, specified\n"
       
    24     "        either in decimal (no prefix), octal (prefix '0')\n"
       
    25     "        or hexadecimal (prefix '0x').\n"
       
    26     "\n"
       
    27     "Command-specific options:\n"
       
    28     "  -s <SLAVE>  Write the alias of the slave with the given\n"
       
    29     "              ring position. If this option is not\n"
       
    30     "              specified, the alias of all slaves is set.\n"
       
    31     "              The --force option is required in this\n"
       
    32     "              case.\n";
       
    33 
       
    34 /*****************************************************************************/
       
    35 
       
    36 void writeSlaveAlias(uint16_t, uint16_t);
       
    37 
       
    38 /*****************************************************************************/
       
    39 
       
    40 /** Writes the Secondary slave address (alias) to the slave's SII.
       
    41  */
       
    42 void command_alias(void)
       
    43 {
       
    44     uint16_t alias;
       
    45     stringstream err, strAlias;
       
    46     int number;
       
    47     unsigned int numSlaves, i;
       
    48 
       
    49     if (commandArgs.size() != 1) {
       
    50         err << "'" << command << "' takes exactly one argument!";
       
    51         throw InvalidUsageException(err);
       
    52     }
       
    53 
       
    54     strAlias << commandArgs[0];
       
    55     strAlias
       
    56         >> resetiosflags(ios::basefield) // guess base from prefix
       
    57         >> number;
       
    58     if (strAlias.fail() || number < 0x0000 || number > 0xffff) {
       
    59         err << "Invalid alias '" << commandArgs[0] << "'!";
       
    60         throw InvalidUsageException(err);
       
    61     }
       
    62     alias = number;
       
    63 
       
    64     if (slavePosition == -1) {
       
    65         if (!force) {
       
    66             err << "This will write the alias addresses of all slaves to "
       
    67                 << alias << "! Please specify --force to proceed.";
       
    68             throw ExecutionFailureException(err);
       
    69         }
       
    70 
       
    71         masterDev.open(MasterDevice::ReadWrite);
       
    72         numSlaves = masterDev.slaveCount();
       
    73 
       
    74         for (i = 0; i < numSlaves; i++) {
       
    75             writeSlaveAlias(i, alias);
       
    76         }
       
    77     } else {
       
    78         masterDev.open(MasterDevice::ReadWrite);
       
    79         writeSlaveAlias(slavePosition, alias);
       
    80     }
       
    81 }
       
    82 
       
    83 /*****************************************************************************/
       
    84 
       
    85 /** Calculates the SII checksum field.
       
    86  *
       
    87  * The checksum is generated with the polynom x^8+x^2+x+1 (0x07) and an
       
    88  * initial value of 0xff (see IEC 61158-6-12 ch. 5.4).
       
    89  *
       
    90  * The below code was originally generated with PYCRC
       
    91  * http://www.tty1.net/pycrc
       
    92  *
       
    93  * ./pycrc.py --width=8 --poly=0x07 --reflect-in=0 --xor-in=0xff
       
    94  *   --reflect-out=0 --xor-out=0 --generate c --algorithm=bit-by-bit
       
    95  *
       
    96  * \return CRC8
       
    97  */
       
    98 uint8_t calcSiiCrc(
       
    99         const uint8_t *data, /**< pointer to data */
       
   100         size_t length /**< number of bytes in \a data */
       
   101         )
       
   102 {
       
   103     unsigned int i;
       
   104     uint8_t bit, byte, crc = 0x48;
       
   105 
       
   106     while (length--) {
       
   107         byte = *data++;
       
   108         for (i = 0; i < 8; i++) {
       
   109             bit = crc & 0x80;
       
   110             crc = (crc << 1) | ((byte >> (7 - i)) & 0x01);
       
   111             if (bit) crc ^= 0x07;
       
   112         }
       
   113     }
       
   114 
       
   115     for (i = 0; i < 8; i++) {
       
   116         bit = crc & 0x80;
       
   117         crc <<= 1;
       
   118         if (bit) crc ^= 0x07;
       
   119     }
       
   120 
       
   121     return crc;
       
   122 }
       
   123 
       
   124 /*****************************************************************************/
       
   125 
       
   126 /** Writes the Secondary slave address (alias) to the slave's SII.
       
   127  */
       
   128 void writeSlaveAlias(
       
   129         uint16_t slavePosition,
       
   130         uint16_t alias
       
   131         )
       
   132 {
       
   133     ec_ioctl_slave_sii_t data;
       
   134     ec_ioctl_slave_t slave;
       
   135     stringstream err;
       
   136     uint8_t crc;
       
   137 
       
   138     masterDev.getSlave(&slave, slavePosition);
       
   139 
       
   140     if (slave.sii_nwords < 8) {
       
   141         err << "Current SII contents are too small to set an alias "
       
   142             << "(" << slave.sii_nwords << " words)!";
       
   143         throw ExecutionFailureException(err);
       
   144     }
       
   145 
       
   146     // read first 8 SII words
       
   147     data.slave_position = slavePosition;
       
   148     data.offset = 0;
       
   149     data.nwords = 8;
       
   150     data.words = new uint16_t[data.nwords];
       
   151 
       
   152     try {
       
   153         masterDev.readSii(&data);
       
   154     } catch (MasterDeviceException &e) {
       
   155         delete [] data.words;
       
   156         err << "Failed to read SII: " << e.what();
       
   157         throw ExecutionFailureException(err);
       
   158     }
       
   159 
       
   160     // write new alias address in word 4
       
   161     data.words[4] = cputole16(alias);
       
   162 
       
   163     // calculate checksum over words 0 to 6
       
   164     crc = calcSiiCrc((const uint8_t *) data.words, 14);
       
   165 
       
   166     // write new checksum into first byte of word 7
       
   167     *(uint8_t *) (data.words + 7) = crc;
       
   168 
       
   169     // write first 8 words with new alias and checksum
       
   170     try {
       
   171         masterDev.writeSii(&data);
       
   172     } catch (MasterDeviceException &e) {
       
   173         delete [] data.words;
       
   174         err << "Failed to read SII: " << e.what();
       
   175         throw ExecutionFailureException(err);
       
   176     }
       
   177 
       
   178     delete [] data.words;
       
   179 }
       
   180 
       
   181 /*****************************************************************************/