plcwait.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791
  1. /*====================================================================*
  2. *
  3. * Copyright (c) 2013 Qualcomm Atheros, Inc.
  4. *
  5. * All rights reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or
  8. * without modification, are permitted (subject to the limitations
  9. * in the disclaimer below) provided that the following conditions
  10. * are met:
  11. *
  12. * * Redistributions of source code must retain the above copyright
  13. * notice, this list of conditions and the following disclaimer.
  14. *
  15. * * Redistributions in binary form must reproduce the above
  16. * copyright notice, this list of conditions and the following
  17. * disclaimer in the documentation and/or other materials
  18. * provided with the distribution.
  19. *
  20. * * Neither the name of Qualcomm Atheros nor the names of
  21. * its contributors may be used to endorse or promote products
  22. * derived from this software without specific prior written
  23. * permission.
  24. *
  25. * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE
  26. * GRANTED BY THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE
  27. * COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
  28. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  29. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  30. * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
  31. * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  32. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  33. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  34. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  35. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  36. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
  37. * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  38. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  39. *
  40. *--------------------------------------------------------------------*/
  41. /*====================================================================*"
  42. *
  43. * plcwait.c -
  44. *
  45. *
  46. * Contributor(s):
  47. * Charles Maier
  48. * Nathaniel Houghton
  49. * Werner Henze
  50. *
  51. *--------------------------------------------------------------------*/
  52. /*====================================================================*"
  53. * system header files;
  54. *--------------------------------------------------------------------*/
  55. #include <unistd.h>
  56. #include <stdlib.h>
  57. #include <stdint.h>
  58. #include <limits.h>
  59. #include <sys/time.h>
  60. /*====================================================================*
  61. * custom header files;
  62. *--------------------------------------------------------------------*/
  63. #include "../tools/getoptv.h"
  64. #include "../tools/putoptv.h"
  65. #include "../tools/memory.h"
  66. #include "../tools/number.h"
  67. #include "../tools/symbol.h"
  68. #include "../tools/types.h"
  69. #include "../tools/flags.h"
  70. #include "../tools/files.h"
  71. #include "../tools/timer.h"
  72. #include "../tools/error.h"
  73. #include "../plc/plc.h"
  74. /*====================================================================*
  75. * custom source files;
  76. *--------------------------------------------------------------------*/
  77. #ifndef MAKEFILE
  78. #include "../tools/getoptv.c"
  79. #include "../tools/putoptv.c"
  80. #include "../tools/version.c"
  81. #include "../tools/uintspec.c"
  82. #include "../tools/hexdump.c"
  83. #include "../tools/hexencode.c"
  84. #include "../tools/hexdecode.c"
  85. #include "../tools/todigit.c"
  86. #include "../tools/checkfilename.c"
  87. #include "../tools/synonym.c"
  88. #include "../tools/error.c"
  89. #endif
  90. #ifndef MAKEFILE
  91. #include "../plc/Confirm.c"
  92. #include "../plc/Display.c"
  93. #include "../plc/Failure.c"
  94. #include "../plc/ReadMME.c"
  95. #include "../plc/Request.c"
  96. #include "../plc/SendMME.c"
  97. #include "../plc/Devices.c"
  98. #endif
  99. #ifndef MAKEFILE
  100. #include "../ether/openchannel.c"
  101. #include "../ether/closechannel.c"
  102. #include "../ether/readpacket.c"
  103. #include "../ether/sendpacket.c"
  104. #include "../ether/channel.c"
  105. #endif
  106. #ifndef MAKEFILE
  107. #include "../mme/MMECode.c"
  108. #include "../mme/EthernetHeader.c"
  109. #include "../mme/QualcommHeader.c"
  110. #include "../mme/QualcommHeader1.c"
  111. #include "../mme/UnwantedMessage.c"
  112. #endif
  113. /*====================================================================*
  114. *
  115. * signed ResetAndWait (struct plc * plc);
  116. *
  117. * plc.h
  118. *
  119. * send VS_RS_DEV.REQ messages every channel->timeout milliseconds
  120. * until the device responds to indicate that it is ready to reset;
  121. * return 0 if the device eventually responds within plc->timer
  122. * seconds or -1 if not;
  123. *
  124. * Contributor(s):
  125. * Charles Maier
  126. * Nathaniel Houghton
  127. *
  128. *--------------------------------------------------------------------*/
  129. signed ResetAndWait (struct plc * plc)
  130. {
  131. struct channel * channel = (struct channel *)(plc->channel);
  132. struct message * message = (struct message *)(plc->message);
  133. struct timeval ts;
  134. struct timeval tc;
  135. unsigned timer = 0;
  136. #ifndef __GNUC__
  137. #pragma pack (push,1)
  138. #endif
  139. struct __packed vs_rs_dev_request
  140. {
  141. struct ethernet_hdr ethernet;
  142. struct qualcomm_hdr qualcomm;
  143. }
  144. * request = (struct vs_rs_dev_request *) (message);
  145. struct __packed vs_rs_dev_confirm
  146. {
  147. struct ethernet_hdr ethernet;
  148. struct qualcomm_hdr qualcomm;
  149. uint8_t MSTATUS;
  150. }
  151. * confirm = (struct vs_rs_dev_confirm *) (message);
  152. #ifndef __GNUC__
  153. #pragma pack (pop)
  154. #endif
  155. Request (plc, "Reset when Ready");
  156. if (gettimeofday (&ts, NULL) == -1)
  157. {
  158. error (1, errno, CANT_START_TIMER);
  159. }
  160. for (timer = 0; timer < plc->timer; timer = SECONDS (ts, tc))
  161. {
  162. memset (message, 0, sizeof (* message));
  163. EthernetHeader (&request->ethernet, channel->peer, channel->host, channel->type);
  164. QualcommHeader (&request->qualcomm, 0, (VS_RS_DEV | MMTYPE_REQ));
  165. plc->packetsize = (ETHER_MIN_LEN - ETHER_CRC_LEN);
  166. if (SendMME (plc) <= 0)
  167. {
  168. error (PLC_EXIT (plc), errno, CHANNEL_CANTSEND);
  169. return (-1);
  170. }
  171. if (ReadMME (plc, 0, (VS_RS_DEV | MMTYPE_CNF)) < 0)
  172. {
  173. error (PLC_EXIT (plc), errno, CHANNEL_CANTREAD);
  174. return (-1);
  175. }
  176. if (gettimeofday (&tc, NULL) == -1)
  177. {
  178. error (1, errno, CANT_RESET_TIMER);
  179. }
  180. if (plc->packetsize)
  181. {
  182. if (!confirm->MSTATUS)
  183. {
  184. Confirm (plc, "Resetting ...");
  185. return (0);
  186. }
  187. }
  188. }
  189. return (-1);
  190. }
  191. /*====================================================================*
  192. *
  193. * signed WaitForReset (struct plc * plc);
  194. *
  195. * plc.h
  196. *
  197. * send VS_SW_VER.REQ messages every channel->timeout milliseconds
  198. * until the device stops responding to indicate that it is inactive;
  199. * return 0 if the device eventually stops responding within
  200. * plc->timer seconds or -1 if not;
  201. *
  202. * this function cannot distinguish between a software reset and
  203. * hardware reset;
  204. *
  205. * Contributor(s):
  206. * Charles Maier
  207. * Nathaniel Houghton
  208. * Werner Henze
  209. *
  210. *--------------------------------------------------------------------*/
  211. signed WaitForReset (struct plc * plc)
  212. {
  213. struct channel * channel = (struct channel *)(plc->channel);
  214. struct message * message = (struct message *)(plc->message);
  215. struct timeval ts;
  216. struct timeval tc;
  217. unsigned timer = 0;
  218. #ifndef __GNUC__
  219. #pragma pack (push,1)
  220. #endif
  221. struct __packed vs_sw_ver_request
  222. {
  223. struct ethernet_hdr ethernet;
  224. struct qualcomm_hdr qualcomm;
  225. uint8_t MSTATUS;
  226. uint8_t MDEVICEID;
  227. uint8_t MVERLENGTH;
  228. char MVERSION [PLC_VERSION_STRING];
  229. }
  230. * request = (struct vs_sw_ver_request *) (message);
  231. #ifndef __GNUC__
  232. #pragma pack (pop)
  233. #endif
  234. Request (plc, "Allow %d seconds for Reset", plc->timer);
  235. if (gettimeofday (&ts, NULL) == -1)
  236. {
  237. error (1, errno, CANT_START_TIMER);
  238. }
  239. for (timer = 0; timer < plc->timer; timer = SECONDS (ts, tc))
  240. {
  241. memset (message, 0, sizeof (* message));
  242. EthernetHeader (&request->ethernet, channel->peer, channel->host, channel->type);
  243. QualcommHeader (&request->qualcomm, 0, (VS_SW_VER | MMTYPE_REQ));
  244. plc->packetsize = (ETHER_MIN_LEN - ETHER_CRC_LEN);
  245. if (SendMME (plc) <= 0)
  246. {
  247. error (PLC_EXIT (plc), errno, CHANNEL_CANTSEND);
  248. return (-1);
  249. }
  250. if (ReadMME (plc, 0, (VS_SW_VER | MMTYPE_CNF)) < 0)
  251. {
  252. error (PLC_EXIT (plc), errno, CHANNEL_CANTREAD);
  253. return (-1);
  254. }
  255. if (gettimeofday (&tc, NULL) == -1)
  256. {
  257. error (1, errno, CANT_RESET_TIMER);
  258. }
  259. if (!plc->packetsize)
  260. {
  261. if (_allset (plc->flags, (PLC_WAITFORRESET | PLC_ANALYSE)))
  262. {
  263. Confirm (plc, "Waited %d seconds for Reset", timer);
  264. }
  265. return (0);
  266. }
  267. }
  268. if (_allset (plc->flags, (PLC_WAITFORRESET | PLC_ANALYSE)))
  269. {
  270. Confirm (plc, "Waited %d seconds for Reset", timer);
  271. }
  272. return (-1);
  273. }
  274. /*====================================================================*
  275. *
  276. * signed WaitForStart (struct plc * plc, char string [], size_t length);
  277. *
  278. * plc.h
  279. *
  280. * send VS_SW_VER.REQ messages every channel->timeout milliseconds
  281. * until the device responds to indicate that it is active; return
  282. * 0 if the device eventually responds within plc->timer seconds
  283. * or -1 if not;
  284. *
  285. * Contributor(s):
  286. * Charles Maier
  287. * Nathaniel Houghton
  288. * Werner Henze
  289. *
  290. *--------------------------------------------------------------------*/
  291. signed WaitForStart (struct plc * plc, char string [], size_t length)
  292. {
  293. struct channel * channel = (struct channel *)(plc->channel);
  294. struct message * message = (struct message *)(plc->message);
  295. struct timeval ts;
  296. struct timeval tc;
  297. unsigned timer = 0;
  298. #ifndef __GNUC__
  299. #pragma pack (push,1)
  300. #endif
  301. struct __packed vs_sw_ver_request
  302. {
  303. struct ethernet_hdr ethernet;
  304. struct qualcomm_hdr qualcomm;
  305. uint8_t MSTATUS;
  306. uint8_t MDEVICEID;
  307. uint8_t MVERLENGTH;
  308. char MVERSION [PLC_VERSION_STRING];
  309. }
  310. * request = (struct vs_sw_ver_request *) (message);
  311. struct __packed vs_sw_ver_confirm
  312. {
  313. struct ethernet_hdr ethernet;
  314. struct qualcomm_hdr qualcomm;
  315. uint8_t MSTATUS;
  316. uint8_t MDEVICEID;
  317. uint8_t MVERLENGTH;
  318. char MVERSION [PLC_VERSION_STRING];
  319. }
  320. * confirm = (struct vs_sw_ver_confirm *) (message);
  321. #ifndef __GNUC__
  322. #pragma pack (pop)
  323. #endif
  324. Request (plc, "Allow %d seconds for Start", plc->timer);
  325. if (gettimeofday (&ts, NULL) == -1)
  326. {
  327. error (1, errno, CANT_START_TIMER);
  328. }
  329. for (timer = 0; timer < plc->timer; timer = SECONDS (ts, tc))
  330. {
  331. memset (message, 0, sizeof (* message));
  332. EthernetHeader (&request->ethernet, channel->peer, channel->host, channel->type);
  333. QualcommHeader (&request->qualcomm, 0, (VS_SW_VER | MMTYPE_REQ));
  334. plc->packetsize = (ETHER_MIN_LEN - ETHER_CRC_LEN);
  335. if (SendMME (plc) <= 0)
  336. {
  337. error (PLC_EXIT (plc), errno, CHANNEL_CANTSEND);
  338. return (-1);
  339. }
  340. if (ReadMME (plc, 0, (VS_SW_VER | MMTYPE_CNF)) < 0)
  341. {
  342. error (PLC_EXIT (plc), errno, CHANNEL_CANTREAD);
  343. return (-1);
  344. }
  345. if (gettimeofday (&tc, NULL) == -1)
  346. {
  347. error (1, errno, CANT_RESET_TIMER);
  348. }
  349. if (plc->packetsize)
  350. {
  351. if (confirm->MSTATUS)
  352. {
  353. Failure (plc, PLC_WONTDOIT);
  354. return (-1);
  355. }
  356. if (_allset (plc->flags, (PLC_WAITFORSTART | PLC_ANALYSE)))
  357. {
  358. Confirm (plc, "Waited %d seconds for Start", timer);
  359. }
  360. strncpy (string, confirm->MVERSION, length);
  361. return (0);
  362. }
  363. }
  364. if (_allset (plc->flags, (PLC_WAITFORSTART | PLC_ANALYSE)))
  365. {
  366. Confirm (plc, "Waited %d seconds for Start", timer);
  367. }
  368. return (-1);
  369. }
  370. /*====================================================================*
  371. *
  372. * signed WaitForAssoc (struct plc * plc);
  373. *
  374. * plc.h
  375. *
  376. * send VS_NW_INFO.REQ messages every channel->timeout milliseconds
  377. * until the device reports that a network has formed; return 0 if a
  378. * network forms within plc->timer seconds or -1 if not;
  379. *
  380. *--------------------------------------------------------------------*/
  381. signed WaitForAssoc (struct plc * plc)
  382. {
  383. extern const uint8_t broadcast [ETHER_ADDR_LEN];
  384. struct channel * channel = (struct channel *)(plc->channel);
  385. struct message * message = (struct message *)(plc->message);
  386. struct timeval ts;
  387. struct timeval tc;
  388. unsigned timer = 0;
  389. #ifndef __GNUC__
  390. #pragma pack (push,1)
  391. #endif
  392. struct __packed vs_nw_info_request
  393. {
  394. struct ethernet_hdr ethernet;
  395. struct qualcomm_fmi qualcomm;
  396. }
  397. * request = (struct vs_nw_info_request *)(message);
  398. struct __packed vs_nw_info_confirm
  399. {
  400. struct ethernet_hdr ethernet;
  401. struct qualcomm_fmi qualcomm;
  402. uint8_t SUB_VERSION;
  403. uint8_t Reserved;
  404. uint16_t DATA_LEN;
  405. uint8_t DATA [1];
  406. }
  407. * confirm = (struct vs_nw_info_confirm *)(message);
  408. struct __packed station
  409. {
  410. uint8_t MAC [ETHER_ADDR_LEN];
  411. uint8_t TEI;
  412. uint8_t Reserved [3];
  413. uint8_t BDA [ETHER_ADDR_LEN];
  414. uint16_t AVGTX;
  415. uint8_t COUPLING;
  416. uint8_t Reserved3;
  417. uint16_t AVGRX;
  418. uint16_t Reserved4;
  419. }
  420. * station;
  421. struct __packed network
  422. {
  423. uint8_t NID [7];
  424. uint8_t Reserved1 [2];
  425. uint8_t SNID;
  426. uint8_t TEI;
  427. uint8_t Reserved2 [4];
  428. uint8_t ROLE;
  429. uint8_t CCO_MAC [ETHER_ADDR_LEN];
  430. uint8_t CCO_TEI;
  431. uint8_t Reserved3 [3];
  432. uint8_t NUMSTAS;
  433. uint8_t Reserved4 [5];
  434. struct station stations [1];
  435. }
  436. * network;
  437. struct __packed networks
  438. {
  439. uint8_t Reserved;
  440. uint8_t NUMAVLNS;
  441. struct network networks [1];
  442. }
  443. * networks = (struct networks *) (confirm->DATA);
  444. #ifndef __GNUC__
  445. #pragma pack (pop)
  446. #endif
  447. Request (plc, "Allow %d seconds for Assoc", plc->timer);
  448. if (gettimeofday (&ts, NULL) == -1)
  449. {
  450. error (1, errno, CANT_START_TIMER);
  451. }
  452. for (timer = 0; timer < plc->timer; timer = SECONDS (ts, tc))
  453. {
  454. memset (message, 0, sizeof (* message));
  455. EthernetHeader (&request->ethernet, channel->peer, channel->host, channel->type);
  456. QualcommHeader1 (&request->qualcomm, 1, (VS_NW_INFO | MMTYPE_REQ));
  457. plc->packetsize = (ETHER_MIN_LEN - ETHER_CRC_LEN);
  458. if (SendMME (plc) <= 0)
  459. {
  460. error (PLC_EXIT (plc), errno, CHANNEL_CANTSEND);
  461. return (-1);
  462. }
  463. if (ReadMME (plc, 1, (VS_NW_INFO | MMTYPE_CNF)) < 0)
  464. {
  465. error (PLC_EXIT (plc), errno, CHANNEL_CANTREAD);
  466. return (-1);
  467. }
  468. if (gettimeofday (&tc, NULL) == -1)
  469. {
  470. error (1, errno, CANT_RESET_TIMER);
  471. }
  472. if (plc->packetsize)
  473. {
  474. network = (struct network *)(&networks->networks);
  475. while (networks->NUMAVLNS--)
  476. {
  477. station = (struct station *)(&network->stations);
  478. while (network->NUMSTAS--)
  479. {
  480. if (memcmp (station->MAC, broadcast, sizeof (broadcast)))
  481. {
  482. if (_allset (plc->flags, (PLC_WAITFORASSOC | PLC_ANALYSE)))
  483. {
  484. Confirm (plc, "Waited %d seconds for Assoc", timer);
  485. }
  486. return (0);
  487. }
  488. station++;
  489. }
  490. network = (struct network *)(station);
  491. }
  492. }
  493. }
  494. if (_allset (plc->flags, (PLC_WAITFORASSOC | PLC_ANALYSE)))
  495. {
  496. Confirm (plc, "Waited %d seconds for Assoc", timer);
  497. }
  498. return (-1);
  499. }
  500. #define COMPARE_TYPE_NONE 0
  501. #define COMPARE_TYPE_EXACT 1
  502. #define COMPARE_TYPE_CONTAINS 2
  503. /*====================================================================*
  504. *
  505. * void function (struct plc * plc, char const * firmware, int compare_type);
  506. *
  507. * perform operations in a logical order;
  508. *
  509. *
  510. *--------------------------------------------------------------------*/
  511. static void function (struct plc * plc, char const * firmware, int compare_type)
  512. {
  513. char string [PLC_VERSION_STRING];
  514. if (_anyset (plc->flags, PLC_RESET_DEVICE))
  515. {
  516. if (ResetAndWait (plc))
  517. {
  518. Failure (plc, "Device did not Reset.");
  519. }
  520. }
  521. if (_anyset (plc->flags, PLC_WAITFORRESET))
  522. {
  523. if (WaitForReset (plc))
  524. {
  525. Failure (plc, "Device did not Reset.");
  526. }
  527. }
  528. if (_anyset (plc->flags, PLC_WAITFORSTART))
  529. {
  530. if (WaitForStart (plc, string, sizeof (string)))
  531. {
  532. Failure (plc, "Device did not Start.");
  533. }
  534. if ((firmware) && (*firmware))
  535. {
  536. switch (compare_type)
  537. {
  538. case COMPARE_TYPE_EXACT:
  539. if (strcmp (firmware, string))
  540. {
  541. Failure (plc, "Started wrong firmware");
  542. }
  543. break;
  544. case COMPARE_TYPE_CONTAINS:
  545. if (strstr (string, firmware) == NULL)
  546. {
  547. Failure (plc, "Started wrong firmware");
  548. }
  549. break;
  550. }
  551. }
  552. }
  553. if (_anyset (plc->flags, PLC_WAITFORASSOC))
  554. {
  555. if (WaitForAssoc (plc))
  556. {
  557. Failure (plc, "Device did not Assoc.");
  558. }
  559. }
  560. if (plc->sleep)
  561. {
  562. Request (plc, "Pause %d seconds", plc->sleep);
  563. sleep (plc->sleep);
  564. }
  565. return;
  566. }
  567. /*====================================================================*
  568. *
  569. * int main (int argc, char const * argv[]);
  570. *
  571. * parse command line, populate plc structure and perform selected
  572. * operations; show help summary if asked; see getoptv and putoptv
  573. * to understand command line parsing and help summary display; see
  574. * plc.h for the definition of struct plc;
  575. *
  576. * the command line accepts multiple MAC addresses and the program
  577. * performs the specified operations on each address, in turn; the
  578. * address order is significant but the option order is not; the
  579. * default address is a local broadcast that causes all devices on
  580. * the local H1 interface to respond but not those at the remote
  581. * end of the powerline;
  582. *
  583. * the default address is 00:B0:52:00:00:01; omitting the address
  584. * will automatically address the local device; some options will
  585. * cancel themselves if this makes no sense;
  586. *
  587. * the default interface is eth1 because most people use eth0 as
  588. * their principle network connection; you can specify another
  589. * interface with -i or define environment string PLC to make
  590. * that the default interface and save typing;
  591. *
  592. *
  593. *--------------------------------------------------------------------*/
  594. int main (int argc, char const * argv [])
  595. {
  596. extern struct channel channel;
  597. static char const * optv [] =
  598. {
  599. "aef:F:i:p:qrRst:vw:xy",
  600. "device [device] [...] [> stdout]",
  601. "Qualcomm Atheros Powerline Procrastinator",
  602. "a\twait for device assoc",
  603. "e\tredirect stderr to stdout",
  604. "f s\tconfirm firmware is revision s",
  605. "F s\tconfirm firmware revision contains substring s",
  606. #if defined (WINPCAP) || defined (LIBPCAP)
  607. "i n\thost interface is (n) [" LITERAL (CHANNEL_ETHNUMBER) "]",
  608. #else
  609. "i s\thost interface is (s) [" LITERAL (CHANNEL_ETHDEVICE) "]",
  610. #endif
  611. "p n\tpause (n) seconds",
  612. "q\tquiet mode",
  613. "r\twait for device reset",
  614. "R\treset device and wait",
  615. "s\twait for device start",
  616. "t n\tchannel timeout is (n) milliseconds [" LITERAL (CHANNEL_TIMEOUT) "]",
  617. "v\tverbose mode",
  618. "w n\twait up to (n) seconds for action [" LITERAL (PLC_TIMER) "]",
  619. "x\texit on error",
  620. "y\treport failure times",
  621. (char const *) (0)
  622. };
  623. #include "../plc/plc.c"
  624. char const * firmware = "";
  625. signed c;
  626. int compare_type = COMPARE_TYPE_NONE;
  627. if (getenv (PLCDEVICE))
  628. {
  629. #if defined (WINPCAP) || defined (LIBPCAP)
  630. channel.ifindex = atoi (getenv (PLCDEVICE));
  631. #else
  632. channel.ifname = strdup (getenv (PLCDEVICE));
  633. #endif
  634. }
  635. optind = 1;
  636. while ((c = getoptv (argc, argv, optv)) != -1)
  637. {
  638. switch (c)
  639. {
  640. case 'a':
  641. _setbits (plc.flags, PLC_WAITFORASSOC);
  642. break;
  643. case 'e':
  644. dup2 (STDOUT_FILENO, STDERR_FILENO);
  645. break;
  646. case 'f':
  647. firmware = optarg;
  648. compare_type = COMPARE_TYPE_EXACT;
  649. break;
  650. case 'F':
  651. firmware = optarg;
  652. compare_type = COMPARE_TYPE_CONTAINS;
  653. break;
  654. case 'i':
  655. #if defined (WINPCAP) || defined (LIBPCAP)
  656. channel.ifindex = atoi (optarg);
  657. #else
  658. channel.ifname = optarg;
  659. #endif
  660. break;
  661. case 'p':
  662. plc.sleep = (unsigned)(uintspec (optarg, 0, 3600));
  663. break;
  664. case 'q':
  665. _setbits (channel.flags, CHANNEL_SILENCE);
  666. _setbits (plc.flags, PLC_SILENCE);
  667. break;
  668. case 'r':
  669. _setbits (plc.flags, PLC_WAITFORRESET);
  670. break;
  671. case 'R':
  672. _setbits (plc.flags, PLC_RESET_DEVICE);
  673. break;
  674. case 's':
  675. _setbits (plc.flags, PLC_WAITFORSTART);
  676. break;
  677. case 't':
  678. channel.timeout = (signed)(uintspec (optarg, 0, UINT_MAX));
  679. break;
  680. case 'v':
  681. _setbits (channel.flags, CHANNEL_VERBOSE);
  682. _setbits (plc.flags, PLC_VERBOSE);
  683. break;
  684. case 'w':
  685. plc.timer = (unsigned)(uintspec (optarg, 0, 86400));
  686. break;
  687. case 'x':
  688. _setbits (plc.flags, PLC_BAILOUT);
  689. break;
  690. case 'y':
  691. _setbits (plc.flags, PLC_ANALYSE);
  692. break;
  693. default:
  694. break;
  695. }
  696. }
  697. argc -= optind;
  698. argv += optind;
  699. openchannel (&channel);
  700. if (!(plc.message = malloc (sizeof (* plc.message))))
  701. {
  702. error (1, errno, PLC_NOMEMORY);
  703. }
  704. if (!argc)
  705. {
  706. function (&plc, firmware, compare_type);
  707. }
  708. while ((argc) && (* argv))
  709. {
  710. if (!hexencode (channel.peer, sizeof (channel.peer), synonym (* argv, devices, SIZEOF (devices))))
  711. {
  712. error (1, errno, PLC_BAD_MAC, * argv);
  713. }
  714. function (&plc, firmware, compare_type);
  715. argv++;
  716. argc--;
  717. }
  718. free (plc.message);
  719. closechannel (&channel);
  720. exit (0);
  721. }