1 /*---------------------------------------------------------------------------*
2 Project: TwlSDK - MB - demos - cloneboot
3 File: child.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: ChildMain
51
52 Description: Child main routine
53
54 Arguments: None.
55
56 Returns: None.
57 *---------------------------------------------------------------------------*/
ChildMain(void)58 void ChildMain(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 { /* FS initialization */
109 static u32 fs_tablework[0x100 / 4];
110 FS_Init(FS_DMA_NOT_USE);
111 (void)FS_LoadTable(fs_tablework, sizeof(fs_tablework));
112 }
113
114 GInitDataShare();
115
116 //********************************
117 // Initialize wireless
118 if (!WH_Initialize())
119 {
120 OS_Panic("WH_Initialize failed.");
121 }
122 //********************************
123
124 // LCD display start
125 GX_DispOn();
126 GXS_DispOn();
127
128 // Debug string output
129 OS_TPrintf("MB child: Simple DataSharing demo started.\n");
130
131 // Empty call for getting key input data (strategy for pressing A Button in the IPL)
132 ReadKey();
133
134 // Main loop
135 for (gFrame = 0; TRUE; gFrame++)
136 {
137 // Get key input data
138 ReadKey();
139
140 // Clear the screen
141 BgClear();
142
143 // Distributes processes based on communication status
144 switch (WH_GetSystemState())
145 {
146 case WH_SYSSTATE_CONNECT_FAIL:
147 {
148 // If WM_StartConnect fails, the WM internal state is invalid. Use WM_Reset to reset the state to the IDLE state.
149 //
150 WH_Reset();
151 }
152 break;
153 case WH_SYSSTATE_IDLE:
154 {
155 static retry = 0;
156 enum
157 {
158 MAX_RETRY = 5
159 };
160
161 if (retry < MAX_RETRY)
162 {
163 ModeConnect();
164 retry++;
165 break;
166 }
167 // If connection to parent is not possible after MAX_RETRY, display ERROR
168 }
169 case WH_SYSSTATE_ERROR:
170 ModeError();
171 break;
172 case WH_SYSSTATE_BUSY:
173 case WH_SYSSTATE_SCANNING:
174 ModeWorking();
175 break;
176
177 case WH_SYSSTATE_CONNECTED:
178 case WH_SYSSTATE_KEYSHARING:
179 case WH_SYSSTATE_DATASHARING:
180 {
181 BgPutString(8, 1, 0x2, "Child mode");
182 GStepDataShare(gFrame);
183 GMain();
184 }
185 break;
186 }
187
188 // Display of signal strength
189 {
190 int level;
191 level = WH_GetLinkLevel();
192 BgPrintStr(31, 23, 0xf, "%d", level);
193 }
194
195 // Waiting for the V-Blank
196 OS_WaitVBlankIntr();
197 }
198 }
199
200 /*---------------------------------------------------------------------------*
201 Name: ModeConnect
202
203 Description: Connection start
204
205 Arguments: None.
206
207 Returns: None.
208 *---------------------------------------------------------------------------*/
ModeConnect(void)209 static void ModeConnect(void)
210 {
211 #define USE_DIRECT_CONNECT
212
213 // When connecting directly without parent rescan.
214 #ifdef USE_DIRECT_CONNECT
215 //********************************
216 (void)WH_ChildConnect(WH_CONNECTMODE_DS_CHILD, &gMBParentBssDesc);
217 // WH_ChildConnect(WH_CONNECTMODE_MP_CHILD, &gMBParentBssDesc, TRUE);
218 // WH_ChildConnect(WH_CONNECTMODE_KS_CHILD, &gMBParentBssDesc, TRUE);
219 //********************************
220 #else
221 WH_SetGgid(gMBParentBssDesc.gameInfo.ggid);
222 // When performing rescanning of the parent device
223 //********************************
224 (void)WH_ChildConnectAuto(WH_CONNECTMODE_DS_CHILD, gMBParentBssDesc.bssid,
225 gMBParentBssDesc.channel);
226 // WH_ChildConnect(WH_CONNECTMODE_MP_CHILD, &gMBParentBssDesc, TRUE);
227 // WH_ChildConnect(WH_CONNECTMODE_KS_CHILD, &gMBParentBssDesc, TRUE);
228 //********************************
229 #endif
230 }
231
232 /*---------------------------------------------------------------------------*
233 Name: ModeError
234
235 Description: Displays error notification screen
236
237 Arguments: None.
238
239 Returns: None.
240 *---------------------------------------------------------------------------*/
ModeError(void)241 static void ModeError(void)
242 {
243 BgPrintStr(5, 10, 0x1, "======= ERROR! =======");
244
245 if (WH_GetLastError() == WM_ERRCODE_OVER_MAX_ENTRY)
246 {
247 BgPrintStr(5, 13, 0xf, "OVER_MAX_ENTRY");
248 }
249 }
250
251 /*---------------------------------------------------------------------------*
252 Name: ModeWorking
253
254 Description: Displays working screen
255
256 Arguments: None.
257
258 Returns: None.
259 *---------------------------------------------------------------------------*/
ModeWorking(void)260 static void ModeWorking(void)
261 {
262 BgPrintStr(9, 11, 0xf, "Now working...");
263
264 if (IS_PAD_TRIGGER(PAD_BUTTON_START))
265 {
266 //********************************
267 (void)WH_Finalize();
268 //********************************
269 }
270 }
271