Store abort code in sdo request; output it in user space; added some
authorFlorian Pose <fp@igh-essen.com>
Thu, 19 Jun 2008 09:24:22 +0000
changeset 1037 59f191c9185b
parent 1036 dc2008bc8113
child 1038 7ca4103ba170
Store abort code in sdo request; output it in user space; added some
re_size checking in fsm_coe.
TODO
master/cdev.c
master/fsm_coe.c
master/ioctl.h
master/sdo_request.c
master/sdo_request.h
tools/Master.cpp
--- a/TODO	Thu Jun 19 08:06:49 2008 +0000
+++ b/TODO	Thu Jun 19 09:24:22 2008 +0000
@@ -16,8 +16,7 @@
 * Update documentation.
 * Attach Pdo names from SII or Coe dictioary to Pdos read via CoE.
 * Add a -n (numeric) switch to ethercat command.
-* Remove Eoe cylces and Idle cycles.
-* Store Sdo abort code in sdo_request_t and output it in user space.
+* Remove Eoe cycles and Idle cycles.
 
 Future issues:
 
--- a/master/cdev.c	Thu Jun 19 08:06:49 2008 +0000
+++ b/master/cdev.c	Thu Jun 19 09:24:22 2008 +0000
@@ -628,6 +628,7 @@
                     if (request.req.state == EC_REQUEST_QUEUED) {
                         list_del(&request.req.list);
                         up(&master->sdo_sem);
+                        ec_sdo_request_clear(&request.req);
                         retval = -EINTR;
                         break;
                     }
@@ -637,27 +638,31 @@
 
                 // wait until master FSM has finished processing
                 wait_event(master->sdo_queue, request.req.state != EC_REQUEST_BUSY);
+                
+                data.abort_code = request.req.abort_code;
 
                 if (request.req.state != EC_REQUEST_SUCCESS) {
+                    data.data_size = 0;
                     retval = -EIO;
-                    break;
-                }
-
-                if (request.req.data_size > data.target_size) {
-                    EC_ERR("Buffer too small.\n");
-                    retval = -EOVERFLOW;
-                    break;
-                }
-                data.data_size = request.req.data_size;
-
-                if (copy_to_user((void __user *) data.target,
-                            request.req.data, data.data_size)) {
-                    retval = -EFAULT;
-                    break;
-                }
+                } else {
+                    if (request.req.data_size > data.target_size) {
+                        EC_ERR("Buffer too small.\n");
+                        ec_sdo_request_clear(&request.req);
+                        retval = -EOVERFLOW;
+                        break;
+                    }
+                    data.data_size = request.req.data_size;
+
+                    if (copy_to_user((void __user *) data.target,
+                                request.req.data, data.data_size)) {
+                        ec_sdo_request_clear(&request.req);
+                        retval = -EFAULT;
+                        break;
+                    }
+                }
+
                 if (__copy_to_user((void __user *) arg, &data, sizeof(data))) {
                     retval = -EFAULT;
-                    break;
                 }
 
                 ec_sdo_request_clear(&request.req);
@@ -721,6 +726,7 @@
                     if (request.req.state == EC_REQUEST_QUEUED) {
                         list_del(&request.req.list);
                         up(&master->sdo_sem);
+                        ec_sdo_request_clear(&request.req);
                         retval = -EINTR;
                         break;
                     }
@@ -731,9 +737,14 @@
                 // wait until master FSM has finished processing
                 wait_event(master->sdo_queue, request.req.state != EC_REQUEST_BUSY);
 
+                data.abort_code = request.req.abort_code;
+
                 if (request.req.state != EC_REQUEST_SUCCESS) {
                     retval = -EIO;
-                    break;
+                }
+
+                if (__copy_to_user((void __user *) arg, &data, sizeof(data))) {
+                    retval = -EFAULT;
                 }
 
                 ec_sdo_request_clear(&request.req);
--- a/master/fsm_coe.c	Thu Jun 19 08:06:49 2008 +0000
+++ b/master/fsm_coe.c	Thu Jun 19 09:24:22 2008 +0000
@@ -430,11 +430,23 @@
         return;
     }
 
+    if (rec_size < 3) {
+        EC_ERR("Received corrupted Sdo dictionary response (size %u).\n",
+                rec_size);
+        fsm->state = ec_fsm_coe_error;
+        return;
+    }
+
     if (EC_READ_U16(data) >> 12 == 0x8 && // Sdo information
         (EC_READ_U8(data + 2) & 0x7F) == 0x07) { // error response
         EC_ERR("Sdo information error response at slave %u!\n",
                slave->ring_position);
-        ec_canopen_abort_msg(EC_READ_U32(data + 6));
+        if (rec_size < 10) {
+            EC_ERR("Incomplete Sdo information error response:\n");
+            ec_print_data(data, rec_size);
+        } else {
+            ec_canopen_abort_msg(EC_READ_U32(data + 6));
+        }
         fsm->state = ec_fsm_coe_error;
         return;
     }
@@ -448,8 +460,8 @@
         return;
     }
 
-    if (rec_size < 8) {
-        EC_ERR("Invalid data size!\n");
+    if (rec_size < 8 || rec_size % 2) {
+        EC_ERR("Invalid data size %u!\n", rec_size);
         ec_print_data(data, rec_size);
         fsm->state = ec_fsm_coe_error;
         return;
@@ -656,6 +668,13 @@
         return;
     }
 
+    if (rec_size < 3) {
+        EC_ERR("Received corrupted Sdo description response (size %u).\n",
+                rec_size);
+        fsm->state = ec_fsm_coe_error;
+        return;
+    }
+
     if (EC_READ_U16(data) >> 12 == 0x8 && // Sdo information
         (EC_READ_U8 (data + 2) & 0x7F) == 0x07) { // error response
         EC_ERR("Sdo information error response at slave %u while"
@@ -666,6 +685,13 @@
         return;
     }
 
+    if (rec_size < 8) {
+        EC_ERR("Received corrupted Sdo description response (size %u).\n",
+                rec_size);
+        fsm->state = ec_fsm_coe_error;
+        return;
+    }
+
     if (EC_READ_U16(data) >> 12 != 0x8 || // Sdo information
         (EC_READ_U8 (data + 2) & 0x7F) != 0x04 || // Object desc. response
         EC_READ_U16(data + 6) != sdo->index) { // Sdo index
@@ -872,6 +898,13 @@
         return;
     }
 
+    if (rec_size < 3) {
+        EC_ERR("Received corrupted Sdo entry description response "
+                "(size %u).\n", rec_size);
+        fsm->state = ec_fsm_coe_error;
+        return;
+    }
+
     if (EC_READ_U16(data) >> 12 == 0x8 && // Sdo information
         (EC_READ_U8 (data + 2) & 0x7F) == 0x07) { // error response
         EC_ERR("Sdo information error response at slave %u while"
@@ -882,6 +915,13 @@
         return;
     }
 
+    if (rec_size < 9) {
+        EC_ERR("Received corrupted Sdo entry description response "
+                "(size %u).\n", rec_size);
+        fsm->state = ec_fsm_coe_error;
+        return;
+    }
+
     if (EC_READ_U16(data) >> 12 != 0x8 || // Sdo information
         (EC_READ_U8(data + 2) & 0x7F) != 0x06 || // Entry desc. response
         EC_READ_U16(data + 6) != sdo->index || // Sdo index
@@ -895,7 +935,7 @@
     }
 
     if (rec_size < 16) {
-        EC_ERR("Invalid data size!\n");
+        EC_ERR("Invalid data size %u!\n", rec_size);
         ec_print_data(data, rec_size);
         fsm->state = ec_fsm_coe_error;
         return;
@@ -1191,7 +1231,7 @@
 
     if (rec_size < 6) {
         fsm->state = ec_fsm_coe_error;
-        EC_ERR("Received data is too small (%u bytes):\n", rec_size);
+        EC_ERR("Received data are too small (%u bytes):\n", rec_size);
         ec_print_data(data, rec_size);
         return;
     }
@@ -1205,9 +1245,10 @@
         if (rec_size < 10) {
             EC_ERR("Incomplete Abort command:\n");
             ec_print_data(data, rec_size);
-        }
-        else
-            ec_canopen_abort_msg(EC_READ_U32(data + 6));
+        } else {
+            fsm->request->abort_code = EC_READ_U32(data + 6);
+            ec_canopen_abort_msg(fsm->request->abort_code);
+        }
         return;
     }
 
@@ -1446,10 +1487,12 @@
         EC_READ_U8 (data + 2) >> 5 == 0x4) { // abort Sdo transfer request
         EC_ERR("Sdo upload 0x%04X:%02X aborted on slave %u.\n",
                request->index, request->subindex, slave->ring_position);
-        if (rec_size >= 10)
-            ec_canopen_abort_msg(EC_READ_U32(data + 6));
-        else
+        if (rec_size >= 10) {
+            request->abort_code = EC_READ_U32(data + 6);
+            ec_canopen_abort_msg(request->abort_code);
+        } else {
             EC_ERR("No abort message.\n");
+        }
         fsm->state = ec_fsm_coe_error;
         return;
     }
@@ -1737,7 +1780,8 @@
         EC_READ_U8 (data + 2) >> 5 == 0x4) { // abort Sdo transfer request
         EC_ERR("Sdo upload 0x%04X:%02X aborted on slave %u.\n",
                request->index, request->subindex, slave->ring_position);
-        ec_canopen_abort_msg(EC_READ_U32(data + 6));
+        request->abort_code = EC_READ_U32(data + 6);
+        ec_canopen_abort_msg(request->abort_code);
         fsm->state = ec_fsm_coe_error;
         return;
     }
--- a/master/ioctl.h	Thu Jun 19 08:06:49 2008 +0000
+++ b/master/ioctl.h	Thu Jun 19 09:24:22 2008 +0000
@@ -67,7 +67,7 @@
 #define EC_IOCTL_SDO              EC_IOWR(0x0a, ec_ioctl_sdo_t)
 #define EC_IOCTL_SDO_ENTRY        EC_IOWR(0x0b, ec_ioctl_sdo_entry_t)
 #define EC_IOCTL_SDO_UPLOAD       EC_IOWR(0x0c, ec_ioctl_sdo_upload_t)
-#define EC_IOCTL_SDO_DOWNLOAD      EC_IOW(0x0d, ec_ioctl_sdo_download_t)
+#define EC_IOCTL_SDO_DOWNLOAD     EC_IOWR(0x0d, ec_ioctl_sdo_download_t)
 #define EC_IOCTL_SII_READ         EC_IOWR(0x0e, ec_ioctl_sii_t)
 #define EC_IOCTL_SII_WRITE         EC_IOW(0x0f, ec_ioctl_sii_t)
 #define EC_IOCTL_CONFIG           EC_IOWR(0x10, ec_ioctl_config_t)
@@ -253,6 +253,7 @@
 
     // outputs
     uint32_t data_size;
+    uint32_t abort_code;
 } ec_ioctl_sdo_upload_t;
 
 /*****************************************************************************/
@@ -264,6 +265,9 @@
     uint8_t sdo_entry_subindex;
     uint32_t data_size;
     uint8_t *data;
+
+    // outputs
+    uint32_t abort_code;
 } ec_ioctl_sdo_download_t;
 
 /*****************************************************************************/
--- a/master/sdo_request.c	Thu Jun 19 08:06:49 2008 +0000
+++ b/master/sdo_request.c	Thu Jun 19 09:24:22 2008 +0000
@@ -73,6 +73,7 @@
     req->issue_timeout = 0; // no timeout
     req->response_timeout = 0; // immediate response required
     req->state = EC_REQUEST_INIT;
+    req->abort_code = 0x00000000;
 }
 
 /*****************************************************************************/
@@ -211,6 +212,7 @@
 {
     req->dir = EC_DIR_INPUT;
     req->state = EC_REQUEST_QUEUED;
+    req->abort_code = 0x00000000;
     req->jiffies_start = jiffies;
 }
 
@@ -220,6 +222,7 @@
 {
     req->dir = EC_DIR_OUTPUT;
     req->state = EC_REQUEST_QUEUED;
+    req->abort_code = 0x00000000;
     req->jiffies_start = jiffies;
 }
 
--- a/master/sdo_request.h	Thu Jun 19 08:06:49 2008 +0000
+++ b/master/sdo_request.h	Thu Jun 19 09:24:22 2008 +0000
@@ -69,6 +69,7 @@
     unsigned long jiffies_start; /**< Jiffies, when the request was issued. */
     unsigned long jiffies_sent; /**< Jiffies, when the upload/download
                                      request was sent. */
+    uint32_t abort_code; /**< Sdo request abort code. Zero on success. */
 };
 
 /*****************************************************************************/
--- a/tools/Master.cpp	Thu Jun 19 08:06:49 2008 +0000
+++ b/tools/Master.cpp	Thu Jun 19 09:24:22 2008 +0000
@@ -656,7 +656,13 @@
 
     if (ioctl(fd, EC_IOCTL_SDO_DOWNLOAD, &data) < 0) {
         stringstream err;
-        err << "Failed to download Sdo: " << strerror(errno);
+        err << "Failed to download Sdo: ";
+        if (errno == EIO && data.abort_code) {
+            err << "Abort code 0x" << hex << setfill('0') << setw(8)
+                << data.abort_code;
+        } else {
+            err << strerror(errno);
+        }
         delete [] data.data;
         throw MasterException(err.str());
     }
@@ -751,7 +757,13 @@
 
     if (ioctl(fd, EC_IOCTL_SDO_UPLOAD, &data) < 0) {
         stringstream err;
-        err << "Failed to upload Sdo: " << strerror(errno);
+        err << "Failed to upload Sdo: ";
+        if (errno == EIO && data.abort_code) {
+            err << "Abort code 0x" << hex << setfill('0') << setw(8)
+                << data.abort_code;
+        } else {
+            err << strerror(errno);
+        }
         delete [] data.target;
         close();
         throw MasterException(err.str());