int6kwait.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782
  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. * int6kwait.c - Atheros Powerline Device Procrastinator;
  44. *
  45. * wait for device events to start or finish before returning;
  46. *
  47. *
  48. * Contributor(s):
  49. * Charles Maier
  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. #define RETRY 300
  114. #define POLL 5
  115. /*====================================================================*
  116. *
  117. * signed ResetAndWait (struct plc * plc);
  118. *
  119. * plc.h
  120. *
  121. * reset the device using a VS_RS_DEV Request message; continue to
  122. * request resets each second until the device accepts the request
  123. * or the wait period expires;
  124. *
  125. * Contributor(s):
  126. * Charles Maier
  127. * Nathaniel Houghton
  128. *
  129. *--------------------------------------------------------------------*/
  130. signed ResetAndWait (struct plc * plc)
  131. {
  132. struct channel * channel = (struct channel *)(plc->channel);
  133. struct message * message = (struct message *)(plc->message);
  134. struct timeval ts;
  135. struct timeval tc;
  136. unsigned timer = 0;
  137. #ifndef __GNUC__
  138. #pragma pack (push,1)
  139. #endif
  140. struct __packed vs_rs_dev_request
  141. {
  142. struct ethernet_hdr ethernet;
  143. struct qualcomm_hdr qualcomm;
  144. }
  145. * request = (struct vs_rs_dev_request *) (message);
  146. struct __packed vs_rs_dev_confirm
  147. {
  148. struct ethernet_hdr ethernet;
  149. struct qualcomm_hdr qualcomm;
  150. uint8_t MSTATUS;
  151. }
  152. * confirm = (struct vs_rs_dev_confirm *) (message);
  153. #ifndef __GNUC__
  154. #pragma pack (pop)
  155. #endif
  156. Request (plc, "Reset when Ready");
  157. if (gettimeofday (&ts, NULL) == -1)
  158. {
  159. error (1, errno, CANT_START_TIMER);
  160. }
  161. for (timer = 0; timer < plc->timer; timer = SECONDS (ts, tc))
  162. {
  163. memset (message, 0, sizeof (* message));
  164. EthernetHeader (&request->ethernet, channel->peer, channel->host, channel->type);
  165. QualcommHeader (&request->qualcomm, 0, (VS_RS_DEV | MMTYPE_REQ));
  166. plc->packetsize = (ETHER_MIN_LEN - ETHER_CRC_LEN);
  167. if (SendMME (plc) <= 0)
  168. {
  169. error (PLC_EXIT (plc), errno, CHANNEL_CANTSEND);
  170. return (-1);
  171. }
  172. if (ReadMME (plc, 0, (VS_RS_DEV | MMTYPE_CNF)) < 0)
  173. {
  174. error (PLC_EXIT (plc), errno, CHANNEL_CANTREAD);
  175. return (-1);
  176. }
  177. if (gettimeofday (&tc, NULL) == -1)
  178. {
  179. error (1, errno, CANT_RESET_TIMER);
  180. }
  181. if (plc->packetsize)
  182. {
  183. if (!confirm->MSTATUS)
  184. {
  185. Confirm (plc, "Resetting ...");
  186. return (0);
  187. }
  188. }
  189. }
  190. return (-1);
  191. }
  192. /*====================================================================*
  193. *
  194. * signed WaitForReset (struct plc * plc);
  195. *
  196. * plc.h
  197. *
  198. * send and receive VS_SW_VER messages until a confirmation is not
  199. * received within channel->timeout milliseconds to indicate that
  200. * the device is inactive; return 0 if the device resets within
  201. * plc->timer seconds; otherwise, return -1;
  202. *
  203. * this function cannot distinguish between a software reset and
  204. * hardware reset;
  205. *
  206. * Contributor(s):
  207. * Charles Maier
  208. * Nathaniel Houghton
  209. * Werner Henze
  210. *
  211. *--------------------------------------------------------------------*/
  212. signed WaitForReset (struct plc * plc)
  213. {
  214. struct channel * channel = (struct channel *)(plc->channel);
  215. struct message * message = (struct message *)(plc->message);
  216. struct timeval ts;
  217. struct timeval tc;
  218. unsigned timer = 0;
  219. #ifndef __GNUC__
  220. #pragma pack (push,1)
  221. #endif
  222. struct __packed vs_sw_ver_request
  223. {
  224. struct ethernet_hdr ethernet;
  225. struct qualcomm_hdr qualcomm;
  226. uint8_t MSTATUS;
  227. uint8_t MDEVICEID;
  228. uint8_t MVERLENGTH;
  229. char MVERSION [PLC_VERSION_STRING];
  230. }
  231. * request = (struct vs_sw_ver_request *) (message);
  232. #ifndef __GNUC__
  233. #pragma pack (pop)
  234. #endif
  235. Request (plc, "Allow %d seconds for Reset", plc->timer);
  236. if (gettimeofday (&ts, NULL) == -1)
  237. {
  238. error (1, errno, CANT_START_TIMER);
  239. }
  240. for (timer = 0; timer < plc->timer; timer = SECONDS (ts, tc))
  241. {
  242. memset (message, 0, sizeof (* message));
  243. EthernetHeader (&request->ethernet, channel->peer, channel->host, channel->type);
  244. QualcommHeader (&request->qualcomm, 0, (VS_SW_VER | MMTYPE_REQ));
  245. plc->packetsize = (ETHER_MIN_LEN - ETHER_CRC_LEN);
  246. if (SendMME (plc) <= 0)
  247. {
  248. error (PLC_EXIT (plc), errno, CHANNEL_CANTSEND);
  249. return (-1);
  250. }
  251. if (ReadMME (plc, 0, (VS_SW_VER | MMTYPE_CNF)) < 0)
  252. {
  253. error (PLC_EXIT (plc), errno, CHANNEL_CANTREAD);
  254. return (-1);
  255. }
  256. if (gettimeofday (&tc, NULL) == -1)
  257. {
  258. error (1, errno, CANT_RESET_TIMER);
  259. }
  260. if (!plc->packetsize)
  261. {
  262. if (_allset (plc->flags, (PLC_WAITFORRESET | PLC_ANALYSE)))
  263. {
  264. Confirm (plc, "Waited %d seconds for Reset", timer);
  265. }
  266. return (0);
  267. }
  268. }
  269. if (_allset (plc->flags, (PLC_WAITFORRESET | PLC_ANALYSE)))
  270. {
  271. Confirm (plc, "Waited %d seconds for Reset", timer);
  272. }
  273. return (-1);
  274. }
  275. /*====================================================================*
  276. *
  277. * signed WaitForStart (struct plc * plc, char string [], size_t length);
  278. *
  279. * plc.h
  280. *
  281. * send VS_SW_VER messages until confirmation is received within
  282. * channel->timeout milliseconds to indicate that the device is
  283. * active; return 0 if the device responds within plc->timer
  284. * seconds; otherwise, return -1;
  285. *
  286. * poll the device using VS_SW_VER messages until it responds or
  287. * the allotted time expires; return 0 if the device responds within
  288. * the allotted time or -1 if it does not or if a transmission error
  289. * occurs;
  290. *
  291. * Contributor(s):
  292. * Charles Maier
  293. * Nathaniel Houghton
  294. *
  295. *--------------------------------------------------------------------*/
  296. signed WaitForStart (struct plc * plc, char string [], size_t length)
  297. {
  298. struct channel * channel = (struct channel *)(plc->channel);
  299. struct message * message = (struct message *)(plc->message);
  300. struct timeval ts;
  301. struct timeval tc;
  302. unsigned timer = 0;
  303. #ifndef __GNUC__
  304. #pragma pack (push,1)
  305. #endif
  306. struct __packed vs_sw_ver_request
  307. {
  308. struct ethernet_hdr ethernet;
  309. struct qualcomm_hdr qualcomm;
  310. uint8_t MSTATUS;
  311. uint8_t MDEVICEID;
  312. uint8_t MVERLENGTH;
  313. char MVERSION [PLC_VERSION_STRING];
  314. }
  315. * request = (struct vs_sw_ver_request *) (message);
  316. struct __packed vs_sw_ver_confirm
  317. {
  318. struct ethernet_hdr ethernet;
  319. struct qualcomm_hdr qualcomm;
  320. uint8_t MSTATUS;
  321. uint8_t MDEVICEID;
  322. uint8_t MVERLENGTH;
  323. char MVERSION [PLC_VERSION_STRING];
  324. }
  325. * confirm = (struct vs_sw_ver_confirm *) (message);
  326. #ifndef __GNUC__
  327. #pragma pack (pop)
  328. #endif
  329. Request (plc, "Allow %d seconds for Start", plc->timer);
  330. if (gettimeofday (&ts, NULL) == -1)
  331. {
  332. error (1, errno, CANT_START_TIMER);
  333. }
  334. for (timer = 0; timer < plc->timer; timer = SECONDS (ts, tc))
  335. {
  336. memset (message, 0, sizeof (* message));
  337. EthernetHeader (&request->ethernet, channel->peer, channel->host, channel->type);
  338. QualcommHeader (&request->qualcomm, 0, (VS_SW_VER | MMTYPE_REQ));
  339. plc->packetsize = (ETHER_MIN_LEN - ETHER_CRC_LEN);
  340. if (SendMME (plc) <= 0)
  341. {
  342. error (PLC_EXIT (plc), errno, CHANNEL_CANTSEND);
  343. return (-1);
  344. }
  345. if (ReadMME (plc, 0, (VS_SW_VER | MMTYPE_CNF)) < 0)
  346. {
  347. error (PLC_EXIT (plc), errno, CHANNEL_CANTREAD);
  348. return (-1);
  349. }
  350. if (gettimeofday (&tc, NULL) == -1)
  351. {
  352. error (1, errno, CANT_RESET_TIMER);
  353. }
  354. if (plc->packetsize)
  355. {
  356. if (confirm->MSTATUS)
  357. {
  358. Failure (plc, PLC_WONTDOIT);
  359. return (-1);
  360. }
  361. if (_allset (plc->flags, (PLC_WAITFORSTART | PLC_ANALYSE)))
  362. {
  363. Confirm (plc, "Waited %d seconds for Start", timer);
  364. }
  365. strncpy (string, confirm->MVERSION, length);
  366. return (0);
  367. }
  368. }
  369. if (_allset (plc->flags, (PLC_WAITFORSTART | PLC_ANALYSE)))
  370. {
  371. Confirm (plc, "Waited %d seconds for Start", timer);
  372. }
  373. return (-1);
  374. }
  375. /*====================================================================*
  376. *
  377. * signed WaitForAssoc (struct plc * plc);
  378. *
  379. * plc.h
  380. *
  381. * send and receive VS_NW_INFO messages until the device reports
  382. * that a network exists and has at least one station; return 0 if
  383. * a network forms within plc->timer seconds; otherwise, return
  384. * -1;
  385. *
  386. * Contributor(s):
  387. * Charles Maier
  388. * Nathaniel Houghton
  389. *
  390. *--------------------------------------------------------------------*/
  391. signed WaitForAssoc (struct plc * plc)
  392. {
  393. extern const uint8_t broadcast [ETHER_ADDR_LEN];
  394. struct channel * channel = (struct channel *)(plc->channel);
  395. struct message * message = (struct message *)(plc->message);
  396. struct timeval ts;
  397. struct timeval tc;
  398. unsigned timer = 0;
  399. #ifndef __GNUC__
  400. #pragma pack (push,1)
  401. #endif
  402. struct __packed vs_nw_info_request
  403. {
  404. struct ethernet_hdr ethernet;
  405. struct qualcomm_fmi qualcomm;
  406. }
  407. * request = (struct vs_nw_info_request *)(message);
  408. struct __packed vs_nw_info_confirm
  409. {
  410. struct ethernet_hdr ethernet;
  411. struct qualcomm_fmi qualcomm;
  412. uint8_t SUB_VERSION;
  413. uint8_t Reserved;
  414. uint16_t DATA_LEN;
  415. uint8_t DATA [1];
  416. }
  417. * confirm = (struct vs_nw_info_confirm *)(message);
  418. struct __packed station
  419. {
  420. uint8_t MAC [ETHER_ADDR_LEN];
  421. uint8_t TEI;
  422. uint8_t Reserved [3];
  423. uint8_t BDA [ETHER_ADDR_LEN];
  424. uint16_t AVGTX;
  425. uint8_t COUPLING;
  426. uint8_t Reserved3;
  427. uint16_t AVGRX;
  428. uint16_t Reserved4;
  429. }
  430. * station;
  431. struct __packed network
  432. {
  433. uint8_t NID [7];
  434. uint8_t Reserved1 [2];
  435. uint8_t SNID;
  436. uint8_t TEI;
  437. uint8_t Reserved2 [4];
  438. uint8_t ROLE;
  439. uint8_t CCO_MAC [ETHER_ADDR_LEN];
  440. uint8_t CCO_TEI;
  441. uint8_t Reserved3 [3];
  442. uint8_t NUMSTAS;
  443. uint8_t Reserved4 [5];
  444. struct station stations [1];
  445. }
  446. * network;
  447. struct __packed networks
  448. {
  449. uint8_t Reserved;
  450. uint8_t NUMAVLNS;
  451. struct network networks [1];
  452. }
  453. * networks = (struct networks *) (confirm->DATA);
  454. #ifndef __GNUC__
  455. #pragma pack (pop)
  456. #endif
  457. Request (plc, "Allow %d seconds for Assoc", plc->timer);
  458. if (gettimeofday (&ts, NULL) == -1)
  459. {
  460. error (1, errno, CANT_START_TIMER);
  461. }
  462. for (timer = 0; timer < plc->timer; timer = SECONDS (ts, tc))
  463. {
  464. memset (message, 0, sizeof (* message));
  465. EthernetHeader (&request->ethernet, channel->peer, channel->host, channel->type);
  466. QualcommHeader1 (&request->qualcomm, 1, (VS_NW_INFO | MMTYPE_REQ));
  467. plc->packetsize = (ETHER_MIN_LEN - ETHER_CRC_LEN);
  468. if (SendMME (plc) <= 0)
  469. {
  470. error (PLC_EXIT (plc), errno, CHANNEL_CANTSEND);
  471. return (-1);
  472. }
  473. if (ReadMME (plc, 1, (VS_NW_INFO | MMTYPE_CNF)) < 0)
  474. {
  475. error (PLC_EXIT (plc), errno, CHANNEL_CANTREAD);
  476. return (-1);
  477. }
  478. if (gettimeofday (&tc, NULL) == -1)
  479. {
  480. error (1, errno, CANT_RESET_TIMER);
  481. }
  482. if (plc->packetsize)
  483. {
  484. network = (struct network *)(&networks->networks);
  485. while (networks->NUMAVLNS--)
  486. {
  487. station = (struct station *)(&network->stations);
  488. while (network->NUMSTAS--)
  489. {
  490. if (memcmp (station->MAC, broadcast, sizeof (broadcast)))
  491. {
  492. if (_allset (plc->flags, (PLC_WAITFORASSOC | PLC_ANALYSE)))
  493. {
  494. Confirm (plc, "Waited %d seconds for Assoc", timer);
  495. }
  496. return (0);
  497. }
  498. station++;
  499. }
  500. network = (struct network *)(station);
  501. }
  502. }
  503. }
  504. if (_allset (plc->flags, (PLC_WAITFORASSOC | PLC_ANALYSE)))
  505. {
  506. Confirm (plc, "Waited %d seconds for Assoc", timer);
  507. }
  508. return (-1);
  509. }
  510. /*====================================================================*
  511. *
  512. * void function (struct plc * plc, char const * firmware);
  513. *
  514. * perform operations in a logical order;
  515. *
  516. *
  517. *--------------------------------------------------------------------*/
  518. static void function (struct plc * plc, char const * firmware)
  519. {
  520. char string [PLC_VERSION_STRING];
  521. if (_anyset (plc->flags, PLC_RESET_DEVICE))
  522. {
  523. if (ResetAndWait (plc))
  524. {
  525. Failure (plc, "Device did not Reset.");
  526. }
  527. }
  528. if (_anyset (plc->flags, PLC_WAITFORRESET))
  529. {
  530. if (WaitForReset (plc))
  531. {
  532. Failure (plc, "Device did not Reset.");
  533. }
  534. }
  535. if (_anyset (plc->flags, PLC_WAITFORSTART))
  536. {
  537. if (WaitForStart (plc, string, sizeof (string)))
  538. {
  539. Failure (plc, "Device did not Start.");
  540. }
  541. if ((firmware) && (*firmware) && strcmp (firmware, string))
  542. {
  543. Failure (plc, "Started wrong firmware");
  544. }
  545. }
  546. if (_anyset (plc->flags, PLC_WAITFORASSOC))
  547. {
  548. if (WaitForAssoc (plc))
  549. {
  550. Failure (plc, "Device did not Assoc.");
  551. }
  552. }
  553. if (plc->sleep)
  554. {
  555. Request (plc, "Pause %d seconds", plc->sleep);
  556. sleep (plc->sleep);
  557. }
  558. return;
  559. }
  560. /*====================================================================*
  561. *
  562. * int main (int argc, char const * argv[]);
  563. *
  564. * parse command line, populate plc structure and perform selected
  565. * operations; show help summary if asked; see getoptv and putoptv
  566. * to understand command line parsing and help summary display; see
  567. * plc.h for the definition of struct plc;
  568. *
  569. * the command line accepts multiple MAC addresses and the program
  570. * performs the specified operations on each address, in turn; the
  571. * address order is significant but the option order is not; the
  572. * default address is a local broadcast that causes all devices on
  573. * the local H1 interface to respond but not those at the remote
  574. * end of the powerline;
  575. *
  576. * the default address is 00:B0:52:00:00:01; omitting the address
  577. * will automatically address the local device; some options will
  578. * cancel themselves if this makes no sense;
  579. *
  580. * the default interface is eth1 because most people use eth0 as
  581. * their principle network connection; you can specify another
  582. * interface with -i or define environment string PLC to make
  583. * that the default interface and save typing;
  584. *
  585. *
  586. *--------------------------------------------------------------------*/
  587. int main (int argc, char const * argv [])
  588. {
  589. extern struct channel channel;
  590. static char const * optv [] =
  591. {
  592. "ac:ef:i:p:qrRstvxw:",
  593. "device [device] [...] [> stdout]",
  594. "Qualcomm Atheros INT6x00 Powerline Device Procrastinator",
  595. "a\twait for device assoc",
  596. "c n\tpolling retry count [" LITERAL (RETRY) "]",
  597. "e\tredirect stderr to stdout",
  598. "f s\tconfirm firmware is revision s",
  599. #if defined (WINPCAP) || defined (LIBPCAP)
  600. "i n\thost interface is (n) [" LITERAL (CHANNEL_ETHNUMBER) "]",
  601. #else
  602. "i s\thost interface is (s) [" LITERAL (CHANNEL_ETHDEVICE) "]",
  603. #endif
  604. "p n\tpoll (n) times per second [" LITERAL (POLL) "]",
  605. "q\tquiet mode",
  606. "v\tverbose mode",
  607. "R\treset device and wait",
  608. "r\twait for device reset",
  609. "s\twait for device start",
  610. "t\tshow wait times",
  611. "w n\twait n seconds",
  612. "x\texit on error",
  613. (char const *) (0)
  614. };
  615. #include "../plc/plc.c"
  616. char const * firmware = "";
  617. unsigned retry = RETRY;
  618. unsigned poll = POLL;
  619. signed c;
  620. if (getenv (PLCDEVICE))
  621. {
  622. #if defined (WINPCAP) || defined (LIBPCAP)
  623. channel.ifindex = atoi (getenv (PLCDEVICE));
  624. #else
  625. channel.ifname = strdup (getenv (PLCDEVICE));
  626. #endif
  627. }
  628. optind = 1;
  629. while ((c = getoptv (argc, argv, optv)) != -1)
  630. {
  631. switch (c)
  632. {
  633. case 'a':
  634. _setbits (plc.flags, PLC_WAITFORASSOC);
  635. break;
  636. case 'c':
  637. retry = (unsigned)(uintspec (optarg, 1, UINT_MAX));
  638. break;
  639. case 'e':
  640. dup2 (STDOUT_FILENO, STDERR_FILENO);
  641. break;
  642. case 'f':
  643. firmware = optarg;
  644. break;
  645. case 'i':
  646. #if defined (WINPCAP) || defined (LIBPCAP)
  647. channel.ifindex = atoi (optarg);
  648. #else
  649. channel.ifname = optarg;
  650. #endif
  651. break;
  652. case 'p':
  653. poll = (unsigned)(uintspec (optarg, 1, 50));
  654. break;
  655. case 'q':
  656. _setbits (channel.flags, CHANNEL_SILENCE);
  657. _setbits (plc.flags, PLC_SILENCE);
  658. break;
  659. case 'r':
  660. _setbits (plc.flags, PLC_WAITFORRESET);
  661. break;
  662. case 'R':
  663. _setbits (plc.flags, PLC_RESET_DEVICE);
  664. break;
  665. case 's':
  666. _setbits (plc.flags, PLC_WAITFORSTART);
  667. break;
  668. case 't':
  669. _setbits (plc.flags, PLC_ANALYSE);
  670. break;
  671. case 'v':
  672. _setbits (channel.flags, CHANNEL_VERBOSE);
  673. _setbits (plc.flags, PLC_VERBOSE);
  674. break;
  675. case 'w':
  676. plc.sleep = (unsigned)(uintspec (optarg, 0, 3600));
  677. break;
  678. case 'x':
  679. _setbits (plc.flags, PLC_BAILOUT);
  680. break;
  681. default:
  682. break;
  683. }
  684. }
  685. argc -= optind;
  686. argv += optind;
  687. plc.timer = retry / poll;
  688. openchannel (&channel);
  689. if (!(plc.message = malloc (sizeof (* plc.message))))
  690. {
  691. error (1, errno, PLC_NOMEMORY);
  692. }
  693. if (!argc)
  694. {
  695. function (&plc, firmware);
  696. }
  697. while ((argc) && (* argv))
  698. {
  699. if (!hexencode (channel.peer, sizeof (channel.peer), synonym (* argv, devices, SIZEOF (devices))))
  700. {
  701. error (1, errno, PLC_BAD_MAC, * argv);
  702. }
  703. function (&plc, firmware);
  704. argv++;
  705. argc--;
  706. }
  707. free (plc.message);
  708. closechannel (&channel);
  709. exit (0);
  710. }