Nut/OS  4.10.3
API Reference
pppc.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2011 by egnite GmbH
00003  * Copyright (C) 2003-2006 by egnite Software GmbH
00004  *
00005  * All rights reserved.
00006  *
00007  * Redistribution and use in source and binary forms, with or without
00008  * modification, are permitted provided that the following conditions
00009  * are met:
00010  *
00011  * 1. Redistributions of source code must retain the above copyright
00012  *    notice, this list of conditions and the following disclaimer.
00013  * 2. Redistributions in binary form must reproduce the above copyright
00014  *    notice, this list of conditions and the following disclaimer in the
00015  *    documentation and/or other materials provided with the distribution.
00016  * 3. Neither the name of the copyright holders nor the names of
00017  *    contributors may be used to endorse or promote products derived
00018  *    from this software without specific prior written permission.
00019  *
00020  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00021  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00022  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00023  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00024  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00025  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00026  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
00027  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
00028  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00029  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
00030  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00031  * SUCH DAMAGE.
00032  *
00033  * For additional information see http://www.ethernut.de/
00034  */
00035 
00064 #include <cfg/ahdlc.h>
00065 
00066 #include <dev/board.h>
00067 #include <dev/ahdlcavr.h>
00068 #include <dev/ppp.h>
00069 #include <dev/chat.h>
00070 
00071 #include <sys/version.h>
00072 #include <sys/timer.h>
00073 
00074 #include <arpa/inet.h>
00075 #include <netdb.h>
00076 #include <net/if_var.h>
00077 #include <net/route.h>
00078 
00079 #include <pro/dhcp.h>
00080 #include <pro/sntp.h>
00081 #include <pro/rfctime.h>
00082 
00083 #include <stdlib.h>
00084 #include <string.h>
00085 #include <stdio.h>
00086 #include <io.h>
00087 #include <fcntl.h>
00088 #include <time.h>
00089 
00090 /*
00091  * Conversational script with a modem.
00092  *
00093  * The Nut/OS modem chat utility works similar to the the UNIX chat
00094  * script. In general it consists of one or more expect-send pairs of
00095  * strings or optional keyword-parameter pairs. Keywords are
00096  *
00097  * - TIMEOUT to set the max. time in seconds to wait for expected string
00098  * - ABORT to specify up to 10 abort strings
00099  * - REPORT to specify up to 3 reported abort strings
00100  *
00101  * Adjust this script to the requirements of your modem equipment
00102  * and your GPRS provider.
00103  *
00104  * The following script had been tested with a Siemens GPRS modem
00105  * (S55 mobile phone), using a t-mobile pre-paid account.
00106  */
00107 #define PPP_CHAT    /* Wait up to 20 seconds for any response. */ \
00108                     "TIMEOUT 20" \
00109                     /* Expect nothing at the beginning. */ \
00110                     " ''" \
00111                     /* Send simple AT command to check the modem. */ \
00112                     " AT OK" \
00113                     /* Define PDP context, expecting 'OK'. */ \
00114                     " AT+CGDCONT=1,\"IP\",\"internet.t-mobile\" OK" \
00115                     /* Dial and wait for 'CONNECT'. */ \
00116                     " ATD*99***1# CONNECT"
00117 
00118 /*
00119  * PPP user and password.
00120  *
00121  * Often GPRS providers accept any login.
00122  */
00123 #define PPP_USER    "me"
00124 #define PPP_PASS    "secret"
00125 
00126 /*
00127  * PPP device settings.
00128  */
00129 #if defined(NUT_THREAD_AHDLCRXSTACK)
00130 #define PPP_DEV         devAhdlc1   /* AHDLC driver */
00131 #define PPP_DEV_NAME    "uart1"     /* Physical device name */
00132 #define PPP_SPEED       115200      /* Baudrate */
00133 #define PPP_RXTO        1000        /* Receive timeout (ms) */
00134 #else
00135 #warning "PPP is not supported on your target"
00136 #endif
00137 
00138 /*
00139  * Open serial debug port for standard output.
00140  */
00141 static void DebugPortOpen(void)
00142 {
00143     uint32_t baud = 115200;
00144 
00145     /* Register debug UART. */
00146     NutRegisterDevice(&DEV_CONSOLE, 0, 0);
00147     /* Open debug device for standard output. */
00148     freopen(DEV_CONSOLE_NAME, "w", stdout);
00149     /* Set baud rate. */
00150     _ioctl(_fileno(stdout), UART_SETSPEED, &baud);
00151 }
00152 
00153 /*
00154  * Initialize the protocol port.
00155  */
00156 static void ProtocolPortInit(void)
00157 {
00158 #ifdef PPP_DEV
00159     /* Register PPP and UART device. */
00160     NutRegisterDevice(&PPP_DEV, 0, 0);
00161     NutRegisterDevice(&devPpp, 0, 0);
00162 #else
00163     /* Use Ethernet. */
00164     NutRegisterDevice(&DEV_ETHER, 0, 0);
00165 #endif
00166 }
00167 
00168 /*
00169  * Open the physical device.
00170  */
00171 static int ProtocolPortOpen(void)
00172 {
00173 #ifdef PPP_DEV
00174     int pppcom;
00175     uint32_t lctl;
00176 
00177     /* Open PPP device. Specify physical device, user and password. */
00178     printf("Open PPP interface at " PPP_DEV_NAME "...");
00179     pppcom = _open("ppp:" PPP_DEV_NAME "/" PPP_USER "/" PPP_PASS, _O_RDWR | _O_BINARY);
00180     if (pppcom == -1) {
00181         puts("failed");
00182         return -1;
00183     }
00184 
00185     /*
00186      * Set PPP line speed.
00187      */
00188     lctl = PPP_SPEED;
00189     _ioctl(pppcom, UART_SETSPEED, &lctl);
00190     printf("%lu baud", lctl);
00191 
00192     /*
00193      * The PPP driver doesn't set any receive timeout, but
00194      * may require it.
00195      */
00196     lctl = PPP_RXTO;
00197     _ioctl(pppcom, UART_SETREADTIMEOUT, &lctl);
00198     printf(", %lu ms timeout\n", lctl);
00199 
00200     return pppcom;
00201 #else
00202     /* Nothing to be done for Ethernet. */
00203     return 0;
00204 #endif
00205 }
00206 
00207 /*
00208  * Establish a modem connection.
00209  */
00210 static int ProtocolPortConnect(int pppcom)
00211 {
00212 #ifdef PPP_DEV
00213     int rc;
00214 
00215     /*
00216      * Connect using a chat script. We may also set any
00217      * required hardware handshake line at this stage.
00218      */
00219     printf("Connecting...");
00220     for (;;) {
00221         rc = NutChat(pppcom, PPP_CHAT);
00222         switch (rc) {
00223         case 0:
00224             puts("done");
00225             /* A short pause is required here to let the driver
00226                initialize the receiver thread. */
00227             NutSleep(100);
00228             break;
00229         case 1:
00230             puts("bad script");
00231             break;
00232         case 2:
00233             puts("I/O error");
00234             break;
00235         case 3:
00236             puts("no response");
00237             break;
00238         default:
00239             printf("aborted (%d)\n", rc);
00240             break;
00241         }
00242         if (rc != 3) {
00243             break;
00244         }
00245         NutSleep(1000);
00246     }
00247     return rc;
00248 #else
00249     /* Nothing to be done for Ethernet. */
00250     return 0;
00251 #endif
00252 }
00253 
00254 /*
00255  * Hang up.
00256  */
00257 static void ProtocolPortClose(int pppcom)
00258 {
00259 #ifdef PPP_DEV
00260     /* Set the UART back to normal mode. */
00261     _ioctl(pppcom, HDLC_SETIFNET, NULL);
00262     /* Close the physical port. This may or may not hang up. Please
00263        check the modem's documentation. */
00264     _close(pppcom);
00265 #endif
00266 }
00267 
00268 static int ProtocolPortConfigure(void)
00269 {
00270 #ifdef PPP_DEV
00271     PPPDCB *dcb;
00272 
00273     /*
00274      * We are connected, configure our PPP network interface.
00275      * This will initiate the PPP configuration negotiation
00276      * and authentication with the server.
00277      */
00278     printf("Configure network interface...");
00279     if (NutNetIfConfig("ppp", 0, 0, 0)) {
00280         puts("failed");
00281         return -1;
00282     }
00283     puts("done");
00284 
00285     /*
00286      * Set name server and default route. Actually the PPP interface
00287      * should do this, but the current release doesn't.
00288      */
00289     dcb = devPpp.dev_dcb;
00290     NutDnsConfig2(0, 0, dcb->dcb_ip_dns1, dcb->dcb_ip_dns2);
00291     NutIpRouteAdd(0, 0, dcb->dcb_remote_ip, &devPpp);
00292 
00293     /*
00294      * Display our IP settings.
00295      */
00296     printf("     Local IP: %s\n", inet_ntoa(dcb->dcb_local_ip));
00297     printf("    Remote IP: %s\n", inet_ntoa(dcb->dcb_remote_ip));
00298     printf("  Primary DNS: %s\n", inet_ntoa(dcb->dcb_ip_dns1));
00299     printf("Secondary DNS: %s\n", inet_ntoa(dcb->dcb_ip_dns2));
00300 #else
00301     /* We use DHCP on Ethernet. */
00302     printf("Configure network interface...");
00303     if (NutDhcpIfConfig(DEV_ETHER_NAME, 0, 60000)) {
00304         puts("failed");
00305         return -1;
00306     }
00307     puts("done");
00308 #endif
00309 
00310     return 0;
00311 }
00312 
00313 /*
00314  * Connect any NTP-Pool server to query the current time.
00315  */
00316 static void QueryDateAndTime(void)
00317 {
00318     uint32_t ip;
00319     time_t now;
00320     int i;
00321 
00322     /* First connect the DNS server to get the IP address. */
00323     printf("Is There Anybody Out There? ");
00324     ip = NutDnsGetHostByName((uint8_t *) "pool.ntp.org");
00325     if (ip == 0) {
00326         puts("No?");
00327     } else {
00328         /* We do have an IP, now try to connect it. */
00329         printf("Yes, found %s\n", inet_ntoa(ip));
00330         for (i = 0; i < 3; i++) {
00331             printf("What's the time? ");
00332             if (NutSNTPGetTime(&ip, &now) == 0) {
00333                 /* We got a valid response, display the result. */
00334                 printf("%s GMT\n", Rfc1123TimeString(gmtime(&now)));
00335                 return;
00336             } else {
00337                 /* It failed. May be the server is too busy. Try
00338                    again in 5 seconds. */
00339                 puts("Sorry?");
00340                 NutSleep(5000);
00341             }
00342         }
00343     }
00344     /* We give up after 3 trials. */
00345     puts("You missed the starting gun.");
00346 }
00347 
00348 /*
00349  * PPP client application entry.
00350  */
00351 int main(void)
00352 {
00353     int pppcom;
00354 
00355     /* Initialize a debug port for standard output and display a banner. */
00356     DebugPortOpen();
00357     printf("\n\nPPP Client Sample - Nut/OS %s\n", NutVersionString());
00358 
00359     /* Initialize the network interface. */
00360     ProtocolPortInit();
00361     /* This loop runs once per hour. */
00362     for (;;) {
00363         /* Open the network interface. */
00364         pppcom = ProtocolPortOpen();
00365         if (pppcom == -1) {
00366             /* If this fails, we are busted. */
00367             break;
00368         }
00369         /* Establish the modem connection. */
00370         if (ProtocolPortConnect(pppcom) == 0) {
00371             /* Configure the network interface. */
00372             if (ProtocolPortConfigure() == 0) {
00373                 /* Talk to the Internet. */
00374                 QueryDateAndTime();
00375             }
00376         }
00377         /* Hang up. */
00378         ProtocolPortClose(pppcom);
00379 
00380         /* Sleep 1 hour. */
00381         puts("I'll be back in 1 hour.");
00382         NutSleep(3600000);
00383     }
00384     /* Ouch... */
00385     puts("Good bye cruel world");
00386 
00387     return 0;
00388 }