iCub-main
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 
28 using namespace yarp::os;
29 
30 string 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 
38 bool 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 
53 eOipv4addr_t acetoipv4(ACE_UINT32 address)
54 {
55  return htonl(address);
56 }
57 
58 
59 ACE_UINT32 ipv4toace(eOipv4addr_t ipv4)
60 {
61  return ntohl(ipv4);
62 }
63 
64 
65 #if defined(WIN32)
66 
67 #else
68 const eOipv4addr_t EthMaintainer::hostIPaddress = EO_COMMON_IPV4ADDR(10, 0, 1, 104);
69 const eOipv4port_t EthMaintainer::mainIPport = 3333;
70 
71 const eOipv4addr_t EthMaintainer::ipv4OfAllSelected = EO_COMMON_IPV4ADDR(0, 0, 0, 0);
72 
73 const 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 
84  _useofinternalboardlist = true;
85 }
86 
88 {
89  close();
90 }
91 
92 
93 
94 bool 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();
119  _internalboardlist.clear();
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 
170 bool EthMaintainer::command_eeprom_erase(eOipv4addr_t ipv4)
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 
188 bool 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 
244 bool 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 
589 bool 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  {
607  mSocket.SendBroad(myIPV4port, cmd, len);
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 
620 bool 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 
641 bool 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 
662 string 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 
1016 std::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 
1118 std::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 
1226 std::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 
1247 int 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 {
1339  _useofinternalboardlist = on;
1340  return true;
1341 }
1342 
1343 
1344 EthBoardList EthMaintainer::discover(bool clearbeforediscovery, int numberofdiscoveries, double waittimeout)
1345 {
1346  EthBoardList boardlist;
1347  EthBoardList *list2use = &boardlist;
1348  if(_useofinternalboardlist)
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 {
1388  _internalboardlist.theboards = boards.theboards;
1389  return true;
1390 }
1391 
1392 
1394 {
1395  return _internalboardlist;
1396 }
1397 
1398 
1400 {
1401  _internalboardlist.clear();
1402  return true;
1403 }
1404 
1405 bool EthMaintainer::boards_select(eOipv4addr_t ipv4, bool on)
1406 {
1407  _internalboardlist.select(on, ipv4);
1408  return true;
1409 }
1410 
1411 int 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 
1418 int EthMaintainer::boards_rem(eOipv4addr_t ipv4)
1419 {
1420  _internalboardlist.rem(ipv4);
1421  return _internalboardlist.size();
1422 }
1423 
1424 
1425 bool EthMaintainer::command_supported(eOipv4addr_t ipv4, eOuprot_proc_capabilities_t capability, bool ask2board)
1426 {
1427  EthBoardList boardlist;
1428  EthBoardList *list2use = &boardlist;
1429  if(_useofinternalboardlist)
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 
1459 EthBoardList EthMaintainer::information(eOipv4addr_t ipv4, bool ask2board, bool forcemaintenance, int numberofrequests, double waittimeout)
1460 {
1461  EthBoardList boardlist;
1462  EthBoardList *list2use = &boardlist;
1463  if(_useofinternalboardlist)
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 
1509 std::string EthMaintainer::moreinformation(eOipv4addr_t ipv4, bool forcemaintenance)
1510 {
1511  EthBoardList boardlist;
1512  EthBoardList *list2use = &boardlist;
1513  if(_useofinternalboardlist)
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 
1552 bool EthMaintainer::go2maintenance(eOipv4addr_t ipv4, bool verify, int retries, double timegap)
1553 {
1554  EthBoardList boardlist;
1555  EthBoardList *list2use = &boardlist;
1556  if(_useofinternalboardlist)
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 
1620 bool 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 
1727 bool 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 
2010 bool EthMaintainer::command_def2run(eOipv4addr_t ipv4, eOuprot_process_t process, bool forcemaintenance, bool verify)
2011 {
2012  EthBoardList boardlist;
2013  EthBoardList *list2use = &boardlist;
2014  if(_useofinternalboardlist)
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 
2090 bool EthMaintainer::command_restart(eOipv4addr_t ipv4)
2091 {
2092  EthBoardList boardlist;
2093  EthBoardList *list2use = &boardlist;
2094  if(_useofinternalboardlist)
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 
2114 bool 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;
2118  if(_useofinternalboardlist)
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 
2282 bool EthMaintainer::command_info32_clr(eOipv4addr_t ipv4)
2283 {
2284  EthBoardList boardlist;
2285  EthBoardList *list2use = &boardlist;
2286  if(_useofinternalboardlist)
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 
2303 bool EthMaintainer::command_info32_set(eOipv4addr_t ipv4, const string &info32)
2304 {
2305  EthBoardList boardlist;
2306  EthBoardList *list2use = &boardlist;
2307  if(_useofinternalboardlist)
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 
2342 vector<string> EthMaintainer::command_info32_get(eOipv4addr_t ipv4)
2343 {
2344  EthBoardList boardlist;
2345  EthBoardList *list2use = &boardlist;
2346  if(_useofinternalboardlist)
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;
2432  if(_useofinternalboardlist)
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 
2449 bool EthMaintainer::command_jump2address(eOipv4addr_t ipv4, uint32_t romaddress)
2450 {
2451  EthBoardList boardlist;
2452  EthBoardList *list2use = &boardlist;
2453  if(_useofinternalboardlist)
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 
2470 bool EthMaintainer::command_blink(eOipv4addr_t ipv4)
2471 {
2472  EthBoardList boardlist;
2473  EthBoardList *list2use = &boardlist;
2474  if(_useofinternalboardlist)
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)
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
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
bool boards_useinternal(bool on)
static const eOipv4addr_t ipv4Broadcast
Definition: EthMaintainer.h:60
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
Definition: EthMaintainer.h:59
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)
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
Definition: EthMaintainer.h:57
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)
bool command_blink(eOipv4addr_t ipv4)
int boards_add(eOipv4addr_t ipv4, boardInfo2_t &info2, bool force)
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
Definition: EthMaintainer.h:56
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)
cmd
Definition: dataTypes.h:30
int n
static struct bpf_program fp
grid on
Definition: show_eyes_axes.m:5
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