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