NNP STM Generic Remote Module git-main
Loading...
Searching...
No Matches
sdo.c
Go to the documentation of this file.
1
13#include "canfestival.h"
14#include "sysdep.h"
15
16/* Uncomment if your compiler does not support inline functions */
17#define NO_INLINE
18
19#ifdef NO_INLINE
20 #define INLINE
21#else
22 #define INLINE inline
23#endif
24
25/*Internals prototypes*/
26
27INLINE UNS8 _writeNetworkDict (CO_Data* d, UNS8 nodeId, UNS16 index,
28 UNS8 subIndex, UNS32 count, UNS8 dataType, void *data, SDOCallback_t Callback, UNS8 endianize);
29INLINE UNS8 _readNetworkDict (CO_Data* d, UNS8 nodeId, UNS16 index, UNS8 subIndex,
30 UNS8 dataType, SDOCallback_t Callback);
31
32
33/***************************************************************************/
34/* SDO (un)packing macros */
35
38#define getSDOcs(byte) (byte >> 5)
39
42#define getSDOn2(byte) ((byte >> 2) & 3)
43
46#define getSDOn3(byte) ((byte >> 1) & 7)
47
50#define getSDOe(byte) ((byte >> 1) & 1)
51
54#define getSDOs(byte) (byte & 1)
55
58#define getSDOc(byte) (byte & 1)
59
62#define getSDOt(byte) ((byte >> 4) & 1)
63
66#define getSDOindex(byte1, byte2) (((UNS16)byte2 << 8) | ((UNS16)byte1))
67
70#define getSDOsubIndex(byte3) (byte3)
71
80{
81 MSG_ERR(0x1A01, "SDO timeout. SDO response not received.", 0);
82 MSG_WAR(0x2A02, "server node : ", d->transfers[id].nodeId);
83 MSG_WAR(0x2A02, " index : ", d->transfers[id].index);
84 MSG_WAR(0x2A02, " subIndex : ", d->transfers[id].subIndex);
85 /* Reset timer handler */
86 d->transfers[id].timer = TIMER_NONE;
87 /*Set aborted state*/
88 d->transfers[id].state = SDO_ABORTED_INTERNAL;
89 /* Sending a SDO abort */
90 sendSDOabort(d, d->transfers[id].whoami, d->transfers[id].nodeId,
91 d->transfers[id].index, d->transfers[id].subIndex, SDOABT_TIMED_OUT);
92 d->transfers[id].abortCode = SDOABT_TIMED_OUT;
93 /* Call the user function to inform of the problem.*/
94 if(d->transfers[id].Callback)
95 /*If ther is a callback, it is responsible to close SDO transfer (client)*/
96 (*d->transfers[id].Callback)(d,d->transfers[id].nodeId);
97 else if(d->transfers[id].whoami == SDO_SERVER) //JML NOTE: see latest CANFestival rev
98 /*Else, if server, reset the line*/
99
100 resetSDOline(d, (UNS8)id);
101}
102
103#define StopSDO_TIMER(id) \
104MSG_WAR(0x3A05, "StopSDO_TIMER for line : ", line);\
105d->transfers[id].timer = DelAlarm(d->transfers[id].timer);
106
107#define StartSDO_TIMER(id) \
108MSG_WAR(0x3A06, "StartSDO_TIMER for line : ", line);\
109d->transfers[id].timer = SetAlarm(d,id,&SDOTimeoutAlarm,MS_TO_TIMEVAL(SDO_TIMEOUT_MS),0);
110
111#define RestartSDO_TIMER(id) \
112MSG_WAR(0x3A07, "restartSDO_TIMER for line : ", line);\
113if(d->transfers[id].timer != TIMER_NONE) { StopSDO_TIMER(id) StartSDO_TIMER(id) }
114
121{
122 UNS8 j;
123
124 /* transfer structure initialization */
125 for (j = 0 ; j < SDO_MAX_SIMULTANEOUS_TRANSFERTS ; j++)
126 resetSDOline(d, j);
127}
128
137{
138 UNS32 size;
139 UNS32 errorCode;
140 MSG_WAR(0x3A08, "Enter in SDOlineToObjdict ", line);
141 /* if SDO initiated with e=0 and s=0 count is null, offset carry effective size*/
142 if( d->transfers[line].count == 0)
143 d->transfers[line].count = d->transfers[line].offset;
144 size = d->transfers[line].count;
145 errorCode = setODentry(d, d->transfers[line].index, d->transfers[line].subIndex,
146 (void *) d->transfers[line].data, &size, 1);
147 if (errorCode != OD_SUCCESSFUL)
148 return errorCode;
149 MSG_WAR(0x3A08, "exit of SDOlineToObjdict ", line);
150 return 0;
151
152}
153
162{
163 UNS32 size = 0;
164 UNS8 dataType;
165 UNS32 errorCode;
166
167 MSG_WAR(0x3A05, "objdict->line index : ", d->transfers[line].index);
168 MSG_WAR(0x3A06, " subIndex : ", d->transfers[line].subIndex);
169
170 errorCode = getODentry(d, d->transfers[line].index,
171 d->transfers[line].subIndex,
172 (void *)d->transfers[line].data,
173 &size, &dataType, 1);
174
175 if (errorCode != OD_SUCCESSFUL)
176 return errorCode;
177
178 d->transfers[line].count = size;
179 d->transfers[line].offset = 0;
180
181 return 0;
182}
183
191UNS32 objdictToSDOBlockline(CO_Data* d, UNS8 line, UNS8 numberOfIndexes)
192{
193 UNS32 size = 0;
194 UNS32 varSize = 0;
195 UNS8 dataType;
196 UNS32 errorCode;
197 UNS8 tempData[4];
198 UNS8 faultFlag = 0;
199 UNS8 data[SDO_MAX_LENGTH_TRANSFERT];
200
201
202 for (int i = 0; i < numberOfIndexes; i++)
203 {
204 // need to reinitialize
205 dataType = 0;
206 varSize = 0;
207
208 errorCode = getODentry( d, d->transfers[line].index, d->transfers[line].subIndex + i, tempData, \
209 &varSize, &dataType, 1);
210
211 if( errorCode != OD_SUCCESSFUL || faultFlag ) // check for overrun
212 return errorCode;
213
214 switch (dataType)
215 {
216 case 5:
217 data[size] = tempData[0];
218 break;
219
220 case 6:
221 data[size] = tempData[0];
222 size++;
223 data[size] = tempData[1];
224 break;
225
226 case 7:
227 data[size] = tempData[0];
228 size++;
229 data[size] = tempData[1];
230 size++;
231 data[size] = tempData[2];
232 size++;
233 data[size] = tempData[3];
234
235 break;
236
237 default:
238 {
239 faultFlag = 1;
240 }
241
242 } // end of case
243 size++;
244
245
246 } // end of for loop
247
248 d->transfers[line].count = size;
249 d->transfers[line].offset = 0;
250 d->transfers[line].dataType = 0x05; // change to bytes
251
252 memcpy(d->transfers[line].data, data, size);
253
254 return 0;
255}
256
266UNS8 lineToSDO (CO_Data* d, UNS8 line, UNS32 nbBytes, UNS8* data) {
267 UNS8 i;
268 UNS32 offset;
269
270 if ((d->transfers[line].offset + nbBytes) > SDO_MAX_LENGTH_TRANSFERT) {
271 MSG_ERR(0x1A10,"SDO Size of data too large. Exceed SDO_MAX_LENGTH_TRANSFERT", nbBytes);
272 return 0xFF;
273 }
274 if ((d->transfers[line].offset + nbBytes) > d->transfers[line].count) {
275 MSG_ERR(0x1A11,"SDO Size of data too large. Exceed count", nbBytes);
276 return 0xFF;
277 }
278 offset = d->transfers[line].offset;
279 for (i = 0 ; i < nbBytes ; i++)
280 * (data + i) = d->transfers[line].data[offset + i];
281 d->transfers[line].offset = d->transfers[line].offset + nbBytes;
282 return 0;
283}
284
294UNS8 SDOtoLine (CO_Data* d, UNS8 line, UNS32 nbBytes, UNS8* data)
295{
296 UNS8 i;
297 UNS32 offset;
298
299 if ((d->transfers[line].offset + nbBytes) > SDO_MAX_LENGTH_TRANSFERT) {
300 MSG_ERR(0x1A15,"SDO Size of data too large. Exceed SDO_MAX_LENGTH_TRANSFERT", nbBytes);
301 return 0xFF;
302 }
303 offset = d->transfers[line].offset;
304 for (i = 0 ; i < nbBytes ; i++)
305 d->transfers[line].data[offset + i] = * (data + i);
306 d->transfers[line].offset = d->transfers[line].offset + nbBytes;
307 return 0;
308}
309
326UNS8 failedSDO (CO_Data* d, UNS8 nodeId, UNS8 whoami, UNS16 index,
327 UNS8 subIndex, UNS32 abortCode)
328{
329 UNS8 err;
330 UNS8 line;
331 err = getSDOlineOnUse( d, nodeId, whoami, &line );
332 if (!err) /* If a line on use have been found.*/
333 MSG_WAR(0x3A20, "FailedSDO : line found : ", line);
334 if ((! err) && (whoami == SDO_SERVER)) {
335 resetSDOline( d, line );
336 MSG_WAR(0x3A21, "FailedSDO : line released : ", line);
337 }
338 if ((! err) && (whoami == SDO_CLIENT)) {
339 StopSDO_TIMER(line);
340 d->transfers[line].state = SDO_ABORTED_INTERNAL;
341 }
342 MSG_WAR(0x3A22, "Sending SDO abort ", 0);
343 err = sendSDOabort(d, whoami, nodeId, index, subIndex, abortCode);
344 if (err) {
345 MSG_WAR(0x3A23, "Unable to send the SDO abort", 0);
346 return 0xFF;
347 }
348 return 0;
349}
350
357void resetSDOline ( CO_Data* d, UNS8 line )
358{
359 UNS32 i;
360 MSG_WAR(0x3A25, "reset SDO line nb : ", line);
361 initSDOline(d, line, 0, 0, 0, SDO_RESET);
362 for (i = 0 ; i < SDO_MAX_LENGTH_TRANSFERT ; i++)
363 d->transfers[line].data[i] = 0;
364 d->transfers[line].whoami = 0;
365 d->transfers[line].abortCode = 0;
366}
367
379UNS8 initSDOline (CO_Data* d, UNS8 line, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS8 state)
380{
381 MSG_WAR(0x3A25, "init SDO line nb : ", line);
382 if (state == SDO_DOWNLOAD_IN_PROGRESS || state == SDO_UPLOAD_IN_PROGRESS)
383 {
384 StartSDO_TIMER(line)
385 }else
386 {
387 StopSDO_TIMER(line)
388 }
389 d->transfers[line].nodeId = nodeId;
390 d->transfers[line].index = index;
391 d->transfers[line].subIndex = subIndex;
392 d->transfers[line].state = state;
393 d->transfers[line].toggle = 0;
394 d->transfers[line].count = 0;
395 d->transfers[line].offset = 0;
396 d->transfers[line].dataType = 0;
397 d->transfers[line].Callback = NULL;
398 return 0;
399}
400
412UNS8 getSDOfreeLine ( CO_Data* d, UNS8 whoami, UNS8 *line )
413{
414
415 UNS8 i;
416
417 for (i = 0 ; i < SDO_MAX_SIMULTANEOUS_TRANSFERTS ; i++){
418 if ( d->transfers[i].state == SDO_RESET ) {
419 *line = i;
420 d->transfers[i].whoami = whoami;
421 return 0;
422 } /* end if */
423 } /* end for */
424 MSG_ERR(0x1A25, "Too many SDO in progress. Aborted.", i);
425 return 0xFF;
426}
427
428
439UNS8 getSDOlineOnUse (CO_Data* d, UNS8 nodeId, UNS8 whoami, UNS8 *line)
440{
441
442 UNS8 i;
443
444 for (i = 0 ; i < SDO_MAX_SIMULTANEOUS_TRANSFERTS ; i++){
445 if ( (d->transfers[i].state != SDO_RESET) && //JML NOTE: see latest CANFestival rev
446 (d->transfers[i].nodeId == nodeId) &&
447 (d->transfers[i].whoami == whoami) ) {
448 *line = i;
449 return 0;
450 }
451 }
452 return 0xFF;
453}
454
455
456UNS8 closeSDOtransfer (CO_Data* d, UNS8 nodeId, UNS8 whoami)
457{
458 UNS8 err;
459 UNS8 line;
460 err = getSDOlineOnUse(d, nodeId, whoami, &line); //JML NOTE: see latest CANFESTIVAL rev
461 if (err)
462 {
463 MSG_WAR(0x2A30, "No SDO communication to close for node : ", nodeId);
464 return 0xFF;
465 }
466 resetSDOline(d, line);
467 return 0;
468}
469
470
480{
481 /* SDO initiated with e=0 and s=0 have count set to null */
482 if (d->transfers[line].count == 0)
483 * nbBytes = 0;
484 else
485 * nbBytes = d->transfers[line].count - d->transfers[line].offset;
486 return 0;
487}
488
489
490
500{
501 if (nbBytes > SDO_MAX_LENGTH_TRANSFERT) {
502 MSG_ERR(0x1A35,"SDO Size of data too large. Exceed SDO_MAX_LENGTH_TRANSFERT", nbBytes);
503 return 0xFF;
504 }
505 d->transfers[line].count = nbBytes;
506 return 0;
507}
508
517UNS8 sendSDO (CO_Data* d, UNS8 whoami, s_SDO sdo)
518{
519 UNS16 offset;
520 UNS16 lastIndex;
521 UNS8 found = 0;
522 Message m;
523 UNS8 i;
524 UNS32 * pwCobId = NULL;
525 UNS8 * pwNodeId = NULL;
526
527 MSG_WAR(0x3A38, "sendSDO",0);
528 if( (d->nodeState == Hibernate) || (d->nodeState == BootCheckReset ))
529 {
530 MSG_WAR(0x2A39, "unable to send the SDO (not in op or pre-op mode", d->nodeState);
531 return 0xFF;
532 }
533
534 /*get the server->client cobid*/
535 if ( whoami == SDO_SERVER ) {/*case server. only one SDO server*/
536 offset = d->firstIndex->SDO_SVR;
537 if (offset == 0)
538 {
539 MSG_ERR(0x1A42, "SendSDO : No SDO server found", 0);
540 return 0xFF;
541 }
542 pwCobId = (UNS32*) d->objdict[offset].pSubindex[2].pObject;
543 MSG_WAR(0x3A41, "I am server. cobId : ", *pwCobId);
544 }
545 else
546 { /*case client*/
547 /* Get the client->server cobid.*/
548 UNS16 sdoNum = 0;
549 offset = d->firstIndex->SDO_CLT;
550 lastIndex = d->lastIndex->SDO_CLT;
551 if (offset == 0)
552 {
553 MSG_ERR(0x1A42, "SendSDO : No SDO client index found", 0);
554 return 0xFF;
555 }
556 /* find index for communication server node */
557 while (offset <= lastIndex){
558 MSG_WAR(0x3A43,"Reading index : ", 0x1280 + sdoNum);
559 if (d->objdict[offset].bSubCount <= 3)
560 {
561 MSG_ERR(0x1A28, "Subindex 3 not found at index ", 0x1280 + sdoNum);
562 return 0xFF;
563 }
564 pwNodeId = (UNS8*) d->objdict[offset].pSubindex[3].pObject;
565 MSG_WAR(0x3A44, "Found nodeId server = ", *pwNodeId);
566 if(*pwNodeId == sdo.nodeId)
567 {
568 found = 1;
569 break;
570 }
571 offset ++;
572 sdoNum ++;
573 }
574 if (! found)
575 {
576 MSG_WAR (0x2A45, "No SDO client corresponds to the mesage to send to node ", sdo.nodeId);
577 return 0xFF;
578 }
579 /* read the client->server cobid */
580 pwCobId = (UNS32*) d->objdict[offset].pSubindex[1].pObject;
581 }
582 /* message copy for sending */
583 m.cob_id = (UNS16)UNS16_LE(*pwCobId);
584 m.rtr = NOT_A_REQUEST;
585 /* the length of SDO must be 8 */
586 m.len = 8;
587 for (i = 0 ; i < 8 ; i++) {
588 m.data[i] = sdo.body.data[i];
589 }
590 return canSend(d->canHandle, &m);
591}
592
608UNS8 sendSDOabort (CO_Data* d, UNS8 whoami, UNS8 nodeID, UNS16 index, UNS8 subIndex, UNS32 abortCode)
609{
610 s_SDO sdo;
611 UNS8 ret;
612
613 MSG_WAR(0x2A50,"Sending SDO abort ", abortCode);
614 if(whoami == SDO_SERVER)
615 {
616 sdo.nodeId = *d->bDeviceNodeId;
617 }
618 else
619 {
620 sdo.nodeId = nodeID;
621 }
622 sdo.body.data[0] = 0x80;
623 /* Index */
624 sdo.body.data[1] = index & 0xFF; /* LSB */
625 sdo.body.data[2] = (index >> 8) & 0xFF; /* MSB */
626 /* Subindex */
627 sdo.body.data[3] = subIndex;
628 /* Data */
629 sdo.body.data[4] = (UNS8)(abortCode & 0xFF);
630 sdo.body.data[5] = (UNS8)((abortCode >> 8) & 0xFF);
631 sdo.body.data[6] = (UNS8)((abortCode >> 16) & 0xFF);
632 sdo.body.data[7] = (UNS8)((abortCode >> 24) & 0xFF);
633 ret = sendSDO(d, whoami, sdo);
634
635 return ret;
636}
637
650{
651 UNS8 err;
652 UNS8 line = 0;
653 UNS32 nbBytes; /* received or to be transmited. */
654 UNS8 nodeId = 0; /* The node from which the SDO is received */
655 UNS8 *pNodeId = NULL;
656 UNS8 whoami = SDO_UNKNOWN; /* SDO_SERVER or SDO_CLIENT.*/
657 UNS32 errorCode; /* while reading or writing in the local object dictionary.*/
658 s_SDO sdo; /* SDO to transmit */
659 UNS16 index;
660 UNS8 subIndex;
661 UNS8 numberOfIndexes;
662 UNS32 abortCode;
663 UNS32 i;
664 UNS8 j;
665 UNS32 *pCobId = NULL;
666 UNS16 offset;
667 UNS16 lastIndex;
668
669
670 MSG_WAR(0x3A60, "processSDO ", 0);
671 whoami = SDO_UNKNOWN;
672 /* Looking for the cobId in the object dictionary. */
673 /* is this SDO for me? check server at 1200 */
674 offset = d->firstIndex->SDO_SVR;
675 lastIndex = d->lastIndex->SDO_SVR;
676 j = 0;
677 if(offset) while (offset <= lastIndex) {
678 if (d->objdict[offset].bSubCount <= 1) {
679 MSG_ERR(0x1A61, "Subindex 1 not found at index ", 0x1200 + j);
680 return 0xFF;
681 }
682 pCobId = (UNS32*) d->objdict[offset].pSubindex[1].pObject;
683 if ( *pCobId == UNS16_LE(m->cob_id) ) {
684 whoami = SDO_SERVER;
685 MSG_WAR(0x3A62, "proceedSDO. I am server. index : ", 0x1200 + j);
686 /* In case of server, the node id of the client may be unknown. So we put the index minus offset */
687 /* 0x1200 where the cobid received is defined. */
688 nodeId = j;
689 break;
690 }
691 j++;
692 offset++;
693 } /* end while */
694 if (whoami == SDO_UNKNOWN) {
695 /* Am-I client ? */
696 offset = d->firstIndex->SDO_CLT;
697 lastIndex = d->lastIndex->SDO_CLT;
698 j = 0;
699 if(offset) while (offset <= lastIndex) {
700 if (d->objdict[offset].bSubCount <= 3) {
701 MSG_ERR(0x1A63, "Subindex 3 not found at index ", 0x1280 + j);
702 return 0xFF;
703 }
704 /* a) Looking for the cobid received. */
705 pCobId = (UNS32*) d->objdict[offset].pSubindex[2].pObject;
706 if (*pCobId == UNS16_LE(m->cob_id) ) {
707 /* b) cobid found, so reading the node id of the server. */
708 pNodeId = (UNS8*) d->objdict[offset].pSubindex[3].pObject;
709 whoami = SDO_CLIENT;
710 nodeId = *pNodeId;
711 MSG_WAR(0x3A64, "proceedSDO. I am server. index : ", 0x1280 + j);
712 MSG_WAR(0x3A65, " Server nodeId : ", nodeId);
713 break;
714 }
715 j++;
716 offset++;
717 } /* end while */
718 }
719 if (whoami == SDO_UNKNOWN) {
720 return 0xFF;/* This SDO was not for us ! */
721 }
722
723 /* Test if the size of the SDO is ok */
724 if ( (*m).len != 8) {
725 MSG_ERR(0x1A67, "Error size SDO. CobId : ", UNS16_LE(m->cob_id));
726 failedSDO(d, nodeId, whoami, 0, 0, SDOABT_GENERAL_ERROR);
727 return 0xFF;
728 }
729
730 if (whoami == SDO_CLIENT) {
731 MSG_WAR(0x3A68, "I am CLIENT. Received SDO from nodeId : ", nodeId);
732 }
733 else {
734 MSG_WAR(0x3A69, "I am SERVER. Received SDO cobId : ", UNS16_LE(m->cob_id));
735 }
736
737 /* Testing the command specifier */
738 /* Allowed : cs = 0, 1, 2, 3, 4. (= all except those for block tranfert). */
739 /* cs = other : Not allowed -> abort. */
740 switch (getSDOcs(m->data[0])) {
741
742 case 0:
743 /* I am SERVER */
744 if (whoami == SDO_SERVER)
745 {
746 /* Receiving a download segment data. */
747 /* A SDO transfert should have been yet initiated. */
748 err = getSDOlineOnUse( d, nodeId, whoami, &line );
749 if (!err)
750 err = d->transfers[line].state != SDO_DOWNLOAD_IN_PROGRESS;
751 if (err)
752 {
753 MSG_ERR(0x1A70, "SDO error : Received download segment for unstarted trans. index 0x1200 + ",
754 nodeId);
755 failedSDO(d, nodeId, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);
756 return 0xFF;
757 }
758 /* Reset the wathdog */
759 RestartSDO_TIMER(line)
760 MSG_WAR(0x3A71, "Received SDO download segment defined at index 0x1200 + ", nodeId);
761 index = d->transfers[line].index;
762 subIndex = d->transfers[line].subIndex;
763 /* Toggle test. */
764 if (d->transfers[line].toggle != getSDOt(m->data[0]))
765 {
766 MSG_ERR(0x1A72, "SDO error : Toggle error : ", getSDOt(m->data[0]));
767 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_TOGGLE_NOT_ALTERNED);
768 return 0xFF;
769 }
770 /* Nb of data to be downloaded */
771 nbBytes = 7 - getSDOn3(m->data[0]);
772 /* Store the data in the transfert structure. */
773 err = SDOtoLine(d, line, nbBytes, (*m).data + 1);
774 if (err)
775 {
776 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
777 return 0xFF;
778 }
779 /* Sending the SDO response, CS = 1 */
780 sdo.nodeId = *d->bDeviceNodeId; /* The node id of the server, (here it is the sender). */
781 sdo.body.data[0] = (1 << 5) | (d->transfers[line].toggle << 4);
782 for (i = 1 ; i < 8 ; i++)
783 sdo.body.data[i] = 0;
784 MSG_WAR(0x3A73, "SDO. Send response to download request defined at index 0x1200 + ", nodeId);
785 sendSDO(d, whoami, sdo);
786 /* Inverting the toggle for the next segment. */
787 d->transfers[line].toggle = ! d->transfers[line].toggle & 1;
788 /* If it was the last segment, */
789 if (getSDOc(m->data[0])) {
790 /* Transfering line data to object dictionary. */
791 /* The code does not use the "d" of initiate frame. So it is safe if e=s=0 */
792 errorCode = SDOlineToObjdict(d, line);
793 if (errorCode) {
794 MSG_ERR(0x1A54, "SDO error : Unable to copy the data in the object dictionary", 0);
795 failedSDO(d, nodeId, whoami, index, subIndex, errorCode);
796 return 0xFF;
797 }
798 /* Release of the line */
799 resetSDOline(d, line);
800 MSG_WAR(0x3A74, "SDO. End of download defined at index 0x1200 + ", nodeId);
801 }
802 } /* end if SERVER */
803 else
804 { /* if CLIENT */
805 /* I am CLIENT */
806 /* It is a request for a previous upload segment. We should find a line opened for this.*/
807 err = getSDOlineOnUse( d, nodeId, whoami, &line);
808 if (!err)
809 err = d->transfers[line].state != SDO_UPLOAD_IN_PROGRESS;
810 if (err) {
811 MSG_ERR(0x1A75, "SDO error : Received segment response for unknown trans. from nodeId", nodeId);
812 failedSDO(d, nodeId, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);
813 return 0xFF;
814 }
815 /* Reset the wathdog */
816 RestartSDO_TIMER(line)
817 index = d->transfers[line].index;
818 subIndex = d->transfers[line].subIndex;
819 /* test of the toggle; */
820 if (d->transfers[line].toggle != getSDOt(m->data[0])) {
821 MSG_ERR(0x1A76, "SDO error : Received segment response Toggle error. from nodeId", nodeId);
822 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_TOGGLE_NOT_ALTERNED);
823 return 0xFF;
824 }
825 /* nb of data to be uploaded */
826 nbBytes = 7 - getSDOn3(m->data[0]);
827 /* Storing the data in the line structure. */
828 err = SDOtoLine(d, line, nbBytes, (*m).data + 1);
829 if (err) {
830 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
831 return 0xFF;
832 }
833 /* Inverting the toggle for the next segment. */
834 d->transfers[line].toggle = ! d->transfers[line].toggle & 1;
835 /* If it was the last segment,*/
836 if ( getSDOc(m->data[0])) {
837 /* Put in state finished */
838 /* The code is safe for the case e=s=0 in initiate frame. */
839 StopSDO_TIMER(line)
840 d->transfers[line].state = SDO_FINISHED;
841 if(d->transfers[line].Callback) (*d->transfers[line].Callback)(d,nodeId);
842
843 MSG_WAR(0x3A77, "SDO. End of upload from node : ", nodeId);
844 }
845 else
846 { /* more segments to receive */
847 /* Sending the request for the next segment. */
848 sdo.nodeId = nodeId;
849 sdo.body.data[0] = (3 << 5) | (d->transfers[line].toggle << 4);
850 for (i = 1 ; i < 8 ; i++)
851 sdo.body.data[i] = 0;
852 sendSDO(d, whoami, sdo);
853 MSG_WAR(0x3A78, "SDO send upload segment request to nodeId", nodeId);
854 }
855 } /* End if CLIENT */
856 break;
857
858 case 1:
859 /* I am SERVER */
860 /* Receive of an initiate download */
861 if (whoami == SDO_SERVER) {
862 index = getSDOindex(m->data[1],m->data[2]);
863 subIndex = getSDOsubIndex(m->data[3]);
864 MSG_WAR(0x3A79, "Received SDO Initiate Download (to store data) defined at index 0x1200 + ",
865 nodeId);
866 MSG_WAR(0x3A80, "Writing at index : ", index);
867 MSG_WAR(0x3A80, "Writing at subIndex : ", subIndex);
868
869 /* Search if a SDO transfert have been yet initiated */
870 err = getSDOlineOnUse( d, nodeId, whoami, &line );
871 if (! err) {
872 MSG_ERR(0x1A81, "SDO error : Transmission yet started.", 0);
873 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_LOCAL_CTRL_ERROR);
874 return 0xFF;
875 }
876 /* No line on use. Great ! */
877 /* Try to open a new line. */
878 err = getSDOfreeLine( d, whoami, &line );
879 if (err) {
880 MSG_ERR(0x1A82, "SDO error : No line free, too many SDO in progress. Aborted.", 0);
881 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_LOCAL_CTRL_ERROR);
882 return 0xFF;
883 }
884 initSDOline(d, line, nodeId, index, subIndex, SDO_DOWNLOAD_IN_PROGRESS);
885
886 if (getSDOe(m->data[0])) { /* If SDO expedited */
887 /* nb of data to be downloaded */
888 nbBytes = 4 - getSDOn2(m->data[0]);
889 /* Storing the data in the line structure. */
890 d->transfers[line].count = nbBytes;
891 err = SDOtoLine(d, line, nbBytes, (*m).data + 4);
892
893 if (err) {
894 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
895 return 0xFF;
896 }
897
898 /* SDO expedited -> transfert finished. Data can be stored in the dictionary. */
899 /*The line will be reseted when it is downloading in the dictionary. */
900 MSG_WAR(0x3A83, "SDO Initiate Download is an expedited transfert. Finished.: ", nodeId);
901 /* Transfering line data to object dictionary. */
902 errorCode = SDOlineToObjdict(d, line);
903 if (errorCode) {
904 MSG_ERR(0x1A84, "SDO error : Unable to copy the data in the object dictionary", 0);
905 failedSDO(d, nodeId, whoami, index, subIndex, errorCode);
906 return 0xFF;
907 }
908 /* Release of the line. */
909 resetSDOline(d, line);
910 }
911 else
912 {/* So, if it is not an expedited transfer */
913 if (getSDOs(m->data[0])) {
914 nbBytes = (m->data[4]) + ((UNS32)(m->data[5])<<8) + ((UNS32)(m->data[6])<<16) + ((UNS32)(m->data[7])<<24);
915 err = setSDOlineRestBytes(d, nodeId, nbBytes);
916 if (err) {
917 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
918 return 0xFF;
919 }
920 }
921 }
922 /*Sending a SDO, cs=3*/
923 sdo.nodeId = *d->bDeviceNodeId; /* The node id of the server, (here it is the sender).*/
924 sdo.body.data[0] = 3 << 5;
925 sdo.body.data[1] = index & 0xFF; /* LSB */
926 sdo.body.data[2] = (index >> 8) & 0xFF; /* MSB */
927 sdo.body.data[3] = subIndex;
928 for (i = 4 ; i < 8 ; i++)
929 sdo.body.data[i] = 0;
930 sendSDO(d, whoami, sdo);
931 } /* end if I am SERVER */
932 else
933 {
934 /* I am CLIENT */
935 /* It is a response for a previous download segment. We should find a line opened for this. */
936 err = getSDOlineOnUse( d, nodeId, whoami, &line);
937 if (!err)
938 err = d->transfers[line].state != SDO_DOWNLOAD_IN_PROGRESS;
939 if (err) {
940 MSG_ERR(0x1A85, "SDO error : Received segment response for unknown trans. from nodeId", nodeId);
941 failedSDO(d, nodeId, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);
942 return 0xFF;
943 }
944 /* Reset the wathdog */
945 RestartSDO_TIMER(line)
946 index = d->transfers[line].index;
947 subIndex = d->transfers[line].subIndex;
948 /* test of the toggle; */
949 if (d->transfers[line].toggle != getSDOt(m->data[0])) {
950 MSG_ERR(0x1A86, "SDO error : Received segment response Toggle error. from nodeId", nodeId);
951 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_TOGGLE_NOT_ALTERNED);
952 return 0xFF;
953 }
954
955 /* End transmission or downloading next segment. We need to know if it will be the last one. */
956 getSDOlineRestBytes(d, line, &nbBytes);
957 if (nbBytes == 0) {
958 MSG_WAR(0x3A87, "SDO End download. segment response received. OK. from nodeId", nodeId);
959 StopSDO_TIMER(line)
960 d->transfers[line].state = SDO_FINISHED;
961 if(d->transfers[line].Callback) (*d->transfers[line].Callback)(d,nodeId);
962 return 0x00;
963 }
964 /* At least one transfer to send. */
965 if (nbBytes > 7) {
966 /* several segments to download.*/
967 /* code to send the next segment. (cs = 0; c = 0) */
968 d->transfers[line].toggle = ! d->transfers[line].toggle & 1;
969 sdo.nodeId = nodeId; /* The server node Id; */
970 sdo.body.data[0] = (d->transfers[line].toggle << 4);
971 err = lineToSDO(d, line, 7, sdo.body.data + 1);
972 if (err) {
973 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
974 return 0xFF;
975 }
976 }
977 else
978 {
979 /* Last segment. */
980 /* code to send the last segment. (cs = 0; c = 1)*/
981 d->transfers[line].toggle = ! d->transfers[line].toggle & 1;
982 sdo.nodeId = nodeId; /* The server node Id; */
983 sdo.body.data[0] = (UNS8)((d->transfers[line].toggle << 4) | ((7 - nbBytes) << 1) | 1);
984 err = lineToSDO(d, line, nbBytes, sdo.body.data + 1);
985 if (err) {
986 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
987 return 0xFF;
988 }
989 for (i = nbBytes + 1 ; i < 8 ; i++)
990 sdo.body.data[i] = 0;
991 }
992 MSG_WAR(0x3A88, "SDO sending download segment to nodeId", nodeId);
993 sendSDO(d, whoami, sdo);
994 } /* end if I am a CLIENT */
995 break;
996
997 case 2:
998 /* I am SERVER */
999 /* Receive of an initiate upload.*/
1000 if (whoami == SDO_SERVER)
1001 {
1002 index = getSDOindex(m->data[1],m->data[2]);
1003 subIndex = getSDOsubIndex(m->data[3]);
1004 MSG_WAR(0x3A89, "Received SDO Initiate upload (to send data) defined at index 0x1200 + ",
1005 nodeId);
1006 MSG_WAR(0x3A90, "Reading at index : ", index);
1007 MSG_WAR(0x3A91, "Reading at subIndex : ", subIndex);
1008 /* Search if a SDO transfer have been yet initiated*/
1009 err = getSDOlineOnUse( d, nodeId, whoami, &line );
1010 if (! err)
1011 {
1012 MSG_ERR(0x1A92, "SDO error : Transmission yet started at line : ", line);
1013 MSG_WAR(0x3A93, "nodeId = ", nodeId);
1014 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_LOCAL_CTRL_ERROR);
1015 return 0xFF;
1016 }
1017 /* No line on use. Great !*/
1018 /* Try to open a new line.*/
1019 err = getSDOfreeLine( d, whoami, &line );
1020 if (err)
1021 {
1022 MSG_ERR(0x1A71, "SDO error : No line free, too many SDO in progress. Aborted.", 0);
1023 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_LOCAL_CTRL_ERROR);
1024 return 0xFF;
1025 }
1026 initSDOline(d, line, nodeId, index, subIndex, SDO_UPLOAD_IN_PROGRESS);
1027 /* Transfer data from dictionary to the line structure. */
1028 errorCode = objdictToSDOline(d, line);
1029
1030 if (errorCode) {
1031 MSG_ERR(0x1A94, "SDO error : Unable to copy the data from object dictionary. Err code : ",
1032 errorCode);
1033 failedSDO(d, nodeId, whoami, index, subIndex, errorCode);
1034 return 0xFF;
1035 }
1036 /* Preparing the response.*/
1037 getSDOlineRestBytes(d, line, &nbBytes); /* Nb bytes to transfer ? */
1038 sdo.nodeId = nodeId; /* The server node Id; */
1039 if (nbBytes > 4) {
1040 /* normal transfert. (segmented). */
1041 /* code to send the initiate upload response. (cs = 2) */
1042 sdo.body.data[0] = (2 << 5) | 1;
1043 sdo.body.data[1] = index & 0xFF; /* LSB */
1044 sdo.body.data[2] = (index >> 8) & 0xFF; /* MSB */
1045 sdo.body.data[3] = subIndex;
1046 sdo.body.data[4] = (UNS8)nbBytes; /* Limitation of canfestival2 : Max tranfert is 256 bytes.*/
1047 /* It takes too much memory to upgrate to 2^32 because the size of data is also coded */
1048 /* in the object dictionary, at every index and subindex. */
1049 for (i = 5 ; i < 8 ; i++)
1050 sdo.body.data[i] = 0;
1051 MSG_WAR(0x3A95, "SDO. Sending normal upload initiate response defined at index 0x1200 + ", nodeId);
1052 sendSDO(d, whoami, sdo);
1053 }
1054 else
1055 {
1056 /* Expedited upload. (cs = 2 ; e = 1) */
1057 sdo.body.data[0] = (UNS8)((2 << 5) | ((4 - nbBytes) << 2) | 3);
1058 sdo.body.data[1] = index & 0xFF; /* LSB */
1059 sdo.body.data[2] = (index >> 8) & 0xFF; /* MSB */
1060 sdo.body.data[3] = subIndex;
1061 err = lineToSDO(d, line, nbBytes, sdo.body.data + 4);
1062 if (err) {
1063 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
1064 return 0xFF;
1065 }
1066 for (i = 4 + nbBytes ; i < 8 ; i++)
1067 sdo.body.data[i] = 0;
1068 MSG_WAR(0x3A96, "SDO. Sending expedited upload initiate response defined at index 0x1200 + ",
1069 nodeId);
1070 sendSDO(d, whoami, sdo);
1071 /* Release the line.*/
1072 resetSDOline(d, line);
1073 }
1074 } /* end if I am SERVER*/
1075 else
1076 {
1077 /* I am CLIENT */
1078 /* It is the response for the previous initiate upload request.*/
1079 /* We should find a line opened for this. */
1080 err = getSDOlineOnUse( d, nodeId, whoami, &line);
1081 if (!err)
1082 err = d->transfers[line].state != SDO_UPLOAD_IN_PROGRESS;
1083 if (err) {
1084 MSG_ERR(0x1A97, "SDO error : Received response for unknown upload request from nodeId", nodeId);
1085 failedSDO(d, nodeId, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);
1086 return 0xFF;
1087 }
1088 /* Reset the wathdog */
1089 RestartSDO_TIMER(line)
1090 index = d->transfers[line].index;
1091 subIndex = d->transfers[line].subIndex;
1092
1093 if (getSDOe(m->data[0])) { /* If SDO expedited */
1094 /* nb of data to be uploaded */
1095 nbBytes = 4 - getSDOn2(m->data[0]);
1096 /* Storing the data in the line structure. */
1097 err = SDOtoLine(d, line, nbBytes, (*m).data + 4);
1098 if (err) {
1099 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
1100 return 0xFF;
1101 }
1102 /* SDO expedited -> transfert finished. data are available via getReadResultNetworkDict(). */
1103 MSG_WAR(0x3A98, "SDO expedited upload finished. Response received from node : ", nodeId);
1104 StopSDO_TIMER(line)
1105 d->transfers[line].count = nbBytes;
1106 d->transfers[line].state = SDO_FINISHED;
1107 if(d->transfers[line].Callback) (*d->transfers[line].Callback)(d,nodeId);
1108 return 0;
1109 }
1110 else
1111 { /* So, if it is not an expedited transfert */
1112 /* Storing the nb of data to receive. */
1113 if (getSDOs(m->data[0])) {
1114 nbBytes = m->data[4] + ((UNS32)(m->data[5])<<8) + ((UNS32)(m->data[6])<<16) + ((UNS32)(m->data[7])<<24);
1115 err = setSDOlineRestBytes(d, line, nbBytes);
1116 if (err) {
1117 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
1118 return 0xFF;
1119 }
1120 }
1121 /* Requesting next segment. (cs = 3) */
1122 sdo.nodeId = nodeId;
1123 sdo.body.data[0] = 3 << 5;
1124 for (i = 1 ; i < 8 ; i++)
1125 sdo.body.data[i] = 0;
1126 MSG_WAR(0x3A99, "SDO. Sending upload segment request to node : ", nodeId);
1127 sendSDO(d, whoami, sdo);
1128 }
1129 } /* End if CLIENT */
1130 break;
1131
1132 case 3:
1133 /* I am SERVER */
1134 if (whoami == SDO_SERVER) {
1135 /* Receiving a upload segment. */
1136 /* A SDO transfert should have been yet initiated. */
1137 err = getSDOlineOnUse( d, nodeId, whoami, &line );
1138 if (!err)
1139 err = d->transfers[line].state != SDO_UPLOAD_IN_PROGRESS;
1140 if (err) {
1141 MSG_ERR(0x1AA0, "SDO error : Received upload segment for unstarted trans. index 0x1200 + ",
1142 nodeId);
1143 failedSDO(d, nodeId, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);
1144 return 0xFF;
1145 }
1146 /* Reset the wathdog */
1147 RestartSDO_TIMER(line)
1148 MSG_WAR(0x3AA1, "Received SDO upload segment defined at index 0x1200 + ", nodeId);
1149 index = d->transfers[line].index;
1150 subIndex = d->transfers[line].subIndex;
1151 /* Toggle test.*/
1152 if (d->transfers[line].toggle != getSDOt(m->data[0])) {
1153 MSG_ERR(0x1AA2, "SDO error : Toggle error : ", getSDOt(m->data[0]));
1154 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_TOGGLE_NOT_ALTERNED);
1155 return 0xFF;
1156 }
1157 /* Uploading next segment. We need to know if it will be the last one. */
1158 getSDOlineRestBytes(d, line, &nbBytes);
1159 if (nbBytes > 7) {
1160 /* The segment to transfer is not the last one.*/
1161 /* code to send the next segment. (cs = 0; c = 0) */
1162 sdo.nodeId = nodeId; /* The server node Id; */
1163 sdo.body.data[0] = (d->transfers[line].toggle << 4);
1164 err = lineToSDO(d, line, 7, sdo.body.data + 1);
1165 if (err) {
1166 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
1167 return 0xFF;
1168 }
1169 /* Inverting the toggle for the next tranfert. */
1170 d->transfers[line].toggle = ! d->transfers[line].toggle & 1;
1171 MSG_WAR(0x3AA3, "SDO. Sending upload segment defined at index 0x1200 + ", nodeId);
1172 sendSDO(d, whoami, sdo);
1173 }
1174 else
1175 {
1176 /* Last segment. */
1177 /* code to send the last segment. (cs = 0; c = 1) */
1178 sdo.nodeId = nodeId;
1179 sdo.body.data[0] = (UNS8)((d->transfers[line].toggle << 4) | ((7 - nbBytes) << 1) | 1);
1180 err = lineToSDO(d, line, nbBytes, sdo.body.data + 1);
1181 if (err) {
1182 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
1183 return 0xFF;
1184 }
1185 for (i = nbBytes + 1 ; i < 8 ; i++)
1186 sdo.body.data[i] = 0;
1187 MSG_WAR(0x3AA4, "SDO. Sending last upload segment defined at index 0x1200 + ", nodeId);
1188 sendSDO(d, whoami, sdo);
1189 /* Release the line */
1190 resetSDOline(d, line);
1191 }
1192 } /* end if SERVER*/
1193 else
1194 {
1195 /* I am CLIENT */
1196 /* It is the response for the previous initiate download request. */
1197 /* We should find a line opened for this. */
1198 err = getSDOlineOnUse( d, nodeId, whoami, &line);
1199 if (!err)
1200 err = d->transfers[line].state != SDO_DOWNLOAD_IN_PROGRESS;
1201 if (err) {
1202 MSG_ERR(0x1AA5, "SDO error : Received response for unknown download request from nodeId", nodeId);
1203 failedSDO(d, nodeId, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);
1204 return 0xFF;
1205 }
1206 /* Reset the watchdog */
1207 RestartSDO_TIMER(line)
1208 index = d->transfers[line].index;
1209 subIndex = d->transfers[line].subIndex;
1210 /* End transmission or requesting next segment. */
1211 getSDOlineRestBytes(d, line, &nbBytes);
1212 if (nbBytes == 0) {
1213 MSG_WAR(0x3AA6, "SDO End download expedited. Response received. from nodeId", nodeId);
1214 StopSDO_TIMER(line)
1215 d->transfers[line].state = SDO_FINISHED;
1216 if(d->transfers[line].Callback) (*d->transfers[line].Callback)(d,nodeId);
1217 return 0x00;
1218 }
1219 if (nbBytes > 7) {
1220 /* more than one request to send */
1221 /* code to send the next segment. (cs = 0; c = 0) */
1222 sdo.nodeId = nodeId;
1223 sdo.body.data[0] = (d->transfers[line].toggle << 4);
1224 err = lineToSDO(d, line, 7, sdo.body.data + 1);
1225 if (err) {
1226 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
1227 return 0xFF;
1228 }
1229 }
1230 else
1231 {
1232 /* Last segment.*/
1233 /* code to send the last segment. (cs = 0; c = 1) */
1234 sdo.nodeId = nodeId; /* The server node Id; */
1235 sdo.body.data[0] = (UNS8)((d->transfers[line].toggle << 4) | ((7 - nbBytes) << 1) | 1);
1236 err = lineToSDO(d, line, nbBytes, sdo.body.data + 1);
1237 if (err) {
1238 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
1239 return 0xFF;
1240 }
1241 for (i = nbBytes + 1 ; i < 8 ; i++)
1242 sdo.body.data[i] = 0;
1243 }
1244 MSG_WAR(0x3AA7, "SDO sending download segment to nodeId", nodeId);
1245 sendSDO(d, whoami, sdo);
1246
1247 } /* end if I am a CLIENT */
1248 break;
1249
1250 case 4:
1251 abortCode =
1252 (UNS32)m->data[4] |
1253 ((UNS32)m->data[5] << 8) |
1254 ((UNS32)m->data[6] << 16) |
1255 ((UNS32)m->data[7] << 24);
1256 /* Received SDO abort. */
1257 /* Looking for the line concerned. */
1258 if (whoami == SDO_SERVER) {
1259 err = getSDOlineOnUse( d, nodeId, whoami, &line );
1260 if (!err) {
1261 resetSDOline( d, line );
1262 MSG_WAR(0x3AA8, "SD0. Received SDO abort. Line released. Code : ", abortCode);
1263 }
1264 else
1265 MSG_WAR(0x3AA9, "SD0. Received SDO abort. No line found. Code : ", abortCode);
1266 /* Tips : The end user has no way to know that the server node has received an abort SDO. */
1267 /* Its is ok, I think.*/
1268 }
1269 else
1270 { /* If I am CLIENT */
1271 err = getSDOlineOnUse( d, nodeId, whoami, &line );
1272 if (!err) {
1273 /* The line *must* be released by the core program. */
1274 StopSDO_TIMER(line)
1275 d->transfers[line].state = SDO_ABORTED_RCV;
1276 d->transfers[line].abortCode = abortCode;
1277 MSG_WAR(0x3AB0, "SD0. Received SDO abort. Line state ABORTED. Code : ", abortCode);
1278 if(d->transfers[line].Callback) (*d->transfers[line].Callback)(d,nodeId);
1279 resetSDOline( d, line );
1280 }
1281 else
1282 MSG_WAR(0x3AB1, "SD0. Received SDO abort. No line found. Code : ", abortCode);
1283 }
1284 break;
1285
1286 case 5: // block upload
1287 /* I am SERVER */
1288 /* Receive of an initiate upload.*/
1289 if (whoami == SDO_SERVER)
1290 {
1291 index = getSDOindex(m->data[1],m->data[2]);
1292 subIndex = getSDOsubIndex(m->data[3]);
1293 numberOfIndexes = m->data[4];
1294
1295 /* Search if a SDO transfer have been yet initiated*/
1296 err = getSDOlineOnUse( d, nodeId, whoami, &line );
1297 if (! err)
1298 {
1299 MSG_ERR(0x1A92, "SDO error : Transmission yet started at line : ", line);
1300 MSG_WAR(0x3A93, "nodeId = ", nodeId);
1301 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_LOCAL_CTRL_ERROR);
1302 return 0xFF;
1303 }
1304 /* No line on use. Great !*/
1305 /* Try to open a new line.*/
1306 err = getSDOfreeLine( d, whoami, &line );
1307 if (err)
1308 {
1309 MSG_ERR(0x1A71, "SDO error : No line free, too many SDO in progress. Aborted.", 0);
1310 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_LOCAL_CTRL_ERROR);
1311 return 0xFF;
1312 }
1313 initSDOline(d, line, nodeId, index, subIndex, SDO_UPLOAD_IN_PROGRESS);
1314
1315 /* Transfer data from dictionary to the line structure. */
1316 errorCode = objdictToSDOBlockline(d, line, numberOfIndexes);
1317
1318 if (errorCode)
1319 {
1320 MSG_ERR(0x1A94, "SDO error : Unable to copy the data from object dictionary. Err code : ",
1321 errorCode);
1322 failedSDO(d, nodeId, whoami, index, subIndex, errorCode);
1323 return 0xFF;
1324 }
1325
1326 /* Preparing the response.*/
1327 getSDOlineRestBytes(d, line, &nbBytes); /* Nb bytes to transfer ? */
1328
1329 sdo.nodeId = nodeId; /* The server node Id; */
1330 if (nbBytes > 4)
1331 {
1332 /* normal transfert. (segmented). */
1333 /* code to send the initiate upload response. (cs = 2) */
1334 sdo.body.data[0] = (2 << 5) | 1;
1335 sdo.body.data[1] = index & 0xFF; /* LSB */
1336 sdo.body.data[2] = (index >> 8) & 0xFF; /* MSB */
1337 sdo.body.data[3] = subIndex;
1338 sdo.body.data[4] = (UNS8)nbBytes; /* Limitation of canfestival2 : Max tranfert is 256 bytes.*/
1339 /* It takes too much memory to upgrate to 2^32 because the size of data is also coded */
1340 /* in the object dictionary, at every index and subindex. */
1341 for (i = 5 ; i < 8 ; i++)
1342 sdo.body.data[i] = 0;
1343 MSG_WAR(0x3A95, "SDO. Sending normal upload initiate response defined at index 0x1200 + ", nodeId);
1344 sendSDO(d, whoami, sdo);
1345 }
1346 else
1347 {
1348 /* Expedited upload. (cs = 2 ; e = 1) */
1349 sdo.body.data[0] = (UNS8)((2 << 5) | ((4 - nbBytes) << 2) | 3);
1350 sdo.body.data[1] = index & 0xFF; /* LSB */
1351 sdo.body.data[2] = (index >> 8) & 0xFF; /* MSB */
1352 sdo.body.data[3] = subIndex;
1353 err = lineToSDO(d, line, nbBytes, sdo.body.data + 4);
1354 if (err) {
1355 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
1356 return 0xFF;
1357 }
1358 for (i = 4 + nbBytes ; i < 8 ; i++)
1359 sdo.body.data[i] = 0;
1360 MSG_WAR(0x3A96, "SDO. Sending expedited upload initiate response defined at index 0x1200 + ",
1361 nodeId);
1362 sendSDO(d, whoami, sdo);
1363 /* Release the line.*/
1364 resetSDOline(d, line);
1365 }
1366 } /* end if I am SERVER*/
1367 else
1368 {
1369 /* I am CLIENT */
1370 /* It is the response for the previous initiate upload request.*/
1371 /* We should find a line opened for this. */
1372 err = getSDOlineOnUse( d, nodeId, whoami, &line);
1373 if (!err)
1374 err = d->transfers[line].state != SDO_UPLOAD_IN_PROGRESS;
1375 if (err) {
1376 MSG_ERR(0x1A97, "SDO error : Received response for unknown upload request from nodeId", nodeId);
1377 failedSDO(d, nodeId, whoami, 0, 0, SDOABT_LOCAL_CTRL_ERROR);
1378 return 0xFF;
1379 }
1380 /* Reset the wathdog */
1381 RestartSDO_TIMER(line)
1382 index = d->transfers[line].index;
1383 subIndex = d->transfers[line].subIndex;
1384
1385 if (getSDOe(m->data[0])) { /* If SDO expedited */
1386 /* nb of data to be uploaded */
1387 nbBytes = 4 - getSDOn2(m->data[0]);
1388 /* Storing the data in the line structure. */
1389 err = SDOtoLine(d, line, nbBytes, (*m).data + 4);
1390 if (err) {
1391 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
1392 return 0xFF;
1393 }
1394 /* SDO expedited -> transfert finished. data are available via getReadResultNetworkDict(). */
1395 MSG_WAR(0x3A98, "SDO expedited upload finished. Response received from node : ", nodeId);
1396 StopSDO_TIMER(line)
1397 d->transfers[line].count = nbBytes;
1398 d->transfers[line].state = SDO_FINISHED;
1399 if(d->transfers[line].Callback) (*d->transfers[line].Callback)(d,nodeId);
1400 return 0;
1401 }
1402 else
1403 { /* So, if it is not an expedited transfer */
1404 /* Storing the nb of data to receive. */
1405 if (getSDOs(m->data[0])) {
1406 nbBytes = m->data[4] + ((UNS32)(m->data[5])<<8) + ((UNS32)(m->data[6])<<16) + ((UNS32)(m->data[7])<<24);
1407 err = setSDOlineRestBytes(d, line, nbBytes);
1408 if (err) {
1409 failedSDO(d, nodeId, whoami, index, subIndex, SDOABT_GENERAL_ERROR);
1410 return 0xFF;
1411 }
1412 }
1413 /* Requesting next segment. (cs = 3) */
1414 sdo.nodeId = nodeId;
1415 sdo.body.data[0] = 3 << 5;
1416 for (i = 1 ; i < 8 ; i++)
1417 sdo.body.data[i] = 0;
1418 MSG_WAR(0x3A99, "SDO. Sending upload segment request to node : ", nodeId);
1419 sendSDO(d, whoami, sdo);
1420 }
1421 } /* End if CLIENT */
1422 break;
1423
1424 default:
1425 /* Error : Unknown cs */
1426 MSG_ERR(0x1AB2, "SDO. Received unknown command specifier : ", getSDOcs(m->data[0]));
1427 resetSDOline( d, line );
1428 return 0xFF;
1429
1430 } /* End switch */
1431 return 0;
1432}
1433
1434
1454INLINE UNS8 _writeNetworkDict (CO_Data* d, UNS8 nodeId, UNS16 index,
1455 UNS8 subIndex, UNS32 count, UNS8 dataType, void *data, SDOCallback_t Callback, UNS8 endianize)
1456{
1457 UNS8 err;
1458 UNS8 SDOfound = 0;
1459 UNS8 line;
1460 s_SDO sdo; /* SDO to transmit */
1461 UNS8 i;
1462 UNS32 j;
1463 UNS16 lastIndex;
1464 UNS16 offset;
1465 UNS8 *pNodeIdServer;
1466 UNS8 nodeIdServer;
1467
1468 MSG_WAR(0x3AC0, "Send SDO to write in the dictionary of node : ", nodeId);
1469 MSG_WAR(0x3AC1, " At index : ", index);
1470 MSG_WAR(0x3AC2, " subIndex : ", subIndex);
1471 MSG_WAR(0x3AC3, " nb bytes : ", count);
1472
1473 /* check to make sure node is online */
1474 if ( d->NMTable[nodeId] == Unknown_state )
1475 {
1476 return 0xFF;
1477 }
1478 /* Verify that there is no SDO communication yet. */
1479 err = getSDOlineOnUse(d, nodeId, SDO_CLIENT, &line);
1480 if (!err) {
1481 MSG_ERR(0x1AC4, "SDO error : Communication yet established. with node : ", nodeId);
1482 return 0xFF;
1483 }
1484 /* Taking the line ... */
1485 err = getSDOfreeLine( d, SDO_CLIENT, &line );
1486 if (err) {
1487 MSG_ERR(0x1AC5, "SDO error : No line free, too many SDO in progress. Aborted for node : ", nodeId);
1488 return (0xFF);
1489 }
1490 /* Check which SDO to use to communicate with the node */
1491 offset = d->firstIndex->SDO_CLT;
1492 lastIndex = d->lastIndex->SDO_CLT;
1493 if (offset == 0) {
1494 MSG_ERR(0x1AC6, "writeNetworkDict : No SDO client index found", 0);
1495 return 0xFF;
1496 }
1497 i = 0;
1498 while (offset <= lastIndex) {
1499 if (d->objdict[offset].bSubCount <= 3) {
1500 MSG_ERR(0x1AC8, "Subindex 3 not found at index ", 0x1280 + i);
1501 return 0xFF;
1502 }
1503 /* looking for the nodeId server */
1504 pNodeIdServer = (UNS8*) d->objdict[offset].pSubindex[3].pObject;
1505 nodeIdServer = *pNodeIdServer;
1506 MSG_WAR(0x1AD2, "index : ", 0x1280 + i);
1507 MSG_WAR(0x1AD3, "nodeIdServer : ", nodeIdServer);
1508
1509 if(nodeIdServer == nodeId) {
1510 SDOfound = 1;
1511 break;
1512 }
1513 offset++;
1514 i++;
1515 } /* end while */
1516 if (!SDOfound) {
1517 MSG_ERR(0x1AC9, "SDO. Error. No client found to communicate with node : ", nodeId);
1518 return 0xFE;
1519 }
1520 MSG_WAR(0x3AD0," SDO client defined at index : ", 0x1280 + i);
1521 initSDOline(d, line, nodeId, index, subIndex, SDO_DOWNLOAD_IN_PROGRESS);
1522 d->transfers[line].count = count;
1523 d->transfers[line].dataType = dataType;
1524
1525 /* Copy data to transfers structure. */
1526 for (j = 0 ; j < count ; j++) {
1527# ifdef CANOPEN_BIG_ENDIAN
1528 if (dataType == 0 && endianize)
1529 d->transfers[line].data[count - 1 - j] = ((char *)data)[j];
1530 else /* String of bytes. */
1531 d->transfers[line].data[j] = ((char *)data)[j];
1532# else
1533 d->transfers[line].data[j] = ((char *)data)[j];
1534# endif
1535 }
1536 /* Send the SDO to the server. Initiate download, cs=1. */
1537 sdo.nodeId = nodeId;
1538 if (count <= 4) { /* Expedited transfert */
1539 sdo.body.data[0] = (UNS8)((1 << 5) | ((4 - count) << 2) | 3);
1540 for (i = 4 ; i < 8 ; i++)
1541 sdo.body.data[i] = d->transfers[line].data[i - 4];
1542 d->transfers[line].offset = count;
1543 }
1544 else {
1545 sdo.body.data[0] = (1 << 5) | 1;
1546 for (i = 0 ; i < 4 ; i++)
1547 sdo.body.data[i+4] = (UNS8)((count << (i<<3))); /* i*8 */
1548 }
1549 sdo.body.data[1] = index & 0xFF; /* LSB */
1550 sdo.body.data[2] = (index >> 8) & 0xFF; /* MSB */
1551 sdo.body.data[3] = subIndex;
1552
1553 d->transfers[line].Callback = Callback;
1554
1555 err = sendSDO(d, SDO_CLIENT, sdo);
1556 if (err) {
1557 MSG_ERR(0x1AD1, "SDO. Error while sending SDO to node : ", nodeId);
1558 /* release the line */
1559 resetSDOline(d, line);
1560 return 0xFF;
1561 }
1562
1563
1564 return 0;
1565}
1566
1584 UNS8 subIndex, UNS32 count, UNS8 dataType, void *data)
1585{
1586 return _writeNetworkDict (d, nodeId, index, subIndex, count, dataType, data, NULL, 1);
1587}
1588
1609 UNS8 subIndex, UNS32 count, UNS8 dataType, void *data, SDOCallback_t Callback)
1610{
1611 return _writeNetworkDict (d, nodeId, index, subIndex, count, dataType, data, Callback, 1);
1612}
1613
1636 UNS8 subIndex, UNS32 count, UNS8 dataType, void *data, SDOCallback_t Callback, UNS8 endianize)
1637{
1638 UNS8 ret;
1639 UNS16 lastIndex;
1640 UNS16 offset;
1641 UNS8 nodeIdServer;
1642
1643
1644 ret = _writeNetworkDict (d, nodeId, index, subIndex, count, dataType, data, Callback, endianize);
1645 if(ret == 0xFE)
1646 {
1647 offset = d->firstIndex->SDO_CLT;
1648 lastIndex = d->lastIndex->SDO_CLT;
1649 if (offset == 0)
1650 {
1651 MSG_ERR(0x1AC6, "writeNetworkDict : No SDO client index found", 0);
1652 return 0xFF;
1653 }
1654
1655 while (offset <= lastIndex)
1656 {
1657 if (d->objdict[offset].bSubCount <= 3)
1658 {
1659 MSG_ERR(0x1AC8, "Subindex 3 not found at index ", 0x1280 + i);
1660 return 0xFF;
1661 }
1662 nodeIdServer = *(UNS8*) d->objdict[offset].pSubindex[3].pObject;
1663 if(nodeIdServer == 0)
1664 {
1665 *(UNS32*)d->objdict[offset].pSubindex[1].pObject = (UNS32)(0x600 + nodeId);
1666 *(UNS32*)d->objdict[offset].pSubindex[2].pObject = (UNS32)(0x580 + nodeId);
1667 *(UNS8*) d->objdict[offset].pSubindex[3].pObject = nodeId;
1668 return _writeNetworkDict (d, nodeId, index, subIndex, count, dataType, data, Callback, 1);
1669 }
1670 offset++;
1671 }
1672 return 0xFF;
1673 }
1674 else if(ret == 0)
1675 {
1676 return 0;
1677 }
1678 else
1679 {
1680 return 0xFF;
1681 }
1682}
1683
1684
1699INLINE UNS8 _readNetworkDict (CO_Data* d, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS8 dataType, SDOCallback_t Callback)
1700{
1701 UNS8 err;
1702 UNS8 SDOfound = 0;
1703 UNS8 i;
1704 UNS8 line;
1705 s_SDO sdo; /* SDO to transmit */
1706 UNS8 *pNodeIdServer;
1707 UNS8 nodeIdServer;
1708 UNS16 offset;
1709 UNS16 lastIndex;
1710 MSG_WAR(0x3AD5, "Send SDO to read in the dictionary of node : ", nodeId);
1711 MSG_WAR(0x3AD6, " At index : ", index);
1712 MSG_WAR(0x3AD7, " subIndex : ", subIndex);
1713
1714 /* check to make sure node is online */
1715 if ( d->NMTable[nodeId] == Unknown_state )
1716 {
1717 return 0xFF;
1718 }
1719
1720 /* Verify that there is no SDO communication yet. */
1721 err = getSDOlineOnUse(d, nodeId, SDO_CLIENT, &line);
1722 if (!err)
1723 {
1724 MSG_ERR(0x1AD8, "SDO error : Communication yet established. with node : ", nodeId);
1725 return 0xFF;
1726 }
1727 /* Taking the line ... */
1728 err = getSDOfreeLine( d, SDO_CLIENT, &line );
1729 if (err) {
1730 MSG_ERR(0x1AD9, "SDO error : No line free, too many SDO in progress. Aborted for node : ", nodeId);
1731 return (0xFF);
1732 }
1733 else
1734 MSG_WAR(0x3AE0, "Transmission on line : ", line);
1735
1736 /* Check which SDO to use to communicate with the node */
1737 offset = d->firstIndex->SDO_CLT;
1738 lastIndex = d->lastIndex->SDO_CLT;
1739 if (offset == 0)
1740 {
1741 MSG_ERR(0x1AE1, "writeNetworkDict : No SDO client index found", 0);
1742 return 0xFF;
1743 }
1744 i = 0;
1745 while (offset <= lastIndex) {
1746 if (d->objdict[offset].bSubCount <= 3)
1747 {
1748 MSG_ERR(0x1AE2, "Subindex 3 not found at index ", 0x1280 + i);
1749 return 0xFF;
1750 }
1751 /* looking for the nodeId server */
1752 pNodeIdServer = (UNS8*) d->objdict[offset].pSubindex[3].pObject;
1753 nodeIdServer = *pNodeIdServer;
1754
1755 if(nodeIdServer == nodeId)
1756 {
1757 SDOfound = 1;
1758 break;
1759 }
1760 offset++;
1761 i++;
1762 } /* end while */
1763 if (!SDOfound)
1764 {
1765 MSG_ERR(0x1AE3, "SDO. Error. No client found to communicate with node : ", nodeId);
1766 return 0xFE;
1767 }
1768 MSG_WAR(0x3AE4," SDO client defined at index : ", 0x1280 + i);
1769 initSDOline(d, line, nodeId, index, subIndex, SDO_UPLOAD_IN_PROGRESS);
1770 getSDOlineOnUse(d, nodeId, SDO_CLIENT, &line);
1771 sdo.nodeId = nodeId;
1772 /* Send the SDO to the server. Initiate upload, cs=2. */
1773 d->transfers[line].dataType = dataType;
1774 sdo.body.data[0] = (2 << 5);
1775 sdo.body.data[1] = index & 0xFF; /* LSB */
1776 sdo.body.data[2] = (index >> 8) & 0xFF; /* MSB */
1777 sdo.body.data[3] = subIndex;
1778 for (i = 4 ; i < 8 ; i++)
1779 sdo.body.data[i] = 0;
1780 d->transfers[line].Callback = Callback;
1781 err = sendSDO(d, SDO_CLIENT, sdo);
1782 if (err)
1783 {
1784 MSG_ERR(0x1AE5, "SDO. Error while sending SDO to node : ", nodeId);
1785 /* release the line */
1786 resetSDOline(d, line);
1787 return 0xFF;
1788 }
1789 return 0;
1790}
1791
1808INLINE UNS8 _readBlockNetworkDict (CO_Data* d, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS8 numberOfIndexes, UNS8 dataType, SDOCallback_t Callback)
1809{
1810 UNS8 err;
1811 UNS8 SDOfound = 0;
1812 UNS8 i;
1813 UNS8 line;
1814 s_SDO sdo; /* SDO to transmit */
1815 UNS8 *pNodeIdServer;
1816 UNS8 nodeIdServer;
1817 UNS16 offset;
1818 UNS16 lastIndex;
1819 MSG_WAR(0x3AD5, "Send SDO to read in the dictionary of node : ", nodeId);
1820 MSG_WAR(0x3AD6, " At index : ", index);
1821 MSG_WAR(0x3AD7, " subIndex : ", subIndex);
1822
1823 /* check to make sure node is online */
1824 if ( d->NMTable[nodeId] == Unknown_state )
1825 {
1826 return 0xFF;
1827 }
1828
1829 /* Verify that there is no SDO communication yet. */
1830 err = getSDOlineOnUse(d, nodeId, SDO_CLIENT, &line);
1831 if (!err)
1832 {
1833 MSG_ERR(0x1AD8, "SDO error : Communication yet established. with node : ", nodeId);
1834 return 0xFF;
1835 }
1836 /* Taking the line ... */
1837 err = getSDOfreeLine( d, SDO_CLIENT, &line );
1838 if (err) {
1839 MSG_ERR(0x1AD9, "SDO error : No line free, too many SDO in progress. Aborted for node : ", nodeId);
1840 return (0xFF);
1841 }
1842 else
1843 MSG_WAR(0x3AE0, "Transmission on line : ", line);
1844
1845 /* Check which SDO to use to communicate with the node */
1846 offset = d->firstIndex->SDO_CLT;
1847 lastIndex = d->lastIndex->SDO_CLT;
1848 if (offset == 0)
1849 {
1850 MSG_ERR(0x1AE1, "writeNetworkDict : No SDO client index found", 0);
1851 return 0xFF;
1852 }
1853 i = 0;
1854 while (offset <= lastIndex) {
1855 if (d->objdict[offset].bSubCount <= 3)
1856 {
1857 MSG_ERR(0x1AE2, "Subindex 3 not found at index ", 0x1280 + i);
1858 return 0xFF;
1859 }
1860 /* looking for the nodeId server */
1861 pNodeIdServer = (UNS8*) d->objdict[offset].pSubindex[3].pObject;
1862 nodeIdServer = *pNodeIdServer;
1863
1864 if(nodeIdServer == nodeId)
1865 {
1866 SDOfound = 1;
1867 break;
1868 }
1869 offset++;
1870 i++;
1871 } /* end while */
1872 if (!SDOfound)
1873 {
1874 MSG_ERR(0x1AE3, "SDO. Error. No client found to communicate with node : ", nodeId);
1875 return 0xFE;
1876 }
1877 MSG_WAR(0x3AE4," SDO client defined at index : ", 0x1280 + i);
1878 initSDOline(d, line, nodeId, index, subIndex, SDO_UPLOAD_IN_PROGRESS);
1879 getSDOlineOnUse(d, nodeId, SDO_CLIENT, &line);
1880 sdo.nodeId = nodeId;
1881 /* Send the SDO to the server. Initiate upload, cs=2. */
1882 d->transfers[line].dataType = dataType;
1883 sdo.body.data[0] = (5 << 5);
1884 sdo.body.data[1] = index & 0xFF; /* LSB */
1885 sdo.body.data[2] = (index >> 8) & 0xFF; /* MSB */
1886 sdo.body.data[3] = subIndex;
1887 sdo.body.data[4] = numberOfIndexes;
1888 for (i = 5 ; i < 8 ; i++)
1889 sdo.body.data[i] = 0;
1890 d->transfers[line].Callback = Callback;
1891 err = sendSDO(d, SDO_CLIENT, sdo);
1892 if (err)
1893 {
1894 MSG_ERR(0x1AE5, "SDO. Error while sending SDO to node : ", nodeId);
1895 /* release the line */
1896 resetSDOline(d, line);
1897 return 0xFF;
1898 }
1899 return 0;
1900}
1901
1917UNS8 readBlockNetworkDict (CO_Data* d, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS8 size, UNS8 dataType)
1918{
1919 return _readBlockNetworkDict (d, nodeId, index, subIndex, size, dataType, NULL);
1920}
1921
1936UNS8 readNetworkDict (CO_Data* d, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS8 dataType)
1937{
1938 return _readNetworkDict (d, nodeId, index, subIndex, dataType, NULL);
1939}
1940
1958UNS8 readNetworkDictCallback (CO_Data* d, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS8 dataType, SDOCallback_t Callback)
1959{
1960 return _readNetworkDict (d, nodeId, index, subIndex, dataType, Callback);
1961}
1962
1979UNS8 readNetworkDictCallbackAI (CO_Data* d, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS8 dataType, SDOCallback_t Callback)
1980{
1981 UNS8 ret;
1982 UNS16 lastIndex;
1983 UNS16 offset;
1984 UNS8 nodeIdServer;
1985
1986
1987
1988 ret = _readNetworkDict (d, nodeId, index, subIndex, dataType, Callback);
1989 if(ret == 0xFE)
1990 {
1991 offset = d->firstIndex->SDO_CLT;
1992 lastIndex = d->lastIndex->SDO_CLT;
1993 if (offset == 0)
1994 {
1995 MSG_ERR(0x1AC6, "writeNetworkDict : No SDO client index found", 0);
1996 return 0xFF;
1997 }
1998
1999 while (offset <= lastIndex)
2000 {
2001 if (d->objdict[offset].bSubCount <= 3)
2002 {
2003 MSG_ERR(0x1AC8, "Subindex 3 not found at index ", 0x1280 + i);
2004 return 0xFF;
2005 }
2006 nodeIdServer = *(UNS8*) d->objdict[offset].pSubindex[3].pObject;
2007 if(nodeIdServer == 0)
2008 {
2009 *(UNS32*)d->objdict[offset].pSubindex[1].pObject = (UNS32)(0x600 + nodeId);
2010 *(UNS32*)d->objdict[offset].pSubindex[2].pObject = (UNS32)(0x580 + nodeId);
2011 *(UNS8*) d->objdict[offset].pSubindex[3].pObject = nodeId;
2012 return _readNetworkDict (d, nodeId, index, subIndex, dataType, Callback);
2013 }
2014 offset++;
2015 }
2016 return 0xFF;
2017 }
2018 else if(ret == 0)
2019 {
2020 return 0;
2021 }
2022 else
2023 {
2024 return 0xFF;
2025 }
2026}
2027
2054UNS8 getReadResultNetworkDict (CO_Data* d, UNS8 nodeId, void* data, UNS32 *size,
2055 UNS32 * abortCode)
2056{
2057 UNS32 i;
2058 UNS8 err;
2059 UNS8 line;
2060 * abortCode = 0;
2061
2062 /* Looking for the line tranfer. */
2063 err = getSDOlineOnUse(d, nodeId, SDO_CLIENT, &line);
2064 if (err)
2065 {
2066 MSG_ERR(0x1AF0, "SDO error : No line found for communication with node : ", nodeId);
2067 return SDO_ABORTED_INTERNAL;
2068 }
2069 * abortCode = d->transfers[line].abortCode;
2070 if (d->transfers[line].state != SDO_FINISHED)
2071 return d->transfers[line].state;
2072
2073 /* if SDO initiated with e=0 and s=0 count is null, offset carry effective size*/
2074 if( d->transfers[line].count == 0)
2075 d->transfers[line].count = d->transfers[line].offset;
2076 /* use transfers[line].count as max size */
2077 if( d->transfers[line].count < *size )
2078 *size = d->transfers[line].count;
2079 /* Copy payload to data pointer */
2080 for ( i = 0 ; i < *size ; i++)
2081 {
2082# ifdef CANOPEN_BIG_ENDIAN
2083 if (d->transfers[line].dataType != visible_string)
2084 ( (char *) data)[*size - 1 - i] = d->transfers[line].data[i];
2085 else /* String of bytes. */
2086 ( (char *) data)[i] = d->transfers[line].data[i];
2087# else
2088 ( (char *) data)[i] = d->transfers[line].data[i];
2089# endif
2090 }
2091 return SDO_FINISHED;
2092}
2093
2121{
2122 UNS8 line = 0;
2123 UNS8 err;
2124
2125 * abortCode = 0;
2126 /* Looking for the line tranfert. */
2127 err = getSDOlineOnUse(d, nodeId, SDO_CLIENT, &line);
2128 if (err) {
2129 MSG_ERR(0x1AF1, "SDO error : No line found for communication with node : ", nodeId);
2130 return SDO_ABORTED_INTERNAL;
2131 }
2132 * abortCode = d->transfers[line].abortCode;
2133 return d->transfers[line].state;
2134}
#define UNS8
Unsigned int8 representation in CANFest.
Definition applicfg.h:25
#define UNS16
Unsigned int16 representation in CANFest.
Definition applicfg.h:26
#define MSG_WAR(num, str, val)
Definition of MSG_WAR.
Definition applicfg.h:64
#define UNS32
Unsigned int32 representation in CANFest.
Definition applicfg.h:27
#define MSG_ERR(num, str, val)
Definition of MSG_ERR.
Definition applicfg.h:52
#define SDO_RESET
Definition def.h:60
#define OD_SUCCESSFUL
Definition def.h:16
UNS32 objdictToSDOBlockline(CO_Data *d, UNS8 line, UNS8 numberOfIndexes)
Copy the data from the object dictionary to the SDO line for a network transfert.
Definition sdo.c:191
UNS8 readNetworkDict(CO_Data *d, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS8 dataType)
Used to send a SDO request frame to read.
Definition sdo.c:1936
INLINE UNS8 _writeNetworkDict(CO_Data *d, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS32 count, UNS8 dataType, void *data, SDOCallback_t Callback, UNS8 endianize)
Used to send a SDO request frame to write in a distant node dictionnary.
Definition sdo.c:1454
void resetSDO(CO_Data *d)
Reset all SDO buffers.
Definition sdo.c:120
UNS8 failedSDO(CO_Data *d, UNS8 nodeId, UNS8 whoami, UNS16 index, UNS8 subIndex, UNS32 abortCode)
Called when an internal SDO abort occurs. Release the line * Only if server * If client,...
Definition sdo.c:326
UNS32 objdictToSDOline(CO_Data *d, UNS8 line)
Copy the data from the object dictionary to the SDO line for a network transfert.
Definition sdo.c:161
UNS8 lineToSDO(CO_Data *d, UNS8 line, UNS32 nbBytes, UNS8 *data)
Copy data from an existant line in the argument "* data".
Definition sdo.c:266
UNS32 SDOlineToObjdict(CO_Data *d, UNS8 line)
Copy the data received from the SDO line transfert to the object dictionary.
Definition sdo.c:136
UNS8 writeNetworkDictCallBackAI(CO_Data *d, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS32 count, UNS8 dataType, void *data, SDOCallback_t Callback, UNS8 endianize)
Used to send a SDO request frame to write in a distant node dictionnary.
Definition sdo.c:1635
UNS8 writeNetworkDictCallBack(CO_Data *d, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS32 count, UNS8 dataType, void *data, SDOCallback_t Callback)
Used to send a SDO request frame to write in a distant node dictionnary.
Definition sdo.c:1608
void resetSDOline(CO_Data *d, UNS8 line)
Reset an unused line.
Definition sdo.c:357
INLINE UNS8 _readNetworkDict(CO_Data *d, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS8 dataType, SDOCallback_t Callback)
Used to send a SDO request frame to read.
Definition sdo.c:1699
INLINE UNS8 _readBlockNetworkDict(CO_Data *d, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS8 numberOfIndexes, UNS8 dataType, SDOCallback_t Callback)
Used to send a SDO request frame to read in a distant node dictionnary.
Definition sdo.c:1808
UNS8 readNetworkDictCallback(CO_Data *d, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS8 dataType, SDOCallback_t Callback)
Used to send a SDO request frame to read in a distant node dictionnary.
Definition sdo.c:1958
UNS8 getSDOfreeLine(CO_Data *d, UNS8 whoami, UNS8 *line)
Search for an unused line in the transfers array to store a new SDO. ie a line which value of the fie...
Definition sdo.c:412
UNS8 writeNetworkDict(CO_Data *d, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS32 count, UNS8 dataType, void *data)
Used to send a SDO request frame to write the data at the index and subIndex indicated.
Definition sdo.c:1583
UNS8 SDOtoLine(CO_Data *d, UNS8 line, UNS32 nbBytes, UNS8 *data)
Add data to an existant line.
Definition sdo.c:294
UNS8 readNetworkDictCallbackAI(CO_Data *d, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS8 dataType, SDOCallback_t Callback)
Used to send a SDO request frame to read in a distant node dictionnary.
Definition sdo.c:1979
UNS8 readBlockNetworkDict(CO_Data *d, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS8 size, UNS8 dataType)
Used to send a SDO request frame to read in a distant node dictionnary.
Definition sdo.c:1917
UNS8 getSDOlineRestBytes(CO_Data *d, UNS8 line, UNS32 *nbBytes)
Bytes in the line structure which must be transmited (or received)
Definition sdo.c:479
UNS8 setSDOlineRestBytes(CO_Data *d, UNS8 line, UNS32 nbBytes)
Store in the line structure the nb of bytes which must be transmited (or received)
Definition sdo.c:499
UNS8 getWriteResultNetworkDict(CO_Data *d, UNS8 nodeId, UNS32 *abortCode)
Use this function after calling writeNetworkDict function to get the result of the write.
Definition sdo.c:2120
void SDOTimeoutAlarm(CO_Data *d, UNS32 id)
Reset of a SDO exchange on timeout. Send a SDO abort.
Definition sdo.c:79
UNS8 getReadResultNetworkDict(CO_Data *d, UNS8 nodeId, void *data, UNS32 *size, UNS32 *abortCode)
Use this function after calling readNetworkDict to get the result.
Definition sdo.c:2054
UNS8 initSDOline(CO_Data *d, UNS8 line, UNS8 nodeId, UNS16 index, UNS8 subIndex, UNS8 state)
Initialize some fields of the structure.
Definition sdo.c:379
UNS8 getSDOlineOnUse(CO_Data *d, UNS8 nodeId, UNS8 whoami, UNS8 *line)
Search for the line, in the transfers array, which contains the beginning of the reception of a fragm...
Definition sdo.c:439
UNS8 sendSDOabort(CO_Data *d, UNS8 whoami, UNS8 nodeID, UNS16 index, UNS8 subIndex, UNS32 abortCode)
Transmit a SDO error to the client. The reasons may be : Read/Write to a undefined object Read/Write ...
Definition sdo.c:608
UNS8 sendSDO(CO_Data *d, UNS8 whoami, s_SDO sdo)
Transmit a SDO frame on the bus bus_id.
Definition sdo.c:517
UNS8 processSDO(CO_Data *d, Message *m)
Treat a SDO frame reception call the function sendSDO.
Definition sdo.c:649
#define getSDOt(byte)
Definition sdo.c:62
#define getSDOsubIndex(byte3)
Definition sdo.c:70
#define getSDOcs(byte)
Definition sdo.c:38
#define getSDOe(byte)
Definition sdo.c:50
#define getSDOindex(byte1, byte2)
Definition sdo.c:66
#define getSDOn2(byte)
Definition sdo.c:42
#define getSDOn3(byte)
Definition sdo.c:46
#define getSDOc(byte)
Definition sdo.c:58
#define getSDOs(byte)
Definition sdo.c:54
UNS8 data[8]
Definition sdo.h:60
Definition can.h:13
UNS16 cob_id
Definition can.h:14
UNS8 data[8]
Definition can.h:17
UNS8 rtr
Definition can.h:15
UNS8 len
Definition can.h:16
This structure contains all necessary informations to define a CANOpen node.
Definition data.h:44
UNS8 nodeId
Definition sdo.h:65
UNS32 abortCode
Definition sdo.h:30
UNS8 nodeId
Definition sdo.h:25
UNS32 count
Definition sdo.h:35
TIMER_HANDLE timer
Definition sdo.h:47
UNS8 whoami
Definition sdo.h:27
UNS8 dataType
Definition sdo.h:43
SDOCallback_t Callback
Definition sdo.h:53
UNS32 offset
Definition sdo.h:36