[processor-sdk/pdk.git] / packages / ti / transport / ndk / nimu / example / client / src / client_am572x.c
1 /**\r
2 * @file client_am572x.c\r
3 *\r
4 * @brief TCP/IP Stack 'Client!' Example application\r
5 * \r
6 */\r
7 /*\r
8 * Copyright (c) 2017, Texas Instruments Incorporated\r
9 * All rights reserved.\r
10 *\r
11 * Redistribution and use in source and binary forms, with or without\r
12 * modification, are permitted provided that the following conditions\r
13 * are met:\r
14 *\r
15 * * Redistributions of source code must retain the above copyright\r
16 * notice, this list of conditions and the following disclaimer.\r
17 *\r
18 * * Redistributions in binary form must reproduce the above copyright\r
19 * notice, this list of conditions and the following disclaimer in the\r
20 * documentation and/or other materials provided with the distribution.\r
21 *\r
22 * * Neither the name of Texas Instruments Incorporated nor the names of\r
23 * its contributors may be used to endorse or promote products derived\r
24 * from this software without specific prior written permission.\r
25 *\r
26 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"\r
27 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,\r
28 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\r
29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\r
30 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\r
31 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\r
32 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;\r
33 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,\r
34 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR\r
35 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\r
36 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
37 */\r
38 \r
39 \r
40 /*\r
41 * This is a skeleton application, intended to provide application\r
42 * programmers with a basic Stack setup, to which they can start\r
43 * adding their code.\r
44 */\r
45 \r
46 #include <stdio.h>\r
47 #include <string.h>\r
48 #include <stdlib.h>\r
49 #include <xdc/std.h>\r
50 #include <xdc/runtime/Error.h>\r
51 #include <xdc/runtime/System.h>\r
52 #include <ti/sysbios/BIOS.h>\r
53 #include <ti/sysbios/knl/Task.h>\r
54 \r
55 \r
56 #include <ti/csl/soc.h>\r
57 #include <ti/csl/cslr_device.h>\r
58 \r
59 #include <ti/ndk/inc/stkmain.h>\r
60 #include <ti/ndk/inc/netmain.h>\r
61 #include <ti/ndk/inc/_stack.h>\r
62 #include <ti/ndk/inc/tools/console.h>\r
63 #include <ti/ndk/inc/tools/servers.h>\r
64 #include "ti/transport/ndk/nimu/example/client/src/client.h"\r
65 #include <ti/board/board.h>\r
66 \r
67 #include <ti/drv/emac/emac_drv.h>\r
68 \r
69 #include <ti/drv/uart/UART.h>\r
70 #include <ti/drv/uart/UART_stdio.h>\r
71 \r
72 \r
73 /* Enable the below macro to have prints on the CIO Console */\r
74 //#define IO_CONSOLE\r
75 #ifndef IO_CONSOLE\r
76 #define NIMU_log UART_printf\r
77 #else\r
78 #define NIMU_log printf\r
79 #endif\r
80 \r
81 /* ========================================================================== */\r
82 /* Macros */\r
83 /* ========================================================================== */\r
84 #define MAX_TABLE_ENTRIES 3U\r
85 \r
86 /* ========================================================================== */\r
87 /* Global Variables */\r
88 /* ========================================================================== */\r
89 static int nimu_device_index = 0U;\r
90 \r
91 NIMU_DEVICE_TABLE_ENTRY NIMUDeviceTable[MAX_TABLE_ENTRIES];\r
92 \r
93 extern int CpswEmacInit (STKEVENT_Handle hEvent);\r
94 \r
95 /* Title String */\r
96 char *VerStr = "\nTCP/IP Stack 'Hello World!' Application\n\n";\r
97 \r
98 /* Our NETCTRL callback functions */\r
99 static void NetworkOpen();\r
100 static void NetworkClose();\r
101 static void NetworkIPAddr( uint32_t IPAddr, uint32_t IfIdx, uint32_t fAdd );\r
102 \r
103 \r
104 /* Reporting function */\r
105 static void NIMU_testServiceReport( uint32_t Item, uint32_t Status, uint32_t Report, void* hCfgEntry );\r
106 \r
107 /* Configuration */\r
108 char *HostName = "tiNet";\r
109 char *LocalIPAddr = "192.168.1.4";\r
110 char *LocalIPMask = "255.255.255.0"; // Not used when using DHCP\r
111 char *GatewayIP = "192.168.1.1"; // Not used when using DHCP\r
112 char *DomainName = "demo.net"; // Not used when using DHCP\r
113 char *DNSServer = "0.0.0.0"; // Used when set to anything but zero\r
114 \r
115 \r
116 /* main entry point */\r
117 int main()\r
118 {\r
119 /* Start the BIOS 6 Scheduler */\r
120 BIOS_start ();\r
121 return 0;\r
122 }\r
123 \r
124 /* Main Thread */\r
125 int StackTest()\r
126 {\r
127 int rc;\r
128 void* hCfg;\r
129 CI_SERVICE_TELNET telnet;\r
130 CI_SERVICE_HTTP http;\r
131 \r
132 /* by default, use DHCP */\r
133 bool useStaticIp = false;\r
134 /* Call board init functions */\r
135 Board_initCfg boardCfg;\r
136 \r
137 \r
138 boardCfg = BOARD_INIT_PINMUX_CONFIG |\r
139 BOARD_INIT_MODULE_CLOCK | BOARD_INIT_UART_STDIO;\r
140 Board_init(boardCfg);\r
141 \r
142 #ifdef _TMS320C6X\r
143 CSL_xbarDspIrqConfigure(1,CSL_XBAR_INST_DSP1_IRQ_75, CSL_XBAR_GMAC_SW_IRQ_RX_PULSE);\r
144 CSL_xbarDspIrqConfigure(1,CSL_XBAR_INST_DSP1_IRQ_76, CSL_XBAR_GMAC_SW_IRQ_TX_PULSE);\r
145 #elif defined (__TI_ARM_V7M4__)\r
146 CSL_xbarIpuIrqConfigure(1, CSL_XBAR_INST_IPU1_IRQ_60, CSL_XBAR_GMAC_SW_IRQ_RX_PULSE);\r
147 CSL_xbarIpuIrqConfigure(1, CSL_XBAR_INST_IPU1_IRQ_61, CSL_XBAR_GMAC_SW_IRQ_TX_PULSE);\r
148 #elif defined(__ARM_ARCH_7A__)\r
149 CSL_xbarMpuIrqConfigure(CSL_XBAR_INST_MPU_IRQ_92, CSL_XBAR_GMAC_SW_IRQ_RX_PULSE);\r
150 CSL_xbarMpuIrqConfigure(CSL_XBAR_INST_MPU_IRQ_93, CSL_XBAR_GMAC_SW_IRQ_TX_PULSE);\r
151 #endif\r
152 \r
153 /* Select RGMII 2 ports GMIIx_SEL = 2 for RGMII*/\r
154 CSL_FINS (((CSL_control_coreRegs *) CSL_MPU_CTRL_MODULE_CORE_CORE_REGISTERS_REGS)->CONTROL_IO_1,\r
155 CONTROL_CORE_CONTROL_IO_1_GMII1_SEL, 2U);\r
156 CSL_FINS (((CSL_control_coreRegs *) CSL_MPU_CTRL_MODULE_CORE_CORE_REGISTERS_REGS)->CONTROL_IO_1,\r
157 CONTROL_CORE_CONTROL_IO_1_GMII2_SEL, 2U);\r
158 \r
159 /*GMAC RESET ISOLATION Enable*/\r
160 CSL_FINS (((CSL_control_coreRegs *) CSL_MPU_CTRL_MODULE_CORE_CORE_REGISTERS_REGS)->CONTROL_IO_2,\r
161 CONTROL_CORE_CONTROL_IO_2_GMAC_RESET_ISOLATION_ENABLE, 0U);\r
162 CSL_FINS (((CSL_control_coreRegs *) CSL_MPU_CTRL_MODULE_CORE_CORE_REGISTERS_REGS)->CONTROL_IO_2,\r
163 CONTROL_CORE_CONTROL_IO_2_GMAC_RESET_ISOLATION_ENABLE, 1U);\r
164 \r
165 /* Update device table with NIMU init function */\r
166 NIMUDeviceTable[nimu_device_index++].init = &CpswEmacInit ;\r
167 NIMUDeviceTable[nimu_device_index].init = NULL ;\r
168 \r
169 /* THIS MUST BE THE ABSOLUTE FIRST THING DONE IN AN APPLICATION before\r
170 using the stack*/\r
171 rc = NC_SystemOpen( NC_PRIORITY_LOW, NC_OPMODE_INTERRUPT );\r
172 if( rc )\r
173 {\r
174 UART_printf("NC_SystemOpen Failed (%d)\n",rc);\r
175 for(;;);\r
176 }\r
177 \r
178 /*Create and build the system configuration from scratch. */\r
179 /* Create a new configuration */\r
180 hCfg = CfgNew();\r
181 if( !hCfg )\r
182 {\r
183 UART_printf("Unable to create configuration\n");\r
184 goto main_exit;\r
185 }\r
186 /* Print out our banner */\r
187 UART_printf(VerStr);\r
188 \r
189 \r
190 /* We better validate the length of the supplied names */\r
191 if( strlen( DomainName ) >= CFG_DOMAIN_MAX ||\r
192 strlen( HostName ) >= CFG_HOSTNAME_MAX )\r
193 {\r
194 UART_printf("Names too long\n");\r
195 goto main_exit;\r
196 }\r
197 \r
198 /*Add our global hostname to hCfg (to be claimed in all connected domains) */\r
199 CfgAddEntry( hCfg, CFGTAG_SYSINFO, CFGITEM_DHCP_HOSTNAME, 0,\r
200 strlen(HostName), (uint8_t *)HostName, 0 );\r
201 \r
202 /* By default will use DHCP, set this flag to true above to verify staticIP use case*/\r
203 if (useStaticIp == true)\r
204 {\r
205 CI_IPNET NA;\r
206 CI_ROUTE RT;\r
207 uint32_t IPTmp;\r
208 \r
209 UART_printf("StackTest: using localIp\n");\r
210 /* Setup manual IP address */\r
211 bzero( &NA, sizeof(NA) );\r
212 NA.IPAddr = inet_addr(LocalIPAddr);\r
213 NA.IPMask = inet_addr(LocalIPMask);\r
214 strcpy( NA.Domain, DomainName );\r
215 NA.NetType = 0;\r
216 \r
217 /*Add the address to interface 1 */\r
218 CfgAddEntry( hCfg, CFGTAG_IPNET, 1, 0,\r
219 sizeof(CI_IPNET), (uint8_t *)&NA, 0 );\r
220 \r
221 /* Add the default gateway. Since it is the default, the\r
222 destination address and mask are both zero (we go ahead\r
223 and show the assignment for clarity) */\r
224 bzero( &RT, sizeof(RT) );\r
225 RT.IPDestAddr = 0;\r
226 RT.IPDestMask = 0;\r
227 RT.IPGateAddr = inet_addr(GatewayIP);\r
228 \r
229 /* Add the route */\r
230 CfgAddEntry( hCfg, CFGTAG_ROUTE, 0, 0,\r
231 sizeof(CI_ROUTE), (uint8_t *)&RT, 0 );\r
232 \r
233 /* Manually add the DNS server when specified */\r
234 IPTmp = inet_addr(DNSServer);\r
235 if( IPTmp )\r
236 CfgAddEntry( hCfg, CFGTAG_SYSINFO, CFGITEM_DHCP_DOMAINNAMESERVER,\r
237 0, sizeof(IPTmp), (uint8_t *)&IPTmp, 0 );\r
238 }\r
239 /* Else we specify DHCP */\r
240 else\r
241 {\r
242 UART_printf("StackTest: using dhcp\n");\r
243 CI_SERVICE_DHCPC dhcpc;\r
244 \r
245 /* Specify DHCP Service on IF-1 */\r
246 bzero( &dhcpc, sizeof(dhcpc) );\r
247 dhcpc.cisargs.Mode = CIS_FLG_IFIDXVALID;\r
248 dhcpc.cisargs.IfIdx = 1;\r
249 dhcpc.cisargs.pCbSrv = &NIMU_testServiceReport;\r
250 CfgAddEntry( hCfg, CFGTAG_SERVICE, CFGITEM_SERVICE_DHCPCLIENT, 0,\r
251 sizeof(dhcpc), (uint8_t *)&dhcpc, 0 );\r
252 }\r
253 \r
254 // Specify TELNET service for our Console example\r
255 bzero( &telnet, sizeof(telnet) );\r
256 telnet.cisargs.IPAddr = INADDR_ANY;\r
257 telnet.cisargs.pCbSrv = &NIMU_testServiceReport;\r
258 telnet.param.MaxCon = 2;\r
259 telnet.param.Callback = &ConsoleOpen;\r
260 CfgAddEntry( hCfg, CFGTAG_SERVICE, CFGITEM_SERVICE_TELNET, 0,\r
261 sizeof(telnet), (uint8_t *)&telnet, 0 );\r
262 \r
263 // Create RAM based WEB files for HTTP\r
264 AddWebFiles();\r
265 \r
266 // HTTP Authentication\r
267 {\r
268 CI_ACCT CA;\r
269 \r
270 // Name our authentication group for HTTP (Max size = 31)\r
271 // This is the authentication "realm" name returned by the HTTP\r
272 // server when authentication is required on group 1.\r
273 CfgAddEntry( hCfg, CFGTAG_SYSINFO, CFGITEM_SYSINFO_REALM1,\r
274 0, 30, (uint8_t *)"DSP_CLIENT_DEMO_AUTHENTICATE1", 0 );\r
275 \r
276 /* Create a sample user account who is a member of realm 1.\r
277 * The username and password are just "username" and "password"\r
278 */\r
279 strcpy( CA.Username, "username" );\r
280 strcpy( CA.Password, "password" );\r
281 CA.Flags = CFG_ACCTFLG_CH1; // Make a member of realm 1\r
282 rc = CfgAddEntry( hCfg, CFGTAG_ACCT, CFGITEM_ACCT_REALM,\r
283 0, sizeof(CI_ACCT), (uint8_t *)&CA, 0 );\r
284 }\r
285 \r
286 /* Specify HTTP service */\r
287 bzero( &http, sizeof(http) );\r
288 http.cisargs.IPAddr = INADDR_ANY;\r
289 http.cisargs.pCbSrv = &NIMU_testServiceReport;\r
290 CfgAddEntry( hCfg, CFGTAG_SERVICE, CFGITEM_SERVICE_HTTP, 0,\r
291 sizeof(http), (uint8_t *)&http, 0 );\r
292 \r
293 \r
294 \r
295 /* Configure IPStack/OS Options */\r
296 \r
297 /* We don't want to see debug messages less than WARNINGS */\r
298 rc = DBG_WARN;\r
299 CfgAddEntry( hCfg, CFGTAG_OS, CFGITEM_OS_DBGPRINTLEVEL,\r
300 CFG_ADDMODE_UNIQUE, sizeof(uint32_t), (uint8_t *)&rc, 0 );\r
301 \r
302 /* This code sets up the TCP and UDP buffer sizes\r
303 (Note 8192 is actually the default. This code is here to\r
304 illustrate how the buffer and limit sizes are configured.) \r
305 */\r
306 \r
307 /* TCP Transmit buffer size */\r
308 rc = 8192;\r
309 CfgAddEntry( hCfg, CFGTAG_IP, CFGITEM_IP_SOCKTCPTXBUF,\r
310 CFG_ADDMODE_UNIQUE, sizeof(uint32_t), (uint8_t *)&rc, 0 );\r
311 \r
312 /*TCP Receive buffer size */\r
313 rc = 8192;\r
314 CfgAddEntry( hCfg, CFGTAG_IP, CFGITEM_IP_SOCKTCPRXBUF,\r
315 CFG_ADDMODE_UNIQUE, sizeof(uint32_t), (uint8_t *)&rc, 0 );\r
316 \r
317 /* TCP Receive limit (non-copy mode) */\r
318 rc = 8192;\r
319 CfgAddEntry( hCfg, CFGTAG_IP, CFGITEM_IP_SOCKTCPRXLIMIT,\r
320 CFG_ADDMODE_UNIQUE, sizeof(uint32_t), (uint8_t *)&rc, 0 );\r
321 \r
322 /* UDP Receive limit */\r
323 rc = 8192;\r
324 CfgAddEntry( hCfg, CFGTAG_IP, CFGITEM_IP_SOCKUDPRXLIMIT,\r
325 CFG_ADDMODE_UNIQUE, sizeof(uint32_t), (uint8_t *)&rc, 0 );\r
326 \r
327 /* increase stack size */\r
328 rc = 8192;\r
329 CfgAddEntry(hCfg, CFGTAG_OS, CFGITEM_OS_TASKSTKBOOT, CFG_ADDMODE_UNIQUE, sizeof(uint32_t), (uint8_t *)&rc, 0 );\r
330 \r
331 /* Boot the system using this configuration\r
332 We keep booting until the function returns 0. This allows\r
333 us to have a "reboot" command. \r
334 */\r
335 \r
336 do\r
337 {\r
338 rc = NC_NetStart( hCfg, NetworkOpen, NetworkClose, NetworkIPAddr );\r
339 } while( rc > 0 );\r
340 \r
341 /* Free the WEB files */\r
342 RemoveWebFiles();\r
343 /* Delete Configuration */\r
344 CfgFree( hCfg );\r
345 \r
346 /*Close the OS */\r
347 main_exit:\r
348 UART_printf("StackTest: exiting\n");\r
349 NC_SystemClose();\r
350 return(0);\r
351 }\r
352 \r
353 \r
354 /* System Task Code [ Server Daemon Servers ] */\r
355 static HANDLE hEcho=0,hEchoUdp=0,hData=0,hNull=0,hOob=0;\r
356 \r
357 #ifdef _INCLUDE_IPv6_CODE\r
358 static HANDLE hEcho6=0, hEchoUdp6=0, hTelnet6=0, hOob6=0, hWeb6=0;\r
359 #endif\r
360 \r
361 \r
362 /* NetworkOpen\r
363 *This function is called after the configuration has booted\r
364 */\r
365 static void NetworkOpen()\r
366 {\r
367 // Create our local servers\r
368 hEcho = DaemonNew( SOCK_STREAMNC, 0, 7, dtask_tcp_echo,\r
369 OS_TASKPRINORM, OS_TASKSTKNORM, 0, 3 );\r
370 hEchoUdp = DaemonNew( SOCK_DGRAM, 0, 7, dtask_udp_echo,\r
371 OS_TASKPRINORM, OS_TASKSTKNORM, 0, 1 );\r
372 hData = DaemonNew( SOCK_STREAM, 0, 1000, dtask_tcp_datasrv,\r
373 OS_TASKPRINORM, OS_TASKSTKNORM, 0, 3 );\r
374 hNull = DaemonNew( SOCK_STREAMNC, 0, 1001, dtask_tcp_nullsrv,\r
375 OS_TASKPRINORM, OS_TASKSTKNORM, 0, 3 );\r
376 hOob = DaemonNew( SOCK_STREAMNC, 0, 999, dtask_tcp_oobsrv,\r
377 OS_TASKPRINORM, OS_TASKSTKNORM, 0, 3 );\r
378 \r
379 // Create the IPv6 Local Servers.\r
380 #ifdef _INCLUDE_IPv6_CODE\r
381 hEcho6 = Daemon6New (SOCK_STREAM, IPV6_UNSPECIFIED_ADDRESS, 7, dtask_tcp_echo6,\r
382 OS_TASKPRINORM, OS_TASKSTKNORM, 0, 3 );\r
383 hEchoUdp6 = Daemon6New (SOCK_DGRAM, IPV6_UNSPECIFIED_ADDRESS, 7, dtask_udp_echo6,\r
384 OS_TASKPRINORM, OS_TASKSTKNORM, 0, 1 );\r
385 hTelnet6 = Daemon6New (SOCK_STREAM, IPV6_UNSPECIFIED_ADDRESS, 23,\r
386 (int(*)(SOCKET,uint32_t))telnetClientProcess, OS_TASKPRINORM, OS_TASKSTKLOW,\r
387 (uint32_t)ConsoleOpen, 2 );\r
388 hOob6 = Daemon6New (SOCK_STREAM, IPV6_UNSPECIFIED_ADDRESS, 999, dtask_tcp_oobsrv,\r
389 OS_TASKPRINORM, OS_TASKSTKNORM, 0, 3 );\r
390 hWeb6 = Daemon6New (SOCK_STREAM, IPV6_UNSPECIFIED_ADDRESS, HTTPPORT, httpClientProcess,\r
391 OS_TASKPRINORM, OS_TASKSTKHIGH, 0, 4);\r
392 #endif\r
393 }\r
394 \r
395 \r
396 /* NetworkClose\r
397 *This function is called when the network is shutting down,\r
398 * or when it no longer has any IP addresses assigned to it.\r
399 */\r
400 static void NetworkClose()\r
401 {\r
402 DaemonFree( hOob );\r
403 DaemonFree( hNull );\r
404 DaemonFree( hData );\r
405 DaemonFree( hEchoUdp );\r
406 DaemonFree( hEcho );\r
407 \r
408 #ifdef _INCLUDE_IPv6_CODE\r
409 Daemon6Free (hEcho6);\r
410 Daemon6Free (hEchoUdp6);\r
411 Daemon6Free (hTelnet6);\r
412 Daemon6Free (hOob6);\r
413 Daemon6Free (hWeb6);\r
414 #endif\r
415 \r
416 #ifdef TEST_RAW_SEND\r
417 TaskDestroy (hSendRaw);\r
418 #endif\r
419 #ifdef TEST_RAW_RECV\r
420 TaskDestroy (hRecvRaw);\r
421 #endif\r
422 \r
423 // Kill any active console\r
424 ConsoleClose();\r
425 }\r
426 \r
427 /* NetworkIPAddr\r
428 *This function is called whenever an IP address binding is\r
429 * added or removed from the system.\r
430 */\r
431 static void NetworkIPAddr( uint32_t IPAddr, uint32_t IfIdx, uint32_t fAdd )\r
432 {\r
433 uint32_t IPTmp;\r
434 \r
435 if( fAdd )\r
436 UART_printf("Network Added: ");\r
437 else\r
438 UART_printf("Network Removed: ");\r
439 \r
440 // Print a message\r
441 IPTmp = NDK_ntohl( IPAddr );\r
442 UART_printf("If-%d:%d.%d.%d.%d\n", IfIdx,\r
443 (uint8_t)(IPTmp>>24)&0xFF, (uint8_t)(IPTmp>>16)&0xFF,\r
444 (uint8_t)(IPTmp>>8)&0xFF, (uint8_t)IPTmp&0xFF );\r
445 }\r
446 \r
447 //\r
448 // Nimu_testDHCPReset()\r
449 //\r
450 // Code to reset DHCP client by removing it from the active config,\r
451 // and then reinstalling it.\r
452 //\r
453 // Called with:\r
454 // IfIdx set to the interface (1-n) that is using DHCP.\r
455 // fOwnTask set when called on a new task thread (via TaskCreate()).\r
456 //\r
457 void Nimu_testDHCPReset( uint32_t IfIdx, uint32_t fOwnTask )\r
458 {\r
459 CI_SERVICE_DHCPC dhcpc;\r
460 void* h;\r
461 int rc,tmp;\r
462 uint32_t idx;\r
463 \r
464 // If we were called from a newly created task thread, allow\r
465 // the entity that created us to complete\r
466 if( fOwnTask )\r
467 TaskSleep(500);\r
468 \r
469 // Find DHCP on the supplied interface\r
470 for(idx=1; ; idx++)\r
471 {\r
472 // Find a DHCP entry\r
473 rc = CfgGetEntry( 0, CFGTAG_SERVICE, CFGITEM_SERVICE_DHCPCLIENT,\r
474 idx, &h );\r
475 if( rc != 1 )\r
476 goto RESET_EXIT;\r
477 \r
478 // Get DHCP entry data\r
479 tmp = sizeof(dhcpc);\r
480 rc = CfgEntryGetData( h, &tmp, (uint8_t *)&dhcpc );\r
481 \r
482 // If not the right entry, continue\r
483 if( (rc<=0) || dhcpc.cisargs.IfIdx != IfIdx )\r
484 {\r
485 CfgEntryDeRef(h);\r
486 h = 0;\r
487 continue;\r
488 }\r
489 \r
490 // This is the entry we want!\r
491 \r
492 // Remove the current DHCP service\r
493 CfgRemoveEntry( 0, h );\r
494 \r
495 // Specify DHCP Service on specified IF\r
496 bzero( &dhcpc, sizeof(dhcpc) );\r
497 dhcpc.cisargs.Mode = CIS_FLG_IFIDXVALID;\r
498 dhcpc.cisargs.IfIdx = IfIdx;\r
499 dhcpc.cisargs.pCbSrv = &NIMU_testServiceReport;\r
500 CfgAddEntry( 0, CFGTAG_SERVICE, CFGITEM_SERVICE_DHCPCLIENT, 0,\r
501 sizeof(dhcpc), (uint8_t *)&dhcpc, 0 );\r
502 break;\r
503 }\r
504 \r
505 RESET_EXIT:\r
506 // If we are a function, return, otherwise, call TaskExit()\r
507 if( fOwnTask )\r
508 TaskExit();\r
509 }\r
510 \r
511 /* Service Status Reports\r
512 * Here's a quick example of using service status updates\r
513 */\r
514 static char *TaskName[] = { "Telnet","HTTP","NAT","DHCPS","DHCPC","DNS" };\r
515 static char *StatusStr[] = { "Disabled","Waiting","IPTerm","Failed","Enabled" };\r
516 static void NIMU_testServiceReport( uint32_t Item, uint32_t Status, uint32_t Report, void* h )\r
517 {\r
518 \r
519 UART_printf( "Service Status: %s: %s\n", TaskName[Item-1], StatusStr[Status]);\r
520 \r
521 /* Example of adding to the DHCP configuration space\r
522 *\r
523 * When using the DHCP client, the client has full control over access\r
524 * to the first 256 entries in the CFGTAG_SYSINFO space.\r
525 *\r
526 * Note that the DHCP client will erase all CFGTAG_SYSINFO tags except\r
527 * CFGITEM_DHCP_HOSTNAME. If the application needs to keep manual\r
528 * entries in the DHCP tag range, then the code to maintain them should\r
529 * be placed here.\r
530 *\r
531 * Here, we want to manually add a DNS server to the configuration, but\r
532 * we can only do it once DHCP has finished its programming.\r
533 */\r
534 if( Item == CFGITEM_SERVICE_DHCPCLIENT &&\r
535 Status == CIS_SRV_STATUS_ENABLED &&\r
536 (Report == (NETTOOLS_STAT_RUNNING|DHCPCODE_IPADD) ||\r
537 Report == (NETTOOLS_STAT_RUNNING|DHCPCODE_IPRENEW)) )\r
538 {\r
539 uint32_t IPTmp;\r
540 \r
541 // Manually add the DNS server when specified\r
542 IPTmp = inet_addr(DNSServer);\r
543 if( IPTmp )\r
544 CfgAddEntry( 0, CFGTAG_SYSINFO, CFGITEM_DHCP_DOMAINNAMESERVER,\r
545 0, sizeof(IPTmp), (uint8_t *)&IPTmp, 0 );\r
546 }\r
547 \r
548 // Reset DHCP client service on failure\r
549 if( Item==CFGITEM_SERVICE_DHCPCLIENT && (Report&~0xFF)==NETTOOLS_STAT_FAULT )\r
550 {\r
551 CI_SERVICE_DHCPC dhcpc;\r
552 int tmp;\r
553 \r
554 // Get DHCP entry data (for index to pass to Nimu_testDHCPReset).\r
555 tmp = sizeof(dhcpc);\r
556 CfgEntryGetData( h, &tmp, (uint8_t *)&dhcpc );\r
557 \r
558 // Create the task to reset DHCP on its designated IF\r
559 // We must use TaskCreate instead of just calling the function as\r
560 // we are in a callback function.\r
561 TaskCreate( Nimu_testDHCPReset, "DHCPreset", OS_TASKPRINORM, 0x1000,\r
562 dhcpc.cisargs.IfIdx, 1, 0 );\r
563 }\r
564 }\r
565 \r
566 \r
567 \r
568 \r