Accept '-' as filename to read from stdin.
authorFlorian Pose <fp@igh-essen.com>
Mon, 28 Jul 2008 13:15:19 +0000
changeset 1161 d1324ac71232
parent 1160 f02ff486b313
child 1162 51a8b41d3dbc
Accept '-' as filename to read from stdin.
TODO
tool/CommandSiiWrite.cpp
tool/CommandSiiWrite.h
--- a/TODO	Mon Jul 28 12:15:25 2008 +0000
+++ b/TODO	Mon Jul 28 13:15:19 2008 +0000
@@ -14,8 +14,6 @@
 * Get original driver for r8169.
 * Race in jiffies frame timeout?
 * ethercat tool:
-    - Show Pdos in 'ethercat slave -v'.
-    - Accept files from stdin.
     - Display attached device's MAC address instead of ff's.
     - Data type abbreviations.
     - Add a -n (numeric) switch.
--- a/tool/CommandSiiWrite.cpp	Mon Jul 28 12:15:25 2008 +0000
+++ b/tool/CommandSiiWrite.cpp	Mon Jul 28 13:15:19 2008 +0000
@@ -37,7 +37,8 @@
         << endl
         << "Arguments:" << endl
         << "  FILENAME must be a path to a file that contains a" << endl
-        << "           positive number of words." << endl
+        << "           positive number of words. If it is '-'," << endl
+        << "           data are read from stdin." << endl
         << endl
         << "Command-specific options:" << endl
         << "  --alias    -a <alias>" << endl
@@ -54,89 +55,141 @@
 
 void CommandSiiWrite::execute(MasterDevice &m, const StringVector &args)
 {
-    SlaveList slaves;
     stringstream err;
     ec_ioctl_slave_sii_t data;
     ifstream file;
-    unsigned int byte_size;
-    const uint16_t *categoryHeader;
-    uint16_t categoryType, categorySize;
-    uint8_t crc;
+    SlaveList slaves;
 
     if (args.size() != 1) {
         err << "'" << getName() << "' takes exactly one argument!";
         throwInvalidUsageException(err);
     }
 
-    file.open(args[0].c_str(), ifstream::in | ifstream::binary);
-    if (file.fail()) {
-        err << "Failed to open '" << args[0] << "'!";
-        throwCommandException(err);
+    if (args[0] == "-") {
+        loadSiiData(&data, cin);
+    } else {
+        file.open(args[0].c_str(), ifstream::in | ifstream::binary);
+        if (file.fail()) {
+            err << "Failed to open '" << args[0] << "'!";
+            throwCommandException(err);
+        }
+        loadSiiData(&data, file);
+        file.close();
     }
 
-    // get length of file
-    file.seekg(0, ios::end);
-    byte_size = file.tellg();
-    file.seekg(0, ios::beg);
-
-    if (!byte_size || byte_size % 2) {
-        err << "Invalid file size! Must be non-zero and even.";
-        throwCommandException(err);
-    }
-
-    data.nwords = byte_size / 2;
-    if (data.nwords < 0x0041 && !force) {
-        err << "SII data too short (" << data.nwords << " words)! Mimimum is"
-                " 40 fixed words + 1 delimiter. Use --force to write anyway.";
-        throwCommandException(err);
-    }
-
-    // allocate buffer and read file into buffer
-    data.words = new uint16_t[data.nwords];
-    file.read((char *) data.words, byte_size);
-    file.close();
-
     if (!force) {
-        // calculate checksum over words 0 to 6
-        crc = calcSiiCrc((const uint8_t *) data.words, 14);
-        if (crc != ((const uint8_t *) data.words)[14]) {
-            err << "CRC incorrect. Must be 0x"
-                << hex << setfill('0') << setw(2) << (unsigned int) crc
-                << ". Use --force to write anyway.";
-            throwCommandException(err);
-        }
-
-        // cycle through categories to detect corruption
-        categoryHeader = data.words + 0x0040U;
-        categoryType = le16tocpu(*categoryHeader);
-        while (categoryType != 0xffff) {
-            if (categoryHeader + 1 > data.words + data.nwords) {
-                err << "SII data seem to be corrupted! "
-                    << "Use --force to write anyway.";
-                throwCommandException(err);
-            }
-            categorySize = le16tocpu(*(categoryHeader + 1));
-            if (categoryHeader + 2 + categorySize + 1
-                    > data.words + data.nwords) {
-                err << "SII data seem to be corrupted! "
-                    "Use --force to write anyway.";
-                throwCommandException(err);
-            }
-            categoryHeader += 2 + categorySize;
-            categoryType = le16tocpu(*categoryHeader);
+        try {
+            checkSiiData(&data);
+        } catch (CommandException &e) {
+            delete [] data.words;
+            throw e;
         }
     }
 
-    m.open(MasterDevice::ReadWrite);
+    try {
+        m.open(MasterDevice::ReadWrite);
+    } catch (MasterDeviceException &e) {
+        delete [] data.words;
+        throw e;
+    }
+
     slaves = selectedSlaves(m);
     if (slaves.size() != 1) {
+        delete [] data.words;
         throwSingleSlaveRequired(slaves.size());
     }
     data.slave_position = slaves.front().position;
 
     // send data to master
     data.offset = 0;
-	m.writeSii(&data);
+    try {
+        m.writeSii(&data);
+    } catch (MasterDeviceException &e) {
+        delete [] data.words;
+        throw e;
+    }
+
+    if (getVerbosity() == Verbose) {
+        cerr << "SII writing finished." << endl;
+    }
+
+    delete [] data.words;
 }
 
 /*****************************************************************************/
+
+void CommandSiiWrite::loadSiiData(
+        ec_ioctl_slave_sii_t *data,
+        const istream &in
+        )
+{
+    stringstream err;
+    ostringstream tmp;
+
+    tmp << in.rdbuf();
+    string const &contents = tmp.str();
+
+    if (getVerbosity() == Verbose) {
+        cerr << "Read " << contents.size() << " bytes of SII data." << endl;
+    }
+
+    if (!contents.size() || contents.size() % 2) {
+        err << "Invalid data size " << contents.size() << "! "
+            << "Must be non-zero and even.";
+        throwCommandException(err);
+    }
+    data->nwords = contents.size() / 2;
+
+    // allocate buffer and read file into buffer
+    data->words = new uint16_t[data->nwords];
+    contents.copy((char *) data->words, contents.size());
+}
+
+/*****************************************************************************/
+
+void CommandSiiWrite::checkSiiData(
+        const ec_ioctl_slave_sii_t *data
+        )
+{
+    stringstream err;
+    const uint16_t *categoryHeader;
+    uint16_t categoryType, categorySize;
+    uint8_t crc;
+
+    if (data->nwords < 0x0041) {
+        err << "SII data too short (" << data->nwords << " words)! Mimimum is"
+            " 40 fixed words + 1 delimiter. Use --force to write anyway.";
+        throwCommandException(err);
+    }
+
+    // calculate checksum over words 0 to 6
+    crc = calcSiiCrc((const uint8_t *) data->words, 14);
+    if (crc != ((const uint8_t *) data->words)[14]) {
+        err << "CRC incorrect. Must be 0x"
+            << hex << setfill('0') << setw(2) << (unsigned int) crc
+            << ". Use --force to write anyway.";
+        throwCommandException(err);
+    }
+
+    // cycle through categories to detect corruption
+    categoryHeader = data->words + 0x0040U;
+    categoryType = le16tocpu(*categoryHeader);
+    while (categoryType != 0xffff) {
+        if (categoryHeader + 1 > data->words + data->nwords) {
+            err << "SII data seem to be corrupted! "
+                << "Use --force to write anyway.";
+            throwCommandException(err);
+        }
+        categorySize = le16tocpu(*(categoryHeader + 1));
+        if (categoryHeader + 2 + categorySize + 1
+                > data->words + data->nwords) {
+            err << "SII data seem to be corrupted! "
+                "Use --force to write anyway.";
+            throwCommandException(err);
+        }
+        categoryHeader += 2 + categorySize;
+        categoryType = le16tocpu(*categoryHeader);
+    }
+}
+
+/*****************************************************************************/
--- a/tool/CommandSiiWrite.h	Mon Jul 28 12:15:25 2008 +0000
+++ b/tool/CommandSiiWrite.h	Mon Jul 28 13:15:19 2008 +0000
@@ -19,6 +19,10 @@
 
         string helpString() const;
         void execute(MasterDevice &, const StringVector &);
+
+    protected:
+        void loadSiiData(ec_ioctl_slave_sii_t *, const istream &);
+        void checkSiiData(const ec_ioctl_slave_sii_t *data);
 };
 
 /****************************************************************************/