1 /*---------------------------------------------------------------------------*
2   Project:  RevoEX - demos - share
3   File:     init.c
4 
5   Copyright 2006 Nintendo. All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain
8   proprietary information of Nintendo of America Inc. and/or Nintendo
9   Company Ltd., and are protected by Federal copyright law. They may
10   not be disclosed to third parties or copied or duplicated in any form,
11   in whole or in part, without the prior written consent of Nintendo.
12  *---------------------------------------------------------------------------*/
13 
14 #include <revolution/os.h>
15 #include <revolution/ncd.h>
16 #include <revolution/so.h>
17 #include <revolution/net.h>
18 #include <string.h>
19 #include <stdlib.h>
20 #include "rexdemo/netconfig.h"
21 #include "rexdemo/graphic.h"
22 
23 /*---------------------------------------------------------------------------*
24     Variable Definitions
25  *---------------------------------------------------------------------------*/
26 
27 static u8 NetConfigId = 0;
28 static char PeerName[256];
29 
30 /*---------------------------------------------------------------------------*
31     Internal function prototype declarations
32  *---------------------------------------------------------------------------*/
33 
34 BOOL
REXDEMOStartNetwork(BOOL override)35 REXDEMOStartNetwork(BOOL override)
36 {
37     s32 result = 0;
38 
39     /* Overwrite the network setting stored in NAND? */
40     if (override)
41     {
42         /* Overwrite the network setting based on argument analysis result (for debug) */
43         result = REXDEMOOverrideNetConfigAuto();
44         if (result < NCD_RESULT_SUCCESS)
45         {
46             REXDEMOError("REXDEMOOverrideNetConfigAuto() failed.(%d)", result);
47             return FALSE;
48         }
49     }
50 
51     /* Create the heap to be given to the socket library */
52     if (!REXDEMOCreateHeapForSocket( REXDEMO_SOCKET_HEAPSIZE_DEFAULT ))
53     {
54         REXDEMOError("REXDEMOCreateHeapForSocket() failed.");
55         return FALSE;
56     }
57     /* Initialize the socket library by specifying the allocator in REXDEMO */
58     result = SOInit( REXDEMOGetSOLibConfig() );
59     if (result == SO_EALREADY)
60     {
61         REXDEMOError("SOInit() already done. (%d)", result);
62     }
63     else if (result < SO_SUCCESS)
64     {
65         REXDEMOError("SOInit() failed.(%d)", result);
66         return FALSE;
67     }
68 
69     /* Start the network feature of the socket library */
70     result = SOStartup();
71     if (result == SO_EALREADY)
72     {
73         REXDEMOError("SOStartup() already done. (%d)", result);
74     }
75     else if (result < SO_SUCCESS)
76     {
77         REXDEMOError("SOStartup() failed.(%d)", result);
78         REXDEMOError("Network Error Code is %d", -NETGetStartupErrorCode(result));
79         return FALSE;
80     }
81 
82     /* SOStartup now waits for DHCP to be resolved */
83 
84     return TRUE;
85 }
86 
87 BOOL
REXDEMOSafeSOFinish(void)88 REXDEMOSafeSOFinish( void )
89 {
90     s32 iRetry;
91     s32 result;
92     BOOL succeeded = TRUE;
93 
94     for ( iRetry = REXDEMO_NETWORK_TERMINATION_RETRY_LIMIT; iRetry > 0; iRetry-- )
95     {
96         result = SOFinish();
97         if ( result == SO_EBUSY || result == SO_EAGAIN || result == SO_EINPROGRESS )
98         {
99             s32 r;
100             REXDEMOError("SOFinish() failed.(%d)\n", result);
101 
102             /* This is a state in which SOFinish cannot be called. Try SOCleanup.*/
103             REXDEMOReport( "Try SOCleanup()...\n" );
104             r = SOCleanup();
105             if ( r < SO_SUCCESS )
106             {
107                 REXDEMOError("SOCleanup() failed.(%d)\n", r);
108             }
109             /* wait for other processes to release their network-related resources*/
110             OSSleepMilliseconds( REXDEMO_NETWORK_TERMINATION_RETRY_WAIT );
111         }
112         else
113         {
114             break;
115         }
116     }
117     if (result == SO_EALREADY)
118     {
119         /* either SOFinish has already been called, or SOInit was not called in the first place*/
120         /* the state is the same as after SOFinish is called, so set the return value to TRUE*/
121         REXDEMOError("SOFinish() already done. (%d)", result);
122     }
123     else if (result < SO_SUCCESS)
124     {
125         /* an unexpected error in SOFinish that should not occur*/
126         /* error processing is required*/
127         REXDEMOError("SOFinish() failed.(%d)", result);
128         succeeded = FALSE;
129     }
130 
131     if ( iRetry <= 0 )
132     {
133         /* The retry limit was reached*/
134         /* Error processing is required because network termination could not be carried out properly*/
135         REXDEMOError("Too many network termination retries; give up to call SOFinish().\n");
136         succeeded = FALSE;
137     }
138 
139     return succeeded;
140 }
141 
142 BOOL
REXDEMOEndNetwork(void)143 REXDEMOEndNetwork( void )
144 {
145     s32 result = 0;
146     BOOL succeeded = TRUE;
147 
148     /* Stop the network function of the socket library */
149     result = SOCleanup();
150     if (result == SO_EALREADY)
151     {
152         REXDEMOError("SOCleanup() already done. (%d)", result);
153     }
154     else if (result < SO_SUCCESS)
155     {
156         REXDEMOError("SOCleanup() failed.(%d)", result);
157         succeeded = FALSE;
158     }
159 
160     /* Deallocate the socket library resource */
161     if (REXDEMOSafeSOFinish() == FALSE)
162     {
163         succeeded = FALSE;
164     }
165 
166     /* Deallocate the heap given to the socket library*/
167     REXDEMODestroyHeapForSocket();
168 
169     return succeeded;
170 }
171 
172 /*---------------------------------------------------------------------------*
173  *---------------------------------------------------------------------------*/
174 
175 /*---------------------------------------------------------------------------*
176   Name        : REXDEMOSetNetConfigId
177   Description :
178   Arguments   : configId     -
179   Returns     : None.
180  *---------------------------------------------------------------------------*/
181 void
REXDEMOSetNetConfigId(u8 configId)182 REXDEMOSetNetConfigId( u8 configId )
183 {
184     NetConfigId = configId;
185 }
186 
187 /*---------------------------------------------------------------------------*
188   Name        : REXDEMOGetNetConfigId
189   Description :
190   Arguments   : None.
191   Returns     : u8           -
192  *---------------------------------------------------------------------------*/
193 u8
REXDEMOGetNetConfigId(void)194 REXDEMOGetNetConfigId( void )
195 {
196     return NetConfigId;
197 }
198 
199 /*---------------------------------------------------------------------------*
200   Name        : REXDEMOSetPeerName
201   Description :
202   Arguments   : peerName -
203   Returns     : None.
204  *---------------------------------------------------------------------------*/
205 void
REXDEMOSetPeerName(const char * peerName)206 REXDEMOSetPeerName( const char* peerName )
207 {
208     if( peerName != NULL )
209     {
210         (void)strncpy(PeerName, peerName, sizeof(PeerName)-1);
211         PeerName[sizeof(PeerName)-1] = 0;
212     }
213     else
214     {
215         (void)memset(PeerName, 0, sizeof(PeerName));
216     }
217 }
218 
219 /*---------------------------------------------------------------------------*
220   Name        : REXDEMOGetPeerName
221   Description :
222   Arguments   : None.
223   Returns     : const u8*    -
224  *---------------------------------------------------------------------------*/
225 const char*
REXDEMOGetPeerName(void)226 REXDEMOGetPeerName( void )
227 {
228     return PeerName;
229 }
230 
231 /*---------------------------------------------------------------------------*
232   Name        : REXDEMOWaitForNCDReady
233   Description : Wait until NCD is capable of receiving request.
234                 If this function enters an infinite loop, the firmware is invalid.
235   Arguments   : None.
236   Returns     : None.
237  *---------------------------------------------------------------------------*/
238 void
REXDEMOWaitForNCDReady(void)239 REXDEMOWaitForNCDReady( void )
240 {
241     while(NCDGetLinkStatus() == NCD_RESULT_INPROGRESS)
242     {
243         OSSleepMilliseconds(100);
244     }
245 }
246 
247 /*---------------------------------------------------------------------------*
248   Name        : REXDEMOOverrideNetConfig
249   Description : Force overwrite of NCD network setting.
250   Arguments   : pIfConfig    -
251                 pIpConfig    -
252   Returns     : s32          -
253  *---------------------------------------------------------------------------*/
254 s32
REXDEMOOverrideNetConfig(const NCDIfConfig * pIfConfig,const NCDIpConfig * pIpConfig)255 REXDEMOOverrideNetConfig( const NCDIfConfig* pIfConfig, const NCDIpConfig* pIpConfig )
256 {
257     s32 resultNcd;
258 
259     REXDEMOWaitForNCDReady();
260 
261     //////////////////////////////////////////////////////////////////////////
262     // * NOTE *
263     // NCDSetIfConfig, NCDSetIpConfig are test functions.
264     // These functions should not be called in the retail release. Simply call SOStartup.
265     //
266     // In such case, the network setting configured to the console will be used.
267     // The network setting for the development machines can be configured through the system tool or RevoEX/RVL/bin/tools/ncdconfigtool.elf.
268     //
269     //////////////////////////////////////////////////////////////////////////
270 
271     if( pIfConfig != NULL )
272     {
273         //OSReport("NCDSetIfConfig...\n");
274         resultNcd = NCDSetIfConfig( pIfConfig );
275         if( resultNcd != NCD_RESULT_SUCCESS )
276         {
277             OSReport( "NCDSetIfConfig failed (%d)\n", resultNcd );
278             return resultNcd;
279         }
280     }
281 
282     if( pIpConfig != NULL )
283     {
284         //OSReport("NCDSetIpConfig...\n");
285         resultNcd   = NCDSetIpConfig( pIpConfig );
286         if( resultNcd != NCD_RESULT_SUCCESS )
287         {
288             OSReport( "NCDSetIpConfig failed (%d)\n", resultNcd );
289             return resultNcd;
290         }
291     }
292 
293     //OSReport("REXDEMOOverrideNetConfig ok\n");
294     return NCD_RESULT_SUCCESS;
295 }
296 
297 /*---------------------------------------------------------------------------*
298   Name        : REXDEMOOverrideNetConfigAuto
299   Description : Force overwrite of NCD network setting with config.c network setting.
300 
301                 config.c setting can be switched with REXDEMOSetNetConfigId().
302   Arguments   : None.
303   Returns     : s32          -
304  *---------------------------------------------------------------------------*/
305 s32
REXDEMOOverrideNetConfigAuto(void)306 REXDEMOOverrideNetConfigAuto( void )
307 {
308     NCDIfConfig ifConfig;
309     NCDIfConfig* pIfConfig;
310     NCDIpConfig ipConfig;
311     NCDIpConfig* pIpConfig;
312     u8 configId;
313     s32 result;
314 
315     configId = REXDEMOGetNetConfigId();
316     pIfConfig = NULL;
317     pIpConfig = NULL;
318     if( REXDEMOCreateIfConfig( &ifConfig, configId ) )
319     {
320         pIfConfig = &ifConfig;
321     }
322     if( REXDEMOCreateIpConfig( &ipConfig, configId ) )
323     {
324         pIpConfig = &ipConfig;
325     }
326 
327     result = REXDEMOOverrideNetConfig( pIfConfig, pIpConfig );
328     if (result < NCD_RESULT_SUCCESS)
329     {
330         return result;
331     }
332     return result;
333 }
334 
335 /*---------------------------------------------------------------------------*
336   Name        : REXDEMOWaitForInterfaceReady
337   Description : Waits until NCD prepares the interface.
338   Arguments   : msecTimeout  -
339   Returns     : s32          -
340  *---------------------------------------------------------------------------*/
341 s32
REXDEMOWaitForInterfaceReady(u32 msecTimeout)342 REXDEMOWaitForInterfaceReady( u32 msecTimeout )
343 {
344     return REXDEMOWaitForInterfaceReadyEx( msecTimeout, FALSE, NULL );
345 }
346 
347 s32
REXDEMOWaitForInterfaceReadyEx(u32 msecTimeout,BOOL wantUp,volatile BOOL * flagCancel)348 REXDEMOWaitForInterfaceReadyEx( u32 msecTimeout, BOOL wantUp, volatile BOOL* flagCancel )
349 {
350     u32 ms;
351     s32 resultNcd;
352     for ( ms = 0; msecTimeout == 0 || ms < msecTimeout; ms+=100 )
353     {
354         if (flagCancel && *flagCancel)
355         {
356             break;
357         }
358         switch( resultNcd = NCDGetLinkStatus() )
359         {
360         case NCD_RESULT_INPROGRESS:
361         case NCD_LINKSTATUS_WORKING:
362             /* in a state where network I/F still cannot be used */
363             break;
364         case NCD_LINKSTATUS_NONE:
365             /* set so that no communication is allowed */
366             OSReport( "Not allowed to use Network functions\n" );
367             return NCD_RESULT_FAILURE;
368 
369         case NCD_LINKSTATUS_WIRELESS_DOWN:
370             if (wantUp)
371             {
372                 break;
373             }
374         case NCD_LINKSTATUS_WIRED:
375         case NCD_LINKSTATUS_WIRELESS_UP:
376             return NCD_RESULT_SUCCESS;
377         default:
378             /* other errors are not normally returned*/
379             OSReport( "NCDGetLinkStatus() failure (%d)\n", resultNcd );
380             return resultNcd;
381         }
382         //OSReport("NCDGetLinkStatus() = %d\n", resultNcd);
383         OSSleepTicks( OSMillisecondsToTicks( 100 ) );
384     }
385     return NCD_RESULT_UNDECIDED;
386 }
387 
388 /*---------------------------------------------------------------------------*
389   Name        : REXDEMOParseArgument
390   Description :
391   Arguments   : argc         -
392   Returns     : None.
393  *---------------------------------------------------------------------------*/
394 void
REXDEMOParseArgument(int argc,const char * argv[])395 REXDEMOParseArgument( int argc, const char* argv[] )
396 {
397     int curr_arg = 1;
398 
399     /* configId */
400     if( curr_arg < argc )
401     {
402         BOOL f;
403         int i;
404         int id;
405         const char* arg = argv[curr_arg];
406 
407         f = FALSE;
408         id = 0;
409         for( i = 0; arg[i] != 0 && i < 256; i++ )
410         {
411             if( '0' <= arg[i] && arg[i] <= '9' )
412             {
413                 f = TRUE;
414                 id *= 10;
415                 id += arg[i] - '0';
416                 if( id >= 256 )
417                 {
418                     /* configId runs from 0 to 255 */
419                     f = FALSE;
420                     break;
421                 }
422             }
423             else
424             {
425                 f = FALSE;
426                 break;
427             }
428         }
429 
430         if( f )
431         {
432             NetConfigId = (u8)id;
433             curr_arg++;
434         }
435         else
436         {
437             NetConfigId = 0;
438         }
439     }
440 
441     /* peerName */
442     if( curr_arg < argc )
443     {
444         REXDEMOSetPeerName(argv[curr_arg]);
445     }
446     else
447     {
448         REXDEMOSetPeerName(NULL);
449     }
450 }
451 
452 /*---------------------------------------------------------------------------*
453   $Log: netconfig.c,v $
454   Revision 1.10  2007/09/07 02:13:31  seiki_masashi
455   Separated the REXDEMOSafeSOFinish function.
456 
457   Revision 1.9  2007/09/07 00:41:27  seiki_masashi
458   Improved the safety of network termination processing.
459 
460   Revision 1.8  2007/06/04 09:40:54  hirose_kazuki
461   Added processing that is divided when the SO result is SO_EALREADY.
462 
463   Revision 1.7  2007/06/04 05:29:05  seiki_masashi
464   Fixed a processing bug when errors occurred.
465 
466   Revision 1.6  2007/05/28 08:37:49  hirose_kazuki
467   Added REXDEMODestroyHeapForSocket() call.
468 
469   Revision 1.5  2007/01/29 07:55:24  terui
470   The implementation of the REXDEMOCreatePeerAddressAuto function was moved to netfunc.c.
471   The implementation of the REXDEMOGetPeerAddress function was moved to netfunc.c.
472 
473   Revision 1.4  2006/09/25 07:06:13  seiki_masashi
474   Revised so that the network setting on the NAND will be used for configId 0.
475   Revised so that peerName is also gotten from the command line argument.
476 
477   Revision 1.3  2006/09/25 02:07:07  seiki_masashi
478   Small fix
479 
480   Revision 1.2  2006/09/25 02:00:37  seiki_masashi
481   Followed the specification change of SOStartup.
482   Added comments for cautions regarding NCDSetIfConfig
483 
484   Revision 1.1  2006/08/29 07:19:20  adachi_hiroaki
485   Changed prefix. Cleaned up code elsewhere.
486 
487  *---------------------------------------------------------------------------*/
488