1 /*---------------------------------------------------------------------------*
2   Project:  TwlSDK - MB - libraries
3   File:     mb_gameinfo.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:: 2008-11-27#$
14   $Rev: 9425 $
15   $Author: yosizaki $
16  *---------------------------------------------------------------------------*/
17 
18 #include <nitro.h>
19 #include "mb_gameinfo.h"
20 #include "mb_common.h"
21 #include "mb_private.h"                // for MB_SCAN_TIME_NORMAL & MB_SCAN_TIME_LOKING & MB_OUTPUT, MB_DEBUG_OUTPUT
22 
23 
24 /*
25 
26    ********** PRECAUTIONS **********
27    - During a scan lock, the scan time should be set to be greater than the parent's beacon interval. (200ms or greater)
28      However, if this is done the scan time will change dynamically, so what will be done about values that have already been counted, and the maximum value of LifetimeCount and LockTimeCount?
29 
30 
31 */
32 
33 
34 /*
35  * The wmDEMOlib functions that are being used:
36  *  - none
37  *
38  * The WM API that is being used:
39  *  - WM_SetGameInfo (MBi_SendFixedBeacon, MBi_SendVolatBeacon)
40  *
41  *
42  *
43  *
44  */
45 
46 // define data---------------------------------------------
47 
48 #define MB_GAME_INFO_LIFETIME_SEC       60      // Lifetime of the received game information (deleted if a beacon is not received in this time period (seconds))
49 #define MB_SCAN_LOCK_SEC                8       // Maximum time for locking a specific parent and scanning
50 #define MB_SAME_BEACON_RECV_MAX_COUNT   3       // The maximum number of times that a parent's beacon can be continuously received when the parent repeatedly sends out the same beacon.
51 
52 #define MB_BEACON_DATA_SIZE         (WM_SIZE_USER_GAMEINFO - 8)
53 #define MB_BEACON_FIXED_DATA_SIZE   (MB_BEACON_DATA_SIZE   - 6) // The data size of the fixed region for the parent device's game information in the beacon.
54 #define MB_BEACON_VOLAT_DATA_SIZE   (MB_BEACON_DATA_SIZE   - 8) // The data size of the volatile region for the parent device's game information in the beacon.
55 #define MB_SEND_MEMBER_MAX_NUM      (MB_BEACON_VOLAT_DATA_SIZE / sizeof(MBUserInfo))    // The maximum amount of member information that can be send at one time in the beacon.
56 
57 #define FIXED_NORMAL_SIZE            sizeof(MBGameInfoFixed)    // The normal size of the game information's fixed region.
58 #define FIXED_NO_ICON_SIZE          (sizeof(MBGameInfoFixed) - sizeof(MBIconInfo))      // The size of the game information's fixed region without icons.
59 #define FIXED_FLAGMENT_MAX(size)    ( ( size / MB_BEACON_FIXED_DATA_SIZE) + ( size % MB_BEACON_FIXED_DATA_SIZE ? 1 : 0 ) )
60                                                                                     // The number of beacon fragments of the game information's fixed region.
61 
62 #define MB_LIFETIME_MAX_COUNT       ( MB_GAME_INFO_LIFETIME_SEC * 1000 / MB_SCAN_TIME_NORMAL + 1 )
63 #define MB_LOCKTIME_MAX_COUNT       ( MB_SCAN_LOCK_SEC          * 1000 / MB_SCAN_TIME_NORMAL + 1 )
64                                                                                     // This is the parent's game information lifetime converted into ScanTime units.
65                                                                                     // This is the scan lock time converted into ScanTime units.
66 #define MB_SCAN_COUNT_UNIT_NORMAL   ( 1 )
67 #define MB_SCAN_COUNT_UNIT_LOCKING  ( MB_SCAN_TIME_LOCKING / MB_SCAN_TIME_NORMAL )
68 
69 
70 
71 typedef enum MbBeaconState
72 {
73     MB_BEACON_STATE_STOP = 0,
74     MB_BEACON_STATE_READY,
75     MB_BEACON_STATE_FIXED_START,
76     MB_BEACON_STATE_FIXED,
77     MB_BEACON_STATE_VOLAT_START,
78     MB_BEACON_STATE_VOLAT,
79     MB_BEACON_STATE_NEXT_GAME
80 }
81 MbBeaconState;
82 
83 
84 /* Beacon Format Structure */
85 typedef struct MbBeacon
86 {
87     u32     ggid;                      // GGID
88     u8      dataAttr:2;                // Data attributes (designated by MbBeaconDataAttr)
89     u8      fileNo:6;                  // File Number
90     u8      seqNoFixed;                // Fixed data sequence number (will be added if there was an update to the data contents)
91     u8      seqNoVolat;                // Volat data sequence number (will be added if there was an update to the data contents)
92     u8      beaconNo;                  // Beacon number (increments for each beacon transmission)
93     /* Original MbBeaconData */
94     union
95     {
96         struct
97         {                              // When sending MbGameInfoFixed
98             u16     sum;               // 16-bit checksum
99             u8      flagmentNo;        // The current number of the fragmented data.
100             u8      flagmentMaxNum;    // The maximum number of the fragmented data.
101             u8      size;              // Data size.
102             u8      rsv;
103             u8      data[MB_BEACON_FIXED_DATA_SIZE];    // The data itself.
104         }
105         fixed;
106         struct
107         {                              // When sending MbGameInfoVolatile
108             u16     sum;               // 16-bit checksum
109             u8      nowPlayerNum;      // Current number of players
110             u8      pad[1];
111             u16     nowPlayerFlag;     // Shows in bits the player numbers of all the current players.
112             u16     changePlayerFlag;  // Shows in bits the numbers of the player information that changed at this update. (Used for judgment only at the instant when the sequence number has changed.)
113             MBUserInfo member[MB_SEND_MEMBER_MAX_NUM];  // Send the user information of each child device in increments of MB_SEND_MEMBER_MAX_NUM (end if the PlayerNo == 15 (parent device))
114             u8      userVolatData[MB_USER_VOLAT_DATA_SIZE];     // The data that can be set by the user
115         }
116         volat;
117     }
118     data;
119 
120 }
121 MbBeacon;
122 
123 /* The parent-side structure for the beacon-transmission status */
124 typedef struct MbBeaconSendStatus
125 {
126     MBGameInfo *gameInfoListTop;       // Pointer to the top of the game information list (a one-way list)
127     MBGameInfo *nowGameInfop;          // Pointer to the game information that is currently being sent.
128     u8     *srcp;                      // Pointer to the source of the game information that is currently being sent.
129     u8      state;                     // The beacon transmission state. (Transmission of fixed data part, dynamic status part. The state changes when each kind of data is completely sent.)
130     u8      seqNoFixed;                // Fixed region's sequence number
131     u8      seqNoVolat;                // Volatile region's sequence number
132     u8      flagmentNo;                //   �@ Fragment number of a region (if a fixed region)
133     u8      flagmentMaxNum;            //   �@ Fragment count of a region (if a fixed region)
134     u8      beaconNo;
135     u8      pad[2];
136 }
137 MbBeaconSendStatus;
138 
139 
140 
141 // function's prototype------------------------------------
142 static BOOL MBi_ReadIconInfo(const char *filePathp, MBIconInfo *iconp, BOOL char_flag);
143 static void MBi_ClearSendStatus(void);
144 static BOOL MBi_ReadyBeaconSendStatus(void);
145 static void MBi_InitSendFixedBeacon(void);
146 static void MBi_SendFixedBeacon(u32 ggid, u16 tgid, u8 attribute);
147 static void MBi_InitSendVolatBeacon(void);
148 static void MBi_SendVolatBeacon(u32 ggid, u16 tgid, u8 attribute);
149 
150 static void MBi_SetSSIDToBssDesc(WMBssDesc *bssDescp, u32 ggid);
151 static int MBi_GetStoreElement(WMBssDesc *bssDescp, MBBeaconMsgCallback Callbackp);
152 static void MBi_CheckCompleteGameInfoFlagments(int index, MBBeaconMsgCallback Callbackp);
153 static void MBi_AnalyzeBeacon(WMBssDesc *bssDescp, int index, u16 linkLevel);
154 static void MBi_CheckTGID(WMBssDesc *bssDescp, int inex);
155 static void MBi_CheckSeqNoFixed(int index);
156 static void MBi_CheckSeqNoVolat(int index);
157 static void MBi_InvalidateGameInfoBssID(u8 *bssidp);
158 static void MBi_RecvFixedBeacon(int index);
159 static void MBi_RecvVolatBeacon(int index);
160 
161 static void MBi_LockScanTarget(int index);
162 static void MBi_UnlockScanTarget(void);
163 static int mystrlen(u16 *str);
164 
165 
166 // const data----------------------------------------------
167 
168 // global variables----------------------------------------
169 
170 static MbBeaconSendStatus mbss;        // Beacon send status.
171 
172 static MbBeaconRecvStatus mbrs;        // Beacon receive status
173 static MbBeaconRecvStatus *mbrsp = NULL;        // Beacon receive status
174 
175 // static variables----------------------------------------
176 static MbScanLockFunc sLockFunc = NULL; // Pointer to the function for setting a scan lock.
177 static MbScanUnlockFunc sUnlockFunc = NULL;     // Pointer to the function for releasing a scan lock.
178 
179 static MbBeacon bsendBuff ATTRIBUTE_ALIGN(32);  // Beacon send buffer.
180 static MbBeacon *brecvBuffp;           // Beacon receive buffer.
181 static WMBssDesc bssDescbuf ATTRIBUTE_ALIGN(32);        // BssDesc temporary buffer.
182 
183 static MBSendVolatCallbackFunc sSendVolatCallback = NULL;       // User data transmission callback
184 static u32 sSendVolatCallbackTimming;  // Timing at which the transmission callback is issued.
185 
186 // function's description-----------------------------------------------
187 
188 
189 //=========================================================
190 // Operations for the work buffer that receives beacons
191 //=========================================================
192 // Obtains the work buffer that is set.
MB_GetBeaconRecvStatus(void)193 const MbBeaconRecvStatus *MB_GetBeaconRecvStatus(void)
194 {
195     return mbrsp;
196 }
197 
198 // Sets the work buffer from a static variable (for compatibility with older versions).
MBi_SetBeaconRecvStatusBufferDefault(void)199 void MBi_SetBeaconRecvStatusBufferDefault(void)
200 {
201     mbrsp = &mbrs;
202 }
203 
204 // Sets the work buffer for receiving beacons.
MBi_SetBeaconRecvStatusBuffer(MbBeaconRecvStatus * buf)205 void MBi_SetBeaconRecvStatusBuffer(MbBeaconRecvStatus * buf)
206 {
207     mbrsp = buf;
208 }
209 
210 
211 // Sets the function for scan lock
MBi_SetScanLockFunc(MbScanLockFunc lock,MbScanUnlockFunc unlock)212 void MBi_SetScanLockFunc(MbScanLockFunc lock, MbScanUnlockFunc unlock)
213 {
214     sLockFunc = lock;
215     sUnlockFunc = unlock;
216 }
217 
218 
219 
220 //=========================================================
221 // Beacon transmission of game information by the parent device
222 //=========================================================
223 
224 // Generate the parent device's game information to be sent by a beacon.
MBi_MakeGameInfo(MBGameInfo * gameInfop,const MBGameRegistry * mbGameRegp,const MBUserInfo * parent)225 void MBi_MakeGameInfo(MBGameInfo *gameInfop,
226                       const MBGameRegistry *mbGameRegp, const MBUserInfo *parent)
227 {
228     BOOL    icon_disable;
229 
230     // Clear all for the time being.
231     MI_CpuClear16(gameInfop, sizeof(MBGameInfo));
232 
233     // Register the icon data.
234     gameInfop->dataAttr = MB_BEACON_DATA_ATTR_FIXED_NORMAL;
235     icon_disable = !MBi_ReadIconInfo(mbGameRegp->iconCharPathp, &gameInfop->fixed.icon, TRUE);
236     icon_disable |= !MBi_ReadIconInfo(mbGameRegp->iconPalettePathp, &gameInfop->fixed.icon, FALSE);
237 
238     if (icon_disable)
239     {
240         gameInfop->dataAttr = MB_BEACON_DATA_ATTR_FIXED_NO_ICON;
241         MI_CpuClearFast(&gameInfop->fixed.icon, sizeof(MBIconInfo));
242     }
243 
244     // GGID
245     gameInfop->ggid = mbGameRegp->ggid;
246 
247     // Register the parent's user information.
248     if (parent != NULL)
249     {
250         MI_CpuCopy16(parent, &gameInfop->fixed.parent, sizeof(MBUserInfo));
251     }
252 
253     // Register the maximum number of players.
254     gameInfop->fixed.maxPlayerNum = mbGameRegp->maxPlayerNum;
255 
256     // Register the game name and a description of the game content.
257     {
258         int     len;
259 
260 #define COPY_GAME_INFO_STRING   MI_CpuCopy16
261 
262         len = mystrlen(mbGameRegp->gameNamep) << 1;
263         COPY_GAME_INFO_STRING((u8 *)mbGameRegp->gameNamep, gameInfop->fixed.gameName, (u16)len);
264         // Data after the NULL character is also sent so that data can be packed in after the game content explanation.
265         len = MB_GAME_INTRO_LENGTH * 2;
266         COPY_GAME_INFO_STRING((u8 *)mbGameRegp->gameIntroductionp,
267                               gameInfop->fixed.gameIntroduction, (u16)len);
268     }
269 
270     // Register the parent device's portion of the player information.
271     gameInfop->volat.nowPlayerNum = 1;
272     gameInfop->volat.nowPlayerFlag = 0x0001;    // The player number of the parent device is 0.
273     gameInfop->broadcastedPlayerFlag = 0x0001;
274 
275     // NOTE: There is no registration at multiboot startup since there are no play members.
276 }
277 
278 
279 // Read icon data.
MBi_ReadIconInfo(const char * filePathp,MBIconInfo * iconp,BOOL char_flag)280 static BOOL MBi_ReadIconInfo(const char *filePathp, MBIconInfo *iconp, BOOL char_flag)
281 {
282     FSFile  file;
283     s32     size = char_flag ? MB_ICON_DATA_SIZE : MB_ICON_PALETTE_SIZE;
284     u16    *dstp = char_flag ? iconp->data : iconp->palette;
285 
286     if (filePathp == NULL)
287     {                                  // Returns FALSE if there is no file designation.
288         return FALSE;
289     }
290 
291     FS_InitFile(&file);
292 
293     if (FS_OpenFileEx(&file, filePathp, FS_FILEMODE_R) == FALSE)
294     {                                  // Returns FALSE if the file could not be opened.
295         MB_DEBUG_OUTPUT("\t%s : file open error.\n", filePathp);
296         return FALSE;
297     }
298     else if ((u32)size != FS_GetFileLength(&file))
299     {
300         MB_DEBUG_OUTPUT("\t%s : different file size.\n", filePathp);
301         (void)FS_CloseFile(&file);
302         return FALSE;
303     }
304 
305     (void)FS_ReadFile(&file, dstp, size);
306     (void)FS_CloseFile(&file);
307     return TRUE;
308 }
309 
310 
311 // Update the volatile portion of the game information.
MB_UpdateGameInfoMember(MBGameInfo * gameInfop,const MBUserInfo * member,u16 nowPlayerFlag,u16 changePlayerFlag)312 void MB_UpdateGameInfoMember(MBGameInfo *gameInfop,
313                              const MBUserInfo *member, u16 nowPlayerFlag, u16 changePlayerFlag)
314 {
315     int     i;
316     u8      playerNum = 1;
317 
318     MI_CpuCopy16(member, &gameInfop->volat.member[0], sizeof(MBUserInfo) * MB_MEMBER_MAX_NUM);
319     /* Count the number of child devices */
320     for (i = 0; i < MB_MEMBER_MAX_NUM; i++)
321     {
322         if (nowPlayerFlag & (0x0002 << i))
323         {
324             playerNum++;
325         }
326     }
327     gameInfop->volat.nowPlayerNum = playerNum;
328     gameInfop->volat.nowPlayerFlag = (u16)(nowPlayerFlag | 0x0001);
329     gameInfop->volat.changePlayerFlag = changePlayerFlag;
330     gameInfop->seqNoVolat++;
331 }
332 
333 
334 // Calculate the length of a character string.
mystrlen(u16 * str)335 static int mystrlen(u16 *str)
336 {
337     int     len = 0;
338     while (*str++)
339         len++;
340     return len;
341 }
342 
343 
344 // Adds the game information to the send list.
MB_AddGameInfo(MBGameInfo * newGameInfop)345 void MB_AddGameInfo(MBGameInfo *newGameInfop)
346 {
347     MBGameInfo *gInfop = mbss.gameInfoListTop;
348 
349     if (!gInfop)
350     {                                  // If the top of mbss is NULL, register at the top.
351         mbss.gameInfoListTop = newGameInfop;
352     }
353     else
354     {                                  // Otherwise, follow the list and add to the end.
355         while (gInfop->nextp != NULL)
356         {
357             gInfop = gInfop->nextp;
358         }
359         gInfop->nextp = newGameInfop;
360     }
361     newGameInfop->nextp = NULL;        // 'next' of the added game information is the end.
362 }
363 
364 
365 // Deletes the game information from the send list.
MB_DeleteGameInfo(MBGameInfo * gameInfop)366 BOOL MB_DeleteGameInfo(MBGameInfo *gameInfop)
367 {
368     MBGameInfo *gInfop = mbss.gameInfoListTop;
369     MBGameInfo *before;
370 
371     while (gInfop != NULL)
372     {
373         if (gInfop != gameInfop)
374         {
375             before = gInfop;
376             gInfop = gInfop->nextp;
377             continue;
378         }
379 
380         // It matched, so it is deleted from the list.
381         if ((u32)gInfop == (u32)mbss.gameInfoListTop)
382         {                              // when deleting the top of the list
383             mbss.gameInfoListTop = mbss.gameInfoListTop->nextp;
384         }
385         else
386         {
387             before->nextp = gInfop->nextp;
388         }
389 
390         if ((u32)gameInfop == (u32)mbss.nowGameInfop)   // If the game information to delete is currently being transmitted, re-set that game information from the rebuilt list.
391         {                              //
392             mbss.nowGameInfop = NULL;
393             if (!MBi_ReadyBeaconSendStatus())
394             {
395                 mbss.state = MB_BEACON_STATE_READY;     // If the game information has been completely deleted, the status shifts to READY.
396             }
397         }
398         return TRUE;
399     }
400 
401     // When there is no game information
402     return FALSE;
403 }
404 
405 
406 // Initializes the game information send configuration.
MB_InitSendGameInfoStatus(void)407 void MB_InitSendGameInfoStatus(void)
408 {
409     mbss.gameInfoListTop = NULL;       // Delete the entire game information list.
410     mbss.nowGameInfop = NULL;          // Also delete the current transmitted game.
411     mbss.state = MB_BEACON_STATE_READY;
412     sSendVolatCallback = NULL;
413     MBi_ClearSendStatus();             // Also clear the send status.
414 }
415 
416 
417 // Clears the send status.
MBi_ClearSendStatus(void)418 static void MBi_ClearSendStatus(void)
419 {
420     mbss.seqNoFixed = 0;
421     mbss.seqNoVolat = 0;
422     mbss.flagmentNo = 0;
423     mbss.flagmentMaxNum = 0;
424     mbss.beaconNo = 0;
425 }
426 
427 
428 // Sends a beacon.
MB_SendGameInfoBeacon(u32 ggid,u16 tgid,u8 attribute)429 void MB_SendGameInfoBeacon(u32 ggid, u16 tgid, u8 attribute)
430 {
431     while (1)
432     {
433         switch (mbss.state)
434         {
435         case MB_BEACON_STATE_STOP:
436         case MB_BEACON_STATE_READY:
437             if (!MBi_ReadyBeaconSendStatus())
438             {                          // Preparations for sending game information.
439                 return;
440             }
441             break;
442         case MB_BEACON_STATE_FIXED_START:
443             MBi_InitSendFixedBeacon();
444             break;
445         case MB_BEACON_STATE_FIXED:
446             MBi_SendFixedBeacon(ggid, tgid, attribute);
447             return;
448         case MB_BEACON_STATE_VOLAT_START:
449             MBi_InitSendVolatBeacon();
450             break;
451         case MB_BEACON_STATE_VOLAT:
452             MBi_SendVolatBeacon(ggid, tgid, attribute);
453             return;
454         case MB_BEACON_STATE_NEXT_GAME:
455             break;
456         }
457     }
458 }
459 
460 
461 // Prepare the beacon send status so that it is sendable.
MBi_ReadyBeaconSendStatus(void)462 static BOOL MBi_ReadyBeaconSendStatus(void)
463 {
464     MBGameInfo *nextGameInfop;
465 
466     // Return an error if the game information has not been registered.
467     if (!mbss.gameInfoListTop)
468     {
469         /* The MB flag and ENTRY flag are dropped here. */
470         (void)WM_SetGameInfo(NULL, (u16 *)&bsendBuff, WM_SIZE_USER_GAMEINFO, MBi_GetGgid(),
471                              MBi_GetTgid(), WM_ATTR_FLAG_CS);
472         return FALSE;
473     }
474 
475     // Select the GameInfo to send next.
476     if (!mbss.nowGameInfop || !mbss.nowGameInfop->nextp)
477     {
478         // If there is no game information still being sent, or if at the end of the list, prepare to send the top of the list.
479         nextGameInfop = mbss.gameInfoListTop;
480     }
481     else
482     {
483         // Otherwise, prepare to send the next game in the list.
484         nextGameInfop = mbss.nowGameInfop->nextp;
485     }
486 
487     mbss.nowGameInfop = nextGameInfop;
488 
489     MBi_ClearSendStatus();
490     mbss.seqNoVolat = mbss.nowGameInfop->seqNoVolat;
491 
492     mbss.state = MB_BEACON_STATE_FIXED_START;
493 
494     return TRUE;
495 }
496 
497 
498 // Initialize transmission of the fixed data portion of the game information.
MBi_InitSendFixedBeacon(void)499 static void MBi_InitSendFixedBeacon(void)
500 {
501     if (mbss.state != MB_BEACON_STATE_FIXED_START)
502     {
503         return;
504     }
505 
506     if (mbss.nowGameInfop->dataAttr == MB_BEACON_DATA_ATTR_FIXED_NORMAL)
507     {
508         mbss.flagmentMaxNum = FIXED_FLAGMENT_MAX(FIXED_NORMAL_SIZE);
509         mbss.srcp = (u8 *)&mbss.nowGameInfop->fixed;
510     }
511     else
512     {
513         mbss.flagmentMaxNum = FIXED_FLAGMENT_MAX(FIXED_NO_ICON_SIZE);
514         mbss.srcp = (u8 *)&mbss.nowGameInfop->fixed.parent;
515     }
516     mbss.state = MB_BEACON_STATE_FIXED;
517 }
518 
519 
520 // Split up the fixed data portion of the game information and send a beacon.
MBi_SendFixedBeacon(u32 ggid,u16 tgid,u8 attribute)521 static void MBi_SendFixedBeacon(u32 ggid, u16 tgid, u8 attribute)
522 {
523     u32     lastAddr = (u32)mbss.nowGameInfop + sizeof(MBGameInfoFixed);
524 
525     if ((u32)mbss.srcp + MB_BEACON_FIXED_DATA_SIZE <= lastAddr)
526     {
527         bsendBuff.data.fixed.size = MB_BEACON_FIXED_DATA_SIZE;
528     }
529     else
530     {
531         bsendBuff.data.fixed.size = (u8)(lastAddr - (u32)mbss.srcp);
532         MI_CpuClear16((void *)((u8 *)bsendBuff.data.fixed.data + bsendBuff.data.fixed.size),
533                       (u32)(MB_BEACON_FIXED_DATA_SIZE - bsendBuff.data.fixed.size));
534     }
535 
536     // Set to the beacon send buffer.
537     MB_DEBUG_OUTPUT("send flagment= %2d  adr = 0x%x\n", mbss.flagmentNo, mbss.srcp);
538     MI_CpuCopy16(mbss.srcp, bsendBuff.data.fixed.data, bsendBuff.data.fixed.size);
539     bsendBuff.data.fixed.flagmentNo = mbss.flagmentNo;
540     bsendBuff.data.fixed.flagmentMaxNum = mbss.flagmentMaxNum;
541     bsendBuff.dataAttr = mbss.nowGameInfop->dataAttr;
542     bsendBuff.seqNoFixed = mbss.nowGameInfop->seqNoFixed;
543     bsendBuff.seqNoVolat = mbss.seqNoVolat;
544     bsendBuff.ggid = mbss.nowGameInfop->ggid;
545     bsendBuff.fileNo = mbss.nowGameInfop->fileNo;
546     bsendBuff.beaconNo = mbss.beaconNo++;
547     bsendBuff.data.fixed.sum = 0;
548     bsendBuff.data.fixed.sum = MBi_calc_cksum((u16 *)&bsendBuff.data, MB_BEACON_DATA_SIZE);
549 
550     // Update the send status.
551     mbss.flagmentNo++;
552     if (mbss.flagmentNo < mbss.flagmentMaxNum)
553     {
554         mbss.srcp += MB_BEACON_FIXED_DATA_SIZE;
555     }
556     else
557     {
558         mbss.state = MB_BEACON_STATE_VOLAT_START;
559     }
560 
561     /* Register the GGID of the parent program itself. */
562     (void)WM_SetGameInfo(NULL, (u16 *)&bsendBuff, WM_SIZE_USER_GAMEINFO, ggid, tgid,
563                          (u8)(attribute | WM_ATTR_FLAG_MB | WM_ATTR_FLAG_ENTRY));
564     // The multiboot flag is activated here.
565 }
566 
567 
568 // Initialize transmission of the volatile data portion of the game information.
MBi_InitSendVolatBeacon(void)569 static void MBi_InitSendVolatBeacon(void)
570 {
571     mbss.nowGameInfop->broadcastedPlayerFlag = 0x0001;
572     mbss.seqNoVolat = mbss.nowGameInfop->seqNoVolat;
573     mbss.state = MB_BEACON_STATE_VOLAT;
574 }
575 
576 
577 // Split up the volatile data portion of the game information and send a beacon.
MBi_SendVolatBeacon(u32 ggid,u16 tgid,u8 attribute)578 static void MBi_SendVolatBeacon(u32 ggid, u16 tgid, u8 attribute)
579 {
580     int     i;
581     int     setPlayerNum;
582     u16     remainPlayerFlag;
583 
584     if (mbss.seqNoVolat != mbss.nowGameInfop->seqNoVolat)
585     {                                  // Resend if the data is updated during a send.
586         MBi_InitSendVolatBeacon();
587     }
588 
589     // Set the beacon information.
590     bsendBuff.dataAttr = MB_BEACON_DATA_ATTR_VOLAT;
591     bsendBuff.seqNoFixed = mbss.nowGameInfop->seqNoFixed;
592     bsendBuff.seqNoVolat = mbss.seqNoVolat;
593     bsendBuff.ggid = mbss.nowGameInfop->ggid;
594     bsendBuff.fileNo = mbss.nowGameInfop->fileNo;
595     bsendBuff.beaconNo = mbss.beaconNo++;
596 
597     // Set the state of the current player information.
598     bsendBuff.data.volat.nowPlayerNum = mbss.nowGameInfop->volat.nowPlayerNum;
599     bsendBuff.data.volat.nowPlayerFlag = mbss.nowGameInfop->volat.nowPlayerFlag;
600     bsendBuff.data.volat.changePlayerFlag = mbss.nowGameInfop->volat.changePlayerFlag;
601 
602     // Set the application configuration data.
603     if (sSendVolatCallbackTimming == MB_SEND_VOLAT_CALLBACK_TIMMING_BEFORE
604         && sSendVolatCallback != NULL)
605     {
606         sSendVolatCallback(mbss.nowGameInfop->ggid);
607     }
608 
609     for (i = 0; i < MB_USER_VOLAT_DATA_SIZE; i++)
610     {
611         bsendBuff.data.volat.userVolatData[i] = mbss.nowGameInfop->volat.userVolatData[i];
612     }
613 
614     MB_DEBUG_OUTPUT("send PlayerFlag = %x\n", mbss.nowGameInfop->volat.nowPlayerFlag);
615 
616     // Set the player information to send this time.
617     MI_CpuClear16(&bsendBuff.data.volat.member[0], sizeof(MBUserInfo) * MB_SEND_MEMBER_MAX_NUM);
618     setPlayerNum = 0;
619     remainPlayerFlag =
620         (u16)(mbss.nowGameInfop->broadcastedPlayerFlag ^ mbss.nowGameInfop->volat.nowPlayerFlag);
621     for (i = 0; i < MB_MEMBER_MAX_NUM; i++)
622     {
623         if ((remainPlayerFlag & (0x0002 << i)) == 0)
624         {
625             continue;
626         }
627 
628         MB_DEBUG_OUTPUT("  member %d set.\n", i);
629 
630         MI_CpuCopy16(&mbss.nowGameInfop->volat.member[i],
631                      &bsendBuff.data.volat.member[setPlayerNum], sizeof(MBUserInfo));
632         mbss.nowGameInfop->broadcastedPlayerFlag |= 0x0002 << i;
633         if (++setPlayerNum == MB_SEND_MEMBER_MAX_NUM)
634         {
635             break;
636         }
637     }
638     if (setPlayerNum < MB_SEND_MEMBER_MAX_NUM)
639     {                                  // Terminate when the maximum number of sends was not reached.
640         bsendBuff.data.volat.member[setPlayerNum].playerNo = 0;
641     }
642 
643     // Set the checksum.
644     bsendBuff.data.volat.sum = 0;
645     bsendBuff.data.volat.sum = MBi_calc_cksum((u16 *)&bsendBuff.data, MB_BEACON_DATA_SIZE);
646 
647 
648     // check for send end
649     if (mbss.nowGameInfop->broadcastedPlayerFlag == mbss.nowGameInfop->volat.nowPlayerFlag)
650     {
651         mbss.state = MB_BEACON_STATE_READY;     // When sending of all information is complete, moves to a ready state in order to send the next game information.
652     }
653 
654     /* Register the GGID of the parent program itself. */
655 
656     (void)WM_SetGameInfo(NULL, (u16 *)&bsendBuff, WM_SIZE_USER_GAMEINFO, ggid, tgid,
657                          (u8)(attribute | WM_ATTR_FLAG_MB | WM_ATTR_FLAG_ENTRY));
658     // The multiboot flag is activated here.
659 
660     if (sSendVolatCallbackTimming == MB_SEND_VOLAT_CALLBACK_TIMMING_AFTER
661         && sSendVolatCallback != NULL)
662     {
663         sSendVolatCallback(mbss.nowGameInfop->ggid);
664     }
665 
666 }
667 
668 
669 //=========================================================
670 // Beacon reception of the game information by the child device.
671 //=========================================================
672 
673 // Initializes the game information receive status.
MB_InitRecvGameInfoStatus(void)674 void MB_InitRecvGameInfoStatus(void)
675 {
676     MI_CpuClearFast(mbrsp, sizeof(MbBeaconRecvStatus));
677 
678     mbrsp->scanCountUnit = MB_SCAN_COUNT_UNIT_NORMAL;
679 }
680 
681 
682 // Receives a beacon.
MB_RecvGameInfoBeacon(MBBeaconMsgCallback Callbackp,u16 linkLevel,WMBssDesc * bssDescp)683 BOOL MB_RecvGameInfoBeacon(MBBeaconMsgCallback Callbackp, u16 linkLevel, WMBssDesc *bssDescp)
684 {
685     int     index;
686 
687     // Determine whether or not the beacon obtained this time is a multiboot parent device.
688     if (!MBi_CheckMBParent(bssDescp))
689     {
690         return FALSE;
691     }
692 
693     /* Copy the obtained bssDesc to a temporary buffer */
694     MI_CpuCopy16(bssDescp, &bssDescbuf, sizeof(WMBssDesc));
695 
696     /* Switch bssDescp to a local buffer. */
697     bssDescp = &bssDescbuf;
698 
699     brecvBuffp = (MbBeacon *) bssDescp->gameInfo.userGameInfo;
700 
701     // Confirm checksum.
702     if (MBi_calc_cksum((u16 *)&brecvBuffp->data, MB_BEACON_DATA_SIZE))
703     {
704         MB_DEBUG_OUTPUT("Beacon checksum error!\n");
705         return FALSE;
706     }
707 
708     // Determines the location for storing the parent's game information (if the same parent data has already been received, continue to store at that location)
709     index = MBi_GetStoreElement(bssDescp, Callbackp);
710     if (index < 0)
711     {
712         return FALSE;                  // Returns an error because there is no storage location
713     }
714     MB_DEBUG_OUTPUT("GameInfo Index:%6d\n", index);
715 
716     // Beacon analysis
717     MBi_AnalyzeBeacon(bssDescp, index, linkLevel);
718 
719     // Determines whether all the parent's game data fragments are gathered together and makes a notification with a callback
720     MBi_CheckCompleteGameInfoFlagments(index, Callbackp);
721 
722     return TRUE;
723 }
724 
725 
726 // Determines whether the beacon that was obtained this time is a multiboot parent device.
MBi_CheckMBParent(WMBssDesc * bssDescp)727 BOOL MBi_CheckMBParent(WMBssDesc *bssDescp)
728 {
729     // Determines whether it is a multiboot parent device.
730     if ((bssDescp->gameInfo.magicNumber != WM_GAMEINFO_MAGIC_NUMBER)
731         || !(bssDescp->gameInfo.attribute & WM_ATTR_FLAG_MB))
732     {
733         MB_DEBUG_OUTPUT("not MB parent : %x%x\n",
734                         *(u16 *)(&bssDescp->bssid[4]), *(u32 *)bssDescp->bssid);
735         return FALSE;
736     }
737     else
738     {
739 
740         MB_DEBUG_OUTPUT("MB parent     : %x%x",
741                         *(u16 *)(&bssDescp->bssid[4]), *(u32 *)bssDescp->bssid);
742         return TRUE;
743     }
744 }
745 
746 
747 // Sets an SSID to bssDesc.
MBi_SetSSIDToBssDesc(WMBssDesc * bssDescp,u32 ggid)748 static void MBi_SetSSIDToBssDesc(WMBssDesc *bssDescp, u32 ggid)
749 {
750     /*
751        SSID settings
752 
753        The SSID is generated from the download application specific GGID and the multiboot parent's TGID.
754 
755        The child reconnects with the parent application using this SSID.
756      */
757     bssDescp->ssidLength = 32;
758     ((u16 *)bssDescp->ssid)[0] = (u16)(ggid & 0x0000ffff);
759     ((u16 *)bssDescp->ssid)[1] = (u16)((ggid & 0xffff0000) >> 16);
760     ((u16 *)bssDescp->ssid)[2] = bssDescp->gameInfo.tgid;
761 }
762 
763 
764 // Based on bssDesc, gets where in the receive list elements to perform a store.
MBi_GetStoreElement(WMBssDesc * bssDescp,MBBeaconMsgCallback Callbackp)765 static int MBi_GetStoreElement(WMBssDesc *bssDescp, MBBeaconMsgCallback Callbackp)
766 {
767     int     i;
768 
769     // Determines whether the same game information has already been received from this parent (if "GGID", "BSSID" and "fileNo" all match, the game information is determined to be the same)
770     for (i = 0; i < MB_GAME_INFO_RECV_LIST_NUM; i++)
771     {
772         MBGameInfoRecvList *info = &mbrsp->list[i];
773 
774         if ((mbrsp->usingGameInfoFlag & (0x01 << i)) == 0)
775         {
776             continue;
777         }
778         // Does GGID match?
779         if (info->gameInfo.ggid != brecvBuffp->ggid)
780         {
781             continue;
782         }
783         // Does the MAC address match?
784         if (!WM_IsBssidEqual(info->bssDesc.bssid, bssDescp->bssid))
785         {
786             continue;
787         }
788         // Does the file number match?
789         if (mbrsp->list[i].gameInfo.fileNo != brecvBuffp->fileNo)
790         {
791             continue;
792         }
793 
794         // =========================================
795         // Determined that a reception location for this parent device information has already been allocated.
796         // =========================================
797         if (!(mbrsp->validGameInfoFlag & (0x01 << i)))
798         {
799             MBi_LockScanTarget(i);     // If information for the appropriate Parent Device is not ready, scan lock.
800         }
801         return i;
802     }
803 
804     // It has not yet been received, so search for the NULL position in the list and make that the storage location.
805     for (i = 0; i < MB_GAME_INFO_RECV_LIST_NUM; i++)
806     {
807         if (mbrsp->usingGameInfoFlag & (0x01 << i))
808         {
809             continue;
810         }
811 
812         MI_CpuCopy16(bssDescp, &mbrsp->list[i].bssDesc, sizeof(WMBssDesc));
813         // Copies BssDesc
814         mbrsp->list[i].gameInfo.seqNoFixed = brecvBuffp->seqNoFixed;
815         mbrsp->usingGameInfoFlag |= (u16)(0x01 << i);
816 
817         MB_DEBUG_OUTPUT("\n");
818         // Only this parent device should be locked to the scan target.
819         MBi_LockScanTarget(i);
820         return i;
821     }
822 
823     // If all the storage locations are full, an error is returned with a callback notification
824     if (Callbackp != NULL)
825     {
826         Callbackp(MB_BC_MSG_GINFO_LIST_FULL, NULL, 0);
827     }
828     return -1;
829 }
830 
831 
832 // Determines whether all the parent's game data fragments are gathered together and makes a notification with a callback
MBi_CheckCompleteGameInfoFlagments(int index,MBBeaconMsgCallback Callbackp)833 static void MBi_CheckCompleteGameInfoFlagments(int index, MBBeaconMsgCallback Callbackp)
834 {
835     MBGameInfoRecvList *info = &mbrsp->list[index];
836 
837     /* In any case, notify the application that a parent was discovered. */
838     if (Callbackp != NULL)
839     {
840         Callbackp(MB_BC_MSG_GINFO_BEACON, info, index);
841     }
842     if ((info->getFlagmentFlag == info->allFlagmentFlag) && (info->getFlagmentFlag)     // If the new parent game information is complete
843         && (info->gameInfo.volat.nowPlayerFlag)
844         && (info->getPlayerFlag == info->gameInfo.volat.nowPlayerFlag))
845     {
846         if (mbrsp->validGameInfoFlag & (0x01 << index))
847         {
848             return;
849         }
850         mbrsp->validGameInfoFlag |= 0x01 << index;
851         mbrsp->usefulGameInfoFlag |= 0x01 << index;
852         MBi_UnlockScanTarget();        // Releases the lock on the scan target
853         MB_DEBUG_OUTPUT("validated ParentInfo = %d\n", index);
854         if (Callbackp != NULL)
855         {
856             Callbackp(MB_BC_MSG_GINFO_VALIDATED, info, index);
857         }
858     }
859     else
860     {                                  // If the parent's game information that was already obtained is updated and becomes incomplete
861         if ((mbrsp->validGameInfoFlag & (0x01 << index)) == 0)
862         {
863             return;
864         }
865         mbrsp->validGameInfoFlag ^= (0x01 << index);
866         MB_DEBUG_OUTPUT("Invaldated ParentInfo = %d\n", index);
867         if (Callbackp != NULL)
868         {
869             Callbackp(MB_BC_MSG_GINFO_INVALIDATED, info, index);
870         }
871     }
872 }
873 
874 
875 // The parent's game information lifetime count (while doing so, also counts the scan lock time)
MB_CountGameInfoLifetime(MBBeaconMsgCallback Callbackp,BOOL found_parent)876 void MB_CountGameInfoLifetime(MBBeaconMsgCallback Callbackp, BOOL found_parent)
877 {
878     int     i;
879     BOOL    unlock = FALSE;
880 
881     // Determines the lifetime of the game information receiving list and confirms the presence of a new lock target.
882     for (i = 0; i < MB_GAME_INFO_RECV_LIST_NUM; i++)
883     {
884         MBGameInfoRecvList *info = &mbrsp->list[i];
885         u16     mask = (u16)(0x0001 << i);
886         if ((mbrsp->usingGameInfoFlag & mask) == 0)
887         {
888             continue;
889         }
890         // Lifetime determination
891         info->lifetimeCount -= mbrsp->scanCountUnit;
892         if (info->lifetimeCount >= 0)
893         {
894             continue;
895         }
896         info->lifetimeCount = 0;
897         if (mbrsp->validGameInfoFlag & mask)
898         {
899             if (Callbackp != NULL)
900             {
901                 Callbackp(MB_BC_MSG_GINFO_LOST, info, i);
902             }
903         }
904         if (mbrsp->nowScanTargetFlag & mask)
905         {
906             unlock = TRUE;
907         }
908         mbrsp->usingGameInfoFlag &= ~mask;
909         MB_DeleteRecvGameInfo(i);      // Deletes game information after callback notification.
910         MB_DEBUG_OUTPUT("gameInfo %2d : lifetime end.\n", i);
911     }
912 
913     // Scan lock time count
914     if (mbrsp->nowScanTargetFlag && mbrsp->nowLockTimeCount > 0)
915     {
916         mbrsp->nowLockTimeCount -= mbrsp->scanCountUnit;        // Releases the lock and searches for the next lock target if the scan lock times out.
917         if (mbrsp->nowLockTimeCount < 0)
918         {
919             MB_DEBUG_OUTPUT("scan lock time up!\n");
920             unlock = TRUE;
921         }
922         else if (!found_parent)
923         {
924             if (++mbrsp->notFoundLockTargetCount > 4)
925             {
926                 MB_DEBUG_OUTPUT("scan lock target not found!\n");
927                 unlock = TRUE;
928             }
929         }
930         else
931         {
932             mbrsp->notFoundLockTargetCount = 0;
933         }
934     }
935 
936     // Scan unlock processing.
937     if (unlock)
938     {
939         mbrsp->nowLockTimeCount = 0;
940         MBi_UnlockScanTarget();
941     }
942 }
943 
944 
945 // Beacon analysis
MBi_AnalyzeBeacon(WMBssDesc * bssDescp,int index,u16 linkLevel)946 static void MBi_AnalyzeBeacon(WMBssDesc *bssDescp, int index, u16 linkLevel)
947 {
948     MBi_CheckTGID(bssDescp, index);    // Checks the TGID
949     MBi_CheckSeqNoFixed(index);        // Checks seqNoFixed
950     MBi_CheckSeqNoVolat(index);        // Checks seqNoVolat
951 
952     // Obtains data for the shared portion of the received beacon
953     {
954         MBGameInfoRecvList *info = &mbrsp->list[index];
955 
956         // Excludes parents that are in an abnormal state, repeatedly sending out the same beacon.
957         if (info->beaconNo == brecvBuffp->beaconNo)
958         {
959             if (++info->sameBeaconRecvCount > MB_SAME_BEACON_RECV_MAX_COUNT)
960             {
961                 info->lifetimeCount = 0;        // Sets the lifetime of the parent information to zero so it gets deleted.
962                 MB_OUTPUT("The parent broadcast same beacon.: %d\n", index);
963                 MBi_InvalidateGameInfoBssID(&info->bssDesc.bssid[0]);
964                 return;                // If this parent has distributed other game information, that is deleted as well.
965             }
966         }
967         else
968         {
969             info->sameBeaconRecvCount = 0;
970         }
971         // Data reception for normal parents.
972         info->beaconNo = brecvBuffp->beaconNo;
973         info->lifetimeCount = MB_LIFETIME_MAX_COUNT;    // Extends the lifetime of the parent's information.
974         info->gameInfo.ggid = brecvBuffp->ggid; // Gets ggid.
975         info->gameInfo.fileNo = brecvBuffp->fileNo;     // Gets fileNo.
976         info->linkLevel = linkLevel;   // Gets the signal strength.
977         // Sets an SSID to bssDesc.
978         MBi_SetSSIDToBssDesc(&info->bssDesc, info->gameInfo.ggid);
979     }
980 
981     // Gets data for each data type in the received beacon.
982     if (brecvBuffp->dataAttr == MB_BEACON_DATA_ATTR_VOLAT)
983     {
984         MBi_RecvVolatBeacon(index);
985     }
986     else
987     {
988         MBi_RecvFixedBeacon(index);
989     }
990 }
991 
992 
993 // Checks tgid
MBi_CheckTGID(WMBssDesc * bssDescp,int index)994 static void MBi_CheckTGID(WMBssDesc *bssDescp, int index)
995 {
996     if (mbrsp->list[index].bssDesc.gameInfo.tgid == bssDescp->gameInfo.tgid)
997     {
998         return;
999     }
1000 
1001     // If tgid is updated, that parent device is assumed to be restarting; all data is cleared and re-obtained.
1002     MB_DEBUG_OUTPUT("\ntgid updated! : %x%x", *(u16 *)(&bssDescp->bssid[4]),
1003                     *(u32 *)bssDescp->bssid);
1004     MB_DeleteRecvGameInfoWithoutBssdesc(index);
1005     MI_CpuCopy16(bssDescp, &mbrsp->list[index].bssDesc, sizeof(WMBssDesc));
1006     // A new bssDesc is copied in the event of a tgid update.
1007     MBi_LockScanTarget(index);         // Scan-locks the appropriate parent.
1008 }
1009 
1010 
1011 // Checks the SeqNo of the fixed data
MBi_CheckSeqNoFixed(int index)1012 static void MBi_CheckSeqNoFixed(int index)
1013 {
1014     // Handles the situation where the sequence number has been updated
1015     if (mbrsp->list[index].gameInfo.seqNoFixed == brecvBuffp->seqNoFixed)
1016     {
1017         return;
1018     }
1019     // Clears the data received thus far if the sequence number has been updated.
1020     MB_DEBUG_OUTPUT("\n seqNoFixed updated!");
1021     MB_DeleteRecvGameInfoWithoutBssdesc(index);
1022     MBi_LockScanTarget(index);         // Scan-locks the appropriate parent.
1023     mbrsp->list[index].gameInfo.seqNoFixed = brecvBuffp->seqNoFixed;
1024 }
1025 
1026 
1027 // Checks the SeqNo of the volatile data.
MBi_CheckSeqNoVolat(int index)1028 static void MBi_CheckSeqNoVolat(int index)
1029 {
1030     MBGameInfoRecvList *grecvp = &mbrsp->list[index];
1031 
1032     // Handles the situation where the sequence number has been updated
1033     if (mbrsp->list[index].gameInfo.seqNoVolat != brecvBuffp->seqNoVolat)
1034     {
1035         MB_DEBUG_OUTPUT("\n seqNoVolat updated!");
1036         MBi_LockScanTarget(index);     // Checks whether a scan lock is possible, then does so.
1037     }
1038 }
1039 
1040 
1041 // Invalidates all the parent game information of the target BSSID.
MBi_InvalidateGameInfoBssID(u8 * bssidp)1042 static void MBi_InvalidateGameInfoBssID(u8 *bssidp)
1043 {
1044     int     i;
1045     for (i = 0; i < MB_GAME_INFO_RECV_LIST_NUM; i++)
1046     {
1047         if ((mbrsp->usingGameInfoFlag & (0x01 << i)) == 0)
1048         {
1049             continue;
1050         }
1051 
1052         if (!WM_IsBssidEqual(bssidp, mbrsp->list[i].bssDesc.bssid))
1053         {
1054             continue;
1055         }
1056 
1057         // Determined to be data that is targeted for deletion.
1058         mbrsp->list[i].lifetimeCount = 0;       // Sets the lifetime of the parent information to zero so it gets deleted.
1059         MB_OUTPUT("The parent broadcast same beacon.: %d\n", i);
1060     }
1061 }
1062 
1063 
1064 // Splits up the fixed data portion of the game information and receives the beacon.
MBi_RecvFixedBeacon(int index)1065 static void MBi_RecvFixedBeacon(int index)
1066 {
1067     MBGameInfoRecvList *grecvp = &mbrsp->list[index];
1068     u32     lastAddr = (u32)&grecvp->gameInfo + sizeof(MBGameInfoFixed);
1069     u8     *dstp;
1070 
1071     // Do not receive if the sequence number has not been updated, and the beacon has already been obtained.
1072     if (grecvp->gameInfo.seqNoFixed == brecvBuffp->seqNoFixed)
1073     {
1074         if (grecvp->getFlagmentFlag & (0x01 << brecvBuffp->data.fixed.flagmentNo))
1075         {
1076             return;
1077         }
1078     }
1079 
1080     // Checks whether the received beacon exceeds the receive buffer.
1081     if (brecvBuffp->dataAttr == MB_BEACON_DATA_ATTR_FIXED_NORMAL)
1082     {
1083         dstp = (u8 *)&grecvp->gameInfo.fixed;
1084     }
1085     else
1086     {
1087         dstp = (u8 *)&grecvp->gameInfo.fixed.parent;
1088     }
1089     dstp += MB_BEACON_FIXED_DATA_SIZE * brecvBuffp->data.fixed.flagmentNo;
1090     // Calculates the receiving address for the game information buffer.
1091 
1092     if ((u32)dstp + brecvBuffp->data.fixed.size > lastAddr)
1093     {
1094         MB_DEBUG_OUTPUT("recv beacon gInfoFixed Buffer over!\n");
1095         // Ignores beacon data that overflows the buffer.
1096         return;
1097     }
1098 
1099     // Sets the received beacon to the target game information buffer
1100     MB_DEBUG_OUTPUT("recv flagment= %2d  adr = 0x%x", brecvBuffp->data.fixed.flagmentNo, dstp);
1101     MI_CpuCopy16(brecvBuffp->data.fixed.data, dstp, brecvBuffp->data.fixed.size);
1102     grecvp->gameInfo.dataAttr = brecvBuffp->dataAttr;
1103     grecvp->getFlagmentFlag |= 0x01 << brecvBuffp->data.fixed.flagmentNo;
1104     grecvp->allFlagmentFlag = (u32)((0x01 << brecvBuffp->data.fixed.flagmentMaxNum) - 1);
1105     MB_DEBUG_OUTPUT("\t now flagment = 0x%x \t all flagment = 0x%x\n",
1106                     grecvp->getFlagmentFlag, grecvp->allFlagmentFlag);
1107 }
1108 
1109 
1110 // Splits up the volatile data portion of the game information and receives the beacon.
MBi_RecvVolatBeacon(int index)1111 static void MBi_RecvVolatBeacon(int index)
1112 {
1113     int     i;
1114     MBGameInfoRecvList *grecvp = &mbrsp->list[index];
1115 
1116     /* Always receive user-defined data. */
1117     for (i = 0; i < MB_USER_VOLAT_DATA_SIZE; i++)
1118     {
1119         grecvp->gameInfo.volat.userVolatData[i] = brecvBuffp->data.volat.userVolatData[i];
1120     }
1121     MI_CpuCopy16(brecvBuffp, &grecvp->bssDesc.gameInfo.userGameInfo, WM_SIZE_USER_GAMEINFO);
1122 
1123     // Processing when a member information update is detected.
1124     if (grecvp->gameInfo.seqNoVolat != brecvBuffp->seqNoVolat)
1125     {
1126         if ((u8)(grecvp->gameInfo.seqNoVolat + 1) == brecvBuffp->seqNoVolat)
1127         {                              // Transfer of non-updated member information if seqNoVolat is off by one
1128             for (i = 0; i < MB_MEMBER_MAX_NUM; i++)
1129             {
1130                 if (brecvBuffp->data.volat.changePlayerFlag & (0x02 << i))
1131                 {
1132                     MI_CpuClear16(&grecvp->gameInfo.volat.member[i], sizeof(MBUserInfo));
1133                 }
1134             }
1135             grecvp->getPlayerFlag &= ~brecvBuffp->data.volat.changePlayerFlag;
1136             mbrsp->validGameInfoFlag &= ~(0x0001 << index);
1137         }
1138         else
1139         {                              // Clears all the member information received thus far if seqNoVolat is further off.
1140             MI_CpuClear16(&grecvp->gameInfo.volat.member[0],
1141                           sizeof(MBUserInfo) * MB_MEMBER_MAX_NUM);
1142             grecvp->getPlayerFlag = 0;
1143             mbrsp->validGameInfoFlag &= ~(0x0001 << index);
1144         }
1145         grecvp->gameInfo.seqNoVolat = brecvBuffp->seqNoVolat;
1146     }
1147     else if (grecvp->getPlayerFlag == brecvBuffp->data.volat.nowPlayerFlag)
1148     {
1149         return;                        // Do not receive if the sequence number has not been updated, and the beacon has already been obtained.
1150     }
1151 
1152     // Reads the player information
1153     grecvp->gameInfo.volat.nowPlayerNum = brecvBuffp->data.volat.nowPlayerNum;
1154     grecvp->gameInfo.volat.nowPlayerFlag = brecvBuffp->data.volat.nowPlayerFlag;
1155     grecvp->gameInfo.volat.changePlayerFlag = brecvBuffp->data.volat.changePlayerFlag;
1156     grecvp->getPlayerFlag |= 0x0001;
1157 
1158     // Reads the user information for each member
1159     for (i = 0; i < MB_SEND_MEMBER_MAX_NUM; i++)
1160     {
1161         int     playerNo = (int)brecvBuffp->data.volat.member[i].playerNo;
1162         if (playerNo == 0)
1163         {
1164             continue;
1165         }
1166         MB_DEBUG_OUTPUT("member %d recv.\n", playerNo);
1167         MI_CpuCopy16(&brecvBuffp->data.volat.member[i],
1168                      &grecvp->gameInfo.volat.member[playerNo - 1], sizeof(MBUserInfo));
1169         grecvp->getPlayerFlag |= 0x01 << playerNo;
1170     }
1171 }
1172 
1173 
1174 // Locks the scan target to a single parent
MBi_LockScanTarget(int index)1175 static void MBi_LockScanTarget(int index)
1176 {
1177     /* Ignore if there is already a locked target */
1178     if (mbrsp->nowScanTargetFlag)
1179     {
1180         return;
1181     }
1182 
1183     if (sLockFunc != NULL)
1184     {
1185         sLockFunc(mbrsp->list[index].bssDesc.bssid);
1186     }
1187     mbrsp->scanCountUnit = MB_SCAN_COUNT_UNIT_LOCKING;
1188 
1189     mbrsp->nowScanTargetFlag = (u16)(0x01 << index);    // Shows new scan lock targets in bits.
1190     mbrsp->nowLockTimeCount = MB_LOCKTIME_MAX_COUNT;    // Initializes the scan lock time
1191     MB_DEBUG_OUTPUT("scan target locked. : %x %x %x %x %x %x\n",
1192                     mbrsp->list[index].bssDesc.bssid[0],
1193                     mbrsp->list[index].bssDesc.bssid[1],
1194                     mbrsp->list[index].bssDesc.bssid[2],
1195                     mbrsp->list[index].bssDesc.bssid[3],
1196                     mbrsp->list[index].bssDesc.bssid[4], mbrsp->list[index].bssDesc.bssid[5]);
1197 }
1198 
1199 
1200 // Releases the scan target lock.
MBi_UnlockScanTarget(void)1201 static void MBi_UnlockScanTarget(void)
1202 {
1203     if (mbrsp->nowScanTargetFlag == 0)
1204     {
1205         return;
1206     }
1207 
1208     if (sUnlockFunc != NULL)
1209     {
1210         sUnlockFunc();
1211     }
1212     mbrsp->scanCountUnit = MB_SCAN_COUNT_UNIT_NORMAL;
1213     mbrsp->nowScanTargetFlag = 0;
1214     mbrsp->notFoundLockTargetCount = 0;
1215 
1216     MB_DEBUG_OUTPUT(" unlock target\n");
1217 }
1218 
1219 
1220 // Completely deletes the received game information (also deletes the valid game information flag)
MB_DeleteRecvGameInfo(int index)1221 void MB_DeleteRecvGameInfo(int index)
1222 {
1223     mbrsp->usefulGameInfoFlag &= ~(0x0001 << index);
1224     mbrsp->validGameInfoFlag &= ~(0x0001 << index);
1225     MI_CpuClear16(&mbrsp->list[index], sizeof(MBGameInfoRecvList));
1226 }
1227 
1228 
1229 // Deletes the received game information, except for bssDesc.
MB_DeleteRecvGameInfoWithoutBssdesc(int index)1230 void MB_DeleteRecvGameInfoWithoutBssdesc(int index)
1231 {
1232     mbrsp->usefulGameInfoFlag &= ~(0x0001 << index);
1233     mbrsp->validGameInfoFlag &= ~(0x0001 << index);
1234     mbrsp->list[index].getFlagmentFlag = 0;
1235     mbrsp->list[index].allFlagmentFlag = 0;
1236     mbrsp->list[index].getPlayerFlag = 0;
1237     mbrsp->list[index].linkLevel = 0;
1238     MI_CpuClear16(&(mbrsp->list[index].gameInfo), sizeof(MBGameInfo));
1239 }
1240 
1241 // Gets a pointer to a received parent information structure.
MB_GetGameInfoRecvList(int index)1242 MBGameInfoRecvList *MB_GetGameInfoRecvList(int index)
1243 {
1244     // Returns NULL if there is no valid data
1245     if ((mbrsp->usefulGameInfoFlag & (0x01 << index)) == 0)
1246     {
1247         return NULL;
1248     }
1249 
1250     return &mbrsp->list[index];
1251 }
1252 
1253 
1254 //=========================================================
1255 // User volatile data settings
1256 //=========================================================
1257 
1258 /*---------------------------------------------------------------------------*
1259   Name:         MB_SetSendVolatileCallback
1260 
1261   Description:  Sets the multiboot beacon-transmission callback.
1262 
1263   Arguments:    callback:    The callback function for a completed transmission.
1264                             The callback is invoked whenever data is sent.
1265                 timing:     The timing for issuing the callback.
1266 
1267   Returns:      None.
1268  *---------------------------------------------------------------------------*/
MB_SetSendVolatCallback(MBSendVolatCallbackFunc callback,u32 timming)1269 void MB_SetSendVolatCallback(MBSendVolatCallbackFunc callback, u32 timming)
1270 {
1271     OSIntrMode enabled = OS_DisableInterrupts();
1272 
1273     sSendVolatCallback = callback;
1274     sSendVolatCallbackTimming = timming;
1275 
1276     (void)OS_RestoreInterrupts(enabled);
1277 }
1278 
1279 
1280 
1281 /*---------------------------------------------------------------------------*
1282   Name:         MB_SetUserVolatData
1283 
1284   Description:  Sets user data in an available region of a multiboot beacon.
1285 
1286   Arguments:    ggid:     Specifies the ggid of the program that was set by MB_RegisterFile, and attaches user data to this file's beacon.
1287 
1288                 userData:    Pointer to the user data being set.
1289                 size:        Size of the user data being set. (8 bytes maximum)
1290 
1291   Returns:      None.
1292  *---------------------------------------------------------------------------*/
MB_SetUserVolatData(u32 ggid,const u8 * userData,u32 size)1293 void MB_SetUserVolatData(u32 ggid, const u8 *userData, u32 size)
1294 {
1295     MBGameInfo *gameInfo;
1296 
1297     SDK_ASSERT(size <= MB_USER_VOLAT_DATA_SIZE);
1298     SDK_NULL_ASSERT(userData);
1299 
1300     gameInfo = mbss.gameInfoListTop;
1301     if (gameInfo == NULL)
1302     {
1303         return;
1304     }
1305 
1306     while (gameInfo->ggid != ggid)
1307     {
1308         if (gameInfo == NULL)
1309         {
1310             return;
1311         }
1312         gameInfo = gameInfo->nextp;
1313     }
1314 
1315     {
1316         u32     i;
1317 
1318         OSIntrMode enabled = OS_DisableInterrupts();
1319 
1320         for (i = 0; i < size; i++)
1321         {
1322             gameInfo->volat.userVolatData[i] = userData[i];
1323         }
1324 
1325         (void)OS_RestoreInterrupts(enabled);
1326     }
1327 }
1328 
1329 /*---------------------------------------------------------------------------*
1330   Name:         MB_GetUserVolatData
1331 
1332   Description:  Gets the user data in an available region of a beacon.
1333 
1334   Arguments:    gameInfo:    Pointer to the gameInfo parameter that will be obtained at Scan time.
1335 
1336   Returns:      Pointer to the user data.
1337  *---------------------------------------------------------------------------*/
MB_GetUserVolatData(const WMGameInfo * gameInfo)1338 void   *MB_GetUserVolatData(const WMGameInfo *gameInfo)
1339 {
1340     MbBeacon *beacon;
1341 
1342     SDK_NULL_ASSERT(gameInfo);
1343 
1344     if (!(gameInfo->attribute & WM_ATTR_FLAG_MB))
1345     {
1346         return NULL;
1347     }
1348 
1349     beacon = (MbBeacon *) (gameInfo->userGameInfo);
1350 
1351     if (beacon->dataAttr != MB_BEACON_DATA_ATTR_VOLAT)
1352     {
1353         return NULL;
1354     }
1355 
1356     return beacon->data.volat.userVolatData;
1357 }
1358