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