日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

CANOpen服务数据对象报文

發(fā)布時間:2025/3/15 编程问答 51 豆豆
生活随笔 收集整理的這篇文章主要介紹了 CANOpen服务数据对象报文 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
SDO是服務(wù)數(shù)據(jù)對象接口(ServiceData Object)的縮寫,顧名思義提供服務(wù)數(shù)據(jù)的訪問接口,所謂服務(wù)數(shù)據(jù)指一些實時性要求不高的數(shù)據(jù),一般是指節(jié)點配置參數(shù),因此,SDO一般用來配置和獲得節(jié)點的配置參數(shù),充當OD對外的接口。

SDO基于CS模式,所有報文都需要確認。通常從節(jié)點作為SDO服務(wù)器,主節(jié)點作為客戶端。客戶端通過索引和子索引,訪問服務(wù)器上的任意對象字典,SDO的上傳與下載,是從server的角度去理解的,上傳:clientserverOD進行讀操作;下載:clientserverOD進行寫操作。

傳送機制有兩種:域傳送和塊傳送。

SDO報文格式如下:



SDO域傳輸一共實現(xiàn)了5個請求/應(yīng)答協(xié)議:啟動域下載,啟動域上傳,域分段下載,域分段上傳,域傳送中止。

SDO命令字包含如下信息:該報文是上傳還是下載,該報文是請求還是應(yīng)答,該報文是分段還是加速,CAN幀數(shù)據(jù)字節(jié)長度,后續(xù)分段的觸發(fā)位。

塊傳輸這里不進行詳細討論,只給出塊下載流程:
?1.客戶端:初始化傳輸通道
?????????? 發(fā)送塊下載初始化指令,包括索引、子索引、字節(jié)數(shù)


?2.服務(wù)器:初始化傳輸通道
?????????? 發(fā)送塊下載初始化響應(yīng),包括索引、子索引、一次傳輸塊數(shù)量


?3.客戶端:復(fù)位傳輸超時定時器
?????????? 發(fā)送多個數(shù)據(jù)包塊下載,包括是否最后一塊、序列號、數(shù)據(jù)


?4.服務(wù)器:復(fù)位傳輸超時定時器
?????????? 將數(shù)據(jù)拷貝到傳輸通道
?????????? 發(fā)送數(shù)據(jù)包塊下載響應(yīng),包括序列號、一次傳輸塊數(shù)量


?5.客戶端:如果沒有下載完,重復(fù)步驟3、4
?????????? 如果下載完,發(fā)送塊下載結(jié)束指令,包括最后一塊補零數(shù)


?6.服務(wù)器:發(fā)送塊下載結(jié)束響應(yīng)
?????????? 將數(shù)據(jù)拷貝到字典中
?????????? 復(fù)位傳輸通道


?7.客戶端:停止傳輸超時定時器
?????????? 設(shè)置傳輸通道為完成狀態(tài)
?????????? 調(diào)用傳輸完成回調(diào)函數(shù)



#include <stdlib.h> #include "canfestival.h" #include "sysdep.h"#define NO_INLINE#ifdef NO_INLINE #define INLINE #else #define INLINE inline #endif/* 通過節(jié)點號查找客戶端號 */ UNS8 GetSDOClientFromNodeId(CO_Data *d, UNS8 nodeId);/* 寫服務(wù)器字典 */ INLINE UNS8 _writeNetworkDict(CO_Data *d, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS32 count, UNS8 dataType, void *data, SDOCallback_t Callback, UNS8 endianize, UNS8 useBlockMode);/* 讀服務(wù)器字典 */ INLINE UNS8 _readNetworkDict(CO_Data *d, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS8 dataType, SDOCallback_t Callback, UNS8 useBlockMode);#define getSDOcs(byte) (byte >> 5) #define getSDOn2(byte) ((byte >> 2) & 3) #define getSDOn3(byte) ((byte >> 1) & 7) #define getSDOe(byte) ((byte >> 1) & 1) #define getSDOs(byte) (byte & 1) #define getSDOc(byte) (byte & 1) #define getSDOt(byte) ((byte >> 4) & 1) #define getSDOindex(byte1, byte2) (((UNS16)byte2 << 8) | ((UNS16)byte1)) #define getSDOsubIndex(byte3) (byte3) #define getSDOblockSC(byte) (byte & 3)/* sdo傳輸超時回調(diào)函數(shù) */ void SDOTimeoutAlarm(CO_Data *d, UNS32 id) {UNS16 offset;UNS8 nodeId;/* 第一個sdo客戶端在字典中的下標 */offset = d->firstIndex->SDO_CLT;if((offset == 0) || ((offset + d->transfers[id].CliServNbr) > d->lastIndex->SDO_CLT)) {return;}/* 從字典中取出服務(wù)器節(jié)點id */nodeId = (UNS8)*((UNS32*)d->objdict[offset + d->transfers[id].CliServNbr].pSubindex[3].pObject);MSG_ERR(0x1A01, "SDO timeout. SDO response not received.", 0);MSG_WAR(0x2A02, "server node id : ", nodeId);MSG_WAR(0x2A02, " index : ", d->transfers[id].index);MSG_WAR(0x2A02, " subIndex : ", d->transfers[id].subIndex);/* 傳輸通道超時定時器置空 */d->transfers[id].timer = TIMER_NONE;/* 傳輸通道狀態(tài)設(shè)置為內(nèi)部中止 */d->transfers[id].state = SDO_ABORTED_INTERNAL;/* 向主站發(fā)送中止報文 */sendSDOabort(d, d->transfers[id].whoami, d->transfers[id].CliServNbr, d->transfers[id].index, d->transfers[id].subIndex, SDOABT_TIMED_OUT);/* 錯誤碼設(shè)置為超時 */d->transfers[id].abortCode = SDOABT_TIMED_OUT;/* 如果傳輸通道超時,則調(diào)用回調(diào)函數(shù) */if(d->transfers[id].Callback)(*d->transfers[id].Callback)(d, nodeId);/* 復(fù)位sdo傳輸通道 */if(d->transfers[id].abortCode == SDOABT_TIMED_OUT) resetSDOline(d, (UNS8)id); }/* 停止sdo超時定時器 */ #define StopSDO_TIMER(id) \MSG_WAR(0x3A05, "StopSDO_TIMER for line : ", line);\ d->transfers[id].timer = DelAlarm(d->transfers[id].timer);/* 啟動sdo超時定時器 */ #define StartSDO_TIMER(id) \MSG_WAR(0x3A06, "StartSDO_TIMER for line : ", line);\d->transfers[id].timer = SetAlarm(d, id, &SDOTimeoutAlarm,MS_TO_TIMEVAL(SDO_TIMEOUT_MS),0);/* 重啟sdo超時定時器 */ #define RestartSDO_TIMER(id) \MSG_WAR(0x3A07, "restartSDO_TIMER for line : ", line);\ if(d->transfers[id].timer != TIMER_NONE) { StopSDO_TIMER(id) StartSDO_TIMER(id) }/* 復(fù)位所有sdo傳輸通道 */ void resetSDO(CO_Data *d) {UNS8 j;/* 復(fù)位所有sdo傳輸通道 */for(j = 0; j < SDO_MAX_SIMULTANEOUS_TRANSFERS; j++){resetSDOline(d, j);} }/* 將數(shù)據(jù)從傳輸通道緩沖區(qū)拷貝到字典中 */ UNS32 SDOlineToObjdict(CO_Data *d, UNS8 line) {UNS32 size;UNS32 errorCode;MSG_WAR(0x3A08, "Enter in SDOlineToObjdict ", line);/* 確定該傳輸通道傳輸了多少字節(jié) */if(d->transfers[line].count == 0){d->transfers[line].count = d->transfers[line].offset;}size = d->transfers[line].count;/* 將數(shù)據(jù)拷貝到字典中 */ #ifdef SDO_DYNAMIC_BUFFER_ALLOCATIONif(size > SDO_MAX_LENGTH_TRANSFER){errorCode = setODentry(d, d->transfers[line].index, d->transfers[line].subIndex, (void *)d->transfers[line].dynamicData, &size, 1);}else{errorCode = setODentry(d, d->transfers[line].index, d->transfers[line].subIndex,(void *)d->transfers[line].data, &size, 1);} #elseerrorCode = setODentry(d, d->transfers[line].index, d->transfers[line].subIndex,(void *)d->transfers[line].data, &size, 1); #endifif(errorCode != OD_SUCCESSFUL)return errorCode;MSG_WAR(0x3A08, "exit of SDOlineToObjdict ", line);return 0;}/* 將數(shù)據(jù)從字典中拷貝到傳輸通道緩沖區(qū) */ UNS32 objdictToSDOline(CO_Data *d, UNS8 line) {UNS32 size = SDO_MAX_LENGTH_TRANSFER;UNS8 dataType;UNS32 errorCode;MSG_WAR(0x3A05, "objdict->line index : ", d->transfers[line].index);MSG_WAR(0x3A06, " subIndex : ", d->transfers[line].subIndex);/* 支持動態(tài)內(nèi)存分配 */ #ifdef SDO_DYNAMIC_BUFFER_ALLOCATION/* 從字典中將數(shù)據(jù)拷貝出來 */errorCode = getODentry(d, d->transfers[line].index, d->transfers[line].subIndex, (void *)d->transfers[line].data, &size, &dataType, 1);/* 如果內(nèi)存不夠拷貝 */if(errorCode == SDOABT_OUT_OF_MEMORY) {if(size <= SDO_DYNAMIC_BUFFER_ALLOCATION_SIZE) {/* 動態(tài)分配內(nèi)存 */d->transfers[line].dynamicData = (UNS8 *)malloc(size * sizeof(UNS8));if(d->transfers[line].dynamicData != NULL) {d->transfers[line].dynamicDataSize = size;/* 從字典中將數(shù)據(jù)拷貝出來 */errorCode = getODentry(d, d->transfers[line].index, d->transfers[line].subIndex, (void *)d->transfers[line].dynamicData,&d->transfers[line].dynamicDataSize, &dataType, 1);}}} #else/* 從字典中將數(shù)據(jù)拷貝出來 */errorCode = getODentry(d, d->transfers[line].index, d->transfers[line].subIndex, (void *)d->transfers[line].data, &size, &dataType, 1); #endifif(errorCode != OD_SUCCESSFUL)return errorCode;d->transfers[line].count = size;d->transfers[line].offset = 0;return 0; }/* 將數(shù)據(jù)從傳輸通道緩沖區(qū)拷貝出來 */ UNS8 lineToSDO(CO_Data *d, UNS8 line, UNS32 nbBytes, UNS8 *data) {UNS8 i;UNS32 offset;#ifndef SDO_DYNAMIC_BUFFER_ALLOCATION/* 如果不支持內(nèi)存動態(tài)分配,并且字節(jié)數(shù)大于靜態(tài)緩沖區(qū),則報錯 */if((d->transfers[line].offset + nbBytes) > SDO_MAX_LENGTH_TRANSFER) {MSG_ERR(0x1A10,"SDO Size of data too large. Exceed SDO_MAX_LENGTH_TRANSFER", nbBytes);return 0xFF;} #endif/* 如果傳輸通道字節(jié)數(shù)大于配置的大小 */if((d->transfers[line].offset + nbBytes) > d->transfers[line].count) {MSG_ERR(0x1A11,"SDO Size of data too large. Exceed count", nbBytes);return 0xFF;}offset = d->transfers[line].offset; #ifdef SDO_DYNAMIC_BUFFER_ALLOCATION/* 如果說sdo傳輸通道字節(jié)數(shù)小于靜態(tài)緩沖區(qū) */if(d->transfers[line].count <= SDO_MAX_LENGTH_TRANSFER){/* 將數(shù)據(jù)從靜態(tài)緩沖區(qū)拷貝出來 */for(i = 0; i < nbBytes; i++)*(data + i) = d->transfers[line].data[offset + i];}/* 如果說sdo傳輸通道字節(jié)數(shù)大于靜態(tài)緩沖區(qū) */else{if(d->transfers[line].dynamicData == NULL){MSG_ERR(0x1A11,"SDO's dynamic buffer not allocated. Line", line);return 0xFF;}/* 將數(shù)據(jù)從動態(tài)緩沖區(qū)拷貝出來 */for(i = 0; i < nbBytes; i++)*(data + i) = d->transfers[line].dynamicData[offset + i];} #else/* 將數(shù)據(jù)拷貝出來 */for(i = 0; i < nbBytes; i++)*(data + i) = d->transfers[line].data[offset + i]; #endif/* 偏移量增大 */d->transfers[line].offset = d->transfers[line].offset + nbBytes;return 0; }/* 將數(shù)據(jù)拷貝到傳輸通道緩沖區(qū) */ UNS8 SDOtoLine(CO_Data *d, UNS8 line, UNS32 nbBytes, UNS8 *data) {UNS8 i;UNS32 offset;#ifndef SDO_DYNAMIC_BUFFER_ALLOCATION/* 不允許動態(tài)分配時數(shù)據(jù)量不能大于緩沖區(qū) */if((d->transfers[line].offset + nbBytes) > SDO_MAX_LENGTH_TRANSFER) {MSG_ERR(0x1A15,"SDO Size of data too large. Exceed SDO_MAX_LENGTH_TRANSFER", nbBytes);return 0xFF;} #endif/* 緩沖區(qū)偏移量 */offset = d->transfers[line].offset;#ifdef SDO_DYNAMIC_BUFFER_ALLOCATION{UNS8 *lineData = d->transfers[line].data;/* 當數(shù)據(jù)量大于緩沖區(qū)時 */if((d->transfers[line].offset + nbBytes) > SDO_MAX_LENGTH_TRANSFER) {/* 如果還沒有動態(tài)分配內(nèi)存 */if(d->transfers[line].dynamicData == NULL) {/* 動態(tài)分配內(nèi)存 */d->transfers[line].dynamicData = (UNS8 *)malloc(SDO_DYNAMIC_BUFFER_ALLOCATION_SIZE);d->transfers[line].dynamicDataSize = SDO_DYNAMIC_BUFFER_ALLOCATION_SIZE;if(d->transfers[line].dynamicData == NULL) {MSG_ERR(0x1A15,"SDO allocating dynamic buffer failed, size", SDO_DYNAMIC_BUFFER_ALLOCATION_SIZE);return 0xFF;}/* 將靜態(tài)緩沖區(qū)數(shù)據(jù)拷貝到動態(tài)內(nèi)存區(qū) */memcpy(d->transfers[line].dynamicData, d->transfers[line].data, offset);}/* 如果已經(jīng)動態(tài)分配內(nèi)存,則要重新分配 */else if((d->transfers[line].offset + nbBytes) > d->transfers[line].dynamicDataSize){UNS8 *newDynamicBuffer = (UNS8*)realloc(d->transfers[line].dynamicData, d->transfers[line].dynamicDataSize + SDO_DYNAMIC_BUFFER_ALLOCATION_SIZE);if(newDynamicBuffer == NULL) {MSG_ERR(0x1A15,"SDO reallocating dynamic buffer failed, size", d->transfers[line].dynamicDataSize + SDO_DYNAMIC_BUFFER_ALLOCATION_SIZE);return 0xFF;}d->transfers[line].dynamicData = newDynamicBuffer;d->transfers[line].dynamicDataSize += SDO_DYNAMIC_BUFFER_ALLOCATION_SIZE;}lineData = d->transfers[line].dynamicData;}/* 將數(shù)據(jù)拷貝到緩沖區(qū) */for(i = 0; i < nbBytes; i++){lineData[offset + i] = *(data + i);}} #else/* 將數(shù)據(jù)拷貝到緩沖區(qū) */for (i = 0; i < nbBytes; i++)d->transfers[line].data[offset + i] = *(data + i); #endif/* 緩沖區(qū)偏移量增加 */d->transfers[line].offset = d->transfers[line].offset + nbBytes;return 0; }/* sdo傳輸通道失敗 */ UNS8 failedSDO(CO_Data *d, UNS8 CliServNbr, UNS8 whoami, UNS16 index, UNS8 subIndex, UNS32 abortCode) {UNS8 err;UNS8 line;/* 通過客戶端/服務(wù)器號獲取sdo傳輸通道號 */err = getSDOlineOnUse(d, CliServNbr, whoami, &line);if(!err){MSG_WAR(0x3A20, "FailedSDO : line found : ", line);}/* 如果自身是服務(wù)器,直接復(fù)位傳輸通道 */if((!err) && (whoami == SDO_SERVER)) {resetSDOline(d, line);MSG_WAR(0x3A21, "FailedSDO : line released : ", line);}/* 如果自身是客戶端,則停止sdo傳輸超時定時器并將狀態(tài)置為中止并設(shè)置錯誤碼 */if((!err) && (whoami == SDO_CLIENT)) {StopSDO_TIMER(line);d->transfers[line].state = SDO_ABORTED_INTERNAL;d->transfers[line].abortCode = abortCode;}MSG_WAR(0x3A22, "Sending SDO abort ", 0);/* 發(fā)送sdo中止報文 */err = sendSDOabort(d, whoami, CliServNbr, index, subIndex, abortCode);if(err) {MSG_WAR(0x3A23, "Unable to send the SDO abort", 0);return 0xFF;}return 0; }/* 復(fù)位sdo通道 */ void resetSDOline(CO_Data *d, UNS8 line) {UNS32 i;MSG_WAR(0x3A25, "reset SDO line nb : ", line);/* 初始化sdo通道 */initSDOline(d, line, 0, 0, 0, SDO_RESET);/* 將sdo傳輸通道緩沖區(qū)清空 */for(i = 0; i < SDO_MAX_LENGTH_TRANSFER; i++)d->transfers[line].data[i] = 0;/* 傳輸通道歸屬(服務(wù)器/客戶端)清空 */d->transfers[line].whoami = 0;/* 傳輸通道錯誤碼清空 */d->transfers[line].abortCode = 0; }/* 初始化sdo傳輸通道 */ UNS8 initSDOline(CO_Data *d, UNS8 line, UNS8 CliServNbr, UNS16 index, UNS8 subIndex, UNS8 state) {MSG_WAR(0x3A25, "init SDO line nb : ", line);/* 判斷是否該SDO傳輸通道在域下載/域上傳/塊下載/塊上傳過程中 */if(state == SDO_DOWNLOAD_IN_PROGRESS || state == SDO_UPLOAD_IN_PROGRESS || state == SDO_BLOCK_DOWNLOAD_IN_PROGRESS || state == SDO_BLOCK_UPLOAD_IN_PROGRESS){/* 開啟sdo定時器,通訊超時做相應(yīng)處理 */StartSDO_TIMER(line)}/* 不在傳輸過程中,關(guān)閉定時器 */else{StopSDO_TIMER(line)}/* 初始化客戶端/服務(wù)器號 */d->transfers[line].CliServNbr = CliServNbr;/* 初始化對象索引 */d->transfers[line].index = index;/* 初始化對象子索引 */d->transfers[line].subIndex = subIndex;/* 初始化傳輸通道狀態(tài) */d->transfers[line].state = state;d->transfers[line].toggle = 0;/* 初始化字節(jié)數(shù) */d->transfers[line].count = 0;d->transfers[line].offset = 0;d->transfers[line].peerCRCsupport = 0;d->transfers[line].blksize = 0;d->transfers[line].ackseq = 0;d->transfers[line].objsize = 0;d->transfers[line].lastblockoffset = 0;d->transfers[line].seqno = 0;d->transfers[line].endfield = 0;/* 初始化塊傳輸接收狀態(tài) */d->transfers[line].rxstep = RXSTEP_INIT;d->transfers[line].dataType = 0;/* 超時回調(diào)函數(shù) */d->transfers[line].Callback = NULL; #ifdef SDO_DYNAMIC_BUFFER_ALLOCATIONfree(d->transfers[line].dynamicData);d->transfers[line].dynamicData = 0;d->transfers[line].dynamicDataSize = 0; #endifreturn 0; }/* 獲取空閑的sdo傳輸通道 */ UNS8 getSDOfreeLine(CO_Data *d, UNS8 whoami, UNS8 *line) {UNS8 i;/* 遍歷所有傳輸通道,查找空閑的傳輸通道 */for(i = 0; i < SDO_MAX_SIMULTANEOUS_TRANSFERS; i++){if(d->transfers[i].state == SDO_RESET) {*line = i;d->transfers[i].whoami = whoami;return 0;}}MSG_ERR(0x1A25, "Too many SDO in progress. Aborted.", i);return 0xFF; }/* 通過客戶端/服務(wù)器號獲取sdo傳輸通道號 */ UNS8 getSDOlineOnUse(CO_Data *d, UNS8 CliServNbr, UNS8 whoami, UNS8 *line) {UNS8 i;/* 遍歷所有sdo傳輸通道 */for(i = 0; i < SDO_MAX_SIMULTANEOUS_TRANSFERS; i++){/* 如果該通道處于正常狀態(tài)并且客戶端/服務(wù)器號匹配,則說明找到了該通道 */if((d->transfers[i].state != SDO_RESET) &&(d->transfers[i].state != SDO_ABORTED_INTERNAL) &&(d->transfers[i].CliServNbr == CliServNbr) &&(d->transfers[i].whoami == whoami)) {/* 獲取該通道號 */if(line){ *line = i;}return 0;}}return 0xFF; }/* 通過客戶端/服務(wù)器號獲取sdo傳輸通道號 */ UNS8 getSDOlineToClose(CO_Data *d, UNS8 CliServNbr, UNS8 whoami, UNS8 *line) {UNS8 i;for(i = 0; i < SDO_MAX_SIMULTANEOUS_TRANSFERS; i++){if((d->transfers[i].state != SDO_RESET) &&(d->transfers[i].CliServNbr == CliServNbr) &&(d->transfers[i].whoami == whoami)) {if(line) *line = i;return 0;}}return 0xFF; }/* 關(guān)閉sdo傳輸通道 */ UNS8 closeSDOtransfer(CO_Data *d, UNS8 nodeId, UNS8 whoami) {UNS8 err;UNS8 line;UNS8 CliNbr;/* 通過節(jié)點號查找客戶端號 */CliNbr = GetSDOClientFromNodeId(d, nodeId);if(CliNbr >= 0xFE)return SDO_ABORTED_INTERNAL;/* 通過客戶端/服務(wù)器號獲取sdo傳輸通道號 */err = getSDOlineToClose(d, CliNbr, whoami, &line);if(err) {MSG_WAR(0x2A30, "No SDO communication to close", 0);return 0xFF;}/* 復(fù)位sdo通道 */resetSDOline(d, line);return 0; }/* 獲取傳輸通道剩余字節(jié)數(shù) */ UNS8 getSDOlineRestBytes(CO_Data *d, UNS8 line, UNS32 *nbBytes) {if(d->transfers[line].count == 0)*nbBytes = 0;else*nbBytes = d->transfers[line].count - d->transfers[line].offset;return 0; }/* sdo傳輸通道剩余字節(jié)數(shù) */ UNS8 setSDOlineRestBytes(CO_Data *d, UNS8 line, UNS32 nbBytes) { #ifndef SDO_DYNAMIC_BUFFER_ALLOCATIONif(nbBytes > SDO_MAX_LENGTH_TRANSFER) {MSG_ERR(0x1A35,"SDO Size of data too large. Exceed SDO_MAX_LENGTH_TRANSFER", nbBytes);return 0xFF;} #endifd->transfers[line].count = nbBytes;return 0; }/* 發(fā)送sdo報文 */ UNS8 sendSDO(CO_Data *d, UNS8 whoami, UNS8 CliServNbr, UNS8 *pData) {UNS16 offset;UNS8 i;Message m;MSG_WAR(0x3A38, "sendSDO",0);/* 運行態(tài)或預(yù)運行態(tài)才可以使用sdo報文 */if(!((d->nodeState == Operational) || (d->nodeState == Pre_operational))) {MSG_WAR(0x2A39, "unable to send the SDO (not in op or pre-op mode", d->nodeState);return 0xFF;}/* 服務(wù)器端發(fā)送sdo報文 */if(whoami == SDO_SERVER) {/* 取出sdo服務(wù)器端的發(fā)送cob_id */offset = d->firstIndex->SDO_SVR;if((offset == 0) || ((offset + CliServNbr) > d->lastIndex->SDO_SVR)) {MSG_ERR(0x1A42, "SendSDO : SDO server not found", 0);return 0xFF;}m.cob_id = (UNS16)*((UNS32*)d->objdict[offset + CliServNbr].pSubindex[2].pObject);MSG_WAR(0x3A41, "I am server Tx cobId : ", m.cob_id);}/* 客戶端發(fā)送sdo報文 */else {/* 取出sdo客戶端發(fā)送cob_id */offset = d->firstIndex->SDO_CLT;if((offset == 0) || ((offset+CliServNbr) > d->lastIndex->SDO_CLT)) {MSG_ERR(0x1A42, "SendSDO : SDO client not found", 0);return 0xFF;}m.cob_id = (UNS16)*((UNS32*)d->objdict[offset + CliServNbr].pSubindex[1].pObject);MSG_WAR(0x3A41, "I am client Tx cobId : ", m.cob_id);}/* 數(shù)據(jù)幀 */m.rtr = NOT_A_REQUEST;/* sdo報文固定8字節(jié) */m.len = 8;/* 數(shù)據(jù) */for(i = 0; i < 8; i++) {m.data[i] = pData[i];}/* 發(fā)送報文 */return canSend(d->canHandle,&m); }/* 發(fā)送sdo中止報文 */ UNS8 sendSDOabort(CO_Data* d, UNS8 whoami, UNS8 CliServNbr, UNS16 index, UNS8 subIndex, UNS32 abortCode) {UNS8 data[8];UNS8 ret;MSG_WAR(0x2A50,"Sending SDO abort ", abortCode);data[0] = 0x80;data[1] = index & 0xFF;data[2] = (index >> 8) & 0xFF;data[3] = subIndex;data[4] = (UNS8)(abortCode & 0xFF);data[5] = (UNS8)((abortCode >> 8) & 0xFF);data[6] = (UNS8)((abortCode >> 16) & 0xFF);data[7] = (UNS8)((abortCode >> 24) & 0xFF);/* 發(fā)送sdo報文 */ret = sendSDO(d, whoami, CliServNbr, data);return ret; }/* 處理sdo報文 */ UNS8 proceedSDO(CO_Data *d, Message *m) {UNS8 err;UNS8 cs;UNS8 line;UNS32 nbBytes;UNS8 nodeId = 0;UNS8 CliServNbr;UNS8 whoami = SDO_UNKNOWN;UNS32 errorCode;UNS8 data[8];UNS16 index;UNS8 subIndex;UNS32 abortCode;UNS32 i;UNS8 j;UNS32 *pCobId = NULL;UNS16 offset;UNS16 lastIndex;UNS8 SubCommand;UNS8 SeqNo;UNS8 AckSeq;UNS8 NbBytesNoData;MSG_WAR(0x3A60, "proceedSDO ", 0);whoami = SDO_UNKNOWN;/* 第一個sdo服務(wù)器在字典中的下標 */offset = d->firstIndex->SDO_SVR;/* 最后一個sdo服務(wù)器在字典中的下標 */lastIndex = d->lastIndex->SDO_SVR;j = 0;/* 如果字典中配置了sdo服務(wù)器 */if(offset) {/* 遍歷所有sdo服務(wù)器 */while(offset <= lastIndex) {/* 服務(wù)器端子索引不能低于1個 */if(d->objdict[offset].bSubCount <= 1) {MSG_ERR(0x1A61, "Subindex 1 not found at index ", 0x1200 + j);return 0xFF;}/* 取出服務(wù)器端的接收CobId */pCobId = (UNS32*)d->objdict[offset].pSubindex[1].pObject;/* 如果和接收到的報文匹配 */if(*pCobId == UNS16_LE(m->cob_id)) {/* 說明自己是服務(wù)器 */whoami = SDO_SERVER;MSG_WAR(0x3A62, "proceedSDO. I am server. index : ", 0x1200 + j);/* 客戶端/服務(wù)器號 */CliServNbr = j;break;}j++;offset++;}}/* 如果不是服務(wù)器,判斷自己是不是客戶端 */if(whoami == SDO_UNKNOWN) {/* 第一個客戶端在字典中的下標 */offset = d->firstIndex->SDO_CLT;/* 最后一個客戶端在字典中的下標 */lastIndex = d->lastIndex->SDO_CLT;j = 0;/* 如果配置了客戶端 */if(offset) {/* 遍歷所有sdo客戶端 */while(offset <= lastIndex) {/* 子索引不可以低于3個 */if(d->objdict[offset].bSubCount <= 3) {MSG_ERR(0x1A63, "Subindex 3 not found at index ", 0x1280 + j);return 0xFF;}/* 取出客戶端的接收CobId */pCobId = (UNS32*)d->objdict[offset].pSubindex[2].pObject;/* 如果和接收到的報文匹配 */if(*pCobId == UNS16_LE(m->cob_id)) {/* 自己為客戶端 */whoami = SDO_CLIENT;MSG_WAR(0x3A64, "proceedSDO. I am client index : ", 0x1280 + j);/* 服務(wù)器/客戶端號 */CliServNbr = j;/* 服務(wù)器端的節(jié)點號 */nodeId = *((UNS8*) d->objdict[offset].pSubindex[3].pObject);break;}j++;offset++;}}}/* 如果沒有配置服務(wù)器,也沒有配置客戶端,則不用處理該保文 */if(whoami == SDO_UNKNOWN) {return 0xFF;}/* SDO報文一定是8字節(jié) */if((*m).len != 8) {MSG_ERR(0x1A67, "Error size SDO", 0);failedSDO(d, CliServNbr, whoami, 0, 0, SDOABT_GENERAL_ERROR);return 0xFF;}if(whoami == SDO_CLIENT) {MSG_WAR(0x3A68, "I am CLIENT number ", CliServNbr);}else {MSG_WAR(0x3A69, "I am SERVER number ", CliServNbr);}/* 通服務(wù)器/客戶端號獲取通道號 */err = getSDOlineOnUse(d, CliServNbr, whoami, &line);cs = 0xFF; if(!err) {/* 客戶端->服務(wù)器:塊下載過程中 服務(wù)器->客戶端:上傳過程中 */if(((whoami == SDO_SERVER) && (d->transfers[line].state == SDO_BLOCK_DOWNLOAD_IN_PROGRESS)) ||((whoami == SDO_CLIENT) && (d->transfers[line].state == SDO_BLOCK_UPLOAD_IN_PROGRESS))) {if(m->data[0] == 0x80)cs = 4;elsecs = 6;}}if(cs == 0xFF){cs = getSDOcs(m->data[0]);}/* 判斷指令 */switch(cs) {/* 客戶端->服務(wù)器:域分段下載/服務(wù)器->客戶端:域分段上傳 */case 0:/* 客戶端->服務(wù)器的域分段下載 */if(whoami == SDO_SERVER) {/* 驗證傳輸通道是否在域分段下載中 */if(!err){err = d->transfers[line].state != SDO_DOWNLOAD_IN_PROGRESS;}if(err) {MSG_ERR(0x1A70, "SDO error : Received download segment for unstarted trans. index 0x1200 + ", CliServNbr);failedSDO(d, CliServNbr, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);return 0xFF;}/* 重啟傳輸通道超時定時器 */RestartSDO_TIMER(line)MSG_WAR(0x3A71, "Received SDO download segment defined at index 0x1200 + ", CliServNbr);/* 取出索引號 */index = d->transfers[line].index;/* 取出子索引號 */subIndex = d->transfers[line].subIndex;/* 校驗觸發(fā)位是否同步 */if(d->transfers[line].toggle != getSDOt(m->data[0])) {MSG_ERR(0x1A72, "SDO error : Toggle error : ", getSDOt(m->data[0]));failedSDO(d, CliServNbr, whoami, index, subIndex, SDOABT_TOGGLE_NOT_ALTERNED);return 0xFF;}/* 取出字節(jié)數(shù) */nbBytes = 7 - getSDOn3(m->data[0]);/* 將數(shù)據(jù)從sdo數(shù)據(jù)包中拷貝到傳輸通道緩沖區(qū) */err = SDOtoLine(d, line, nbBytes, (*m).data + 1);if(err){failedSDO(d, CliServNbr, whoami, index, subIndex, SDOABT_GENERAL_ERROR);return 0xFF;}/* 構(gòu)建響應(yīng)包 */data[0] = (1 << 5) | (d->transfers[line].toggle << 4);for(i = 1 ; i < 8 ; i++){data[i] = 0;}MSG_WAR(0x3A73, "SDO. Send response to download request defined at index 0x1200 + ", CliServNbr);/* 發(fā)送響應(yīng)包 */sendSDO(d, whoami, CliServNbr, data);/* 觸發(fā)位取反 */d->transfers[line].toggle = !d->transfers[line].toggle & 1;/* 檢查該段是否是最后一段 */if(getSDOc(m->data[0])) {/* 將數(shù)據(jù)從sdo傳輸通道緩沖區(qū)拷貝到字典中 */errorCode = SDOlineToObjdict(d, line);if(errorCode) {MSG_ERR(0x1A54, "SDO error : Unable to copy the data in the object dictionary", 0);/* sdo傳輸失敗 */failedSDO(d, CliServNbr, whoami, index, subIndex, errorCode);return 0xFF;}/* 復(fù)位sdo傳輸通道 */resetSDOline(d, line);MSG_WAR(0x3A74, "SDO. End of download defined at index 0x1200 + ", CliServNbr);}}/* 服務(wù)器->客戶端:域分段上傳 */else {/* 驗證傳輸通道是否在域分段上傳中 */if(!err){err = d->transfers[line].state != SDO_UPLOAD_IN_PROGRESS;}if(err) {MSG_ERR(0x1A75, "SDO error : Received segment response for unknown trans. from nodeId", nodeId);failedSDO(d, CliServNbr, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);return 0xFF;}/* 重啟傳輸通道超時定時器 */RestartSDO_TIMER(line)/* 取出索引號 */index = d->transfers[line].index;/* 取出子索引號 */subIndex = d->transfers[line].subIndex;/* 校驗觸發(fā)位是否同步 */if(d->transfers[line].toggle != getSDOt(m->data[0])) {MSG_ERR(0x1A76, "SDO error : Received segment response Toggle error. from nodeId", nodeId);failedSDO(d, CliServNbr, whoami, index, subIndex, SDOABT_TOGGLE_NOT_ALTERNED);return 0xFF;}/* 取出字節(jié)數(shù) */nbBytes = 7 - getSDOn3(m->data[0]);/* 將數(shù)據(jù)從sdo數(shù)據(jù)包中拷貝到傳輸通道緩沖區(qū) */err = SDOtoLine(d, line, nbBytes, (*m).data + 1);if(err) {failedSDO(d, CliServNbr, whoami, index, subIndex, SDOABT_GENERAL_ERROR);return 0xFF;}/* 觸發(fā)位取反 */d->transfers[line].toggle = ! d->transfers[line].toggle & 1;/* 檢查該段是否是最后一段 */if(getSDOc(m->data[0])) {/* 停止超時定時器 */StopSDO_TIMER(line)/* 傳輸完成 */d->transfers[line].state = SDO_FINISHED;/* 傳輸完成回調(diào)函數(shù) */if(d->transfers[line].Callback){(*d->transfers[line].Callback)(d,nodeId);}MSG_WAR(0x3A77, "SDO. End of upload from node : ", nodeId);}/* 如果不是最后一段,繼續(xù)請求上傳 */else {data[0] = (3 << 5) | (d->transfers[line].toggle << 4);for(i = 1; i < 8; i++)data[i] = 0;sendSDO(d, whoami, CliServNbr, data);MSG_WAR(0x3A78, "SDO send upload segment request to nodeId", nodeId);}}break;/* 客戶端->服務(wù)器:啟動域下載/服務(wù)器->客戶端:域分段下載 */case 1:/* 客戶端->服務(wù)器:啟動域下載 */if(whoami == SDO_SERVER) {/* 索引 */index = getSDOindex(m->data[1], m->data[2]);/* 子索引 */subIndex = getSDOsubIndex(m->data[3]);MSG_WAR(0x3A79, "Received SDO Initiate Download (to store data) defined at index 0x1200 + ", CliServNbr);MSG_WAR(0x3A80, "Writing at index : ", index);MSG_WAR(0x3A80, "Writing at subIndex : ", subIndex);if(!err) {MSG_ERR(0x1A81, "SDO error : Transmission yet started.", 0);failedSDO(d, CliServNbr, whoami, index, subIndex, SDOABT_LOCAL_CTRL_ERROR);return 0xFF;}/* 查找空閑傳輸通道 */err = getSDOfreeLine(d, whoami, &line);if(err) {MSG_ERR(0x1A82, "SDO error : No line free, too many SDO in progress. Aborted.", 0);failedSDO(d, CliServNbr, whoami, index, subIndex, SDOABT_LOCAL_CTRL_ERROR);return 0xFF;}/* 初始化sdo傳輸通道 */initSDOline(d, line, CliServNbr, index, subIndex, SDO_DOWNLOAD_IN_PROGRESS);/* 如果是快速傳輸 */if(getSDOe(m->data[0])) {/* 取出字節(jié)數(shù) */nbBytes = 4 - getSDOn2(m->data[0]);/* 存儲字節(jié)數(shù) */d->transfers[line].count = nbBytes;/* 將數(shù)據(jù)數(shù)據(jù)拷貝到傳輸通道緩沖區(qū) */err = SDOtoLine(d, line, nbBytes, (*m).data + 4);if(err) {failedSDO(d, CliServNbr, whoami, index, subIndex, SDOABT_GENERAL_ERROR);return 0xFF;}MSG_WAR(0x3A83, "SDO Initiate Download is an expedited transfer. Finished. ", 0);/* 將數(shù)據(jù)從傳輸通道緩沖區(qū)拷貝到字典中 */errorCode = SDOlineToObjdict(d, line);if(errorCode) {MSG_ERR(0x1A84, "SDO error : Unable to copy the data in the object dictionary", 0);failedSDO(d, CliServNbr, whoami, index, subIndex, errorCode);return 0xFF;}/* 復(fù)位sdo通道 */resetSDOline(d, line);}/* 如果是正常傳輸 */else {/* 數(shù)據(jù)字節(jié)為字節(jié)計數(shù)器 */if(getSDOs(m->data[0])) {/* 取出字節(jié)數(shù) */nbBytes = (m->data[4]) + ((UNS32)(m->data[5])<<8) + ((UNS32)(m->data[6])<<16) + ((UNS32)(m->data[7])<<24);/* 設(shè)置sdo傳輸通道字節(jié)數(shù)剩余 */err = setSDOlineRestBytes(d, line, nbBytes);if(err){failedSDO(d, CliServNbr, whoami, index, subIndex, SDOABT_GENERAL_ERROR);return 0xFF;}}}/* 發(fā)送啟動域下載響應(yīng) */data[0] = 3 << 5;data[1] = index & 0xFF;data[2] = (index >> 8) & 0xFF;data[3] = subIndex;for(i = 4 ; i < 8 ; i++)data[i] = 0;sendSDO(d, whoami, CliServNbr, data);}/* 服務(wù)器->客戶端:域分段下載 */else {/* 驗證傳輸通道是否在域分段下載中 */if(!err)err = d->transfers[line].state != SDO_DOWNLOAD_IN_PROGRESS;if(err) {MSG_ERR(0x1A85, "SDO error : Received segment response for unknown trans. from nodeId", nodeId);failedSDO(d, CliServNbr, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);return 0xFF;}/* 重啟傳輸通道超時定時器 */RestartSDO_TIMER(line)/* 索引 */ index = d->transfers[line].index;/* 子索引 */subIndex = d->transfers[line].subIndex;/* 校驗觸發(fā)位是否同步 */if(d->transfers[line].toggle != getSDOt(m->data[0])) {MSG_ERR(0x1A86, "SDO error : Received segment response Toggle error. from nodeId", nodeId);failedSDO(d, CliServNbr, whoami, index, subIndex, SDOABT_TOGGLE_NOT_ALTERNED);return 0xFF;}/* 獲取傳輸通道剩余字節(jié)數(shù) */getSDOlineRestBytes(d, line, &nbBytes);/* 如果已經(jīng)傳輸完 */if(nbBytes == 0) {MSG_WAR(0x3A87, "SDO End download. segment response received. OK. from nodeId", nodeId);/* 停止超時定時器 */StopSDO_TIMER(line)/* 將狀態(tài)置為完成 */d->transfers[line].state = SDO_FINISHED;/* 傳輸完成回調(diào)函數(shù) */if(d->transfers[line].Callback) {(*d->transfers[line].Callback)(d,nodeId);}return 0x00;}/* 如果至少還有7個字節(jié)沒傳輸完畢 */if(nbBytes > 7) {/* 觸發(fā)位取反 */d->transfers[line].toggle = ! d->transfers[line].toggle & 1;/* 構(gòu)建報文 */data[0] = (d->transfers[line].toggle << 4);/* 將數(shù)據(jù)從傳輸通道緩沖區(qū)拷貝到sdo報文中 */err = lineToSDO(d, line, 7, data + 1);if(err) {failedSDO(d, CliServNbr, whoami, index, subIndex, SDOABT_GENERAL_ERROR);return 0xFF;}}/* 如果數(shù)據(jù)量小于7個字節(jié) */else {/* 觸發(fā)位取反 */d->transfers[line].toggle = !d->transfers[line].toggle & 1;/* 構(gòu)建報文 */data[0] = (UNS8)((d->transfers[line].toggle << 4) | ((7 - nbBytes) << 1) | 1);/* 將數(shù)據(jù)從傳輸通道緩沖區(qū)拷貝到sdo報文中 */err = lineToSDO(d, line, nbBytes, data + 1);if(err) {failedSDO(d, CliServNbr, whoami, index, subIndex, SDOABT_GENERAL_ERROR);return 0xFF;}/* 剩余字節(jié)填0 */for(i = nbBytes + 1; i < 8; i++){data[i] = 0;}}MSG_WAR(0x3A88, "SDO sending download segment to nodeId", nodeId);/* 發(fā)送sdo報文 */sendSDO(d, whoami, CliServNbr, data);}break;/* 客戶端->服務(wù)器:啟動域上傳/服務(wù)器->客戶端:啟動域上傳 */case 2:/* 客戶端->服務(wù)器:啟動域上傳 */if(whoami == SDO_SERVER) {/* 索引 */index = getSDOindex(m->data[1], m->data[2]);/* 子索引 */subIndex = getSDOsubIndex(m->data[3]);MSG_WAR(0x3A89, "Received SDO Initiate upload (to send data) defined at index 0x1200 + ", CliServNbr);MSG_WAR(0x3A90, "Reading at index : ", index);MSG_WAR(0x3A91, "Reading at subIndex : ", subIndex);if(!err) {MSG_ERR(0x1A92, "SDO error : Transmission yet started at line : ", line);MSG_WAR(0x3A93, "Server Nbr = ", CliServNbr);failedSDO(d, CliServNbr, whoami, index, subIndex, SDOABT_LOCAL_CTRL_ERROR);return 0xFF;}/* 獲取sdo空閑傳輸通道 */err = getSDOfreeLine(d, whoami, &line);if(err) {MSG_ERR(0x1A71, "SDO error : No line free, too many SDO in progress. Aborted.", 0);failedSDO(d, CliServNbr, whoami, index, subIndex, SDOABT_LOCAL_CTRL_ERROR);return 0xFF;}/* 初始化傳輸通道 */initSDOline(d, line, CliServNbr, index, subIndex, SDO_UPLOAD_IN_PROGRESS);/* 將數(shù)據(jù)從字典中拷貝到傳輸通道緩沖區(qū) */errorCode = objdictToSDOline(d, line);if(errorCode) {MSG_ERR(0x1A94, "SDO error : Unable to copy the data from object dictionary. Err code : ", errorCode);failedSDO(d, CliServNbr, whoami, index, subIndex, errorCode);return 0xFF;}/* 獲取傳輸通道剩余字節(jié)數(shù) */getSDOlineRestBytes(d, line, &nbBytes);/* 字節(jié)數(shù)大于4,正常傳輸 */if(nbBytes > 4) {/* 命令 */data[0] = (2 << 5) | 1;/* 索引 */data[1] = index & 0xFF;data[2] = (index >> 8) & 0xFF;/* 子索引 */data[3] = subIndex;/* 字節(jié)計數(shù)器 */data[4] = (UNS8)nbBytes;data[5] = (UNS8)(nbBytes >> 8);data[6] = (UNS8)(nbBytes >> 16);data[7] = (UNS8)(nbBytes >> 24);MSG_WAR(0x3A95, "SDO. Sending normal upload initiate response defined at index 0x1200 + ", nodeId);/* 發(fā)送sdo報文 */sendSDO(d, whoami, CliServNbr, data);}/* 字節(jié)數(shù)不高于4,快速傳輸 */else{/* 命令 */data[0] = (UNS8)((2 << 5) | ((4 - nbBytes) << 2) | 3);/* 索引 */data[1] = index & 0xFF;data[2] = (index >> 8) & 0xFF;/* 子索引 */data[3] = subIndex;/* 將數(shù)據(jù)從傳輸通道緩沖區(qū)拷貝到sdo報文 */err = lineToSDO(d, line, nbBytes, data + 4);if(err) {failedSDO(d, CliServNbr, whoami, index, subIndex, SDOABT_GENERAL_ERROR);return 0xFF;}/* 不足8字節(jié)填0 */for(i = 4 + nbBytes; i < 8; i++){data[i] = 0;}MSG_WAR(0x3A96, "SDO. Sending expedited upload initiate response defined at index 0x1200 + ", CliServNbr);/* 發(fā)送sdo報文 */sendSDO(d, whoami, CliServNbr, data);/* 復(fù)位sdo傳輸通道 */resetSDOline(d, line);}}/* 服務(wù)器->客戶端:啟動域上傳 */else {/* 驗證傳輸通道是否在域上傳中 */if(!err)err = d->transfers[line].state != SDO_UPLOAD_IN_PROGRESS;if(err) {MSG_ERR(0x1A97, "SDO error : Received response for unknown upload request from nodeId", nodeId);failedSDO(d, CliServNbr, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);return 0xFF;}/* 重置傳輸超時定時器 */RestartSDO_TIMER(line)/* 索引 */index = d->transfers[line].index;/* 子索引 */subIndex = d->transfers[line].subIndex;/* 加速傳輸完成 */if(getSDOe(m->data[0])) {/* 字節(jié)數(shù) */nbBytes = 4 - getSDOn2(m->data[0]);/* 將數(shù)據(jù)拷貝到傳輸通道緩沖區(qū) */err = SDOtoLine(d, line, nbBytes, (*m).data + 4);if(err) {failedSDO(d, CliServNbr, whoami, index, subIndex, SDOABT_GENERAL_ERROR);return 0xFF;}MSG_WAR(0x3A98, "SDO expedited upload finished. Response received from node : ", nodeId);/* 停止sdo傳輸通道超時定時器 */StopSDO_TIMER(line)/* 接收到的字節(jié)數(shù) */d->transfers[line].count = nbBytes;/* sdo傳輸通道傳輸完成 */d->transfers[line].state = SDO_FINISHED;/* 傳輸完成后調(diào)用回調(diào)函數(shù) */if(d->transfers[line].Callback) (*d->transfers[line].Callback)(d,nodeId);return 0;}/* 正常傳輸 */else {if(getSDOs(m->data[0])) {/* 字節(jié)計數(shù)器 */nbBytes = m->data[4] + ((UNS32)(m->data[5]) << 8) + ((UNS32)(m->data[6]) << 16) + ((UNS32)(m->data[7]) << 24);/* 設(shè)置sdo傳輸通道剩余字節(jié)數(shù) */err = setSDOlineRestBytes(d, line, nbBytes);if(err) {failedSDO(d, CliServNbr, whoami, index, subIndex, SDOABT_GENERAL_ERROR);return 0xFF;}}/* 請求:域分段上傳 */data[0] = 3 << 5;for(i = 1; i < 8; i++)data[i] = 0;MSG_WAR(0x3A99, "SDO. Sending upload segment request to node : ", nodeId);/* 發(fā)送報文 */sendSDO(d, whoami, CliServNbr, data);}}break;/* 客戶端->服務(wù)器:域分段上傳/服務(wù)器->客戶端:啟動域下載 */case 3:/* 客戶端->服務(wù)器:域分段上傳 */if(whoami == SDO_SERVER) {if(!err)err = d->transfers[line].state != SDO_UPLOAD_IN_PROGRESS;if(err) {MSG_ERR(0x1AA0, "SDO error : Received upload segment for unstarted trans. index 0x1200 + ", CliServNbr);failedSDO(d, CliServNbr, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);return 0xFF;}/* 復(fù)位sdo傳輸通道超時定時器 */RestartSDO_TIMER(line)MSG_WAR(0x3AA1, "Received SDO upload segment defined at index 0x1200 + ", CliServNbr);/* 索引 */index = d->transfers[line].index;/* 子索引 */subIndex = d->transfers[line].subIndex;/* 校驗觸發(fā)位是否同步 */if(d->transfers[line].toggle != getSDOt(m->data[0])) {MSG_ERR(0x1AA2, "SDO error : Toggle error : ", getSDOt(m->data[0]));failedSDO(d, CliServNbr, whoami, index, subIndex, SDOABT_TOGGLE_NOT_ALTERNED);return 0xFF;}/* 獲取傳輸通道剩余字節(jié)數(shù) */getSDOlineRestBytes(d, line, &nbBytes);/* 如果至少還有7個字節(jié)沒傳輸完畢 */if(nbBytes > 7) {/* 構(gòu)建報文 */data[0] = (d->transfers[line].toggle << 4);/* 將數(shù)據(jù)從sdo傳輸通道緩沖區(qū)拷貝到sdo報文中 */err = lineToSDO(d, line, 7, data + 1);if(err) {failedSDO(d, CliServNbr, whoami, index, subIndex, SDOABT_GENERAL_ERROR);return 0xFF;}/* 將觸發(fā)位取反 */d->transfers[line].toggle = !d->transfers[line].toggle & 1;MSG_WAR(0x3AA3, "SDO. Sending upload segment defined at index 0x1200 + ", CliServNbr);/* 發(fā)送報文 */sendSDO(d, whoami, CliServNbr, data);}/* 不大于7字節(jié),則說明是最后一段 */else {/* 構(gòu)建報文 */data[0] = (UNS8)((d->transfers[line].toggle << 4) | ((7 - nbBytes) << 1) | 1);/* 將數(shù)據(jù)從sdo傳輸通道緩沖區(qū)拷貝到sdo報文中 */err = lineToSDO(d, line, nbBytes, data + 1);if (err) {failedSDO(d, CliServNbr, whoami, index, subIndex, SDOABT_GENERAL_ERROR);return 0xFF;}/* 不滿8字節(jié)補0 */for(i = nbBytes + 1; i < 8; i++)data[i] = 0;MSG_WAR(0x3AA4, "SDO. Sending last upload segment defined at index 0x1200 + ", CliServNbr);/* 發(fā)送報文 */sendSDO(d, whoami, CliServNbr, data);/* 復(fù)位傳輸通道 */resetSDOline(d, line);}}/* 服務(wù)器->客戶端:啟動域下載 */else {/* 校驗傳輸通道是否在域下載過程中 */if(!err)err = d->transfers[line].state != SDO_DOWNLOAD_IN_PROGRESS;if(err) {MSG_ERR(0x1AA5, "SDO error : Received response for unknown download request from nodeId", nodeId);failedSDO(d, CliServNbr, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);return 0xFF;}/* 復(fù)位sdo傳輸通道定時器 */RestartSDO_TIMER(line)/* 索引 */index = d->transfers[line].index;/* 子索引 */subIndex = d->transfers[line].subIndex;/* 獲取sdo傳輸通道剩余字節(jié)數(shù) */getSDOlineRestBytes(d, line, &nbBytes);/* 傳輸完成 */if(nbBytes == 0) {MSG_WAR(0x3AA6, "SDO End download expedited. Response received. from nodeId", nodeId);/* 停止傳輸通道超時定時器 */StopSDO_TIMER(line)/* 將傳輸通道狀態(tài)設(shè)置為完成 */d->transfers[line].state = SDO_FINISHED;/* 傳輸完成回調(diào)函數(shù) */if(d->transfers[line].Callback) (*d->transfers[line].Callback)(d,nodeId);return 0x00;}/* 剩余字節(jié)數(shù)大于7個:域分段下載 */if(nbBytes > 7) {/* 構(gòu)建報文 */data[0] = (d->transfers[line].toggle << 4);/* 將數(shù)據(jù)從傳輸通道中拷貝到sdo報文中 */err = lineToSDO(d, line, 7, data + 1);if(err) {failedSDO(d, CliServNbr, whoami, index, subIndex, SDOABT_GENERAL_ERROR);return 0xFF;}}/* 剩余字節(jié)數(shù)不大于7個:域分段下載,最后一段 */else {/* 構(gòu)建報文 */data[0] = (UNS8)((d->transfers[line].toggle << 4) | ((7 - nbBytes) << 1) | 1);/* 將數(shù)據(jù)從傳輸通道中拷貝到sdo報文中 */err = lineToSDO(d, line, nbBytes, data + 1);if(err) {failedSDO(d, CliServNbr, whoami, index, subIndex, SDOABT_GENERAL_ERROR);return 0xFF;}/* 不足8字節(jié)補0 */for(i = nbBytes + 1; i < 8; i++)data[i] = 0;}MSG_WAR(0x3AA7, "SDO sending download segment to nodeId", nodeId);/* 發(fā)送sdo報文 */sendSDO(d, whoami, CliServNbr, data);}break;/* 中止 */case 4:/* 中止碼 */abortCode = (UNS32)m->data[4] | ((UNS32)m->data[5] << 8) | ((UNS32)m->data[6] << 16) | ((UNS32)m->data[7] << 24);/* 客戶端->服務(wù)器:中止 */if(whoami == SDO_SERVER) {/* 復(fù)位sdo傳輸通道 */if(!err) {resetSDOline(d, line);MSG_WAR(0x3AA8, "SD0. Received SDO abort. Line released. Code : ", abortCode);}elseMSG_WAR(0x3AA9, "SD0. Received SDO abort. No line found. Code : ", abortCode);}/* 服務(wù)器->客戶端:中止 */else {if(!err) {/* 停止sdo傳輸通道超時定時器 */StopSDO_TIMER(line)/* 將傳輸通道狀態(tài)設(shè)置為中止 */d->transfers[line].state = SDO_ABORTED_RCV;/* 中止碼 */d->transfers[line].abortCode = abortCode;MSG_WAR(0x3AB0, "SD0. Received SDO abort. Line state ABORTED. Code : ", abortCode);/* 傳輸結(jié)束調(diào)用回調(diào)函數(shù) */if(d->transfers[line].Callback) (*d->transfers[line].Callback)(d, nodeId);}elseMSG_WAR(0x3AB1, "SD0. Received SDO abort. No line found. Code : ", abortCode);}break;/* 服務(wù)器->客戶端:塊下載初始化/服務(wù)器->客戶端:塊下載/服務(wù)器->客戶端:塊下載結(jié)束 *//* 客戶端->服務(wù)器:塊上傳初始化/客戶端->服務(wù)器:塊上傳開始命令/客戶端->服務(wù)器:塊上傳/客戶端->服務(wù)器:塊上傳結(jié)束 */case 5:/* 子命令 */SubCommand = getSDOblockSC(m->data[0]);/* 客戶端->服務(wù)器:塊上傳初始化/客戶端->服務(wù)器:塊上傳/客戶端->服務(wù)器:塊上傳結(jié)束 */if(whoami == SDO_SERVER) {/* 客戶端->服務(wù)器:塊上傳初始化 */if(SubCommand == SDO_BCS_INITIATE_UPLOAD_REQUEST) {/* 索引 */index = getSDOindex(m->data[1], m->data[2]);/* 子索引 */subIndex = getSDOsubIndex(m->data[3]);MSG_WAR(0x3AB2, "Received SDO Initiate block upload defined at index 0x1200 + ", CliServNbr);MSG_WAR(0x3AB3, "Reading at index : ", index);MSG_WAR(0x3AB4, "Reading at subIndex : ", subIndex);if(!err) {MSG_ERR(0x1A93, "SDO error : Transmission yet started at line : ", line);MSG_WAR(0x3AB5, "Server Nbr = ", CliServNbr);failedSDO(d, CliServNbr, whoami, index, subIndex, SDOABT_LOCAL_CTRL_ERROR);return 0xFF;}/* 獲取sdo空閑傳輸通道 */err = getSDOfreeLine(d, whoami, &line);if(err) {MSG_ERR(0x1A73, "SDO error : No line free, too many SDO in progress. Aborted.", 0);failedSDO(d, CliServNbr, whoami, index, subIndex, SDOABT_LOCAL_CTRL_ERROR);return 0xFF;}/* 初始化sdo傳輸通道 */initSDOline(d, line, CliServNbr, index, subIndex, SDO_BLOCK_UPLOAD_IN_PROGRESS);/* 是否支持crc校驗 */d->transfers[line].peerCRCsupport = ((m->data[0]) >> 2) & 1;/* 塊數(shù)量 */d->transfers[line].blksize = m->data[4];/* 將數(shù)據(jù)從字典中拷貝到sdo傳輸通道緩沖區(qū) */errorCode = objdictToSDOline(d, line);if(errorCode) {MSG_ERR(0x1A95, "SDO error : Unable to copy the data from object dictionary. Err code : ", errorCode);failedSDO(d, CliServNbr, whoami, index, subIndex, errorCode);return 0xFF;}/* 獲取sdo傳輸剩余字節(jié)數(shù) */getSDOlineRestBytes(d, line, &nbBytes);/* 設(shè)置對象大小 */d->transfers[line].objsize = nbBytes;/* sdo塊上傳初始化響應(yīng) */data[0] = (6 << 5) | (1 << 1) | SDO_BSS_INITIATE_UPLOAD_RESPONSE;/* 索引 */data[1] = index & 0xFF;data[2] = (index >> 8) & 0xFF;/* 子索引 */data[3] = subIndex;/* 字節(jié)數(shù) */data[4] = (UNS8)nbBytes;data[5] = (UNS8)(nbBytes >> 8);data[6] = (UNS8)(nbBytes >> 16);data[7] = (UNS8)(nbBytes >> 24);MSG_WAR(0x3A9A, "SDO. Sending normal block upload initiate response defined at index 0x1200 + ", nodeId);/* 發(fā)送sdo報文 */sendSDO(d, whoami, CliServNbr, data);}/* 客戶端->服務(wù)器:塊上傳結(jié)束響應(yīng) */else if(SubCommand == SDO_BCS_END_UPLOAD_REQUEST) {MSG_WAR(0x3AA2, "Received SDO block END upload request defined at index 0x1200 + ", CliServNbr);/* 校驗是否在塊上傳過程中 */if(!err)err = d->transfers[line].state != SDO_BLOCK_UPLOAD_IN_PROGRESS;if(err) {MSG_ERR(0x1AA1, "SDO error : Received block upload request for unstarted trans. index 0x1200 + ", CliServNbr);failedSDO(d, CliServNbr, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);return 0xFF;}/* 復(fù)位sdo傳輸通道 */resetSDOline(d, line);}/* 客戶端->服務(wù)器:塊上傳/客戶端->服務(wù)器:塊上傳開始命令 */else if((SubCommand == SDO_BCS_UPLOAD_RESPONSE) || (SubCommand == SDO_BCS_START_UPLOAD)) {/* 校驗是否在塊上傳過程中 */if(!err)err = d->transfers[line].state != SDO_BLOCK_UPLOAD_IN_PROGRESS;if(err) {MSG_ERR(0x1AA1, "SDO error : Received block upload response for unstarted trans. index 0x1200 + ", CliServNbr);failedSDO(d, CliServNbr, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);return 0xFF;}/* 重啟傳輸通道超時定時器 */RestartSDO_TIMER(line);/* 索引 */index = d->transfers[line].index;/* 子索引 */subIndex = d->transfers[line].subIndex;/* 塊上傳響應(yīng) */if(SubCommand == SDO_BCS_UPLOAD_RESPONSE) {MSG_WAR(0x3AA2, "Received SDO block upload response defined at index 0x1200 + ", CliServNbr);/* 一次最大上傳塊數(shù) */d->transfers[line].blksize = m->data[2];/* 響應(yīng)序列號 */AckSeq = (m->data[1]) & 0x7f;/* 獲取剩余字節(jié)數(shù) */getSDOlineRestBytes(d, line, &nbBytes);/* 如果傳輸完 */if((nbBytes == 0) && (AckSeq == d->transfers[line].seqno)){/* 上傳結(jié)束指令 */data[0] = (6 << 5) | ((d->transfers[line].endfield) << 2) | SDO_BSS_END_UPLOAD_RESPONSE;for(i = 1; i < 8; i++)data[i] = 0;MSG_WAR(0x3AA5, "SDO. Sending block END upload response defined at index 0x1200 + ", CliServNbr);/* 發(fā)送sdo報文 */sendSDO(d, whoami, CliServNbr, data);break;}elsed->transfers[line].offset = d->transfers[line].lastblockoffset + 7 * AckSeq;if(d->transfers[line].offset > d->transfers[line].count) {MSG_ERR(0x1AA1, "SDO error : Received upload response with bad ackseq index 0x1200 + ", CliServNbr);failedSDO(d, CliServNbr, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);return 0xFF;}}elseMSG_WAR(0x3AA2, "Received SDO block START upload defined at index 0x1200 + ", CliServNbr);/* 上一次塊傳輸后數(shù)據(jù)偏移量 */d->transfers[line].lastblockoffset = (UNS8) d->transfers[line].offset;/* 進行一次塊上傳數(shù)據(jù) */for(SeqNo = 1; SeqNo <= d->transfers[line].blksize; SeqNo++) {/* 塊序列號 */d->transfers[line].seqno = SeqNo;/* 獲取傳輸通道剩余字節(jié)數(shù) */getSDOlineRestBytes(d, line, &nbBytes);/* 如果大于7字節(jié),則說明不是最后一塊數(shù)據(jù) */if(nbBytes > 7) {/* 塊序列號 */data[0] = SeqNo;/* 將傳輸通道上的數(shù)據(jù)拷貝到sdo報文中 */err = lineToSDO(d, line, 7, data + 1);if(err) {failedSDO(d, CliServNbr, whoami, index, subIndex, SDOABT_GENERAL_ERROR);return 0xFF;}MSG_WAR(0x3AA5, "SDO. Sending upload segment defined at index 0x1200 + ", CliServNbr);/* 發(fā)送sdo報文 */sendSDO(d, whoami, CliServNbr, data);}/* 如果不大于7字節(jié),則說明是最后一塊數(shù)據(jù) */else {/* 塊序列號,最高位表示最后一塊 */data[0] = 0x80 | SeqNo;/* 將傳輸通道上的數(shù)據(jù)拷貝到sdo報文中 */err = lineToSDO(d, line, nbBytes, data + 1);if(err) {failedSDO(d, CliServNbr, whoami, index, subIndex, SDOABT_GENERAL_ERROR);return 0xFF;}/* 不滿8字節(jié)補0 */for(i = nbBytes + 1 ; i < 8 ; i++)data[i] = 0;MSG_WAR(0x3AA5, "SDO. Sending last upload segment defined at index 0x1200 + ", CliServNbr);/* 發(fā)送sdo報文 */sendSDO(d, whoami, CliServNbr, data);/* 記錄補零個數(shù) */d->transfers[line].endfield = (UNS8)(7 - nbBytes);break;}}}}/* 服務(wù)器->客戶端:塊下載初始化/服務(wù)器->客戶端:塊下載/服務(wù)器->客戶端:塊下載結(jié)束 */else {/* 服務(wù)器->客戶端:塊下載初始化/服務(wù)器->客戶端:塊下載 */if((SubCommand == SDO_BSS_INITIATE_DOWNLOAD_RESPONSE) || (SubCommand == SDO_BSS_DOWNLOAD_RESPONSE)) {/* 判斷sdo傳輸通道是否在塊下載過程中 */if(!err)err = d->transfers[line].state != SDO_BLOCK_DOWNLOAD_IN_PROGRESS;if(err){MSG_ERR(0x1AAA, "SDO error : Received response for unknown block download request from node id", nodeId);failedSDO(d, CliServNbr, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);return 0xFF;}/* 復(fù)位sdo傳輸超時定時器 */RestartSDO_TIMER(line)/* 服務(wù)器->客戶端:塊下載初始化 */if(SubCommand == SDO_BSS_INITIATE_DOWNLOAD_RESPONSE) {/* 索引 */index = d->transfers[line].index;/* 子索引 */subIndex = d->transfers[line].subIndex;/* 是否支持crc校驗 */d->transfers[line].peerCRCsupport = ((m->data[0])>>2) & 1;/* 塊數(shù)量 */d->transfers[line].blksize = m->data[4];}/* 服務(wù)器->客戶端:塊下載 */else {/* 塊數(shù)量 */d->transfers[line].blksize = m->data[2];/* 序列號 */AckSeq = (m->data[1]) & 0x7f;/* 獲取sdo傳輸通道緩沖區(qū)剩余字節(jié)數(shù) */getSDOlineRestBytes(d, line, &nbBytes);/* 如果剩余字節(jié)數(shù)為0,并且序列號校驗通過 */if((nbBytes == 0) && (AckSeq == d->transfers[line].seqno)){/* 塊下載結(jié)束 */data[0] = (6 << 5) | ((d->transfers[line].endfield) << 2) | SDO_BCS_END_DOWNLOAD_REQUEST;/* 數(shù)據(jù)填0 */for(i = 1; i < 8; i++)data[i] = 0;MSG_WAR(0x3AA5, "SDO. Sending block END download request defined at index 0x1200 + ", CliServNbr);/* 發(fā)送sdo報文 */sendSDO(d, whoami, CliServNbr, data);break;}/* 如果剩余字節(jié)數(shù)不為0 */elsed->transfers[line].offset = d->transfers[line].lastblockoffset + 7 * AckSeq;if(d->transfers[line].offset > d->transfers[line].count) {MSG_ERR(0x1AA1, "SDO error : Received upload segment with bad ackseq index 0x1200 + ", CliServNbr);failedSDO(d, CliServNbr, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);return 0xFF;}}/* 上一次內(nèi)存塊發(fā)送完后傳輸通道的偏移量 */d->transfers[line].lastblockoffset = (UNS8)d->transfers[line].offset;/* 將數(shù)據(jù)分塊發(fā)送出去,不能超過從站指定的最大塊數(shù)量 */for(SeqNo = 1; SeqNo <= d->transfers[line].blksize; SeqNo++) {/* 塊序列號 */d->transfers[line].seqno = SeqNo;/* 獲取傳輸通道剩余字節(jié)數(shù) */getSDOlineRestBytes(d, line, &nbBytes);/* 如果剩余字節(jié)數(shù)大于7 */if(nbBytes > 7) {/* 塊序列號,最高位表示是否最后一塊 */data[0] = SeqNo;/* 將傳輸通道緩沖區(qū)數(shù)據(jù)拷貝到sdo報文中 */err = lineToSDO(d, line, 7, data + 1);if(err) {failedSDO(d, CliServNbr, whoami, index, subIndex, SDOABT_GENERAL_ERROR);return 0xFF;}MSG_WAR(0x3AAB, "SDO. Sending download segment to node id ", nodeId);/* 發(fā)送報文 */sendSDO(d, whoami, CliServNbr, data);}/* 如果剩余字節(jié)數(shù)不大于7,說明這是最后一塊 */else {/* 塊序列號,最高位表示是否最后一塊 */data[0] = 0x80 | SeqNo;/* 將傳輸通道緩沖區(qū)數(shù)據(jù)拷貝到sdo報文中 */err = lineToSDO(d, line, nbBytes, data + 1);if(err) {failedSDO(d, CliServNbr, whoami, index, subIndex, SDOABT_GENERAL_ERROR);return 0xFF;}/* 不足8字節(jié)補0 */for(i = nbBytes + 1; i < 8; i++)data[i] = 0;MSG_WAR(0x3AAB, "SDO. Sending last download segment to node id ", nodeId);/* 發(fā)送報文 */sendSDO(d, whoami, CliServNbr, data);/* 最后一個塊數(shù)據(jù)包中,補0的字節(jié)數(shù) */d->transfers[line].endfield = (UNS8)(7 - nbBytes);break;}}}/* 服務(wù)器->客戶端:塊下載結(jié)束 */else if(SubCommand == SDO_BSS_END_DOWNLOAD_RESPONSE) {MSG_WAR(0x3AAC, "SDO End block download response from nodeId", nodeId);/* 停止sdo傳輸超時定時器 */StopSDO_TIMER(line)/* 傳輸通道狀態(tài)置為傳輸完成 */d->transfers[line].state = SDO_FINISHED;/* 傳輸完成調(diào)用回調(diào)函數(shù) */if(d->transfers[line].Callback) (*d->transfers[line].Callback)(d, nodeId);return 0x00;}/* 錯誤指令 */else {MSG_ERR(0x1AAB, "SDO error block download : Received wrong subcommand from nodeId", nodeId);failedSDO(d, CliServNbr, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);return 0xFF;}}break;/* 客戶端->服務(wù)器:塊下載初始化/客戶端->服務(wù)器:塊下載/客戶端->服務(wù)器:塊下載結(jié)束 *//* 服務(wù)器->客戶端:塊上傳初始化/服務(wù)器->客戶端:塊上傳/服務(wù)器->客戶端:塊上傳結(jié)束 */case 6:/* 客戶端->服務(wù)器:塊下載初始化/客戶端->服務(wù)器:塊下載/客戶端->服務(wù)器:塊下載結(jié)束 */if(whoami == SDO_SERVER) {/* 如果傳輸通道未建立,則說明客戶端->服務(wù)器:塊下載初始化 */if(err) {/* 取出子命令,判斷是否為塊下載初始化 */SubCommand = (m->data[0]) & 1;if(SubCommand != SDO_BCS_INITIATE_DOWNLOAD_REQUEST) {MSG_ERR(0x1AAC, "SDO error block download : Received wrong subcommand from node id", nodeId);failedSDO(d, CliServNbr, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);return 0xFF;}/* 取出索引 */index = getSDOindex(m->data[1], m->data[2]);/* 取出子索引 */subIndex = getSDOsubIndex(m->data[3]);MSG_WAR(0x3A9B, "Received SDO block download initiate defined at index 0x1200 + ", CliServNbr);MSG_WAR(0x3A9B, "Writing at index : ", index);MSG_WAR(0x3A9B, "Writing at subIndex : ", subIndex);/* 獲取空閑的sdo傳輸通道 */err = getSDOfreeLine(d, whoami, &line);if(err) {MSG_ERR(0x1A89, "SDO error : No line free, too many SDO in progress. Aborted.", 0);failedSDO(d, CliServNbr, whoami, index, subIndex, SDOABT_LOCAL_CTRL_ERROR);return 0xFF;}/* 初始化sdo傳輸通道 */initSDOline(d, line, CliServNbr, index, subIndex, SDO_BLOCK_DOWNLOAD_IN_PROGRESS);/* 塊傳輸接收狀態(tài) */d->transfers[line].rxstep = RXSTEP_STARTED;/* 是否crc校驗 */d->transfers[line].peerCRCsupport = ((m->data[0]) >> 2) & 1;/* 是否指明字節(jié)大小 */if((m->data[0]) & 2){d->transfers[line].objsize = (UNS32)m->data[4] + (UNS32)m->data[5] * 256 + (UNS32)m->data[6] * 256 * 256 + (UNS32)m->data[7] * 256 * 256 * 256;}/* 塊下載初始化響應(yīng) */data[0] = (5 << 5) | SDO_BSS_INITIATE_DOWNLOAD_RESPONSE;/* 索引 */data[1] = (UNS8)index;data[2] = (UNS8)(index >> 8);/* 子索引 */data[3] = subIndex;/* 塊數(shù)量 */data[4] = SDO_BLOCK_SIZE;/* 不足8字節(jié)補0 */data[5] = data[6] = data[7] = 0;MSG_WAR(0x3AAD, "SDO. Sending block download initiate response - index 0x1200 + ", CliServNbr);/* 發(fā)送sdo報文 */sendSDO(d, whoami, CliServNbr, data);}/* 客戶端->服務(wù)器:塊下載 */else if(d->transfers[line].rxstep == RXSTEP_STARTED) {MSG_WAR(0x3A9B, "Received SDO block download data segment - index 0x1200 + ", CliServNbr);/* 重啟sdo傳輸通道超時定時器 */RestartSDO_TIMER(line)/* 取出序列號 */SeqNo = m->data[0] & 0x7F;/* 檢查是否最后一塊 */if(m->data[0] & 0x80) {/* 對序列號進行校驗 */if(SeqNo == (d->transfers[line].seqno + 1)) {/* 接收結(jié)束 */d->transfers[line].rxstep = RXSTEP_END;/* 設(shè)置序列號 */d->transfers[line].seqno = SeqNo;/* 將數(shù)據(jù)拷貝到傳輸通道臨時數(shù)據(jù)緩沖 */memcpy(d->transfers[line].tmpData, m->data, 8);}/* 塊傳輸響應(yīng) */data[0] = (5 << 5) | SDO_BSS_DOWNLOAD_RESPONSE;/* 序列號 */data[1] = d->transfers[line].seqno;/* 塊數(shù)量 */data[2] = SDO_BLOCK_SIZE;/* 不足8字節(jié)補0 */data[3] = data[4] = data[5] = data[6] = data[7] = 0;MSG_WAR(0x3AAE, "SDO. Sending block download response - index 0x1200 + ", CliServNbr);/* 發(fā)送sdo數(shù)據(jù)包 */sendSDO(d, whoami, CliServNbr, data);/* 將序列號置0 */d->transfers[line].seqno = 0;}/* 如果不是最后一塊 */else {/* 對序列號進行校驗 */if(SeqNo == (d->transfers[line].seqno + 1)) {/* 設(shè)置序列號 */d->transfers[line].seqno = SeqNo;/* 將數(shù)據(jù)從sdo報文中拷貝到傳輸通道緩沖區(qū)*/err = SDOtoLine(d, line, 7, (*m).data + 1);if(err) {failedSDO(d, CliServNbr, whoami, d->transfers[line].index, d->transfers[line].subIndex, SDOABT_GENERAL_ERROR);return 0xFF;}}/* 如果一次傳輸還不夠傳,則響應(yīng) */if(SeqNo == SDO_BLOCK_SIZE) {/* 塊傳輸響應(yīng) */data[0] = (5 << 5) | SDO_BSS_DOWNLOAD_RESPONSE;/* 序列號 */data[1] = d->transfers[line].seqno;/* 塊數(shù)量 */data[2] = SDO_BLOCK_SIZE;/* 不足8字節(jié)補0 */data[3] = data[4] = data[5] = data[6] = data[7] = 0;MSG_WAR(0x3AAE, "SDO. Sending block download response - index 0x1200 + ", CliServNbr);/* 發(fā)送sdo數(shù)據(jù)包 */sendSDO(d, whoami, CliServNbr, data);/* 將序列號置0 */d->transfers[line].seqno = 0;}}}/* 客戶端->服務(wù)器:塊下載結(jié)束 */else if(d->transfers[line].rxstep == RXSTEP_END) {MSG_WAR(0x3A9B, "Received SDO block download end request - index 0x1200 + ", CliServNbr);/* 驗證數(shù)據(jù)包是不是塊下載結(jié)束 */if((m->data[0] & 1) != SDO_BCS_END_DOWNLOAD_REQUEST) {MSG_ERR(0x1AAD, "SDO error block download : Received wrong subcommand - index 0x1200 + ", CliServNbr);failedSDO(d, CliServNbr, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);return 0xFF;}/* 重啟sdo傳輸通道超時定時器 */RestartSDO_TIMER(line)/* 取出補零個數(shù) */NbBytesNoData = (m->data[0] >> 2) & 0x07;/* 將數(shù)據(jù)從傳輸通道臨時緩沖區(qū)拷貝到傳輸通道緩沖區(qū) */err = SDOtoLine(d, line, 7 - NbBytesNoData, d->transfers[line].tmpData + 1);if(err) {failedSDO(d, CliServNbr, whoami, d->transfers[line].index, d->transfers[line].subIndex, SDOABT_GENERAL_ERROR);return 0xFF;}/* 判斷接收到的數(shù)據(jù)和初始化發(fā)過來的數(shù)據(jù)個數(shù)是否一致 */if(d->transfers[line].objsize){if(d->transfers[line].objsize != d->transfers[line].offset){MSG_ERR(0x1AAE, "SDO error block download : sizes do not match - index 0x1200 + ", CliServNbr);failedSDO(d, CliServNbr, whoami, d->transfers[line].index, d->transfers[line].subIndex, SDOABT_LOCAL_CTRL_ERROR);return 0xFF;}}/* 塊下載傳輸結(jié)束 */data[0] = (5 << 5) | SDO_BSS_END_DOWNLOAD_RESPONSE;/* 數(shù)據(jù)填0 */for(i = 1; i < 8; i++)data[i] = 0;MSG_WAR(0x3AAF, "SDO. Sending block download end response - index 0x1200 + ", CliServNbr);/* 發(fā)送sdo報文 */sendSDO(d, whoami, CliServNbr, data);/* 將數(shù)據(jù)從sdo傳輸通道拷貝到字典中 */errorCode = SDOlineToObjdict(d, line);if(errorCode) {MSG_ERR(0x1AAF, "SDO error : Unable to copy the data in the object dictionary", 0);failedSDO(d, CliServNbr, whoami, d->transfers[line].index, d->transfers[line].subIndex, errorCode);return 0xFF;}/* 復(fù)位sdo傳輸通道 */resetSDOline(d, line);MSG_WAR(0x3AAF, "SDO. End of block download defined at index 0x1200 + ", CliServNbr);}}/* 服務(wù)器->客戶端:塊上傳初始化/服務(wù)器->客戶端:塊上傳/服務(wù)器->客戶端:塊上傳結(jié)束 */else{if(err) {MSG_ERR(0x1AAD, "SDO error block upload : no transmission started", nodeId);failedSDO(d, CliServNbr, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);return 0xFF;}/* 重啟傳輸通道超時定時器 */RestartSDO_TIMER(line)/* 服務(wù)器->客戶端:塊上傳初始化 */if(d->transfers[line].rxstep == RXSTEP_INIT) {/* 校驗數(shù)據(jù)包是不是塊上傳響應(yīng) */if((m->data[0] & 1) == SDO_BSS_INITIATE_UPLOAD_RESPONSE) {MSG_WAR(0x3A9C, "Received SDO block upload response from node id ", nodeId);/* 塊傳輸開始 */d->transfers[line].rxstep = RXSTEP_STARTED;/* 是否支持crc */d->transfers[line].peerCRCsupport = ((m->data[0]) >> 2) & 1;/* 是否指明數(shù)據(jù)長度 */if((m->data[0]) & 2){d->transfers[line].objsize = (UNS32)m->data[4] + (UNS32)m->data[5] * 256 + (UNS32)m->data[6] * 256 * 256 + (UNS32)m->data[7] * 256 * 256 * 256;}/* 開始上傳請求 */data[0] = (5 << 5) | SDO_BCS_START_UPLOAD;for(i = 1; i < 8; i++)data[i] = 0;MSG_WAR(0x3AB6, "SDO. Sending block upload start to node id ", nodeId);/* 發(fā)送手動報文 */sendSDO(d, whoami, CliServNbr, data);}}/* 服務(wù)器->客戶端:塊上傳 */else if(d->transfers[line].rxstep == RXSTEP_STARTED) {/* 序列號 */SeqNo = m->data[0] & 0x7F;/* 最后一塊 */if(m->data[0] & 0x80) {/* 校驗序列號,如果通過則將狀態(tài)置為結(jié)束 */if(SeqNo == (d->transfers[line].seqno + 1)) {d->transfers[line].rxstep = RXSTEP_END;d->transfers[line].seqno = SeqNo;/* 將數(shù)據(jù)拷貝到傳輸通道臨時緩沖區(qū) */memcpy(d->transfers[line].tmpData, m->data, 8);}/* 對塊傳輸進行相應(yīng) */data[0] = (5 << 5) | SDO_BCS_UPLOAD_RESPONSE;/* 序列號 */data[1] = d->transfers[line].seqno;/* 一次傳輸最大塊數(shù)量 */data[2] = SDO_BLOCK_SIZE;/* 補零 */data[3] = data[4] = data[5] = data[6] = data[7] = 0;MSG_WAR(0x3AB7, "SDO. Sending block upload response to node id ", nodeId);/* 發(fā)送報文 */sendSDO(d, whoami, CliServNbr, data);/* 序列號置零 */ d->transfers[line].seqno = 0;}/* 如果不是最后一塊 */else {/* 校驗序列號,如果通過則將數(shù)據(jù)拷貝到傳輸通道 */if(SeqNo == (d->transfers[line].seqno + 1)) { d->transfers[line].seqno = SeqNo;/* 將數(shù)據(jù)拷貝到傳輸通道 */err = SDOtoLine(d, line, 7, (*m).data + 1);if(err) {failedSDO(d, CliServNbr, whoami, d->transfers[line].index, d->transfers[line].subIndex, SDOABT_GENERAL_ERROR);return 0xFF;}}/* 如果一次傳輸結(jié)束 */if(SeqNo == SDO_BLOCK_SIZE) {/* 響應(yīng) */data[0] = (5 << 5) | SDO_BCS_UPLOAD_RESPONSE;data[1] = d->transfers[line].seqno;data[2] = SDO_BLOCK_SIZE;data[3] = data[4] = data[5] = data[6] = data[7] = 0;MSG_WAR(0x3AAE, "SDO. Sending block upload response to node id ", nodeId);sendSDO(d, whoami, CliServNbr, data);d->transfers[line].seqno = 0;}}}/* 服務(wù)器->客戶端:塊上傳結(jié)束 */else if(d->transfers[line].rxstep == RXSTEP_END) {/* 校驗上傳結(jié)束 */if((m->data[0] & 1) != SDO_BSS_END_UPLOAD_RESPONSE) {MSG_ERR(0x1AAD, "SDO error block upload : Received wrong subcommand from node id ", nodeId);failedSDO(d, CliServNbr, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);return 0xFF;}/* 補零字節(jié)數(shù) */NbBytesNoData = (m->data[0] >> 2) & 0x07;/* 將數(shù)據(jù)從sdo報文中拷貝到傳輸通道緩沖區(qū) */err = SDOtoLine(d, line, 7 - NbBytesNoData, d->transfers[line].tmpData + 1);if(err) {failedSDO(d, CliServNbr, whoami, d->transfers[line].index, d->transfers[line].subIndex, SDOABT_GENERAL_ERROR);return 0xFF;}/* 校驗一下數(shù)據(jù)長度 */if(d->transfers[line].objsize){if(d->transfers[line].objsize != d->transfers[line].offset){MSG_ERR(0x1AAE, "SDO error block download : sizes do not match - from node id ", nodeId);failedSDO(d, CliServNbr, whoami, d->transfers[line].index, d->transfers[line].subIndex, SDOABT_LOCAL_CTRL_ERROR);return 0xFF;}}/* 塊上傳結(jié)束請求 */data[0] = (5 << 5) | SDO_BCS_END_UPLOAD_REQUEST;for(i = 1; i < 8; i++)data[i] = 0;MSG_WAR(0x3AAF, "SDO. Sending block upload end request to node id ", nodeId);/* 發(fā)送數(shù)據(jù)包 */sendSDO(d, whoami, CliServNbr, data);MSG_WAR(0x3AAF, "SDO. End of block upload request", 0);/* 停止超時定時器 */StopSDO_TIMER(line)/* 傳輸完成 */d->transfers[line].state = SDO_FINISHED;/* 調(diào)用回調(diào)函數(shù) */if(d->transfers[line].Callback) (*d->transfers[line].Callback)(d,nodeId);}}break;default:MSG_ERR(0x1AB2, "SDO. Received unknown command specifier : ", cs);return 0xFF;} return 0; }/* 通過節(jié)點號查找客戶端號 */ UNS8 GetSDOClientFromNodeId(CO_Data *d, UNS8 nodeId) {UNS8 SDOfound = 0;UNS8 CliNbr;UNS16 lastIndex;UNS16 offset;UNS8 nodeIdServer;/* 第一個sdo客戶端在字典中的下標 */offset = d->firstIndex->SDO_CLT;/* 最后一個sdo客戶端在字典中的下標 */lastIndex = d->lastIndex->SDO_CLT;if(offset == 0) {MSG_ERR(0x1AC6, "No SDO client index found for nodeId ", nodeId);return 0xFF;}/* 客戶端號置零 */CliNbr = 0;/* 遍歷字典中所有客戶端條目 */while(offset <= lastIndex){/* 客戶端條目中子索引個數(shù)大于3 */if(d->objdict[offset].bSubCount <= 3){MSG_ERR(0x1AC8, "Subindex 3 not found at index ", 0x1280 + CliNbr);return 0xFF;}/* 從字典中取出服務(wù)器節(jié)點id */nodeIdServer = *((UNS8*)d->objdict[offset].pSubindex[3].pObject);MSG_WAR(0x1AD2, "index : ", 0x1280 + CliNbr);MSG_WAR(0x1AD3, "nodeIdServer : ", nodeIdServer);/* 如果節(jié)點id和服務(wù)器節(jié)點id匹配,相當于找到了對應(yīng)的客戶端號,因為每個客戶端對應(yīng)一個服務(wù)器 */if(nodeIdServer == nodeId) {SDOfound = 1;break;}offset++;CliNbr++;}/* 如果沒找到對應(yīng)的服務(wù)器。則退出 */if(!SDOfound) {MSG_WAR(0x1AC9, "SDO No preset client found to communicate with node : ", nodeId);return 0xFE;}MSG_WAR(0x3AD0, " SDO client defined at index : ", 0x1280 + CliNbr);return CliNbr; }/* 寫服務(wù)器字典 */ INLINE UNS8 _writeNetworkDict(CO_Data *d, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS32 count, UNS8 dataType, void *data, SDOCallback_t Callback, UNS8 endianize, UNS8 useBlockMode) {UNS8 err;UNS8 line;UNS8 CliNbr;UNS32 j;UNS8 i;UNS8 buf[8];MSG_WAR(0x3AC0, "Send SDO to write in the dictionary of node : ", nodeId);MSG_WAR(0x3AC1, " At index : ", index);MSG_WAR(0x3AC2, " subIndex : ", subIndex);MSG_WAR(0x3AC3, " nb bytes : ", count);/* 通過服務(wù)器節(jié)點ID查找客戶端號 */CliNbr = GetSDOClientFromNodeId(d, nodeId);/* 客戶端不能大于等于254個 */if(CliNbr >= 0xFE)return CliNbr;/* 通過客戶端號獲取sdo傳輸通道,檢查該客戶端是否正在傳輸過程中,如果在直接退出 */err = getSDOlineOnUse(d, CliNbr, SDO_CLIENT, &line);if(!err){MSG_ERR(0x1AC4, "SDO error : Communication yet established. with node : ", nodeId);return 0xFF;}/* 獲取空閑的sdo傳輸通道 */err = getSDOfreeLine(d, SDO_CLIENT, &line);if(err) {MSG_ERR(0x1AC5, "SDO error : No line free, too many SDO in progress. Aborted for node : ", nodeId);return (0xFF);}else{MSG_WAR(0x3AE1, "Transmission on line : ", line);}/* 塊模式 */if(useBlockMode) {/* 初始化sdo傳輸通道 */initSDOline(d, line, CliNbr, index, subIndex, SDO_BLOCK_DOWNLOAD_IN_PROGRESS);d->transfers[line].objsize = count;}else{/* 初始化sdo傳輸通道 */initSDOline(d, line, CliNbr, index, subIndex, SDO_DOWNLOAD_IN_PROGRESS);}/* 字節(jié)數(shù) */d->transfers[line].count = count;/* 數(shù)據(jù)類型 */d->transfers[line].dataType = dataType;/* 支持內(nèi)存動態(tài)分配 */ #ifdef SDO_DYNAMIC_BUFFER_ALLOCATION{/* 緩沖區(qū)指針 */UNS8 *lineData = d->transfers[line].data;/* 如果字節(jié)數(shù)大于緩沖區(qū)長度 */if(count > SDO_MAX_LENGTH_TRANSFER){/* 動態(tài)分配內(nèi)存 */d->transfers[line].dynamicData = (UNS8*)malloc(count);d->transfers[line].dynamicDataSize = count;if(d->transfers[line].dynamicData == NULL){MSG_ERR(0x1AC9, "SDO. Error. Could not allocate enough bytes : ", count);return 0xFE;}lineData = d->transfers[line].dynamicData;} #endif/* 將數(shù)據(jù)拷貝到緩沖區(qū) */for(j = 0; j < count; j++) { #ifdef SDO_DYNAMIC_BUFFER_ALLOCATION #ifdef CANOPEN_BIG_ENDIANif(dataType == 0 && endianize)lineData[count - 1 - j] = ((char *)data)[j];elselineData[j] = ((char *)data)[j]; #elselineData[j] = ((char *)data)[j]; #endif} #else #ifdef CANOPEN_BIG_ENDIANif(dataType == 0 && endianize)d->transfers[line].data[count - 1 - j] = ((char *)data)[j];elsed->transfers[line].data[j] = ((char *)data)[j]; #elsed->transfers[line].data[j] = ((char *)data)[j]; #endif #endif}/* 塊下載 */if(useBlockMode) {/* 塊下載:110 */buf[0] = (6 << 5) | (1 << 1);/* 字節(jié)數(shù) */for(i = 0; i < 4; i++){buf[i + 4] = (UNS8)((count >> (i << 3)));}}/* 域下載 */else{/* 字節(jié)數(shù)少于4字節(jié),加速下載 */if(count <= 4){/* 下載:001 + 無意義字節(jié)數(shù) + 加速下載 + 指明數(shù)據(jù)長度 */buf[0] = (UNS8)((1 << 5) | ((4 - count) << 2) | 3);/* 拷貝數(shù)據(jù) */for(i = 4; i < 8; i++)buf[i] = d->transfers[line].data[i - 4];d->transfers[line].offset = count;}/* 字節(jié)數(shù)大于4字節(jié),正常下載 */else{/* 下載:001 + 數(shù)據(jù)字節(jié)為字節(jié)計數(shù)器 */buf[0] = (1 << 5) | 1;/* 數(shù)據(jù)字節(jié)數(shù) */for(i = 0; i < 4; i++)buf[i + 4] = (UNS8)((count >> (i << 3)));}}/* 索引 */buf[1] = index & 0xFF;buf[2] = (index >> 8) & 0xFF;/* 子索引 */buf[3] = subIndex;/* 注冊傳輸完成回調(diào)函數(shù) */d->transfers[line].Callback = Callback;/* 發(fā)送sdo報文 */err = sendSDO(d, SDO_CLIENT, CliNbr, buf);if(err) {MSG_ERR(0x1AD1, "SDO. Error while sending SDO to node : ", nodeId);/* 復(fù)位該sdo傳輸通道 */resetSDOline(d, line);return 0xFF;}return 0; }/* 寫服務(wù)器字典 */ UNS8 writeNetworkDict(CO_Data *d, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS32 count, UNS8 dataType, void *data, UNS8 useBlockMode) {return _writeNetworkDict(d, nodeId, index, subIndex, count, dataType, data, NULL, 1, useBlockMode); }/* 寫服務(wù)器字典,寫完調(diào)用回調(diào)函數(shù) */ UNS8 writeNetworkDictCallBack(CO_Data* d, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS32 count, UNS8 dataType, void *data, SDOCallback_t Callback, UNS8 useBlockMode) {return _writeNetworkDict(d, nodeId, index, subIndex, count, dataType, data, Callback, 1, useBlockMode); }/* 自動初始化客戶端,并且寫服務(wù)器字典 */ UNS8 writeNetworkDictCallBackAI(CO_Data *d, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS32 count, UNS8 dataType, void *data, SDOCallback_t Callback, UNS8 endianize, UNS8 useBlockMode) {UNS8 ret;UNS16 lastIndex;UNS16 offset;UNS8 nodeIdServer;/* 寫服務(wù)器字典 */ret = _writeNetworkDict(d, nodeId, index, subIndex, count, dataType, data, Callback, endianize, useBlockMode);/* 如果寫失敗 */if(ret == 0xFE){/* 自動初始化客戶端,并且寫字典 */offset = d->firstIndex->SDO_CLT;lastIndex = d->lastIndex->SDO_CLT;if(offset == 0){MSG_ERR(0x1AC6, "writeNetworkDict : No SDO client index found", 0);return 0xFF;}while(offset <= lastIndex){if(d->objdict[offset].bSubCount <= 3){MSG_ERR(0x1AC8, "Subindex 3 not found at index ", 0x1280 + i);return 0xFF;}nodeIdServer = *(UNS8*) d->objdict[offset].pSubindex[3].pObject;if(nodeIdServer == 0){*(UNS32*)d->objdict[offset].pSubindex[1].pObject = (UNS32)(0x600 + nodeId);*(UNS32*)d->objdict[offset].pSubindex[2].pObject = (UNS32)(0x580 + nodeId);*(UNS8*) d->objdict[offset].pSubindex[3].pObject = nodeId;return _writeNetworkDict(d, nodeId, index, subIndex, count, dataType, data, Callback, endianize, useBlockMode);}offset++;}return 0xFF;}else if(ret == 0){return 0;}else{return 0xFF;} }/* 讀服務(wù)器字典 */ INLINE UNS8 _readNetworkDict(CO_Data *d, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS8 dataType, SDOCallback_t Callback, UNS8 useBlockMode) {UNS8 err;UNS8 i;UNS8 CliNbr;UNS8 line;UNS8 data[8];MSG_WAR(0x3AD5, "Send SDO to read in the dictionary of node : ", nodeId);MSG_WAR(0x3AD6, " At index : ", index);MSG_WAR(0x3AD7, " subIndex : ", subIndex);/* 通過節(jié)點號查找客戶端號 */CliNbr = GetSDOClientFromNodeId(d, nodeId);if(CliNbr >= 0xFE)return CliNbr;/* 通過客戶端/服務(wù)器號獲取sdo傳輸通道號,檢查客戶端是否在通訊中 */err = getSDOlineOnUse(d, CliNbr, SDO_CLIENT, &line);if(!err) {MSG_ERR(0x1AD8, "SDO error : Communication yet established. with node : ", nodeId);return 0xFF;}/* 獲取空閑的sdo傳輸通道 */err = getSDOfreeLine(d, SDO_CLIENT, &line );if(err) {MSG_ERR(0x1AD9, "SDO error : No line free, too many SDO in progress. Aborted for node : ", nodeId);return (0xFF);}elseMSG_WAR(0x3AE0, "Transmission on line : ", line);/* 塊傳輸模式 */if(useBlockMode) {/* 初始化sdo傳輸通道 */initSDOline(d, line, CliNbr, index, subIndex, SDO_BLOCK_UPLOAD_IN_PROGRESS);/* 設(shè)置數(shù)據(jù)類型 */d->transfers[line].dataType = dataType;/* 塊上傳初始化 */data[0] = (5 << 5) | SDO_BCS_INITIATE_UPLOAD_REQUEST;/* 索引 */data[1] = index & 0xFF;data[2] = (index >> 8) & 0xFF;/* 子索引 */data[3] = subIndex;/* 塊數(shù)量 */data[4] = SDO_BLOCK_SIZE;/* 不足8字節(jié)部分填0 */for(i = 5; i < 8; i++)data[i] = 0;}else {/* 初始化sdo傳輸通道 */initSDOline(d, line, CliNbr, index, subIndex, SDO_UPLOAD_IN_PROGRESS);/* 設(shè)置數(shù)據(jù)類型 */d->transfers[line].dataType = dataType;/* 啟動域上傳 */data[0] = (2 << 5);/* 索引 */data[1] = index & 0xFF;data[2] = (index >> 8) & 0xFF;/* 子索引 */data[3] = subIndex;/* 不足8字節(jié)部分填0 */for(i = 4; i < 8; i++)data[i] = 0;}/* 注冊傳輸完成回調(diào)函數(shù) */d->transfers[line].Callback = Callback;/* 發(fā)送sdo數(shù)據(jù)包 */err = sendSDO(d, SDO_CLIENT, CliNbr, data);if(err) {MSG_ERR(0x1AE5, "SDO. Error while sending SDO to node : ", nodeId);resetSDOline(d, line);return 0xFF;}return 0; }/* 讀服務(wù)器字典 */ UNS8 readNetworkDict(CO_Data *d, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS8 dataType, UNS8 useBlockMode) {return _readNetworkDict(d, nodeId, index, subIndex, dataType, NULL, useBlockMode); }/* 讀服務(wù)器字典,完成調(diào)用回調(diào)函數(shù) */ UNS8 readNetworkDictCallback (CO_Data* d, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS8 dataType, SDOCallback_t Callback, UNS8 useBlockMode) {return _readNetworkDict (d, nodeId, index, subIndex, dataType, Callback, useBlockMode); }/* 自動初始化客戶端,并且讀服務(wù)器字典 */ UNS8 readNetworkDictCallbackAI(CO_Data* d, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS8 dataType, SDOCallback_t Callback, UNS8 useBlockMode) {UNS8 ret;UNS16 lastIndex;UNS16 offset;UNS8 nodeIdServer;/* 讀服務(wù)器字典 */ret = _readNetworkDict(d, nodeId, index, subIndex, dataType, Callback, useBlockMode);/* 如果讀失敗 */if(ret == 0xFE){/* 自動初始化客戶端,并且讀字典 */offset = d->firstIndex->SDO_CLT;lastIndex = d->lastIndex->SDO_CLT;if(offset == 0){MSG_ERR(0x1AC6, "writeNetworkDict : No SDO client index found", 0);return 0xFF;}while(offset <= lastIndex){if (d->objdict[offset].bSubCount <= 3){MSG_ERR(0x1AC8, "Subindex 3 not found at index ", 0x1280 + i);return 0xFF;}nodeIdServer = *(UNS8*)d->objdict[offset].pSubindex[3].pObject;if(nodeIdServer == 0){*(UNS32*)d->objdict[offset].pSubindex[1].pObject = (UNS32)(0x600 + nodeId);*(UNS32*)d->objdict[offset].pSubindex[2].pObject = (UNS32)(0x580 + nodeId);*(UNS8*)d->objdict[offset].pSubindex[3].pObject = nodeId;return _readNetworkDict(d, nodeId, index, subIndex, dataType, Callback, useBlockMode);}offset++;}return 0xFF;}else if(ret == 0){return 0;}else{return 0xFF;} }/* 獲取讀服務(wù)器字典結(jié)果 */ UNS8 getReadResultNetworkDict(CO_Data *d, UNS8 nodeId, void *data, UNS32 *size, UNS32 *abortCode) {UNS32 i;UNS8 err;UNS8 CliNbr;UNS8 line;*abortCode = 0;/* 通過節(jié)點號查找客戶端號 */CliNbr = GetSDOClientFromNodeId(d, nodeId);if(CliNbr >= 0xFE) {*size = 0;return SDO_ABORTED_INTERNAL;}/* 通過客戶端/服務(wù)器號獲取sdo傳輸通道號 */err = getSDOlineOnUse(d, CliNbr, SDO_CLIENT, &line);if(err) {MSG_ERR(0x1AF0, "SDO error : No line found for communication with node : ", nodeId);*size = 0;return SDO_ABORTED_INTERNAL;}/* 如果寫字典未完成,則返回傳輸通道狀態(tài) */if(d->transfers[line].state != SDO_FINISHED) {if((d->transfers[line].state == SDO_ABORTED_RCV) || (d->transfers[line].state == SDO_ABORTED_INTERNAL)) {*abortCode = d->transfers[line].abortCode;*size = 0;}return d->transfers[line].state;}/* 檢查數(shù)據(jù)傳輸是否完整 */if(d->transfers[line].count == 0)d->transfers[line].count = d->transfers[line].offset;if(*size < d->transfers[line].count) {*size = 0;return SDO_PROVIDED_BUFFER_TOO_SMALL;}/* 把字節(jié)數(shù)傳回去 */*size = d->transfers[line].count;/* 將數(shù)據(jù)傳回去 */ #ifdef SDO_DYNAMIC_BUFFER_ALLOCATION{UNS8 *lineData = d->transfers[line].data;if(d->transfers[line].dynamicData && d->transfers[line].dynamicDataSize){lineData = d->transfers[line].dynamicData;}for(i = 0; i < *size; i++) { #ifdef CANOPEN_BIG_ENDIANif(d->transfers[line].dataType != visible_string)((char *)data)[*size - 1 - i] = lineData[i];else((char *)data)[i] = lineData[i]; #else((char *)data)[i] = lineData[i]; #endif}} #elsefor(i = 0 ; i < *size; i++) { #ifdef CANOPEN_BIG_ENDIANif(d->transfers[line].dataType != visible_string)((char *)data)[*size - 1 - i] = d->transfers[line].data[i];else((char *)data)[i] = d->transfers[line].data[i]; #else((char *)data)[i] = d->transfers[line].data[i]; #endif} #endif/* 復(fù)位sdo傳輸通道 */resetSDOline(d, line);/* 返回傳輸完成 */return SDO_FINISHED; }/* 獲取寫服務(wù)器字典結(jié)果 */ UNS8 getWriteResultNetworkDict(CO_Data *d, UNS8 nodeId, UNS32 *abortCode) {UNS8 line = 0;UNS8 err;UNS8 CliNbr;*abortCode = 0;/* 通過節(jié)點號查找客戶端號 */CliNbr = GetSDOClientFromNodeId(d, nodeId);if(CliNbr >= 0xFE)return SDO_ABORTED_INTERNAL;/* 通過客戶端/服務(wù)器號獲取sdo傳輸通道號 */err = getSDOlineOnUse(d, CliNbr, SDO_CLIENT, &line);if(err) {MSG_ERR(0x1AF1, "SDO error : No line found for communication with node : ", nodeId);return SDO_ABORTED_INTERNAL;}/* 中止碼 */*abortCode = d->transfers[line].abortCode;/* 如果寫字典未完成,則返回傳輸通道狀態(tài) */if(d->transfers[line].state != SDO_FINISHED)return d->transfers[line].state;/* 復(fù)位sdo傳輸通道 */resetSDOline(d, line);/* 返回傳輸完成 */return SDO_FINISHED; }



總結(jié)

以上是生活随笔為你收集整理的CANOpen服务数据对象报文的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。

免费成人av网站 | 日韩a在线观看 | 玖玖在线观看视频 | 又黄又爽又色无遮挡免费 | 在线播放视频一区 | 免费在线观看日韩视频 | 亚洲第一伊人 | 国产视频在线免费观看 | 91精品综合在线观看 | 亚洲天堂精品 | 亚洲国产精品成人综合 | 国产精品久久久久久久久久直播 | 日韩簧片在线观看 | 日本女人逼| 麻豆传媒视频观看 | 欧美日韩免费在线视频 | 天天综合婷婷 | 免费在线观看一区 | 久久久久成人精品免费播放动漫 | 亚洲欧美成人网 | 欧美一级免费 | www九九热 | 亚洲成色777777在线观看影院 | 人人狠狠综合久久亚洲婷 | 日韩欧美国产精品 | 久久av一区二区三区亚洲 | av资源免费看 | 久艹视频在线免费观看 | 日日草天天草 | 日韩高清在线一区二区三区 | 久久黄色网址 | 亚洲精品高清一区二区三区四区 | 999国产精品视频 | 日本黄区免费视频观看 | 国产一线二线三线性视频 | 日韩中文字幕91 | 又污又黄的网站 | 91av色| 日日干天夜夜 | 日韩在线观看视频网站 | 国产精品 国内视频 | 天天操天天色综合 | 日韩欧美在线综合网 | 伊人色播| 九色91在线 | 在线综合 亚洲 欧美在线视频 | 日韩成人欧美 | 天天爱天天操 | a天堂中文在线 | av在线免费播放网站 | 日韩欧美成人网 | 国产美女视频黄a视频免费 久久综合九色欧美综合狠狠 | 国产福利精品一区二区 | 最新av免费在线 | 成人在线免费小视频 | 在线看国产日韩 | 久久99精品久久久久久三级 | 欧美少妇影院 | 亚洲激情 欧美激情 | 欧美男同视频网站 | 97在线观看免费视频 | 人人爽人人爽人人爽学生一级 | 久久69精品久久久久久久电影好 | 综合激情婷婷 | 国产视频18 | 992tv在线观看网站 | 日日射天天射 | 一区二区视频网站 | 在线观看亚洲a | 狠狠色香婷婷久久亚洲精品 | 96久久 | 日韩精品免费在线 | 嫩草91影院 | 国产精品系列在线观看 | 99热官网 | 国产成人在线免费观看 | 欧美一区二区在线刺激视频 | 亚洲国产精品女人久久久 | 亚洲精品男人天堂 | 中国一级特黄毛片大片久久 | 日日碰狠狠添天天爽超碰97久久 | 天天骚夜夜操 | 亚洲一级在线观看 | 最新av电影网址 | 天天干.com | 久久精品韩国 | 国产精品一区二区免费看 | 亚洲黄色免费网站 | 九九久久精品视频 | 玖玖爱免费视频 | 中文字幕在线观看视频网站 | 国产精品一区二区久久精品爱涩 | 在线中文字幕网站 | 亚洲精品动漫在线 | 久久精品国产v日韩v亚洲 | 国产一级做a爱片久久毛片a | 国产亚洲91| 91九色精品女同系列 | 最新免费av在线 | 国产午夜三级一区二区三桃花影视 | 丁香影院在线 | 亚洲高清91 | 美女黄视频免费看 | 久久视频在线观看免费 | 在线精品国产 | 国偷自产中文字幕亚洲手机在线 | 在线看片一区 | a黄色影院 | 操操碰| 国产亚洲精品无 | 国产精品麻豆91 | 久久中国精品 | 蜜臀aⅴ国产精品久久久国产 | 日本午夜在线观看 | 久久99在线 | 国产一区二区在线看 | 91av在线免费 | 色婷婷综合视频在线观看 | 天天爽网站 | www178ccom视频在线 | 日韩在线观看高清 | 亚洲最新在线视频 | 在线视频一二三 | 国产高清在线永久 | 99日韩精品 | 欧美成a人片在线观看久 | 99久久婷婷国产综合精品 | 天天色宗合 | 日韩欧美一区二区在线观看 | 日韩a在线观看 | 国产在线精品播放 | av在线播放亚洲 | 国产高清不卡在线 | 黄色小说免费在线观看 | 久久久久激情 | 天天干天天草天天爽 | 福利精品在线 | 日本丶国产丶欧美色综合 | 国产精品国产三级国产不产一地 | 天天躁日日躁狠狠躁 | 久久美女免费视频 | 91免费观看视频网站 | 91精品久久久久久久99蜜桃 | 久久艹欧美 | www免费网站在线观看 | 日韩小视频 | 狠狠久久婷婷 | 开心婷婷色 | 9i看片成人免费看片 | 精品国产一区二区三区久久久蜜月 | 日韩视频中文字幕在线观看 | 国产精品久久久久久久久毛片 | 欧美一级乱黄 | 亚洲日韩中文字幕 | 鲁一鲁影院 | 成人午夜电影在线 | 日韩高清免费电影 | 日日操天天操狠狠操 | 亚洲成人黄色在线观看 | a级片久久| av黄色成人 | 狠狠躁18三区二区一区ai明星 | 亚洲国产精品一区二区尤物区 | 久草热久草视频 | 国产精品久久久久一区二区国产 | 色视频网站在线 | 久久夜色精品国产亚洲aⅴ 91chinesexxx | 久久好看免费视频 | 久久九九影视 | 天天操操| 婷婷丁香六月天 | 国产专区一 | 在线免费国产视频 | 在线网站黄 | 国产一级黄色电影 | 免费 在线 中文 日本 | 免费视频在线观看网站 | 久久综合中文色婷婷 | 亚洲国产三级 | 久久经典国产 | 日韩毛片在线一区二区毛片 | 欧美日韩免费一区 | 精品视频中文字幕 | 欧美天天综合网 | 六月丁香综合 | 毛片的网址 | 国产一区二区手机在线观看 | 91亚洲永久精品 | 国产在线免费观看 | 亚洲精品国产成人 | 91精品在线麻豆 | 久久天天躁狠狠躁亚洲综合公司 | 亚洲日本一区二区在线 | 看国产黄色片 | 精品在线观看视频 | 日韩免费一级a毛片在线播放一级 | 中文字幕在线视频一区二区三区 | 伊人影院av | 久久一区国产 | 韩国av一区二区三区 | 久久久久免费看 | 国产第一页福利影院 | 国产91在| 日本中文字幕在线看 | 日韩欧美在线观看 | 中文字幕二区 | 午夜三级福利 | av免费片 | 国产中文在线播放 | 一区二区三区高清不卡 | 国产精品麻豆欧美日韩ww | 在线观看国产91 | 中文字幕乱在线伦视频中文字幕乱码在线 | 国产精品女主播一区二区三区 | 亚洲欧美日韩在线一区二区 | 欧美日韩成人 | 久久成人国产精品 | 国产99久久久久 | 久久久91精品国产一区二区精品 | 久久永久视频 | 婷婷久操| 欧美一区,二区 | 中文字幕日韩免费视频 | 精品国产99国产精品 | 成人在线视频免费观看 | 婷婷丁香在线 | 91传媒在线 | 国产福利在线免费 | 人人爽久久久噜噜噜电影 | 中文字幕在线观 | 欧美一级专区免费大片 | 2023天天干| 亚洲传媒在线 | 亚洲国产成人久久综合 | 国产精品麻豆欧美日韩ww | 激情网综合 | 日韩精品一区在线观看 | 在线观看国产区 | 亚洲国产精品va在线看黑人动漫 | 伊人久久精品久久亚洲一区 | 亚州中文av | 精品欧美在线视频 | 欧洲精品视频一区 | 国产成人亚洲在线电影 | 国产精品免费一区二区 | 激情av在线播放 | 亚洲欧美日韩国产精品一区午夜 | 337p日本欧洲亚洲大胆裸体艺术 | 天天做天天爱夜夜爽 | 在线观看免费观看在线91 | a久久久久久 | 国产精品99精品久久免费 | 日韩视频图片 | 久久久不卡影院 | 99久久精品国产亚洲 | 射综合网 | 精品视频在线视频 | 亚洲免费视频在线观看 | 五月婷婷视频在线 | 99热最新在线 | 四虎成人精品永久免费av | 国产剧情一区二区 | 国产精品久久久久久久久久妇女 | 香蕉视频在线播放 | 亚洲1区 在线 | 91精品一区二区三区蜜桃 | 国产成人三级在线播放 | 久青草电影 | 国产成人精品女人久久久 | a久久久久| 免费黄a大片 | 国产精品9999久久久久仙踪林 | 91精品在线免费观看视频 | 精品一区二区三区电影 | 亚洲精品国产综合99久久夜夜嗨 | 成人午夜黄色影院 | 欧美另类老妇 | 成人av动漫在线观看 | 国产精品一区免费观看 | 香蕉久久久久 | 中文字幕日本在线 | 亚洲黄在线观看 | 在线看一区二区 | 欧美一区二区三区在线观看 | 99爱精品视频 | 久久99爱视频 | 免费高清在线观看成人 | 天天干天天怕 | 黄色小说在线免费观看 | 午夜视频免费 | av网址aaa| 免费在线观看国产黄 | 国产精品精品久久久 | 97超碰超碰久久福利超碰 | 美女视频久久 | 久久专区 | 亚洲精品国产区 | 亚洲网站在线 | 国产成人精品一区二三区 | 亚洲日本中文字幕在线观看 | 九九九热精品 | 国产高清综合 | 国产精品h在线观看 | 日韩一区在线免费观看 | 国产香蕉视频在线观看 | 五月天开心| 国产精品18久久久久久久网站 | 国产精品99在线观看 | 午夜精品婷婷 | 美女一级毛片视频 | 国产亚洲欧美日韩高清 | 麻豆国产精品视频 | 久久免费视频99 | 精品视频国产 | 亚洲综合色网站 | 欧美电影在线观看 | 日本xxxx.com| 在线亚洲播放 | 911亚洲精品第一 | 久久观看免费视频 | av一区二区三区在线观看 | 免费成人看片 | 成人一区电影 | 亚洲综合色丁香婷婷六月图片 | 婷婷播播网 | 操操日日| 国产黄色免费看 | 亚洲性少妇性猛交wwww乱大交 | 国产精品电影一区 | 久久91久久久久麻豆精品 | 这里只有精彩视频 | 一区二区中文字幕在线播放 | 天天干天天碰 | 日韩av电影免费观看 | 中文字幕国产精品一区二区 | 天天舔夜夜操 | 欧美视频不卡 | 亚洲免费在线视频 | 国产精品欧美久久久久久 | 久久婷婷色综合 | 国产麻豆电影 | 久久久国产一区二区三区四区小说 | 99热精品国产 | 日韩精品一区二区免费 | 国产资源在线免费观看 | 国产五十路毛片 | 在线看片中文字幕 | 97国产在线观看 | 国产超碰在线 | 国产专区在线视频 | 91久久丝袜国产露脸动漫 | aaa日本高清在线播放免费观看 | av电影 一区二区 | 81精品国产乱码久久久久久 | 日韩久久精品一区二区三区 | a在线一区 | 美女久久99 | 91亚洲永久精品 | 激情av网址 | 香蕉视频在线免费 | 美女免费视频一区二区 | 久久国产精彩视频 | 天天草综合网 | 99久久99视频只有精品 | 国产视频在线免费观看 | 五月婷婷六月丁香激情 | 国产精品久久久久久久久免费 | www.久久久 | 亚洲高清av| 91av原创| 久久99久国产精品黄毛片入口 | 一区二区三区四区在线 | 精品国产伦一区二区三区免费 | 久久久久久久久久久久久久av | av导航福利 | h动漫中文字幕 | 成人性生爱a∨ | 欧美一级免费在线 | 成 人 黄 色 视频 免费观看 | 国内精品久久久久久久久 | 婷婷在线不卡 | 丁香国产视频 | 在线观看精品一区 | 亚洲国产精品小视频 | 久久久久电影网站 | 激情在线五月天 | 亚洲精品xxx | 国产成人综合图片 | 欧美一二区视频 | 久久深夜| 中文字幕在线观看av | 人人爽人人爽av | 激情五月婷婷综合 | a在线视频v视频 | 久久成人综合 | 欧美精品一区在线发布 | 国产精品理论在线观看 | 干亚洲少妇| 色婷婷在线播放 | 婷婷网五月天 | 在线观看片| av成人免费在线 | 91成人免费在线 | 国产成人一二三 | 成年人在线免费视频观看 | 亚洲天堂网站 | 亚洲精品在线二区 | 81国产精品久久久久久久久久 | 少妇性xxx | 欧美a视频在线观看 | 操操操com | 草久在线| 久久久免费观看完整版 | 婷婷五情天综123 | 色婷婷国产精品一区在线观看 | 日韩三级视频在线观看 | 亚洲精品视频免费在线 | 日本中文在线播放 | 亚洲精品午夜一区人人爽 | 久久五月精品 | 国产免费美女 | 人人爽人人爽人人片av | 亚洲国产三级在线观看 | 丁香综合av | 精品免费观看视频 | 成人免费xxxxxx视频 | 91免费在线看片 | 午夜视频色 | 日本超碰在线 | 成+人+色综合 | 91视频在线观看大全 | 人人看人人做人人澡 | 久久av高清 | 超碰av在线播放 | 久久人人爽人人爽 | 婷婷夜夜| 人人澡人人爱 | 免费日韩在线 | 精品亚洲免费 | 久久久久久美女 | aav在线| 少妇资源站| 久久婷亚洲五月一区天天躁 | 在线日韩视频 | 91精品成人久久 | 中文一区在线 | 精品一区二区在线免费观看 | 国产黄影院色大全免费 | 婷婷丁香在线视频 | 一区二区三区在线观看免费 | 日韩精品久久久久久久电影99爱 | 国产成人在线精品 | 欧美日韩亚洲精品在线 | 精品国产亚洲一区二区麻豆 | 久久国语露脸国产精品电影 | 操操色| 激情在线网址 | 国产亚洲精品久久 | 狠狠狠狠狠狠狠干 | 人人插人人看 | 婷婷激情网站 | 天天综合成人 | 精品国产乱码久久久久 | 精品国产一二区 | 黄色成人av| 久久亚洲精品国产亚洲老地址 | 久久综合婷婷综合 | 色.www| 国产精品久久久久久爽爽爽 | 黄色毛片在线 | 日韩久久精品一区 | 在线观看一二三区 | 天天色天天草天天射 | 久草在线高清 | 欧美午夜精品久久久久久浪潮 | 成年人免费电影 | 91精品久久香蕉国产线看观看 | 国产福利一区二区三区视频 | 欧美日韩一区二区免费在线观看 | 久久精品aaa | 日韩一区二区在线免费观看 | 免费亚洲一区二区 | 久久在线播放 | 一级免费黄视频 | 激情av资源网 | 亚洲伊人av | 96亚洲精品久久久蜜桃 | 精品国产区| 久草在线视频首页 | 国产在线精品国自产拍影院 | 99久久久国产免费 | 亚洲五月婷 | 六月丁香色婷婷 | 中文日韩在线视频 | 人人爽人人乐 | 国产精品成人自产拍在线观看 | 国产精品 中文字幕 亚洲 欧美 | 成人av网站在线观看 | 天天av天天 | 日韩欧美在线视频一区二区三区 | 久爱精品在线 | 99c视频高清免费观看 | av在线电影播放 | 久久高清免费观看 | 欧美视频不卡 | 精品毛片一区二区免费看 | 操碰av| 日韩欧美高清免费 | 中文字幕之中文字幕 | 一区二区精品视频 | 久久午夜电影网 | 亚洲国产精品女人久久久 | 最近日韩中文字幕中文 | 日韩毛片在线免费观看 | 夜色成人av | 久久久免费观看 | 久草青青在线观看 | a黄色大片 | 激情久久伊人 | 98涩涩国产露脸精品国产网 | 欧美一级电影免费观看 | 国产淫片 | 天天曰夜夜操 | 激情五月婷婷激情 | 国产精品久久久久久一二三四五 | 四虎免费在线观看 | 国产精品一区二区三区免费看 | 国产一区二区免费在线观看 | 国产精品精品 | 欧美一级免费黄色片 | 深爱开心激情网 | 97国产大学生情侣白嫩酒店 | 久久国产成人午夜av影院宅 | 国产中文字幕在线看 | 91成年视频| 国产日韩欧美视频在线观看 | 99热国产在线观看 | 911久久香蕉国产线看观看 | zzijzzij亚洲日本少妇熟睡 | 青青草在久久免费久久免费 | 99久久精品国产免费看不卡 | 九九在线精品视频 | 亚洲网站在线 | 四虎成人免费影院 | av不卡在线看 | 亚洲欧洲精品一区二区 | www.亚洲在线 | 成人夜晚看av | 久久精品播放 | 国产一级二级三级在线观看 | 激情开心色 | 亚洲高清免费在线 | 成人亚洲欧美 | 成年人免费在线观看网站 | 国产色在线 | 久久精品婷婷 | 午夜久久成人 | 在线观看aaa | 欧美一级在线观看视频 | 高潮久久久 | 亚洲成av人片在线观看无 | 99精品在线免费 | 97视频网址| 91精品国产91久久久久福利 | 中文字幕一区二区三区乱码在线 | 最新色视频 | 亚洲视频一区二区三区在线观看 | 九九九九精品九九九九 | 午夜电影 电影 | 2018亚洲男人天堂 | 91在线视频| 久久亚洲福利 | 中文字幕乱偷在线 | 五月天丁香亚洲 | 91精品播放 | 天天天干夜夜夜操 | 日本黄色免费在线 | 天天色天天爱天天射综合 | 国产精品久久久久久久婷婷 | 中文字幕国产一区 | 国外调教视频网站 | 久草视频免费观 | 91一区啪爱嗯打偷拍欧美 | 99视频国产精品 | 久久8精品| 日韩高清在线一区二区 | 日韩在线欧美在线 | 日日麻批40分钟视频免费观看 | 97精品国产97久久久久久 | 久久少妇| 午夜在线免费观看视频 | 麻豆网站免费观看 | 在线成人欧美 | 国产日韩av在线 | 色综合久久天天 | 免费一级特黄录像 | 日本精品视频在线 | 国产性xxxx| 夜夜看av | 香蕉视频导航 | 蜜臀av性久久久久av蜜臀三区 | 国产一区视频在线播放 | 日韩a欧美 | 日韩视 | 久久成人国产精品一区二区 | 99c视频在线 | 国产精品久久久久久麻豆一区 | 狠狠网亚洲精品 | 国产色就色 | 波多野结衣一区 | 国产日本亚洲高清 | 久久久久一区二区三区四区 | 深爱激情五月网 | 国产我不卡 | 人人干天天射 | 色播99| 国产精品久久久久影视 | 国产一区二区在线播放 | 久久午夜精品影院一区 | 亚洲综合色激情五月 | 欧美一二三专区 | 狠狠色丁香婷婷综合橹88 | 韩日色视频 | av免费看在线 | 激情视频一区二区三区 | 超碰在线色 | 在线视频中文字幕一区 | 亚洲高清视频一区二区三区 | 久久精品4 | 2024国产精品视频 | 色婷婷久久一区二区 | 美女黄频在线观看 | 日韩三级视频 | 婷婷色站| 天天干天天做天天操 | 日韩欧美精选 | 国产视频一二三 | 国产资源免费在线观看 | 成人综合婷婷国产精品久久免费 | 国产精品日韩欧美一区二区 | 91手机视频| 丁香 婷婷 激情 | 蜜桃视频日本 | 中文字幕av全部资源www中文字幕在线观看 | 国产无套精品久久久久久 | 久久久免费电影 | 91试看| 精品国产一区二区三区久久久蜜月 | 91久久久久久国产精品 | 久久99国产视频 | 色综合咪咪久久网 | 国内外激情视频 | 久久9视频 | 亚洲视频999 | 亚洲国产精品va在线看黑人动漫 | 夜夜操天天干, | 国产精品18久久久久久久 | 久久精品中文字幕一区二区三区 | 欧美日本中文字幕 | 深爱婷婷久久综合 | 国产日产精品一区二区三区四区 | 国产91对白在线播 | 黄色av电影一级片 | 天天干中文字幕 | 18国产精品福利片久久婷 | 偷拍精偷拍精品欧洲亚洲网站 | 免费看特级毛片 | 日韩在线观看电影 | 色欧美视频 | 久久亚洲精品电影 | 久久久受www免费人成 | 中文字幕免费观看视频 | 国产精品综合久久久 | 91视频88av | 免费合欢视频成人app | 免费在线观看亚洲视频 | 日韩精品中文字幕av | 国际精品网 | 日韩av进入| 欧美性久久久久久 | 麻豆视频免费入口 | 日韩免费播放 | 国产女人18毛片水真多18精品 | 欧美午夜视频在线 | 国产中出在线观看 | 夜夜夜夜猛噜噜噜噜噜初音未来 | 久久精国产 | 国产夫妻av在线 | 激情五月婷婷激情 | 深爱激情开心 | 国产精品久久久久久麻豆一区 | 69av国产 | 日本xxxx裸体xxxx17 | 激情五月婷婷综合 | 国产精品一区二区久久 | 久草精品在线观看 | 国产成人综合精品 | 免费一级片在线观看 | 成人app在线播放 | 免费亚洲一区二区 | 成年人黄色免费网站 | 免费av福利| 伊人色综合久久天天 | 99超碰在线观看 | 久久综合色婷婷 | 成人在线视频免费观看 | 99re久久资源最新地址 | 视频在线观看入口黄最新永久免费国产 | 久久久国产精华液 | 日本一区二区不卡高清 | 国产精品va视频 | 在线三级av | 国产资源 | 中文字幕高清有码 | 中文字幕国产一区 | 久久精品视频在线播放 | 欧美视频在线二区 | 97精品超碰一区二区三区 | 欧美成人中文字幕 | 欧美日韩在线网站 | 超碰在线最新地址 | 国内免费久久久久久久久久久 | 国产在线视频不卡 | 久草热久草视频 | 国产在线色视频 | 国产小视频精品 | 免费a网址| av高清免费在线 | www.五月婷婷.com | 日本中文在线播放 | 国语黄色片 | 成人久久久久久久久久 | 成人精品一区二区三区电影免费 | 视频国产 | 久久精品欧美一 | 久草电影在线观看 | 一级理论片在线观看 | 五月婷婷在线综合 | 亚洲最新av | 在线观看国产www | 97av在线视频免费播放 | 亚洲精品99久久久久久 | 精品国产福利在线 | 超碰成人网 | 在线观看电影av | 免费网址你懂的 | 超碰免费公开 | 激情久久伊人 | 98涩涩国产露脸精品国产网 | 久久这里只有精品1 | 四虎影视成人精品国库在线观看 | 91在线观看欧美日韩 | 国产精品高清在线 | 亚洲日本va在线观看 | 99精品在线视频观看 | 中文字幕在线观看国产 | 美女视频又黄又免费 | 日韩免费一区二区三区 | 不卡中文字幕在线 | 天天色天天射天天综合网 | av久久久 | 亚洲精品国产精品国自产 | 成人免费看片网址 | 亚洲精品国偷自产在线91正片 | 久久99精品国产99久久 | 久久免费在线 | 超碰人人av| 亚洲全部视频 | 成人小视频在线播放 | 精品久久久久久久久久久久久久久久久久 | 久国产在线播放 | 国产亚洲精品免费 | 欧美性脚交 | 国精产品999国精产品视频 | 成年人国产在线观看 | 天堂av在线网站 | 精品视频一区在线观看 | 日韩高清av | 九九九热精品免费视频观看网站 | 国产免费不卡av | 正在播放亚洲精品 | 黄色的视频| 亚洲精品在线观看视频 | 国产精品国产毛片 | 中文字幕成人一区 | 欧美日韩中文另类 | 久久久久久99精品 | 99久久99| 六月色丁 | www国产亚洲 | 在线看片a | 一级黄色视屏 | 美国av片在线观看 | 日本夜夜草视频网站 | 黄色影院在线免费观看 | 国产a国产 | 中文国产成人精品久久一 | 国产视频2 | 中国一级片在线 | 国产精品美女久久久久久久久 | 久久久www成人免费毛片麻豆 | 很黄很污的视频网站 | 国产va饥渴难耐女保洁员在线观看 | 国产中文字幕视频在线观看 | 激情欧美一区二区免费视频 | 久久一区二区三区日韩 | 日日噜噜噜噜夜夜爽亚洲精品 | 国产又粗又猛又爽又黄的视频先 | 一级欧美日韩 | 免费观看成人网 | 亚州精品视频 | 国产日韩精品一区二区 | 国产精品亚洲片在线播放 | 人人玩人人添人人澡97 | 在线 国产 亚洲 欧美 | 91精品伦理 | 五月香视频在线观看 | 国产黄免费 | 91精品看片| 国产一二三四在线视频 | 亚洲欧洲久久久 | 97视频免费观看2区 亚洲视屏 | 欧美天天干| 美国av大片 | 国产伦理精品一区二区 | 超碰在线1| 97看片吧| 91网站在线视频 | 成年人免费看的视频 | 久久精久久精 | 成人中文字幕+乱码+中文字幕 | 成人免费视频网站在线观看 | www.91国产 | 日韩av在线免费看 | 亚洲精品成人av在线 | 国产福利精品一区二区 | 免费看国产曰批40分钟 | 成人网页在线免费观看 | 久久久久久久久久久久影院 | 天天操天天操一操 | 波多野结衣理论片 | 亚洲一区二区三区四区精品 | 免费黄色av. | 国产色拍拍拍拍在线精品 | 日韩av一区二区在线影视 | 国产午夜在线 | 99久久www | 超碰在线94| 丁香婷婷色综合亚洲电影 | 国产精品18久久久久久久久久久久 | 色www精品视频在线观看 | 欧美日韩视频一区二区三区 | 日本精品久久久久久 | 91干干干 | 六月久久婷婷 | 99re热精品视频 | 江苏妇搡bbbb搡bbbb | 91成人在线网站 | 五月婷婷视频在线 | 久久久国产日韩 | 九色视频网址 | 婷婷久久网| 日韩精品久久中文字幕 | 91精品电影 | 亚洲精品高清一区二区三区四区 | av大全在线免费观看 | 日韩在线观看视频一区二区三区 | 国产精品久久久久免费 | 国产精品18久久久久久首页狼 | 又爽又黄又刺激的视频 | 久久久免费 | 91高清在线看 | 97在线免费视频观看 | 国产精品12| 97在线免费观看视频 | 中文区中文字幕免费看 | 97成人在线视频 | 亚洲精品三级 | 伊人久操 | 美女黄频在线观看 | 国产999在线观看 | www久久 | www夜夜操 | 国产精品色视频 | 高清不卡免费视频 | 欧美日韩精品影院 | 精品久久久久免费极品大片 | 亚洲国产高清在线 | www.国产高清 | 久久精品女人毛片国产 | 亚洲综合欧美日韩狠狠色 | 91看毛片 | 精品久久久99 | 91综合久久一区二区 | 91九色精品国产 | 超碰人人91 | 日韩大片在线 | 婷婷久操 | 免费91麻豆精品国产自产在线观看 | 五月天久久久久 | 久久久久亚洲精品男人的天堂 | 成人9ⅰ免费影视网站 | 国产精品久久影院 | 亚洲特级毛片 | 日本最新中文字幕 | 色天天综合久久久久综合片 | 天天干天天摸 | 天天干.com | va视频在线 | 亚洲欧美综合 | 久草免费看| 韩国一区二区三区在线观看 | av一级二级 | 天天爽夜夜爽精品视频婷婷 | 激情综合狠狠 | 欧美二区在线播放 | 在线观看av大片 | 日日日天天天 | 国产四虎影院 | 国产成人av电影在线观看 | 九九综合久久 | 亚洲中字幕 | 国产精品久久久网站 | 9在线观看免费高清完整版在线观看明 | a级黄色片视频 | 久久人人爽人人爽 | 右手影院亚洲欧美 | 97超碰人| 4hu视频| 丝袜av一区 | 97在线观 | 久久精品九色 | 国产精品一区二区三区视频免费 | www黄色软件 | 国产成人一区二区啪在线观看 | 日韩在线看片 | 免费观看的av | 91麻豆精品国产午夜天堂 | 久久伊人国产精品 | 成人免费网站在线观看 | 天天干天天干天天干天天干天天干天天干 | 蜜臀av性久久久久av蜜臀妖精 | 五月天久久久久 | 国产亚洲一级高清 | 国产中文字幕在线免费观看 | 亚洲视频99 | 玖玖在线视频观看 | 色综合久久精品 | 99国内精品久久久久久久 | 中文字幕在线看视频 | 在线观看中文字幕一区 | 狠狠干狠狠久久 | 91豆花在线 | 久久影院午夜论 | 日韩高清二区 | 97超碰人| www.888.av| 色综合久久中文字幕综合网 | 91成人天堂久久成人 | 国产精品一区专区欧美日韩 | 在线观看深夜福利 | 五月婷婷激情综合 | www.色婷婷| 一区二区视频电影在线观看 | 亚洲欧美日韩国产 | 亚洲成人资源在线观看 | 日韩在线视频一区 | 亚洲黄色大片 | av片在线看 | 成人黄色电影免费观看 | 国产精品国产三级国产不产一地 | 免费高清国产 | 国产午夜精品一区二区三区在线观看 | 视频在线观看一区 | 香蕉在线视频播放网站 | 97色婷婷| 精品国产福利在线 | 91久久精品一区二区三区 | 中文字幕久久久精品 | 欧美夫妻生活视频 | 在线观看视频99 | 偷拍视频一区 | 日本公妇色中文字幕 | 黄色小说在线免费观看 | 成人免费观看视频网站 | 国产黄av| 欧美成年网站 | 草久久久久久久 | 久久在线| 国产高清在线观看 | 成片免费观看视频 | 国产高清视频在线 | 91av在线精品 | 国产区免费在线 | 色99视频| 国产精久久 | 日韩一区二区三区高清免费看看 | a黄色一级|