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