1 /*---------------------------------------------------------------------------*
2   Project:  TwlSDK - MB - demos - fake_child
3   File:     main.c
4 
5   Copyright 2007-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-02-19#$
14   $Rev: 10047 $
15   $Author: nishimoto_takashi $
16 *---------------------------------------------------------------------------*/
17 
18 #ifdef SDK_TWL
19 #include <twl.h>
20 #else
21 #include <nitro.h>
22 #endif
23 
24 #include "common.h"
25 #include "disp.h"
26 #include "gmain.h"
27 #include "wh.h"
28 
29 
30 #define     DEBUG_PRINT
31 
32 /*
33  * This sample makes an entry as a child with demos/mb/multiboot-Model and participates in network communication with other DS Download Play children.
34  * The target application is configured by the MB_FakeScanParent function's GGID argument.
35  *
36  *
37  */
38 
39 
40 enum
41 {
42     MODE_TITLE,
43     MODE_START_SCAN,
44     MODE_SCANNING,
45     MODE_ENTRY,
46     MODE_RECONNECT,
47     MODE_GMAIN,
48     MODE_ERROR,
49     MODE_CANCEL
50 };
51 
52 typedef struct
53 {
54     MBUserInfo info;
55     u16     valid;
56     u8      maxPlayerNum;              // Max number of players
57     u8      nowPlayerNum;              // Current number of players
58     u8      macAddr[6];                // MAC address
59 }
60 ParentInfo;
61 
62 #define WH_GGID (0x003FFF00 | (0x21))
63 
64 static void PrintError(MBFakeScanErrorCallback *arg);
65 
66 static void ModeTitle(void);
67 static void ModeStartScan(void);
68 static void ModeScanning(void);
69 static void ModeEntry(void);
70 static void ModeError(void);
71 static void ModeReconnect(void);
72 static void ModeGMain(void);
73 static void ModeCancel(void);
74 
75 static void NotifyScanParent(u16 type, void *arg);
76 static void MBStateCallback(u32 status, void *arg);
77 
78 
79 // Parent info list
80 static ParentInfo parentInfo[MB_GAME_INFO_RECV_LIST_NUM];
81 static ParentInfo parentInfoBuf[MB_GAME_INFO_RECV_LIST_NUM];
82 
83 static WMBssDesc sParentBssDesc;       // BssDesc of entered parent
84 
85 static u8 *mbfBuf = NULL;
86 static u8 *wmBuf = NULL;
87 
88 
89 static s32 gFrame;                     // Frame counter
90 
91 static u16 sMode;
92 
93 enum
94 {
95     WSTATE_STOP,                       // Stop state
96     WSTATE_INITIALIZE_BUSY,            // Initializing wireless
97     WSTATE_IDLE,                       // Idle state
98     WSTATE_ERROR,                      // Error before starting/after stopping fake child
99     WSTATE_FAKE_SCAN,                  // Scan state
100     WSTATE_FAKE_END_SCAN,              // End scan
101     WSTATE_FAKE_ENTRY,                 // Entry to parent
102     WSTATE_FAKE_BOOT_READY,            // Entry to DS download play is complete
103     WSTATE_FAKE_BOOT_END_BUSY,         // DS download processing is now finishing
104     WSTATE_FAKE_BOOT_END,
105     WSTATE_FAKE_CANCEL_BUSY,           // DS download canceling
106     WSTATE_FAKE_ERROR                  // Error
107 };
108 static u16 sWirelessState = WSTATE_STOP;
109 
110 static u16 sConnectIndex;              // Index of parent devices to connect
111 
112 /******************************************************************************/
113 /* Functions */
114 
115 #ifdef DEBUG_PRINT
ChangeWirelessState(u16 wstate)116 static void ChangeWirelessState(u16 wstate)
117 {
118     static const char *WSTATE_NAME[] = {
119         "WSTATE_STOP",
120         "WSTATE_INITIALIZE_BUSY",
121         "WSTATE_IDLE",
122         "WSTATE_ERROR",
123         "WSTATE_FAKE_SCAN",
124         "WSTATE_FAKE_END_SCAN",
125         "WSTATE_FAKE_ENTRY",
126         "WSTATE_FAKE_BOOT_READY",
127         "WSTATE_FAKE_BOOT_END_BUSY",
128         "WSTATE_FAKE_BOOT_END",
129         "WSTATE_FAKE_CANCEL_BUSY",
130         "WSTATE_FAKE_ERROR"
131     };
132 
133     if (sWirelessState != wstate)
134     {
135         OS_TPrintf("change sWirelessState %s -> %s\n", WSTATE_NAME[sWirelessState],
136                    WSTATE_NAME[wstate]);
137     }
138 #else
139 static inline void ChangeWirelessState(u16 wstate)
140 {
141 #endif
142     sWirelessState = wstate;
143 }
144 
145 /* V-Blank interrupt process */
146 static void VBlankIntr(void)
147 {
148     //---- Interrupt check flag
149     OS_SetIrqCheckFlag(OS_IE_V_BLANK);
150 }
151 
152 
153 /* Main */
154 #ifdef SDK_TWL
155 void TwlMain()
156 #else
157 void NitroMain()
158 #endif
159 {
160     // Initialize system
161     CommonInit();
162     // Initialize screen
163     DispInit();
164 
165     // Initialize the heap
166     InitAllocateSystem();
167 
168     // Enable interrupts
169     (void)OS_EnableIrq();
170     (void)OS_EnableInterrupts();
171 
172     {                                  /* FS initialization */
173         static u32 fs_tablework[0x100 / 4];
174         FS_Init(FS_DMA_NOT_USE);
175         (void)FS_LoadTable(fs_tablework, sizeof(fs_tablework));
176     }
177 
178 
179     // Clear buffer for data sharing
180     GInitDataShare();
181 
182     // To title screen
183     sMode = MODE_TITLE;
184 
185     // LCD display start
186     GX_DispOn();
187     GXS_DispOn();
188 
189     // Debug string output
190     OS_TPrintf("MB fake child: Simple DataSharing demo started.\n");
191     // Empty call for getting key input data (strategy for pressing A Button in the IPL)
192     ReadKey();
193 
194     /* Main loop */
195     for (gFrame = 0; TRUE; gFrame++)
196     {
197         // Get key input data
198         ReadKey();
199 
200         // Clear the screen
201         BgClear();
202 
203         switch (sMode)
204         {
205         case MODE_TITLE:
206             // Display title screen
207             ModeTitle();
208             break;
209         case MODE_START_SCAN:
210             // Start scan
211             ModeStartScan();
212             break;
213         case MODE_SCANNING:
214             // Scanning MB parent
215             ModeScanning();
216             break;
217         case MODE_ENTRY:
218             // Entry to MB parent
219             ModeEntry();
220             break;
221         case MODE_RECONNECT:
222             // Reconnect to MB parent
223             ModeReconnect();
224             break;
225         case MODE_GMAIN:
226             // Game main
227             ModeGMain();
228             break;
229         case MODE_ERROR:
230             // Error processing
231             ModeError();
232             break;
233         case MODE_CANCEL:
234             // Canceling
235             ModeCancel();
236             break;
237         }
238 
239         OS_WaitVBlankIntr();
240     }
241 }
242 
243 
244 
245 /* ----------------------------------------------------------------------
246   Name:        ModeTitle
247 
248   Description: Title screen
249 
250   Arguments:   None.
251 
252   Returns:     None.
253   ---------------------------------------------------------------------- */
254 static void ModeTitle(void)
255 {
256     BgSetMessage(PLTT_WHITE, " Press Button A to start   ");
257 
258     ChangeWirelessState(WSTATE_STOP);
259 
260     // When A Button is pressed, set wireless to ON and enter MB parent search mode
261     if (IS_PAD_TRIGGER(PAD_BUTTON_A))
262     {
263         sMode = MODE_START_SCAN;
264     }
265 }
266 
267 /* ----------------------------------------------------------------------
268   Name:        ModeStartScan
269 
270   Description: Starts parent scan.
271 
272   Arguments:   None.
273 
274   Returns:     None.
275   ---------------------------------------------------------------------- */
276 static void ModeStartScan(void)
277 {
278     BgSetMessage(PLTT_WHITE, "Now working....         ");
279 
280     switch (sWirelessState)
281     {
282         //--------------------------
283         // Start wireless communication
284     case WSTATE_STOP:
285         if (!WH_Initialize())
286         {
287             ChangeWirelessState(WSTATE_ERROR);
288             sMode = MODE_ERROR;
289             return;
290         }
291         ChangeWirelessState(WSTATE_INITIALIZE_BUSY);
292         break;
293 
294         //--------------------------
295         // Initializing wireless
296     case WSTATE_INITIALIZE_BUSY:
297         if (WH_GetSystemState() == WH_SYSSTATE_BUSY)
298         {
299             BgSetMessage(PLTT_WHITE, "Now working....         ");
300             return;
301         }
302         if (WH_GetSystemState() != WH_SYSSTATE_IDLE)
303         {
304             ChangeWirelessState(WSTATE_ERROR);
305             sMode = MODE_ERROR;
306             return;
307         }
308         ChangeWirelessState(WSTATE_IDLE);
309         // Don't break
310 
311         //--------------------------
312         // Start parent scan
313     case WSTATE_IDLE:
314         {
315             // Set user info
316             MBUserInfo userInfo;
317 
318             OSOwnerInfo info;
319 
320             OS_GetOwnerInfo(&info);
321             userInfo.favoriteColor = info.favoriteColor;
322             userInfo.nameLength = (u8)info.nickNameLength;
323             MI_CpuCopy8(info.nickName, userInfo.name, (u32)(userInfo.nameLength * 2));
324 
325             // Normally with MB child, playerNo will be 0, but by setting a value it can be passed to a parent as a parameter.
326             userInfo.playerNo = 7;
327 
328             // Allocate work buffer for multiboot entries
329             mbfBuf = (u8 *)OS_Alloc(MB_FakeGetWorkSize());
330             MB_FakeInit(mbfBuf, &userInfo);
331             // Set the state transition notification callback function
332             MB_FakeSetCStateCallback(MBStateCallback);
333 
334             // Clear parent list
335             MI_CpuClear8(parentInfo, sizeof(parentInfo));
336 
337             // Wireless state changes to scanning
338             ChangeWirelessState(WSTATE_FAKE_SCAN);
339 
340             // Set GGID of the parent to scan and the notification callback function; start scanning
341             MB_FakeStartScanParent(NotifyScanParent, WH_GGID);
342 
343             // Transition to scan mode
344             sMode = MODE_SCANNING;
345         }
346         break;
347     default:
348         OS_TPanic("illegal state %d", sWirelessState);
349         break;
350     }
351 }
352 
353 
354 /* ----------------------------------------------------------------------
355   Name:        ModeScanning
356 
357   Description: Parent scanning.
358 
359   Arguments:   None.
360 
361   Returns:     None.
362   ---------------------------------------------------------------------- */
363 static void ModeScanning(void)
364 {
365     enum
366     { STR_X = 4, STR_Y = 4, NUM_STR_X = 24 };
367     static u16 cursol_idx = 0;
368 
369     u16     i;
370 
371     // If error occurs, terminate
372     if (sWirelessState == WSTATE_FAKE_ERROR)
373     {
374         sMode = MODE_ERROR;
375         return;
376     }
377 
378     // The parent information is copied to the temporary buffer before use, so that it won't be changed by an interrupt during rendering.
379     //
380     {
381         OSIntrMode enabled = OS_DisableInterrupts();
382         MI_CpuCopy8(parentInfo, parentInfoBuf, sizeof(parentInfo));
383         (void)OS_RestoreInterrupts(enabled);
384     }
385 
386     // Move cursor
387     if (IS_PAD_TRIGGER(PAD_KEY_UP))
388     {
389         cursol_idx = (u16)((cursol_idx - 1) & 0xF);
390     }
391     else if (IS_PAD_TRIGGER(PAD_KEY_DOWN))
392     {
393         cursol_idx = (u16)((cursol_idx + 1) & 0xF);
394     }
395 
396     // Display parent info
397     BgPutString(10, 1, PLTT_RED, "Select Parent");
398 
399     BgPutString(STR_X - 2, STR_Y + cursol_idx, PLTT_WHITE, ">");
400     for (i = 0; i < MB_GAME_INFO_RECV_LIST_NUM; i++)
401     {
402         if (parentInfoBuf[i].valid)
403         {
404             BgPrintStr(STR_X, STR_Y + i, PLTT_GREEN, "%02x:%02x:%02x:%02x:%02x:%02x",
405                        parentInfoBuf[i].macAddr[0], parentInfoBuf[i].macAddr[1],
406                        parentInfoBuf[i].macAddr[2], parentInfoBuf[i].macAddr[3],
407                        parentInfoBuf[i].macAddr[4], parentInfoBuf[i].macAddr[5]);
408             BgPrintStr(NUM_STR_X, STR_Y + i, PLTT_GREEN, "%d/%d",
409                        parentInfoBuf[i].nowPlayerNum, parentInfoBuf[i].maxPlayerNum);
410         }
411         else
412         {
413             BgPutString(STR_X, STR_Y + i, PLTT_WHITE, "Searching...");
414         }
415     }
416 
417     // Cancel communication
418     if (IS_PAD_TRIGGER(PAD_BUTTON_B))
419     {
420         ChangeWirelessState(WSTATE_FAKE_CANCEL_BUSY);
421         sMode = MODE_CANCEL;
422         MB_FakeEnd();
423         return;
424     }
425 
426     // Select the parent to connect to
427     if (IS_PAD_TRIGGER(PAD_BUTTON_A))
428     {
429         if (!parentInfoBuf[cursol_idx].valid)
430         {
431             return;
432         }
433 
434         // Get info from the parent to connect to
435         sConnectIndex = cursol_idx;
436         if (!MB_FakeReadParentBssDesc
437             (sConnectIndex, &sParentBssDesc, WH_PARENT_MAX_SIZE, WH_CHILD_MAX_SIZE, FALSE, FALSE))
438         {
439             // If the parent info is not valid, continue scan
440             return;
441         }
442         sMode = MODE_ENTRY;
443     }
444 }
445 
446 
447 /* ----------------------------------------------------------------------
448   Name:        ModeEntry
449 
450   Description: Entry to parent device.
451 
452   Arguments:   None.
453 
454   Returns:     None.
455   ---------------------------------------------------------------------- */
456 static void ModeEntry(void)
457 {
458     BgSetMessage(PLTT_WHITE, "Now Entrying...        ");
459 
460     switch (sWirelessState)
461     {
462         //--------------------------
463         // If scanning
464     case WSTATE_FAKE_SCAN:
465         {
466             // Terminate scan
467             MB_FakeEndScan();
468             ChangeWirelessState(WSTATE_FAKE_END_SCAN);
469         }
470         break;
471 
472         //--------------------------
473         // Terminating scan
474     case WSTATE_FAKE_END_SCAN:
475         break;
476 
477         //--------------------------
478         // Start wireless communication
479     case WSTATE_IDLE:
480         {
481             if (!MB_FakeEntryToParent(sConnectIndex))
482             {
483                 // If specified index is not valid, error
484                 OS_TPrintf("ERR: Illegal Parent index\n");
485                 ChangeWirelessState(WSTATE_FAKE_ERROR);
486                 sMode = MODE_ERROR;
487                 return;
488             }
489             ChangeWirelessState(WSTATE_FAKE_ENTRY);
490         }
491         break;
492 
493         //--------------------------
494         // Undergoing entry
495     case WSTATE_FAKE_ENTRY:
496         // If entry has not been completed, cancel with B Button
497         if (IS_PAD_TRIGGER(PAD_BUTTON_B))
498         {
499             ChangeWirelessState(WSTATE_FAKE_CANCEL_BUSY);
500             sMode = MODE_CANCEL;
501             MB_FakeEnd();
502             return;
503         }
504         break;
505 
506         //--------------------------
507         // Complete entry processing
508     case WSTATE_FAKE_BOOT_READY:
509         {
510             // Ending processing for entry processing
511             ChangeWirelessState(WSTATE_FAKE_BOOT_END_BUSY);
512             MB_FakeEnd();
513         }
514         break;
515 
516         //--------------------------
517         // Wait for finish
518     case WSTATE_FAKE_BOOT_END_BUSY:
519         break;
520 
521         //--------------------------
522         // Complete processing for fake child
523     case WSTATE_FAKE_BOOT_END:
524         {
525             // Align with parent and increment tgid
526             sParentBssDesc.gameInfo.tgid++;
527             // Start reconnection
528             ChangeWirelessState(WSTATE_IDLE);
529             sMode = MODE_RECONNECT;
530         }
531         break;
532 
533         //--------------------------
534         // Error complete
535     case WSTATE_FAKE_ERROR:
536         sMode = MODE_ERROR;
537         break;
538 
539     default:
540         OS_TPanic("illegal state %d\n", sWirelessState);
541     }
542 }
543 
544 
545 /* ----------------------------------------------------------------------
546   Name:        ModeReconnect
547 
548   Description: Title screen.
549 
550   Arguments:   None.
551 
552   Returns:     None.
553   ---------------------------------------------------------------------- */
554 static void ModeReconnect(void)
555 {
556     BgSetMessage(PLTT_WHITE, "Connecting to Parent...        ");
557 
558     switch (WH_GetSystemState())
559     {
560     case WH_SYSSTATE_CONNECT_FAIL:
561         {
562             // If WM_StartConnect fails, the WM internal state is invalid. Use WM_Reset to reset the state to the IDLE state.
563             //
564             WH_Reset();
565         }
566         break;
567     case WH_SYSSTATE_IDLE:
568         {
569             (void)WH_ChildConnect(WH_CONNECTMODE_DS_CHILD, &sParentBssDesc);
570         }
571         break;
572     case WH_SYSSTATE_ERROR:
573         ChangeWirelessState(WSTATE_ERROR);
574         sMode = MODE_ERROR;
575         break;
576     case WH_SYSSTATE_BUSY:
577         break;
578     case WH_SYSSTATE_CONNECTED:
579     case WH_SYSSTATE_KEYSHARING:
580     case WH_SYSSTATE_DATASHARING:
581         sMode = MODE_GMAIN;
582         break;
583     }
584 }
585 
586 
587 /* ----------------------------------------------------------------------
588   Name:        ModeGMain
589 
590   Description: Title screen
591 
592   Arguments:   None.
593 
594   Returns:     None.
595   ---------------------------------------------------------------------- */
596 static void ModeGMain(void)
597 {
598     if (WH_GetSystemState() == WH_SYSSTATE_ERROR)
599     {
600         ChangeWirelessState(WSTATE_ERROR);
601         sMode = MODE_ERROR;
602         return;
603     }
604     GStepDataShare(gFrame);
605     GMain();
606 }
607 
608 
609 /* ----------------------------------------------------------------------
610   Name:        ModeCancel
611 
612   Description: Canceling screen
613 
614   Arguments:   None.
615 
616   Returns:     None.
617   ---------------------------------------------------------------------- */
618 static void ModeCancel(void)
619 {
620     switch (sWirelessState)
621     {
622         //-------------------------
623         // End wireless after moving to idle state
624     case WSTATE_IDLE:
625         if (WH_GetSystemState() == WH_SYSSTATE_IDLE)
626         {
627             (void)WH_End();
628             return;
629         }
630 
631         if (WH_GetSystemState() != WH_SYSSTATE_STOP)
632         {
633             return;
634         }
635         ChangeWirelessState(WSTATE_STOP);
636         sMode = MODE_TITLE;
637         break;
638         //--------------------------
639         // Canceling
640     case WSTATE_FAKE_CANCEL_BUSY:
641         break;
642 
643         //--------------------------
644         // Error occurred
645     case WSTATE_ERROR:
646         ChangeWirelessState(WSTATE_IDLE);
647         (void)WH_Finalize();
648         break;
649 
650         //--------------------------
651         // End processing
652     default:
653         ChangeWirelessState(WSTATE_IDLE);
654         (void)WH_Finalize();
655         break;
656     }
657 }
658 
659 
660 /* ----------------------------------------------------------------------
661   Name:        ModeError
662 
663   Description: Error screen
664 
665   Arguments:   None.
666 
667   Returns:     None.
668   ---------------------------------------------------------------------- */
669 static void ModeError(void)
670 {
671     BgPutString(4, 10, PLTT_RED, "========== ERROR ==========");
672 
673     if (IS_PAD_TRIGGER(PAD_BUTTON_B) || IS_PAD_TRIGGER(PAD_BUTTON_A))
674     {
675         if (sWirelessState == WSTATE_FAKE_ERROR)
676         {
677             ChangeWirelessState(WSTATE_FAKE_CANCEL_BUSY);
678             MB_FakeEnd();
679         }
680         sMode = MODE_CANCEL;
681     }
682 }
683 
684 
685 /* ----------------------------------------------------------------------
686   Name:        NotifyScanParent
687 
688   Description: Parent scan state notification callback.
689 
690   Arguments:   state: Scan state
691                         MB_FAKESCAN_PARENT_FOUND, MB_FAKESCAN_PARENT_LOST,
692                         MB_FAKESCAN_PARENT_FOUND, MB_FAKESCAN_PARENT_LOST,
693                         These 4 types of messages are indicated.
694 
695                arg: If MB_FAKESCAN_PARENT_FOUND or MB_FAKESCAN_PARENT_LOST, the information of the parent can be obtained
696 
697 
698   Returns:     None.
699   ---------------------------------------------------------------------- */
700 static void NotifyScanParent(u16 type, void *arg)
701 {
702     static const char *MB_FAKESCAN_CALLBACK_TYPE_NAME[] = {
703         "MB_FAKESCAN_PARENT_FOUND",
704         "MB_FAKESCAN_PARENT_LOST",
705         "MB_FAKESCAN_API_ERROR",
706         "MB_FAKESCAN_END_SCAN",
707         "MB_FAKESCAN_PARENT_BEACON",
708         "MB_FAKESCAN_CONNECTED",
709         "MB_FAKESCAN_ENTRY",
710         "MB_FAKESCAN_DISCONNECTED",
711         "MB_FAKESCAN_SUCCESS"
712     };
713 
714     OS_TPrintf("> %s\n", MB_FAKESCAN_CALLBACK_TYPE_NAME[type]);
715 
716     switch (type)
717     {
718     case MB_FAKESCAN_PARENT_BEACON:
719         {
720             MBFakeScanCallback *cb = (MBFakeScanCallback *)arg;
721             WMBssDesc *bssdesc = cb->bssDesc;
722             const u8 *volat_data = (const u8 *)MB_GetUserVolatData(&bssdesc->gameInfo);
723             OS_TPrintf(" find MB-beacon MAC=(%04x%08x)\n",
724                        *(u16 *)(&bssdesc->bssid[4]), *(u32 *)(&bssdesc->bssid[0]));
725             if (volat_data)
726             {
727                 OS_TPrintf("                VOLAT=(%02x %02x %02x %02x %02x %02x %02x %02x)\n",
728                            volat_data[0], volat_data[1], volat_data[2], volat_data[3],
729                            volat_data[4], volat_data[5], volat_data[6], volat_data[7]);
730             }
731         }
732         break;
733     case MB_FAKESCAN_PARENT_FOUND:
734         {
735             MBFakeScanCallback *cb = (MBFakeScanCallback *)arg;
736             WMBssDesc *bssdesc = cb->bssDesc;
737             MBGameInfo *gameInfo = cb->gameInfo;
738 
739             OS_TPrintf(" find parent %04x%08x %d\n", *(u16 *)(&bssdesc->bssid[4]),
740                        *(u32 *)(&bssdesc->bssid[0]), cb->index);
741             OS_TPrintf("      parentMaxSize = %d, childMaxSize = %d\n",
742                        bssdesc->gameInfo.parentMaxSize, bssdesc->gameInfo.childMaxSize);
743 
744             parentInfo[cb->index].valid = 1;
745             parentInfo[cb->index].maxPlayerNum = gameInfo->fixed.maxPlayerNum;
746             parentInfo[cb->index].nowPlayerNum = gameInfo->volat.nowPlayerNum;
747             MI_CpuCopy8(&gameInfo->fixed.parent, &parentInfo[cb->index].info, sizeof(MBUserInfo));
748             WM_CopyBssid(bssdesc->bssid, parentInfo[cb->index].macAddr);
749         }
750         break;
751     case MB_FAKESCAN_PARENT_LOST:
752         {
753             MBFakeScanCallback *cb = (MBFakeScanCallback *)arg;
754 
755             OS_TPrintf(" lost parent %d\n", cb->index);
756 
757             parentInfo[cb->index].valid = 0;
758         }
759         break;
760     case MB_FAKESCAN_API_ERROR:
761         {
762             PrintError((MBFakeScanErrorCallback *)arg);
763             OS_TPrintf("ERR : API Error occured\n");
764             ChangeWirelessState(WSTATE_FAKE_ERROR);
765         }
766         break;
767     case MB_FAKESCAN_END_SCAN:
768         {
769             ChangeWirelessState(WSTATE_IDLE);
770         }
771         break;
772     default:
773         break;
774     }
775 }
776 
777 
778 /* ----------------------------------------------------------------------
779   Name:        MBStateCallback
780 
781   Description: Fake child state-transition notification callback.
782                After MB_FakeEntryToParent is called, the sequence up to the child boot completion message will execute automatically. No special processing is needed.
783 
784 
785                When all multiboot processing is complete, the MB_COMM_CSTATE_BOOT_READY callback will return.
786 
787 
788   Arguments:   status: Current state of the MB child
789                arg: Callback argument
790 
791   Returns:     None.
792   ---------------------------------------------------------------------- */
793 static void MBStateCallback(u32 status, void *arg)
794 {
795 #pragma unused( arg )
796     switch (status)
797     {
798     case MB_COMM_CSTATE_INIT_COMPLETE: // Notification of connection to parent complete
799     case MB_COMM_CSTATE_CONNECT:      // Notification of connection to parent complete
800     case MB_COMM_CSTATE_REQ_ENABLE:   // Notification of MP communication with parent complete
801     case MB_COMM_CSTATE_DLINFO_ACCEPTED:       // Notification of completion of entry to parent
802     case MB_COMM_CSTATE_RECV_PROCEED: // Notification of start of data transmission from parent
803     case MB_COMM_CSTATE_RECV_COMPLETE: // Notification of completion of parent's data transmission
804     case MB_COMM_CSTATE_BOOTREQ_ACCEPTED:      // Notification of reception of boot request from parent
805         // Special processing is unnecessary
806         break;
807 
808     case MB_COMM_CSTATE_BOOT_READY:
809         // Notiffication of disconnection from parent and MB processing complete
810         {
811             ChangeWirelessState(WSTATE_FAKE_BOOT_READY);
812         }
813         break;
814 
815     case MB_COMM_CSTATE_CANCELED:
816         // Notification that an entry with a parent device was cancelled mid-process
817         break;
818 
819     case MB_COMM_CSTATE_CONNECT_FAILED:        // Notification of connection failure to parent
820     case MB_COMM_CSTATE_DISCONNECTED_BY_PARENT:        // Notification of disconnection from parent
821     case MB_COMM_CSTATE_REQ_REFUSED:  // Notification when request to parent was refused
822     case MB_COMM_CSTATE_MEMBER_FULL:  // Notification that the entry child number of the parent was exceeded
823     case MB_COMM_CSTATE_ERROR:        // Processing if abnormal transmission status occurred midway
824         {
825             OS_TPrintf("ERR : MB Error occured reason 0x%x\n", status);
826             ChangeWirelessState(WSTATE_FAKE_ERROR);
827         }
828         break;
829 
830     case MB_COMM_CSTATE_FAKE_END:
831         // Release the work passed to MB
832         OS_Free(mbfBuf);
833         mbfBuf = NULL;
834 
835         if (sWirelessState == WSTATE_FAKE_BOOT_END_BUSY)
836         {
837             ChangeWirelessState(WSTATE_FAKE_BOOT_END);
838         }
839         else
840         {
841             ChangeWirelessState(WSTATE_IDLE);
842         }
843     }
844 }
845 
846 
847 
848 /* ----------------------------------------------------------------------
849   Name:        PrintError
850 
851   Description: Outputs contents of the WM API error.
852 
853   Arguments:   arg: Error callback for MB_FakeStartScanParent
854 
855   Returns:     None.
856   ---------------------------------------------------------------------- */
857 static void PrintError(MBFakeScanErrorCallback *arg)
858 {
859 #pragma unused( arg )
860     static const char *APIID_NAME[] = {
861         "WM_APIID_INITIALIZE",
862         "WM_APIID_RESET",
863         "WM_APIID_END",
864         "WM_APIID_ENABLE",
865         "WM_APIID_DISABLE",
866         "WM_APIID_POWER_ON",
867         "WM_APIID_POWER_OFF",
868         "WM_APIID_SET_P_PARAM",
869         "WM_APIID_START_PARENT",
870         "WM_APIID_END_PARENT",
871         "WM_APIID_START_SCAN",
872         "WM_APIID_END_SCAN",
873         "WM_APIID_START_CONNECT",
874         "WM_APIID_DISCONNECT",
875         "WM_APIID_START_MP",
876         "WM_APIID_SET_MP_DATA",
877         "WM_APIID_END_MP",
878         "WM_APIID_START_DCF",
879         "WM_APIID_SET_DCF_DATA",
880         "WM_APIID_END_DCF",
881         "WM_APIID_SET_WEPKEY",
882         "WM_APIID_START_KS",
883         "WM_APIID_END_KS",
884         "WM_APIID_GET_KEYSET",
885         "WM_APIID_SET_GAMEINFO",
886         "WM_APIID_SET_BEACON_IND",
887         "WM_APIID_START_TESTMODE",
888         "WM_APIID_STOP_TESTMODE",
889         "WM_APIID_VALARM_MP",
890         "WM_APIID_SET_LIFETIME",
891         "WM_APIID_MEASURE_CHANNEL",
892         "WM_APIID_INIT_W_COUNTER",
893         "WM_APIID_GET_W_COUNTER",
894         "WM_APIID_SET_ENTRY",
895         "WM_APIID_AUTO_DEAUTH",
896         "WM_APIID_SET_MP_PARAMETER",
897         "WM_APIID_SET_BEACON_PERIOD",
898         "WM_APIID_AUTO_DISCONNECT",
899         "WM_APIID_START_SCAN_EX",
900         "WM_APIID_KICK_MP_PARENT",
901         "WM_APIID_KICK_MP_CHILD",
902         "WM_APIID_KICK_MP_RESUME",
903         "WM_APIID_ASYNC_KIND_MAX",
904         "WM_APIID_INDICATION",
905         "WM_APIID_PORT_SEND",
906         "WM_APIID_PORT_RECV",
907         "WM_APIID_READ_STATUS",
908         "WM_APIID_UNKNOWN",
909     };
910 
911     static const char *ERRCODE_NAME[] = {
912         "WM_ERRCODE_SUCCESS",
913         "WM_ERRCODE_FAILED",
914         "WM_ERRCODE_OPERATING",
915         "WM_ERRCODE_ILLEGAL_STATE",
916         "WM_ERRCODE_WM_DISABLE",
917         "WM_ERRCODE_NO_DATASET",
918         "WM_ERRCODE_INVALID_PARAM",
919         "WM_ERRCODE_NO_CHILD",
920         "WM_ERRCODE_FIFO_ERROR",
921         "WM_ERRCODE_TIMEOUT",
922         "WM_ERRCODE_SEND_QUEUE_FULL",
923         "WM_ERRCODE_NO_ENTRY",
924         "WM_ERRCODE_OVER_MAX_ENTRY",
925         "WM_ERRCODE_INVALID_POLLBITMAP",
926         "WM_ERRCODE_NO_DATA",
927         "WM_ERRCODE_SEND_FAILED",
928         "WM_ERRCODE_DCF_TEST",
929         "WM_ERRCODE_WL_INVALID_PARAM",
930         "WM_ERRCODE_WL_LENGTH_ERR",
931         "WM_ERRCODE_FLASH_ERROR"
932     };
933 
934     OS_TPrintf("ERR: %s %s\n", APIID_NAME[arg->apiid], ERRCODE_NAME[arg->errcode]);
935 }
936