plcinit.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685
  1. /*====================================================================*
  2. *
  3. * Copyright (c) 2013 Qualcomm Atheros, Inc.
  4. *
  5. * All rights reserved.
  6. *
  7. *====================================================================*/
  8. /*====================================================================*
  9. *
  10. * plcinit.c -
  11. *
  12. *--------------------------------------------------------------------*/
  13. /*====================================================================*
  14. * system header files;
  15. *--------------------------------------------------------------------*/
  16. #include <unistd.h>
  17. #include <stdlib.h>
  18. #include <stdint.h>
  19. #include <limits.h>
  20. /*====================================================================*
  21. * custom header files;
  22. *--------------------------------------------------------------------*/
  23. #include "../tools/getoptv.h"
  24. #include "../tools/putoptv.h"
  25. #include "../tools/memory.h"
  26. #include "../tools/number.h"
  27. #include "../tools/symbol.h"
  28. #include "../tools/types.h"
  29. #include "../tools/flags.h"
  30. #include "../tools/files.h"
  31. #include "../tools/error.h"
  32. #include "../ether/channel.h"
  33. #include "../key/HPAVKey.h"
  34. #include "../key/keys.h"
  35. #include "../ram/sdram.h"
  36. #include "../pib/pib.h"
  37. #include "../nvm/nvm.h"
  38. #include "../plc/plc.h"
  39. #include "../nda/nda.h"
  40. /*====================================================================*
  41. * custom source files;
  42. *--------------------------------------------------------------------*/
  43. #ifndef MAKEFILE
  44. #include "../plc/Attributes2.c"
  45. #include "../plc/chipset.c"
  46. #include "../plc/Failure.c"
  47. #include "../plc/Devices.c"
  48. #include "../plc/Confirm.c"
  49. #include "../plc/Display.c"
  50. #include "../plc/FlashDevice2.c"
  51. #include "../plc/FlashSoftloader.c"
  52. #include "../plc/FlashFirmware.c"
  53. #include "../plc/FlashParameters.c"
  54. #include "../plc/FlashNVM.c"
  55. #include "../plc/FactoryDefaults.c"
  56. #include "../plc/Identity2.c"
  57. #include "../plc/LinkStatus.c"
  58. #include "../plc/HostActionResponse.c"
  59. #include "../plc/ModuleCommit.c"
  60. #include "../plc/ModuleRead.c"
  61. #include "../plc/ModuleSession.c"
  62. #include "../plc/ModuleSpec.c"
  63. #include "../plc/ModuleWrite.c"
  64. #include "../plc/NetInfo2.c"
  65. #include "../plc/NVRAMInfo.c"
  66. #include "../plc/PushButton.c"
  67. #include "../plc/SetNMK.c"
  68. #include "../plc/Request.c"
  69. #include "../plc/PLCSelect.c"
  70. #include "../plc/ReadFirmware1.c"
  71. #include "../plc/ReadMME.c"
  72. #include "../plc/ReadMFG.c"
  73. #include "../plc/ReadParameters2.c"
  74. #include "../plc/RemoteHosts.c"
  75. #include "../plc/ResetDevice.c"
  76. #include "../plc/SDRAMInfo.c"
  77. #include "../plc/SendMME.c"
  78. #include "../plc/StationRole.c"
  79. #include "../plc/StartFirmware1.c"
  80. #include "../plc/VersionInfo2.c"
  81. #include "../plc/WaitForReset.c"
  82. #include "../plc/WaitForStart.c"
  83. #include "../plc/WaitForRestart.c"
  84. #include "../plc/WatchdogReport.c"
  85. #include "../plc/WritePIB.c"
  86. #include "../plc/WriteNVM.c"
  87. #endif
  88. #ifndef MAKEFILE
  89. #include "../tools/error.c"
  90. #include "../tools/getoptv.c"
  91. #include "../tools/putoptv.c"
  92. #include "../tools/synonym.c"
  93. #include "../tools/uintspec.c"
  94. #include "../tools/basespec.c"
  95. #include "../tools/version.c"
  96. #include "../tools/hexdump.c"
  97. #include "../tools/hexencode.c"
  98. #include "../tools/hexdecode.c"
  99. #include "../tools/hexstring.c"
  100. #include "../tools/hexout.c"
  101. #include "../tools/todigit.c"
  102. #include "../tools/checkfilename.c"
  103. #include "../tools/checksum32.c"
  104. #include "../tools/fdchecksum32.c"
  105. #include "../tools/strfbits.c"
  106. #include "../tools/typename.c"
  107. #endif
  108. #ifndef MAKEFILE
  109. #include "../ether/openchannel.c"
  110. #include "../ether/closechannel.c"
  111. #include "../ether/readpacket.c"
  112. #include "../ether/sendpacket.c"
  113. #include "../ether/channel.c"
  114. #endif
  115. #ifndef MAKEFILE
  116. #include "../nda/EraseFlashSector.c"
  117. #include "../nda/EraseFlashMemory2.c"
  118. #include "../nda/ReadFlashMemory2.c"
  119. #include "../nda/ModuleErase.c"
  120. #include "../nda/AccessLevelPTS.c"
  121. #endif
  122. #ifndef MAKEFILE
  123. #include "../ram/nvram.c"
  124. #include "../ram/sdramfile.c"
  125. #include "../ram/sdrampeek.c"
  126. #endif
  127. #ifndef MAKEFILE
  128. #include "../nvm/panther_nvm_file.c"
  129. #endif
  130. #ifndef MAKEFILE
  131. #include "../pib/panther_pib_file.c"
  132. #include "../pib/panther_pib_peek.c"
  133. #endif
  134. #ifndef MAKEFILE
  135. #include "../mme/EthernetHeader.c"
  136. #include "../mme/QualcommHeader.c"
  137. #include "../mme/QualcommHeader1.c"
  138. #include "../mme/UnwantedMessage.c"
  139. #include "../mme/MMECode.c"
  140. #endif
  141. #ifndef MAKEFILE
  142. #include "../key/keys.c"
  143. #endif
  144. /*====================================================================*
  145. * program constants;
  146. *--------------------------------------------------------------------*/
  147. #define DEFAULT_LOOP 1
  148. #define DEFAULT_WAIT 0
  149. /*====================================================================*
  150. * program variables;
  151. *--------------------------------------------------------------------*/
  152. static const struct _term_ buttons [] =
  153. {
  154. {
  155. "join",
  156. "1"
  157. },
  158. {
  159. "leave",
  160. "2"
  161. },
  162. {
  163. "reset",
  164. "4"
  165. },
  166. {
  167. "status",
  168. "3"
  169. }
  170. };
  171. /*====================================================================*
  172. *
  173. * void manager (struct plc * plc, signed count, signed pause);
  174. *
  175. * perform operations in logical order despite any order specfied
  176. * on the command line; for example read PIB before writing PIB;
  177. *
  178. * operation order is controlled by the order of "if" statements
  179. * shown here; the entire operation sequence can be repeated with
  180. * an optional pause between each iteration;
  181. *
  182. *--------------------------------------------------------------------*/
  183. static void manager (struct plc * plc, signed count, signed pause)
  184. {
  185. while (count--)
  186. {
  187. if (_anyset (plc->flags, PLC_LINK_STATUS))
  188. {
  189. LinkStatus (plc);
  190. }
  191. if (_anyset (plc->flags, PLC_VERSION))
  192. {
  193. VersionInfo2 (plc);
  194. }
  195. if (_anyset (plc->flags, PLC_ATTRIBUTES))
  196. {
  197. Attributes2 (plc);
  198. }
  199. if (_anyset (plc->flags, PLC_WATCHDOG_REPORT))
  200. {
  201. WatchdogReport (plc);
  202. }
  203. if (_anyset (plc->flags, PLC_NVRAM_INFO))
  204. {
  205. NVRAMInfo (plc);
  206. }
  207. if (_anyset (plc->flags, PLC_SDRAM_INFO))
  208. {
  209. SDRAMInfo (plc);
  210. }
  211. if (_anyset (plc->flags, PLC_READ_IDENTITY))
  212. {
  213. Identity2 (plc);
  214. }
  215. if (_anyset (plc->flags, PLC_REMOTEHOSTS))
  216. {
  217. RemoteHosts (plc);
  218. }
  219. if (_anyset (plc->flags, PLC_NETWORK))
  220. {
  221. NetInfo2 (plc);
  222. }
  223. if (_anyset (plc->flags, PLC_HOST_ACTION))
  224. {
  225. HostActionResponse (plc);
  226. }
  227. if (_anyset (plc->flags, PLC_PUSH_BUTTON))
  228. {
  229. PushButton (plc);
  230. }
  231. if (_anyset (plc->flags, PLC_FACTORY_DEFAULTS))
  232. {
  233. FactoryDefaults (plc);
  234. }
  235. if (_anyset (plc->flags, (PLC_SETLOCALKEY | PLC_SETREMOTEKEY)))
  236. {
  237. SetNMK (plc);
  238. }
  239. if (_anyset (plc->flags, PLC_READ_PIB))
  240. {
  241. if (AccessLevelPTS (plc) != -1)
  242. {
  243. ModuleRead (plc, & plc->pib, PLC_MOD_OP_READ_FLASH, PLC_MODULEID_PARAMETERS, 0);
  244. }
  245. }
  246. if (_anyset (plc->flags, PLC_READ_MAC))
  247. {
  248. if (AccessLevelPTS (plc) != -1)
  249. {
  250. ModuleRead (plc, & plc->nvm, PLC_MOD_OP_READ_FLASH, PLC_MODULEID_FIRMWARE, 0);
  251. }
  252. }
  253. if (_anyset (plc->flags, PLC_READ_ALL))
  254. {
  255. if (AccessLevelPTS (plc) != -1)
  256. {
  257. ReadFlashMemory2 (plc);
  258. }
  259. }
  260. if (_anyset (plc->flags, PLC_ERASE_DEVICE))
  261. {
  262. if (AccessLevelPTS (plc) != -1)
  263. {
  264. EraseFlashMemory2 (plc);
  265. }
  266. }
  267. if (_anyset (plc->flags, PLC_FLASH_DEVICE))
  268. {
  269. if (AccessLevelPTS (plc) != -1)
  270. {
  271. FlashDevice2 (plc, (PLC_COMMIT_FORCE | PLC_COMMIT_NORESET | PLC_COMMIT_FACTPIB));
  272. }
  273. }
  274. if (_anyset (plc->flags, PLC_RESET_DEVICE))
  275. {
  276. ResetDevice (plc);
  277. }
  278. sleep (pause);
  279. }
  280. return;
  281. }
  282. /*====================================================================*
  283. *
  284. * int main (int argc, char const * argv[]);
  285. *
  286. * parse command line, populate plc structure and perform selected
  287. * operations; show help summary if asked; see getoptv and putoptv
  288. * to understand command line parsing and help summary display; see
  289. * plc.h for the definition of struct plc;
  290. *
  291. * the command line accepts multiple MAC addresses and the program
  292. * performs the specified operations on each address, in turn; the
  293. * address order is significant but the option order is not; the
  294. * default address is a local broadcast that causes all devices on
  295. * the local H1 interface to respond but not those at the remote
  296. * end of the powerline;
  297. *
  298. * the default address is 00:B0:52:00:00:01; omitting the address
  299. * will automatically address the local device; some options will
  300. * cancel themselves if this makes no sense;
  301. *
  302. * the default interface is eth1 because most people use eth0 as
  303. * their principle network connection; you can specify another
  304. * interface with -i or define environment string PLC to make
  305. * that the default interface and save typing;
  306. *
  307. *--------------------------------------------------------------------*/
  308. int main (int argc, char const * argv [])
  309. {
  310. extern struct channel channel;
  311. extern struct _term_ const daks [];
  312. extern struct _term_ const nmks [];
  313. static char const * optv [] =
  314. {
  315. "aAbB:d:D:eEfFi:HIJ:K:l:mMn:N:o:p:P:QqrRS:t:Tvw:x12",
  316. "device [device] [...]",
  317. "Qualcomm Atheros Panther/Lynx Powerline Device Manager",
  318. "a\tread Device Attributes using VS_OP_ATTRIBUTES",
  319. "b\tread device enumeration ID table using VS_EM_ID_TABLE",
  320. "B n\tperform pushbutton action (n) using MS_PB_ENC [1|2|3|4|'join'|'leave'|'status'|'reset']",
  321. "d f\tdump and clear watchdog report to file (f) using VS_WD_RPT",
  322. "D x\tDevice Access Key (DAK) is (x) [" DAK1 "]",
  323. "e\tredirect stderr to stdout",
  324. "E\terase flash memory using VS_MODULE_OPERATION",
  325. "f\tread NVRAM Configuration using VS_GET_NVM",
  326. #if defined (WINPCAP) || defined (LIBPCAP)
  327. "i n\thost interface is (n) [" LITERAL (CHANNEL_ETHNUMBER) "]",
  328. #else
  329. "i s\thost interface is (s) [" LITERAL (CHANNEL_ETHDEVICE) "]",
  330. #endif
  331. "H\tstop host action requests using VS_HOST_ACTION.IND",
  332. "I\tread device identity using VS_MODULE_OPERATION",
  333. "J x\tset NMK on remote device (x) via local device using VS_SET_KEY (see -K)",
  334. "K x\tNetwork Membership Key (NMK) is (x) [" NMK1 "]",
  335. "l n\tloop (n) times [" LITERAL (DEFAULT_LOOP) "]",
  336. "L\tdisplay link status",
  337. "m\tread network membership information using VS_NW_INFO",
  338. "M\tset NMK on local device using VS_SET_KEY (see -K)",
  339. "n f\tread NVM from FLASH/SDRAM to file (f) using VS_MODULE_OPERATION",
  340. "N f\twrite firmware file (f) to flash memory using VS_MODULE_OPERATION",
  341. "o f\tread all of flash memory using VS_MODULE_OPERATION",
  342. "p f\tread PIB from FLASH/SDRAM to file (f) using VS_MODULE_OPERATION",
  343. "P f\twrite parameter file (f) to flash memory using VS_MODULE_OPERATION",
  344. "q\tquiet mode",
  345. "Q\tquick flash (return immediately)",
  346. "r\tread hardware and firmware revision using VS_SW_VER",
  347. "R\treset device using VS_RS_DEV",
  348. "S f\twrite softloader file (f) to flash memory using VS_MODULE_OPERATION",
  349. "t n\tread timeout is (n) milliseconds [" LITERAL (CHANNEL_TIMEOUT) "]",
  350. "T\trestore factory defaults using VS_FAC_DEFAULTS",
  351. "v\tverbose mode",
  352. "w n\tpause (n) seconds [" LITERAL (DEFAULT_WAIT) "]",
  353. "x\texit on error",
  354. "1\tsuppress confirm MME when resetting device [option -R only]",
  355. "2\tboot from host after reset [option -R only]",
  356. (char const *) (0)
  357. };
  358. #include "../plc/plc.c"
  359. signed loop = DEFAULT_LOOP;
  360. signed wait = DEFAULT_WAIT;
  361. signed c;
  362. if (getenv (PLCDEVICE))
  363. {
  364. #if defined (WINPCAP) || defined (LIBPCAP)
  365. channel.ifindex = atoi (getenv (PLCDEVICE));
  366. #else
  367. channel.ifname = strdup (getenv (PLCDEVICE));
  368. #endif
  369. }
  370. optind = 1;
  371. while (~ (c = getoptv (argc, argv, optv)))
  372. {
  373. switch (c)
  374. {
  375. case 'a':
  376. _setbits (plc.flags, PLC_ATTRIBUTES);
  377. break;
  378. case 'b':
  379. _setbits (plc.flags, PLC_REMOTEHOSTS);
  380. break;
  381. case 'B':
  382. _setbits (plc.flags, PLC_PUSH_BUTTON);
  383. plc.pushbutton = (unsigned) (uintspec (synonym (optarg, buttons, SIZEOF (buttons)), 0, UCHAR_MAX));
  384. break;
  385. case 'd':
  386. _setbits (plc.flags, PLC_WATCHDOG_REPORT);
  387. if (! checkfilename (optarg))
  388. {
  389. error (1, EINVAL, "%s", optarg);
  390. }
  391. if ((plc.rpt.file = open (plc.rpt.name = optarg, O_BINARY | O_CREAT | O_RDWR | O_TRUNC, FILE_FILEMODE)) == -1)
  392. {
  393. error (1, errno, "%s", optarg);
  394. }
  395. #ifndef WIN32
  396. chown (optarg, getuid (), getgid ());
  397. #endif
  398. plc.readaction = 3;
  399. break;
  400. case 'D':
  401. if (! hexencode (plc.DAK, sizeof (plc.DAK), synonym (optarg, daks, SIZEOF (daks))))
  402. {
  403. error (1, errno, PLC_BAD_DAK, optarg);
  404. }
  405. break;
  406. case 'e':
  407. dup2 (STDOUT_FILENO, STDERR_FILENO);
  408. break;
  409. case 'E':
  410. _setbits (plc.flags, PLC_ERASE_DEVICE);
  411. break;
  412. case 'f':
  413. _setbits (plc.flags, PLC_NVRAM_INFO);
  414. break;
  415. case 'H':
  416. _setbits (plc.flags, PLC_HOST_ACTION);
  417. break;
  418. case 'I':
  419. _setbits (plc.flags, PLC_READ_IDENTITY);
  420. break;
  421. case 'i':
  422. #if defined (WINPCAP) || defined (LIBPCAP)
  423. channel.ifindex = atoi (optarg);
  424. #else
  425. channel.ifname = optarg;
  426. #endif
  427. break;
  428. case 'J':
  429. if (! hexencode (plc.RDA, sizeof (plc.RDA), (char const *) (optarg)))
  430. {
  431. error (1, errno, PLC_BAD_MAC, optarg);
  432. }
  433. _setbits (plc.flags, PLC_SETREMOTEKEY);
  434. break;
  435. case 'K':
  436. if (! hexencode (plc.NMK, sizeof (plc.NMK), synonym (optarg, nmks, SIZEOF (nmks))))
  437. {
  438. error (1, errno, PLC_BAD_NMK, optarg);
  439. }
  440. break;
  441. case 'M':
  442. _setbits (plc.flags, PLC_SETLOCALKEY);
  443. break;
  444. case 'l':
  445. loop = (unsigned) (uintspec (optarg, 0, UINT_MAX));
  446. break;
  447. case 'L':
  448. _setbits (plc.flags, PLC_LINK_STATUS);
  449. break;
  450. case 'm':
  451. _setbits (plc.flags, PLC_NETWORK);
  452. break;
  453. case 'N':
  454. if (! checkfilename (optarg))
  455. {
  456. error (1, EINVAL, "%s", optarg);
  457. }
  458. if ((plc.NVM.file = open (plc.NVM.name = optarg, O_BINARY | O_RDONLY)) == -1)
  459. {
  460. error (1, errno, "%s", plc.NVM.name);
  461. }
  462. if (panther_nvm_file (& plc.NVM))
  463. {
  464. error (1, errno, "Bad panther image file: %s", plc.NVM.name);
  465. }
  466. _setbits (plc.flags, PLC_FLASH_DEVICE);
  467. break;
  468. case 'n':
  469. if (! checkfilename (optarg))
  470. {
  471. error (1, EINVAL, "%s", optarg);
  472. }
  473. if ((plc.nvm.file = open (plc.nvm.name = optarg, O_BINARY | O_CREAT | O_RDWR | O_TRUNC, FILE_FILEMODE)) == -1)
  474. {
  475. error (1, errno, "%s", plc.nvm.name);
  476. }
  477. #ifndef WIN32
  478. chown (optarg, getuid (), getgid ());
  479. #endif
  480. _setbits (plc.flags, PLC_READ_MAC);
  481. break;
  482. case 'o':
  483. if (! checkfilename (optarg))
  484. {
  485. error (1, EINVAL, "%s", optarg);
  486. }
  487. if ((plc.nvm.file = open (plc.nvm.name = optarg, O_BINARY | O_CREAT | O_RDWR | O_TRUNC, FILE_FILEMODE)) == -1)
  488. {
  489. error (1, errno, "%s", plc.nvm.name);
  490. }
  491. #ifndef WIN32
  492. chown (optarg, getuid (), getgid ());
  493. #endif
  494. _setbits (plc.flags, PLC_READ_ALL);
  495. break;
  496. case 'P':
  497. if (! checkfilename (optarg))
  498. {
  499. error (1, EINVAL, "%s", optarg);
  500. }
  501. if ((plc.PIB.file = open (plc.PIB.name = optarg, O_BINARY | O_RDONLY)) == -1)
  502. {
  503. error (1, errno, "%s", plc.PIB.name);
  504. }
  505. if (panther_pib_file (& plc.PIB))
  506. {
  507. error (1, errno, "Bad panther image file: %s", plc.PIB.name);
  508. }
  509. _setbits (plc.flags, PLC_FLASH_DEVICE);
  510. break;
  511. case 'p':
  512. if (! checkfilename (optarg))
  513. {
  514. error (1, EINVAL, "%s", optarg);
  515. }
  516. if ((plc.pib.file = open (plc.pib.name = optarg, O_BINARY | O_CREAT | O_RDWR | O_TRUNC, FILE_FILEMODE)) == -1)
  517. {
  518. error (1, errno, "%s", plc.pib.name);
  519. }
  520. #ifndef WIN32
  521. chown (optarg, getuid (), getgid ());
  522. #endif
  523. _setbits (plc.flags, PLC_READ_PIB);
  524. break;
  525. case 'Q':
  526. _setbits (plc.flags, PLC_QUICK_FLASH);
  527. break;
  528. case 'q':
  529. _setbits (channel.flags, CHANNEL_SILENCE);
  530. _setbits (plc.flags, PLC_SILENCE);
  531. break;
  532. case 'R':
  533. _setbits (plc.flags, PLC_RESET_DEVICE);
  534. break;
  535. case 'r':
  536. _setbits (plc.flags, PLC_VERSION);
  537. break;
  538. case 'S':
  539. if (! checkfilename (optarg))
  540. {
  541. error (1, EINVAL, "%s", optarg);
  542. }
  543. if ((plc.SFT.file = open (plc.SFT.name = optarg, O_BINARY | O_RDONLY)) == -1)
  544. {
  545. error (1, errno, "%s", plc.SFT.name);
  546. }
  547. if (panther_nvm_file (& plc.SFT))
  548. {
  549. error (1, errno, "Bad image file: %s", plc.SFT.name);
  550. }
  551. _setbits (plc.flags, PLC_FLASH_DEVICE);
  552. break;
  553. case 't':
  554. channel.timeout = (signed) (uintspec (optarg, 0, UINT_MAX));
  555. break;
  556. case 'T':
  557. _setbits (plc.flags, PLC_FACTORY_DEFAULTS);
  558. break;
  559. case 'v':
  560. _setbits (channel.flags, CHANNEL_VERBOSE);
  561. _setbits (plc.flags, PLC_VERBOSE);
  562. break;
  563. case 'V':
  564. _setbits (plc.flags, PLC_SNIFFER);
  565. plc.action = (uint8_t) (uintspec (optarg, 0, UCHAR_MAX));
  566. break;
  567. case 'w':
  568. wait = (unsigned) (uintspec (optarg, 0, 3600));
  569. break;
  570. case 'x':
  571. _setbits (plc.flags, PLC_BAILOUT);
  572. break;
  573. case '1':
  574. _setbits (plc.flag2, PLC_FLAG2_CFM_ACT);
  575. break;
  576. case '2':
  577. _setbits (plc.flag2, PLC_FLAG2_BT_SRC);
  578. break;
  579. default:
  580. break;
  581. }
  582. }
  583. argc -= optind;
  584. argv += optind;
  585. if (argc != 1)
  586. {
  587. if (plc.nvm.file != -1)
  588. {
  589. error (1, ECANCELED, PLC_NODEVICE);
  590. }
  591. if (plc.pib.file != -1)
  592. {
  593. error (1, ECANCELED, PLC_NODEVICE);
  594. }
  595. if (plc.rpt.file != -1)
  596. {
  597. error (1, ECANCELED, PLC_NODEVICE);
  598. }
  599. }
  600. openchannel (& channel);
  601. if (! (plc.message = malloc (sizeof (* plc.message))))
  602. {
  603. error (1, errno, PLC_NOMEMORY);
  604. }
  605. if (! argc)
  606. {
  607. manager (& plc, loop, wait);
  608. }
  609. while ((argc) && (* argv))
  610. {
  611. if (! hexencode (channel.peer, sizeof (channel.peer), synonym (* argv, devices, SIZEOF (devices))))
  612. {
  613. error (1, errno, PLC_BAD_MAC, * argv);
  614. }
  615. manager (& plc, loop, wait);
  616. argc--;
  617. argv++;
  618. }
  619. free (plc.message);
  620. closechannel (& channel);
  621. exit (0);
  622. }