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