INTEGER16 CO_SDOclient_init( CO_SDOclient_t **ppSDOclient, CO_SDO_t *SDO, OD_SDOClientParameter_t *ObjDict_SDOClientParameter, CO_CANmodule_t *CANdevRx, UNSIGNED16 CANdevRxIdx, CO_CANmodule_t *CANdevTx, UNSIGNED16 CANdevTxIdx) { CO_SDOclient_t *SDO_C; //verify parameters if(ObjDict_SDOClientParameter->maxSubIndex!=3) return CO_ERROR_ILLEGAL_ARGUMENT; //allocate memory if not already allocated if((*ppSDOclient) == NULL) { if(((*ppSDOclient) = (CO_SDOclient_t*) malloc(sizeof(CO_SDOclient_t))) == NULL) { return CO_ERROR_OUT_OF_MEMORY; } } SDO_C = *ppSDOclient; //pointer to (newly created) object //Configure object variables SDO_C->state = 0; SDO_C->SDO = SDO; SDO_C->ObjDict_SDOClientParameter = ObjDict_SDOClientParameter; SDO_C->CANdevRx = CANdevRx; SDO_C->CANdevRxIdx = CANdevRxIdx; SDO_C->CANdevTx = CANdevTx; SDO_C->CANdevTxIdx = CANdevTxIdx; CO_SDOclient_setup(SDO_C, 0, 0, 0); return CO_ERROR_NO; }
static void huge _pascal CgiCliFunction(rpCgiPtr CgiRequest){ /* Buffers for building the page */ extern CgiCli_t *CgiCli; extern CO_t *CO; CO_SDOclient_t *SDO_C = CO->SDOclient; uint32_t bufLen = 0; /* current length of the buffer */ uint32_t timeouts = 0; const uint32_t maxTimeouts = 5; /* Prepare function, which will wake this task after CAN SDO response is */ /* received (inside CAN receive interrupt). */ SDO_C->pFunctSignal = CgiCli_signal; /* will wake from RTX_Sleep_Time() */ SDO_C->functArg = RTX_Get_TaskID(); /* id of this task */ /* Construct HTML page */ if(strlen(CgiRequest->fArgumentBufferPtr)){ char_t *buf = CgiCli->buf; /* buffer for CGI message */ char_t far *name = NULL; char_t far *val = NULL; while(CGI_GetArgument(&name, &val, CgiRequest) == 0){ /* decode and verify name */ char_t rw = name[0]; uint32_t nodeId, idx, sidx, len; char_t err = 0; uint8_t *data = CgiCli->SDOBuf; /* data sent or received on CANopen */ uint32_t dataLen = 0; if(!name) err++; len = strlen(name); if (rw == 'r' || rw == 'R'){ rw = 'r'; if(len < 9 || len > 17) err++; } else if(rw == 'w' || rw == 'W'){ rw = 'w'; if(len < 10 || len > 17) err++; } else{ err++; } err += hex2dec(&name[1], 2, &nodeId); if(nodeId > 127) err++; err += hex2dec(&name[3], 4, &idx); err += hex2dec(&name[7], 2, &sidx); if(rw == 'w'){ err += hex2dec(&name[9], len-9, &len); /* decode value */ int32_t i; int32_t valLen; if(val) valLen = strlen(val); else valLen = 0; for(i=0; i<valLen; i=i+2){ uint32_t dc; err += hex2dec(&val[i], 2, &dc); data[dataLen] = dc; if(++dataLen >= CgiCli->SDOBufSize) break; } /* verify value length */ if(dataLen != len || dataLen == 0) err++; } /* SDO clinet access */ uint32_t SDOabortCode = 0; if(err){ buf += sprintf(buf, "Error in argument: %s=%s\n", name, val); } /* read object dictionary */ else if(rw == 'r'){ CO_SDOclient_return_t ret; CO_SDOclient_setup(SDO_C, 0, 0, nodeId); CO_SDOclientUploadInitiate(SDO_C, idx, sidx, data, CgiCli->SDOBufSize, 1); do{ uint16_t dt = 50; ret = CO_SDOclientUpload(SDO_C, dt, 500, &dataLen, &SDOabortCode); RTX_Sleep_Time(dt); }while(ret > 0); CO_SDOclientClose(SDO_C); if(ret == CO_SDOcli_endedWithTimeout) { timeouts++; } else { timeouts = 0; } if(SDOabortCode){ buf += sprintf(buf, "R %02X%04X%02X%X AB: %08X\n", (unsigned int)nodeId, (unsigned int)idx, (unsigned int)sidx, (unsigned int)dataLen, (unsigned int)SDOabortCode); } else{ uint32_t i; buf += sprintf(buf, "R %02X%04X%02X%X OK:", (unsigned int)nodeId, (unsigned int)idx, (unsigned int)sidx, (unsigned int)dataLen); for(i=0; i<dataLen; i++) buf += sprintf(buf, " %02X", data[i]); buf += sprintf(buf, "\n"); } } /* write into object dictionary */ else if(rw == 'w'){ CO_SDOclient_return_t ret; CO_SDOclient_setup(SDO_C, 0, 0, nodeId); CO_SDOclientDownloadInitiate(SDO_C, idx, sidx, data, dataLen, 1); do{ uint16_t dt = 2; ret = CO_SDOclientDownload(SDO_C, dt, 500, &SDOabortCode); if(ret == CO_SDOcli_waitingServerResponse) { dt = 50; } RTX_Sleep_Time(dt); }while(ret > 0); CO_SDOclientClose(SDO_C); if(ret == CO_SDOcli_endedWithTimeout) { timeouts++; } else { timeouts = 0; } if(SDOabortCode){ buf += sprintf(buf, "W %02X%04X%02X%X AB: %08X\n", (unsigned int)nodeId, (unsigned int)idx, (unsigned int)sidx, (unsigned int)dataLen, (unsigned int)SDOabortCode); } else{ uint32_t i; buf += sprintf(buf, "W %02X%04X%02X%X OK:", (unsigned int)nodeId, (unsigned int)idx, (unsigned int)sidx, (unsigned int)dataLen); for(i=0; i<dataLen; i++) buf += sprintf(buf, " %02X", data[i]); buf += sprintf(buf, "\n"); } } /* calculate buffer length, if not enough space for next object, break */ bufLen = (uint32_t)(buf - CgiCli->buf); if((bufLen+1000) > CgiCli->bufSize){ break; } /* if no response from remote node for multiple times, break the loop */ if(timeouts > maxTimeouts){ break; } } } else{ sprintf(CgiCli->buf, "CGI function provides access to object dictionary on any device on the CANopen network.\n\n" "Usage with POST method:\n" " odcli?wnniiiissll=xxxx[&rnniiiissll=]\n" " w - 'w'rite or 'r'ead.\n" " nn - node ID in hex format.\n" " iiii - Object dictionary index in hex format.\n" " ss - Object dictionary subindex in hex format.\n" " ll - length of variable (1 to FFFFFFFF) in hex format. If reading, this value is ignored.\n" " xxxx - Value to be written in hex and little endian format. If reading, this value is ignored.\n"); bufLen = strlen(CgiCli->buf); } /* disable SDO client */ CO_SDOclient_setup(SDO_C, 0, 0, 0); /* Give page to the web server */ CgiRequest->fHttpResponse = CgiHttpOk; CgiRequest->fDataType = CGIDataTypeText; CgiRequest->fResponseBufferPtr = CgiCli->buf; CgiRequest->fResponseBufferLength = bufLen; }