1 /*---------------------------------------------------------------------------*
2 Project: TwlSDK - MB - libraries
3 File: mb_child.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 #include "mb_private.h"
19
20
21 // ----------------------------------------------------------------------------
22 // Definitions
23
24 #define MY_ROUND(n, a) (((u32) (n) + (a) - 1) & ~((a) - 1))
25
26 // --- For child
27 static int MBi_CommRequestFile(u8 file_no, u32 ggid);
28 static void MBi_CommChangeChildState(int state, void *arg);
29 static void MBi_CommChangeChildStateCallbackOnly(int state, void *arg);
30 static void MBi_CommChildRecvData(void *arg);
31 static int MBi_CommChildSendData(void);
32 static void MBi_CommBeaconRecvCallback(MbBeaconMsg msg, MBGameInfoRecvList * gInfop, int index);
33
34 // --- Miscellany
35 static BOOL checkRecvFlag(int x);
36 static void setRecvFlag(int x);
37 static u16 countRemainingblocks(void);
38 static u16 get_next_blockno(void);
39 static BOOL checkPollbmp(u16 pollbmp, u16 child_aid);
40 static void clearRecvRegion(void);
41 static void MBi_CommCallChildError(u16 errcode);
42
43
44 /* StartScanEx scan buffer */
45 static u8 scanBuf[WM_SIZE_SCAN_EX_BUF] ATTRIBUTE_ALIGN(32);
46 extern WMscanExParam mbiScanParam;
47
48
49
50 /* ============================================================================
51
52 Child Functions
53
54 ============================================================================*/
55
56 /*---------------------------------------------------------------------------*
57 Name: MB_CommDownloadRequest
58
59 Description: Sends a download request (a function that triggers the continuous operation: connect to the parent -> request file -> download).
60 Packs the lower MB_CommDownloadRequest, and makes a connection request with the index number of the mbrs list.
61 By remembering the index number, the parent device information can be cleared internally when the connection fails.
62
63
64
65
66 Arguments: index: The MbBeaconRecvStatus list index number that is requested
67
68 Returns:
69 *---------------------------------------------------------------------------*/
70
MB_CommDownloadRequest(int index)71 int MB_CommDownloadRequest(int index)
72 {
73 const MbBeaconRecvStatus *mbrsp; // Parent information receive status
74 const WMBssDesc *bssDescp; // Pointer to the parent information of the connection destination
75 u8 fileNo; // File number to request of the connection destination
76 int ret;
77 OSIntrMode enabled = OS_DisableInterrupts(); /* Interrupts disabled */
78
79 mbrsp = MB_GetBeaconRecvStatus(); // Parent information receive status
80 bssDescp = &(mbrsp->list[index].bssDesc);
81 fileNo = mbrsp->list[index].gameInfo.fileNo;
82
83 pCwork->connectTargetNo = index; // Saves the list number of the parent to which to attempt a connection
84 pCwork->fileid = fileNo; // Register the requested file ID in advance
85 pCwork->last_recv_seq_no = -1; //Initialize the last received block sequence number
86
87 // Copy bssDescription into working memory
88 MI_CpuCopy16(bssDescp, &pCwork->bssDescbuf, WM_BSS_DESC_SIZE);
89
90 ret = MBi_CommConnectToParent((const WMBssDesc *)&pCwork->bssDescbuf); // First, establish a connection
91 (void)OS_RestoreInterrupts(enabled); /* Cancel interrupt disabling */
92
93 return ret;
94 }
95
96 /*---------------------------------------------------------------------------*
97 Name: MBi_CommRequestFile
98
99 Description: Specifies a file number and issues a request.
100
101 Arguments: file_no
102
103 Returns:
104 *---------------------------------------------------------------------------*/
105
MBi_CommRequestFile(u8 file_no,u32 ggid)106 static int MBi_CommRequestFile(u8 file_no, u32 ggid)
107 {
108 int errcode;
109 MBCommChildBlockHeader hd;
110 u8 *databuf;
111 MBCommRequestData req_data;
112
113 /* Register the requested game's GGID, UserInfo and Version */
114 req_data.ggid = ggid;
115 MI_CpuCopy8(&pCwork->common.user, &req_data.userinfo, sizeof(MBUserInfo));
116 req_data.version = MB_IPL_VERSION;
117 req_data.fileid = file_no;
118
119 hd.type = MB_COMM_TYPE_CHILD_FILEREQ;
120 // Copy data to the send buffer
121 hd.req_data.piece = MBi_SendRequestDataPiece(hd.req_data.data, &req_data);
122
123 databuf = MBi_MakeChildSendBuffer(&hd, (u8 *)pCwork->common.sendbuf);
124
125 if (!databuf)
126 {
127 return MB_SENDFUNC_STATE_ERR;
128 }
129 errcode = MBi_BlockHeaderEnd(MB_COMM_CHILD_HEADER_SIZE, 0xFFFF, pCwork->common.sendbuf);
130 return errcode;
131 }
132
133 /*---------------------------------------------------------------------------*
134 Name: MB_CommSetChildStateCallback
135
136 Description: Child event callback settings.
137
138 Arguments:
139
140 Returns:
141 *---------------------------------------------------------------------------*/
142
MB_CommSetChildStateCallback(MBCommCStateCallbackFunc callback)143 void MB_CommSetChildStateCallback(MBCommCStateCallbackFunc callback)
144 {
145 OSIntrMode enabled;
146
147 SDK_ASSERT(pCwork != 0);
148
149 enabled = OS_DisableInterrupts(); /* Interrupts disabled */
150
151 pCwork->child_callback = callback;
152
153 (void)OS_RestoreInterrupts(enabled); /* Cancel interrupt disabling */
154 }
155
156 /*---------------------------------------------------------------------------*
157 Name: MB_CommGetChildState
158
159 Description: Gets the download state.
160
161 Arguments:
162
163 Returns:
164 *---------------------------------------------------------------------------*/
165
MB_CommGetChildState(void)166 int MB_CommGetChildState(void)
167 {
168 if (pCwork)
169 {
170 return pCwork->c_comm_state;
171 }
172 return 0;
173 }
174
175 /*---------------------------------------------------------------------------*
176 Name: MB_GetChildProgressPercentage
177
178 Description: Gets the download progress percentage.
179
180 Arguments:
181
182 Returns:
183 *---------------------------------------------------------------------------*/
184
MB_GetChildProgressPercentage(void)185 u16 MB_GetChildProgressPercentage(void)
186 {
187 OSIntrMode enabled;
188 u16 ret = 0;
189
190 enabled = OS_DisableInterrupts(); /* Interrupts disabled */
191
192 if (pCwork->total_block > 0)
193 {
194 ret = (u16)((u32)(pCwork->got_block * 100) / pCwork->total_block);
195 }
196
197 (void)OS_RestoreInterrupts(enabled); /* Cancel interrupt disabling */
198
199 return ret; // Return 0% if the TotalBlock count is zero
200 }
201
202
203 /*---------------------------------------------------------------------------*
204 Name: MB_CommStartDownload
205
206 Description: Starts a download.
207
208 Arguments:
209
210 Returns:
211 *---------------------------------------------------------------------------*/
212
MB_CommStartDownload(void)213 BOOL MB_CommStartDownload(void)
214 {
215 OSIntrMode enabled;
216 BOOL ret = FALSE;
217
218 enabled = OS_DisableInterrupts(); /* Interrupts disabled */
219
220 if (pCwork
221 && pCwork->c_comm_state == MB_COMM_CSTATE_DLINFO_ACCEPTED
222 && pCwork->user_req == MB_COMM_USER_REQ_NONE)
223 {
224
225 pCwork->user_req = MB_COMM_USER_REQ_DL_START;
226
227 ret = TRUE;
228 }
229
230 (void)OS_RestoreInterrupts(enabled); /* Cancel interrupt disabling */
231 return ret;
232 }
233
234
235 /*---------------------------------------------------------------------------*
236 Name: MBi_CommChangeChildState
237
238 Description: Changes the child state and invokes a callback.
239
240 Arguments:
241
242 Returns:
243 *---------------------------------------------------------------------------*/
244
MBi_CommChangeChildState(int state,void * arg)245 static void MBi_CommChangeChildState(int state, void *arg)
246 {
247 pCwork->c_comm_state = state;
248
249 MBi_CommChangeChildStateCallbackOnly(state, arg);
250
251 }
252
253 /*---------------------------------------------------------------------------*
254 Name: MBi_CommChangeChildStateCallbackOnly
255
256 Description: Perform child state notification with only a callback invocation.
257 The internal state is not changed.
258
259 Arguments:
260
261 Returns:
262 *---------------------------------------------------------------------------*/
263
MBi_CommChangeChildStateCallbackOnly(int state,void * arg)264 static void MBi_CommChangeChildStateCallbackOnly(int state, void *arg)
265 {
266 if (pCwork->child_callback) // State-change callback
267 {
268 (*pCwork->child_callback) ((u32)state, arg);
269 }
270
271 }
272
273 /*---------------------------------------------------------------------------*
274 Name: MBi_CommChildCallback
275
276 Description: Main body of the child callback.
277
278 Arguments: type:WM_TYPE event arg:callback argument
279
280 Returns: None.
281 *---------------------------------------------------------------------------*/
MBi_CommChildCallback(u16 type,void * arg)282 void MBi_CommChildCallback(u16 type, void *arg)
283 {
284 MB_COMM_WMEVENT_OUTPUT(type, arg);
285
286 switch (type)
287 {
288 case MB_CALLBACK_INIT_COMPLETE:
289 /* Initialization complete */
290 MBi_CommChangeChildState(MB_COMM_CSTATE_INIT_COMPLETE, arg);
291
292 // Specify the scan buffer when the child has finished initialization to reduce (dead strip) parent memory
293 mbiScanParam.scanBuf = (WMBssDesc*)scanBuf;
294 mbiScanParam.scanBufSize = WM_SIZE_SCAN_EX_BUF;
295 break;
296
297 case MB_CALLBACK_PARENT_FOUND:
298 {
299 u16 *linkLevel = (u16 *)arg;
300 int parent_no = MBi_GetLastFountParent();
301 WMBssDesc *bssDescp = MBi_GetParentBssDesc(parent_no);
302
303 /* Discover parent devices */
304 /* Get parent game information via a beacon */
305 (void)MB_RecvGameInfoBeacon(MBi_CommBeaconRecvCallback, *linkLevel, bssDescp);
306
307 MB_CountGameInfoLifetime(MBi_CommBeaconRecvCallback, TRUE);
308 }
309 break;
310 case MB_CALLBACK_PARENT_NOT_FOUND:
311 /* Lifetime count of parent game information */
312 MB_CountGameInfoLifetime(MBi_CommBeaconRecvCallback, FALSE);
313 break;
314
315 case MB_CALLBACK_CONNECTED_TO_PARENT:
316 MBi_CommChangeChildState(MB_COMM_CSTATE_CONNECT, arg);
317 break;
318
319 case MB_CALLBACK_MP_CHILD_RECV:
320 MBi_CommChildRecvData(arg);
321 break;
322
323 case MB_CALLBACK_MP_SEND_ENABLE:
324 (void)MBi_CommChildSendData();
325 break;
326
327 case MB_CALLBACK_END_COMPLETE:
328 /* End complete */
329
330 /* If MBi_CommEnd() was called while in a state where a BOOT request was received */
331 if (pCwork->c_comm_state == MB_COMM_CSTATE_BOOTREQ_ACCEPTED && pCwork->boot_end_flag == 1)
332 {
333 // Set DownloadFileInfo and bssDesc in a fixed region -> use with loader
334 MI_CpuCopy16(&pCwork->dl_fileinfo,
335 (void *)MB_DOWNLOAD_FILEINFO_ADDRESS, sizeof(MBDownloadFileInfo));
336 MI_CpuCopy16(&pCwork->bssDescbuf, (void *)MB_BSSDESC_ADDRESS, MB_BSSDESC_SIZE);
337 MBi_CommChangeChildState(MB_COMM_CSTATE_BOOT_READY, NULL); // Boot preparation completed
338 }
339 /* In other cases (cancel) */
340 else
341 {
342 MBi_CommChangeChildState(MB_COMM_CSTATE_CANCELLED, NULL); // Cancel
343
344 /* Zero out PlayerNo */
345 pCwork->common.user.playerNo = 0;
346 clearRecvRegion();
347
348 pCwork->c_comm_state = MB_COMM_CSTATE_NONE;
349 }
350
351 break;
352
353 case MB_CALLBACK_CONNECT_FAILED:
354 /* Connection failure */
355 /* Pass an arg of type WMstartConnectCallback in the callback arguments */
356 MBi_CommChangeChildState(MB_COMM_CSTATE_CONNECT_FAILED, arg);
357 MB_DeleteRecvGameInfo(pCwork->connectTargetNo); // Delete the game information of a parent that failed to connect
358 pCwork->connectTargetNo = 0;
359 (void)MBi_RestartScan(); // Resume scanning after callback notification
360 (void)MBi_CommEnd();
361
362 break;
363
364 case MB_CALLBACK_DISCONNECTED_FROM_PARENT:
365 /* Disconnect notification */
366 /* Pass an arg of type WMstartConnectCallback in the callback arguments */
367 MBi_CommChangeChildState(MB_COMM_CSTATE_DISCONNECTED_BY_PARENT, arg);
368 (void)MBi_RestartScan(); // Resume scanning after callback notification
369 (void)MBi_CommEnd();
370 break;
371
372 case MB_CALLBACK_API_ERROR:
373 /* Error values returned when WM API was called in ARM9 */
374 {
375 u16 apiid, errcode;
376
377 apiid = ((u16 *)arg)[0];
378 errcode = ((u16 *)arg)[1];
379
380 switch (errcode)
381 {
382 case WM_ERRCODE_INVALID_PARAM:
383 case WM_ERRCODE_FAILED:
384 case WM_ERRCODE_WM_DISABLE:
385 case WM_ERRCODE_NO_DATASET:
386 case WM_ERRCODE_FIFO_ERROR:
387 case WM_ERRCODE_TIMEOUT:
388 MBi_CommCallChildError(MB_ERRCODE_FATAL);
389 break;
390 case WM_ERRCODE_OPERATING:
391 case WM_ERRCODE_ILLEGAL_STATE:
392 case WM_ERRCODE_NO_CHILD:
393 case WM_ERRCODE_OVER_MAX_ENTRY:
394 case WM_ERRCODE_NO_ENTRY:
395 case WM_ERRCODE_INVALID_POLLBITMAP:
396 case WM_ERRCODE_NO_DATA:
397 case WM_ERRCODE_SEND_QUEUE_FULL:
398 case WM_ERRCODE_SEND_FAILED:
399 default:
400 MBi_CommCallChildError(MB_ERRCODE_WM_FAILURE);
401 break;
402 }
403 }
404 break;
405 case MB_CALLBACK_ERROR:
406 {
407 /* Errors in callbacks returned after a WM API call */
408 WMCallback *pWmcb = (WMCallback *)arg;
409 switch (pWmcb->apiid)
410 {
411 case WM_APIID_INITIALIZE:
412 case WM_APIID_SET_LIFETIME:
413 case WM_APIID_SET_P_PARAM:
414 case WM_APIID_SET_BEACON_IND:
415 case WM_APIID_START_PARENT:
416 case WM_APIID_START_MP:
417 case WM_APIID_SET_MP_DATA:
418 case WM_APIID_START_DCF:
419 case WM_APIID_SET_DCF_DATA:
420 case WM_APIID_DISCONNECT:
421 case WM_APIID_START_KS:
422 /* The above errors are important to WM initialization */
423 MBi_CommCallChildError(MB_ERRCODE_FATAL);
424 break;
425 case WM_APIID_RESET:
426 case WM_APIID_END:
427 default:
428 /* Other errors are returned as callback errors */
429 MBi_CommCallChildError(MB_ERRCODE_WM_FAILURE);
430 break;
431 }
432 }
433 break;
434
435 default:
436 break;
437 }
438
439 #if ( CALLBACK_WM_STATE == 1 )
440 if (pCwork->child_callback)
441 {
442 (*pCwork->child_callback) ((u32)(MB_COMM_CSTATE_WM_EVENT | type), arg);
443 }
444 #endif
445
446 if (type == MB_CALLBACK_END_COMPLETE)
447 {
448 // Release working memory
449 MI_CpuClear16(pCwork, sizeof(MB_CommCWork));
450 pCwork = NULL;
451 }
452 }
453
454
455 /*---------------------------------------------------------------------------*
456 Name: MBi_CommChildRecvData
457
458 Description: Receives child data.
459
460 Arguments: arg: Pointer to callback argument
461
462 Returns: None.
463 *---------------------------------------------------------------------------*/
464
MBi_CommChildRecvData(void * arg)465 static void MBi_CommChildRecvData(void *arg)
466 {
467 WMPortRecvCallback *bufp = (WMPortRecvCallback *)arg;
468 MB_CommCWork *const p_child = pCwork;
469 MBCommParentBlockHeader hd;
470 u8 *databuf;
471 u16 aid = MBi_GetAid();
472
473 // Destroy the receive buffer cache
474 // DC_InvalidateRange( bufp->data, MY_ROUND(bufp->length, 32) );
475
476 databuf = MBi_SetRecvBufferFromParent(&hd, (u8 *)bufp->data);
477
478 MB_DEBUG_OUTPUT("RECV ");
479 MB_COMM_TYPE_OUTPUT(hd.type);
480
481 switch (hd.type) // State transition depending on receive block type
482 {
483 case MB_COMM_TYPE_PARENT_SENDSTART:
484 // Send start message from parent
485 if (p_child->c_comm_state == MB_COMM_CSTATE_CONNECT)
486 {
487 MB_DEBUG_OUTPUT("Allowed to request file from parent!\n");
488 MBi_CommChangeChildState(MB_COMM_CSTATE_REQ_ENABLE, NULL);
489 }
490 break;
491
492 case MB_COMM_TYPE_PARENT_KICKREQ: // Kick message from parent
493 if (p_child->c_comm_state == MB_COMM_CSTATE_REQ_ENABLE)
494 {
495 MB_DEBUG_OUTPUT("Kicked from parent!\n");
496 MBi_CommChangeChildState(MB_COMM_CSTATE_REQ_REFUSED, NULL);
497 }
498 break;
499
500 case MB_COMM_TYPE_PARENT_MEMBER_FULL: // Message from parent regarding excessive number of members
501 if (p_child->c_comm_state == MB_COMM_CSTATE_REQ_ENABLE)
502 {
503 MB_DEBUG_OUTPUT("Member full!\n");
504 MBi_CommChangeChildState(MB_COMM_CSTATE_MEMBER_FULL, NULL);
505 }
506 break;
507
508 case MB_COMM_TYPE_PARENT_DL_FILEINFO:
509 // Receive MbDownloadFileInfoHeader
510 if (p_child->c_comm_state == MB_COMM_CSTATE_REQ_ENABLE)
511 {
512
513 // Stores MbDownloadFileInfoHeader in an exclusive buffer
514 MI_CpuCopy8(databuf, &p_child->dl_fileinfo, sizeof(MBDownloadFileInfo));
515
516 MB_DEBUG_OUTPUT("Download File Info has received (Total block num = %d)\n",
517 p_child->total_block);
518 if (!MBi_MakeBlockInfoTable(&p_child->blockinfo_table,
519 (MbDownloadFileInfoHeader *) & p_child->dl_fileinfo))
520 {
521 /* The received DownloadFileInfo was invalid */
522 MBi_CommCallChildError(MB_ERRCODE_INVALID_DLFILEINFO);
523 OS_TWarning("The received DownloadFileInfo is illegal.\n");
524 return;
525 }
526
527 /* Assign PlayerNo */
528 p_child->common.user.playerNo = aid;
529
530 // Store the total block count
531 p_child->total_block = MBi_get_blocknum(&p_child->blockinfo_table);
532
533 /* Pass the received MbDownloadFileInfo as an argument */
534 MBi_CommChangeChildState(MB_COMM_CSTATE_DLINFO_ACCEPTED, (void *)&p_child->dl_fileinfo);
535 }
536
537 break;
538
539 case MB_COMM_TYPE_PARENT_DATA:
540 /* Receive block data */
541 if (p_child->c_comm_state == MB_COMM_CSTATE_DLINFO_ACCEPTED
542 && p_child->user_req == MB_COMM_USER_REQ_DL_START)
543 {
544 MBi_CommChangeChildState(MB_COMM_CSTATE_RECV_PROCEED, NULL);
545 p_child->user_req = MB_COMM_USER_REQ_NONE;
546 /* Once the state is changed, received data can be immediately obtained */
547 }
548
549 if (p_child->c_comm_state == MB_COMM_CSTATE_RECV_PROCEED)
550 {
551 u16 block_num;
552 MB_BlockInfo bi;
553
554 // Processing only when MB_COMM_TYPE_DATA
555 block_num = p_child->total_block;
556
557 if (block_num == 0 || block_num >= MB_MAX_BLOCK)
558 {
559
560 MBi_CommCallChildError(MB_ERRCODE_INVALID_BLOCK_NUM);
561
562 OS_TWarning("Illegal Number of Block! [%d]\n", block_num);
563 return;
564 }
565
566 /* Evaluation relating to the block number */
567 if (hd.seqno < 0 ||
568 hd.seqno >= block_num ||
569 MBi_get_blockinfo(&bi, &p_child->blockinfo_table, hd.seqno,
570 &p_child->dl_fileinfo.header) == FALSE)
571 {
572 /* Block number is invalid */
573 MBi_CommCallChildError(MB_ERRCODE_INVALID_BLOCK_NO);
574 OS_TWarning("The illegal block No.[%d] has been received! (maxnum %d)\n",
575 hd.seqno, block_num);
576 goto CheckRemainBlock;
577 }
578
579 if (hd.fid != p_child->fileid)
580 {
581 /* FileID is different from the requested one */
582 MBi_CommCallChildError(MB_ERRCODE_INVALID_FILE);
583 OS_TWarning("Received File ID [%d] differs from what was requested!\n", hd.fid);
584 goto CheckRemainBlock;
585 }
586
587 if (!MBi_IsAbleToRecv(bi.segment_no, bi.child_address, bi.size))
588 {
589 /* Receive address is invalid */
590 MBi_CommCallChildError(MB_ERRCODE_INVALID_RECV_ADDR);
591 OS_TWarning("The receive address of Block No.%d is illegal. [%08x - %08x]\n",
592 hd.seqno, bi.child_address, bi.child_address + bi.size);
593 goto CheckRemainBlock;
594 }
595
596 /* Copy to the specified address after checking the receive address */
597 if (checkRecvFlag(hd.seqno) == FALSE)
598 {
599 MB_DEBUG_OUTPUT("DATA : BLOCK(%d)/REMAIN(%d), Recv address[%x] size[%x]\n",
600 hd.seqno, countRemainingblocks(), bi.child_address, bi.size);
601 MI_CpuCopy8(databuf, (void *)bi.child_address, bi.size);
602 p_child->got_block++;
603 setRecvFlag(hd.seqno);
604 }
605
606 CheckRemainBlock:
607 /* Have all blocks been received? */
608 if (0 == countRemainingblocks())
609 {
610 MBi_CommChangeChildState(MB_COMM_CSTATE_RECV_COMPLETE, NULL); // Receive complete
611 }
612 }
613 break;
614
615 case MB_COMM_TYPE_PARENT_BOOTREQ:
616 if (p_child->c_comm_state == MB_COMM_CSTATE_RECV_COMPLETE)
617 {
618 MBi_CommChangeChildState(MB_COMM_CSTATE_BOOTREQ_ACCEPTED, NULL);
619 }
620 else if (p_child->c_comm_state == MB_COMM_CSTATE_BOOTREQ_ACCEPTED)
621 {
622 p_child->boot_end_flag = 1;
623 (void)MBi_CommEnd(); // End communication
624 }
625 break;
626 default:
627 break;
628 }
629 return;
630 }
631
632 /*---------------------------------------------------------------------------*
633 Name: MBi_CommChildSendData
634
635 Description: Sends child data.
636
637 Arguments: None.
638
639 Returns: None.
640 *---------------------------------------------------------------------------*/
641
MBi_CommChildSendData(void)642 static int MBi_CommChildSendData(void)
643 {
644 u16 block_num = pCwork->total_block;
645 MBCommChildBlockHeader hd;
646 int errcode = 0;
647 u16 pollbmp = 0xffff;
648
649 switch (pCwork->c_comm_state)
650 {
651 default:
652 // Send DUMMY MP to establish MP communication
653 hd.type = MB_COMM_TYPE_DUMMY;
654 (void)MBi_MakeChildSendBuffer(&hd, (u8 *)pCwork->common.sendbuf);
655 errcode = MBi_BlockHeaderEnd(MB_COMM_CHILD_HEADER_SIZE, pollbmp, pCwork->common.sendbuf);
656 break;
657
658 case MB_COMM_CSTATE_REQ_ENABLE:
659 {
660 const MbBeaconRecvStatus *mbrsp = MB_GetBeaconRecvStatus();
661 // Send a FileRequest
662 errcode = MBi_CommRequestFile(pCwork->fileid,
663 mbrsp->list[pCwork->connectTargetNo].gameInfo.ggid);
664 MB_DEBUG_OUTPUT("Requested File (errcode:%d)\n", errcode);
665 // MP is set with RequestFile
666 }
667 break;
668
669 case MB_COMM_CSTATE_DLINFO_ACCEPTED:
670 // DownloadInfo reception message
671 hd.type = MB_COMM_TYPE_CHILD_ACCEPT_FILEINFO;
672 (void)MBi_MakeChildSendBuffer(&hd, (u8 *)pCwork->common.sendbuf);
673 errcode = MBi_BlockHeaderEnd(MB_COMM_CHILD_HEADER_SIZE, pollbmp, pCwork->common.sendbuf);
674 break;
675
676 case MB_COMM_CSTATE_RECV_PROCEED:
677 // Block transfer continuation message
678 MI_CpuClear8(&hd, sizeof(MBCommChildBlockHeader));
679 hd.type = MB_COMM_TYPE_CHILD_CONTINUE;
680 hd.data.req = get_next_blockno();
681 hd.data.reserved[0] = (u8)(0x00ff & pCwork->got_block); // Lo
682 hd.data.reserved[1] = (u8)((0xff00 & pCwork->got_block) >> 8); // Hi
683 (void)MBi_MakeChildSendBuffer(&hd, (u8 *)pCwork->common.sendbuf);
684 errcode = MBi_BlockHeaderEnd(MB_COMM_CHILD_HEADER_SIZE, pollbmp, pCwork->common.sendbuf);
685 break;
686
687 case MB_COMM_CSTATE_RECV_COMPLETE:
688 // Block transfer stop message (send continues until BOOTREQ comes from parent)
689 hd.type = MB_COMM_TYPE_CHILD_STOPREQ;
690 (void)MBi_MakeChildSendBuffer(&hd, (u8 *)pCwork->common.sendbuf);
691 errcode = MBi_BlockHeaderEnd(MB_COMM_CHILD_HEADER_SIZE, pollbmp, pCwork->common.sendbuf);
692 break;
693
694 case MB_COMM_CSTATE_BOOTREQ_ACCEPTED:
695 hd.type = MB_COMM_TYPE_CHILD_BOOTREQ_ACCEPTED;
696 (void)MBi_MakeChildSendBuffer(&hd, (u8 *)pCwork->common.sendbuf);
697 errcode = MBi_BlockHeaderEnd(MB_COMM_CHILD_HEADER_SIZE, pollbmp, pCwork->common.sendbuf);
698 break;
699 }
700
701 return errcode;
702 }
703
704 /*---------------------------------------------------------------------------*
705 Name: MBi_CommBeaconRecvCallback
706
707 Description: Child beacon receive callback
708
709 Arguments: msg: Beacon receive message
710 gInfop: Parent game information
711 index: Beacon index
712
713 Returns: None.
714 *---------------------------------------------------------------------------*/
715
MBi_CommBeaconRecvCallback(MbBeaconMsg msg,MBGameInfoRecvList * gInfop,int index)716 static void MBi_CommBeaconRecvCallback(MbBeaconMsg msg, MBGameInfoRecvList * gInfop, int index)
717 {
718 #pragma unused(index)
719 void* arg = (gInfop == NULL)? NULL : (void *)&gInfop->gameInfo;
720
721 switch (msg)
722 {
723 case MB_BC_MSG_GINFO_VALIDATED:
724 MBi_CommChangeChildStateCallbackOnly(MB_COMM_CSTATE_GAMEINFO_VALIDATED,
725 arg);
726 MB_DEBUG_OUTPUT("Parent Info Enable\n");
727 break;
728 case MB_BC_MSG_GINFO_INVALIDATED:
729 MBi_CommChangeChildStateCallbackOnly(MB_COMM_CSTATE_GAMEINFO_INVALIDATED,
730 arg);
731 break;
732 case MB_BC_MSG_GINFO_LOST:
733 MBi_CommChangeChildStateCallbackOnly(MB_COMM_CSTATE_GAMEINFO_LOST,
734 arg);
735 break;
736 case MB_BC_MSG_GINFO_LIST_FULL:
737 MBi_CommChangeChildStateCallbackOnly(MB_COMM_CSTATE_GAMEINFO_LIST_FULL,
738 arg);
739 break;
740 }
741 }
742
743 /*---------------------------------------------------------------------------*
744 Name: MB_ReadMultiBootParentBssDesc
745
746 Description: Set up WMBssDesc structure information
747 with MB_GetMultiBootParentBssDesc() data,
748 in order to use by WM_StartConnect().
749
750 Arguments: p_desc: Pointer to destination WMBssDesc
751 parent_max_size: Max packet length of parent in MP-protocol
752 (must be equal to parent's WMParentParam!)
753 child_max_size: Max packet length of child in MP-protocol
754 (must be equal to parent's WMParentParam!)
755 ks_flag: If use key-sharing mode, TRUE
756 (must be equal to parent's WMParentParam!)
757 cs_flag: If use continuous mode, TRUE
758 (must be equal to parent's WMParentParam!)
759
760 Returns: None.
761 *---------------------------------------------------------------------------*/
MB_ReadMultiBootParentBssDesc(WMBssDesc * p_desc,u16 parent_max_size,u16 child_max_size,BOOL ks_flag,BOOL cs_flag)762 void MB_ReadMultiBootParentBssDesc(WMBssDesc *p_desc,
763 u16 parent_max_size, u16 child_max_size, BOOL ks_flag,
764 BOOL cs_flag)
765 {
766 const MBParentBssDesc *parentInfo = MB_GetMultiBootParentBssDesc();
767 SDK_NULL_ASSERT(parentInfo);
768 MI_CpuCopy8(parentInfo, p_desc, sizeof(MBParentBssDesc));
769
770 p_desc->gameInfoLength = 0x10;
771 p_desc->gameInfo.magicNumber = 0x0001;
772 p_desc->gameInfo.ver = 0;
773 p_desc->gameInfo.ggid =
774 (u32)(*(const u16 *)(&p_desc->ssid[0]) | (*(const u16 *)(&p_desc->ssid[2]) << 16));
775 p_desc->gameInfo.tgid = *(const u16 *)(&p_desc->ssid[4]);
776 p_desc->gameInfo.userGameInfoLength = 0;
777 p_desc->gameInfo.parentMaxSize = parent_max_size;
778 p_desc->gameInfo.childMaxSize = child_max_size;
779 MI_WriteByte(&p_desc->gameInfo.attribute,
780 (u8)((ks_flag ? WM_ATTR_FLAG_KS : 0) |
781 (cs_flag ? WM_ATTR_FLAG_CS : 0) | WM_ATTR_FLAG_ENTRY));
782 }
783
784
785 /* ============================================================================
786
787 Miscellaneous functions
788
789 ============================================================================*/
790
checkRecvFlag(int x)791 static BOOL checkRecvFlag(int x)
792 {
793 int pos = (x >> 3);
794 int bit = (x & 0x7);
795
796 SDK_ASSERT(x < MB_MAX_BLOCK);
797
798 if (pCwork->recvflag[pos] & (1 << bit))
799 {
800 return TRUE;
801 }
802 return FALSE;
803 }
804
setRecvFlag(int x)805 static void setRecvFlag(int x)
806 {
807 int pos = (x >> 3);
808 int bit = (x & 0x7);
809
810 SDK_ASSERT(x < MB_MAX_BLOCK);
811
812 pCwork->recvflag[pos] |= (1 << bit);
813
814 pCwork->last_recv_seq_no = x;
815 }
816
817
countRemainingblocks(void)818 static u16 countRemainingblocks(void)
819 {
820 return (u16)(pCwork->total_block - pCwork->got_block);
821 }
822
get_next_blockno(void)823 static u16 get_next_blockno(void)
824 {
825 int req;
826 int search_count = 0;
827 req = pCwork->last_recv_seq_no;
828 req++;
829
830 while (1)
831 {
832 if (req < 0 || req >= pCwork->total_block)
833 {
834 req = 0;
835 }
836 else if (checkRecvFlag(req))
837 {
838 req++;
839 }
840 else
841 {
842 return (u16)req;
843 }
844
845 if (pCwork->last_recv_seq_no == req)
846 {
847 return (u16)(pCwork->total_block);
848 }
849 search_count++;
850
851 if (search_count > 1000)
852 {
853 pCwork->last_recv_seq_no = req;
854 return (u16)req;
855 }
856 }
857 }
858
859 // Check whether the child AID bit that was specified in pollbmp is enabled or not
checkPollbmp(u16 pollbmp,u16 child_aid)860 static BOOL checkPollbmp(u16 pollbmp, u16 child_aid)
861 {
862 if (pollbmp & (u16)(1 << child_aid))
863 {
864 return TRUE;
865 }
866 return FALSE;
867 }
868
869 /* Clear the reception region */
clearRecvRegion(void)870 static void clearRecvRegion(void)
871 {
872 /* For anything other than FINALROM, the downloadable region is not cleared */
873 #ifdef SDK_FINALROM
874 /* Clear the ARM9 loadable region */
875 MI_CpuClearFast((void *)MB_LOAD_AREA_LO, MB_LOAD_MAX_SIZE);
876 /* Clear the ARM7 load buffer address region */
877 MI_CpuClearFast((void *)MB_ARM7_STATIC_RECV_BUFFER, MB_ARM7_STATIC_RECV_BUFFER_SIZE);
878 /* Clear the MBbssDesc and MBDownloadFileInfo regions */
879 MI_CpuClear16((void *)MB_BSSDESC_ADDRESS,
880 MB_DOWNLOAD_FILEINFO_ADDRESS + MB_DOWNLOAD_FILEINFO_SIZE - MB_BSSDESC_ADDRESS);
881 /* Clear the ROM Header region */
882 MI_CpuClear16((void *)HW_ROM_HEADER_BUF, ROM_HEADER_SIZE_FULL);
883 #endif
884
885 }
886
887
MBi_CommCallChildError(u16 errcode)888 static void MBi_CommCallChildError(u16 errcode)
889 {
890 MBErrorStatus e_stat;
891 e_stat.errcode = errcode;
892
893 MBi_CommChangeChildStateCallbackOnly(MB_COMM_CSTATE_ERROR, &e_stat);
894
895 }
896