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