pppc.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2003-2006 by egnite Software GmbH
00003  *
00004  * All rights reserved.
00005  *
00006  * Redistribution and use in source and binary forms, with or without
00007  * modification, are permitted provided that the following conditions
00008  * are met:
00009  *
00010  * 1. Redistributions of source code must retain the above copyright
00011  *    notice, this list of conditions and the following disclaimer.
00012  * 2. Redistributions in binary form must reproduce the above copyright
00013  *    notice, this list of conditions and the following disclaimer in the
00014  *    documentation and/or other materials provided with the distribution.
00015  * 3. Neither the name of the copyright holders nor the names of
00016  *    contributors may be used to endorse or promote products derived
00017  *    from this software without specific prior written permission.
00018  *
00019  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00020  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00021  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00022  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00023  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00024  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00025  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
00026  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
00027  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00028  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
00029  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00030  * SUCH DAMAGE.
00031  *
00032  * For additional information see http://www.ethernut.de/
00033  */
00034 
00055 #include <cfg/arch.h>
00056 
00057 /*
00058  * PPP user and password.
00059  */
00060 #define PPPUSER     "me"
00061 #define PPPPASS     "secret"
00062 
00063 /*
00064  * The Nut/OS modem chat utility works similar to the the UNIX
00065  * chat script. This one is used to connect to a Windows PC
00066  * using a direct cable.
00067  */
00068 #define PPPCHAT     "TIMEOUT 2 '' CLIENT\\c CLIENTSERVER"
00069 
00070 /*
00071  * A very simple modem script.
00072  */
00073 //#define PPPCHAT     "'' AT OK ATD555 CONNECT"
00074 
00075 
00076 /*
00077  * PPP device settings.
00078  */
00079 #if defined(__AVR__)
00080 #define PPPDEV      devAhdlc0   /* Use HDLC driver. */
00081 //#define PPPDEV      devUart0    /* Use standard UART driver. */
00082 #else
00083 #warning "Works on ATmega128 only."
00084 #endif
00085 #define PPPCOM      "uart0"     /* Physical device name. */
00086 #define PPPSPEED    115200      /* Baudrate. */
00087 #define PPPRXTO     1000        /* Character receive timeout. */
00088 
00089 
00090 /*
00091  * Server input buffer size.
00092  */
00093 #define RXBUFFSIZE  256
00094 
00095 #include <cfg/os.h>
00096 #include <dev/debug.h>
00097 //#include <dev/hd44780.h>
00098 #include <dev/ahdlcavr.h>
00099 //#include <dev/uartavr.h>
00100 #include <dev/ppp.h>
00101 #include <dev/chat.h>
00102 
00103 #include <sys/version.h>
00104 #include <sys/heap.h>
00105 #include <sys/thread.h>
00106 #include <sys/socket.h>
00107 
00108 #include <sys/timer.h>
00109 
00110 #include <arpa/inet.h>
00111 #include <netdb.h>
00112 #include <net/if_var.h>
00113 #include <net/route.h>
00114 
00115 #ifdef NUTDEBUG
00116 #include <net/netdebug.h>
00117 #endif
00118 
00119 #include <stdlib.h>
00120 #include <string.h>
00121 #include <stdio.h>
00122 #include <io.h>
00123 #include <fcntl.h>
00124 
00125 #if defined(__IMAGECRAFT__)
00126 #define CC_STRING   "ICCAVR"
00127 #elif defined(__GNUC__)
00128 #define CC_STRING   "AVRGCC"
00129 #else
00130 #define CC_STRING   "Compiler unknown"
00131 #endif
00132 
00133 /*
00134  * Debug output device settings.
00135  */
00136 #ifdef __AVR_ENHANCED__
00137 #define DBGDEV      devDebug1   /* Use debug driver. */
00138 //#define DBGDEV      devUart1    /* Use standard UART driver. */
00139 #define DBGCOM      "uart1"     /* Device name. */
00140 #define DBGSPEED    115200      /* Baudrate. */
00141 #endif
00142 
00143 prog_char vbanner_P[] = "\n\nPPP Client Sample - Nut/OS %s - " CC_STRING "\n";
00144 prog_char banner_P[] = "200 Welcome to tcps. Type help to get help.\r\n";
00145 prog_char help_P[] = "400 List of commands follows\r\n"
00146     "m[emory]\tQueries number of RAM bytes free.\r\n"
00147     "t[hreads]\tLists all created threads.\r\n"
00148     "ti[mers]\tLists all running timers.\r\n" "q[uit]\t\tTerminates connection.\r\n" ".\r\n";
00149 prog_char thread_intro_P[] = "220 List of threads with name,state,prio,stack,mem,timeout follows\r\n";
00150 prog_char timer_intro_P[] = "221 List of timers with ticks left and interval follows\r\n";
00151 prog_char mem_fmt_P[] = "210 %lu bytes RAM free\r\n";
00152 
00153 
00154 /*
00155  * Process client requests.
00156  */
00157 void ProcessRequests(FILE * stream)
00158 {
00159     int got;
00160     char *cp;
00161     char *buff;
00162 
00163     /*
00164      * We allocate the input buffer from heap memory.
00165      */
00166     buff = malloc(RXBUFFSIZE);
00167 
00168     /*
00169      * Send a welcome banner.
00170      */
00171     fputs_P(banner_P, stream);
00172     for (;;) {
00173 
00174         /*
00175          * Flush output and read a line.
00176          */
00177         fflush(stream);
00178         if (fgets(buff, RXBUFFSIZE, stream) == 0)
00179             break;
00180 
00181         /*
00182          * Chop off EOL.
00183          */
00184         if ((cp = strchr(buff, '\r')) != 0)
00185             *cp = 0;
00186         if ((cp = strchr(buff, '\n')) != 0)
00187             *cp = 0;
00188 
00189         /*
00190          * Ignore blank lines.
00191          */
00192         got = strlen(buff);
00193         if (got == 0)
00194             continue;
00195 
00196         /*
00197          * Memory info.
00198          */
00199         if (strncmp(buff, "memory", got) == 0) {
00200             fprintf_P(stream, mem_fmt_P, NutHeapAvailable());
00201             continue;
00202         }
00203 
00204         /*
00205          * List threads.
00206          */
00207         if (strncmp(buff, "threads", got) == 0) {
00208             NUTTHREADINFO *tdp;
00209             NUTTIMERINFO *tnp;
00210 
00211             fputs_P(thread_intro_P, stream);
00212             for (tdp = nutThreadList; tdp; tdp = tdp->td_next) {
00213                 fputs(tdp->td_name, stream);
00214                 switch (tdp->td_state) {
00215                 case TDS_TERM:
00216                     fputs("\tTerm\t", stream);
00217                     break;
00218                 case TDS_RUNNING:
00219                     fputs("\tRun\t", stream);
00220                     break;
00221                 case TDS_READY:
00222                     fputs("\tReady\t", stream);
00223                     break;
00224                 case TDS_SLEEP:
00225                     fputs("\tSleep\t", stream);
00226                     break;
00227                 }
00228                 fprintf(stream, "%u\t%u", tdp->td_priority, (uint16_t) tdp->td_sp - (uint16_t) tdp->td_memory);
00229                 if (*((uint32_t *) tdp->td_memory) != DEADBEEF)
00230                     fputs("\tCorrupted\t", stream);
00231                 else
00232                     fputs("\tOK\t", stream);
00233 
00234                 if ((tnp = (NUTTIMERINFO *) tdp->td_timer) != 0)
00235                     fprintf(stream, "%lu\r\n", tnp->tn_ticks_left);
00236                 else
00237                     fputs("None\r\n", stream);
00238             }
00239             fputs(".\r\n", stream);
00240             continue;
00241         }
00242 
00243         /*
00244          * List timers.
00245          */
00246         if (strncmp("timers", buff, got) == 0) {
00247             NUTTIMERINFO *tnp;
00248 
00249             fputs_P(timer_intro_P, stream);
00250             for (tnp = nutTimerList; tnp; tnp = tnp->tn_next) {
00251                 fprintf(stream, "%lu\t", tnp->tn_ticks_left);
00252                 if (tnp->tn_ticks)
00253                     fprintf(stream, "%lu\r\n", tnp->tn_ticks);
00254                 else
00255                     fputs("Oneshot\r\n", stream);
00256             }
00257             fputs(".\r\n", stream);
00258             continue;
00259         }
00260 
00261         /*
00262          * Quit connection.
00263          */
00264         if (strncmp("quit", buff, got) == 0) {
00265             break;
00266         }
00267 
00268         /*
00269          * Display help text on any unknown command.
00270          */
00271         fputs_P(help_P, stream);
00272     }
00273 }
00274 
00275 /*
00276  * PPP client application entry.
00277  */
00278 int main(void)
00279 {
00280     int pppcom;
00281     uint32_t lctl;
00282 #ifdef PPPDEV
00283     PPPDCB *dcb;
00284     int rc;
00285 #endif
00286     /*
00287      * Register our devices.
00288      */
00289 #ifdef __AVR_ENHANCED__
00290     NutRegisterDevice(&DBGDEV, 0, 0);
00291 #endif
00292 #ifdef PPPDEV
00293     NutRegisterDevice(&PPPDEV, 0, 0);
00294     NutRegisterDevice(&devPpp, 0, 0);
00295 #endif
00296 
00297     /*
00298      * Open debug device for standard output.
00299      */
00300     if(freopen("uart1", "w", stdout) == 0) {
00301         for(;;);
00302     }
00303 
00304     /*
00305      * Set debug output speed.
00306      */
00307 #ifdef __AVR_ENHANCED__
00308     lctl = DBGSPEED;
00309     _ioctl(_fileno(stdout), UART_SETSPEED, &lctl);
00310 #endif
00311 
00312     /*
00313      * Display banner including compiler info and Nut/OS version.
00314      */
00315     printf_P(vbanner_P, NutVersionString());
00316 
00317     /*
00318      * Open PPP device. Specify physical device, user and password.
00319      */
00320     printf("Open uart...");
00321     if ((pppcom = _open("ppp:" PPPCOM "/" PPPUSER "/" PPPPASS, _O_RDWR | _O_BINARY)) == -1) {
00322         printf("Failed to open " PPPCOM "\n");
00323         for (;;);
00324     }
00325     puts("done");
00326 
00327 #ifdef PPPDEV
00328     /*
00329      * Set PPP line speed.
00330      */
00331     lctl = PPPSPEED;
00332     _ioctl(pppcom, UART_SETSPEED, &lctl);
00333 
00334     /*
00335      * The PPP driver doesn't set any receive timeout, but
00336      * may require it.
00337      */
00338     lctl = PPPRXTO;
00339     _ioctl(pppcom, UART_SETREADTIMEOUT, &lctl);
00340 
00341 #ifdef NUTDEBUG
00342     /*
00343      * Optionally enable PPP trace.
00344      */
00345     NutTracePPP(stdout, 1);
00346 #endif
00347 
00348     /*
00349      * This delay may be removed. It is quite helpful during development.
00350      */
00351     NutSleep(5000);
00352 
00353     /*
00354      * PPP connection loop.
00355      */
00356     for (;;) {
00357         /*
00358          * Connect using a chat script. We may also set any
00359          * required hardware handshake line at this stage.
00360          */
00361         printf("Connecting...");
00362         if ((rc = NutChat(pppcom, PPPCHAT)) != 0) {
00363             printf("no connect, reason = %d\n", rc);
00364             continue;
00365         }
00366         puts("done");
00367 
00368         /*
00369          * We are connected, configure our PPP network interface.
00370          * This will initiate the PPP configuration negotiation
00371          * and authentication with the server.
00372          */
00373         printf("Configure PPP...");
00374         rc = NutNetIfConfig("ppp", 0, 0, 0);
00375         if (rc != 0) {
00376             puts("failed");
00377             /*
00378              * Optionally toggle DTR to hang up the modem.
00379              */
00380             continue;
00381         }
00382         puts("done");
00383 
00384         /*
00385          * Set name server and default route. Actually the PPP interface
00386          * should do this, but the current release doesn't.
00387          */
00388         dcb = devPpp.dev_dcb;
00389         NutDnsConfig2(0, 0, dcb->dcb_ip_dns1, dcb->dcb_ip_dns2);
00390         NutIpRouteAdd(0, 0, dcb->dcb_remote_ip, &devPpp);
00391 
00392         /*
00393          * Display our IP settings.
00394          */
00395         printf("     Local IP: %s\n", inet_ntoa(dcb->dcb_local_ip));
00396         printf("    Remote IP: %s\n", inet_ntoa(dcb->dcb_remote_ip));
00397         printf("  Primary DNS: %s\n", inet_ntoa(dcb->dcb_ip_dns1));
00398         printf("Secondary DNS: %s\n", inet_ntoa(dcb->dcb_ip_dns2));
00399 
00400         /*
00401          * Client connection loop.
00402          */
00403         for (;;) {
00404             TCPSOCKET *sock;
00405             FILE *stream;
00406 
00407             /*
00408              * Create a socket.
00409              */
00410             if ((sock = NutTcpCreateSocket()) != 0) {
00411 
00412                 /*
00413                  * Listen on port 23. If we return, we got a client.
00414                  */
00415                 printf("Waiting for a client...");
00416                 if (NutTcpAccept(sock, 23) == 0) {
00417                     puts("connected");
00418 
00419                     /*
00420                      * Open a stream and associate it with the socket, so
00421                      * we can use standard I/O. Note, that socket streams
00422                      * currently do support text mode.
00423                      */
00424                     if ((stream = _fdopen((int) sock, "r+b")) != 0) {
00425                         /*
00426                          * Process client requests.
00427                          */
00428                         ProcessRequests(stream);
00429                         puts("\nDisconnected");
00430 
00431                         /*
00432                          * Close the stream.
00433                          */
00434                         fclose(stream);
00435                     } else {
00436                         puts("Assigning a stream failed");
00437                     }
00438                 } else {
00439                     puts("failed");
00440                 }
00441 
00442                 /*
00443                  * Close our socket.
00444                  */
00445                 NutTcpCloseSocket(sock);
00446             }
00447             NutSleep(1000);
00448             printf("%u bytes free\n", NutHeapAvailable());
00449         }
00450     }
00451 #endif /* PPPDEV */
00452     return 0;
00453 }

© 2000-2010 by contributors - visit http://www.ethernut.de/