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