# HG changeset patch # User Florian Pose # Date 1213867462 0 # Node ID 59f191c9185ba4253a9c34fa796b60526d5101c2 # Parent dc2008bc8113c9f8d0616e3b5538ef944664bf42 Store abort code in sdo request; output it in user space; added some re_size checking in fsm_coe. diff -r dc2008bc8113 -r 59f191c9185b TODO --- 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: diff -r dc2008bc8113 -r 59f191c9185b master/cdev.c --- 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); diff -r dc2008bc8113 -r 59f191c9185b master/fsm_coe.c --- 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; } diff -r dc2008bc8113 -r 59f191c9185b master/ioctl.h --- 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; /*****************************************************************************/ diff -r dc2008bc8113 -r 59f191c9185b master/sdo_request.c --- 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; } diff -r dc2008bc8113 -r 59f191c9185b master/sdo_request.h --- 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. */ }; /*****************************************************************************/ diff -r dc2008bc8113 -r 59f191c9185b tools/Master.cpp --- 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());