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