pppc.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388
  1. /*
  2. * Copyright (C) 2011 by egnite GmbH
  3. * Copyright (C) 2003-2006 by egnite Software GmbH
  4. *
  5. * All rights reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. *
  11. * 1. Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. * 2. Redistributions in binary form must reproduce the above copyright
  14. * notice, this list of conditions and the following disclaimer in the
  15. * documentation and/or other materials provided with the distribution.
  16. * 3. Neither the name of the copyright holders nor the names of
  17. * contributors may be used to endorse or promote products derived
  18. * from this software without specific prior written permission.
  19. *
  20. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  21. * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  22. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  23. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  24. * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  25. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
  26. * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
  27. * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
  28. * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  29. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
  30. * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31. * SUCH DAMAGE.
  32. *
  33. * For additional information see http://www.ethernut.de/
  34. */
  35. /*!
  36. * $Id: pppc.c 4640 2012-09-24 12:05:56Z u_bonnes $
  37. */
  38. /*!
  39. * \example pppc/pppc.c
  40. *
  41. * PPP client sample.
  42. *
  43. * This example demonstrates Nut/OS Point-To-Point protocol. Most likely
  44. * it will not run without modification. See the '#define' entries
  45. * below.
  46. *
  47. * The application will dial the provider via a modem, using the specified
  48. * chat script. When connected, it will establish a PPP session. Then DNS
  49. * is used to query the IP address of an NTP server, from which it queries
  50. * the current time. Finally the PPP session is terminated and the whole
  51. * procedure is repeated every hour.
  52. *
  53. * By default the application will use 2 serial ports. The first one is
  54. * used for debugging output on stdout and the second UART will be
  55. * connected to a modem.
  56. *
  57. * Note, that PPP is not available for all target boards. If this is the
  58. * case the program will use the local Ethernet network, where DHCP must
  59. * be available.
  60. */
  61. #include <cfg/ahdlc.h>
  62. #include <dev/board.h>
  63. #include <dev/ahdlcavr.h>
  64. #include <dev/ppp.h>
  65. #include <dev/chat.h>
  66. #include <sys/version.h>
  67. #include <sys/timer.h>
  68. #include <arpa/inet.h>
  69. #include <netdb.h>
  70. #include <net/if_var.h>
  71. #include <net/route.h>
  72. #include <pro/dhcp.h>
  73. #include <pro/sntp.h>
  74. #include <pro/rfctime.h>
  75. #include <stdlib.h>
  76. #include <string.h>
  77. #include <stdio.h>
  78. #include <io.h>
  79. #include <fcntl.h>
  80. #include <time.h>
  81. /*
  82. * Conversational script with a modem.
  83. *
  84. * The Nut/OS modem chat utility works similar to the the UNIX chat
  85. * script. In general it consists of one or more expect-send pairs of
  86. * strings or optional keyword-parameter pairs. Keywords are
  87. *
  88. * - TIMEOUT to set the max. time in seconds to wait for expected string
  89. * - ABORT to specify up to 10 abort strings
  90. * - REPORT to specify up to 3 reported abort strings
  91. *
  92. * Adjust this script to the requirements of your modem equipment
  93. * and your GPRS provider.
  94. *
  95. * The following script had been tested with a Siemens GPRS modem
  96. * (S55 mobile phone), using a t-mobile pre-paid account.
  97. */
  98. #define PPP_CHAT /* Wait up to 20 seconds for any response. */ \
  99. "TIMEOUT 20" \
  100. /* Expect nothing at the beginning. */ \
  101. " ''" \
  102. /* Send simple AT command to check the modem. */ \
  103. " AT OK" \
  104. /* Define PDP context, expecting 'OK'. */ \
  105. " AT+CGDCONT=1,\"IP\",\"internet.t-mobile\" OK" \
  106. /* Dial and wait for 'CONNECT'. */ \
  107. " ATD*99***1# CONNECT"
  108. /*
  109. * PPP user and password.
  110. *
  111. * Often GPRS providers accept any login.
  112. */
  113. #define PPP_USER "me"
  114. #define PPP_PASS "secret"
  115. /*
  116. * PPP device settings.
  117. */
  118. #if defined(NUT_THREAD_AHDLCRXSTACK)
  119. #define PPP_DEV devAhdlc1 /* AHDLC driver */
  120. #define PPP_DEV_NAME "uart1" /* Physical device name */
  121. #define PPP_SPEED 115200 /* Baudrate */
  122. #define PPP_RXTO 1000 /* Receive timeout (ms) */
  123. #else
  124. #warning "PPP is not supported on your target"
  125. #endif
  126. /*
  127. * Open serial debug port for standard output.
  128. */
  129. static void DebugPortOpen(void)
  130. {
  131. uint32_t baud = 115200;
  132. /* Register debug UART. */
  133. NutRegisterDevice(&DEV_CONSOLE, 0, 0);
  134. /* Open debug device for standard output. */
  135. freopen(DEV_CONSOLE.dev_name, "w", stdout);
  136. /* Set baud rate. */
  137. _ioctl(_fileno(stdout), UART_SETSPEED, &baud);
  138. }
  139. /*
  140. * Initialize the protocol port.
  141. */
  142. static void ProtocolPortInit(void)
  143. {
  144. #ifdef PPP_DEV
  145. /* Register PPP and UART device. */
  146. NutRegisterDevice(&PPP_DEV, 0, 0);
  147. NutRegisterDevice(&devPpp, 0, 0);
  148. #else
  149. /* Use Ethernet. */
  150. NutRegisterDevice(&DEV_ETHER, 0, 0);
  151. #endif
  152. }
  153. /*
  154. * Open the physical device.
  155. */
  156. static int ProtocolPortOpen(void)
  157. {
  158. #ifdef PPP_DEV
  159. int pppcom;
  160. uint32_t lctl;
  161. /* Open PPP device. Specify physical device, user and password. */
  162. printf("Open PPP interface at " PPP_DEV_NAME "...");
  163. pppcom = _open("ppp:" PPP_DEV_NAME "/" PPP_USER "/" PPP_PASS, _O_RDWR | _O_BINARY);
  164. if (pppcom == -1) {
  165. puts("failed");
  166. return -1;
  167. }
  168. /*
  169. * Set PPP line speed.
  170. */
  171. lctl = PPP_SPEED;
  172. _ioctl(pppcom, UART_SETSPEED, &lctl);
  173. printf("%lu baud", lctl);
  174. /*
  175. * The PPP driver doesn't set any receive timeout, but
  176. * may require it.
  177. */
  178. lctl = PPP_RXTO;
  179. _ioctl(pppcom, UART_SETREADTIMEOUT, &lctl);
  180. printf(", %lu ms timeout\n", lctl);
  181. return pppcom;
  182. #else
  183. /* Nothing to be done for Ethernet. */
  184. return 0;
  185. #endif
  186. }
  187. /*
  188. * Establish a modem connection.
  189. */
  190. static int ProtocolPortConnect(int pppcom)
  191. {
  192. #ifdef PPP_DEV
  193. int rc;
  194. /*
  195. * Connect using a chat script. We may also set any
  196. * required hardware handshake line at this stage.
  197. */
  198. printf("Connecting...");
  199. for (;;) {
  200. rc = NutChat(pppcom, PPP_CHAT);
  201. switch (rc) {
  202. case 0:
  203. puts("done");
  204. /* A short pause is required here to let the driver
  205. initialize the receiver thread. */
  206. NutSleep(100);
  207. break;
  208. case 1:
  209. puts("bad script");
  210. break;
  211. case 2:
  212. puts("I/O error");
  213. break;
  214. case 3:
  215. puts("no response");
  216. break;
  217. default:
  218. printf("aborted (%d)\n", rc);
  219. break;
  220. }
  221. if (rc != 3) {
  222. break;
  223. }
  224. NutSleep(1000);
  225. }
  226. return rc;
  227. #else
  228. /* Nothing to be done for Ethernet. */
  229. return 0;
  230. #endif
  231. }
  232. /*
  233. * Hang up.
  234. */
  235. static void ProtocolPortClose(int pppcom)
  236. {
  237. #ifdef PPP_DEV
  238. /* Set the UART back to normal mode. */
  239. _ioctl(pppcom, HDLC_SETIFNET, NULL);
  240. /* Close the physical port. This may or may not hang up. Please
  241. check the modem's documentation. */
  242. _close(pppcom);
  243. #endif
  244. }
  245. static int ProtocolPortConfigure(void)
  246. {
  247. #ifdef PPP_DEV
  248. PPPDCB *dcb;
  249. /*
  250. * We are connected, configure our PPP network interface.
  251. * This will initiate the PPP configuration negotiation
  252. * and authentication with the server.
  253. */
  254. printf("Configure network interface...");
  255. if (NutNetIfConfig("ppp", 0, 0, 0)) {
  256. puts("failed");
  257. return -1;
  258. }
  259. puts("done");
  260. /*
  261. * Set name server and default route. Actually the PPP interface
  262. * should do this, but the current release doesn't.
  263. */
  264. dcb = devPpp.dev_dcb;
  265. NutDnsConfig2(0, 0, dcb->dcb_ip_dns1, dcb->dcb_ip_dns2);
  266. NutIpRouteAdd(0, 0, dcb->dcb_remote_ip, &devPpp);
  267. /*
  268. * Display our IP settings.
  269. */
  270. printf(" Local IP: %s\n", inet_ntoa(dcb->dcb_local_ip));
  271. printf(" Remote IP: %s\n", inet_ntoa(dcb->dcb_remote_ip));
  272. printf(" Primary DNS: %s\n", inet_ntoa(dcb->dcb_ip_dns1));
  273. printf("Secondary DNS: %s\n", inet_ntoa(dcb->dcb_ip_dns2));
  274. #else
  275. /* We use DHCP on Ethernet. */
  276. printf("Configure network interface...");
  277. if (NutDhcpIfConfig(DEV_ETHER_NAME, 0, 60000)) {
  278. puts("failed");
  279. return -1;
  280. }
  281. puts("done");
  282. #endif
  283. return 0;
  284. }
  285. /*
  286. * Connect any NTP-Pool server to query the current time.
  287. */
  288. static void QueryDateAndTime(void)
  289. {
  290. uint32_t ip;
  291. time_t now;
  292. int i;
  293. /* First connect the DNS server to get the IP address. */
  294. printf("Is There Anybody Out There? ");
  295. ip = NutDnsGetHostByName((uint8_t *) "pool.ntp.org");
  296. if (ip == 0) {
  297. puts("No?");
  298. } else {
  299. /* We do have an IP, now try to connect it. */
  300. printf("Yes, found %s\n", inet_ntoa(ip));
  301. for (i = 0; i < 3; i++) {
  302. printf("What's the time? ");
  303. if (NutSNTPGetTime(&ip, &now) == 0) {
  304. /* We got a valid response, display the result. */
  305. printf("%s GMT\n", Rfc1123TimeString(gmtime(&now)));
  306. return;
  307. } else {
  308. /* It failed. May be the server is too busy. Try
  309. again in 5 seconds. */
  310. puts("Sorry?");
  311. NutSleep(5000);
  312. }
  313. }
  314. }
  315. /* We give up after 3 trials. */
  316. puts("You missed the starting gun.");
  317. }
  318. /*
  319. * PPP client application entry.
  320. */
  321. int main(void)
  322. {
  323. int pppcom;
  324. /* Initialize a debug port for standard output and display a banner. */
  325. DebugPortOpen();
  326. printf("\n\nPPP Client Sample - Nut/OS %s\n", NutVersionString());
  327. /* Initialize the network interface. */
  328. ProtocolPortInit();
  329. /* This loop runs once per hour. */
  330. for (;;) {
  331. /* Open the network interface. */
  332. pppcom = ProtocolPortOpen();
  333. if (pppcom == -1) {
  334. /* If this fails, we are busted. */
  335. break;
  336. }
  337. /* Establish the modem connection. */
  338. if (ProtocolPortConnect(pppcom) == 0) {
  339. /* Configure the network interface. */
  340. if (ProtocolPortConfigure() == 0) {
  341. /* Talk to the Internet. */
  342. QueryDateAndTime();
  343. }
  344. }
  345. /* Hang up. */
  346. ProtocolPortClose(pppcom);
  347. /* Sleep 1 hour. */
  348. puts("I'll be back in 1 hour.");
  349. NutSleep(3600000);
  350. }
  351. /* Ouch... */
  352. puts("Good bye cruel world");
  353. return 0;
  354. }