iCub-main
Loading...
Searching...
No Matches
EthMaintainer.cpp
Go to the documentation of this file.
1
2/*
3 * Copyright (C) 2016 iCub Facility - Istituto Italiano di Tecnologia
4 * Author: Marco Accame, Alessandro Scalzo
5 * email: marco.accame@iit.it, alessandro.scalzo@iit.it
6 * website: www.robotcub.org
7 * Permission is granted to copy, distribute, and/or modify this program
8 * under the terms of the GNU General Public License, version 2 or any
9 * later version published by the Free Software Foundation.
10 *
11 * A copy of the license can be found at
12 * http://www.robotcub.org/icub/license/gpl.txt
13 *
14 * This program is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
17 * Public License for more details
18*/
19
20
21#include "EthMaintainer.h"
22
23#include <ace/ACE.h>
24#include <yarp/os/Time.h>
25
26#include <yarp/os/Log.h>
27
28using namespace yarp::os;
29
30string ipv4tostring(eOipv4addr_t ipv4)
31{
32 char ipv4text[20];
33 eo_common_ipv4addr_to_string(ipv4, ipv4text, sizeof(ipv4text));
34 string ret(ipv4text);
35 return ret;
36}
37
38bool string2ipv4(const string &ipv4string, eOipv4addr_t &ipv4)
39{
40 int ip1, ip2, ip3, ip4;
41 int n = sscanf(ipv4string.c_str(), "%d.%d.%d.%d", &ip1, &ip2, &ip3, &ip4);
42 if(4 != n)
43 {
44 return false;
45 }
46
47 ipv4 = EO_COMMON_IPV4ADDR(ip1, ip2, ip3, ip4);
48
49 return true;
50}
51
52
53eOipv4addr_t acetoipv4(ACE_UINT32 address)
54{
55 return htonl(address);
56}
57
58
59ACE_UINT32 ipv4toace(eOipv4addr_t ipv4)
60{
61 return ntohl(ipv4);
62}
63
64
65#if defined(WIN32)
66
67#else
68const eOipv4addr_t EthMaintainer::hostIPaddress = EO_COMMON_IPV4ADDR(10, 0, 1, 104);
69const eOipv4port_t EthMaintainer::mainIPport = 3333;
70
71const eOipv4addr_t EthMaintainer::ipv4OfAllSelected = EO_COMMON_IPV4ADDR(0, 0, 0, 0);
72
73const eOipv4addr_t EthMaintainer::ipv4Broadcast = EO_COMMON_IPV4ADDR(255, 255, 255, 255);
74#endif
75
76
77
79{
80 _opened = false;
81 _verbose = true;
82 _debugprint = false;
83
85}
86
91
92
93
94bool EthMaintainer::open(eOipv4addr_t ipv4, eOipv4port_t port)
95{
96 if(!_opened)
97 {
98 myIPV4addr = ipv4;
99 myIPV4port = port;
100
101 _opened = mSocket.Create(ipv4, port);
102
103 return _opened;
104 }
105 else if((myIPV4addr == ipv4) && (myIPV4port == port))
106 {
107 return true;
108 }
109
110 return false;
111}
112
113
115{
116 if(_opened)
117 {
118 mSocket.Close();
120 _opened = false;
121 }
122
123 return true;
124}
125
126
128{
129 _verbose = on;
130}
131
132
134{
135 _debugprint = on;
136}
137
138//EthBoardList& EthMaintainer::getBoards()
139//{
140// return _internalboardlist;
141//}
142
143
144//void EthMaintainer::clearBoards()
145//{
146// _internalboardlist.clear();
147//}
148
149//int EthMaintainer::addBoard(eOipv4addr_t ipv4)
150//{
151// boardInfo2_t info2;
152
153// bool force = true;
154// _internalboardlist.add(info2, ipv4, force);
155
156// return _internalboardlist.size();
157//}
158
159//int EthMaintainer::remBoard(eOipv4addr_t ipv4)
160//{
161// _internalboardlist.rem(ipv4);
162// return _internalboardlist.size();
163//}
164
165
166
167
168
169
171{
172 bool ret = true;
173
174 eOuprot_cmd_EEPROM_ERASE_t command = {EOUPROT_VALUE_OF_UNUSED_BYTE};
175
176 command.opc = uprot_OPC_LEGACY_EEPROM_ERASE;
177 command.opc2 = uprot_OPC_EEPROM_ERASE;
178 command.sysrestart = 0;
179 command.address = 0;
180 command.size = 0;
181
182 sendCommand(ipv4, &command, sizeof(command));
183
184 return ret;
185}
186
187
188bool EthMaintainer::command_eeprom_read(eOipv4addr_t ipv4, uint16_t from, uint16_t size, uint8_t **value)
189{
190 bool ret = false;
191
192 if(NULL == value)
193 {
194 return ret;
195 }
196
197 if(0 == ipv4)
198 {
199 return ret;
200 }
201
202 if((0 == size) || (size > uprot_EEPROMmaxsize))
203 {
204 return ret;
205 }
206
207 eOuprot_cmd_EEPROM_READ_t command = {EOUPROT_VALUE_OF_UNUSED_BYTE};
208
209 command.opc = uprot_OPC_EEPROM_READ;
210 command.address = from;
211 command.size = size;
212
213 sendCommand(ipv4, &command, sizeof(command));
214
215 // now we wait for the reply ...
216
217 eOipv4addr_t rxipv4addr;
218 eOipv4port_t rxipv4port;
219
220 while(mSocket.ReceiveFrom(rxipv4addr, rxipv4port, mRxBuffer, sizeof(mRxBuffer), 1000) > 0)
221 {
222 eOuprot_cmd_EEPROM_READ_REPLY_t * eepromread = (eOuprot_cmd_EEPROM_READ_REPLY_t*) mRxBuffer;
223
224 if(uprot_OPC_EEPROM_READ == eepromread->reply.opc)
225 {
226 // the board has replied.
227 if(rxipv4addr == ipv4)
228 {
229 ret = (uprot_RES_OK == eepromread->reply.res) ? true : false;
230
231 if(ret)
232 {
233 *value = eepromread->eeprom;
234 }
235 }
236 }
237 }
238
239 return ret;
240}
241
242
243
244bool EthMaintainer::command_program(eOipv4addr_t ipv4, FILE *programFile, eOuprot_partition2prog_t partition, void (*updateProgressBar)(float), EthBoardList *pboardlist, string &stringresult)
245{
246
247 EthBoardList *boardlist2use = pboardlist;
248 if(NULL == boardlist2use)
249 {
250 boardlist2use = &_internalboardlist;
251 }
252
253 progData_t progdata;
254 progdata.mN2Prog = 0;
255 progdata.mNProgSteps = 0;
256 progdata.mNChunks = 0;
257
258 progdata.selected = boardlist2use->get(ipv4);
259
260 progdata.steps.resize(progdata.selected.size(), 0);
261
262 if(NULL != updateProgressBar)
263 {
264 updateProgressBar(0.0f);
265 }
266
267 eOuprot_cmd_PROG_START_t * cmdStart = (eOuprot_cmd_PROG_START_t*) mTxBuffer;
268 eOuprot_cmd_PROG_DATA_t * cmdData = (eOuprot_cmd_PROG_DATA_t*) mTxBuffer;
269 eOuprot_cmd_PROG_END_t * cmdEnd = (eOuprot_cmd_PROG_END_t*) mTxBuffer;
270
271 const int sizeStart = sizeof(eOuprot_cmd_PROG_START_t);
272 const int sizeEnd = sizeof(eOuprot_cmd_PROG_END_t);
273
274
275 const int HEAD_SIZE = 7;
276
277 fseek(programFile,0,SEEK_END);
278 float fileSize=(float)(ftell(programFile)/3);
279 fseek(programFile,0,SEEK_SET);
280
281 memset(cmdStart, EOUPROT_VALUE_OF_UNUSED_BYTE, sizeof(eOuprot_cmd_PROG_START_t));
282 cmdStart->opc = uprot_OPC_PROG_START;
283 cmdStart->partition = partition;
284
285 string partname("UNK");
286 eOuprot_proc_capabilities_t capability = uprot_canDO_nothing;
287 if(uprot_partitionLOADER == partition)
288 {
289 partname = string("LDR");
290 capability = uprot_canDO_PROG_loader;
291 }
292 else if(uprot_partitionUPDATER == partition)
293 {
294 partname = string("UPD");
295 capability = uprot_canDO_PROG_updater;
296 }
297 else if(uprot_partitionAPPLICATION == partition)
298 {
299 partname = string("APP");
300 capability = uprot_canDO_PROG_application;
301 }
302
303
304 // sending the start and preparing the list of boards to program
305
306 // send the start command to all selected
307 sendCommand(ipv4, cmdStart, sizeStart, boardlist2use);
308 // wait a tick
309 yarp::os::Time::delay(0.01);
310
311
312
313 if(_verbose)
314 {
315 printf("EthMaintainer::cmdProgram() is about to program the %s partition of %d boards:", partname.c_str(), (int)progdata.selected.size());
316 for(int j=0; j< progdata.selected.size(); j++)
317 {
318 eOipv4addr_t ipv4 = progdata.selected[j]->getIPV4();
319// bool ok = isCommandSupported(capability, ipv4);
320 bool ok = command_supported(ipv4, capability);
321
322 printf(" %s (%s)", progdata.selected[j]->getIPV4string().c_str(), ok ? ("candoit") : ("CANTdoit"));
323 }
324 printf("\n");
325 fflush(stdout);
326 }
327
328
329 // now we start
330
331 progdata.mNProgSteps = 0;
332 progdata.mNChunks = 1;
333
334 eOipv4addr_t rxipv4addr;
335 eOipv4port_t rxipv4port;
336
337 ++progdata.mNProgSteps;
338
339 int success=0;
340
341 int numberOfOKreplies = 0;
342
343 // waiting for reply of start
344 for(int n=0; n<1000; ++n)
345 {
346 while(mSocket.ReceiveFrom(rxipv4addr, rxipv4port, mRxBuffer, sizeof(mRxBuffer), 10) > 0)
347 {
348 eOuprot_cmdREPLY_t * reply = (eOuprot_cmdREPLY_t*) mRxBuffer;
349
350 if (uprot_OPC_PROG_START == reply->opc)
351 {
352 if (rxipv4addr != myIPV4addr)
353 {
354
355 // search for the ip inside boards2prog. if found then...
356 for(int i=0; i<progdata.selected.size(); i++)
357 {
358 if(rxipv4addr == (progdata.selected[i]->getIPV4()))
359 { // found!
360 if(uprot_RES_OK == reply->res)
361 {
362 progdata.steps[i]++;
363 numberOfOKreplies++;
364 }
365 else
366 {
367 if(_verbose)
368 {
369 // print that the board tells that we cannot program that partition
370 printf("board %s tells that we cannot program the %s partition\n", progdata.selected[i]->getIPV4string().c_str(), partname.c_str());
371 fflush(stdout);
372 }
373 }
374
375 if (++success >= progdata.selected.size())
376 {
377 n = 1000;
378 }
379 }
380 }
381
382 }
383 }
384 }
385 }
386
387
388 if(0 == numberOfOKreplies)
389 {
390 std::string earlyexit;
391
392 for(int i=0; i<progdata.selected.size(); ++i)
393 {
394 eOipv4addr_t ipv4adr = progdata.selected[i]->getIPV4();
395 string ipv4adrstring = ipv4tostring(ipv4adr);
396
397 earlyexit += ipv4adrstring;
398 earlyexit += ": ";
399 earlyexit += partname;
400 earlyexit += (progdata.steps[i] == progdata.mNProgSteps)?" OK\r\n":" CANT (early exit)\r\n";
401 }
402
403 stringresult = earlyexit;
404
405 return false;
406 }
407
408 int addrH=0;
409 int baseAddress=0;
410 int bytesToWrite=0;
411 int bytesWritten=0;
412
413 char buffer[1024];
414
415 bool beof=false;
416
417 // sending data
418 while (!beof && fgets(buffer,1024,programFile))
419 {
420 std::string line(buffer);
421
422 int cmd=strtol(line.substr(7,2).c_str(),NULL,16);
423
424 switch (cmd)
425 {
426 case 0: //standard data record
427 {
428 int size =strtol(line.substr(1,2).c_str(),NULL,16);
429 int addrL=strtol(line.substr(3,4).c_str(),NULL,16);
430
431 int addressHL=addrH<<16|addrL;
432
433 if (!baseAddress) baseAddress=addressHL;
434
435 if (bytesToWrite+size>uprot_PROGmaxsize || addressHL!=baseAddress+bytesToWrite)
436 {
437 if (bytesToWrite)
438 {
439 cmdData->size[0]= bytesToWrite &0xFF;
440 cmdData->size[1]=(bytesToWrite>>8)&0xFF;
441
442 progdata.data = cmdData;
443 progdata.size = HEAD_SIZE+bytesToWrite;
444 progdata.answers = progdata.selected.size();
445 progdata.retries = 1000;
446 sendPROG2(uprot_OPC_PROG_DATA, progdata);
447 if(NULL != updateProgressBar)
448 {
449 updateProgressBar(float(bytesWritten+=bytesToWrite)/fileSize);
450 }
451 bytesToWrite=0;
452 }
453 }
454
455 if (!bytesToWrite)
456 {
457 baseAddress=addressHL;
458 cmdData->opc = uprot_OPC_PROG_DATA;
459 cmdData->address[0] = addrL&0xFF;
460 cmdData->address[1] = (addrL>>8)&0xFF;
461 cmdData->address[2] = addrH&0xFF;
462 cmdData->address[3] = (addrH>>8)&0xFF;
463 }
464
465 for (int i=0; i<size; ++i)
466 {
467 cmdData->data[bytesToWrite+i]=(unsigned char)strtol(line.substr(i*2+9,2).c_str(),NULL,16);
468 }
469
470 bytesToWrite+=size;
471
472 break;
473 }
474 case 1: //end of file
475 if (bytesToWrite) // force write
476 {
477 beof=true;
478 cmdData->size[0] = bytesToWrite &0xFF;
479 cmdData->size[1] = (bytesToWrite>>8)&0xFF;
480
481 progdata.data = cmdData;
482 progdata.size = HEAD_SIZE+bytesToWrite;
483 progdata.answers = progdata.selected.size(); // mN2Prog
484 progdata.retries = 1000;
485 sendPROG2(uprot_OPC_PROG_DATA, progdata);
486 if(NULL != updateProgressBar)
487 {
488 updateProgressBar(1.0f);
489 }
490 bytesToWrite=0;
491 }
492 break;
493 case 2:
494 case 3:
495 //AfxMessageBox("Unsupported hex commad");
496 break;
497 case 4: //extended linear address record
498 {
499 if (bytesToWrite) // force write
500 {
501 cmdData->size[0] = bytesToWrite &0xFF;
502 cmdData->size[1] = (bytesToWrite>>8)&0xFF;
503
504 progdata.data = cmdData;
505 progdata.size = HEAD_SIZE+bytesToWrite;
506 progdata.answers = progdata.selected.size(); // mN2Prog
507 progdata.retries = 1000;
508 sendPROG2(uprot_OPC_PROG_DATA, progdata);
509 if(NULL != updateProgressBar)
510 {
511 updateProgressBar(float(bytesWritten+=bytesToWrite)/fileSize);
512 }
513 bytesToWrite=0;
514 }
515
516 addrH=strtol(line.substr(9,4).c_str(),NULL,16);
517
518 break;
519 }
520 case 5: // jump
521 if (bytesToWrite) // force write
522 {
523 cmdData->size[0]= bytesToWrite &0xFF;
524 cmdData->size[1]= (bytesToWrite>>8)&0xFF;
525
526 progdata.data = cmdData;
527 progdata.size = HEAD_SIZE+bytesToWrite;
528 progdata.answers = progdata.selected.size(); // mN2Prog
529 progdata.retries = 1000;
530 sendPROG2(uprot_OPC_PROG_DATA, progdata);
531 if(NULL != updateProgressBar)
532 {
533 updateProgressBar(float(bytesWritten+=bytesToWrite)/fileSize);
534 }
535 bytesToWrite=0;
536 }
537
538 break;
539 }
540 }
541
542
543 // now we send the end
544 memset(cmdEnd, EOUPROT_VALUE_OF_UNUSED_BYTE, sizeof(eOuprot_cmd_PROG_END_t));
545 cmdEnd->opc = uprot_OPC_PROG_END;
546 cmdEnd->numberofpkts[0] = progdata.mNChunks & 0xFF;
547 cmdEnd->numberofpkts[1] = (progdata.mNChunks>>8) & 0xFF;
548
549 progdata.data = cmdEnd;
550 progdata.size = sizeEnd;
551 progdata.answers = progdata.selected.size(); // mN2Prog
552 progdata.retries = 1000;
553 sendPROG2(uprot_OPC_PROG_END, progdata);
554
555 if(NULL != updateProgressBar)
556 {
557 updateProgressBar(1.0f);
558 }
559
560
561 std::string sOutput;
562 bool result = true;
563
564 for(int i=0; i<progdata.selected.size(); ++i)
565 {
566 bool ok = (progdata.steps[i]==progdata.mNProgSteps) ? true : false;
567 if(false == ok)
568 {
569 result = false;
570 }
571 eOipv4addr_t ipv4adr = progdata.selected[i]->getIPV4();
572 string ipv4adrstring = ipv4tostring(ipv4adr);
573
574 sOutput += ipv4adrstring;
575 sOutput += ": ";
576 sOutput += partname;
577 sOutput += (ok)?" OK\r\n":" NOK\r\n";
578 }
579
580 stringresult = sOutput;
581
582 return result;
583}
584
585
586// helper functions
587
588
589bool EthMaintainer::sendCommand(eOipv4addr_t ipv4, void * cmd, uint16_t len, EthBoardList *boardlist)
590{
591 bool ret = false;
592 if(ipv4OfAllSelected == ipv4)
593 {
594 if(NULL == boardlist)
595 {
596 boardlist = &_internalboardlist;
597 }
598 vector<EthBoard *> selected = boardlist->get(ipv4);
599 for(int i=0; i<selected.size(); i++)
600 {
601 mSocket.SendTo(selected[i]->getIPV4(), myIPV4port, cmd, len);
602 ret = true;
603 }
604 }
605 else if(ipv4Broadcast == ipv4)
606 {
608 ret = true;
609 }
610 else
611 {
612 mSocket.SendTo(ipv4, myIPV4port, cmd, len);
613 ret = true;
614 }
615 return ret;
616}
617
618
619
620bool EthMaintainer::isInMaintenance(eOipv4addr_t ipv4, EthBoardList &boardlist)
621{
622 vector<EthBoard *> selected = boardlist.get(ipv4);
623
624 if(selected.empty())
625 {
626 return false;
627 }
628
629 for(int i=0; i<selected.size(); i++)
630 {
631 if(false == selected[i]->isInMaintenance())
632 {
633 return false;
634 }
635 }
636
637 return true;
638}
639
640
641bool EthMaintainer::isInApplication(eOipv4addr_t ipv4, EthBoardList &boardlist)
642{
643 vector<EthBoard *> selected = boardlist.get(ipv4);
644
645 if(selected.empty())
646 {
647 return false;
648 }
649
650 for(int i=0; i<selected.size(); i++)
651 {
652 if(false == selected[i]->isInApplication())
653 {
654 return false;
655 }
656 }
657
658 return true;
659}
660
661
662string EthMaintainer::processDiscoveryReplies2(EthBoardList &boardlist, double waittimeout)
663{
664 string info;
665
666 eOipv4addr_t rxipv4addr;
667 eOipv4port_t rxipv4port;
668
669 while(mSocket.ReceiveFrom(rxipv4addr, rxipv4port, mRxBuffer, sizeof(mRxBuffer), waittimeout*1000.0) > 0)
670 {
671 eOuprot_cmd_DISCOVER_REPLY2_t * disc2 = reinterpret_cast<eOuprot_cmd_DISCOVER_REPLY2_t*>(mRxBuffer);
672 eOuprot_cmd_DISCOVER_REPLY_t * disc = reinterpret_cast<eOuprot_cmd_DISCOVER_REPLY_t*>(mRxBuffer);
673 eOuprot_cmd_LEGACY_SCAN_REPLY_t * scan = reinterpret_cast<eOuprot_cmd_LEGACY_SCAN_REPLY_t*> (mRxBuffer);
674
675 string ipv4rxstring = ipv4tostring(rxipv4addr);
676
677 if(uprot_OPC_DISCOVER == disc->reply.opc)
678 {
679 // the board has replied with the new protocol.
680
681 if(rxipv4addr != myIPV4addr)
682 {
683 boardInfo2_t binfo;
684
685 // the protococol version and capabilities are properties of the running process.
686 binfo.protversion = disc->reply.protversion;
687 binfo.capabilities = disc->capabilities;
688
689 memcpy(&binfo.macaddress, disc->mac48, 6);
690 binfo.boardtype = (eObrd_ethtype_t)disc->boardtype;
691 binfo.applicationdetails = disc->unused[0];
692
693 memcpy(&binfo.processes, &disc->processes, sizeof(eOuprot_proctable_t));
694 memcpy(binfo.boardinfo32, disc->boardinfo32, sizeof(binfo.boardinfo32));
695
696 binfo.maintenanceIsActive = false;
697 if(eUpdater == binfo.processes.runningnow)
698 {
699 binfo.maintenanceIsActive = true;
700 }
701
702 uint8_t index = eouprot_process2index((eOuprot_process_t)disc->processes.runningnow);
703
704 binfo.versionOfRunning.major = binfo.processes.info[index].version.major;
705 binfo.versionOfRunning.minor = binfo.processes.info[index].version.minor;
706
707 binfo.moreinfostring = prepareMoreInfoText(disc, ipv4rxstring.c_str());
708
709 boardlist.add(binfo, rxipv4addr);
710
711 // now we add into the string
712 {
713 info += binfo.moreinfostring;
714 }
715
716
717 if(_verbose)
718 {
719 printf("EthMaintainer::processDiscoveryReplies2() has found a board @ %s: %s w/ %s v%d.%d running protocol v%d w/ capabilities = 0x%x. mainteinance = %s\n",
720 ipv4rxstring.c_str(),
721 eoboards_type2string2((eObrd_type_t)disc->boardtype, eobool_true),
722 eouprot_process2string((eOuprot_process_t)disc->processes.runningnow),
723 disc->processes.info[index].version.major,
724 disc->processes.info[index].version.minor,
725 disc->reply.protversion,
726 disc->capabilities,
727 (binfo.maintenanceIsActive) ? ("ON") : ("OFF")
728 );
729 fflush(stdout);
730 }
731 }
732
733 }
734 else if (uprot_OPC_LEGACY_SCAN == scan->opc)
735 {
736 // we have an old board ... by definition it has protocol version 0.
737
738 if(rxipv4addr != myIPV4addr)
739 {
740
741 // the protococol version and capabilities are properties of the running process.
742 // from the legacy answer uprot_OPC_LEGACY_SCAN i know that we have protocol version 0.
743 // however ... which process is it replying? the most probable is eUpdater, the second most probable is
744 // eApplication. It is unlikely that it is a legacy eMaintainer because we should not use it.
745 // i decide the following:
746 // i give the permissions of legacy updater which contains those of legacy application.
747 // because even if it was the application which replied then, surely now it is the updater running.
748
749 // in this case we add the board ...
750
751
752 uint8_t procmajor = scan->version.major;
753 uint8_t procminor = scan->version.minor;
754
755
756 //uint32_t mask=*(ACE_UINT32*)(scan->ipmask);
757 uint64_t mac=0;
758
759 for(int i=7; i>=0; --i)
760 {
761 mac=(mac<<8)|scan->mac48[i];
762 }
763
764
765
766 boardInfo2_t binfo;
767
768 binfo.reset();
769
770 // the protococol version and capabilities are properties of the running process.
771 binfo.protversion = 0;
772 binfo.capabilities = eouprot_get_capabilities(eUpdater, binfo.protversion);
773
774 memcpy(&binfo.macaddress, &mac, 6);
775 binfo.boardtype = eobrd_ethtype_unknown;
776
777 // we decide that we are in maintenance, even if we dont really know ...
778 // because: if the applition replied with legacy protocol then it surely goes into updater.
779 // if it was teh updater then ... ok.
780 // we dont use an old maintainer anymore .
781 // moreover ... we decide that the running process is the updater.
782 binfo.maintenanceIsActive = true;
783 binfo.processes.runningnow = eUpdater;
784 binfo.processes.info[eUpdater].type = eUpdater;
785 binfo.processes.info[eUpdater].version.major = procmajor;
786 binfo.processes.info[eUpdater].version.minor = procminor;
787
788 binfo.versionOfRunning.major = procmajor;
789 binfo.versionOfRunning.minor = procminor;
790
791 boardlist.add(binfo, rxipv4addr);
792
793
794 if(_verbose)
795 {
796 printf("EthMaintainer::processDiscoveryReplies2() has found board @ %s in maintenance: the running process is v %d.%d, uses legacy protocol, i assume protocol capabilities = 0x%x.\n",
797 ipv4rxstring.c_str(), procmajor, procminor, binfo.capabilities);
798 fflush(stdout);
799 }
800 }
801 }
802 else if(uprot_OPC_DISCOVER2 == disc2->discoveryreply.reply.opc)
803 {
804 // the board has replied with the new multi-application-processes protocol.
805
806 if(rxipv4addr != myIPV4addr)
807 {
808 boardInfo2_t binfo;
809
810 // the protococol version and capabilities are properties of the running process.
811 binfo.protversion = disc2->discoveryreply.reply.protversion;
812 binfo.capabilities = disc2->discoveryreply.capabilities;
813
814 memcpy(&binfo.macaddress, disc2->discoveryreply.mac48, 6);
815 binfo.boardtype = (eObrd_ethtype_t)disc2->discoveryreply.boardtype;
816 binfo.applicationdetails = disc2->discoveryreply.unused[0];
817
818 memcpy(&binfo.processes, &disc2->discoveryreply.processes, sizeof(eOuprot_proctable_t));
819 memcpy(binfo.boardinfo32, disc2->discoveryreply.boardinfo32, sizeof(binfo.boardinfo32));
820 memcpy(binfo.extraprocesses, disc2->extraprocs, sizeof(eOuprot_procinfo_t));
821
822 binfo.maintenanceIsActive = (eUpdater == binfo.processes.runningnow) ? true : false;
823
824 uint8_t index = eouprot_process2index((eOuprot_process_t)disc2->discoveryreply.processes.runningnow);
825
826 binfo.versionOfRunning.major = binfo.processes.info[index].version.major;
827 binfo.versionOfRunning.minor = binfo.processes.info[index].version.minor;
828
829 binfo.moreinfostring = prepareMoreInfoText(disc2, ipv4rxstring.c_str());
830
831 boardlist.add(binfo, rxipv4addr);
832
833 // now we add into the string
834 info += binfo.moreinfostring;
835
836 if(_verbose)
837 {
838 printf("EthMaintainer::processDiscoveryReplies2() has a found board @ %s: %s w/ %s v%d.%d running protocol v%d w/ capabilities = 0x%x. mainteinance = %s\n",
839 ipv4rxstring.c_str(),
840 eoboards_type2string2((eObrd_type_t)disc2->discoveryreply.boardtype, eobool_true),
841 eouprot_process2string((eOuprot_process_t)disc2->discoveryreply.processes.runningnow),
842 disc2->discoveryreply.processes.info[index].version.major,
843 disc2->discoveryreply.processes.info[index].version.minor,
844 disc2->discoveryreply.reply.protversion,
845 disc2->discoveryreply.capabilities,
846 (binfo.maintenanceIsActive) ? ("ON") : ("OFF")
847 );
848 fflush(stdout);
849 }
850 }
851 }
852 }
853
854 return info;
855
856}
857
858
859
861{
862 std::string info;
863
864 eOipv4addr_t rxipv4addr;
865 eOipv4port_t rxipv4port;
866
867 while(mSocket.ReceiveFrom(rxipv4addr, rxipv4port, mRxBuffer, sizeof(mRxBuffer), 500) > 0)
868 {
869 eOuprot_cmd_MOREINFO_REPLY_t *moreinfo = reinterpret_cast<eOuprot_cmd_MOREINFO_REPLY_t*>(mRxBuffer);
870 eOuprot_cmd_LEGACY_PROCS_REPLY_t *procs = reinterpret_cast<eOuprot_cmd_LEGACY_PROCS_REPLY_t*>(mRxBuffer);
871
872 string ipv4rxstring = ipv4tostring(rxipv4addr);
873
874 if(uprot_OPC_MOREINFO == moreinfo->discover.reply.opc)
875 {
876 // the board has replied with the new protocol.
877
878 if(rxipv4addr != myIPV4addr)
879 {
880 eOuprot_cmd_DISCOVER_REPLY_t * disc = &moreinfo->discover;
881
882 boardInfo2_t binfo;
883
884 // the protococol version and capabilities are properties of the running process.
885 binfo.protversion = disc->reply.protversion;
886 binfo.capabilities = disc->capabilities;
887
888 memcpy(&binfo.macaddress, disc->mac48, 6);
889 binfo.boardtype = (eObrd_ethtype_t)disc->boardtype;
890 binfo.applicationdetails = disc->unused[0];
891
892 memcpy(&binfo.processes, &disc->processes, sizeof(eOuprot_proctable_t));
893 memcpy(binfo.boardinfo32, disc->boardinfo32, sizeof(binfo.boardinfo32));
894
895 binfo.maintenanceIsActive = false;
896 if(eUpdater == binfo.processes.runningnow)
897 {
898 binfo.maintenanceIsActive = true;
899 }
900
901 binfo.versionOfRunning.major = binfo.processes.info[binfo.processes.runningnow].version.major;
902 binfo.versionOfRunning.minor = binfo.processes.info[binfo.processes.runningnow].version.minor;
903
904 binfo.moreinfostring = prepareMoreInfoText(disc, ipv4rxstring.c_str());
905
906 boardlist.add(binfo, rxipv4addr);
907
908 // now we add into the string
909 {
910 info += binfo.moreinfostring;
911 }
912
913
914 if(_verbose)
915 {
916 // print binfo.
917 // it would be much bettwer, however, store it somewhere and made it available
918 // through some method
919
920
921 printf("\nBOARD at address %s:", ipv4rxstring.c_str());
922 printf("\n prot = %d, boardtype = %s, startup proc = %s, def2run proc = %s. it has %d processes:",
923 binfo.protversion,
924 eoboards_type2string2((eObrd_type_t)binfo.boardtype, eobool_true),
925 eouprot_process2string((eOuprot_process_t)binfo.processes.startup),
926 eouprot_process2string((eOuprot_process_t)binfo.processes.def2run),
927 binfo.processes.numberofthem
928 );
929 for(int n=0; n<binfo.processes.numberofthem; n++)
930 {
931 char strdate[24] = {0};
932 char builton[24] = {0};
933 eo_common_date_to_string(binfo.processes.info[n].date, strdate, sizeof(strdate));
934 eo_common_date_to_string(binfo.processes.info[n].compilationdate, builton, sizeof(builton));
935 printf("\n proc-%d: type %s w/ appl version = (%d, %d), dated %s, built on %s, rom = [%d, %d) kb",
936 n,
937 eouprot_process2string((eOuprot_process_t)binfo.processes.info[n].type),
938 binfo.processes.info[n].version.major, binfo.processes.info[n].version.minor,
939 strdate,
940 builton,
941 binfo.processes.info[n].rom_addr_kb, binfo.processes.info[n].rom_addr_kb + binfo.processes.info[n].rom_size_kb
942 );
943
944 }
945
946 printf("\n now process %s is running", eouprot_process2string((eOuprot_process_t)binfo.processes.runningnow));
947
948 if(0xff == binfo.boardinfo32[0])
949 {
950 printf("\n stored info32 is .. ");
951 for(int m=0; m<32; m++)
952 {
953 printf("0x%x ", binfo.boardinfo32[m]);
954 }
955
956 }
957 else
958 {
959 printf("\n stored info32 is .. ");
960 printf("l = %d, string = %s \n", binfo.boardinfo32[0], &binfo.boardinfo32[1]);
961 }
962
963 printf("\n\n");
964
965 }
966 }
967 }
968 else if(uprot_OPC_LEGACY_PROCS == procs->opc)
969 {
970 // old boards reply with uprot_OPC_LEGACY_PROCS
971 // unfortunately this field only has ... numofprocesses and textual description
972 // I DONT add a entry ....
973
974 if (rxipv4addr != myIPV4addr)
975 {
976
977 // 1. i prepare the string
978
979 string moreinfostring;
980
981 moreinfostring += "------------------------------\r\n";
982 moreinfostring += std::string("Board\t")+ipv4rxstring;
983 moreinfostring += "\r\n\r\n";
984 moreinfostring += std::string((char*)procs->description);
985
986
987 // 2. i retrieve the boards
988 vector<EthBoard *> boards = boardlist.get(rxipv4addr);
989 for(int i=0; i<boards.size(); i++)
990 {
991 boards[i]->setMoreInfo(moreinfostring);
992 }
993
994 // finally we update return string
995
996 info += moreinfostring;
997
998
999 if(_verbose)
1000 {
1001 printf("\n received a uprot_OPC_LEGACY_PROCS from IP %s \n", ipv4rxstring.c_str());
1002 fflush(stdout);
1003 }
1004
1005 }
1006
1007 }
1008 }
1009
1010
1011 return info;
1012
1013}
1014
1015
1016std::string EthMaintainer::prepareMoreInfoText(eOuprot_cmd_DISCOVER_REPLY_t * disc, const char *ipv4rxaddr_string)
1017{
1018 std::string info;
1019
1020 char tmp[512] = {0};
1021
1022
1023 boardInfo2_t binfo;
1024
1025 binfo.reset();
1026
1027
1028 binfo.protversion = disc->reply.protversion;
1029 binfo.capabilities = disc->capabilities;
1030 memcpy(&binfo.macaddress, disc->mac48, 6);
1031 binfo.boardtype = (eObrd_ethtype_t)disc->boardtype;
1032 binfo.applicationdetails = disc->unused[0];
1033 memcpy(&binfo.processes, &disc->processes, sizeof(eOuprot_proctable_t));
1034 memcpy(binfo.boardinfo32, disc->boardinfo32, sizeof(binfo.boardinfo32));
1035
1036 binfo.maintenanceIsActive = false;
1037 if(eUpdater == binfo.processes.runningnow)
1038 {
1039 binfo.maintenanceIsActive = true;
1040 }
1041
1042 uint8_t index = eouprot_process2index((eOuprot_process_t)disc->processes.runningnow);
1043
1044 binfo.versionOfRunning.major = binfo.processes.info[index].version.major;
1045 binfo.versionOfRunning.minor = binfo.processes.info[index].version.minor;
1046
1047
1048
1049 char status[64] = "normal";
1050 if(true == binfo.maintenanceIsActive)
1051 {
1052 snprintf(status, sizeof(status), "maintenance");
1053 }
1054 else
1055 {
1056 snprintf(status, sizeof(status), "normal");
1057 }
1058
1059 char mac_string[64] = "00-00-00-00-00-00";
1060 snprintf(mac_string, sizeof(mac_string), "%02X-%02X-%02X-%02X-%02X-%02X",
1061 (uint8_t)(binfo.macaddress >> 40) & 0xff,
1062 (uint8_t)(binfo.macaddress >> 32) & 0xff,
1063 (uint8_t)(binfo.macaddress >> 24) & 0xff,
1064 (uint8_t)(binfo.macaddress >> 16) & 0xff,
1065 (uint8_t)(binfo.macaddress >> 8 ) & 0xff,
1066 (uint8_t)(binfo.macaddress ) & 0xff
1067 );
1068
1069
1070 snprintf(tmp, sizeof(tmp), "BOARD: \n- type: %s \n- mac: %s \n- ip: %s \n- status: %s",
1071 eoboards_type2string2((eObrd_type_t)binfo.boardtype, eobool_true),
1072 mac_string,
1073 ipv4rxaddr_string,
1074 status);
1075 info += tmp;
1076
1077 snprintf(tmp, sizeof(tmp), "\n\nBOOTSTRAP PROCESSES:"
1078 );
1079 info += tmp;
1080
1081 snprintf(tmp, sizeof(tmp), "\n- startup: %s, \n- default: %s, \n- running: %s.",
1082 eouprot_process2string((eOuprot_process_t)binfo.processes.startup),
1083 eouprot_process2string((eOuprot_process_t)binfo.processes.def2run),
1084 eouprot_process2string((eOuprot_process_t)binfo.processes.runningnow)
1085 );
1086 info += tmp;
1087
1088 snprintf(tmp, sizeof(tmp), "\n\nPROPS OF THE %d PROCESSES:",
1089 binfo.processes.numberofthem
1090 );
1091 info += tmp;
1092
1093 for(int n=0; n<binfo.processes.numberofthem; n++)
1094 {
1095 char strdate[24] = {0};
1096 char builton[24] = {0};
1097 eo_common_date_to_string(binfo.processes.info[n].date, strdate, sizeof(strdate));
1098 eo_common_date_to_string(binfo.processes.info[n].compilationdate, builton, sizeof(builton));
1099 snprintf(tmp, sizeof(tmp), "\n- proc-%d: \n type: %s \n version: %d.%d, \n dated: %s, \n built on: %s, \n rom: [%d, %d) kb",
1100 n,
1101 eouprot_process2string((eOuprot_process_t)binfo.processes.info[n].type),
1102 binfo.processes.info[n].version.major, binfo.processes.info[n].version.minor,
1103 strdate,
1104 builton,
1105 binfo.processes.info[n].rom_addr_kb, binfo.processes.info[n].rom_addr_kb + binfo.processes.info[n].rom_size_kb
1106 );
1107 info += tmp;
1108
1109 }
1110
1111
1112
1113 info += "\n\n";
1114
1115 return info;
1116}
1117
1118std::string EthMaintainer::prepareMoreInfoText(eOuprot_cmd_DISCOVER_REPLY2_t * disc, const char *ipv4rxaddr_string)
1119{
1120 std::string info;
1121
1122 char tmp[512] = {0};
1123
1124
1125 boardInfo2_t binfo;
1126
1127 binfo.reset();
1128
1129
1130 binfo.protversion = disc->discoveryreply.reply.protversion;
1131 binfo.capabilities = disc->discoveryreply.capabilities;
1132 memcpy(&binfo.macaddress, disc->discoveryreply.mac48, 6);
1133 binfo.boardtype = (eObrd_ethtype_t)disc->discoveryreply.boardtype;
1134 binfo.applicationdetails = disc->discoveryreply.unused[0];
1135 memcpy(&binfo.processes, &disc->discoveryreply.processes, sizeof(eOuprot_proctable_t));
1136 memcpy(binfo.boardinfo32, disc->discoveryreply.boardinfo32, sizeof(binfo.boardinfo32));
1137 memcpy(binfo.extraprocesses, disc->extraprocs, sizeof(eOuprot_procinfo_t));
1138
1139 binfo.maintenanceIsActive = false;
1140 if(eUpdater == binfo.processes.runningnow)
1141 {
1142 binfo.maintenanceIsActive = true;
1143 }
1144
1145 uint8_t index = eouprot_process2index((eOuprot_process_t)disc->discoveryreply.processes.runningnow);
1146
1147 binfo.versionOfRunning.major = binfo.processes.info[index].version.major;
1148 binfo.versionOfRunning.minor = binfo.processes.info[index].version.minor;
1149
1150
1151
1152 char status[64] = "normal";
1153 if(true == binfo.maintenanceIsActive)
1154 {
1155 snprintf(status, sizeof(status), "maintenance");
1156 }
1157 else
1158 {
1159 snprintf(status, sizeof(status), "normal");
1160 }
1161
1162 char mac_string[64] = "00-00-00-00-00-00";
1163 snprintf(mac_string, sizeof(mac_string), "%02X-%02X-%02X-%02X-%02X-%02X",
1164 (uint8_t)(binfo.macaddress >> 40) & 0xff,
1165 (uint8_t)(binfo.macaddress >> 32) & 0xff,
1166 (uint8_t)(binfo.macaddress >> 24) & 0xff,
1167 (uint8_t)(binfo.macaddress >> 16) & 0xff,
1168 (uint8_t)(binfo.macaddress >> 8 ) & 0xff,
1169 (uint8_t)(binfo.macaddress ) & 0xff
1170 );
1171
1172
1173 snprintf(tmp, sizeof(tmp), "BOARD: \n- type: %s \n- mac: %s \n- ip: %s \n- status: %s",
1174 eoboards_type2string2((eObrd_type_t)binfo.boardtype, eobool_true),
1175 mac_string,
1176 ipv4rxaddr_string,
1177 status);
1178 info += tmp;
1179
1180 snprintf(tmp, sizeof(tmp), "\n\nBOOTSTRAP PROCESSES:"
1181 );
1182 info += tmp;
1183
1184 snprintf(tmp, sizeof(tmp), "\n- startup: %s, \n- default: %s, \n- running: %s.",
1185 eouprot_process2string((eOuprot_process_t)binfo.processes.startup),
1186 eouprot_process2string((eOuprot_process_t)binfo.processes.def2run),
1187 eouprot_process2string((eOuprot_process_t)binfo.processes.runningnow)
1188 );
1189 info += tmp;
1190
1191 snprintf(tmp, sizeof(tmp), "\n\nPROPS OF THE %d PROCESSES:",
1192 binfo.processes.numberofthem
1193 );
1194 info += tmp;
1195
1196 for(int n=0; n<binfo.processes.numberofthem; n++)
1197 {
1198 char strdate[24] = {0};
1199 char builton[24] = {0};
1200 constexpr uint8_t maxNumberOfProcessesOnSingleCore {3};
1201
1202 // When "n" is in [0,3) we are considering the standard single core processes (loader, updater, application)
1203 // if n >= 3 we are using a multi-core board un one o more processes
1204 eOuprot_procinfo_t pInfo = (n < maxNumberOfProcessesOnSingleCore) ? binfo.processes.info[n] : binfo.extraprocesses[n];
1205
1206 eo_common_date_to_string(pInfo.date, strdate, sizeof(strdate));
1207 eo_common_date_to_string(pInfo.compilationdate, builton, sizeof(builton));
1208 snprintf(tmp, sizeof(tmp), "\n- proc-%d: \n type: %s \n version: %d.%d, \n dated: %s, \n built on: %s, \n rom: [%d, %d) kb",
1209 n,
1210 eouprot_process2string((eOuprot_process_t)binfo.processes.info[n].type),
1211 pInfo.version.major, pInfo.version.minor,
1212 strdate,
1213 builton,
1214 pInfo.rom_addr_kb, pInfo.rom_addr_kb + pInfo.rom_size_kb
1215 );
1216
1217 info += tmp;
1218
1219 }
1220 info += "\n\n";
1221
1222 return info;
1223}
1224
1225
1226std::string EthMaintainer::getMoreInfoText(eOuprot_cmd_MOREINFO_REPLY_t *moreinfo, char *ipaddr)
1227{
1228 std::string info;
1229
1230 info += "------------------------------\r\n";
1231 info += std::string("Board\t")+std::string(ipaddr);
1232 info += "\r\n\r\n";
1233
1234 if(1 == moreinfo->hasdescription)
1235 {
1236 info += std::string((char*)moreinfo->description);
1237 }
1238 else
1239 {
1240 info += std::string("the message does not have a textual description");
1241 }
1242
1243 return info;
1244}
1245
1246
1247int EthMaintainer::sendPROG2(const uint8_t opc, progData_t &progdata)
1248{
1249 // data can be either a eOuprot_cmd_PROG_DATA_t* or a eOuprot_cmd_PROG_END_t*
1250 // both have the same layout of the opc in first position
1251
1252 if(uprot_OPC_PROG_DATA == opc)
1253 {
1254 bool validFLASHaddress = true;
1255
1256 // add a filter.
1257 // the filter depends on the memory layout of the board.
1258 // for ems, mc4plu, mc2plus valid flash is inside [0x08000000, 0x0800000 + 1MB = 0x08100000)
1259 // for amc and future dual core boards is inside [0x08000000, 0x0800000 + 2MB = 0x08200000)
1260 // so ... either we get the valid flash range from board to board or we get the union of teh two ranges.
1261 // i will be quick and ...
1262 eOuprot_cmd_PROG_DATA_t *pd = reinterpret_cast<eOuprot_cmd_PROG_DATA_t*>(progdata.data);
1263 uint32_t adr = * reinterpret_cast<uint32_t*>(&pd->address[0]); // quick conversion for u32 in little endian
1264 uint16_t siz = * reinterpret_cast<uint16_t*>(&pd->size[0]); // quick conversion for u16 in little endian
1265
1266 if((adr < 0x08000000) || (adr >= 0x08200000) || ((adr+siz) > 0x08200000))
1267 {
1268 validFLASHaddress = false;
1269 printf("EthMaintainer::sendPROG2() detected and filtered out a eOuprot_cmd_PROG_DATA_t w/ non-FLASH chunch of %d bytes in [0x%x, 0x%x]\n" ,
1270 siz, adr, adr+siz);
1271 }
1272
1273 if(false == validFLASHaddress)
1274 {
1275 return 0;
1276 }
1277 }
1278
1279
1280 // use unicast to all selected boards
1281 for(int k=0;k<progdata.selected.size(); k++)
1282 {
1283 mSocket.SendTo(progdata.selected[k]->getIPV4(), myIPV4port, progdata.data, progdata.size);
1284 }
1285
1286
1287 eOipv4addr_t rxipv4addr;
1288 eOipv4port_t rxipv4port;
1289
1290 if(uprot_OPC_PROG_DATA == opc)
1291 {
1292 ++progdata.mNChunks;
1293 }
1294
1295 if(progdata.answers)
1296 {
1297 ++progdata.mNProgSteps;
1298
1299 for (int r=0; r<progdata.retries; ++r)
1300 {
1301 for (int a=0; a<progdata.answers; ++a)
1302 {
1303 if(mSocket.ReceiveFrom(rxipv4addr, rxipv4port, mRxBuffer, sizeof(mRxBuffer), 10) > 0)
1304 {
1305 eOuprot_cmdREPLY_t * reply = (eOuprot_cmdREPLY_t*) mRxBuffer;
1306
1307 if (opc == reply->opc)
1308 {
1309 if (rxipv4addr != myIPV4addr)
1310 {
1311
1312 // search for the ip inside boards2prog. if found then...
1313 for(int i=0; i<progdata.selected.size(); i++)
1314 {
1315 if(rxipv4addr == (progdata.selected[i]->getIPV4()))
1316 {
1317 if (uprot_RES_OK == reply->res)
1318 {
1319 ++(progdata.steps[i]);
1320 }
1321 break;
1322
1323 }
1324 }
1325
1326 if (!--progdata.answers) return 0;
1327 }
1328 }
1329 }
1330 }
1331 }
1332 }
1333
1334 return progdata.answers;
1335}
1336
1338{
1340 return true;
1341}
1342
1343
1344EthBoardList EthMaintainer::discover(bool clearbeforediscovery, int numberofdiscoveries, double waittimeout)
1345{
1346 EthBoardList boardlist;
1347 EthBoardList *list2use = &boardlist;
1349 {
1350 list2use = &_internalboardlist;
1351 }
1352
1353 if(clearbeforediscovery)
1354 {
1355 list2use->clear();
1356 }
1357
1358 const bool forceUpdatingMode = false;
1359 eOuprot_cmd_DISCOVER_t * cmd = (eOuprot_cmd_DISCOVER_t*) mTxBuffer;
1360 memset(cmd, EOUPROT_VALUE_OF_UNUSED_BYTE, sizeof(eOuprot_cmd_DISCOVER_t));
1361 cmd->opc = uprot_OPC_LEGACY_SCAN;
1362 cmd->opc2 = uprot_OPC_DISCOVER;
1363 cmd->jump2updater = (true == forceUpdatingMode) ? (1) : (0);
1364#define ETH_MAINTAINER_DISCOVER_UNICASTMODE
1365 for(int i=0; i<numberofdiscoveries; i++)
1366 {
1367#if defined(ETH_MAINTAINER_DISCOVER_UNICASTMODE)
1368 eOipv4addr_t adr = EO_COMMON_IPV4ADDR(10, 0, 1, 99);
1369 sendCommand(adr, cmd, sizeof(eOuprot_cmd_DISCOVER_t), list2use);
1370 for(int i=1; i<=32; i++)
1371 {
1372 adr = EO_COMMON_IPV4ADDR(10, 0, 1, i);
1373 sendCommand(adr, cmd, sizeof(eOuprot_cmd_DISCOVER_t), list2use);
1374 }
1375#else
1376 sendCommand(ipv4Broadcast, cmd, sizeof(eOuprot_cmd_DISCOVER_t), list2use);
1377#endif
1378
1379 processDiscoveryReplies2(*list2use, waittimeout);
1380 }
1381
1382 return *list2use;
1383}
1384
1385
1387{
1389 return true;
1390}
1391
1392
1397
1398
1400{
1402 return true;
1403}
1404
1405bool EthMaintainer::boards_select(eOipv4addr_t ipv4, bool on)
1406{
1408 return true;
1409}
1410
1411int EthMaintainer::boards_add(eOipv4addr_t ipv4, boardInfo2_t &info2, bool force)
1412{
1413 _internalboardlist.add(info2, ipv4, force);
1414
1415 return _internalboardlist.size();
1416}
1417
1418int EthMaintainer::boards_rem(eOipv4addr_t ipv4)
1419{
1420 _internalboardlist.rem(ipv4);
1421 return _internalboardlist.size();
1422}
1423
1424
1425bool EthMaintainer::command_supported(eOipv4addr_t ipv4, eOuprot_proc_capabilities_t capability, bool ask2board)
1426{
1427 EthBoardList boardlist;
1428 EthBoardList *list2use = &boardlist;
1430 {
1431 list2use = &_internalboardlist;
1432 }
1433
1434 if(ask2board)
1435 {
1436 //boardlist = information(ipv4, true, false, 1, 1.0);
1437 }
1438
1439 vector<EthBoard *> boards = list2use->get(ipv4);
1440
1441 if(0 == boards.size())
1442 {
1443 return false;
1444 }
1445
1446 // i assume it is true. i return true only if all the boards support it.
1447 bool ret = true;
1448 for(int i=0; i<boards.size(); i++)
1449 {
1450 uint32_t mask = boards[i]->getInfo().capabilities;
1451 bool r = ((mask & capability) == capability) ? true : false;
1452 ret = ret && r;
1453 }
1454
1455 return ret;
1456}
1457
1458
1459EthBoardList EthMaintainer::information(eOipv4addr_t ipv4, bool ask2board, bool forcemaintenance, int numberofrequests, double waittimeout)
1460{
1461 EthBoardList boardlist;
1462 EthBoardList *list2use = &boardlist;
1464 {
1465 list2use = &_internalboardlist;
1466 }
1467
1468 if(true == ask2board)
1469 {
1470 // send the command
1471
1472 if(forcemaintenance)
1473 {
1474 go2maintenance(ipv4, true, 6, 1.0);
1475 }
1476
1477 // now we send the info request. we use the uprot_OPC_DISCOVER w/out go2updater
1478
1479 const bool forceUpdatingMode = false;
1480 eOuprot_cmd_DISCOVER_t * cmd = (eOuprot_cmd_DISCOVER_t*) mTxBuffer;
1481 memset(cmd, EOUPROT_VALUE_OF_UNUSED_BYTE, sizeof(eOuprot_cmd_DISCOVER_t));
1482 cmd->opc = uprot_OPC_LEGACY_SCAN;
1483 cmd->opc2 = uprot_OPC_DISCOVER;
1484 cmd->jump2updater = (true == forceUpdatingMode) ? (1) : (0);
1485
1486 for(int i=0; i<numberofrequests; i++)
1487 {
1488 sendCommand(ipv4Broadcast, cmd, sizeof(eOuprot_cmd_DISCOVER_t), list2use);
1489
1490 processDiscoveryReplies2(*list2use, waittimeout);
1491 }
1492 }
1493
1494 // extract from *list2use all the relevant ipv4 ....
1495 EthBoardList ret;
1496
1497 vector<EthBoard *> bb = list2use->get(ipv4);
1498
1499 for(int i=0; i<bb.size(); i++)
1500 { // we add the info and we keep the selection ...
1501 ret.add(bb.at(i)->getInfo(), bb.at(i)->getIPV4());
1502 ret.select(bb.at(i)->isSelected(), bb.at(i)->getIPV4());
1503 }
1504
1505 return ret;
1506}
1507
1508
1509std::string EthMaintainer::moreinformation(eOipv4addr_t ipv4, bool forcemaintenance)
1510{
1511 EthBoardList boardlist;
1512 EthBoardList *list2use = &boardlist;
1514 {
1515 list2use = &_internalboardlist;
1516 }
1517
1518 const bool ask2board = true;
1519 const int numberofrequests = 1;
1520 //double waittimeout = 1.0;
1521 string ret;
1522
1523 if(true == ask2board)
1524 {
1525 // send the command
1526
1527 if(forcemaintenance)
1528 {
1529 go2maintenance(ipv4, true, 6, 1.0);
1530 }
1531
1532 // now we send the info request. we use the uprot_OPC_DISCOVER w/out go2updater
1533
1534 eOuprot_cmd_MOREINFO_t command;
1535
1536 command.opc = uprot_OPC_LEGACY_PROCS;
1537 command.opc2 = uprot_OPC_MOREINFO;
1538 command.plusdescription = 1;
1539 command.jump2updater = 0;
1540
1541 for(int i=0; i<numberofrequests; i++)
1542 {
1543 sendCommand(ipv4, &command, sizeof(command), list2use);
1544
1545 ret += processMoreInfoReplies(*list2use);
1546 }
1547 }
1548
1549 return ret;
1550}
1551
1552bool EthMaintainer::go2maintenance(eOipv4addr_t ipv4, bool verify, int retries, double timegap)
1553{
1554 EthBoardList boardlist;
1555 EthBoardList *list2use = &boardlist;
1557 {
1558 list2use = &_internalboardlist;
1559 }
1560
1561
1562 const bool forceUpdatingMode = true;
1563 eOuprot_cmd_DISCOVER_t command;
1564 memset(&command, EOUPROT_VALUE_OF_UNUSED_BYTE, sizeof(eOuprot_cmd_DISCOVER_t));
1565 command.opc = uprot_OPC_LEGACY_SCAN;
1566 command.opc2 = uprot_OPC_DISCOVER;
1567 command.jump2updater = (true == forceUpdatingMode) ? (1) : (0);
1568
1569 // step 1. we send command and process replies a first time
1570 sendCommand(ipv4, &command, sizeof(command), list2use);
1571 processDiscoveryReplies2(*list2use);
1572
1573
1574 // step 2. must verify that all boards to which we sent the command are in maintenance
1575 if(true == verify)
1576 {
1577 for(int iter=0; iter<retries; iter++)
1578 {
1579 if(isInMaintenance(ipv4, *list2use))
1580 {
1581 if(_verbose)
1582 {
1583 printf("EthMaintainer::go2maintenance() succesfully sent in maintenance board %s after %d attempts\n", ipv4tostring(ipv4).c_str(), iter+1);
1584 }
1585 return true;
1586 }
1587
1588 yarp::os::Time::delay(timegap);
1589
1590 if(_verbose)
1591 {
1592 printf("EthMaintainer::go2maintenance() resent command for the %d-th time to board %s after %f secs\n", iter+1, ipv4tostring(ipv4).c_str(), timegap);
1593 }
1594
1595 // re-send the message and process replies
1596 sendCommand(ipv4, &command, sizeof(command), list2use);
1597 processDiscoveryReplies2(*list2use);
1598 }
1599
1600 }
1601
1602 bool ret = isInMaintenance(ipv4, *list2use);
1603
1604 if(_verbose)
1605 {
1606 if(ret)
1607 {
1608 printf("EthMaintainer::go2maintenance() succesfully sent in maintenance board %s after %d retries\n", ipv4tostring(ipv4).c_str(), retries);
1609 }
1610 else
1611 {
1612 printf("EthMaintainer::go2maintenance() could not send in maintenance board %s even after %d retries\n", ipv4tostring(ipv4).c_str(), retries);
1613 }
1614 }
1615
1616 return ret;
1617}
1618
1619
1620bool EthMaintainer::go2application(eOipv4addr_t ipv4, bool checkdef2runapplication, double bootstraptime, bool verify)
1621{
1622 bool ret = false;
1623
1624 EthBoardList boardlist = information(ipv4, true, false, 2, 1.0);
1625 vector<EthBoard *> pboards;
1626
1627 // check if the application is running and ifde2run is application.
1628 // if ok we do nothing.
1629 // else ...
1630
1631 bool forcemaintainance = false;
1632 bool forcedef2runapplication = false;
1633
1634 if(true == isInApplication(ipv4, boardlist))
1635 {
1636 if(checkdef2runapplication)
1637 {
1638 // must verify for all the boards
1639 pboards = boardlist.get(ipv4);
1640 for(int i=0; i<pboards.size(); i++)
1641 {
1642 boardInfo2_t info = pboards[i]->getInfo();
1643 if(eApplication != info.processes.def2run)
1644 {
1645 forcemaintainance = true;
1646 forcedef2runapplication = true;
1647 break;
1648 }
1649 }
1650
1651 if((false == forcemaintainance) && (false == forcedef2runapplication))
1652 {
1653 return true;
1654 }
1655 }
1656 }
1657
1658 // if in here ... i send them all in maintenance anyway
1659 if(false == go2maintenance(ipv4))
1660 {
1661 if(_verbose)
1662 {
1663 printf("EthMaintainer::go2application() has called go2maintenance() which has failed for board %s.\n", ipv4tostring(ipv4).c_str());
1664 fflush(stdout);
1665 }
1666 return false;
1667 }
1668
1669 // and i set the def2run anyway ...
1670
1671 if(false == command_def2run(ipv4, eApplication, false, true))
1672 {
1673 if(_verbose)
1674 {
1675 printf("EthMaintainer::go2application() has called command_def2run() which has failed for board %s.\n", ipv4tostring(ipv4).c_str());
1676 fflush(stdout);
1677 }
1678 return false;
1679 }
1680
1681
1682 // now we are ok to send a restart, wait for some seconds, discover, check ...
1683 command_restart(ipv4);
1684
1685 yarp::os::Time::delay(bootstraptime);
1686
1687 if(!verify)
1688 {
1689 return true;
1690 }
1691
1692 boardlist = information(ipv4, true, false, 2, 1.0);
1693
1694 ret = isInApplication(ipv4, boardlist);
1695
1696 if(false == ret)
1697 {
1698 pboards = boardlist.get(ipv4);
1699 if(pboards.empty())
1700 {
1701 if(_verbose)
1702 {
1703 printf("EthMaintainer::go2application(): could not find any board %s after restart and wait of %f seconds \n", ipv4tostring(ipv4).c_str(), bootstraptime);
1704 }
1705 return false;
1706 }
1707 else
1708 {
1709 if(_verbose)
1710 {
1711 printf("EthMaintainer::go2application(): some boards %s are not in eApplication after restart and wait of %f seconds:\n", ipv4tostring(ipv4).c_str(), bootstraptime);
1712 for(int i=0; i<pboards.size(); i++)
1713 {
1714 boardInfo2_t info = pboards[i]->getInfo();
1715 printf("- board %s is in %s\n", pboards[i]->getIPV4string().c_str(), eouprot_process2string((eOuprot_process_t)info.processes.runningnow));
1716 }
1717 }
1718 }
1719 }
1720
1721
1722 return ret;
1723}
1724
1725
1726
1727bool EthMaintainer::program(eOipv4addr_t ipv4, eObrd_ethtype_t type, eOuprot_process_t process, eOversion_t targetversion, FILE *fp, bool forcemaintenance, void progress(float), bool restart2application)
1728{
1729 bool ret = false;
1730 string ipv4string = ipv4tostring(ipv4);
1731 const char *targetboardtext = eoboards_type2string2(eoboards_ethtype2type(type), eobool_true);
1732
1733 bool checkversion = (0 == (targetversion.major+targetversion.minor)) ? false : true;
1734 bool checktype = ((eobrd_ethtype_none == type) || (eobrd_ethtype_unknown == type)) ? false : true;
1735
1736 if(NULL == fp)
1737 {
1738 if(_verbose)
1739 {
1740 printf("ERROR: EthMaintainer::program() could not open the file with the binary code.\n");
1741 }
1742 return false;
1743 }
1744
1745 EthBoardList boardlist;
1746 vector<EthBoard *> pboards;
1747
1748
1749 if(_verbose)
1750 {
1751 printf("\nEthMaintainer::program() is about to program the board @ %s of type %s with an %s.\n", ipv4string.c_str(), targetboardtext, eouprot_process2string(process));
1752 }
1753
1754 if(eUpdater == process)
1755 {
1756 if(_verbose)
1757 {
1758 printf("EthMaintainer::program(): is forcing restart2application = false\n");
1759 }
1760 restart2application = false;
1761 }
1762
1763
1764 // check the address
1765 if(ipv4 == ipv4Broadcast)
1766 {
1767 if(_verbose)
1768 {
1769 printf("\nERROR: EthMaintainer::program() cannot program the board @ %s because address is invalid.\n", ipv4string.c_str());
1770 }
1771 return false;
1772 }
1773
1774
1775 if(forcemaintenance)
1776 {
1777 if(_verbose)
1778 {
1779 printf("\nEthMaintainer::program() is about to send the board @ %s in maintenance.\n", ipv4string.c_str());
1780 }
1781 // i send the board in maintenance.
1782 const bool verify = true;
1783 if(false == go2maintenance(ipv4, verify, 6, 1.0))
1784 {
1785 if(_verbose)
1786 {
1787 printf("ERROR: EthMaintainer::program() cannot send the board @ %s in maintenance.\n", ipv4string.c_str());
1788 }
1789 return false;
1790 }
1791 }
1792
1793 // i need its info ...
1794 const bool forcemaintenance4information = false;
1795 boardlist = information(ipv4, true, forcemaintenance4information, 2, 1.0);
1796
1797 pboards = boardlist.get(ipv4Broadcast); // i get all the boards ....
1798
1799 uint8_t nboards = pboards.size();
1800
1801 if(_verbose)
1802 {
1803 printf("WARNING: EthMaintainer::program() has found %d boards @ %s.\n", (int)nboards, ipv4string.c_str());
1804 }
1805
1806
1807 for(int i=0; i<nboards; i++)
1808 {
1809 boardInfo2_t boardinfo = pboards.at(i)->getInfo();
1810
1811 const char *found = eoboards_type2string2(eoboards_ethtype2type(boardinfo.boardtype), eobool_true);
1812
1813 if(_verbose)
1814 {
1815 printf("- board %d of %d: %s\n", i+1, nboards, pboards.at(i)->getIPV4string().c_str());
1816 }
1817
1818 if(checktype)
1819 {
1820 // do the check
1821 if((eobrd_ethtype_unknown == boardinfo.boardtype) || (eobrd_ethtype_none == boardinfo.boardtype))
1822 {
1823 if(_verbose)
1824 printf("WARNING: EthMaintainer::program() has found @ %s: type %s and not %s as wanted.\n", pboards.at(i)->getIPV4string().c_str(), found, targetboardtext);
1825 }
1826 else if(type != boardinfo.boardtype)
1827 {
1828 if(_verbose)
1829 {
1830 printf("ERROR: EthMaintainer::program() has found @ %s: type %s and not %s as wanted.\n", pboards.at(i)->getIPV4string().c_str(), found, targetboardtext);
1831 }
1832 return false;
1833 }
1834 }
1835
1836 switch(process)
1837 {
1838 case eUpdater:
1839 {
1840 if(eApplPROGupdater == boardinfo.processes.runningnow)
1841 {
1842 }
1843 else
1844 {
1845 if(_verbose)
1846 {
1847 const char *runningprocess = eouprot_process2string((eOuprot_process_t)boardinfo.processes.runningnow);
1848 printf("ERROR: EthMaintainer::program() has found @ %s: %s is running and not the eApplPROGupdater as needed to program a %s.\n",
1849 pboards.at(i)->getIPV4string().c_str(), runningprocess, eouprot_process2string(process));
1850 }
1851 return false;
1852 }
1853 } break;
1854
1855 default:
1856 {
1857 if(eUpdater == boardinfo.processes.runningnow)
1858 {
1859 }
1860 else
1861 {
1862 if(_verbose)
1863 {
1864 const char *runningprocess = eouprot_process2string((eOuprot_process_t)boardinfo.processes.runningnow);
1865 printf("ERROR: EthMaintainer::program() has found @ %s: %s is running and not the eUpdater as needed to program a %s.\n",
1866 pboards.at(i)->getIPV4string().c_str(), runningprocess, eouprot_process2string(process));
1867 }
1868 return false;
1869 }
1870 } break;
1871 }
1872
1873 }
1874
1875
1876
1877 string result;
1878 eOuprot_partition2prog_t partition = uprot_partitionAPPLICATION;
1879 switch(process)
1880 {
1881 case eLoader:
1882 {
1883 partition = uprot_partitionLOADER;
1884 } break;
1885
1886 case eApplPROGupdater:
1887 case eApplication:
1888 {
1889 partition = uprot_partitionAPPLICATION;
1890 } break;
1891
1892 case eUpdater:
1893 {
1894 partition = uprot_partitionUPDATER;
1895 } break;
1896
1897 default:
1898 {
1899 partition = uprot_partitionAPPLICATION;
1900 } break;
1901 };
1902
1903
1904 // we program the boards .......
1905 ret = command_program(ipv4, fp, partition, progress, &boardlist, result);
1906
1907
1908 if(false == ret)
1909 {
1910 if(_verbose)
1911 {
1912 //TBD sepcify which board fails
1913 // see https://github.com/robotology/icub-main/issues/945
1914 printf("KO: EthMaintainer::program() could not program some of these boards:\n");
1915 for(int i=0; i<pboards.size(); i++)
1916 {
1917 boardInfo2_t boardinfo = pboards.at(i)->getInfo();
1918 printf("board %s @ %s.\n",
1919 eoboards_type2string2(eoboards_ethtype2type(boardinfo.boardtype), eobool_true),
1920 pboards.at(i)->_ipv4string.c_str());
1921 }
1922 }
1923 return false;
1924 }
1925
1926
1927 if(_verbose)
1928 {
1929
1930 for(int i=0; i<pboards.size(); i++)
1931 {
1932 //list of programmed boards
1933 // see https://github.com/robotology/icub-main/pull/944
1934 boardInfo2_t boardinfo = pboards.at(i)->getInfo();
1935 printf("OK: EthMaintainer::program() has succesfully programmed board %s @ %s.\n",
1936 eoboards_type2string2(eoboards_ethtype2type(boardinfo.boardtype), eobool_true),
1937 pboards.at(i)->_ipv4string.c_str());
1938 }
1939 }
1940
1941
1942 if(checkversion)
1943 {
1944 // i verify the version
1945
1946 if(_verbose)
1947 {
1948 printf("EthMaintainer::program() will now verify if target version matches w/ programmed version.\n");
1949 }
1950
1951 boardlist = information(ipv4, true, false, 2, 1.0);
1952 pboards = boardlist.get(ipv4Broadcast); // i get them all ...
1953
1954 if(nboards != pboards.size())
1955 {
1956 if(_verbose)
1957 {
1958 printf("WARNING: there were %d boards and there are %d now...\n", (int)nboards, (int)boardlist.size());
1959 }
1960 }
1961
1962 for(int i=0; i<pboards.size(); i++)
1963 {
1964
1965 boardInfo2_t boardinfo = pboards.at(i)->getInfo();
1966
1967 uint8_t index = eouprot_process2index(process);
1968 eOuprot_procinfo_t procinfo = boardinfo.processes.info[index];
1969 char datestr[32];
1970 eo_common_date_to_string(procinfo.date, datestr, sizeof(datestr));
1971
1972 if((procinfo.version.major != targetversion.major) || (procinfo.version.minor != targetversion.minor))
1973 {
1974 if(_verbose)
1975 {
1976 printf("\nWARNING: EthMaintainer::program() found an unexpected version for board %s: instead of %d.%d, there is %d.%d dated %s:\n",
1977 pboards.at(i)->getIPV4string().c_str(),
1978 targetversion.major, targetversion.minor,
1979 procinfo.version.major, procinfo.version.minor,
1980 datestr
1981 );
1982 }
1983 }
1984
1985
1986 if(_verbose)
1987 {
1988 printf("\nOK: EthMaintainer::program() has succesfully verified that board @ %s contains a %s w/ v = (%d.%d) dated %s\n",
1989 pboards.at(i)->getIPV4string().c_str(),
1990 eouprot_process2string(process),
1991 procinfo.version.major, procinfo.version.minor,
1992 datestr
1993 );
1994 fflush(stdout);
1995 }
1996 }
1997 }
1998
1999 ret = true;
2000
2001 if(restart2application)
2002 {
2003 ret = go2application(ipv4, true, 10, true);
2004 }
2005
2006 return ret;
2007}
2008
2009
2010bool EthMaintainer::command_def2run(eOipv4addr_t ipv4, eOuprot_process_t process, bool forcemaintenance, bool verify)
2011{
2012 EthBoardList boardlist;
2013 EthBoardList *list2use = &boardlist;
2015 {
2016 list2use = &_internalboardlist;
2017 }
2018
2019 if(forcemaintenance)
2020 {
2021 if(false == go2maintenance(ipv4, true, 6, 1.0))
2022 {
2023 if(_verbose)
2024 {
2025 printf("EthMaintainer::command_def2run(): cannot send the boards to maintenance.\n");
2026 }
2027 return false;
2028 }
2029 }
2030
2031 // send the command
2032
2033 eOuprot_cmd_DEF2RUN_t command = {EOUPROT_VALUE_OF_UNUSED_BYTE};
2034 command.opc = uprot_OPC_DEF2RUN;
2035 command.proc = process;
2036
2037 sendCommand(ipv4, &command, sizeof(command), list2use);
2038
2039 if(!verify)
2040 {
2041 return true;
2042 }
2043
2044 // discover again and check
2045
2046 boardlist = information(ipv4, true, false, 2, 1.0);
2047
2048 vector<EthBoard *> boards = boardlist.get(ipv4);
2049 if(0 == boards.size())
2050 {
2051 if(_verbose)
2052 {
2053 printf("EthMaintainer::command_def2run(): found no boards in verify step.\n");
2054 }
2055 return false;
2056 }
2057
2058 bool ret = true;
2059 for(int i=0; i< boards.size(); i++)
2060 {
2061 boardInfo2_t info = boards[i]->getInfo();
2062 if(process != info.processes.def2run)
2063 {
2064 if(0 != info.protversion)
2065 {
2066 if(_verbose)
2067 {
2068 printf("EthMaintainer::command_def2run(): could not set DEF2RUN = %s for board %s. detected value is %s",
2069 eouprot_process2string(process),
2070 boards[i]->getIPV4string().c_str(), eouprot_process2string((eOuprot_process_t)info.processes.def2run)
2071 );
2072 }
2073 ret = false;
2074 }
2075 else
2076 {
2077 printf("EthMaintainer::command_def2run(): could not check DEF2RUN = %s for board %s beacuse protocolversion is 0",
2078 eouprot_process2string(process),
2079 boards[i]->getIPV4string().c_str()
2080 );
2081 }
2082
2083 }
2084 }
2085
2086 return ret;
2087}
2088
2089
2090bool EthMaintainer::command_restart(eOipv4addr_t ipv4)
2091{
2092 EthBoardList boardlist;
2093 EthBoardList *list2use = &boardlist;
2095 {
2096 list2use = &_internalboardlist;
2097 }
2098
2099 eOuprot_cmd_RESTART_t command = {EOUPROT_VALUE_OF_UNUSED_BYTE};
2100 command.opc = uprot_OPC_RESTART;
2101
2102 bool ret = sendCommand(ipv4, &command, sizeof(command), list2use);
2103
2104 if(_verbose)
2105 {
2106 printf("EthMaintainer::command_restart(%s): %d\n", ipv4tostring(ipv4).c_str(), ret);
2107 }
2108
2109 return ret;
2110}
2111
2112
2113
2114bool EthMaintainer::command_changeaddress(eOipv4addr_t ipv4, eOipv4addr_t ipv4new, bool checkifnewispresent, bool forcemaintenance, bool restart, bool verify)
2115{
2116 EthBoardList boardlist;
2117 EthBoardList *list2use = &boardlist;
2119 {
2120 list2use = &_internalboardlist;
2121 }
2122
2123 bool ret = false;
2124
2125 eOuprot_cmd_IP_ADDR_SET_t command = {EOUPROT_VALUE_OF_UNUSED_BYTE};
2126
2127 command.opc = uprot_OPC_LEGACY_IP_ADDR_SET;
2128 command.opc2 = uprot_OPC_IP_ADDR_SET;
2129 command.sysrestart = 0; //(restart) ? (1) : (0);
2130
2131 command.address[3] = (ipv4new>>24) & 0xFF;
2132 command.address[2] = (ipv4new>>16) & 0xFF;
2133 command.address[1] = (ipv4new>>8 ) & 0xFF;
2134 command.address[0] = (ipv4new ) & 0xFF;
2135
2136
2137 string ipv4string = ipv4tostring(ipv4);
2138 string ipv4newstring = ipv4tostring(ipv4new);
2139
2140
2141 bool stopit = false;
2142
2143 if(0 == ipv4)
2144 {
2145 stopit = true;
2146 }
2147
2148 // 09/2020 davide.tome@iit.it - possible to give 10.X.X.X IP address
2149 if(!((10 == command.address[0]) || (0 < command.address[1] < 255) || (0 < command.address[2] < 255) || (0 < command.address[3] < 255)))
2150 {
2151 stopit = true;
2152 }
2153
2154 if(true == stopit)
2155 {
2156 if(_verbose)
2157 {
2158 printf("EthMaintainer::command_changeaddress(): cannot send command uprot_OPC_IP_ADDR_SET to %s with new address %s because either one or both are not valid\n", ipv4string.c_str(), ipv4newstring.c_str());
2159 }
2160
2161 return ret;
2162 }
2163
2164 if(checkifnewispresent)
2165 { // ipv4 cannot be 0 ...
2166 boardlist = information(ipv4new, true, false, 1, 1.0);
2167 if(0 != boardlist.numberof(ipv4new))
2168 {
2169 if(_verbose)
2170 {
2171 printf("EthMaintainer::command_changeaddress(): cannot send command uprot_OPC_IP_ADDR_SET to %s with new address %s because the new address is already present\n", ipv4string.c_str(), ipv4newstring.c_str());
2172 }
2173
2174 return false;
2175 }
2176 else
2177 {
2178 if(_verbose)
2179 {
2180 printf("EthMaintainer::command_changeaddress(): new address %s is not present\n", ipv4newstring.c_str());
2181 }
2182 }
2183 }
2184
2185 if(forcemaintenance)
2186 {
2187 bool r1 = go2maintenance(ipv4, true, 6, 1.0);
2188
2189 if(false == r1)
2190 {
2191 if(_verbose)
2192 {
2193 printf("EthMaintainer::command_changeaddress(): failed to send %s in maintenance\n", ipv4newstring.c_str());
2194 }
2195 return false;
2196 }
2197 else
2198 {
2199 if(_verbose)
2200 {
2201 printf("EthMaintainer::command_changeaddress(): succesfully sent %s in maintenance\n", ipv4newstring.c_str());
2202 }
2203 }
2204
2205 }
2206
2207
2208 if(_verbose)
2209 {
2210 printf("EthMaintainer::command_changeaddress(): sent command uprot_OPC_IP_ADDR_SET to %s, new address is %s. w/%s sysrestart\n", ipv4string.c_str(), ipv4newstring.c_str(), (0 == command.sysrestart) ? "out" : "");
2211 }
2212
2213 bool r = sendCommand(ipv4, &command, sizeof(command), list2use);
2214
2215 if(false == r)
2216 {
2217 if(_verbose)
2218 {
2219 printf("EthMaintainer::command_changeaddress(): could not send command\n");
2220 }
2221 }
2222
2223 if(true == restart)
2224 {
2225 bool rr = command_restart(ipv4);
2226 if(_verbose)
2227 {
2228 printf("EthMaintainer::command_changeaddress(): called command_restart() w/ res %d\n", rr);
2229 }
2230 }
2231
2232 if(true == verify)
2233 { // cannot verify if we dont restart.
2234 verify = restart;
2235 }
2236
2237
2238 if(false == verify)
2239 {
2240 return true;
2241 }
2242
2243 // we verify ....
2244
2245 // must wait a tick ... maybe 500 ms and then i run a discovery on the new address.
2246 yarp::os::Time::delay(1.000);
2247
2248
2249 ret = go2maintenance(ipv4new, true, 5, 0.5);
2250
2251 if(_verbose)
2252 {
2253 printf("EthMaintainer::command_changeaddress(): board w/ new address %s is in maintenance: %s\n", ipv4newstring.c_str(), ret ? "YES" : "NO!");
2254 }
2255
2256 if(false == ret)
2257 {
2258 return false;
2259 }
2260
2261
2262 boardlist = information(ipv4new, true, false, 1, 1.0);
2263
2264 if(0 == boardlist.numberof(ipv4new))
2265 {
2266 if(_verbose)
2267 {
2268 printf("EthMaintainer::command_changeaddress(): error: we dont have the new address %s ...\n", ipv4newstring.c_str());
2269 }
2270 return false;
2271 }
2272
2273 if(_verbose)
2274 {
2275 printf("EthMaintainer::command_changeaddress(): OK\n");
2276 }
2277
2278 return true;
2279}
2280
2281
2283{
2284 EthBoardList boardlist;
2285 EthBoardList *list2use = &boardlist;
2287 {
2288 list2use = &_internalboardlist;
2289 }
2290
2291 bool ret = true;
2292
2293 eOuprot_cmd_PAGE_CLR_t command = {EOUPROT_VALUE_OF_UNUSED_BYTE};
2294 command.opc = uprot_OPC_PAGE_CLR;
2295 command.pagesize = 32;
2296
2297 ret = sendCommand(ipv4, &command, sizeof(command), list2use);
2298
2299 return ret;
2300}
2301
2302
2303bool EthMaintainer::command_info32_set(eOipv4addr_t ipv4, const string &info32)
2304{
2305 EthBoardList boardlist;
2306 EthBoardList *list2use = &boardlist;
2308 {
2309 list2use = &_internalboardlist;
2310 }
2311
2312 bool ret = true;
2313
2314 eOuprot_cmd_PAGE_SET_t *cmd = (eOuprot_cmd_PAGE_SET_t*) mTxBuffer;
2315 uint16_t sizeofcmd = sizeof(eOuprot_cmd_PAGE_SET_t) - uprot_pagemaxsize + 32;
2316 // think of the best way to specify the length of themessage in a proper way
2317 // we could decide to send always a length of sizeof(eOuprot_cmd_PAGE_SET_t) which is 132, or ...
2318
2319 memset(cmd, EOUPROT_VALUE_OF_UNUSED_BYTE, sizeofcmd);
2320
2321 cmd->opc = uprot_OPC_PAGE_SET;
2322 cmd->pagesize = 32;
2323 memset(cmd->page, 0, 32);
2324
2325
2326 const char * str32 = info32.c_str();
2327
2328 int len = strlen(str32);
2329 if(len>30)
2330 {
2331 len = 30;
2332 }
2333 cmd->page[0] = len;
2334 memcpy(&cmd->page[1], str32, len);
2335
2336 ret = sendCommand(ipv4, cmd, sizeofcmd, list2use);
2337
2338 return ret;
2339}
2340
2341
2342vector<string> EthMaintainer::command_info32_get(eOipv4addr_t ipv4)
2343{
2344 EthBoardList boardlist;
2345 EthBoardList *list2use = &boardlist;
2347 {
2348 list2use = &_internalboardlist;
2349 }
2350
2351 vector<string> thestrings(0);
2352
2353 eOuprot_cmd_PAGE_GET_t command = {EOUPROT_VALUE_OF_UNUSED_BYTE};
2354 command.opc = uprot_OPC_PAGE_GET;
2355 command.pagesize = 32;
2356
2357 bool r = sendCommand(ipv4, &command, sizeof(command), list2use);
2358
2359 eOipv4addr_t rxipv4addr;
2360 eOipv4port_t rxipv4port;
2361
2362 while(mSocket.ReceiveFrom(rxipv4addr, rxipv4port, mRxBuffer, sizeof(mRxBuffer), 500) > 0)
2363 {
2364 eOuprot_cmd_PAGE_GET_REPLY_t * pageget = (eOuprot_cmd_PAGE_GET_REPLY_t*) mRxBuffer;
2365
2366 string ipv4rxstring = ipv4tostring(rxipv4addr);
2367
2368 if(uprot_OPC_PAGE_GET == pageget->reply.opc)
2369 {
2370 string readstring;
2371
2372 if((rxipv4addr != myIPV4addr) && (uprot_RES_OK == pageget->reply.res) && (32 == pageget->pagesize) && (0xff != pageget->page[0]))
2373 {
2374 readstring = string((const char*)&pageget->page[1]);
2375 thestrings.push_back(readstring);
2376 // and update what in boardinfo32
2377 vector<EthBoard *> selected = _internalboardlist.get(rxipv4addr);
2378 for(int i=0; i<selected.size(); i++)
2379 {
2380 boardInfo2_t & binfo = selected[i]->getInfo();
2381 memcpy(binfo.boardinfo32, pageget->page, sizeof(binfo.boardinfo32));
2382 }
2383 }
2384
2385 if(_verbose)
2386 {
2387 if(uprot_RES_OK != pageget->reply.res)
2388 {
2389 printf("\n received a eOuprot_cmd_PAGE_GET_REPLY_t from IP %s with a failure result %d for size %d", ipv4rxstring.c_str(), pageget->reply.res, pageget->pagesize);
2390 }
2391 else if(rxipv4addr != myIPV4addr)
2392 {
2393 printf("\n received a eOuprot_cmd_PAGE_GET_REPLY_t from IP %s with size %d: ", ipv4rxstring.c_str(), pageget->pagesize);
2394
2395 if(32 == pageget->pagesize)
2396 { // the page is formatted so that in position 0 there is 0xff if erased and never programmed or strlen(&page[1])
2397
2398 uint8_t info32[32] = {0};
2399 memcpy(info32, pageget->page, 32);
2400
2401 if(0xff == info32[0])
2402 {
2403 printf("\n stored info32 is .. ");
2404 for(int m=0; m<32; m++)
2405 {
2406 printf("0x%x ", info32[m]);
2407 }
2408
2409 }
2410 else
2411 {
2412 printf("l = %d, string = %s \n", info32[0], &info32[1]);
2413 }
2414
2415 }
2416
2417 fflush(stdout);
2418 }
2419 }
2420
2421 }
2422 }
2423
2424 return thestrings;
2425}
2426
2427
2429{
2430 EthBoardList boardlist;
2431 EthBoardList *list2use = &boardlist;
2433 {
2434 list2use = &_internalboardlist;
2435 }
2436
2437 bool ret = true;
2438
2439 eOuprot_cmd_JUMP2UPDATER_t command = {EOUPROT_VALUE_OF_UNUSED_BYTE};
2440 command.opc = uprot_OPC_JUMP2UPDATER;
2441
2442 ret = sendCommand(ipv4, &command, sizeof(command), list2use);
2443
2444 return ret;
2445}
2446
2447
2448
2449bool EthMaintainer::command_jump2address(eOipv4addr_t ipv4, uint32_t romaddress)
2450{
2451 EthBoardList boardlist;
2452 EthBoardList *list2use = &boardlist;
2454 {
2455 list2use = &_internalboardlist;
2456 }
2457
2458 bool ret = true;
2459
2460 eOuprot_cmd_JUMP2ADDRESS_t command = {EOUPROT_VALUE_OF_UNUSED_BYTE};
2461 command.opc = uprot_OPC_JUMP2ADDRESS;
2462 command.address = romaddress;
2463
2464 ret = sendCommand(ipv4, &command, sizeof(command), list2use);
2465
2466 return ret;
2467}
2468
2469
2470bool EthMaintainer::command_blink(eOipv4addr_t ipv4)
2471{
2472 EthBoardList boardlist;
2473 EthBoardList *list2use = &boardlist;
2475 {
2476 list2use = &_internalboardlist;
2477 }
2478
2479 bool ret = true;
2480
2481 eOuprot_cmd_BLINK_t command = {EOUPROT_VALUE_OF_UNUSED_BYTE};
2482 command.opc = uprot_OPC_BLINK;
2483
2484 ret = sendCommand(ipv4, &command, sizeof(command), list2use);
2485
2486 return ret;
2487}
2488
2489
2490// eof
2491
2492
2493
string ipv4tostring(eOipv4addr_t ipv4)
eOipv4addr_t acetoipv4(ACE_UINT32 address)
bool string2ipv4(const string &ipv4string, eOipv4addr_t &ipv4)
ACE_UINT32 ipv4toace(eOipv4addr_t ipv4)
string ipv4tostring(eOipv4addr_t ipv4)
void SendTo(eOipv4addr_t ipv4, eOipv4port_t port, void *data, size_t len)
Definition DSocket.cpp:58
bool Create(ACE_UINT16 port, std::string &address)
Definition DSocket.cpp:25
void SendBroad(eOipv4port_t port, void *data, size_t len)
Definition DSocket.cpp:70
ssize_t ReceiveFrom(eOipv4addr_t &ipv4, eOipv4port_t &port, void *data, size_t len, int wait_msec)
Definition DSocket.cpp:116
void Close()
Definition DSocket.cpp:137
vector< EthBoard > theboards
Definition EthBoard.h:132
int numberof(eOipv4addr_t ipv4)
Definition EthBoard.cpp:279
vector< EthBoard * > get(eOipv4addr_t ipv4)
Definition EthBoard.cpp:310
int rem(eOipv4addr_t ipv4)
Definition EthBoard.cpp:239
void select(bool on, eOipv4addr_t ipv4)
Definition EthBoard.cpp:347
int add(boardInfo2_t &info2, eOipv4addr_t ipv4, bool force=false)
Definition EthBoard.cpp:186
unsigned char mRxBuffer[uprot_UDPmaxsize]
bool boards_useinternal(bool on)
static const eOipv4addr_t ipv4Broadcast
std::string moreinformation(eOipv4addr_t ipv4, bool forcemaintenance=false)
std::string getMoreInfoText(eOuprot_cmd_MOREINFO_REPLY_t *moreinfo, char *ipv4string)
EthBoardList information(eOipv4addr_t ipv4, bool ask2board=true, bool forcemaintenance=true, int numberofrequests=1, double waittimeout=1.0)
bool command_jump2updater(eOipv4addr_t ipv4)
EthBoardList discover(bool clearbeforediscovery=true, int numberofdiscoveries=1, double waittimeout=1.0)
static const eOipv4addr_t ipv4OfAllSelected
bool open(eOipv4addr_t ipv4=hostIPaddress, eOipv4port_t port=mainIPport)
bool command_def2run(eOipv4addr_t ipv4, eOuprot_process_t process, bool forcemaintenance=true, bool verify=true)
bool boards_set(EthBoardList &boards)
eOipv4port_t myIPV4port
string processDiscoveryReplies2(EthBoardList &boardlist, double waittimeout=1.0)
int sendPROG2(const uint8_t opc, progData_t &progdata)
bool boards_clr(void)
bool go2application(eOipv4addr_t ipv4, bool checkdef2runapplication=true, double bootstraptime=10.0, bool verify=true)
int boards_rem(eOipv4addr_t ipv4)
EthBoardList & boards_get(void)
void verbose(bool on)
bool boards_select(eOipv4addr_t ipv4, bool on)
bool command_info32_clr(eOipv4addr_t ipv4)
bool isInApplication(eOipv4addr_t ipv4, EthBoardList &boardlist)
bool isInMaintenance(eOipv4addr_t ipv4, EthBoardList &boardlist)
static const eOipv4port_t mainIPport
bool sendCommand(eOipv4addr_t ipv4, void *cmd, uint16_t len, EthBoardList *boardlist=NULL)
void debugprint(bool on)
bool go2maintenance(eOipv4addr_t ipv4, bool verify=true, int retries=6, double timegap=1.0)
bool command_eeprom_read(eOipv4addr_t ipv4, uint16_t from, uint16_t size, uint8_t **value)
std::string processMoreInfoReplies(EthBoardList &boardlist)
bool command_info32_set(eOipv4addr_t ipv4, const string &info32)
vector< string > command_info32_get(eOipv4addr_t ipv4)
std::string prepareMoreInfoText(eOuprot_cmd_DISCOVER_REPLY_t *disc, const char *ipv4string)
EthBoardList _internalboardlist
bool command_blink(eOipv4addr_t ipv4)
int boards_add(eOipv4addr_t ipv4, boardInfo2_t &info2, bool force)
unsigned char mTxBuffer[uprot_UDPmaxsize]
bool program(eOipv4addr_t ipv4, eObrd_ethtype_t type, eOuprot_process_t process, eOversion_t targetversion, FILE *fp, bool forcemaintenance=true, void progress(float)=NULL, bool restart2application=true)
bool command_program(eOipv4addr_t ipv4, FILE *programFile, eOuprot_partition2prog_t partition, void(*updateProgressBar)(float), EthBoardList *pboardlist, string &stringresult)
static const eOipv4addr_t hostIPaddress
eOipv4addr_t myIPV4addr
bool command_eeprom_erase(eOipv4addr_t ipv4)
bool command_restart(eOipv4addr_t ipv4)
bool command_supported(eOipv4addr_t ipv4, eOuprot_proc_capabilities_t capability, bool ask2board=false)
bool command_jump2address(eOipv4addr_t ipv4, uint32_t romaddress)
bool command_changeaddress(eOipv4addr_t ipv4, eOipv4addr_t ipv4new, bool checkifnewispresent=true, bool forcemaintenance=true, bool restart=false, bool verify=false)
bool _useofinternalboardlist
cmd
Definition dataTypes.h:30
int n
static struct bpf_program fp
grid on
vector< EthBoard * > selected
eOversion_t versionOfRunning
Definition EthBoard.h:44
void reset(void)
Definition EthBoard.h:54
eObrd_ethtype_t boardtype
Definition EthBoard.h:38
uint8_t applicationdetails
Definition EthBoard.h:43
uint8_t protversion
Definition EthBoard.h:36
string moreinfostring
Definition EthBoard.h:46
uint8_t boardinfo32[32]
Definition EthBoard.h:41
uint32_t capabilities
Definition EthBoard.h:39
uint64_t macaddress
Definition EthBoard.h:37
eOuprot_procinfo_t extraprocesses[2]
Definition EthBoard.h:47
bool maintenanceIsActive
Definition EthBoard.h:42
eOuprot_proctable_t processes
Definition EthBoard.h:40