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