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