1 /*---------------------------------------------------------------------------*
2   Project:  TwlSDK - WVR - demos - with_mb - child
3   File:     main.c
4 
5   Copyright 2003-2009 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   $Date:: 2009-08-31#$
14   $Rev: 11030 $
15   $Author: tominaga_masafumi $
16  *---------------------------------------------------------------------------*/
17 
18 /*
19  * This demo uses the WH library for wireless communications, but does not perform wireless shutdown processing.
20  *
21  * For details on WH library wireless shutdown processing, see the comments at the top of the WH library source code or the wm/dataShare-Model demo.
22  *
23  *
24  */
25 
26 #include <nitro.h>
27 #include <nitro/wm.h>
28 #include <nitro/mb.h>
29 
30 #include "common.h"
31 #include "disp.h"
32 #include "gmain.h"
33 #include "wh.h"
34 
35 #include <nitro/wvr.h>
36 
37 //============================================================================
38 //  Prototype Declarations
39 //============================================================================
40 
41 static void ModeConnect(void);         // Begins a connection to a parent device
42 static void ModeError(void);           // Error display screen
43 static void ModeWorking(void);         // Busy screen
44 static void ChildReceiveCallback(WMmpRecvBuf *data);
45 
46 static void StartUpCallback(void *arg, WVRResult result);
47 
48 
49 //============================================================================
50 //  Variable Definitions
51 //============================================================================
52 
53 static u32 gFrame;                     // Frame counter
54 
55 static WMBssDesc gMBParentBssDesc ATTRIBUTE_ALIGN(32);
56 
57 static volatile u8 startCheck;
58 
59 
60 //============================================================================
61 //  Function definitions
62 //============================================================================
63 
64 /*---------------------------------------------------------------------------*
65   Name:         NitroMain
66 
67   Description:  Child main routine
68 
69   Arguments:    None.
70 
71   Returns:      None.
72  *---------------------------------------------------------------------------*/
NitroMain(void)73 void NitroMain(void)
74 {
75 
76     // Initialize screen and OS
77     CommonInit();
78 
79     // The local host checks to see if it is a child started from multiboot.
80     if (!MB_IsMultiBootChild())
81     {
82         OS_Panic("not found Multiboot child flag!\n");
83     }
84 
85     //--------------------------------------------------------------
86     // If it was started from multi-boot, it will be reset once, and communication will be disconnected.
87     // The child maintains the BssDesc of the parent that booted it. Use this information to reconnect to the parent.
88     //
89     // There is no particular problem with extracting the MAC address from BssDesc, then specifying that MAC address and scanning for and connecting to that parent. However, to connect to the parent directly using the stored BssDesc, it is necessary to set the parent's and child's communications size and transfer mode to match ahead of time.
90     //
91     //
92     //
93     //--------------------------------------------------------------
94 
95     /*
96      * Gets parent data for reconnecting to the parent.
97      * The WMBssDesc used for the connection must be 32-byte aligned.
98      * When reconnecting without using the parent's MAC address to rescan, make the KS/CS flags and the maximum send size match in advance for the parent and the child.
99      *
100      * All of these values may be 0 if you rescan before connecting.
101      */
102     MB_ReadMultiBootParentBssDesc(&gMBParentBssDesc, WH_PARENT_MAX_SIZE,        // Maximum parent send size
103                                   WH_CHILD_MAX_SIZE,    // Maximum child send size
104                                   0,   // Key sharing flag
105                                   0);  // Continuous transfer mode flag
106 
107     // When connecting without rescanning the parent, the tgid on the parent and child must match.
108     //
109     // In order to avoid connections from an unrelated IPL, it is necessary to change the tgid of the parent after the parent is restarted, along with the tgid of the child.
110     //
111     // In this demo, the parent and child tgids are both incremented by 1.
112     gMBParentBssDesc.gameInfo.tgid++;
113 
114     // Initialize screen
115     DispInit();
116     // Initialize the heap
117     InitAllocateSystem();
118 
119     // Enable interrupts
120     (void)OS_EnableIrq();
121     (void)OS_EnableInterrupts();
122 
123     /*================================================================*/
124     // Start activating the wireless library
125     startCheck = 0;
126     if (WVR_RESULT_OPERATING != WVR_StartUpAsync(GX_VRAM_ARM7_128_D, StartUpCallback, NULL))
127     {
128         OS_TPanic("WVR_StartUpAsync failed. \n");
129     }
130     while (!startCheck)
131     {
132     }
133     /*================================================================*/
134 
135     GInitDataShare();
136 
137     //********************************
138     // Initialize wireless
139     if(!WH_Initialize())
140     {
141         OS_Panic("WH_Initialize failed.");
142     }
143     //********************************
144 
145     // LCD display start
146     GX_DispOn();
147     GXS_DispOn();
148 
149     // Debug string output
150     OS_TPrintf("MB child: Simple DataSharing demo started.\n");
151 
152     // Empty call for getting key input data (strategy for pressing A Button in the IPL)
153     ReadKey();
154 
155     // Main loop
156     for (gFrame = 0; TRUE; gFrame++)
157     {
158         // Get key input data
159         ReadKey();
160 
161         // Clear the screen
162         BgClear();
163 
164         // Distributes processes based on communication status
165         switch (WH_GetSystemState())
166         {
167         case WH_SYSSTATE_CONNECT_FAIL:
168             {
169                 // Because the internal WM state is invalid if the WM_StartConnect function fails, WM_Reset must be called once to reset the state to IDLE
170                 //
171                 WH_Reset();
172             }
173             break;
174         case WH_SYSSTATE_IDLE:
175             {
176                 static  retry = 0;
177                 enum
178                 {
179                     MAX_RETRY = 5
180                 };
181 
182                 if (retry < MAX_RETRY)
183                 {
184                     ModeConnect();
185                     retry++;
186                     break;
187                 }
188                 // If connection to parent is not possible after MAX_RETRY, display ERROR
189             }
190         case WH_SYSSTATE_ERROR:
191             ModeError();
192             break;
193         case WH_SYSSTATE_BUSY:
194         case WH_SYSSTATE_SCANNING:
195             ModeWorking();
196             break;
197 
198         case WH_SYSSTATE_CONNECTED:
199         case WH_SYSSTATE_KEYSHARING:
200         case WH_SYSSTATE_DATASHARING:
201             {
202                 BgPutString(8, 1, 0x2, "Child mode");
203                 GStepDataShare(gFrame);
204                 GMain();
205             }
206             break;
207         }
208 
209         // Display of signal strength
210         {
211             int     level;
212             level = WH_GetLinkLevel();
213             BgPrintStr(31, 23, 0xf, "%d", level);
214         }
215 
216         // Waiting for the V-Blank
217         OS_WaitVBlankIntr();
218     }
219 }
220 
221 /*---------------------------------------------------------------------------*
222   Name:         StartUpCallback
223 
224   Description:  Callback function to be notified end of async processing in wireless operation control library.
225 
226 
227   Arguments:    arg: Argument specified when WVR_StartUpAsync is called. Not used.
228                 result: The processing results from the asynchronous function
229 
230   Returns:      None.
231  *---------------------------------------------------------------------------*/
StartUpCallback(void * arg,WVRResult result)232 static void StartUpCallback(void *arg, WVRResult result)
233 {
234 #pragma unused( arg )
235 
236     if (result != WVR_RESULT_SUCCESS)
237     {
238         OS_TPanic("WVR_StartUpAsync error.[%08xh]\n", result);
239     }
240     startCheck = 1;
241 }
242 
243 /*---------------------------------------------------------------------------*
244   Name:         ModeConnect
245 
246   Description:  Connection start
247 
248   Arguments:    None.
249 
250   Returns:      None.
251  *---------------------------------------------------------------------------*/
ModeConnect(void)252 static void ModeConnect(void)
253 {
254 #define USE_DIRECT_CONNECT
255 
256     // When connecting directly without parent rescan.
257 #ifdef USE_DIRECT_CONNECT
258     //********************************
259     (void)WH_ChildConnect(WH_CONNECTMODE_DS_CHILD, &gMBParentBssDesc);
260     // WH_ChildConnect(WH_CONNECTMODE_MP_CHILD, &gMBParentBssDesc, TRUE);
261     // WH_ChildConnect(WH_CONNECTMODE_KS_CHILD, &gMBParentBssDesc, TRUE);
262     //********************************
263 #else
264     WH_SetGgid(gMBParentBssDesc.gameInfo.ggid);
265     // When rescanning for parent device.
266     //********************************
267     (void)WH_ChildConnectAuto(WH_CONNECTMODE_DS_CHILD, gMBParentBssDesc.bssid,
268                               gMBParentBssDesc.channel);
269     // WH_ChildConnect(WH_CONNECTMODE_MP_CHILD, &gMBParentBssDesc, TRUE);
270     // WH_ChildConnect(WH_CONNECTMODE_KS_CHILD, &gMBParentBssDesc, TRUE);
271     //********************************
272 #endif
273 }
274 
275 /*---------------------------------------------------------------------------*
276   Name:         ModeError
277 
278   Description:  Displays error notification screen
279 
280   Arguments:    None.
281 
282   Returns:      None.
283  *---------------------------------------------------------------------------*/
ModeError(void)284 static void ModeError(void)
285 {
286     BgPrintStr(5, 10, 0x1, "======= ERROR! =======");
287 
288     if (WH_GetLastError() == WM_ERRCODE_OVER_MAX_ENTRY)
289     {
290         BgPrintStr(5, 13, 0xf, "OVER_MAX_ENTRY");
291     }
292 }
293 
294 /*---------------------------------------------------------------------------*
295   Name:         ModeWorking
296 
297   Description:  Displays "working..." screen.
298 
299   Arguments:    None.
300 
301   Returns:      None.
302  *---------------------------------------------------------------------------*/
ModeWorking(void)303 static void ModeWorking(void)
304 {
305     BgPrintStr(9, 11, 0xf, "Now working...");
306 
307     if (IS_PAD_TRIGGER(PAD_BUTTON_START))
308     {
309         //********************************
310         (void)WH_Finalize();
311         //********************************
312     }
313 }
314