1 /*---------------------------------------------------------------------------*
2   Project:  TwlSDK - MB - libraries
3   File:     mb_wm_base.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-04#$
14   $Rev: 9966 $
15   $Author: okajima_manabu $
16  *---------------------------------------------------------------------------*/
17 
18 
19 
20 #include "mb_private.h"
21 
22 
23 /*
24  * Determines whether the capacity is correct for the size that is being requested.
25  */
26 SDK_COMPILER_ASSERT(32 + sizeof(MBiParam) + 32 + sizeof(MB_CommPWork) + 32 + WM_SYSTEM_BUF_SIZE <=
27                     MB_SYSTEM_BUF_SIZE);
28 SDK_COMPILER_ASSERT(32 + sizeof(MBiParam) + 32 + sizeof(MB_CommCWork) + 32 + WM_SYSTEM_BUF_SIZE <=
29                     MB_CHILD_SYSTEM_BUF_SIZE);
30 
31 
32 /*
33  * Macro to calculate send and receive buffer sizes for the parent and child.
34  * Receive buffer:  parentMaxSize + WLHeader (48B) + WMHeader (2B)
35  * Send buffer: (parentMaxSize + WMHeader (2B) + ( KeySet (36B) only when KS ) + 31) & 0xffffffe0 (Correct alignment)
36  * Receive buffer: 15 devices' worth of (childMaxSize + WLHeader (8B) + WMHeader (2B) + ( KeyData (2B) (only when KeySharing) ) + total Header (8B) + 31) & 0xffffffe0 (Correct alignment)
37  */
38 #define WL_HEADER_LENGTH_P  48         /* WL header length when the parent receives. */
39 #define WM_HEADER_LENGTH    2          /* WM Header length. */
40 #define WL_HEADER_LENGTH_T  8          /* Total WL header length. */
41 #define WL_HEADER_LENGTH_C  8          /* WL header length of each child's data. */
42 
43 
44 // Macro; computes the size of the child receive buffer.
45 
46 #define WM_CalcChildSendBufSize(_pInfo_)        (u16)(WM_SIZE_MP_CHILD_SEND_BUFFER(((WMGameInfo *)(&(((WMBssDesc*)(_pInfo_))->gameInfo)))->childMaxSize, FALSE))
47 #define WM_CalcChildRecvBufSize(_pInfo_)        (u16)(WM_SIZE_MP_CHILD_RECEIVE_BUFFER(((WMGameInfo *)(&(((WMBssDesc*)(_pInfo_))->gameInfo)))->parentMaxSize, FALSE))
48 
49 // Macro; computes the size of the parent send and receive buffers.
50 #define WM_CalcParentSendBufSize(_libParam_)    (u16)(WM_SIZE_MP_PARENT_SEND_BUFFER(((MBiParam*)(_libParam_))->parentParam.parentMaxSize, FALSE))
51 #define WM_CalcParentRecvBufSize(_libParam_)    (u16)(WM_SIZE_MP_PARENT_RECEIVE_BUFFER(((MBiParam*)(_libParam_))->parentParam.childMaxSize, WM_NUM_MAX_CHILD, FALSE))
52 
53 
54 /* Default value for the Beacon interval (ms). */
55 #define MB_BEACON_PERIOD_DEFAULT    (200)
56 
57 /*
58  * Debug switch for switching the LifeTime.
59  */
60 #define  NO_LIFETIME    0
61 #if (NO_LIFETIME == 1)
62 #define FRAME_LIFE_TIME 0xFFFF
63 #define CAM_LIFE_TIME   0xFFFF
64 #define MP_LIFE_TIME    0xFFFF
65 #else
66 /* Measure that was performed during the period in which the WM library was unstable. */
67 /*
68 #define FRAME_LIFE_TIME 0xFFFF
69 */
70 #define FRAME_LIFE_TIME 5
71 #define CAM_LIFE_TIME   40
72 #define MP_LIFE_TIME    40
73 #endif
74 
75 #define TABLE_NO    0xFFFF
76 
77 
78 static u16 mbi_life_table_no = TABLE_NO;
79 static u16 mbi_life_frame = FRAME_LIFE_TIME;
80 static u16 mbi_life_cam = CAM_LIFE_TIME;
81 static u16 mbi_life_mp = MP_LIFE_TIME;
82 static BOOL mbi_power_save_mode = TRUE;
83 
84 static BOOL isEnableReject    = FALSE;
85 static u32  rejectGgid        = 0xffffffff;
86 static u32  rejectGgidMask    = 0xffffffff;
87 
88 //===========================================================
89 // Function Prototype Declarations
90 //===========================================================
91 static void MBi_ScanLock(u8 *macAddr); // Scan lock setting function.
92 static void MBi_ScanUnlock(void);      // Scan lock releasing function.
93 
94 /*
95  * Callback if there is an error when the WM result value is checked.
96  */
97 static void MBi_CheckWmErrcode(u16 apiid, int errcode);
98 static void MBi_ParentCallback(void *arg);
99 
100 
101 
102 /******************************************************************************/
103 /* Variables */
104 
105 static MBiParam *p_mbi_param;
106 static u16 WM_DMA_NO;
107 
108 /*
109  * WM system buffer.
110  * This was originally a member of MBiParam, but it was made independent for MB_StartParentFromIdle().
111  *
112  */
113 static u8 *wmBuf;
114 
115 
116 MB_CommCommonWork *mbc = NULL;
117 
118 
119 /* Variables for child */
120 WMscanExParam mbiScanParam ATTRIBUTE_ALIGN(32);
121 
122 
123 /******************************************************************************/
124 /* Functions */
125 
126 
127 /* Cycle through ScanChannel and make changes. */
changeScanChannel(WMscanExParam * p)128 static BOOL changeScanChannel(WMscanExParam *p)
129 {
130     u16     channel_bmp, channel, i;
131 
132     /* Get channel bitmap. */
133     channel_bmp = WM_GetAllowedChannel();
134 
135     /* If there is no channel that can be used, return FALSE. */
136     if (channel_bmp == 0)
137     {
138         OS_TWarning("No Available Scan channel\n");
139         return FALSE;
140     }
141 
142     /* If usable channels exist. */
143     for (i = 0, channel = p->channelList;
144          i < 16; i++, channel = (u16)((channel == 0) ? 1 : channel << 1))
145     {
146         if ((channel_bmp & channel ) == 0)
147         {
148             continue;
149         }
150 
151         /* If the detected channel is the same one as before, search for another channel. */
152         if (p->channelList != channel)
153         {
154             p->channelList =  channel;
155             break;
156         }
157     }
158 
159     return TRUE;
160 
161 }
162 
163 
164 /*---------------------------------------------------------------------------*
165   Name:         MB_SetLifeTime
166 
167   Description:  Explicitly specifies the lifetime of the MB wireless driver.
168                 The default value is ( 0xFFFF, 40, 0xFFFF, 40 ).
169 
170   Arguments:    tgid            TGID that will be specified.
171 
172   Returns:      The argument as is, or a suitable TGID.
173  *---------------------------------------------------------------------------*/
MB_SetLifeTime(u16 tableNumber,u16 camLifeTime,u16 frameLifeTime,u16 mpLifeTime)174 void MB_SetLifeTime(u16 tableNumber, u16 camLifeTime, u16 frameLifeTime, u16 mpLifeTime)
175 {
176     mbi_life_table_no = tableNumber;
177     mbi_life_cam = camLifeTime;
178     mbi_life_frame = frameLifeTime;
179     mbi_life_mp = mpLifeTime;
180 }
181 
182 /*---------------------------------------------------------------------------*
183   Name:         MB_SetPowerSaveMode
184 
185   Description:  Sets continuous power mode.
186                 This option is for stabilized driving in situations where power consumption can be ignored. It is disabled by default.
187 
188                 This should not be used by typical game applications unless they are being operated in an environment in which connection to power is guaranteed.
189 
190 
191   Arguments:    enable:           To enable, TRUE; To disable, FALSE.
192 
193   Returns:      None.
194  *---------------------------------------------------------------------------*/
MB_SetPowerSaveMode(BOOL enable)195 void MB_SetPowerSaveMode(BOOL enable)
196 {
197     mbi_power_save_mode = enable;
198 }
199 
200 
201 /*
202  * If we are currently processing, consider this to be success and return the converted WM result.
203  */
conv_errcode(int errcode)204 static inline int conv_errcode(int errcode)
205 {
206     return (errcode == WM_ERRCODE_OPERATING) ? WM_ERRCODE_SUCCESS : errcode;
207 }
208 
209 
210 /*
211  * Check MP transmit permission
212 
213    Added the mpBusy flag, which is set when SetMP is executed, to the determination elements, so that MP will not be set again after SetMP and before the callback returns.
214 
215 
216  */
MBi_IsSendEnabled(void)217 static BOOL MBi_IsSendEnabled(void)
218 {
219     return (p_mbi_param->mpStarted == 1) &&
220         (p_mbi_param->mpBusy == 0) &&
221         (p_mbi_param->endReq == 0) && (p_mbi_param->child_bitmap != 0);
222 }
223 
MBi_OnInitializeDone(void)224 static void MBi_OnInitializeDone(void)
225 {
226     int     errcode;
227     /* Issue API */
228     errcode = WM_SetIndCallback(MBi_ParentCallback);
229     MBi_CheckWmErrcode(WM_APIID_INDICATION, errcode);
230     errcode = WM_SetLifeTime(MBi_ParentCallback, mbi_life_table_no,
231                              mbi_life_cam, mbi_life_frame, mbi_life_mp);
232     MBi_CheckWmErrcode(WM_APIID_SET_LIFETIME, errcode);
233 }
234 
235 
236 /*
237  * If the MB parent device is using ichneumon to operate wirelessly with VRAM, the parent's MP data settings will be processed too fast if there are not enough child units, and the IPL will not follow the parent's MP communications.
238  *
239  *
240  * As a countermeasure to this, insert a fixed wait.
241  */
MbWaitForWvr(u32 cycles)242 static inline void MbWaitForWvr(u32 cycles)
243 {
244     u32     child_cnt = 0;
245     u32     i;
246 
247     for (i = 0; i < MB_MAX_CHILD; i++)
248     {
249         if (pPwork->p_comm_state[i] != MB_COMM_PSTATE_NONE)
250         {
251             if (++child_cnt >= 2)
252                 break;
253         }
254     }
255     // If there is only one child, insert a wait process.
256     if (child_cnt == 1)
257     {
258         OS_SpinWait(cycles);
259     }
260 }
261 
262 /*---------------------------------------------------------------------------*
263   Name:         MBi_EndCommon
264 
265   Description:  Common MB end processing.
266 
267   Arguments:    arg:              End callback arguments to the user.
268 
269   Returns:      None.
270  *---------------------------------------------------------------------------*/
MBi_EndCommon(void * arg)271 static void MBi_EndCommon(void *arg)
272 {
273     p_mbi_param->mbIsStarted = 0;
274     mbc->isMbInitialized = 0;
275     if (p_mbi_param->callback)
276     {
277         p_mbi_param->callback(MB_CALLBACK_END_COMPLETE, arg);
278     }
279 }
280 
281 /*
282  * Parent device callback
283  */
MBi_ParentCallback(void * arg)284 static void MBi_ParentCallback(void *arg)
285 {
286     int     errcode;
287     WMCallback *buf = (WMCallback *)arg;
288 
289     switch (buf->apiid)
290     {
291     case WM_APIID_INITIALIZE:
292         {
293             if (buf->errcode != WM_ERRCODE_SUCCESS)
294             {
295                 p_mbi_param->callback(MB_CALLBACK_ERROR, arg);
296                 return;
297             }
298             MBi_OnInitializeDone();
299         }
300         break;
301 
302     case WM_APIID_SET_LIFETIME:
303         {
304             if (buf->errcode != WM_ERRCODE_SUCCESS)
305             {
306                 p_mbi_param->callback(MB_CALLBACK_ERROR, arg);
307                 return;
308             }
309 
310             // Issue API
311             errcode = WM_SetParentParameter(MBi_ParentCallback, &p_mbi_param->parentParam);
312             MBi_CheckWmErrcode(WM_APIID_SET_P_PARAM, errcode);
313         }
314         break;
315 
316     case WM_APIID_SET_P_PARAM:
317         {
318             p_mbi_param->callback(MB_CALLBACK_INIT_COMPLETE, arg);
319             // An error code does not get returned here.
320             errcode = WM_SetBeaconIndication(MBi_ParentCallback, 1 /* 1:ON, 0:OFF */ );
321             MBi_CheckWmErrcode(WM_APIID_SET_BEACON_IND, errcode);
322         }
323         break;
324 
325         // Check whether or not to cause Beacon Send/Recv Indication to be issued.
326     case WM_APIID_SET_BEACON_IND:
327         if (!p_mbi_param->endReq)
328         {
329             if (buf->errcode != WM_ERRCODE_SUCCESS)
330             {
331                 p_mbi_param->callback(MB_CALLBACK_ERROR, arg);
332                 return;
333             }
334 
335             errcode = WMi_StartParentEx(MBi_ParentCallback, mbi_power_save_mode);
336             MBi_CheckWmErrcode(WM_APIID_START_PARENT, errcode);
337         }
338         else
339         {
340             // Disable beacon notifications and complete end processing
341             if (buf->errcode != WM_ERRCODE_SUCCESS)
342             {
343                 p_mbi_param->endReq = 0;
344                 p_mbi_param->callback(MB_CALLBACK_ERROR, arg);
345             }
346             else
347             {
348                 MBi_EndCommon(arg);
349             }
350         }
351         break;
352 
353     case WM_APIID_START_PARENT:
354         {
355             WMstartParentCallback *callback = (WMstartParentCallback *)arg;
356 
357             if (callback->errcode != WM_ERRCODE_SUCCESS)
358             {
359                 p_mbi_param->callback(MB_CALLBACK_ERROR, arg);
360                 return;
361             }
362 
363             switch (callback->state)
364             {
365             case WM_STATECODE_PARENT_START:
366                 p_mbi_param->child_bitmap = 0;
367                 p_mbi_param->mpStarted = 0;
368                 break;
369             case WM_STATECODE_CHILD_CONNECTED:
370 
371                 /* Forcibly break after a call to MB_End(). */
372                 if (p_mbi_param->endReq == 1)
373                     break;
374 
375                 p_mbi_param->child_bitmap |= (0x1 << callback->aid);
376                 p_mbi_param->callback(MB_CALLBACK_CHILD_CONNECTED, arg);
377 
378                 // If MP has not been started, start MP.
379                 if ((p_mbi_param->mpStarted == 0) && (!mbc->start_mp_busy))
380                 {
381                     mbc->start_mp_busy = TRUE;
382                     errcode = WM_StartMPEx(MBi_ParentCallback, (u16 *)p_mbi_param->recvBuf, p_mbi_param->recvBufSize, (u16 *)p_mbi_param->sendBuf, p_mbi_param->sendBufSize, (u16)(p_mbi_param->contSend ? 0 : 1), 0,   /* defaultRetryCount */
383                                            FALSE, FALSE, 1,     /* fixFreqMode */
384                                            TRUE /* ignoreFatalError */
385                         );
386                     MBi_CheckWmErrcode(WM_APIID_START_MP, errcode);
387 
388                 }
389                 else
390                 {
391                     // MP send-enabled callback.
392                     if (MBi_IsSendEnabled())
393                     {
394                         p_mbi_param->callback(MB_CALLBACK_MP_SEND_ENABLE, NULL);
395                     }
396                 }
397                 break;
398 
399             case WM_STATECODE_DISCONNECTED:
400                 p_mbi_param->child_bitmap &= ~(0x1 << callback->aid);
401                 p_mbi_param->callback(MB_CALLBACK_CHILD_DISCONNECTED, arg);
402                 break;
403 
404             case WM_STATECODE_DISCONNECTED_FROM_MYSELF:
405                 // Do nothing if it disconnects itself.
406                 break;
407 
408             case WM_STATECODE_BEACON_SENT:
409                 /* Forcibly break after a call to MB_End(). */
410                 if (p_mbi_param->endReq == 1)
411                     break;
412 
413                 // Send a notification that beacon transmission completed.
414                 p_mbi_param->callback(MB_CALLBACK_BEACON_SENT, arg);
415                 break;
416 
417             default:
418                 p_mbi_param->callback(MB_CALLBACK_ERROR, arg);
419                 break;
420             }
421         }
422         break;
423 
424     case WM_APIID_START_MP:
425         {
426             // An error code does not get returned here.
427             WMstartMPCallback *callback = (WMstartMPCallback *)arg;
428             mbc->start_mp_busy = FALSE;
429             switch (callback->state)
430             {
431             case WM_STATECODE_MP_START:
432                 // Set the flag that indicates MP has started.
433                 p_mbi_param->mpStarted = 1;
434                 {
435                     // MP send-enabled callback.
436                     if (p_mbi_param->endReq == 0)
437                     {
438                         p_mbi_param->callback(MB_CALLBACK_MP_SEND_ENABLE, NULL);
439                     }
440                 }
441                 break;
442 
443             case WM_STATECODE_MPEND_IND:
444                 // MP receive callback.
445                 p_mbi_param->callback(MB_CALLBACK_MP_PARENT_RECV, (void *)(callback->recvBuf));
446                 break;
447 
448             default:
449                 p_mbi_param->callback(MB_CALLBACK_ERROR, arg);
450                 break;
451             }
452             break;
453         }
454         break;
455 
456     case WM_APIID_SET_MP_DATA:
457         {
458             /* If MB parent is using ichneumon, enter a wait */
459             if (pPwork->useWvrFlag)
460             {
461                 MbWaitForWvr(13000);   // Make ARM9 wait for approximately 3 lines during an IRQ interrupt.
462             }
463             p_mbi_param->mpBusy = 0;
464             if (buf->errcode == WM_ERRCODE_SUCCESS)
465             {
466                 p_mbi_param->callback(MB_CALLBACK_MP_PARENT_SENT, arg);
467                 if (p_mbi_param->endReq == 0)
468                 {
469                     p_mbi_param->callback(MB_CALLBACK_MP_SEND_ENABLE, NULL);        // Allow the next transmission.
470                 }
471             }
472             else if (buf->errcode == WM_ERRCODE_SEND_QUEUE_FULL)
473             {
474                 p_mbi_param->callback(MB_CALLBACK_SEND_QUEUE_FULL_ERR, arg);
475             }
476             else
477             {
478                 p_mbi_param->callback(MB_CALLBACK_MP_PARENT_SENT_ERR, arg);
479                 if (p_mbi_param->endReq == 0)
480                 {
481                     p_mbi_param->callback(MB_CALLBACK_MP_SEND_ENABLE, NULL);        // Allow the next transmission.
482                 }
483             }
484         }
485         break;
486 
487     case WM_APIID_RESET:
488         if (!mbc->is_started_ex)
489         {
490             if (buf->errcode != WM_ERRCODE_SUCCESS)
491             {
492                 p_mbi_param->endReq = 0;
493                 p_mbi_param->callback(MB_CALLBACK_ERROR, arg);
494             }
495             else
496             {
497                 p_mbi_param->child_bitmap = 0;
498                 p_mbi_param->mpStarted = 0;
499                 errcode = WM_End(MBi_ParentCallback);
500                 MBi_CheckWmErrcode(WM_APIID_END, errcode);
501             }
502         }
503         else
504         {
505             (void)WM_SetPortCallback(WM_PORT_BT, NULL, NULL);
506             (void)WM_SetIndCallback(NULL);
507             if (buf->errcode != WM_ERRCODE_SUCCESS)
508             {
509                 p_mbi_param->endReq = 0;
510                 p_mbi_param->callback(MB_CALLBACK_ERROR, arg);
511             }
512             else
513             {
514                 errcode = WM_SetBeaconIndication(MBi_ParentCallback, 0);
515                 MBi_CheckWmErrcode(WM_APIID_SET_BEACON_IND, errcode);
516             }
517         }
518         break;
519     case WM_APIID_END:
520         {
521             if (buf->errcode != WM_ERRCODE_SUCCESS)
522             {
523                 p_mbi_param->endReq = 0;
524                 p_mbi_param->callback(MB_CALLBACK_ERROR, arg);
525             }
526             else
527             {
528                 MBi_EndCommon(arg);
529             }
530         }
531         break;
532 
533     case WM_APIID_DISCONNECT:
534         {
535             WMDisconnectCallback *callback = (WMDisconnectCallback *)arg;
536 
537             if (buf->errcode != WM_ERRCODE_SUCCESS)
538             {
539                 return;
540             }
541 
542             // Update the child information.
543             p_mbi_param->child_bitmap &= ~(callback->disconnectedBitmap);
544         }
545         break;
546 
547     case WM_APIID_INDICATION:
548         {
549             WMindCallback *cb = (WMindCallback *)arg;
550             switch (cb->state)
551             {
552             case WM_STATECODE_BEACON_RECV:     // Indicate beacon received
553                 p_mbi_param->callback(MB_CALLBACK_BEACON_RECV, arg);
554                 break;
555             case WM_STATECODE_DISASSOCIATE:    // Indicate disconnection
556                 p_mbi_param->callback(MB_CALLBACK_DISASSOCIATE, arg);
557                 break;
558             case WM_STATECODE_REASSOCIATE:     // Indicate reconnection
559                 p_mbi_param->callback(MB_CALLBACK_REASSOCIATE, arg);
560                 break;
561             case WM_STATECODE_AUTHENTICATE:    // Indicate confirmed authentication
562                 p_mbi_param->callback(MB_CALLBACK_AUTHENTICATE, arg);
563                 break;
564 
565             case WM_STATECODE_FIFO_ERROR:
566                 OS_TPanic("FIFO Error\n");
567                 break;
568             case WM_STATECODE_INFORMATION:
569                 // Does nothing.
570                 break;
571             }
572         }
573         break;
574 
575     default:
576         p_mbi_param->callback(MB_CALLBACK_ERROR, arg);
577         break;
578     }
579 }
580 
581 /*
582  * Child device callback
583  */
MBi_ChildPortCallback(void * arg)584 static void MBi_ChildPortCallback(void *arg)
585 {
586     WMPortRecvCallback *cb = (WMPortRecvCallback *)arg;
587 
588     if (cb->errcode != WM_ERRCODE_SUCCESS)
589     {
590         return;
591     }
592 
593     switch (cb->state)
594     {
595     case WM_STATECODE_PORT_RECV:
596         // Notify the program that data was received.
597         p_mbi_param->callback(MB_CALLBACK_MP_CHILD_RECV, (void *)(arg));
598         break;
599     case WM_STATECODE_CONNECTED:
600         // Connection notification
601         break;
602     case WM_STATECODE_PORT_INIT:
603     case WM_STATECODE_DISCONNECTED:
604     case WM_STATECODE_DISCONNECTED_FROM_MYSELF:
605         break;
606     }
607 }
608 
MBi_ChildCallback(void * arg)609 static void MBi_ChildCallback(void *arg)
610 {
611     WMCallback *buf = (WMCallback *)arg;
612     MBiParam *const p_param = p_mbi_param;
613     int     errcode;
614 
615     switch (buf->apiid)
616     {
617         //---------------------------------------------------------------
618     case WM_APIID_INITIALIZE:
619         {
620             if (buf->errcode != WM_ERRCODE_SUCCESS)
621             {
622                 p_param->callback(MB_CALLBACK_ERROR, arg);
623                 return;
624             }
625 
626             p_param->callback(MB_CALLBACK_INIT_COMPLETE, arg);
627 
628             // Issue API
629             errcode =
630                 WM_SetLifeTime(MBi_ChildCallback, mbi_life_table_no, mbi_life_cam, mbi_life_frame,
631                                mbi_life_mp);
632             MBi_CheckWmErrcode(WM_APIID_SET_LIFETIME, errcode);
633         }
634         break;
635 
636     case WM_APIID_SET_LIFETIME:
637         {
638             if (buf->errcode != WM_ERRCODE_SUCCESS)
639             {
640                 p_param->callback(MB_CALLBACK_ERROR, arg);
641                 return;
642             }
643 
644             // Issue WM_StartScan
645             if (mbiScanParam.channelList == 0)
646                 mbiScanParam.channelList = 0x0001; /* 1ch */
647             if (mbiScanParam.maxChannelTime == 0)
648             {
649                 mbiScanParam.maxChannelTime = 200;
650             }
651             mbiScanParam.bssid[0] = 0xff;
652             mbiScanParam.bssid[1] = 0xff;
653             mbiScanParam.bssid[2] = 0xff;
654             mbiScanParam.bssid[3] = 0xff;
655             mbiScanParam.bssid[4] = 0xff;
656             mbiScanParam.bssid[5] = 0xff;
657             mbiScanParam.scanType = WM_SCANTYPE_PASSIVE;
658             mbiScanParam.ssidLength = 0;
659             p_param->scanning_flag = TRUE;
660             p_param->scan_channel_flag = TRUE;
661             errcode = WM_StartScanEx(MBi_ChildCallback, &mbiScanParam);
662             MBi_CheckWmErrcode(WM_APIID_START_SCAN_EX, errcode);
663         }
664         break;
665 
666     case WM_APIID_START_SCAN_EX:
667         {
668             WMstartScanExCallback *callback = (WMstartScanExCallback *)arg;
669 
670             if (callback->errcode != WM_ERRCODE_SUCCESS)
671             {
672                 p_param->callback(MB_CALLBACK_ERROR, arg);
673                 return;
674             }
675 
676             switch (callback->state)
677             {
678             case WM_STATECODE_SCAN_START:
679                 break;
680 
681             case WM_STATECODE_PARENT_FOUND:
682                 // Store the parent information gotten with scan
683                 {
684                     WMstartScanExCallback *tmpBuf = (WMstartScanExCallback *)arg;
685 
686                     u8 j;
687                     u8 numInvalidBeacon =0;
688                     for(j=0;j<tmpBuf->bssDescCount;j++)
689                     {
690                         WMBssDesc *buffer = tmpBuf->bssDesc[j];
691                         ParentInfo *p = &p_param->parent_info[0];
692                         int i;
693 
694                         /* A problem was discovered where MP communication beacons that are not general AP or MB fill up the list, so beacons from other than MB parent devices are removed from the list.
695                          *    */
696                         if( !WM_IsValidGameBeacon( buffer ) || !MBi_CheckMBParent( buffer ) )
697                         {
698                             numInvalidBeacon++;
699                             continue; //Anything other than the MB beacon is destroyed
700                         }
701 
702                         /* In the TWL download play feature, removed from list due to Parental Control reasons.
703                          *                                               */
704                         if( isEnableReject == TRUE && ((buffer->gameInfo.ggid & rejectGgidMask) == (rejectGgid & rejectGgidMask)) )
705                         {
706                             numInvalidBeacon++;
707                             OS_TPrintf("GGID %08X is reject!\n", buffer->gameInfo.ggid);
708                             continue; //Anything other than the MB beacon is destroyed
709                         }
710 
711                         for (i = 0; i < p_param->found_parent_count; ++i)
712                         {
713 
714                             if (WM_IsBssidEqual(buffer->bssid, p[i].scan_data.macAddress))
715                             {
716                                 p[i].scan_data.gameInfoLength = buffer->gameInfoLength;
717                                 p[i].scan_data.gameInfo = buffer->gameInfo;
718                                 DC_InvalidateRange(p_param->parent_info[i].parentInfo,
719                                                    WM_BSS_DESC_SIZE);
720                                 MI_DmaCopy16(WM_DMA_NO, buffer,
721                                              p_param->parent_info[i].parentInfo, WM_BSS_DESC_SIZE);
722                                 p_param->last_found_parent_no = i;
723                                 p_param->callback(MB_CALLBACK_PARENT_FOUND, &tmpBuf->linkLevel[j]);
724                                 goto scan_end; //In the meantime, do not receive multiple MB beacons
725                             }
726                         }
727 
728                         if (i < MB_NUM_PARENT_INFORMATIONS)
729                         {
730                             p_param->found_parent_count = (u16)(i + 1);
731                             // This is a newly discovered parent device, so store the data (to maintain compatibility, store in StartScanCallback)
732                             MI_CpuCopy8(buffer->bssid, p[i].scan_data.macAddress, WM_SIZE_BSSID );
733                             p[i].scan_data.channel   = buffer->channel;
734                             p[i].scan_data.linkLevel = tmpBuf->linkLevel[j];
735                             MI_CpuCopy16(&buffer->gameInfo, &p[i].scan_data.gameInfo, WM_SIZE_GAMEINFO);
736 
737                             DC_InvalidateRange(p_param->parent_info[i].parentInfo, WM_BSS_DESC_SIZE);
738                             MI_DmaCopy16(WM_DMA_NO, buffer,
739                                          p_param->parent_info[i].parentInfo, WM_BSS_DESC_SIZE);
740                             p_param->last_found_parent_no = i;
741                             p_param->callback(MB_CALLBACK_PARENT_FOUND, &tmpBuf->linkLevel[j]);
742                             goto scan_end; //In the meantime, do not receive multiple MB beacons
743                         }
744                     }
745                     if( tmpBuf->bssDescCount == numInvalidBeacon)
746                     {
747                         p_param->callback(MB_CALLBACK_PARENT_NOT_FOUND, arg);   // This callback to ParentInfoLifeTimeCount
748                     }
749 
750                 scan_end:
751                     if (!p_param->scanning_flag)
752                     {
753                         return;
754                     }
755 
756                     if (p_param->scan_channel_flag)
757                     {
758                         if (FALSE == changeScanChannel(&mbiScanParam))
759                         {
760                             (void)MBi_CommEnd();
761                         }
762                     }
763                     errcode = WM_StartScanEx(MBi_ChildCallback, &mbiScanParam);
764                     MBi_CheckWmErrcode(WM_APIID_START_SCAN_EX, errcode);
765                 }
766                 break;
767 
768             case WM_STATECODE_PARENT_NOT_FOUND:
769                 p_param->callback(MB_CALLBACK_PARENT_NOT_FOUND, arg);   // This callback to ParentInfoLifeTimeCount
770                 if (!p_param->scanning_flag)
771                 {
772                     return;
773                 }
774 
775                 if (p_param->scan_channel_flag)
776                 {
777                     if (FALSE == changeScanChannel(&mbiScanParam))
778                     {
779                         (void)MBi_CommEnd();
780                     }
781                 }
782                 errcode = WM_StartScanEx(MBi_ChildCallback, &mbiScanParam);
783                 MBi_CheckWmErrcode(WM_APIID_START_SCAN_EX, errcode);
784                 break;
785 
786             default:
787                 p_param->callback(MB_CALLBACK_ERROR, arg);
788                 break;
789             }
790         }
791         break;
792 
793     case WM_APIID_END_SCAN:
794         {
795             if (buf->errcode != WM_ERRCODE_SUCCESS)
796             {
797                 p_param->callback(MB_CALLBACK_ERROR, arg);
798                 return;
799             }
800 
801             errcode = WM_StartConnect(MBi_ChildCallback, p_param->pInfo, NULL);
802             MBi_CheckWmErrcode(WM_APIID_START_CONNECT, errcode);
803         }
804         break;
805 
806     case WM_APIID_START_CONNECT:
807         {
808             WMstartConnectCallback *callback = (WMstartConnectCallback *)arg;
809 
810             if (callback->errcode != WM_ERRCODE_SUCCESS)
811             {
812                 /* Reset the number of parents. */
813                 p_param->found_parent_count = 0;
814                 // Error notification by a callback.
815                 p_param->callback(MB_CALLBACK_CONNECT_FAILED, arg);
816                 return;
817             }
818 
819             switch (callback->state)
820             {
821             case WM_STATECODE_CONNECT_START:
822                 p_param->child_bitmap = 0;
823                 p_param->mpStarted = 1;
824                 break;
825 
826             case WM_STATECODE_CONNECTED:
827                 p_param->my_aid = (u16)callback->aid;
828                 p_param->callback(MB_CALLBACK_CONNECTED_TO_PARENT, arg);
829                 p_param->child_bitmap = 1;
830 
831                 errcode = WM_SetPortCallback(WM_PORT_BT, MBi_ChildPortCallback, NULL);
832 
833                 if (errcode != WM_ERRCODE_SUCCESS)
834                 {
835                     break;
836                 }
837 
838                 errcode = WM_StartMPEx(MBi_ChildCallback, (u16 *)p_param->recvBuf, p_param->recvBufSize, (u16 *)p_param->sendBuf, p_param->sendBufSize, (u16)(p_param->contSend ? 0 : 1), 0,    /* defaultRetryCount */
839                                        FALSE, FALSE, 1, /* fixFreqMode */
840                                        TRUE     /* ignoreFatalError */
841                     );
842                 MBi_CheckWmErrcode(WM_APIID_START_MP, errcode);
843                 break;
844 
845             case WM_STATECODE_DISCONNECTED:
846                 p_param->callback(MB_CALLBACK_DISCONNECTED_FROM_PARENT, arg);
847                 p_param->child_bitmap = 0;
848                 p_param->mpStarted = 0;
849                 break;
850 
851             case WM_STATECODE_DISCONNECTED_FROM_MYSELF:
852                 // Do nothing if it disconnects itself.
853                 break;
854 
855             default:
856                 p_param->callback(MB_CALLBACK_ERROR, arg);
857                 break;
858             }
859         }
860         break;
861 
862     case WM_APIID_START_MP:
863         {
864             WMstartMPCallback *callback = (WMstartMPCallback *)arg;
865 
866             switch (callback->state)
867             {
868             case WM_STATECODE_MP_START:
869                 p_param->mpStarted = 1; // Set the flag that indicates MP has started.
870                 {
871                     // MP send-enabled callback.
872                     if (MBi_IsSendEnabled())
873                     {
874                         p_param->callback(MB_CALLBACK_MP_SEND_ENABLE, NULL);
875                     }
876                 }
877                 break;
878 
879             case WM_STATECODE_MP_IND:
880                 if (callback->errcode == WM_ERRCODE_INVALID_POLLBITMAP)
881                 {
882 //                  p_param->callback( MB_CALLBACK_MP_CHILD_RECV, (void*)(callback->recvBuf) );
883                 }
884                 else
885                 {
886 //                    p_param->callback( MB_CALLBACK_MP_CHILD_RECV, (void*)(callback->recvBuf) );
887                 }
888                 break;
889 
890             case WM_STATECODE_MPACK_IND:
891                 {
892                     //p_param->callback( MB_CALLBACK_MPACK_IND, NULL );
893                 }
894                 break;
895 
896             default:
897                 p_param->callback(MB_CALLBACK_ERROR, arg);
898                 break;
899             }
900         }
901         break;
902 
903     case WM_APIID_SET_MP_DATA:
904         {
905             p_param->mpBusy = 0;
906             if (buf->errcode == WM_ERRCODE_SUCCESS)
907             {
908                 p_param->callback(MB_CALLBACK_MP_CHILD_SENT, arg);
909             }
910             else if (buf->errcode == WM_ERRCODE_TIMEOUT)
911             {
912                 p_param->callback(MB_CALLBACK_MP_CHILD_SENT_TIMEOUT, arg);
913             }
914             else
915             {
916                 p_param->callback(MB_CALLBACK_MP_CHILD_SENT_ERR, arg);
917             }
918             // Allow the next transmission.
919             if (p_mbi_param->endReq == 0)
920             {
921                 p_param->callback(MB_CALLBACK_MP_SEND_ENABLE, NULL);
922             }
923         }
924         break;
925 
926         //---------------------------------------------------------------
927     case WM_APIID_RESET:
928         {
929             if (buf->errcode != WM_ERRCODE_SUCCESS)
930             {
931                 p_param->endReq = 0;
932                 p_param->callback(MB_CALLBACK_ERROR, arg);
933                 return;
934             }
935             p_mbi_param->child_bitmap = 0;
936             p_mbi_param->mpStarted = 0;
937 
938             errcode = WM_End(MBi_ChildCallback);
939             MBi_CheckWmErrcode(WM_APIID_END, errcode);
940         }
941         break;
942 
943         //---------------------------------------------------------------
944     case WM_APIID_END:
945         {
946             if (buf->errcode != WM_ERRCODE_SUCCESS)
947             {
948                 p_param->endReq = 0;
949                 p_param->callback(MB_CALLBACK_ERROR, arg);
950                 return;
951             }
952             MBi_EndCommon(arg);
953         }
954         break;
955 
956         //---------------------------------------------------------------
957     case WM_APIID_START_KS:
958         {
959             // MP send-enabled callback.
960             if (MBi_IsSendEnabled())
961             {
962                 p_param->callback(MB_CALLBACK_MP_SEND_ENABLE, NULL);
963             }
964         }
965         break;
966 
967         //---------------------------------------------------------------
968     case WM_APIID_INDICATION:
969         {
970             WMindCallback *cb = (WMindCallback *)arg;
971             switch (cb->state)
972             {
973             case WM_STATECODE_FIFO_ERROR:
974                 OS_TPanic("FIFO Error\n");
975                 break;
976             case WM_STATECODE_INFORMATION:
977                 // Does nothing.
978                 break;
979             }
980         }
981         break;
982     default:
983         p_param->callback(MB_CALLBACK_ERROR, arg);
984         break;
985     }
986 }
987 
988 
989 /*---------------------------------------------------------------------------*
990   Name:         MBi_GetBeaconPeriodDispersion
991 
992   Description:  Gets the value to be added to the beacon interval with appropriate variation for each device's MAC address.
993 
994 
995   Arguments:    None.
996 
997   Returns:      u32 -   Returns a value between 0 and 19 that is varied as appropriate for each device.
998  *---------------------------------------------------------------------------*/
MBi_GetBeaconPeriodDispersion(void)999 static u32 MBi_GetBeaconPeriodDispersion(void)
1000 {
1001     u8      mac[6];
1002     u32     ret;
1003     s32     i;
1004 
1005     OS_GetMacAddress(mac);
1006     for (i = 0, ret = 0; i < 6; i++)
1007     {
1008         ret += mac[i];
1009     }
1010     ret += OS_GetVBlankCount();
1011     ret *= 7;
1012     return (ret % 20);
1013 }
1014 
1015 
1016 /******************************************************************************/
1017 /* API */
1018 
1019 /* Initialization */
MB_Init(void * work,const MBUserInfo * user,u32 ggid,u32 tgid,u32 dma)1020 int MB_Init(void *work, const MBUserInfo *user, u32 ggid, u32 tgid, u32 dma)
1021 {
1022 
1023     SDK_ASSERT(user != NULL);
1024     SDK_ASSERT(work != NULL);
1025     SDK_ASSERT((dma < 4));
1026     SDK_ASSERT(user->nameLength <= MB_USER_NAME_LENGTH);
1027 
1028     if (mbc && mbc->isMbInitialized)
1029     {
1030         return MB_ERRCODE_INVALID_STATE;
1031     }
1032     else
1033     {
1034         MBiParam *const p_parm = (MBiParam *) ((((u32)work) + 0x1F) & ~0x1F);
1035         MB_CommCommonWork *const p_com =
1036             (MB_CommCommonWork *) ((((u32)p_parm) + sizeof(*p_parm) + 0x1F) & ~0x1F);
1037         OSIntrMode enabled;
1038 
1039         /*
1040          * Automatic retrieval is performed if TGID is automatically specified.
1041          * (since RTC is used internally, retrieve before interrupts are disabled)
1042          */
1043         if (tgid == MB_TGID_AUTO)
1044         {
1045             tgid = WM_GetNextTgid();
1046         }
1047 
1048         enabled = OS_DisableInterrupts();
1049 
1050         /* Initialization of values for lifetime and power-save mode settings. */
1051         mbi_life_table_no = TABLE_NO;
1052         mbi_life_frame = FRAME_LIFE_TIME;
1053         mbi_life_cam = CAM_LIFE_TIME;
1054         mbi_life_mp = MP_LIFE_TIME;
1055         mbi_power_save_mode = TRUE;
1056 
1057         /* Initialize the DMA channel and work region. */
1058         WM_DMA_NO = (u16)dma;
1059         p_mbi_param = p_parm;
1060         mbc = p_com;
1061         MI_CpuClear32(p_parm, sizeof(*p_parm));
1062         MI_CpuClear16(p_com, sizeof(*p_com));
1063 
1064         {                              /* Save the user name and game name. */
1065             int     i;
1066             static const u16 *game = L"multiboot";
1067             u16    *c;
1068             c = (u16 *)p_parm->uname;
1069             for (i = 0; i < user->nameLength; ++i)
1070             {
1071                 *c++ = user->name[i];
1072             }
1073             c = (u16 *)p_parm->gname;
1074             for (i = 0; i < WM_SIZE_GAMENAME; ++i)
1075             {
1076                 if (*game == 0)
1077                 {
1078                     break;
1079                 }
1080                 *c++ = *game++;
1081             }
1082             MI_CpuCopy8(user, &p_com->user, sizeof(MBUserInfo));
1083             if (user->nameLength < MB_USER_NAME_LENGTH)
1084             {
1085                 p_com->user.name[user->nameLength] = 0;
1086             }
1087         }
1088 
1089         {
1090             p_parm->p_sendlen = MB_COMM_P_SENDLEN_DEFAULT;
1091             p_parm->p_recvlen = MB_COMM_P_RECVLEN_DEFAULT;
1092 
1093             /* Set the parent information (information obtained by a child when scanning). */
1094             p_parm->sendBufSize = 0;
1095             p_parm->recvBufSize = 0;
1096 
1097             /* Unnecessary? */
1098             p_parm->contSend = 1;
1099 
1100             p_parm->recvBuf = (WMmpRecvBuf *)p_com->recvbuf;
1101 
1102             {
1103                 WMParentParam *const p_parent = &p_parm->parentParam;
1104                 /*
1105                  * The beacon's entry and mb are disabled the first time.
1106                  * This is turned on with SetGameInfo in MbBeacon.
1107                  */
1108                 p_parent->entryFlag = 0;
1109                 p_parent->multiBootFlag = 0;
1110                 p_parent->CS_Flag = 1;
1111                 p_parent->KS_Flag = 0;
1112                 /* Set this device's unique GGID and TGID. */
1113                 p_parent->ggid = ggid;
1114                 p_parent->tgid = (u16)tgid;
1115                 p_parent->beaconPeriod =
1116                     (u16)(MB_BEACON_PERIOD_DEFAULT + MBi_GetBeaconPeriodDispersion());
1117                 p_parent->maxEntry = 15;
1118             }
1119         }
1120 
1121         p_parm->mpBusy = 0;
1122         p_parm->mbIsStarted = 0;
1123         p_com->isMbInitialized = 1;
1124 
1125         p_com->start_mp_busy = FALSE;
1126 
1127         (void)OS_RestoreInterrupts(enabled);
1128     }
1129 
1130     return MB_ERRCODE_SUCCESS;
1131 }
1132 
1133 #define MP_USEC_TIME_LIMIT  (5600)
1134 
MBi_IsCommSizeValid(u16 sendSize,u16 recvSize,u16 entry_num)1135 static BOOL MBi_IsCommSizeValid(u16 sendSize, u16 recvSize, u16 entry_num)
1136 {
1137     int     usec;
1138 
1139     SDK_ASSERT(entry_num > 0 && entry_num <= 15);
1140 
1141     /* If sendSize is outside the defined range, judge it to be an invalid size setting. */
1142     if (sendSize > MB_COMM_P_SENDLEN_MAX || sendSize < MB_COMM_P_SENDLEN_MIN)
1143     {
1144         OS_TWarning("MB Parent send buffer size is out of the range.[%3d - %3d Bytes]\n",
1145                     MB_COMM_P_SENDLEN_MIN, MB_COMM_P_SENDLEN_MAX);
1146         return FALSE;
1147     }
1148 
1149     /* If recvSize is outside the defined range, judge it to be an invalid size setting. */
1150     if (recvSize > MB_COMM_P_RECVLEN_MAX || recvSize < MB_COMM_P_RECVLEN_MIN)
1151     {
1152         OS_TWarning
1153             ("MB Parent receive buffer size per child is out of the range.[%3d - %3d Bytes]\n",
1154              MB_COMM_P_RECVLEN_MIN, MB_COMM_P_RECVLEN_MAX);
1155         return FALSE;
1156     }
1157 
1158     /* Evaluation for the time taken to perform MP communications once. */
1159     usec = 330 + 4 * (sendSize + 38) + entry_num * (112 + 4 * (recvSize + 32));
1160 
1161     /* If needed time exceeds 5600 microseconds, judge it to be an invalid size setting. */
1162     if (usec >= MP_USEC_TIME_LIMIT)
1163     {
1164         OS_TWarning("These send receive sizes require lower than %4dusec\n"
1165                     "it exceeds %4d usec\n", MP_USEC_TIME_LIMIT, usec);
1166         return FALSE;
1167     }
1168 
1169     return TRUE;
1170 }
1171 
1172 
MB_SetParentCommParam(u16 sendSize,u16 maxChildren)1173 BOOL MB_SetParentCommParam(u16 sendSize, u16 maxChildren)
1174 {
1175     OSIntrMode enabled = OS_DisableInterrupts();
1176 
1177     /* Cannot change if WM has started. */
1178     if (p_mbi_param->mbIsStarted)
1179     {
1180         OS_TWarning("MB has Already started\n");
1181 
1182         (void)OS_RestoreInterrupts(enabled);
1183         return FALSE;
1184     }
1185 
1186     /* Judge whether the send/receive data sizes are correct */
1187     if (FALSE == MBi_IsCommSizeValid(sendSize, MB_COMM_P_RECVLEN_DEFAULT, maxChildren))
1188     {
1189         OS_TWarning("MP data sizes have not changed\n");
1190         //
1191         (void)OS_RestoreInterrupts(enabled);
1192         return FALSE;
1193     }
1194 
1195     /* Set the maximum number of people that can connect. */
1196     p_mbi_param->parentParam.maxEntry = maxChildren;
1197 
1198     /* Set the size of the data being sent and received. */
1199     p_mbi_param->p_sendlen = sendSize;
1200     p_mbi_param->p_recvlen = MB_COMM_P_RECVLEN_DEFAULT;
1201 
1202     (void)OS_RestoreInterrupts(enabled);
1203 
1204     return TRUE;
1205 }
1206 
1207 
MB_SetParentCommSize(u16 sendSize)1208 BOOL MB_SetParentCommSize(u16 sendSize)
1209 {
1210     OSIntrMode enabled = OS_DisableInterrupts();
1211     BOOL    ret;
1212 
1213     /* The maximum number of connected people inherits the current settings. */
1214     ret = MB_SetParentCommParam(sendSize, p_mbi_param->parentParam.maxEntry);
1215 
1216     (void)OS_RestoreInterrupts(enabled);
1217 
1218     return ret;
1219 }
1220 
MB_GetTgid(void)1221 u16 MB_GetTgid(void)
1222 {
1223     return p_mbi_param->parentParam.tgid;
1224 }
1225 
1226 /* Initialization (The part common to parent and child) */
MBi_StartCommon(void)1227 static int MBi_StartCommon(void)
1228 {
1229     int     errcode;
1230 
1231     p_mbi_param->mpStarted = 0;
1232     p_mbi_param->child_bitmap = 0;
1233     p_mbi_param->endReq = 0;
1234     p_mbi_param->currentTgid = 0;
1235     MBi_SetMaxScanTime(MB_SCAN_TIME_NORMAL);
1236 
1237     if (!mbc->is_started_ex)
1238     {
1239         do
1240         {
1241             errcode = WM_Initialize(wmBuf, p_mbi_param->callback_ptr, WM_DMA_NO);
1242         }
1243         while (errcode == WM_ERRCODE_WM_DISABLE);
1244         if (errcode != WM_ERRCODE_OPERATING)
1245         {
1246             OS_TWarning("WM_Initialize failed!\n");
1247             return MB_ERRCODE_WM_FAILURE;
1248         }
1249         else
1250         {
1251             (void)WM_SetIndCallback(p_mbi_param->callback_ptr);
1252             p_mbi_param->mbIsStarted = 1;
1253             return MB_ERRCODE_SUCCESS;
1254         }
1255     }
1256     else
1257     {
1258         (void)WM_SetIndCallback(p_mbi_param->callback_ptr);
1259         p_mbi_param->mbIsStarted = 1;
1260         MBi_OnInitializeDone();
1261         return MB_ERRCODE_SUCCESS;
1262     }
1263 }
1264 
1265 
1266 /* Shared processing for setting parent parameters and starting. */
MBi_StartParentCore(int channel)1267 static int MBi_StartParentCore(int channel)
1268 {
1269     int     i, ret;
1270     MBCommPStateCallback cb_tmp;
1271     OSIntrMode enabled;
1272 
1273     enabled = OS_DisableInterrupts();
1274 
1275     p_mbi_param->parentParam.channel = (u16)channel;
1276     wmBuf = (u8 *)((((u32)mbc) + sizeof(MB_CommPWork) + 31) & ~31);
1277 
1278     /* Save temporarily for times when the callback is already set. */
1279     cb_tmp = pPwork->parent_callback;
1280 
1281     /* Clear the parent's unique work region */
1282     MI_CpuClear16((void *)((u32)pPwork + sizeof(MB_CommCommonWork)),
1283                   sizeof(MB_CommPWork) - sizeof(MB_CommCommonWork));
1284     MB_CommSetParentStateCallback(cb_tmp);
1285 
1286     /* Calculate parameters that depend on the send/receive size. */
1287     mbc->block_size_max = MB_COMM_CALC_BLOCK_SIZE(p_mbi_param->p_sendlen);
1288 
1289     MBi_SetChildMPMaxSize(p_mbi_param->p_recvlen);
1290     MBi_SetParentPieceBuffer(&pPwork->req_data_buf);
1291 
1292     for (i = 0; i < MB_MAX_CHILD; i++)
1293     {
1294         pPwork->p_comm_state[i] = MB_COMM_PSTATE_NONE;
1295         pPwork->fileid_of_child[i] = -1;        /* Initialize the requested FileID from the child. */
1296     }
1297     pPwork->file_num = 0;
1298 
1299     MI_CpuClear16(&pPwork->fileinfo[0], sizeof(pPwork->fileinfo));
1300     MI_CpuClear8(&pPwork->req2child[0], sizeof(pPwork->req2child));
1301 
1302     p_mbi_param->mode = MB_MODE_PARENT;
1303     p_mbi_param->callback = MBi_CommParentCallback;
1304     p_mbi_param->callback_ptr = MBi_ParentCallback;
1305 
1306     /* Parent maximum transmission size (Bytes). */
1307     p_mbi_param->parentParam.parentMaxSize = p_mbi_param->p_sendlen;
1308     p_mbi_param->sendBufSize = WM_CalcParentSendBufSize(p_mbi_param);
1309     /* Child maximum transmission size (Bytes). */
1310     p_mbi_param->parentParam.childMaxSize = p_mbi_param->p_recvlen;
1311     p_mbi_param->recvBufSize = WM_CalcParentRecvBufSize(p_mbi_param);
1312 
1313     OS_TPrintf("Parent sendSize : %4d\n", p_mbi_param->parentParam.parentMaxSize);
1314     OS_TPrintf("Parent recvSize : %4d\n", p_mbi_param->parentParam.childMaxSize);
1315     OS_TPrintf("Parent sendBufSize : %4d\n", p_mbi_param->sendBufSize);
1316     OS_TPrintf("Parent recvBufSize : %4d\n", p_mbi_param->recvBufSize);
1317 
1318     MB_InitSendGameInfoStatus();
1319 
1320     ret = MBi_StartCommon();
1321 
1322     (void)OS_RestoreInterrupts(enabled);
1323 
1324     pPwork->useWvrFlag = PXI_IsCallbackReady(PXI_FIFO_TAG_WVR, PXI_PROC_ARM7);
1325 
1326     return ret;
1327 }
1328 
1329 /* Set parent parameters & start (Initialized internally in WM) */
MB_StartParent(int channel)1330 int MB_StartParent(int channel)
1331 {
1332     mbc->is_started_ex = FALSE;
1333     return MBi_StartParentCore(channel);
1334 }
1335 
1336 /* Set parent parameters & start (Already started external to WM) */
MB_StartParentFromIdle(int channel)1337 int MB_StartParentFromIdle(int channel)
1338 {
1339     mbc->is_started_ex = TRUE;
1340     return MBi_StartParentCore(channel);
1341 }
1342 
1343 /* Set child parameters and start. */
MB_StartChild(void)1344 int MB_StartChild(void)
1345 {
1346     int     ret;
1347     MBCommCStateCallbackFunc cb_tmp;
1348     OSIntrMode enabled;
1349 
1350     enabled = OS_DisableInterrupts();
1351 
1352     mbc->is_started_ex = FALSE;
1353 
1354     wmBuf = (u8 *)((((u32)mbc) + sizeof(MB_CommCWork) + 31) & ~31);
1355 
1356     /* Save temporarily for times when the callback is already set. */
1357     cb_tmp = pCwork->child_callback;
1358 
1359     /* Clear the child's unique work region */
1360     MI_CpuClear16((void *)((u32)pCwork + sizeof(MB_CommCommonWork)),
1361                   sizeof(MB_CommCWork) - sizeof(MB_CommCommonWork));
1362     MB_CommSetChildStateCallback(cb_tmp);
1363 
1364     pCwork->c_comm_state = MB_COMM_CSTATE_NONE;
1365 
1366     p_mbi_param->mode = MB_MODE_CHILD;
1367     p_mbi_param->callback = MBi_CommChildCallback;
1368     p_mbi_param->callback_ptr = MBi_ChildCallback;
1369 
1370     p_mbi_param->scanning_flag = FALSE;
1371     p_mbi_param->scan_channel_flag = TRUE;
1372     p_mbi_param->last_found_parent_no = -1;
1373 
1374     MBi_SetBeaconRecvStatusBufferDefault();
1375     MBi_SetScanLockFunc(MBi_ScanLock, MBi_ScanUnlock);
1376     MB_InitRecvGameInfoStatus();
1377 
1378     ret = MBi_StartCommon();
1379 
1380     (void)OS_RestoreInterrupts(enabled);
1381 
1382     return ret;
1383 }
1384 
1385 
1386 /* Process for ending wireless communications if the task thread has ended or if it never started. */
MBi_CallReset(void)1387 static int MBi_CallReset(void)
1388 {
1389     int     errcode;
1390     errcode = WM_Reset(p_mbi_param->callback_ptr);
1391     MBi_CheckWmErrcode(WM_APIID_RESET, errcode);
1392     return conv_errcode(errcode);
1393 }
1394 
MBi_OnReset(MBiTaskInfo * p_task)1395 static void MBi_OnReset(MBiTaskInfo * p_task)
1396 {
1397     (void)p_task;
1398     (void)MBi_CallReset();
1399 }
1400 
1401 /* End communications */
MBi_CommEnd(void)1402 int MBi_CommEnd(void)
1403 {
1404     int     ret = WM_ERRCODE_FAILED;
1405     OSIntrMode enabled = OS_DisableInterrupts();
1406 
1407     /* If it hasn't been started yet, end immediately here */
1408     if (!p_mbi_param->mbIsStarted)
1409     {
1410         MBi_EndCommon(NULL);
1411     }
1412     else if (p_mbi_param->endReq == 0)
1413     {
1414         p_mbi_param->scanning_flag = FALSE;
1415         p_mbi_param->endReq = 1;
1416         /* If the task thread is running, reset after stopping this. */
1417         if (MBi_IsTaskAvailable())
1418         {
1419             MBi_EndTaskThread(MBi_OnReset);
1420             ret = WM_ERRCODE_SUCCESS;
1421         }
1422         /* If not, reset here. */
1423         else
1424         {
1425             ret = MBi_CallReset();
1426         }
1427     }
1428 
1429     (void)OS_RestoreInterrupts(enabled);
1430 
1431     return ret;
1432 }
1433 
MB_End(void)1434 void MB_End(void)
1435 {
1436     OSIntrMode enabled = OS_DisableInterrupts();
1437 
1438     if (mbc->is_started_ex)
1439     {
1440         OS_TPanic("MB_End called after MB_StartParentFromIdle! (please call MB_EndToIdle)");
1441     }
1442 
1443     (void)MBi_CommEnd();
1444 
1445     (void)OS_RestoreInterrupts(enabled);
1446 }
1447 
MB_EndToIdle(void)1448 void MB_EndToIdle(void)
1449 {
1450     OSIntrMode enabled = OS_DisableInterrupts();
1451 
1452     if (!mbc->is_started_ex)
1453     {
1454         OS_TPanic("MB_EndToIdle called after MB_StartParent! (please call MB_End)");
1455     }
1456 
1457     (void)MBi_CommEnd();
1458 
1459     (void)OS_RestoreInterrupts(enabled);
1460 }
1461 
1462 //-------------------------------------
1463 // Disconnect child
1464 //-------------------------------------
MB_DisconnectChild(u16 aid)1465 void MB_DisconnectChild(u16 aid)
1466 {
1467     SDK_NULL_ASSERT(pPwork);
1468     SDK_ASSERT(p_mbi_param->endReq != 1);
1469 
1470     if (WM_Disconnect(MBi_ParentCallback, aid) != WM_ERRCODE_OPERATING)
1471     {
1472         OS_TWarning("MB_DisconnectChild failed disconnect child %d\n", aid);
1473     }
1474 
1475     if (aid == 0 || aid >= 16)
1476     {
1477         OS_TWarning("Disconnected Illegal AID No. ---> %2d\n", aid);
1478         return;
1479     }
1480 
1481     /* Delete child information.
1482        (If disconnected, delete child information relating to that AID) */
1483     pPwork->childversion[aid - 1] = 0;
1484     MI_CpuClear8(&pPwork->childggid[aid - 1], sizeof(u32));
1485     MI_CpuClear8(&pPwork->childUser[aid - 1], sizeof(MBUserInfo));
1486 
1487     /* Clear the receive buffer. */
1488     MBi_ClearParentPieceBuffer(aid);
1489 
1490     pPwork->req2child[aid - 1] = MB_COMM_USER_REQ_NONE;
1491 
1492     /* When the requested FileID has been set. Clear the ID to -1. */
1493     if (pPwork->fileid_of_child[aid - 1] != -1)
1494     {
1495         u8      fileID = (u8)pPwork->fileid_of_child[aid - 1];
1496         u16     nowChildFlag = pPwork->fileinfo[fileID].gameinfo_child_bmp;
1497         u16     child = aid;
1498 
1499         pPwork->fileinfo[fileID].gameinfo_child_bmp &= ~(MB_GAMEINFO_CHILD_FLAG(child));
1500         pPwork->fileinfo[fileID].gameinfo_changed_bmp |= MB_GAMEINFO_CHILD_FLAG(child);
1501         pPwork->fileid_of_child[child - 1] = -1;
1502         pPwork->fileinfo[fileID].pollbmp &= ~(0x0001 << child);
1503 
1504         MB_DEBUG_OUTPUT("Update Member (AID:%2d)\n", child);
1505     }
1506 
1507     /* Clear the connection information. */
1508     if (pPwork->child_entry_bmp & (0x0001 << aid))
1509     {
1510         pPwork->child_num--;
1511         pPwork->child_entry_bmp &= ~(0x0001 << aid);
1512     }
1513     pPwork->p_comm_state[aid - 1] = MB_COMM_PSTATE_NONE;
1514 }
1515 
1516 
1517 /* Used only in mb_child.c ***********************************************/
1518 
MBi_GetLastFountParent(void)1519 int MBi_GetLastFountParent(void)
1520 {
1521     return p_mbi_param->last_found_parent_no;
1522 }
1523 
MBi_GetParentBssDesc(int id)1524 WMBssDesc *MBi_GetParentBssDesc(int id)
1525 {
1526     return p_mbi_param->parent_info[id].parentInfo;
1527 }
1528 
MBi_ScanLock(u8 * macAddr)1529 static void MBi_ScanLock(u8 *macAddr)
1530 {
1531     mbiScanParam.maxChannelTime = MB_SCAN_TIME_LOCKING;
1532     p_mbi_param->scan_channel_flag = FALSE;
1533     WM_CopyBssid(macAddr, mbiScanParam.bssid);
1534 }
1535 
MBi_ScanUnlock(void)1536 static void MBi_ScanUnlock(void)
1537 {
1538     static const u8 bss_fill[6] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
1539 
1540     mbiScanParam.maxChannelTime = MB_SCAN_TIME_NORMAL;
1541     p_mbi_param->scan_channel_flag = TRUE;
1542     WM_CopyBssid(bss_fill, mbiScanParam.bssid);
1543 }
1544 
1545 /* Used only in mb_comm *************************************************/
1546 
1547 // Settings at scan time
MBi_SetMaxScanTime(u16 time)1548 void MBi_SetMaxScanTime(u16 time)
1549 {
1550     mbiScanParam.maxChannelTime = time;
1551 }
1552 
1553 static int
MBi_SetMPData(WMCallbackFunc callback,const u16 * sendData,u16 sendDataSize,u16 tmptt,u16 pollbmp)1554 MBi_SetMPData(WMCallbackFunc callback, const u16 *sendData, u16 sendDataSize, u16 tmptt,
1555               u16 pollbmp)
1556 {
1557 #pragma unused( tmptt )
1558     int     errcode;
1559     errcode =
1560         WM_SetMPDataToPort(callback, sendData, sendDataSize, pollbmp, WM_PORT_BT, WM_PRIORITY_LOW);
1561     MBi_CheckWmErrcode(WM_APIID_SET_MP_DATA, errcode);
1562     return errcode;
1563 }
1564 
1565 
MBi_SendMP(const void * buf,int len,int pollbmp)1566 int MBi_SendMP(const void *buf, int len, int pollbmp)
1567 {
1568     int     errcode;
1569 
1570     u16     size = (u16)len;
1571     u16     pollbitmap = (u16)pollbmp;
1572 
1573     // MP data cannot be sent before MP is started as well as after a request to end MP has been issued.
1574     if ((p_mbi_param->mpStarted == 0) || (p_mbi_param->endReq == 1))
1575     {
1576         return WM_ERRCODE_FAILED;
1577     }
1578 
1579     switch (p_mbi_param->mode)
1580     {
1581     case MB_MODE_PARENT:
1582         errcode = MBi_SetMPData(p_mbi_param->callback_ptr, (u16 *)buf, size,    // * If MBi_ParentCallback is used, ParentCallback will be linked in mb_child as well, so callback_ptr should be used instead.
1583                                 (u16)((!p_mbi_param->contSend) ? 1000 : 0), pollbitmap);
1584 
1585         if (errcode == WM_ERRCODE_OPERATING)
1586         {
1587             p_mbi_param->mpBusy = 1;
1588         }
1589 
1590         return conv_errcode(errcode);
1591 
1592     case MB_MODE_CHILD:
1593         errcode = MBi_SetMPData(MBi_ChildCallback, (u16 *)buf, size, 0, pollbitmap);
1594 
1595         if (errcode == WM_ERRCODE_OPERATING)
1596         {
1597             p_mbi_param->mpBusy = 1;
1598         }
1599 
1600         return conv_errcode(errcode);
1601 
1602     default:
1603         return WM_ERRCODE_FAILED;
1604     }
1605 }
1606 
MBi_GetSendBufSize(void)1607 int MBi_GetSendBufSize(void)
1608 {
1609     return (int)p_mbi_param->sendBufSize;
1610 }
1611 
MBi_GetRecvBufSize(void)1612 int MBi_GetRecvBufSize(void)
1613 {
1614     return (int)p_mbi_param->recvBufSize;
1615 }
1616 
MBi_CommConnectToParent(const WMBssDesc * bssDescp)1617 int MBi_CommConnectToParent(const WMBssDesc *bssDescp)
1618 {
1619     WMgameInfo *gameInfo;
1620     int     errcode;
1621     SDK_ASSERT(bssDescp != 0);
1622 
1623     gameInfo = (WMgameInfo *)(&(bssDescp->gameInfo));
1624     p_mbi_param->p_sendlen = gameInfo->parentMaxSize;
1625     p_mbi_param->p_recvlen = gameInfo->childMaxSize;
1626     /* Calculate parameters that depend on the send/receive size. */
1627     mbc->block_size_max = MB_COMM_CALC_BLOCK_SIZE(p_mbi_param->p_sendlen);
1628 
1629     MBi_SetChildMPMaxSize(p_mbi_param->p_recvlen);
1630 
1631     OS_TPrintf("\trecv size : %d\n", p_mbi_param->p_sendlen);
1632     OS_TPrintf("\tsend size : %d\n", p_mbi_param->p_recvlen);
1633     OS_TPrintf("\tblock size: %d\n", mbc->block_size_max);
1634 
1635     p_mbi_param->recvBufSize = (u16)WM_CalcChildRecvBufSize(bssDescp);
1636     p_mbi_param->sendBufSize = (u16)WM_CalcChildSendBufSize(bssDescp);
1637     p_mbi_param->pInfo = bssDescp;
1638     p_mbi_param->currentTgid = ((WMGameInfo *)&(bssDescp->gameInfo))->tgid;
1639     p_mbi_param->scanning_flag = FALSE;
1640 
1641     errcode = WM_EndScan(p_mbi_param->callback_ptr);
1642     MBi_CheckWmErrcode(WM_APIID_END_SCAN, errcode);
1643     return conv_errcode(errcode);
1644 }
1645 
MBi_GetGgid(void)1646 u32 MBi_GetGgid(void)
1647 {
1648     return p_mbi_param->parentParam.ggid;
1649 }
1650 
MBi_GetTgid(void)1651 u16 MBi_GetTgid(void)
1652 {
1653     return (p_mbi_param->parentParam.tgid);
1654 }
1655 
MBi_GetAttribute(void)1656 u8 MBi_GetAttribute(void)
1657 {
1658     return ((u8)(((p_mbi_param->parentParam.entryFlag) ? WM_ATTR_FLAG_ENTRY : 0) |      // entryFlag lowest bit
1659                  ((p_mbi_param->parentParam.multiBootFlag) ? WM_ATTR_FLAG_MB : 0) |     // multiBootFlag second bit
1660                  ((p_mbi_param->parentParam.KS_Flag) ? WM_ATTR_FLAG_KS : 0) |   // KS_Flag third bit
1661                  ((p_mbi_param->parentParam.CS_Flag) ? WM_ATTR_FLAG_CS : 0)     // CS_Flag fourth bit
1662             ));
1663 }
1664 
1665 
1666 // Restart scanning
MBi_RestartScan(void)1667 int MBi_RestartScan(void)
1668 {
1669     int     errcode;
1670 
1671     p_mbi_param->scanning_flag = TRUE;
1672 
1673     if (p_mbi_param->scan_channel_flag)
1674     {
1675         if (FALSE == changeScanChannel(&mbiScanParam))
1676         {
1677             (void)MBi_CommEnd();
1678         }
1679     }
1680 
1681     errcode = WM_StartScanEx(MBi_ChildCallback, &mbiScanParam);
1682     MBi_CheckWmErrcode(WM_APIID_START_SCAN_EX, errcode);
1683     return conv_errcode(errcode);
1684 }
1685 
MB_SetRejectGgid(u32 ggid,u32 mask,BOOL enable)1686 void MB_SetRejectGgid(u32 ggid, u32 mask, BOOL enable)
1687 {
1688     isEnableReject    = enable;
1689     rejectGgidMask    = mask;
1690     rejectGgid        = ggid;
1691 }
1692 
1693 // Get scan channel
MBi_GetScanChannel(void)1694 int MBi_GetScanChannel(void)
1695 {
1696     return mbiScanParam.channelList;
1697 }
1698 
1699 // Get one's own AID.
MBi_GetAid(void)1700 u16 MBi_GetAid(void)
1701 {
1702     return p_mbi_param->my_aid;
1703 }
1704 
MBi_IsStarted(void)1705 BOOL MBi_IsStarted(void)
1706 {
1707     return (p_mbi_param->mbIsStarted == 1) ? TRUE : FALSE;
1708 }
1709 
1710 // Check WM_API's returned value
MBi_CheckWmErrcode(u16 apiid,int errcode)1711 static void MBi_CheckWmErrcode(u16 apiid, int errcode)
1712 {
1713     u16     arg[2];
1714 
1715     if (errcode != WM_ERRCODE_OPERATING && errcode != WM_ERRCODE_SUCCESS)
1716     {
1717         arg[0] = apiid;
1718         arg[1] = (u16)errcode;
1719         p_mbi_param->callback(MB_CALLBACK_API_ERROR, arg);
1720     }
1721 }
1722