1 /*---------------------------------------------------------------------------*
2   Project:  TwlSDK - WM - demos.Twl
3   File:     wh.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-09-17#$
14   $Rev: 8557 $
15   $Author: nishimoto_takashi $
16  *---------------------------------------------------------------------------*/
17 
18 #include <nitro.h>
19 #include <nitro/wm.h>
20 #include <nitro/cht.h>
21 
22 #include "wh.h"
23 
24 /*
25   wh.c : Wireless Manager related Wrapper
26 
27   -Internal description for users
28 
29   The WM API implements the following three communication formats, in order of degree of specialization.
30 
31   - General MP communication
32   - Data sharing
33   - Key sharing
34 
35 
36   These are not mutually exclusive. Key sharing, for example, is a method that uses data sharing, and although data sharing is just a means of sharing data using MP communication, we broke things down into these three levels for the sake of explanation.
37 
38 
39 
40 
41   "General MP communication" refers to a communications mode at the multi-poll protocol level, and can be briefly summarized as performing the following steps for a single communication cycle.
42 
43 
44   (1) Broadcasting of data by the parent to all the children
45   (2) Replying from each child
46   (3) The parent broadcasts notification that the communication cycle has ended.
47 
48 
49 
50   Data sharing is a mode where parent devices get data from all connected children (step 2, above) and then, after including their own portion, distribute that as share data to all children (step 1, above).
51 
52 
53 
54 
55   Key sharing is where the data shared in data sharing is an array of key data for each device.
56 
57 
58 
59   1) Overview of communication processing
60 
61   When wireless LAN function is implemented, it is the ARM7 processor that does the actual work.
62 
63 
64 
65 All send, receive, and other requests from the ARM9 must therefore pass through the ARM7. As a result, nearly all WM functions on the ARM9 are asynchronous and basic processing proceeds approximately as follows.
66   1. A function for writing ARM7 requests to the FIFO is called
67   2. The system that obtained the results returned by the ARM7 will invoke the callback function (specified in step 1)
68 
69 
70 
71 
72   In this sample's implementation, the two functions needed are considered as one set that indicates the status of wireless LAN functionality. Communication processes occur in creating links to that status. (When we refer to WH status, hereafter, it will indicate the wireless LAN status.)
73 
74 
75 
76 
77 
78   The names of functions in this source correspond to their respective WH states, as shown below.
79 
80   WH_StateInXXXXXX   - Start function for the WH state XXXXXX.
81   WH_StateOutXXXXXX  - Callback function that receives completion notifications for the WH state XXXXXX.
82 
83 
84 
85 
86   2) Transitions between WH states
87 
88   A callback function that should automatically transition to the next WH state is configured to call a function to start transitioning to that state when processing has finished.
89 
90   (The state transition basically works from the top to bottom in the source.)
91 
92   All the WH state names, and their mutual sequence transition relationships, are as follows.
93 
94 
95   - Initialization sequence
96   (WH_Initialize function)
97   ��
98   Initialize
99 
100   - Parent communication preparation sequence
101   (WH_Connect function)
102   ��
103   SetParentParam
104   ��
105   StartParent
106   ��
107   StartParentMP
108   ��
109   (**)
110   ��
111   StartParentKeyShare
112 
113   Note: If MP connection mode (or DS connection mode) is specified in WH_Connect, end at (**).
114 
115 
116   - Parent end sequence
117   (WH_Finalize function)
118   ��
119   (EndParentKeyShare)
120   ��
121   EndParentMP
122   ��
123   EndParent
124 
125   - Child communication preparation sequence
126   (WH_Connect function)
127   ��
128   StartScan
129   ��
130   EndScan
131   ��
132   StartChild
133   ��
134   StartChildMP
135   ��
136   (**)
137   ��
138   StartChildKeyShare
139 
140   Note: If MP connection mode (or DS connection mode) is specified in WH_Connect, end at (**).
141 
142 
143   - Child end sequence
144   (WH_Finalize function)
145   ��
146   (EndChildKeyShare)
147   ��
148   EndChildMP
149   ��
150   EndChild
151 
152   Be careful here because the callback function for each WH state will not necessarily be called only when that WH state ends.
153 
154 
155   For example, the WH_StateOutStartParentMP function, which is a callback for the StartParentMP WH status, is called not only when StartMP ends but also in situations such as when the MP sequence is complete. (Refer also to comments within the function itself.)
156 
157 
158 
159 
160   3) Actual sending and receiving operations
161 
162   Generally, with this source, three communications methods are implemented: MP communications, data sharing, and key sharing. Several of these are carried out, so data sending and receiving methods differ for each format.
163 
164 
165 
166   For general MP communication, the following callbacks need to be configured at initialization.
167 
168 
169   WH_SetReceiver(WHReceiverFunc proc);
170 
171   When data is received, it is passed to the callback function set by the received content when received.
172 
173   Data transmission is executed with WH_SendData.
174   Make sure the transmission data memory is not overwritten until the callback set with the WH_SendData function is called.
175 
176 
177   With data sharing, internal updating is carried out at the same time the the WH_StepDS function is called and data is passed, and data is fetched with WH_GetSharedDataAdr.
178 
179 
180   With key sharing communication, key data is fetched with the WH_GetKeySet function.
181   (Processing corresponding to WH_StepDS is carried out internally.
182   The library takes care of sending key data that needs to be sent, so nothing in particular has to be done.)
183 
184 
185   4) Errors and recovering
186 
187   This implementation takes the following course of action.
188 
189   - High-level functions use return values to determine whether there is an error.
190     TRUE is determined to be success, and FALSE to be failure.
191   - More detailed error codes are stored in sErrCode.
192   - sSysState will change to WH_SYSSTATE_ERROR when processing reaches a state from which it cannot continue (such as when an operation is required), and that is detected.
193 
194 
195 
196   Some applications may need to use a callback function or OS_SendMessage to report an error, but this is not expressly supported by this implementation.
197   (It is probably adequate to rewrite the WH_SetError function if the source is used elsewhere.)
198 
199 
200 
201   Also, for "well-behaved" disconnection (recovery) processing, we recommended that you explicitly call WM_Disconnect or a similar function whenever possible after a state ends.
202 
203    This implementation has prepared the WH_Finalize function to perform a "well-behaved termination."
204    This function will branch off to various shutdown processes (at least whenever possible) depending on the current state.
205 
206 
207 
208   5) Guideline compliance
209 
210   Comments are attached to code that is required for guideline compliance.
211   (Note that processing to handle guideline rules may also be located outside of this file.
212    Relevant locations are accompanied by a comment with the string 'GUIDELINE'; use these for reference.)
213 
214  */
215 
216 /* ======================================================================
217    Static contents
218    ====================================================================== */
219 
220 static WMParentParam sParentParam ATTRIBUTE_ALIGN(32);
221 
222 /*  The values below are configured throughout the code.
223 static WMParentParam sParentParam ATTRIBUTE_ALIGN(32) =
224 {
225     Specify user definition data here if to be used in the beacon.
226     // To display a parent device's nickname on the child device's parent selection screen (or for some other situation), set the information here and the parent will convey it to the child.
227     //
228     NULL,                         // userGameInfo
229     0,                            // userGameInfoLength
230     0,                            // padding
231     // The ggid is used in identifying the game loop.
232     // A value allocated by the game is used here.
233     0,
234     // The tgid is used to identify the temporary group.
235     // A different value is needed each time activity is started as the parent device.
236     // In this source, it is configured in the WH_Initialize function.
237     0x0001,                       // tgid
238     //  Designate whether or not to accept the new connection from the child device.
239     1,                            // entryFlag
240     // Designate the maximum number of connectable child devices
241     WH_CHILD_MAX,                 // maxEntry
242     //  Set to zero when not doing multiboot
243     0,                            // multiBootFlag
244     // If KS_Flag is set to 1, key sharing correction will automatically be placed in parentMaxSize and childMaxSize when a connection is made.
245     //
246     // Even when key sharing is in use, a value of 0 is acceptable if parentMaxSize and childMaxSize are accurately calculated and specified.
247     //
248     0,                            // KS_Flag
249     // In order to maintain compatibility with past versions, this is currently ignored in the prepared fields.
250     0,                            // CS_Flag
251     The interval of the beacon sent by the parent. [ms]
252     // Values that have been appropriately scattered by WM_GetDispersionBeaconPeriod() are used during actual startup, but they are approximately 200[ms].
253     //
254     200,                          // beaconPeriod (millisec)
255     // This is a reserved region
256     {0},                           // rsv1
257     {0},                           // rsv2
258     // This is the wireless channel where the parent device waits for the child device.
259     WH_DEFAULT_CHANNEL ,          // channel
260     // Appropriate values have been set as maximum values in the members below
261     // parentMaxSize - the maximum size of the data the parent device sends
262     WH_PARENT_MAX_SIZE,
263     // childMaxSize - the maximum data size the child device sends
264     WH_CHILD_MAX_SIZE,
265 };
266 */
267 
268 // The wh state (This is different from the WH state. It can only be referenced externally.)
269 static int sSysState = WH_SYSSTATE_STOP;
270 
271 // Connection mode (set externally, not touched in this source)
272 static int sConnectMode;
273 
274 // The data receiving user function in MP communication mode
275 static WHReceiverFunc sReceiverFunc;
276 
277 // User function for determining connection permission
278 static WHJudgeAcceptFunc sJudgeAcceptFunc;
279 
280 // Own aid enters (the child may change during disconnect or reconnect)
281 static u16 sMyAid;
282 
283 // Stores the bitmap showing the connection state
284 static u16 sConnectBitmap;
285 
286 // For storing the error code
287 static int sErrCode;
288 
289 // For random numbers
290 static u32 sRand;
291 
292 /* For determining the communications usage rate (used in WH_StartMeasureChannel and WH_GetMeasureChannel) */
293 static u16 sChannel;
294 static u16 sChannelBusyRatio;
295 static u16 sChannelBitmap;
296 
297 /* System work region buffer for WM */
298 static u8 sWmBuffer[WM_SYSTEM_BUF_SIZE] ATTRIBUTE_ALIGN(32);
299 // Send and receive buffer used internally and its size
300 static u8 sSendBuffer[MATH_MAX(WH_PARENT_SEND_BUFFER_SIZE, WH_CHILD_SEND_BUFFER_SIZE)]
301 ATTRIBUTE_ALIGN(32);
302 static u8 sRecvBuffer[MATH_MAX(WH_PARENT_RECV_BUFFER_SIZE, WH_CHILD_RECV_BUFFER_SIZE)]
303 ATTRIBUTE_ALIGN(32);
304 static s32 sSendBufferSize;
305 static s32 sRecvBufferSize;
306 
307 
308 /* For parent device search */
309 static WMBssDesc sBssDesc ATTRIBUTE_ALIGN(32);
310 static u8 sScanBuf[WM_SIZE_SCAN_EX_BUF] ATTRIBUTE_ALIGN(32);
311 static WMScanExParam sScanExParam ATTRIBUTE_ALIGN(32);
312 static WHStartScanCallbackFunc sScanCallback;
313 static u16 sChannelIndex;
314 static u16 sAutoConnectFlag;
315 
316 static BOOL sPictoCatchFlag = FALSE;
317 
318 /* Settings used for the parent connection */
319 static u8 sConnectionSsid[WM_SIZE_CHILD_SSID];
320 
321 /* For WEP settings */
322 static WHParentWEPKeyGeneratorFunc sParentWEPKeyGenerator = NULL;
323 static WHChildWEPKeyGeneratorFunc sChildWEPKeyGenerator = NULL;
324 static u16 sWEPKey[20 / sizeof(u16)] ATTRIBUTE_ALIGN(32);
325 
326 /* For data sharing */
327 static WMDataSharingInfo sDSInfo ATTRIBUTE_ALIGN(32);
328 static WMDataSet sDataSet ATTRIBUTE_ALIGN(32);
329 static WMKeySetBuf sWMKeySetBuf ATTRIBUTE_ALIGN(32);
330 
331 /* WH initialization flag */
332 static u16 whInitialized = 0;
333 
334 /* Callback for Indication notification of WM */
335 static WMCallbackFunc sIndicationCallback = NULL;
336 
337 /* debug output hook function */
338 static void (*wh_trace) (const char *, ...) =
339 #if !defined(SDK_FINALROM)
340         OS_TPrintf;
341 #else
342         NULL;
343 #endif
344 
345 
346 // * WH members, extended for compatibility with WC.
347 static void (*sStateCallback)(int state, int prev) = NULL;
348 static BOOL sDataSharingDoubleMode = TRUE;
349 static WMCallbackFunc sPortExtraCallback = NULL;
350 
351 #if defined(WM_DEMO_WIRELESS_SHARED_WC_WH_CONFIG_H_)
352 // Members to preserve behavior that is identical to WC.
353 
354 typedef struct WHCompatibleInfoForWC
355 {
356     WMParentParam               parentParam ATTRIBUTE_ALIGN(32);
357     OSThreadQueue               queue[1];
358     WCPictoCatchCallbackFunc    pictoCatchCallback;
359     BOOL                        useDS;
360     WCStatus                    wcStatus;
361     WCStatus                    wcTarget;
362     u16                         framePeriod;
363     u16                         targetChannel;
364     u16                         tmpTgid;
365     u8                          padding[2];
366 }
367 WHCompatibleInfoForWC;
368 
369 static WHCompatibleInfoForWC infoForWC[1] ATTRIBUTE_ALIGN(32);
370 
371 static const int    parentRecvBufferSize = WH_PARENT_RECV_BUFFER_SIZE;
372 static const int    parentSendBufferSize = WH_PARENT_SEND_BUFFER_SIZE;
373 static const int    childRecvBufferSize = WH_CHILD_RECV_BUFFER_SIZE;
374 static const int    childSendBufferSize = WH_CHILD_SEND_BUFFER_SIZE;
375 #undef  WH_PARENT_RECV_BUFFER_SIZE
376 #define WH_PARENT_RECV_BUFFER_SIZE  parentRecvBufferSize
377 #undef  WH_PARENT_SEND_BUFFER_SIZE
378 #define WH_PARENT_SEND_BUFFER_SIZE  parentSendBufferSize
379 #undef  WH_CHILD_RECV_BUFFER_SIZE
380 #define WH_CHILD_RECV_BUFFER_SIZE   childRecvBufferSize
381 #undef  WH_CHILD_SEND_BUFFER_SIZE
382 #define WH_CHILD_SEND_BUFFER_SIZE   childSendBufferSize
383 #undef  WH_PLAYER_MAX
384 #define WH_PLAYER_MAX             (infoForWC->parentParam.maxEntry + 1)
385 #undef  WH_CHILD_MAX
386 #define WH_CHILD_MAX              infoForWC->parentParam.maxEntry
387 #undef  WH_DS_DATA_SIZE
388 #define WH_DS_DATA_SIZE           infoForWC->parentParam.childMaxSize
389 #undef  WH_PARENT_MAX_SIZE
390 #define WH_PARENT_MAX_SIZE        infoForWC->parentParam.parentMaxSize
391 #undef  WH_CHILD_MAX_SIZE
392 #define WH_CHILD_MAX_SIZE         infoForWC->parentParam.childMaxSize
393 #undef  WH_MP_FREQUENCY
394 #define WH_MP_FREQUENCY           (u16)(infoForWC->parentParam.CS_Flag ? 0 : 1)
395 
396 #endif // WM_DEMO_WIRELESS_SHARED_WC_WH_CONFIG_H_
397 
398 
399 /* ======================================================================
400    State functions
401    ====================================================================== */
402 
403 // Random number macro
404 #define RAND()  ( sRand = sRand * 69069UL + 12345 )
405 #define RAND_INIT(x) ( sRand = (u32)(x) )
406 
407 #define WH_MAX(a, b) ( ((a) > (b)) ? (a) : (b) )
408 
409 /* Function that receives irregular notifications */
410 static void WH_IndicateHandler(void *arg);
411 
412 /* (Stateless) -> READY -> STOP -> IDLE */
413 static BOOL WH_StateInInitialize(void);
414 
415 #ifndef WH_USE_DETAILED_INITIALIZE
416 static void WH_StateOutInitialize(void *arg);
417 #else
418 static BOOL WH_StateInEnable(void);
419 static void WH_StateOutEnable(void *arg);
420 static BOOL WH_StateInPowerOn(void);
421 static void WH_StateOutPowerOn(void *arg);
422 #endif
423 
424 /* IDLE -> MEASURECHANNEL -> IDLE */
425 static u16 WH_StateInMeasureChannel(u16 channel);
426 static void WH_StateOutMeasureChannel(void *arg);
427 static WMErrCode WHi_MeasureChannel(WMCallbackFunc func, u16 channel);
428 static s16 SelectChannel(u16 bitmap);
429 
430 
431 /* IDLE -> PARENT -> MP-PARENT */
432 static BOOL WH_StateInSetParentParam(void);
433 static void WH_StateOutSetParentParam(void *arg);
434 static BOOL WH_StateInSetParentWEPKey(void);
435 static void WH_StateOutSetParentWEPKey(void *arg);
436 static BOOL WH_StateInStartParent(void);
437 static void WH_StateOutStartParent(void *arg);
438 static BOOL WH_StateInStartParentMP(void);
439 static void WH_StateOutStartParentMP(void *arg);
440 
441 /* IDLE -> SCAN */
442 static BOOL WH_StateInStartScan(void);
443 static void WH_StateOutStartScan(void *arg);
444 
445 /* SCAN -> IDLE */
446 static BOOL WH_StateInEndScan(void);
447 static void WH_StateOutEndScan(void *arg);
448 
449 /* IDLE -> CHILD -> MP-CHILD */
450 static BOOL WH_StateInSetChildWEPKey(void);
451 static void WH_StateOutSetChildWEPKey(void *arg);
452 static BOOL WH_StateInStartChild(void);
453 static void WH_StateOutStartChild(void *arg);
454 static BOOL WH_StateInStartChildMP(void);
455 static void WH_StateOutStartChildMP(void *arg);
456 
457 /* MP + key sharing */
458 static BOOL WH_StateInStartParentKeyShare(void);
459 static BOOL WH_StateInEndParentKeyShare(void);
460 static BOOL WH_StateInStartChildKeyShare(void);
461 static BOOL WH_StateInEndChildKeyShare(void);
462 
463 /* MP + SetMPData */
464 static BOOL WH_StateInSetMPData(const void *data, u16 datasize, WHSendCallbackFunc callback);
465 static void WH_StateOutSetMPData(void *arg);
466 static void WH_PortReceiveCallback(void *arg);
467 
468 /* MP-PARENT -> IDLE */
469 static BOOL WH_StateInEndParentMP(void);
470 static void WH_StateOutEndParentMP(void *arg);
471 static BOOL WH_StateInEndParent(void);
472 static void WH_StateOutEndParent(void *arg);
473 static BOOL WH_StateInDisconnectChildren(u16 bitmap);
474 static void WH_StateOutDisconnectChildren(void *arg);
475 
476 /* MP-CHILD -> IDLE */
477 static BOOL WH_StateInEndChildMP(void);
478 static void WH_StateOutEndChildMP(void *arg);
479 static BOOL WH_StateInEndChild(void);
480 static void WH_StateOutEndChild(void *arg);
481 
482 /* IDLE -> STOP -> READY -> (stateless) */
483 static BOOL WH_StateInPowerOff(void);
484 static void WH_StateOutPowerOff(void *arg);
485 static BOOL WH_StateInDisable(void);
486 static void WH_StateOutDisable(void *arg);
487 static void WH_StateOutEnd(void *arg);
488 
489 /* X -> IDLE */
490 static BOOL WH_StateInReset(void);
491 static void WH_StateOutReset(void *arg);
492 
493 
494 /* ======================================================================
495    Debug codes
496    ====================================================================== */
497 #define WMHIGH_DEBUG
498 
499 #if defined(WMHIGH_DEBUG)
500 
501 #define WH_TRACE    if(wh_trace) wh_trace
502 
503 #define WH_TRACE_STATE OS_TPrintf("%s sSysState = %d\n", __func__, sSysState)
504 
505 #define WH_REPORT_FAILURE(result)                \
506     do{ OS_TPrintf("Failed in %s, %s = %s\n",      \
507                   __func__,                      \
508                   #result,                       \
509                   WH_GetWMErrCodeName(result));  \
510         WH_SetError(result); }while(0)
511 
512 #define WH_ASSERT(exp) \
513     (void) ((exp) || (OSi_Panic(__FILE__, __LINE__, "Failed assertion " #exp), 0))
514 
515 #else  /* defined(WMHIGH_DEBUG) */
516 
517 #define WH_TRACE_STATE                 /* */
518 #define WH_TRACE(...)               ((void)0)
519 #define WH_REPORT_FAILURE(result)   WH_SetError(result)
520 #define WH_ASSERT(exp)              ((void) 0)
521 
522 #endif
523 
524 
525 
526 #if defined(WMHIGH_DEBUG)
527 static const char *sStateNames[] = {
528     "WM_STATE_READY",
529     "WM_STATE_STOP",
530     "WM_STATE_IDLE",
531     "WM_STATE_CLASS1",
532     "WM_STATE_TESTMODE",
533     "WM_STATE_SCAN",
534     "WM_STATE_CONNECT",
535     "WM_STATE_PARENT",
536     "WM_STATE_CHILD",
537     "WM_STATE_MP_PARENT",
538     "WM_STATE_MP_CHILD",
539     "WM_STATE_DCF_CHILD",
540 };
541 
WH_GetWMErrCodeName(int result)542 static const char *WH_GetWMErrCodeName(int result)
543 {
544     static const char *errnames[] = {
545         "WM_ERRCODE_SUCCESS",
546         "WM_ERRCODE_FAILED",
547         "WM_ERRCODE_OPERATING",
548         "WM_ERRCODE_ILLEGAL_STATE",
549         "WM_ERRCODE_WM_DISABLE",
550         "WM_ERRCODE_NO_DATASET",
551         "WM_ERRCODE_INVALID_PARAM",
552         "WM_ERRCODE_NO_CHILD",
553         "WM_ERRCODE_FIFO_ERROR",
554         "WM_ERRCODE_TIMEOUT",
555         "WM_ERRCODE_SEND_QUEUE_FULL",
556         "WM_ERRCODE_NO_ENTRY",
557         "WM_ERRCODE_OVER_MAX_ENTRY",
558         "WM_ERRCODE_INVALID_POLLBITMAP",
559         "WM_ERRCODE_NO_DATA",
560         "WM_ERRCODE_SEND_FAILED",
561         "WM_ERRCODE_DCF_TEST",
562         "WM_ERRCODE_WL_INVALID_PARAM",
563         "WM_ERRCODE_WL_LENGTH_ERR",
564         "WM_ERRCODE_FLASH_ERROR",
565 
566         "WH_ERRCODE_DISCONNECTED",
567         "WH_ERRCODE_PARENT_NOT_FOUND",
568         "WH_ERRCODE_NO_RADIO",
569     };
570 
571     if (0 <= result && result < sizeof(errnames) / sizeof(char *))
572     {
573         return errnames[result];
574     }
575     else
576     {
577         return "N/A";
578     }
579 }
580 
WH_GetWMStateCodeName(u16 code)581 static const char *WH_GetWMStateCodeName(u16 code)
582 {
583     static const char *statenames[] = {
584         "WM_STATECODE_PARENT_START",
585         "N/A",
586         "WM_STATECODE_BEACON_SENT",
587         "WM_STATECODE_SCAN_START",
588         "WM_STATECODE_PARENT_NOT_FOUND",
589         "WM_STATECODE_PARENT_FOUND",
590         "WM_STATECODE_CONNECT_START",
591         "WM_STATECODE_CONNECTED",
592         "WM_STATECODE_BEACON_LOST",
593         "WM_STATECODE_DISCONNECTED",
594         "WM_STATECODE_MP_START",
595         "WM_STATECODE_MPEND_IND",
596         "WM_STATECODE_MP_IND",
597         "WM_STATECODE_MPACK_IND",
598         "WM_STATECODE_DCF_START",
599         "WM_STATECODE_DCF_IND",
600         "WM_STATECODE_BEACON_RECV",
601         "WM_STATECODE_DISASSOCIATE",
602         "WM_STATECODE_REASSOCIATE",
603         "WM_STATECODE_AUTHENTICATE",
604         "WM_STATECODE_PORT_SEND",
605         "WM_STATECODE_PORT_RECV",
606         "WM_STATECODE_FIFO_ERROR",
607         "WM_STATECODE_INFORMATION",
608         "WM_STATECODE_UNKNOWN",
609         "WM_STATECODE_PORT_INIT",
610         "WM_STATECODE_DISCONNECTED_FROM_MYSELF",
611     };
612 
613     if (0 <= code && code < sizeof(statenames) / sizeof(char *))
614     {
615         return statenames[code];
616     }
617     else
618     {
619         return "N/A";
620     }
621 }
622 
WH_GetWMApiidName(u16 apiid)623 static const char *WH_GetWMApiidName(u16 apiid)
624 {
625     static const char *apinames[] = {
626         "WM_APIID_INITIALIZE",
627         "WM_APIID_RESET",
628         "WM_APIID_END",
629 
630         "WM_APIID_ENABLE",
631         "WM_APIID_DISABLE",
632         "WM_APIID_POWER_ON",
633         "WM_APIID_POWER_OFF",
634 
635         "WM_APIID_SET_P_PARAM",
636         "WM_APIID_START_PARENT",
637         "WM_APIID_END_PARENT",
638         "WM_APIID_START_SCAN",
639         "WM_APIID_END_SCAN",
640         "WM_APIID_START_CONNECT",
641         "WM_APIID_DISCONNECT",
642         "WM_APIID_START_MP",
643         "WM_APIID_SET_MP_DATA",
644         "WM_APIID_END_MP",
645         "WM_APIID_START_DCF",
646         "WM_APIID_SET_DCF_DATA",
647         "WM_APIID_END_DCF",
648         "WM_APIID_SET_WEPKEY",
649         "WM_APIID_START_KS",
650         "WM_APIID_END_KS",
651         "WM_APIID_GET_KEYSET",
652         "WM_APIID_SET_GAMEINFO",
653         "WM_APIID_SET_BEACON_IND",
654         "WM_APIID_START_TESTMODE",
655         "WM_APIID_STOP_TESTMODE",
656         "WM_APIID_VALARM_MP",
657         "WM_APIID_SET_LIFETIME",
658         "WM_APIID_MEASURE_CHANNEL",
659         "WM_APIID_INIT_W_COUNTER",
660         "WM_APIID_GET_W_COUNTER",
661         "WM_APIID_SET_ENTRY",
662         "WM_APIID_AUTO_DEAUTH",
663         "WM_APIID_SET_MP_PARAMETER",
664         "WM_APIID_SET_BEACON_PERIOD",
665         "WM_APIID_AUTO_DISCONNECT",
666 
667         "WM_APIID_KICK_MP_PARENT",
668         "WM_APIID_KICK_MP_CHILD",
669         "WM_APIID_KICK_MP_RESUME",
670     };
671     static const char *apinames_indicates[] = {
672         "WM_APIID_INDICATION",
673         "WM_APIID_PORT_SEND",
674         "WM_APIID_PORT_RECV",
675         "WM_APIID_READ_STATUS"
676     };
677     static const char *apiname_unknown = "WM_APIID_UNKNOWN";
678 
679     if (0 <= apiid && apiid < sizeof(apinames) / sizeof(char *))
680     {
681         return apinames[apiid];
682     }
683     else if (WM_APIID_INDICATION <= apiid &&
684              apiid < WM_APIID_INDICATION + sizeof(apinames_indicates) / sizeof(char *))
685     {
686         return apinames_indicates[apiid - WM_APIID_INDICATION];
687     }
688     else if (apiid == WM_APIID_UNKNOWN)
689     {
690         return apiname_unknown;
691     }
692     else
693     {
694         return "N/A";
695     }
696 }
697 
WH_OutputWMState(void)698 static void WH_OutputWMState(void)
699 {
700     WMStatus s;
701 
702     if (WM_ReadStatus(&s) == WM_ERRCODE_SUCCESS)
703     {
704         WH_TRACE("state = %s\n", WH_GetWMStateCodeName(s.state));
705         WH_TRACE("apiid = %s\n", WH_GetWMApiidName(s.BusyApiid));
706     }
707     else
708     {
709         WH_TRACE("WM not Initialized\n");
710     }
711 }
712 
WH_OutputBitmap(u16 bitmap)713 static void WH_OutputBitmap(u16 bitmap)
714 {
715     u16     i;
716     for (i = 15; i >= 0; --i)
717     {
718         if ((bitmap >> i) & 0x01)
719         {
720             OS_TPrintf("o");
721         }
722         else
723         {
724             OS_TPrintf("-");
725         }
726     }
727 
728     OS_TPrintf("\n");
729 }
730 
WH_ChangeSysState(int state)731 static void WH_ChangeSysState(int state)
732 {
733     static const char *statenames[] = {
734         "WH_SYSSTATE_STOP",
735         "WH_SYSSTATE_IDLE",
736         "WH_SYSSTATE_SCANNING",
737         "WH_SYSSTATE_BUSY",
738         "WH_SYSSTATE_CONNECTED",
739         "WH_SYSSTATE_DATASHARING",
740         "WH_SYSSTATE_KEYSHARING",
741         "WH_SYSSTATE_MEASURECHANNEL",
742         "WH_SYSSTATE_CONNECT_FAIL",
743         "WH_SYSSTATE_ERROR",
744         "WH_SYSSTATE_FATAL",
745     };
746     int     prev = sSysState;
747     WH_TRACE("%s -> ", statenames[sSysState]);
748     sSysState = state;
749     WH_TRACE("%s\n", statenames[sSysState]);
750     if (sStateCallback)
751     {
752         (*sStateCallback)(sSysState, prev);
753     }
754 }
755 
756 #else
757 
758 #define WH_GetWMErrCodeName(result)    ("")
759 #define WH_GetWMStateCodeName(result)  ("")
760 #define WH_GetWMApiidName(result)      ("")
761 
WH_OutputWMState(void)762 static void WH_OutputWMState(void)
763 {;
764 }
WH_OutputBitmap(void)765 static void WH_OutputBitmap(void)
766 {;
767 }
768 
WH_ChangeSysState(int state)769 static void WH_ChangeSysState(int state)
770 {
771     sSysState = state;
772 }
773 
774 #endif
775 
WH_SetError(int code)776 static void WH_SetError(int code)
777 {
778     // Does not overwrite if the system is already in an ERROR state.
779     if (sSysState == WH_SYSSTATE_ERROR || sSysState == WH_SYSSTATE_FATAL)
780     {
781         return;
782     }
783 
784     sErrCode = code;
785 }
786 
787 
788 
789 /* ======================================================================
790    State functions
791    ====================================================================== */
792 
793 /* ----------------------------------------------------------------------
794    State: setparentparam
795   ---------------------------------------------------------------------- */
WH_StateInSetParentParam(void)796 static BOOL WH_StateInSetParentParam(void)
797 {
798     // In this state, the game information held by the parent is passed to the ARM7
799     WMErrCode result;
800     WH_TRACE_STATE;
801 
802     WH_ChangeSysState(WH_SYSSTATE_BUSY);
803 
804     result = WM_SetParentParameter(WH_StateOutSetParentParam, &sParentParam);
805     if (result != WM_ERRCODE_OPERATING)
806     {
807         WH_REPORT_FAILURE(result);
808         WH_ChangeSysState(WH_SYSSTATE_ERROR);
809         return FALSE;
810     }
811 
812     return TRUE;
813 }
814 
WH_StateOutSetParentParam(void * arg)815 static void WH_StateOutSetParentParam(void *arg)
816 {
817     WMCallback *cb = (WMCallback *)arg;
818     WH_TRACE_STATE;
819 
820     if (cb->errcode != WM_ERRCODE_SUCCESS)
821     {
822         WH_REPORT_FAILURE(cb->errcode);
823         WH_ChangeSysState(WH_SYSSTATE_ERROR);
824         return;
825     }
826 
827     if (sParentWEPKeyGenerator != NULL)
828     {
829         // If the WEP Key Generator is configured, set the WEP Key
830         if (!WH_StateInSetParentWEPKey())
831         {
832             WH_ChangeSysState(WH_SYSSTATE_ERROR);
833         }
834     }
835     else
836     {
837         // If progress is normal, moves to the StartParent state
838         if (!WH_StateInStartParent())
839         {
840             WH_ChangeSysState(WH_SYSSTATE_ERROR);
841         }
842     }
843 }
844 
WH_StateInSetParentWEPKey(void)845 static BOOL WH_StateInSetParentWEPKey(void)
846 {
847     u16     wepmode;
848     WMErrCode result;
849     WH_TRACE_STATE;
850 
851     WH_ChangeSysState(WH_SYSSTATE_BUSY);
852 
853     wepmode = (*sParentWEPKeyGenerator) (sWEPKey, &sParentParam);
854     result = WM_SetWEPKey(WH_StateOutSetParentWEPKey, wepmode, sWEPKey);
855     if (result != WM_ERRCODE_OPERATING)
856     {
857         WH_REPORT_FAILURE(result);
858         WH_ChangeSysState(WH_SYSSTATE_ERROR);
859         return FALSE;
860     }
861 
862     return TRUE;
863 }
864 
WH_StateOutSetParentWEPKey(void * arg)865 static void WH_StateOutSetParentWEPKey(void *arg)
866 {
867     WMCallback *cb = (WMCallback *)arg;
868     WH_TRACE_STATE;
869 
870     if (cb->errcode != WM_ERRCODE_SUCCESS)
871     {
872         WH_REPORT_FAILURE(cb->errcode);
873         WH_ChangeSysState(WH_SYSSTATE_ERROR);
874         return;
875     }
876 
877     // If progress is normal, moves to the StartParent state
878     if (!WH_StateInStartParent())
879     {
880         WH_ChangeSysState(WH_SYSSTATE_ERROR);
881     }
882 }
883 
884 
885 /* ----------------------------------------------------------------------
886    State: StartParent
887   ---------------------------------------------------------------------- */
WH_StateInStartParent(void)888 static BOOL WH_StateInStartParent(void)
889 {
890     // In this state, the StartParent function is called, and the settings are started for a parent
891 
892     WMErrCode result;
893     WH_TRACE_STATE;
894 
895     if ((sSysState == WH_SYSSTATE_CONNECTED)
896         || (sSysState == WH_SYSSTATE_KEYSHARING) || (sSysState == WH_SYSSTATE_DATASHARING))
897     {
898         // For the above case, the parent settings should have already been set
899         return TRUE;
900     }
901 
902     result = WM_StartParent(WH_StateOutStartParent);
903 
904     if (result != WM_ERRCODE_OPERATING)
905     {
906         WH_REPORT_FAILURE(result);
907         return FALSE;
908     }
909 
910     sMyAid = 0;
911     sConnectBitmap = WH_BITMAP_EMPTY;
912 
913     return TRUE;
914 }
915 
WH_StateOutStartParent(void * arg)916 static void WH_StateOutStartParent(void *arg)
917 {
918     // The callback function set by StartParent will be called for a number of cases, as follows, so they need to be differentiated from each other.
919     // 1) A beacon is sent
920     // 2) A new connection is made to a child
921     // 3) A StartParent ends
922     // 4) A child disconnection is detected
923     //
924 
925     WMStartParentCallback *cb = (WMStartParentCallback *)arg;
926     const u16 target_bitmap = (u16)(1 << cb->aid);
927 
928     if (cb->errcode != WM_ERRCODE_SUCCESS)
929     {
930         WH_REPORT_FAILURE(cb->errcode);
931         WH_ChangeSysState(WH_SYSSTATE_ERROR);
932         return;
933     }
934 
935     switch (cb->state)
936     {
937         //-----------------------------------
938         // Beacon transmission notification
939     case WM_STATECODE_BEACON_SENT:
940         // Ignores the beacon transmission notification
941         break;
942 
943         //-----------------------------------
944         // Child connection notification
945     case WM_STATECODE_CONNECTED:
946         {
947             // The connected child device MAC address is in cb->macAddress.
948             // cb->ssid is the data the child device set in the ssid argument of WM_StartConnect.
949             WH_TRACE("StartParent - new child (aid 0x%x) connected\n", cb->aid);
950             // Checks whether the newly connected child satisfies the conditions for connection permission
951             if (sJudgeAcceptFunc != NULL)
952             {
953                 if (!sJudgeAcceptFunc(cb))
954                 {
955                     WMErrCode result;
956                     // Terminates the connection
957                     result = WM_Disconnect(NULL, cb->aid);
958                     if (result != WM_ERRCODE_OPERATING)
959                     {
960                         WH_REPORT_FAILURE(result);
961                         WH_ChangeSysState(WH_SYSSTATE_ERROR);
962                     }
963                     break;
964                 }
965             }
966             sConnectBitmap |= target_bitmap;
967             if (sPortExtraCallback)
968             {
969                 (*sPortExtraCallback)(arg);
970             }
971         }
972         break;
973 
974         //-----------------------------------
975         // Notifies of a child disconnection
976     case WM_STATECODE_DISCONNECTED:
977         {
978             WH_TRACE("StartParent - child (aid 0x%x) disconnected\n", cb->aid);
979             // The disconnected child device MAC address is in cb->macAddress
980             sConnectBitmap &= ~target_bitmap;
981             if (sPortExtraCallback)
982             {
983                 (*sPortExtraCallback)(arg);
984             }
985         }
986         break;
987 
988         //-----------------------------------
989         // Child has disconnected from itself
990     case WM_STATECODE_DISCONNECTED_FROM_MYSELF:
991         {
992             WH_TRACE("StartParent - child (aid 0x%x) disconnected from myself\n", cb->aid);
993             // Does nothing if the unit disconnects from itself
994             // The disconnected child device MAC address is in cb->macAddress
995         }
996         break;
997 
998         //-----------------------------------
999         // StartParent processing ends
1000     case WM_STATECODE_PARENT_START:
1001         {
1002             // Changes to the MP communication state
1003             if (!WH_StateInStartParentMP())
1004             {
1005                 WH_ChangeSysState(WH_SYSSTATE_ERROR);
1006             }
1007         }
1008         break;
1009 
1010         //-----------------------------------
1011     default:
1012         WH_TRACE("unknown indicate, state = %d\n", cb->state);
1013     }
1014 }
1015 
1016 /* ----------------------------------------------------------------------
1017    State: StartParentMP
1018   ---------------------------------------------------------------------- */
WH_StateInStartParentMP(void)1019 static BOOL WH_StateInStartParentMP(void)
1020 {
1021     // Calls the WM_Start function, and starts a connection using the MP communication protocol
1022 
1023     WMErrCode result;
1024     WH_TRACE_STATE;
1025 
1026     if ((sSysState == WH_SYSSTATE_CONNECTED)
1027         || (sSysState == WH_SYSSTATE_KEYSHARING) || (sSysState == WH_SYSSTATE_DATASHARING))
1028     {
1029         return TRUE;
1030     }
1031 
1032     WH_ChangeSysState(WH_SYSSTATE_CONNECTED);
1033     result = WM_StartMP(WH_StateOutStartParentMP,
1034                         (u16 *)sRecvBuffer,
1035                         (u16)sRecvBufferSize, (u16 *)sSendBuffer, (u16)sSendBufferSize,
1036                         WH_MP_FREQUENCY);
1037 
1038     if (result != WM_ERRCODE_OPERATING)
1039     {
1040         WH_REPORT_FAILURE(result);
1041         return FALSE;
1042     }
1043 
1044     return TRUE;
1045 }
1046 
WH_StateOutStartParentMP(void * arg)1047 static void WH_StateOutStartParentMP(void *arg)
1048 {
1049     // The callback function specified by StartMP will be called in the following four cases, so they need to be differentiated from each other.
1050     // 1) When a mode starts up due to StartMP
1051     // 2) When the MP sequence ends (parent only)
1052     // 3) During MP reception (child only)
1053     // 4) When MP sequence completion notification (ACK receiving) is detected (child only)
1054     //
1055 
1056     WMStartMPCallback *cb = (WMStartMPCallback *)arg;
1057     // WH_TRACE_STATE;
1058 
1059     if (cb->errcode != WM_ERRCODE_SUCCESS)
1060     {
1061         WH_REPORT_FAILURE(cb->errcode);
1062         WH_ChangeSysState(WH_SYSSTATE_ERROR);
1063         return;
1064     }
1065 
1066     switch (cb->state)
1067     {
1068     case WM_STATECODE_MP_START:
1069         // Notification that StartMP has ended normally.
1070         // Hereafter, send and receive are enabled.
1071         if (sConnectMode == WH_CONNECTMODE_KS_PARENT)
1072         {
1073             // Transition to StartParentKeyShare if key-sharing was specified
1074             //
1075             if (sSysState == WH_SYSSTATE_CONNECTED)
1076             {
1077                 // Normal MP connection
1078                 if (!WH_StateInStartParentKeyShare())
1079                 {
1080                     WH_TRACE("WH_StateInStartParentKeyShare failed\n");
1081                     WH_ChangeSysState(WH_SYSSTATE_ERROR);
1082                 }
1083                 return;
1084 
1085             }
1086             else if (sSysState == WH_SYSSTATE_KEYSHARING)
1087             {
1088                 // Appears that the key sharing state is already set
1089                 return;
1090             }
1091         }
1092         else if (sConnectMode == WH_CONNECTMODE_DS_PARENT)
1093         {
1094             // StartDataSharing is called if data sharing is specified.
1095             // This function is a synchronous operating function, so a switch to WH state is not made.
1096             WMErrCode result;
1097             u16     aidBitmap;
1098 
1099             aidBitmap = (u16)((1 << (WH_CHILD_MAX + 1)) - 1);   // Bitmap with the lower WH_CHILD_MAX+1 bit==1
1100             result = WM_StartDataSharing(&sDSInfo, WH_DS_PORT, aidBitmap, WH_DS_DATA_SIZE, sDataSharingDoubleMode);
1101 
1102             if (result != WM_ERRCODE_SUCCESS)
1103             {
1104                 WH_REPORT_FAILURE(result);
1105                 WH_ChangeSysState(WH_SYSSTATE_ERROR);
1106                 return;
1107             }
1108             // WH_TRACE("WM_StartDataSharing OK\n");
1109             WH_ChangeSysState(WH_SYSSTATE_DATASHARING);
1110             if (sPortExtraCallback)
1111             {
1112                 (*sPortExtraCallback)(arg);
1113             }
1114             return;
1115         }
1116 
1117         WH_ChangeSysState(WH_SYSSTATE_CONNECTED);
1118         if (sPortExtraCallback)
1119         {
1120             (*sPortExtraCallback)(arg);
1121         }
1122         break;
1123 
1124     case WM_STATECODE_MPEND_IND:
1125         // Parent receiving compete notification
1126 
1127         // cb->recvBuf accepts the data frame content received from the child device, but for normal data reception set a callback with WM_SetPortCallback.
1128         //
1129         // Data is received internally when data sharing or key sharing is in use, so WM_SetPortCallback does not need to be used.
1130         //
1131         break;
1132 
1133     case WM_STATECODE_MP_IND:
1134     case WM_STATECODE_MPACK_IND:
1135         // The parent should not come here
1136 
1137     default:
1138         WH_TRACE("unknown indicate, state = %d\n", cb->state);
1139         break;
1140     }
1141 }
1142 
1143 /* ----------------------------------------------------------------------
1144   State: StartParentKeyShare
1145   ---------------------------------------------------------------------- */
WH_StateInStartParentKeyShare(void)1146 static BOOL WH_StateInStartParentKeyShare(void)
1147 {
1148     WMErrCode result;
1149     WH_TRACE_STATE;
1150     WH_ChangeSysState(WH_SYSSTATE_KEYSHARING);
1151 
1152     // Calls the WM_StartKeySharing function and starts key sharing
1153     result = WM_StartKeySharing(&sWMKeySetBuf, WH_DS_PORT);
1154 
1155     if (result != WM_ERRCODE_SUCCESS)
1156     {
1157         WH_REPORT_FAILURE(result);
1158         return FALSE;
1159     }
1160 
1161     return TRUE;
1162 }
1163 
1164 /* ----------------------------------------------------------------------
1165    State: EndParentKeyShare
1166   ---------------------------------------------------------------------- */
WH_StateInEndParentKeyShare(void)1167 static BOOL WH_StateInEndParentKeyShare(void)
1168 {
1169     // Calls WM_EndKeySharing and ends key sharing
1170     WMErrCode result;
1171     WH_TRACE_STATE;
1172 
1173     result = WM_EndKeySharing(&sWMKeySetBuf);
1174 
1175     if (result != WM_ERRCODE_SUCCESS)
1176     {
1177         WH_REPORT_FAILURE(result);
1178         return FALSE;
1179     }
1180 
1181     // Automatically starts MP communication termination processing
1182     if (!WH_StateInEndParentMP())
1183     {
1184         WH_TRACE("WH_StateInEndParentMP failed\n");
1185         WH_Reset();
1186         return FALSE;
1187     }
1188 
1189     return TRUE;
1190 }
1191 
1192 /* ----------------------------------------------------------------------
1193    State: EndParentMP
1194   ---------------------------------------------------------------------- */
WH_StateInEndParentMP(void)1195 static BOOL WH_StateInEndParentMP(void)
1196 {
1197     WMErrCode result;
1198     WH_TRACE_STATE;
1199 
1200     // Hereafter, send and receive are disabled
1201     WH_ChangeSysState(WH_SYSSTATE_BUSY);
1202 
1203     result = WM_EndMP(WH_StateOutEndParentMP);
1204     if (result != WM_ERRCODE_OPERATING)
1205     {
1206         WH_REPORT_FAILURE(result);
1207         return FALSE;
1208     }
1209 
1210     return TRUE;
1211 }
1212 
WH_StateOutEndParentMP(void * arg)1213 static void WH_StateOutEndParentMP(void *arg)
1214 {
1215     WMCallback *cb = (WMCallback *)arg;
1216     WH_TRACE_STATE;
1217 
1218     if (cb->errcode != WM_ERRCODE_SUCCESS)
1219     {
1220         WH_REPORT_FAILURE(cb->errcode);
1221         WH_Reset();
1222         return;
1223     }
1224 
1225     // Automatically starts termination processing
1226     if (!WH_StateInEndParent())
1227     {
1228         WH_TRACE("WH_StateInEndParent failed\n");
1229         WH_Reset();
1230         return;
1231     }
1232 }
1233 
1234 /* ----------------------------------------------------------------------
1235    State: EndParent
1236    ---------------------------------------------------------------------- */
WH_StateInEndParent(void)1237 static BOOL WH_StateInEndParent(void)
1238 {
1239     WMErrCode result;
1240     WH_TRACE_STATE;
1241 
1242     // Operation as a parent ends here.
1243     // If there are connected children, parent operations end after the parent severs authentication for each child individually.
1244     //
1245     result = WM_EndParent(WH_StateOutEndParent);
1246     if (result != WM_ERRCODE_OPERATING)
1247     {
1248         WH_REPORT_FAILURE(result);
1249         return FALSE;
1250     }
1251 
1252     return TRUE;
1253 }
1254 
WH_StateOutEndParent(void * arg)1255 static void WH_StateOutEndParent(void *arg)
1256 {
1257     WMCallback *cb = (WMCallback *)arg;
1258     WH_TRACE_STATE;
1259 
1260     if (cb->errcode != WM_ERRCODE_SUCCESS)
1261     {
1262         WH_REPORT_FAILURE(cb->errcode);
1263         return;
1264     }
1265 
1266     // At this point, the parent disconnection processing ends, and the state returns to idle (standby)
1267     WH_ChangeSysState(WH_SYSSTATE_IDLE);
1268 }
1269 
1270 /* ----------------------------------------------------------------------
1271    Name:        WH_ChildConnectAuto
1272    Description: Starts the child device connection sequence.
1273                 However, each type of setting specified with WH_ParentConnect or WH_ChildConnect is left to automatic internal processing.
1274 
1275    Arguments:   mode:     Start MP as the child if WH_CONNECTMODE_MP_CHILD.
1276                           Start DataSharing as the child if WH_CONNECTMODE_DS_CHILD.
1277                           Start KeySharing as the child if WH_CONNECTMODE_KS_CHILD.
1278 
1279                 macAddr:   Specifies the MAC address for the connected parent
1280                           If NULL or 0xFFFFFFFFFFFF, all parents are searched.
1281 
1282                 channel:  Designate the channels on which to search for the parent.
1283                           If 0, all channels are searched.
1284 
1285    ---------------------------------------------------------------------- */
WH_ChildConnectAuto(int mode,const u8 * macAddr,u16 channel)1286 BOOL WH_ChildConnectAuto(int mode, const u8 *macAddr, u16 channel)
1287 {
1288     WH_TRACE_STATE;
1289 
1290     // Calculation of send and receive buffer size for WM_StartMP()
1291     // Use the WM_SIZE_MP_* function macros to statically allocate a buffer in advance. If this may be allocated dynamically, use the WM_GetReceiveBufferSize function after the parent and child have been connected and immediately before calling the WM_StartMP function.
1292     //
1293     //
1294     // Similarly, use the WM_SIZE_MP_* function macros to statically allocate a buffer in advance. If this may be allocated dynamically, use the WM_GetSendBufferSize function after the parent and child have been connected and immediately before calling the WM_StartMP function.
1295     //
1296     //
1297     sRecvBufferSize = WH_CHILD_RECV_BUFFER_SIZE;
1298     sSendBufferSize = WH_CHILD_SEND_BUFFER_SIZE;
1299 
1300     WH_TRACE("recv buffer size = %d\n", sRecvBufferSize);
1301     WH_TRACE("send buffer size = %d\n", sSendBufferSize);
1302 
1303     WH_ChangeSysState(WH_SYSSTATE_SCANNING);
1304 
1305     // Detection starts in child mode
1306     if (macAddr != NULL)
1307     {
1308         *(u16 *)(&sScanExParam.bssid[4]) = *(u16 *)(macAddr + 4);
1309         *(u16 *)(&sScanExParam.bssid[2]) = *(u16 *)(macAddr + 2);
1310         *(u16 *)(&sScanExParam.bssid[0]) = *(u16 *)(macAddr + 0);
1311     }
1312     else
1313     {
1314         MI_CpuFill8(&sScanExParam.bssid, 0xff, WM_SIZE_BSSID);
1315     }
1316 
1317     sConnectMode = mode;
1318 
1319     sScanCallback = NULL;
1320     sChannelIndex = channel;
1321     sScanExParam.channelList = 1;
1322     sAutoConnectFlag = TRUE;
1323 
1324     if (!WH_StateInStartScan())
1325     {
1326         WH_ChangeSysState(WH_SYSSTATE_ERROR);
1327         return FALSE;
1328     }
1329 
1330     return TRUE;
1331 }
1332 
1333 
1334 /*---------------------------------------------------------------------------*
1335   Name:         WH_TurnOnPictoCatch
1336 
1337   Description:  Enables the Pictochat Search feature.
1338                 The callback function is called even if Pictochat was found while scanning with WH_StartScan.
1339 
1340 
1341   Arguments:    None.
1342 
1343   Returns:      None.
1344  *---------------------------------------------------------------------------*/
WH_TurnOnPictoCatch(void)1345 void WH_TurnOnPictoCatch(void)
1346 {
1347     sPictoCatchFlag = TRUE;
1348 }
1349 
1350 /*---------------------------------------------------------------------------*
1351   Name:         WH_TurnOffPictoCatch
1352 
1353   Description:  Disables the Pictochat Search feature.
1354                 Ignored even if pictochat was found while scanning with WH_StartScan.
1355 
1356 
1357   Arguments:    None.
1358 
1359   Returns:      None.
1360  *---------------------------------------------------------------------------*/
WH_TurnOffPictoCatch(void)1361 void WH_TurnOffPictoCatch(void)
1362 {
1363     sPictoCatchFlag = FALSE;
1364 }
1365 
1366 /*---------------------------------------------------------------------------*
1367   Name:         WH_StartScan
1368 
1369   Description:  Fetches the parent beacon.
1370 
1371   Arguments:    callback: Callback returned when the parent device is found
1372 
1373                 macAddr: MAC address for the connected parent
1374                            If NULL or 0xFFFFFFFFFFFF, all parents are searched.
1375 
1376                 channel: Channels on which to search for the parent.
1377                            If 0, all channels are searched.
1378 
1379   Returns:      None.
1380  *---------------------------------------------------------------------------*/
WH_StartScan(WHStartScanCallbackFunc callback,const u8 * macAddr,u16 channel)1381 BOOL WH_StartScan(WHStartScanCallbackFunc callback, const u8 *macAddr, u16 channel)
1382 {
1383     WH_TRACE_STATE;
1384     WH_ASSERT(sSysState == WH_SYSSTATE_IDLE);
1385 
1386     WH_ChangeSysState(WH_SYSSTATE_SCANNING);
1387 
1388     sScanCallback = callback;
1389     sChannelIndex = channel;
1390     sScanExParam.channelList = 1;
1391     sAutoConnectFlag = FALSE;          // Does not automatically connect
1392 
1393     // Sets the conditions for the MAC address to be searched for
1394     if (macAddr != NULL)
1395     {
1396         *(u16 *)(&sScanExParam.bssid[4]) = *(u16 *)(macAddr + 4);
1397         *(u16 *)(&sScanExParam.bssid[2]) = *(u16 *)(macAddr + 2);
1398         *(u16 *)(&sScanExParam.bssid[0]) = *(u16 *)(macAddr);
1399     }
1400     else
1401     {
1402         MI_CpuFill8(&sScanExParam.bssid, 0xff, WM_SIZE_BSSID);
1403     }
1404 
1405     if (!WH_StateInStartScan())
1406     {
1407         WH_ChangeSysState(WH_SYSSTATE_ERROR);
1408         return FALSE;
1409     }
1410 
1411     return TRUE;
1412 }
1413 
1414 /* ----------------------------------------------------------------------
1415   State: StartScan
1416   ---------------------------------------------------------------------- */
WH_StateInStartScan(void)1417 static BOOL WH_StateInStartScan(void)
1418 {
1419     // When in this state, looks for a parent
1420     WMErrCode result;
1421     u16     chanpat;
1422 
1423     WH_ASSERT(sSysState == WH_SYSSTATE_SCANNING);
1424 
1425     chanpat = WM_GetAllowedChannel();
1426 
1427     // Checks if wireless is usable
1428     if (chanpat == 0x8000)
1429     {
1430         // If 0x8000 is returned, it indicates that wireless is not initialized or there is some other abnormality with the wireless library. Therefore, set to an error.
1431         //
1432         WH_REPORT_FAILURE(WM_ERRCODE_ILLEGAL_STATE);
1433         return FALSE;
1434     }
1435     if (chanpat == 0)
1436     {
1437         // In this state, wireless cannot be used
1438         WH_REPORT_FAILURE(WH_ERRCODE_NO_RADIO);
1439         return FALSE;
1440     }
1441 
1442     if (sChannelIndex == 0)
1443     {
1444         /* Search possible channels in ascending order from the current designation */
1445         u32 chan = MATH_CountTrailingZeros(sScanExParam.channelList) + 1;
1446         while (TRUE)
1447         {
1448             chan++;
1449             if (chan > 16)
1450             {
1451                 chan = 1;
1452             }
1453 
1454             if (chanpat & (0x0001 << (chan - 1)))
1455             {
1456                 break;
1457             }
1458         }
1459         sScanExParam.channelList = (u16)(1 << (chan - 1));
1460     }
1461     else
1462     {
1463         sScanExParam.channelList = (u16)(1 << (sChannelIndex - 1));
1464     }
1465 
1466     sScanExParam.maxChannelTime = WM_GetDispersionScanPeriod();
1467     sScanExParam.scanBuf = (WMbssDesc *)sScanBuf;
1468     sScanExParam.scanBufSize = WM_SIZE_SCAN_EX_BUF;
1469     sScanExParam.scanType = WM_SCANTYPE_PASSIVE;
1470     sScanExParam.ssidLength = 0;
1471     MI_CpuFill8(sScanExParam.ssid, 0xFF, sizeof(sScanExParam.ssid));
1472 
1473     result = WM_StartScanEx(WH_StateOutStartScan, &sScanExParam);
1474 
1475     if (result != WM_ERRCODE_OPERATING)
1476     {
1477         WH_REPORT_FAILURE(result);
1478         return FALSE;
1479     }
1480     return TRUE;
1481 }
1482 
1483 
WH_StateOutStartScan(void * arg)1484 static void WH_StateOutStartScan(void *arg)
1485 {
1486     WMStartScanExCallback *cb = (WMStartScanExCallback *)arg;
1487     int i;
1488     BOOL found;
1489 
1490     // If the scan command fails
1491     if (cb->errcode != WM_ERRCODE_SUCCESS)
1492     {
1493         WH_REPORT_FAILURE(cb->errcode);
1494         WH_ChangeSysState(WH_SYSSTATE_ERROR);
1495         return;
1496     }
1497 
1498     if (sSysState != WH_SYSSTATE_SCANNING)
1499     {
1500         // End scan if the state has been changed
1501         sAutoConnectFlag = FALSE;      // Cancel the automatic connection
1502         if (!WH_StateInEndScan())
1503         {
1504             WH_ChangeSysState(WH_SYSSTATE_ERROR);
1505         }
1506         return;
1507     }
1508 
1509     switch (cb->state)
1510     {
1511     case WM_STATECODE_PARENT_NOT_FOUND:
1512         break;
1513 
1514     case WM_STATECODE_PARENT_FOUND:
1515         // If a parent is found
1516 
1517         WH_TRACE("WH_StateOutStartScan : bssDescCount=%d\n", cb->bssDescCount);
1518 
1519         if ( cb->bssDescCount > 0 )
1520         {
1521             // Discards the BssDesc cache that is set in the buffer because the BssDesc information is written from the ARM7
1522             //
1523             DC_InvalidateRange(&sScanBuf, sizeof(sScanBuf));
1524         }
1525 
1526         found = FALSE;
1527         for ( i = 0; i < cb->bssDescCount; i++ )
1528         {
1529             WMBssDesc* bd = cb->bssDesc[i];
1530 
1531             // GUIDELINE: Guideline compliance items (6.3.5)
1532             // Compares ggids and fails if different.
1533             // First, you must confirm WMBssDesc.gameInfoLength, and check to see if ggid has a valid value.
1534             //
1535             WH_TRACE(" parent: MAC=%02x%02x%02x%02x%02x%02x ",
1536                      bd->bssid[0], bd->bssid[1], bd->bssid[2],
1537                      bd->bssid[3], bd->bssid[4], bd->bssid[5]);
1538 
1539             // Determines if the parent is using pictochat
1540             if (sPictoCatchFlag)
1541             {
1542                 if (CHT_IsPictochatParent(bd))
1543                 {
1544                     // If the parent is using pictochat
1545                     WH_TRACE("pictochat parent find\n");
1546                     if (sScanCallback != NULL)
1547                     {
1548                         sScanCallback(bd);
1549                     }
1550                     continue;
1551                 }
1552             }
1553 
1554             if ((!WM_IsValidGameInfo(&bd->gameInfo, bd->gameInfoLength))
1555                 || bd->gameInfo.ggid != sParentParam.ggid)
1556             {
1557                 // If GGIDs are different, this is ignored
1558                 WH_TRACE("not my parent ggid \n");
1559                 continue;
1560             }
1561 
1562             // If the entry flag is not up, the child is not receiving, so this is ignored
1563             // Also, if the multiboot flag is enabled, it is the DS download parent device, so ignore.
1564             if ((bd->gameInfo.gameNameCount_attribute & (WM_ATTR_FLAG_ENTRY | WM_ATTR_FLAG_MB))
1565                 != WM_ATTR_FLAG_ENTRY)
1566             {
1567                 WH_TRACE("not recieve entry\n");
1568                 continue;
1569             }
1570 
1571             WH_TRACE("parent find\n");
1572             MI_CpuCopy8(bd, &sBssDesc, sizeof(WMBssDesc)); // Cache-safe copy to the buffer.
1573             found = TRUE;
1574             break;
1575         }
1576 
1577         if (found)
1578         {
1579             // Call if callback is necessary
1580             if (sScanCallback != NULL)
1581             {
1582                 sScanCallback(&sBssDesc);
1583             }
1584 
1585             // End scan for automatic connection to found parent
1586             if (sAutoConnectFlag)
1587             {
1588                 if (!WH_StateInEndScan())
1589                 {
1590                     WH_ChangeSysState(WH_SYSSTATE_ERROR);
1591                 }
1592                 return;
1593             }
1594         }
1595         break;
1596     }
1597 
1598     // Changes the channel and starts another scan
1599     if (!WH_StateInStartScan())
1600     {
1601         WH_ChangeSysState(WH_SYSSTATE_ERROR);
1602     }
1603 }
1604 
1605 /* ----------------------------------------------------------------------
1606    State: EndScan
1607   ---------------------------------------------------------------------- */
1608 
1609 /*---------------------------------------------------------------------------*
1610   Name:         WH_EndScan
1611 
1612   Description:  Fetches the parent beacon.
1613 
1614   Arguments:    None.
1615 
1616   Returns:      None.
1617  *---------------------------------------------------------------------------*/
WH_EndScan(void)1618 BOOL WH_EndScan(void)
1619 {
1620     if (sSysState != WH_SYSSTATE_SCANNING)
1621     {
1622         return FALSE;
1623     }
1624 
1625     sAutoConnectFlag = FALSE;
1626     WH_ChangeSysState(WH_SYSSTATE_BUSY);
1627     return TRUE;
1628 }
1629 
1630 
WH_StateInEndScan(void)1631 static BOOL WH_StateInEndScan(void)
1632 {
1633     WMErrCode result;
1634     WH_TRACE_STATE;
1635 
1636     // In this state, scan end processing is carried out
1637     result = WM_EndScan(WH_StateOutEndScan);
1638     if (result != WM_ERRCODE_OPERATING)
1639     {
1640         WH_REPORT_FAILURE(result);
1641         return FALSE;
1642     }
1643 
1644     return TRUE;
1645 }
1646 
WH_StateOutEndScan(void * arg)1647 static void WH_StateOutEndScan(void *arg)
1648 {
1649     WMCallback *cb = (WMCallback *)arg;
1650     WH_TRACE_STATE;
1651 
1652     if (cb->errcode != WM_ERRCODE_SUCCESS)
1653     {
1654         WH_REPORT_FAILURE(cb->errcode);
1655         return;
1656     }
1657 
1658     WH_ChangeSysState(WH_SYSSTATE_IDLE);
1659 
1660     if (!sAutoConnectFlag)
1661     {
1662         // If only a scan was indicated, complete processing here
1663         return;
1664     }
1665 
1666     // The automatic connection destination has been established; thus, cancel automatic connection mode
1667     sAutoConnectFlag = FALSE;
1668 
1669     if (sChildWEPKeyGenerator != NULL)
1670     {
1671         // If the WEP Key Generator is configured, set the WEP Key
1672         if (!WH_StateInSetChildWEPKey())
1673         {
1674             WH_ChangeSysState(WH_SYSSTATE_ERROR);
1675         }
1676     }
1677     else
1678     {
1679         // The end of scan processing has finished, so begin child operations unchanged
1680         //
1681         if (!WH_StateInStartChild())
1682         {
1683             WH_TRACE("WH_StateOutEndScan : startchild failed\n");
1684             WH_ChangeSysState(WH_SYSSTATE_ERROR);
1685         }
1686     }
1687 }
1688 
WH_StateInSetChildWEPKey(void)1689 static BOOL WH_StateInSetChildWEPKey(void)
1690 {
1691     u16     wepmode;
1692     WMErrCode result;
1693     WH_TRACE_STATE;
1694 
1695     WH_ChangeSysState(WH_SYSSTATE_BUSY);
1696 
1697     wepmode = (*sChildWEPKeyGenerator) (sWEPKey, &sBssDesc);
1698     result = WM_SetWEPKey(WH_StateOutSetChildWEPKey, wepmode, sWEPKey);
1699     if (result != WM_ERRCODE_OPERATING)
1700     {
1701         WH_REPORT_FAILURE(result);
1702         WH_ChangeSysState(WH_SYSSTATE_ERROR);
1703         return FALSE;
1704     }
1705 
1706     return TRUE;
1707 }
1708 
WH_StateOutSetChildWEPKey(void * arg)1709 static void WH_StateOutSetChildWEPKey(void *arg)
1710 {
1711     WMCallback *cb = (WMCallback *)arg;
1712     WH_TRACE_STATE;
1713 
1714     if (cb->errcode != WM_ERRCODE_SUCCESS)
1715     {
1716         WH_REPORT_FAILURE(cb->errcode);
1717         WH_ChangeSysState(WH_SYSSTATE_ERROR);
1718         return;
1719     }
1720 
1721     // Connect to parent as a child
1722     if (!WH_StateInStartChild())
1723     {
1724         WH_TRACE("WH_StateOutSetChildWEPKey : startchild failed\n");
1725         WH_ChangeSysState(WH_SYSSTATE_ERROR);
1726     }
1727 }
1728 
1729 
1730 /* ----------------------------------------------------------------------
1731    State: StartChild
1732   ---------------------------------------------------------------------- */
WH_StateInStartChild(void)1733 static BOOL WH_StateInStartChild(void)
1734 {
1735     WMErrCode result;
1736     WH_TRACE_STATE;
1737 
1738     if ((sSysState == WH_SYSSTATE_CONNECTED)
1739         || (sSysState == WH_SYSSTATE_KEYSHARING) || (sSysState == WH_SYSSTATE_DATASHARING))
1740     {
1741         // Already connected
1742         WH_TRACE("WH_StateInStartChild : already connected?\n");
1743         return TRUE;
1744     }
1745 
1746     WH_ChangeSysState(WH_SYSSTATE_BUSY);
1747 
1748     result = WM_StartConnectEx(WH_StateOutStartChild, &sBssDesc, sConnectionSsid, TRUE,
1749                                (u16)((sChildWEPKeyGenerator !=
1750                                       NULL) ? WM_AUTHMODE_SHARED_KEY : WM_AUTHMODE_OPEN_SYSTEM));
1751     if (result != WM_ERRCODE_OPERATING)
1752     {
1753         WH_REPORT_FAILURE(result);
1754         return FALSE;
1755     }
1756 
1757     return TRUE;
1758 }
1759 
WH_StateOutStartChild(void * arg)1760 static void WH_StateOutStartChild(void *arg)
1761 {
1762     // The callback set by StartConnect will be invoked in several cases, as follows, so a distinction needs to be made between them.
1763     // 1) When the connection processing begins
1764     // 2) When authentication ends
1765     // 3) When the parent disconnects after a connection is complete
1766     // 4) When more than the maximum number of devices try to connect
1767     //
1768     // For this function, advancing to the next item is possible only with 2).
1769 
1770     WMStartConnectCallback *cb = (WMStartConnectCallback *)arg;
1771     WH_TRACE_STATE;
1772 
1773     if (cb->errcode != WM_ERRCODE_SUCCESS)
1774     {
1775         WH_REPORT_FAILURE(cb->errcode);
1776 
1777         if (cb->errcode == WM_ERRCODE_OVER_MAX_ENTRY)
1778         {
1779             // GUIDELINE: Guideline compliance items (6.3.7)
1780             // If there are more children than the parent can handle.
1781             // Here, this qualifies as a fatal error.
1782             // At this time, something needs to be displayed by main.
1783             // The WH_GetLastError function can be used to check whether the error code was WM_ERRCODE_OVER_MAX_ENTRY.
1784             //
1785             WH_ChangeSysState(WH_SYSSTATE_ERROR);
1786             return;
1787         }
1788         else if (cb->errcode == WM_ERRCODE_NO_ENTRY)
1789         {
1790             // The case wherein this child device tried to connect to the parent, which rejected the entry.
1791             //
1792             // Here, this qualifies as a fatal error.
1793             // At this time, something needs to be displayed by main.
1794             // The WH_GetLastError function can be used to check whether the error code was WM_ERRCODE_NO_ENTRY.
1795             //
1796             WH_ChangeSysState(WH_SYSSTATE_ERROR);
1797             return;
1798         }
1799         else if (cb->errcode == WM_ERRCODE_FAILED)
1800         {
1801             // The case wherein a connection request timed out, for example because the parent to which this child device tried to connect no longer exists.
1802             //
1803             // Here, this qualifies as a fatal error.
1804             // At this time, either something needs to be displayed or the connection needs to be retried after a reset is performed by the main process.
1805             //
1806             // The WH_GetLastError function can be used to check whether the error code was WM_ERRCODE_FAILED.
1807             //
1808             WH_ChangeSysState(WH_SYSSTATE_CONNECT_FAIL);
1809             return;
1810         }
1811         else
1812         {
1813             // If the parent's channel setting is invalid, WM_ERRCODE_INVALID_PARAM may be returned
1814             //
1815             WH_ChangeSysState(WH_SYSSTATE_ERROR);
1816         }
1817         return;
1818     }
1819 
1820     if (cb->state == WM_STATECODE_BEACON_LOST)
1821     {
1822         // Beacon reception failed after 16 attempts from the parent being connected.
1823         // If the beacon is lost, VBlank synchronization may be lost and we may not be able to notice when the parent has started the next session (the TGID has changed).
1824         //
1825         //
1826 
1827         // Nothing is executed in the demo.
1828         return;
1829     }
1830 
1831     if (cb->state == WM_STATECODE_CONNECTED)
1832     {
1833         // When authentication is complete.
1834         // Self-allocated AID goes in cb->aid
1835         WH_TRACE("Connect to Parent\n");
1836         WH_ChangeSysState(WH_SYSSTATE_CONNECTED);
1837         if (!WH_StateInStartChildMP())
1838         {
1839             /* FIXME : Is it OK to put this here while BUSY? */
1840             WH_TRACE("WH_StateInStartChildMP failed\n");
1841             WH_ChangeSysState(WH_SYSSTATE_BUSY);
1842             return;
1843         }
1844 
1845         // Saves own aid
1846         sMyAid = cb->aid;
1847         return;
1848 
1849     }
1850     else if (cb->state == WM_STATECODE_CONNECT_START)
1851     {
1852         // When the connection processing begins.
1853         // The following values are returned in cb->errcode: WM_ERRCODE_FAILED if the parent is no longer present (and in similar situations); WM_ERRCODE_NO_ENTRY if the parent has rejected an entry; and WM_ERRCODE_OVER_MAX_ENTRY if the parent has reached its connection capacity.
1854         //
1855         //
1856         //
1857         // The process does nothing and waits for authentication to end.
1858         return;
1859 
1860     }
1861     else if (cb->state == WM_STATECODE_DISCONNECTED)
1862     {
1863         // GUIDELINE: Guideline compliance items (6.3.1)
1864         // When disconnected by the parent.
1865         // Processing like that above (6.3.7) is needed (to display something).
1866         // The error code here is WH_ERRCODE_DISCONNECTED
1867         // (Note that it is not 'WM_'.)
1868         // An ordinary game may be in play in a case such as this (disconnected from the parent), but for now this is treated as an error to be handled by main.
1869         //
1870         //
1871 
1872         WH_TRACE("Disconnected from Parent\n");
1873         WH_SetError(WH_ERRCODE_DISCONNECTED);
1874         WH_ChangeSysState(WH_SYSSTATE_ERROR);
1875         return;
1876     }
1877     else if (cb->state == WM_STATECODE_DISCONNECTED_FROM_MYSELF)
1878     {
1879         // Does nothing if the unit disconnects from itself
1880         return;
1881     }
1882 
1883     WH_TRACE("unknown state %d, %s\n", cb->state, WH_GetWMStateCodeName(cb->state));
1884     WH_ChangeSysState(WH_SYSSTATE_ERROR);
1885 }
1886 
1887 /* ----------------------------------------------------------------------
1888    State: StartChildMP
1889    ---------------------------------------------------------------------- */
WH_StateInStartChildMP(void)1890 static BOOL WH_StateInStartChildMP(void)
1891 {
1892     WMErrCode result;
1893     WH_TRACE_STATE;
1894 
1895     result = WM_StartMP(WH_StateOutStartChildMP,
1896                         (u16 *)sRecvBuffer,
1897                         (u16)sRecvBufferSize, (u16 *)sSendBuffer, (u16)sSendBufferSize,
1898                         WH_MP_FREQUENCY);
1899 
1900     if (result != WM_ERRCODE_OPERATING)
1901     {
1902         WH_REPORT_FAILURE(result);
1903         return FALSE;
1904     }
1905 
1906     return TRUE;
1907 }
1908 
WH_StateOutStartChildMP(void * arg)1909 static void WH_StateOutStartChildMP(void *arg)
1910 {
1911     WMStartMPCallback *cb = (WMStartMPCallback *)arg;
1912     // WH_TRACE_STATE;
1913 
1914     if (cb->errcode != WM_ERRCODE_SUCCESS)
1915     {
1916 
1917         if (cb->errcode == WM_ERRCODE_SEND_FAILED)
1918         {
1919             // The case wherein a notification was sent for a receive error by the parent, caused by an MPACK frame, for WM_STATECODE_MPACK_IND.
1920             //
1921             // Since retransmission and other processing is handled in a separate location, nothing in particular needs to be done here.
1922             //  This is for debugging.
1923             return;
1924 
1925         }
1926         else if (cb->errcode == WM_ERRCODE_TIMEOUT)
1927         {
1928             // In this case, the MPACK frame could not be received even after waiting a fixed period of time after receiving the MP frame.
1929             //  (cb->state == WM_STATECODE_MPACK_IND)
1930             // Since retransmission and other processing is handled in a separate location, nothing in particular needs to be done here.
1931             //  This is for debugging.
1932             return;
1933 
1934         }
1935         else if (cb->errcode == WM_ERRCODE_INVALID_POLLBITMAP)
1936         {
1937             // In this case, a frame sent to another machine was received during WM_STATECODE_MP_IND or WM_STATECODE_MPACK_IND.
1938             //
1939             // This occurs often during communications with 3 or more devices, so it cannot be treated as a fatal error.
1940             //
1941             // Nothing in particular needs to be done here. This is for debugging.
1942             return;
1943         }
1944 
1945         WH_REPORT_FAILURE(cb->errcode);
1946         WH_ChangeSysState(WH_SYSSTATE_ERROR);
1947         return;
1948     }
1949 
1950     switch (cb->state)
1951     {
1952     case WM_STATECODE_MP_START:
1953         // Notification that the StartMP has ended normally.
1954         // Hereafter, send and receive are enabled.
1955 
1956         if (sConnectMode == WH_CONNECTMODE_KS_CHILD)
1957         {
1958             // If key sharing was specified.
1959             if (sSysState == WH_SYSSTATE_KEYSHARING)
1960             {
1961                 // The key sharing state is already set, so nothing happens.
1962                 return;
1963             }
1964 
1965             if (sSysState == WH_SYSSTATE_CONNECTED)
1966             {
1967                 // Switches to StartChildKeyShare.
1968                 if (!WH_StateInStartChildKeyShare())
1969                 {
1970                     WH_TRACE("WH_StateInStartChildKeyShare failed\n");
1971                     (void)WH_Finalize();
1972                 }
1973                 return;
1974             }
1975 
1976         }
1977         else if (sConnectMode == WH_CONNECTMODE_DS_CHILD)
1978         {
1979             // Call WM_StartDataSharing if data sharing is specified.
1980             //  This function is synchronous, so no switch has been made to a WH state.
1981             WMErrCode result;
1982             u16     aidBitmap;
1983 
1984             aidBitmap = (u16)((1 << (WH_CHILD_MAX + 1)) - 1);   // Bitmap with the lower WH_CHILD_MAX+1 bit==1
1985             result = WM_StartDataSharing(&sDSInfo, WH_DS_PORT, aidBitmap, WH_DS_DATA_SIZE, sDataSharingDoubleMode);
1986             if (result != WM_ERRCODE_SUCCESS)
1987             {
1988                 WH_REPORT_FAILURE(result);
1989                 (void)WH_Finalize();
1990                 return;
1991             }
1992 
1993             WH_TRACE("WH_StateOutStartChildMP : WM_StartDataSharing OK\n");
1994             WH_ChangeSysState(WH_SYSSTATE_DATASHARING);
1995             if (sPortExtraCallback)
1996             {
1997                 (*sPortExtraCallback)(arg);
1998             }
1999             return;
2000         }
2001 
2002         WH_ChangeSysState(WH_SYSSTATE_CONNECTED);
2003         if (sPortExtraCallback)
2004         {
2005             (*sPortExtraCallback)(arg);
2006         }
2007         break;
2008 
2009     case WM_STATECODE_MP_IND:
2010         // The child receiving is complete.
2011 
2012         // cb->recvBuf accepts the data frame content received from the parent device, but for normal data reception set a callback with WM_SetPortCallback.
2013         //
2014         // Data is received internally when data sharing or key sharing is in use, so WM_SetPortCallback does not need to be used.
2015         //
2016 
2017         break;
2018 
2019     case WM_STATECODE_MPACK_IND:
2020         // Notification of the MPACK frame. This is for debugging.
2021         break;
2022 
2023     case WM_STATECODE_MPEND_IND:
2024         // The child should not come here
2025 
2026     default:
2027         WH_TRACE("unknown indicate, state = %d\n", cb->state);
2028         break;
2029     }
2030 }
2031 
2032 /* ----------------------------------------------------------------------
2033    State: StartChildKeyShare
2034   ---------------------------------------------------------------------- */
WH_StateInStartChildKeyShare(void)2035 static BOOL WH_StateInStartChildKeyShare(void)
2036 {
2037     WMErrCode result;
2038     WH_TRACE_STATE;
2039 
2040     if (sSysState == WH_SYSSTATE_KEYSHARING)
2041     {
2042         // Already key sharing
2043         return TRUE;
2044     }
2045 
2046     if (sSysState != WH_SYSSTATE_CONNECTED)
2047     {
2048         // Not connected
2049         return FALSE;
2050     }
2051 
2052     WH_ChangeSysState(WH_SYSSTATE_KEYSHARING);
2053     result = WM_StartKeySharing(&sWMKeySetBuf, WH_DS_PORT);
2054 
2055     if (result != WM_ERRCODE_SUCCESS)
2056     {
2057         WH_REPORT_FAILURE(result);
2058         return FALSE;
2059     }
2060 
2061     return TRUE;
2062 }
2063 
2064 /* ----------------------------------------------------------------------
2065    State: EndChildKeyShare
2066    ---------------------------------------------------------------------- */
WH_StateInEndChildKeyShare(void)2067 static BOOL WH_StateInEndChildKeyShare(void)
2068 {
2069     // Ends key sharing
2070     WMErrCode result;
2071     WH_TRACE_STATE;
2072 
2073     if (sSysState != WH_SYSSTATE_KEYSHARING)
2074     {
2075         return FALSE;
2076     }
2077 
2078     WH_ChangeSysState(WH_SYSSTATE_BUSY);
2079     result = WM_EndKeySharing(&sWMKeySetBuf);
2080 
2081     if (result != WM_ERRCODE_SUCCESS)
2082     {
2083         WH_REPORT_FAILURE(result);
2084         return FALSE;
2085     }
2086 
2087     if (!WH_StateInEndChildMP())
2088     {
2089         return FALSE;
2090     }
2091 
2092     return TRUE;
2093 }
2094 
2095 /* ----------------------------------------------------------------------
2096    State: EndChildMP
2097   ---------------------------------------------------------------------- */
WH_StateInEndChildMP(void)2098 static BOOL WH_StateInEndChildMP(void)
2099 {
2100     // Ends MP communication
2101     WMErrCode result;
2102     WH_TRACE_STATE;
2103 
2104     WH_ChangeSysState(WH_SYSSTATE_BUSY);
2105 
2106     result = WM_EndMP(WH_StateOutEndChildMP);
2107     if (result != WM_ERRCODE_OPERATING)
2108     {
2109         WH_REPORT_FAILURE(result);
2110         return FALSE;
2111     }
2112     return TRUE;
2113 }
2114 
WH_StateOutEndChildMP(void * arg)2115 static void WH_StateOutEndChildMP(void *arg)
2116 {
2117     WMCallback *cb = (WMCallback *)arg;
2118     WH_TRACE_STATE;
2119 
2120     if (cb->errcode != WM_ERRCODE_SUCCESS)
2121     {
2122         WH_REPORT_FAILURE(cb->errcode);
2123         (void)WH_Finalize();
2124         return;
2125     }
2126 
2127     if (!WH_StateInEndChild())
2128     {
2129         WH_ChangeSysState(WH_SYSSTATE_ERROR);
2130     }
2131 }
2132 
2133 /* ----------------------------------------------------------------------
2134   State: EndChild
2135   ---------------------------------------------------------------------- */
WH_StateInEndChild(void)2136 static BOOL WH_StateInEndChild(void)
2137 {
2138     WMErrCode result;
2139     WH_TRACE_STATE;
2140 
2141     WH_ChangeSysState(WH_SYSSTATE_BUSY);
2142 
2143     // Terminates the connection with the parent
2144     result = WM_Disconnect(WH_StateOutEndChild, 0);
2145     if (result != WM_ERRCODE_OPERATING)
2146     {
2147         WH_REPORT_FAILURE(result);
2148         WH_Reset();
2149         return FALSE;
2150     }
2151 
2152     return TRUE;
2153 }
2154 
WH_StateOutEndChild(void * arg)2155 static void WH_StateOutEndChild(void *arg)
2156 {
2157     WMCallback *cb = (WMCallback *)arg;
2158     WH_TRACE_STATE;
2159     if (cb->errcode != WM_ERRCODE_SUCCESS)
2160     {
2161         WH_REPORT_FAILURE(cb->errcode);
2162         return;
2163     }
2164     // At this point, the child disconnection processing ends, and the state returns to idle (standby)
2165     WH_ChangeSysState(WH_SYSSTATE_IDLE);
2166 }
2167 
2168 /* ----------------------------------------------------------------------
2169   State: Reset
2170   ---------------------------------------------------------------------- */
WH_StateInReset(void)2171 static BOOL WH_StateInReset(void)
2172 {
2173     // This state is common to parents and children.
2174     // Restores system to its defaults.
2175     WMErrCode result;
2176     WH_TRACE_STATE;
2177 
2178     WH_ChangeSysState(WH_SYSSTATE_BUSY);
2179     result = WM_Reset(WH_StateOutReset);
2180     if (result != WM_ERRCODE_OPERATING)
2181     {
2182         WH_REPORT_FAILURE(result);
2183         return FALSE;
2184     }
2185     return TRUE;
2186 }
2187 
WH_StateOutReset(void * arg)2188 static void WH_StateOutReset(void *arg)
2189 {
2190     WMCallback *cb = (WMCallback *)arg;
2191     WH_TRACE_STATE;
2192     if (cb->errcode != WM_ERRCODE_SUCCESS)
2193     {
2194         WH_ChangeSysState(WH_SYSSTATE_ERROR);
2195         WH_REPORT_FAILURE(cb->errcode);
2196         return;
2197     }
2198     if (sPortExtraCallback)
2199     {
2200         (*sPortExtraCallback)(arg);
2201     }
2202     // Reset sets to the idling (standby) state without starting the next state
2203     WH_ChangeSysState(WH_SYSSTATE_IDLE);
2204 }
2205 
2206 /* ----------------------------------------------------------------------
2207    Disconnect
2208   ---------------------------------------------------------------------- */
WH_StateInDisconnectChildren(u16 bitmap)2209 static BOOL WH_StateInDisconnectChildren(u16 bitmap)
2210 {
2211     // In this state, the connection with the child set with the argument is cut
2212     WMErrCode result;
2213     WH_TRACE_STATE;
2214 
2215     result = WM_DisconnectChildren(WH_StateOutDisconnectChildren, bitmap);
2216 
2217     if (result == WM_ERRCODE_NO_CHILD)
2218     {
2219         return FALSE;
2220     }
2221 
2222     if (result != WM_ERRCODE_OPERATING)
2223     {
2224         WH_REPORT_FAILURE(result);
2225         return FALSE;
2226     }
2227 
2228     {
2229         OSIntrMode enabled = OS_DisableInterrupts();
2230         sConnectBitmap &= ~bitmap;
2231         (void)OS_RestoreInterrupts(enabled);
2232     }
2233     return TRUE;
2234 }
2235 
WH_StateOutDisconnectChildren(void * arg)2236 static void WH_StateOutDisconnectChildren(void *arg)
2237 {
2238     WMCallback *cb = (WMCallback *)arg;
2239     WH_TRACE_STATE;
2240     if (cb->errcode != WM_ERRCODE_SUCCESS)
2241     {
2242         WH_REPORT_FAILURE(cb->errcode);
2243         return;
2244     }
2245 }
2246 
2247 /* ----------------------------------------------------------------------
2248    Power off
2249   ---------------------------------------------------------------------- */
WH_StateInPowerOff(void)2250 static BOOL WH_StateInPowerOff(void)
2251 {
2252     // Ends the power supply to the wireless hardware.
2253     // This state is common to parents and children.
2254     WMErrCode result;
2255     WH_TRACE_STATE;
2256 
2257     result = WM_PowerOff(WH_StateOutPowerOff);
2258     if (result != WM_ERRCODE_OPERATING)
2259     {
2260         WH_REPORT_FAILURE(result);
2261         return FALSE;
2262     }
2263     return TRUE;
2264 }
2265 
WH_StateOutPowerOff(void * arg)2266 static void WH_StateOutPowerOff(void *arg)
2267 {
2268     // This state is after power disconnect
2269     WMCallback *cb = (WMCallback *)arg;
2270     WH_TRACE_STATE;
2271 
2272     if (cb->errcode != WM_ERRCODE_SUCCESS)
2273     {
2274         WH_REPORT_FAILURE(cb->errcode);
2275         return;
2276     }
2277 
2278     if (!WH_StateInDisable())
2279     {
2280         WH_ChangeSysState(WH_SYSSTATE_FATAL);
2281     }
2282 }
2283 
2284 /* ----------------------------------------------------------------------
2285    Disable
2286   ---------------------------------------------------------------------- */
WH_StateInDisable(void)2287 static BOOL WH_StateInDisable(void)
2288 {
2289     // Communicates that the wireless hardware use has ended.
2290     // This state is common to parents and children.
2291     WMErrCode result;
2292     WH_TRACE_STATE;
2293 
2294     result = WM_Disable(WH_StateOutDisable);
2295     if (result != WM_ERRCODE_OPERATING)
2296     {
2297         WH_REPORT_FAILURE(result);
2298         return FALSE;
2299     }
2300     return TRUE;
2301 }
2302 
WH_StateOutDisable(void * arg)2303 static void WH_StateOutDisable(void *arg)
2304 {
2305     // Everything has ended
2306     WMCallback *cb = (WMCallback *)arg;
2307     WH_TRACE_STATE;
2308 
2309     if (cb->errcode != WM_ERRCODE_SUCCESS)
2310     {
2311         WH_REPORT_FAILURE(cb->errcode);
2312     }
2313 }
2314 
2315 /* ----------------------------------------------------------------------
2316   State: SetMPData
2317   ---------------------------------------------------------------------- */
WH_StateInSetMPData(const void * data,u16 datasize,WHSendCallbackFunc callback)2318 static BOOL WH_StateInSetMPData(const void *data, u16 datasize, WHSendCallbackFunc callback)
2319 {
2320     // This state is common to parents and children.
2321     // Sets and sends the data.
2322     WMErrCode result;
2323     // WH_TRACE_STATE;
2324 
2325     DC_FlushRange(sSendBuffer, (u32)sSendBufferSize);
2326     /* The I/O register is accessed using PXI operation, so cache wait is not needed */
2327     // DC_WaitWriteBufferEmpty();
2328     result = WM_SetMPDataToPortEx(WH_StateOutSetMPData,
2329                                   (void *)callback,
2330                                   data, datasize, 0xffff, WH_DATA_PORT, WH_DATA_PRIO);
2331     if (result != WM_ERRCODE_OPERATING)
2332     {
2333         WH_TRACE("WH_StateInSetMPData failed - %s\n", WH_GetWMErrCodeName(result));
2334         return FALSE;
2335     }
2336     return TRUE;
2337 }
2338 
WH_StateOutSetMPData(void * arg)2339 static void WH_StateOutSetMPData(void *arg)
2340 {
2341     WMPortSendCallback *cb = (WMPortSendCallback *)arg;
2342     // WH_TRACE_STATE;
2343 
2344     // You cannot overwrite the memory region for the transmission data specified with SetMPDataToPort until this callback is invoked.
2345     //
2346 
2347     // WM_ERRCODE_SEND_FAILED is returned if ports 0-7 are used and the transmission fails.
2348     //
2349     // WM_ERRCODE_SEND_QUEUE_FULL is returned if the transmission queue was full.
2350     //
2351 
2352     if (sPortExtraCallback)
2353     {
2354         (*sPortExtraCallback)(arg);
2355     }
2356     if (cb->errcode != WM_ERRCODE_SUCCESS && cb->errcode != WM_ERRCODE_SEND_FAILED)
2357     {
2358         WH_REPORT_FAILURE(cb->errcode);
2359         return;
2360     }
2361 
2362     if (cb->arg != NULL)
2363     {
2364         WHSendCallbackFunc callback = (WHSendCallbackFunc) cb->arg;
2365         // Change the WHSendCallbackFunc type as necessary and cause cb->aid, cb->data, and other information to be received.
2366         //
2367         (*callback) ((cb->errcode == WM_ERRCODE_SUCCESS));
2368     }
2369 }
2370 
WH_PortReceiveCallback(void * arg)2371 static void WH_PortReceiveCallback(void *arg)
2372 {
2373     WMPortRecvCallback *cb = (WMPortRecvCallback *)arg;
2374 
2375     if (cb->errcode != WM_ERRCODE_SUCCESS)
2376     {
2377         WH_REPORT_FAILURE(cb->errcode);
2378     }
2379     else if (sReceiverFunc != NULL)
2380     {
2381         if (cb->state == WM_STATECODE_PORT_INIT)
2382         {
2383             // Does nothing during initialization.
2384             // The aid of the other parties connected at time of initialization are set in cb->aidBitmap.
2385             //
2386         }
2387         if (cb->state == WM_STATECODE_PORT_RECV)
2388         {
2389             // Data was received, so the callback is called.
2390             (*sReceiverFunc) (cb->aid, cb->data, cb->length);
2391         }
2392         else if (cb->state == WM_STATECODE_DISCONNECTED)
2393         {
2394             // The fact that there was a disconnection is communicated with NULL transmission.
2395             (*sReceiverFunc) (cb->aid, NULL, 0);
2396         }
2397         else if (cb->state == WM_STATECODE_DISCONNECTED_FROM_MYSELF)
2398         {
2399             // For backward compatibility, no notification is made regarding self-disconnection.
2400         }
2401         else if (cb->state == WM_STATECODE_CONNECTED)
2402         {
2403             // Do nothing when connected.
2404             // The aid of the partner connected to cb->aid, and the MAC address of the partner in cb->macAddress, are configured.
2405             //
2406             //
2407         }
2408     }
2409 }
2410 
2411 
2412 /* ----------------------------------------------------------------------
2413   State: End
2414   ---------------------------------------------------------------------- */
2415 
2416 /* ----------------------------------------------------------------------
2417   State: WM_End
2418   ---------------------------------------------------------------------- */
WH_StateOutEnd(void * arg)2419 static void WH_StateOutEnd(void *arg)
2420 {
2421     WMCallback *cb = (WMCallback *)arg;
2422     if (cb->errcode != WM_ERRCODE_SUCCESS)
2423     {
2424         WH_ChangeSysState(WH_SYSSTATE_FATAL);
2425         return;
2426     }
2427     WH_ChangeSysState(WH_SYSSTATE_STOP);
2428 }
2429 
2430 
2431 /* ======================================================================
2432    Public Interfaces
2433    ====================================================================== */
2434 
2435 
2436 /**************************************************************************
2437  * The functions below alter each type of WH configuration values
2438  **************************************************************************/
2439 
2440 /*---------------------------------------------------------------------------*
2441   Name:         WH_SetGgid
2442 
2443   Description:  Configures the game group ID.
2444                 Call before making a connection to the parent device.
2445 
2446   Arguments:    ggid:    The game group ID to configure
2447 
2448   Returns:      None.
2449  *---------------------------------------------------------------------------*/
WH_SetGgid(u32 ggid)2450 void WH_SetGgid(u32 ggid)
2451 {
2452     sParentParam.ggid = ggid;
2453 }
2454 
2455 /*---------------------------------------------------------------------------*
2456   Name:         WH_SetSsid
2457 
2458   Description:  Sets the SSID specified during child connection.
2459                 Call before making a connection from the child device.
2460 
2461   Arguments:    ssid:    Buffer in which the SSID to be set has been stored
2462                 length:  data length of the SSID to be set.
2463                         If less than WM_SIZE_CHILD_SSID (24-byte), fill the subsequent whitespace with 0s. If more than WM_SIZE_CHILD_SSID, truncate.
2464 
2465 
2466   Returns:      None.
2467  *---------------------------------------------------------------------------*/
WH_SetSsid(const void * ssid,u32 length)2468 void WH_SetSsid(const void *ssid, u32 length)
2469 {
2470     length = (u32)MATH_MIN(length, WM_SIZE_CHILD_SSID);
2471     MI_CpuCopy8(ssid, sConnectionSsid, length);
2472     MI_CpuClear8(sConnectionSsid + length, (u32)(WM_SIZE_CHILD_SSID - length));
2473 }
2474 
2475 /*---------------------------------------------------------------------------*
2476   Name:         WH_SetUserGameInfo
2477 
2478   Description:  Configures user-defined parent device information
2479                 Call before making a connection to the parent device.
2480 
2481   Arguments:    userGameInfo:   Pointer to user-defined parent device information
2482                 length:         Size of the user-defined parent device information
2483 
2484   Returns:      None.
2485  *---------------------------------------------------------------------------*/
WH_SetUserGameInfo(u16 * userGameInfo,u16 length)2486 void WH_SetUserGameInfo(u16 *userGameInfo, u16 length)
2487 {
2488     SDK_ASSERT(length <= WM_SIZE_USER_GAMEINFO);
2489     SDK_ASSERT((userGameInfo != NULL) || (length > 0));
2490     SDK_ASSERT(sSysState == WH_SYSSTATE_IDLE);
2491 
2492     // Specify user definition data here if to be used in the beacon.
2493     // To display a parent device's nickname on the child device's parent selection screen (or for some other situation), set the information here and the parent will convey it to the child.
2494     //
2495     sParentParam.userGameInfo = userGameInfo;
2496     sParentParam.userGameInfoLength = length;
2497 }
2498 
2499 /*---------------------------------------------------------------------------*
2500   Name:         WH_SetDebugOutput
2501 
2502   Description:  Configures the function for outputting the debug string.
2503 
2504   Arguments:    func:   Function for the set debug string output
2505 
2506   Returns:      None.
2507  *---------------------------------------------------------------------------*/
WH_SetDebugOutput(void (* func)(const char *,...))2508 void WH_SetDebugOutput(void (*func) (const char *, ...))
2509 {
2510     OSIntrMode enabled = OS_DisableInterrupts();
2511     wh_trace = func;
2512     (void)OS_RestoreInterrupts(enabled);
2513 }
2514 
2515 
2516 /**************************************************************************
2517  * Wrapper functions for fetching the WM library state are given below
2518  **************************************************************************/
2519 
2520 /* ----------------------------------------------------------------------
2521   Name:        WH_GetLinkLevel
2522   Description: Gets the radio reception strength.
2523   Arguments:   None.
2524   Returns:     Numeric value of WMLinkLevel.
2525   ---------------------------------------------------------------------- */
WH_GetLinkLevel(void)2526 int WH_GetLinkLevel(void)
2527 {
2528     return (int)WM_GetLinkLevel();
2529 }
2530 
2531 /* ----------------------------------------------------------------------
2532    Name:        WH_GetAllowedChannel
2533    Description: Gets the bit pattern of channels that can be used for connection.
2534    Arguments:   None.
2535    Returns:     Channel pattern.
2536    ---------------------------------------------------------------------- */
WH_GetAllowedChannel(void)2537 u16 WH_GetAllowedChannel(void)
2538 {
2539     return WM_GetAllowedChannel();
2540 }
2541 
2542 
2543 /**************************************************************************
2544  * The following functions get the WH status
2545  **************************************************************************/
2546 
2547 /* ----------------------------------------------------------------------
2548    Name:        WH_GetBitmap
2549    Description: Gets the bit pattern for displaying the connection state.
2550    Arguments:   None.
2551    Returns:     Bitmap pattern.
2552    ---------------------------------------------------------------------- */
WH_GetBitmap(void)2553 u16 WH_GetBitmap(void)
2554 {
2555     return sConnectBitmap;
2556 }
2557 
2558 /* ----------------------------------------------------------------------
2559    Name:        WH_GetSystemState
2560    Description: Gets the WH internal state.
2561    Arguments:   None.
2562    Returns:     The internal state (WH_SYSSTATE_XXXX).
2563    ---------------------------------------------------------------------- */
WH_GetSystemState(void)2564 int WH_GetSystemState(void)
2565 {
2566     return sSysState;
2567 }
2568 
2569 /* ----------------------------------------------------------------------
2570    Name:        WH_GetConnectMode
2571    Description: Gets the connection information.
2572    Arguments:   None.
2573    Returns:     The connection information (WH_CONNECTMODE_XX_XXXX).
2574    ---------------------------------------------------------------------- */
WH_GetConnectMode(void)2575 int WH_GetConnectMode(void)
2576 {
2577     return sConnectMode;
2578 }
2579 
2580 /* ----------------------------------------------------------------------
2581    Name:        WH_GetLastError
2582    Description: Gets the error code that most recently occurred.
2583    Arguments:   None.
2584    Returns:     The error code.
2585    ---------------------------------------------------------------------- */
WH_GetLastError(void)2586 int WH_GetLastError(void)
2587 {
2588     return sErrCode;
2589 }
2590 
2591 /*---------------------------------------------------------------------------*
2592   Name:         WH_PrintBssDesc
2593 
2594   Description:  Debug outputs the members of the WMBssDesc structure.
2595 
2596   Arguments:    info:    Pointer to the BssDesc to be debug output
2597 
2598   Returns:      None.
2599  *---------------------------------------------------------------------------*/
WH_PrintBssDesc(WMBssDesc * info)2600 void WH_PrintBssDesc(WMBssDesc *info)
2601 {
2602 #pragma unused( info )
2603     u16     i;
2604 
2605     OS_TPrintf("length = 0x%04x\n", info->length);
2606     OS_TPrintf("rssi   = 0x%04x\n", info->rssi);
2607     OS_TPrintf("bssid = %02x%02x%02x%02x%02x%02x\n", info->bssid[0], info->bssid[1], info->bssid[2],
2608                info->bssid[3], info->bssid[4], info->bssid[5]);
2609     OS_TPrintf("ssidLength = 0x%04x\n", info->ssidLength);
2610     OS_TPrintf("ssid = ");
2611     for (i = 0; i < 32; i++)
2612     {
2613         OS_TPrintf("0x%02x", info->ssid[i]);
2614     }
2615     OS_TPrintf("\n");
2616     OS_TPrintf("capaInfo        = 0x%04x\n", info->capaInfo);
2617     OS_TPrintf("rateSet.basic   = 0x%04x\n", info->rateSet.basic);
2618     OS_TPrintf("rateSet.support = 0x%04x\n", info->rateSet.support);
2619     OS_TPrintf("beaconPeriod    = 0x%04x\n", info->beaconPeriod);
2620     OS_TPrintf("dtimPeriod      = 0x%04x\n", info->dtimPeriod);
2621     OS_TPrintf("channel         = 0x%04x\n", info->channel);
2622     OS_TPrintf("cfpPeriod       = 0x%04x\n", info->cfpPeriod);
2623     OS_TPrintf("cfpMaxDuration  = 0x%04x\n", info->cfpMaxDuration);
2624     OS_TPrintf("gameInfoLength  = 0x%04x\n", info->gameInfoLength);
2625     OS_TPrintf("gameInfo.magicNumber = 0x%04x\n", info->gameInfo.magicNumber);
2626     OS_TPrintf("gameInfo.ver    = 0x%02x\n", info->gameInfo.ver);
2627     OS_TPrintf("gameInfo.ggid   = 0x%08x\n", info->gameInfo.ggid);
2628     OS_TPrintf("gameInfo.tgid   = 0x%04x\n", info->gameInfo.tgid);
2629     OS_TPrintf("gameInfo.userGameInfoLength = 0x%02x\n", info->gameInfo.userGameInfoLength);
2630     OS_TPrintf("gameInfo.gameNameCount_attribute = 0x%02x\n",
2631                info->gameInfo.gameNameCount_attribute);
2632     OS_TPrintf("gameInfo.parentMaxSize   = 0x%04x\n", info->gameInfo.parentMaxSize);
2633     OS_TPrintf("gameInfo.childMaxSize    = 0x%04x\n", info->gameInfo.childMaxSize);
2634 }
2635 
2636 
2637 /**************************************************************************
2638  * The following functions perform channel-related processes
2639  **************************************************************************/
2640 
2641 /*---------------------------------------------------------------------------*
2642   Name:         WH_StartMeasureChannel
2643 
2644   Description:  Starts an examination of the channel signal use rate
2645 
2646   Arguments:    None.
2647 
2648   Returns:     TRUE if the sequence start was a success.
2649  *---------------------------------------------------------------------------*/
WH_StartMeasureChannel(void)2650 BOOL WH_StartMeasureChannel(void)
2651 {
2652 #define MAX_RATIO 100                  // The channel use rate is between 0 and 100
2653     u16     result;
2654     u8      macAddr[6];
2655 
2656     OS_GetMacAddress(macAddr);
2657     RAND_INIT(OS_GetVBlankCount() + *(u16 *)&macAddr[0] + *(u16 *)&macAddr[2] + *(u16 *)&macAddr[4]);   // Random number initialization
2658     RAND();
2659 
2660     sChannel = 0;
2661     sChannelBusyRatio = MAX_RATIO + 1;
2662 
2663     WH_ChangeSysState(WH_SYSSTATE_BUSY);
2664 
2665     result = WH_StateInMeasureChannel(1);
2666 
2667     if (result == WH_ERRCODE_NOMORE_CHANNEL)
2668     {
2669         // There are not any channels available
2670         // An error is returned here because this is, after all, a special state wherein wireless signals cannot be used.
2671         //
2672         // (Generally, something should be displayed at this point.)
2673         WH_REPORT_FAILURE(WH_ERRCODE_NOMORE_CHANNEL);
2674         WH_ChangeSysState(WH_SYSSTATE_ERROR);
2675         return FALSE;
2676     }
2677 
2678     if (result != WM_ERRCODE_OPERATING)
2679     {
2680         // Error complete
2681         WH_REPORT_FAILURE(result);
2682         WH_ChangeSysState(WH_SYSSTATE_ERROR);
2683         return FALSE;
2684     }
2685     return TRUE;
2686 }
2687 
2688 /*---------------------------------------------------------------------------*
2689   Name:         WH_StateInMeasureChannel
2690 
2691   Arguments:    channel:     The channel number to start the search at
2692 
2693   Returns:      WM_ERRCODE_SUCCESS        - Searching
2694                 WM_ERRCODE_NOMORE_CHANNEL - There are no more channels to search
2695                 WM_ERRCODE_API_ERR        - WM_MeasureChannel API call failure
2696  *---------------------------------------------------------------------------*/
WH_StateInMeasureChannel(u16 channel)2697 static u16 WH_StateInMeasureChannel(u16 channel)
2698 {
2699     u16     allowedChannel;
2700     u16     result;
2701 
2702     allowedChannel = WM_GetAllowedChannel();
2703 
2704     if (allowedChannel == 0x8000)
2705     {
2706         // If 0x8000 is returned, it indicates that wireless is not initialized or there is some other abnormality with the wireless library. Therefore, set to an error.
2707         //
2708         WH_REPORT_FAILURE(WM_ERRCODE_ILLEGAL_STATE);
2709         WH_ChangeSysState(WH_SYSSTATE_ERROR);
2710         return WM_ERRCODE_ILLEGAL_STATE;
2711     }
2712     if (allowedChannel == 0)
2713     {
2714         // If 0 has been returned, this is a special state wherein wireless signals cannot be used. Therefore, return a value indicating that there are no available channels.
2715         //
2716         WH_REPORT_FAILURE(WH_ERRCODE_NO_RADIO);
2717         WH_ChangeSysState(WH_SYSSTATE_ERROR);
2718         return WH_ERRCODE_NOMORE_CHANNEL;
2719     }
2720 
2721     while (((1 << (channel - 1)) & allowedChannel) == 0)
2722     {
2723         channel++;
2724         if (channel > 16)
2725         {
2726             /* When finished searching all allowed channels */
2727             return WH_ERRCODE_NOMORE_CHANNEL;
2728         }
2729     }
2730 
2731     result = WHi_MeasureChannel(WH_StateOutMeasureChannel, channel);
2732     if (result != WM_ERRCODE_OPERATING)
2733     {
2734         return result;
2735     }
2736     return result;
2737 }
2738 
2739 /*---------------------------------------------------------------------------*
2740   Name:         WH_StateOutMeasureChannel
2741 
2742   Arguments:    arg:    The WMMeasureChannelCallback structure for notification of the search results
2743 
2744   Returns:      None.
2745  *---------------------------------------------------------------------------*/
WH_StateOutMeasureChannel(void * arg)2746 static void WH_StateOutMeasureChannel(void *arg)
2747 {
2748     u16     result;
2749     u16     channel;
2750     WMMeasureChannelCallback *cb = (WMMeasureChannelCallback *)arg;
2751     WH_TRACE_STATE;
2752 
2753     if (cb->errcode != WM_ERRCODE_SUCCESS)
2754     {
2755         // If there is anything wrong
2756         // It can be assumed that wireless signals are unusable if MeasureChannel fails, so an error state will be the result.
2757         //
2758         WH_REPORT_FAILURE(cb->errcode);
2759         WH_ChangeSysState(WH_SYSSTATE_ERROR);
2760         return;
2761     }
2762 
2763     WH_TRACE("channel %d bratio = 0x%x\n", cb->channel, cb->ccaBusyRatio);
2764 
2765     channel = cb->channel;
2766 
2767     /* Get a channel with a lower usage rate (initial value is 101%, so be sure to select the top) */
2768     if (sChannelBusyRatio > cb->ccaBusyRatio)
2769     {
2770         sChannelBusyRatio = cb->ccaBusyRatio;
2771         sChannelBitmap = (u16)(1 << (channel - 1));
2772     }
2773     else if (sChannelBusyRatio == cb->ccaBusyRatio)
2774     {
2775         sChannelBitmap |= 1 << (channel - 1);
2776     }
2777 
2778     result = WH_StateInMeasureChannel(++channel);
2779 
2780     if (result == WH_ERRCODE_NOMORE_CHANNEL)
2781     {
2782         // The channel search ends
2783         WH_ChangeSysState(WH_SYSSTATE_MEASURECHANNEL);
2784         return;
2785     }
2786 
2787     if (result != WM_ERRCODE_OPERATING)
2788     {
2789         // Error complete
2790         WH_ChangeSysState(WH_SYSSTATE_ERROR);
2791         return;
2792     }
2793 }
2794 
2795 /* ----------------------------------------------------------------------
2796   Checks the signal use rate
2797   ---------------------------------------------------------------------- */
WHi_MeasureChannel(WMCallbackFunc func,u16 channel)2798 static WMErrCode WHi_MeasureChannel(WMCallbackFunc func, u16 channel)
2799 {
2800 #define WH_MEASURE_TIME         30     // The time interval in ms for picking up the signal for making one communication for one frame
2801 #define WH_MEASURE_CS_OR_ED     3      // The logical OR of the carrier sense and the ED value
2802 #define WH_MEASURE_ED_THRESHOLD 17     // The recommended ED threshold value which has been empirically shown to be effective
2803 
2804     /*
2805      * A value considered to be empirically valid is used as a parameter for getting the wireless activity ratio
2806      *
2807      */
2808     return WM_MeasureChannel(func,     /* Callback settings */
2809                              WH_MEASURE_CS_OR_ED,       /* CS or ED */
2810                              WH_MEASURE_ED_THRESHOLD,   /* Invalid only when the 2nd argument is carrier sense */
2811                              channel,  /* Current search channel */
2812                              WH_MEASURE_TIME);  /*Search time (in ms) of each channel */
2813 }
2814 
2815 
2816 /*---------------------------------------------------------------------------*
2817   Name:         WH_GetMeasureChannel
2818 
2819   Description:  Returns the channel with the lowest usage rate from all the usable channels.
2820                 The WH_MeasureChannel operations must be complete and it must be in a WH_SYSSTATE_MEASURECHANNEL state.
2821 
2822                 When this function is called, the channel with the lowest use rate is returned and the state transitions to WH_SYSSTATE_IDLE.
2823 
2824 
2825   Arguments:    None.
2826 
2827   Returns:      The channel number of the usable channel with the lowest usage rate
2828  *---------------------------------------------------------------------------*/
WH_GetMeasureChannel(void)2829 u16 WH_GetMeasureChannel(void)
2830 {
2831     WH_ASSERT(sSysState == WH_SYSSTATE_MEASURECHANNEL);
2832 
2833     WH_ChangeSysState(WH_SYSSTATE_IDLE);
2834     sChannel = (u16)SelectChannel(sChannelBitmap);
2835     WH_TRACE("decided channel = %d\n", sChannel);
2836     return sChannel;
2837 }
2838 
2839 
2840 /*---------------------------------------------------------------------------*
2841   Name:         SelectChannel
2842 
2843   Description:  Gets the channel with the lowest usage rate.
2844                 If there are multiple channels with the lowest usage rate, a random number is used.
2845 
2846 
2847   Arguments:    Channel bitmap
2848 
2849   Returns:      The channel number of the usable channel with the lowest usage rate
2850  *---------------------------------------------------------------------------*/
SelectChannel(u16 bitmap)2851 static s16 SelectChannel(u16 bitmap)
2852 {
2853     s16     i;
2854     s16     channel = 0;
2855     u16     num = 0;
2856     u16     select;
2857 
2858     for (i = 0; i < 16; i++)
2859     {
2860         if (bitmap & (1 << i))
2861         {
2862             channel = (s16)(i + 1);
2863             num++;
2864         }
2865     }
2866 
2867     if (num <= 1)
2868     {
2869         return channel;
2870     }
2871 
2872     // If there are multiple channels of the same signal usage rate
2873     select = (u16)(((RAND() & 0xFF) * num) / 0x100);
2874 
2875     channel = 1;
2876 
2877     for (i = 0; i < 16; i++)
2878     {
2879         if (bitmap & 1)
2880         {
2881             if (select == 0)
2882             {
2883                 return (s16)(i + 1);
2884             }
2885             select--;
2886         }
2887         bitmap >>= 1;
2888     }
2889 
2890     return 0;
2891 }
2892 
2893 
2894 /**************************************************************************
2895  * Functions initializing wireless and switching to a communication enabled state are given below
2896  **************************************************************************/
2897 
2898 /* ----------------------------------------------------------------------
2899    Name:        WH_Initialize
2900    Description: Performs initialization operations and starts the initialization sequence.
2901    Arguments:   None.
2902    Returns:     TRUE if the sequence start was a success.
2903    ---------------------------------------------------------------------- */
WH_Initialize(void)2904 BOOL WH_Initialize(void)
2905 {
2906     if (whInitialized)
2907     {
2908         return FALSE;
2909     }
2910 
2911     if (sIndicationCallback == NULL)
2912     {
2913         sIndicationCallback = WH_IndicateHandler;
2914     }
2915 
2916     sRecvBufferSize = 0;
2917     sSendBufferSize = 0;
2918 
2919     sReceiverFunc = NULL;
2920     sMyAid = 0;
2921     sConnectBitmap = WH_BITMAP_EMPTY;
2922     sErrCode = WM_ERRCODE_SUCCESS;
2923 
2924     sParentParam.userGameInfo = NULL;
2925     sParentParam.userGameInfoLength = 0;
2926 
2927     MI_CpuClear8(sScanBuf, sizeof(sScanBuf));
2928     MI_CpuClear8(&sBssDesc, sizeof(sBssDesc));
2929 
2930     MI_CpuClear8(sConnectionSsid, sizeof(sConnectionSsid));
2931     // Sets the connected child user determination function to NULL (multiboot)
2932     sJudgeAcceptFunc = NULL;
2933 
2934     // Starts the initialization sequence
2935     if (!WH_StateInInitialize())
2936     {
2937         return FALSE;
2938     }
2939 
2940     whInitialized = 1;
2941 
2942     return TRUE;
2943 }
2944 
2945 /* ----------------------------------------------------------------------
2946    Indicate handler
2947    ---------------------------------------------------------------------- */
WH_IndicateHandler(void * arg)2948 static void WH_IndicateHandler(void *arg)
2949 {
2950     WMindCallback *cb = (WMindCallback *)arg;
2951 
2952     if (cb->errcode == WM_ERRCODE_FIFO_ERROR)
2953     {
2954         // In case an unrecoverable error occurred.
2955         // Display a screen or otherwise notify the player of this, and stop wireless communications.
2956         //
2957         WH_ChangeSysState(WH_SYSSTATE_ERROR);
2958         OS_TPanic("Wireless FATAL error occured.\n");
2959     }
2960 }
2961 
2962 /* ----------------------------------------------------------------------
2963    State: Initialize
2964    ---------------------------------------------------------------------- */
WH_StateInInitialize(void)2965 static BOOL WH_StateInInitialize(void)
2966 {
2967     // Starts the initialization sequence
2968     WMErrCode result;
2969     WH_TRACE_STATE;
2970 
2971 #ifndef WH_USE_DETAILED_INITIALIZE
2972     WH_ChangeSysState(WH_SYSSTATE_BUSY);
2973     result = WM_Initialize(&sWmBuffer, WH_StateOutInitialize, WH_DMA_NO);
2974     if (result != WM_ERRCODE_OPERATING)
2975     {
2976         WH_REPORT_FAILURE(result);
2977         WH_ChangeSysState(WH_SYSSTATE_FATAL);
2978         return FALSE;
2979     }
2980 
2981 #else
2982     // WM_Init is a synchronous function
2983     result = WM_Init(&sWmBuffer, WH_DMA_NO);
2984     if (result != WM_ERRCODE_SUCCESS)
2985     {
2986         WH_REPORT_FAILURE(result);
2987         return FALSE;
2988     }
2989 
2990     WH_ChangeSysState(WH_SYSSTATE_BUSY);
2991 
2992     if (!WH_StateInEnable())
2993     {
2994         WH_ChangeSysState(WH_SYSSTATE_FATAL);
2995         return FALSE;
2996     }
2997 #endif
2998 
2999     return TRUE;
3000 }
3001 
3002 
3003 #ifndef WH_USE_DETAILED_INITIALIZE
3004 
WH_StateOutInitialize(void * arg)3005 static void WH_StateOutInitialize(void *arg)
3006 {
3007     // State after power-on
3008     WMErrCode result;
3009     WMCallback *cb = (WMCallback *)arg;
3010     WH_TRACE_STATE;
3011 
3012     if (cb->errcode != WM_ERRCODE_SUCCESS)
3013     {
3014         WH_REPORT_FAILURE(cb->errcode);
3015         WH_ChangeSysState(WH_SYSSTATE_FATAL);
3016         return;
3017     }
3018     // Sets the callback function to receive notifications that are generated irregularly
3019     result = WM_SetIndCallback(sIndicationCallback);
3020     if (result != WM_ERRCODE_SUCCESS)
3021     {
3022         WH_REPORT_FAILURE(result);
3023         WH_ChangeSysState(WH_SYSSTATE_FATAL);
3024         return;
3025     }
3026 
3027     // Changes the system state to idling (waiting)
3028     WH_ChangeSysState(WH_SYSSTATE_IDLE);
3029 
3030     // Does not set the next state, so the sequence ends here.
3031     // If WH_Connect is called while in this state, it changes to the connection operation.
3032 }
3033 
3034 #else
3035 
3036 /* ----------------------------------------------------------------------
3037    Enable
3038   ---------------------------------------------------------------------- */
WH_StateInEnable(void)3039 static BOOL WH_StateInEnable(void)
3040 {
3041     // Makes the hardware usable. (Gets the permission to use.)
3042     WMErrCode result;
3043     WH_TRACE_STATE;
3044 
3045     result = WM_Enable(WH_StateOutEnable);
3046     if (result != WM_ERRCODE_OPERATING)
3047     {
3048         WH_REPORT_FAILURE(result);
3049         WH_ChangeSysState(WH_SYSSTATE_FATAL);
3050         return FALSE;
3051     }
3052     return TRUE;
3053 }
3054 
WH_StateOutEnable(void * arg)3055 static void WH_StateOutEnable(void *arg)
3056 {
3057     // When the hardware use is permitted, it changes to the power-on state
3058     WMCallback *cb = (WMCallback *)arg;
3059     WH_TRACE_STATE;
3060 
3061     if (cb->errcode != WM_ERRCODE_SUCCESS)
3062     {
3063         WH_REPORT_FAILURE(cb->errcode);
3064         WH_ChangeSysState(WH_SYSSTATE_FATAL);
3065         return;
3066     }
3067 
3068     if (!WH_StateInPowerOn())
3069     {
3070         WH_ChangeSysState(WH_SYSSTATE_FATAL);
3071         return;
3072     }
3073 }
3074 
3075 /* ----------------------------------------------------------------------
3076    Power on
3077   ---------------------------------------------------------------------- */
WH_StateInPowerOn(void)3078 static BOOL WH_StateInPowerOn(void)
3079 {
3080     // Because the wireless hardware became usable, start supplying power
3081     WMErrCode result;
3082     WH_TRACE_STATE;
3083 
3084     result = WM_PowerOn(WH_StateOutPowerOn);
3085     if (result != WM_ERRCODE_OPERATING)
3086     {
3087         WH_REPORT_FAILURE(result);
3088         WH_ChangeSysState(WH_SYSSTATE_FATAL);
3089         return FALSE;
3090     }
3091 
3092     return TRUE;
3093 }
3094 
WH_StateOutPowerOn(void * arg)3095 static void WH_StateOutPowerOn(void *arg)
3096 {
3097     // State after power-on
3098     WMErrCode result;
3099     WMCallback *cb = (WMCallback *)arg;
3100     WH_TRACE_STATE;
3101 
3102     if (cb->errcode != WM_ERRCODE_SUCCESS)
3103     {
3104         WH_REPORT_FAILURE(cb->errcode);
3105         WH_ChangeSysState(WH_SYSSTATE_FATAL);
3106         return;
3107     }
3108 
3109     // Sets the callback function to receive notifications that are generated irregularly
3110     result = WM_SetIndCallback(sIndicationCallback);
3111     if (result != WM_ERRCODE_SUCCESS)
3112     {
3113         WH_REPORT_FAILURE(result);
3114         WH_ChangeSysState(WH_SYSSTATE_FATAL);
3115         return;
3116     }
3117 
3118     // Changes the system state to idling (waiting)
3119     WH_ChangeSysState(WH_SYSSTATE_IDLE);
3120 
3121     // Does not set the next state, so the sequence ends here.
3122     // If WH_Connect is called while in this state, it changes to the connection operation.
3123 }
3124 
3125 #endif // #ifdef WH_USE_DETAILED_INITIALIZE
3126 
3127 
3128 /* ----------------------------------------------------------------------
3129   Name:        WH_ParentConnect
3130   Description: Starts the connection sequence.
3131   Arguments:   mode:     If WH_CONNECTMODE_MP_PARENT, MP starts as a parent.
3132                          If WH_CONNECTMODE_DS_PARENT, DataSharing starts as a parent.
3133                          If WH_CONNECTMODE_KS_PARENT, KeySharing starts as a parent.
3134                tgid:     The parent device communications tgid
3135                channel:  The parent device communications channel
3136   Returns:     TRUE if the connection sequence is successful
3137   ---------------------------------------------------------------------- */
WH_ParentConnect(int mode,u16 tgid,u16 channel)3138 BOOL WH_ParentConnect(int mode, u16 tgid, u16 channel)
3139 {
3140     // If not in a standby state, the connection sequence cannot be started
3141     WH_ASSERT(sSysState == WH_SYSSTATE_IDLE);
3142 
3143     // Calculation of send and receive buffer size for WM_StartMP()
3144     // Use the WM_SIZE_MP_* function macros to statically allocate a buffer in advance. If this may be allocated dynamically, use the WM_GetReceiveBufferSize function after the parent and child have been connected and immediately before calling the WM_StartMP function.
3145     //
3146     //
3147     // Similarly, use the WM_SIZE_MP_* function macros to statically allocate a buffer in advance. If this may be allocated dynamically, use the WM_GetSendBufferSize function after the parent and child have been connected and immediately before calling the WM_StartMP function.
3148     //
3149     //
3150     sRecvBufferSize = WH_PARENT_RECV_BUFFER_SIZE;
3151     sSendBufferSize = WH_PARENT_SEND_BUFFER_SIZE;
3152 
3153     WH_TRACE("recv buffer size = %d\n", sRecvBufferSize);
3154     WH_TRACE("send buffer size = %d\n", sSendBufferSize);
3155 
3156     sConnectMode = mode;
3157     WH_ChangeSysState(WH_SYSSTATE_BUSY);
3158 
3159     sParentParam.tgid = tgid;
3160     sParentParam.channel = channel;
3161     sParentParam.beaconPeriod = WM_GetDispersionBeaconPeriod();
3162     sParentParam.parentMaxSize = WH_PARENT_MAX_SIZE;
3163     sParentParam.childMaxSize = WH_CHILD_MAX_SIZE;
3164     sParentParam.maxEntry = WH_CHILD_MAX;
3165     sParentParam.CS_Flag = 0;
3166     sParentParam.multiBootFlag = 0;
3167     sParentParam.entryFlag = 1;
3168     sParentParam.KS_Flag = (u16)((mode == WH_CONNECTMODE_KS_PARENT) ? 1 : 0);
3169 
3170     switch (mode)
3171     {
3172     case WH_CONNECTMODE_MP_PARENT:
3173     case WH_CONNECTMODE_KS_PARENT:
3174     case WH_CONNECTMODE_DS_PARENT:
3175         // Starts the connection in child mode
3176         return WH_StateInSetParentParam();
3177     default:
3178         break;
3179     }
3180 
3181     WH_TRACE("unknown connect mode %d\n", mode);
3182     return FALSE;
3183 }
3184 
3185 
3186 /* ----------------------------------------------------------------------
3187   Name:        WH_ChildConnect
3188   Description: Starts the connection sequence.
3189   Arguments:   mode:     Start MP as the child if WH_CONNECTMODE_MP_CHILD.
3190                          Start DataSharing as the child if WH_CONNECTMODE_DS_CHILD.
3191                          Start KeySharing as the child if WH_CONNECTMODE_KS_CHILD.
3192                bssDesc:  The bssDesc of the parent device to connect to.
3193 
3194   Returns:     TRUE if the connection sequence is successful
3195   ---------------------------------------------------------------------- */
WH_ChildConnect(int mode,WMBssDesc * bssDesc)3196 BOOL WH_ChildConnect(int mode, WMBssDesc *bssDesc)
3197 {
3198     // If not in a standby state, the connection sequence cannot be started
3199     WH_ASSERT(sSysState == WH_SYSSTATE_IDLE);
3200 
3201     // Calculation of send and receive buffer size for WM_StartMP()
3202     // Use the WM_SIZE_MP_* function macros to statically allocate a buffer in advance. If this may be allocated dynamically, use the WM_GetReceiveBufferSize function after the parent and child have been connected and immediately before calling the WM_StartMP function.
3203     //
3204     //
3205     // Similarly, use the WM_SIZE_MP_* function macros to statically allocate a buffer in advance. If this may be allocated dynamically, use the WM_GetSendBufferSize function after the parent and child have been connected and immediately before calling the WM_StartMP function.
3206     //
3207     //
3208     sRecvBufferSize = WH_CHILD_RECV_BUFFER_SIZE;
3209     sSendBufferSize = WH_CHILD_SEND_BUFFER_SIZE;
3210 
3211     WH_TRACE("recv buffer size = %d\n", sRecvBufferSize);
3212     WH_TRACE("send buffer size = %d\n", sSendBufferSize);
3213 
3214     sConnectMode = mode;
3215     WH_ChangeSysState(WH_SYSSTATE_BUSY);
3216 
3217     switch (mode)
3218     {
3219     case WH_CONNECTMODE_MP_CHILD:
3220     case WH_CONNECTMODE_KS_CHILD:
3221     case WH_CONNECTMODE_DS_CHILD:
3222         // Starts the connection in child mode.
3223         // Uses the saved BssDesc for the parent and connects without scanning.
3224         MI_CpuCopy8(bssDesc, &sBssDesc, sizeof(WMBssDesc));
3225         if (sChildWEPKeyGenerator != NULL)
3226         {
3227             // If the WEP Key Generator is configured, set the WEP Key
3228             return WH_StateInSetChildWEPKey();
3229         }
3230         else
3231         {
3232             return WH_StateInStartChild();
3233         }
3234     default:
3235         break;
3236     }
3237 
3238     WH_TRACE("unknown connect mode %d\n", mode);
3239     return FALSE;
3240 }
3241 
3242 /*---------------------------------------------------------------------------*
3243   Name:         WH_SetJudgeAcceptFunc
3244 
3245   Description:  Sets the functions used to determine whether to accept the child device connection.
3246 
3247   Arguments:    Set the child device connection determination functions.
3248 
3249   Returns:      None.
3250  *---------------------------------------------------------------------------*/
WH_SetJudgeAcceptFunc(WHJudgeAcceptFunc func)3251 void WH_SetJudgeAcceptFunc(WHJudgeAcceptFunc func)
3252 {
3253     sJudgeAcceptFunc = func;
3254 }
3255 
3256 
3257 /**************************************************************************
3258  * The functions below are for direct MP communication that uses the WH_DATA_PORT port
3259  **************************************************************************/
3260 
3261 /* ----------------------------------------------------------------------
3262    Name:        WH_SetReceiver
3263    Description: Configures the data receipt callback in the WH_DATA_PORT port.
3264    Arguments:   proc: The data receipt callback
3265    Returns:     None.
3266    ---------------------------------------------------------------------- */
WH_SetReceiver(WHReceiverFunc proc)3267 void WH_SetReceiver(WHReceiverFunc proc)
3268 {
3269     sReceiverFunc = proc;
3270     if (WM_SetPortCallback(WH_DATA_PORT, WH_PortReceiveCallback, NULL) != WM_ERRCODE_SUCCESS)
3271     {
3272         WH_ChangeSysState(WH_SYSSTATE_ERROR);
3273         WH_TRACE("WM not Initialized\n");
3274     }
3275 }
3276 
3277 /* ----------------------------------------------------------------------
3278    Name:        WH_SendData
3279    Description: Starts sending data to the WH_DATA_PORT port.
3280                (For MP communications. There is no need to call this function while data sharing, etc.)
3281    Arguments:   size:  The data size
3282    Returns:     Returns TRUE if starting the send is successful.
3283    ---------------------------------------------------------------------- */
WH_SendData(const void * data,u16 size,WHSendCallbackFunc callback)3284 BOOL WH_SendData(const void *data, u16 size, WHSendCallbackFunc callback)
3285 {
3286     return WH_StateInSetMPData(data, size, callback);
3287 }
3288 
3289 
3290 /**************************************************************************
3291  * The functions below control data sharing communication
3292  **************************************************************************/
3293 
3294 /* ----------------------------------------------------------------------
3295    Name:        WH_GetKeySet
3296    Description: Reads the common key data.
3297    Arguments:   keyset: Data storage destination
3298    Returns:     If it succeeds, returns TRUE.
3299    ---------------------------------------------------------------------- */
WH_GetKeySet(WMKeySet * keyset)3300 BOOL WH_GetKeySet(WMKeySet *keyset)
3301 {
3302     WMErrCode result;
3303 
3304     if (sSysState != WH_SYSSTATE_KEYSHARING)
3305     {
3306         WH_TRACE("WH_GetKeySet failed (invalid system state)\n");
3307         return FALSE;
3308     }
3309 
3310     if ((sConnectMode != WH_CONNECTMODE_KS_CHILD) && (sConnectMode != WH_CONNECTMODE_KS_PARENT))
3311     {
3312         WH_TRACE("WH_GetKeySet failed (invalid connect mode)\n");
3313         return FALSE;
3314     }
3315 
3316     result = WM_GetKeySet(&sWMKeySetBuf, keyset);
3317     if (result != WM_ERRCODE_SUCCESS)
3318     {
3319         WH_REPORT_FAILURE(result);
3320         return FALSE;
3321     }
3322 
3323     return TRUE;
3324 }
3325 
3326 /* ----------------------------------------------------------------------
3327    Name:        WH_GetSharedDataAdr
3328   Description: Calculates and gets the data address obtained from the machine with the designated aid from the shared data address.
3329 
3330    Arguments:   aid: The machine designation
3331    Returns:     NULL on failure.
3332    ---------------------------------------------------------------------- */
WH_GetSharedDataAdr(u16 aid)3333 u16    *WH_GetSharedDataAdr(u16 aid)
3334 {
3335     return WM_GetSharedDataAddress(&sDSInfo, &sDataSet, aid);
3336 }
3337 
3338 /* ----------------------------------------------------------------------
3339    Name:        WH_StepDS
3340    Description: Proceeds to the next synchronized data sharing process.
3341                 If communication is performed for each frame, this function must also be called for each frame.
3342 
3343    Arguments:   data: Data to send
3344    Returns:     If it succeeds, returns TRUE.
3345    ---------------------------------------------------------------------- */
WH_StepDS(const void * data)3346 BOOL WH_StepDS(const void *data)
3347 {
3348     WMErrCode result;
3349 
3350     result = WM_StepDataSharing(&sDSInfo, (const u16 *)data, &sDataSet);
3351 
3352     if (result == WM_ERRCODE_NO_CHILD)
3353     {
3354         // A parent with no children (this can be made an error if desired)
3355         return TRUE;
3356     }
3357 
3358     if (result == WM_ERRCODE_NO_DATASET)
3359     {
3360         WH_TRACE("WH_StepDataSharing - Warning No DataSet\n");
3361         WH_SetError(result);
3362         return FALSE;
3363     }
3364 
3365     if (result != WM_ERRCODE_SUCCESS)
3366     {
3367         WH_REPORT_FAILURE(result);
3368         return FALSE;
3369     }
3370 
3371     return TRUE;
3372 }
3373 
3374 /* ----------------------------------------------------------------------
3375    Name:        WH_GetBitmapDS
3376    Description: Gets a list of systems that use data sharing.
3377    Arguments:   None.
3378    Returns:     Bitmap.
3379    ---------------------------------------------------------------------- */
WH_GetBitmapDS(void)3380 u16 WH_GetBitmapDS(void)
3381 {
3382 	return sDataSet.receivedBitmap;
3383 }
3384 /**************************************************************************
3385  * The functions below end communication and transition to initialization states
3386  **************************************************************************/
3387 
3388 /* ----------------------------------------------------------------------
3389    Name:        WH_Reset
3390    Description: Starts the reset sequence.
3391                 When this function is called, it resets regardless of the current state.
3392         It is used for forced recovery from errors.
3393    Arguments:   None.
3394    Returns:     None.
3395    ---------------------------------------------------------------------- */
WH_Reset(void)3396 void WH_Reset(void)
3397 {
3398     WMErrCode result;
3399 
3400     if (sSysState == WH_SYSSTATE_DATASHARING)
3401     {
3402         result = WM_EndDataSharing(&sDSInfo);
3403         if (result != WM_ERRCODE_SUCCESS)
3404         {
3405             WH_REPORT_FAILURE(result);
3406         }
3407     }
3408 
3409     if (!WH_StateInReset())
3410     {
3411         WH_ChangeSysState(WH_SYSSTATE_FATAL);
3412     }
3413 }
3414 
3415 /* ----------------------------------------------------------------------
3416    Name:        WH_Finalize
3417    Description: Starts the post-processing / end sequence.
3418                 When this function is called, the current state is referenced and an appropriate end sequence is executed.
3419 
3420                 This function is used in the normal end process (not WH_Reset).
3421    Arguments:   None.
3422    Returns:     None.
3423    ---------------------------------------------------------------------- */
WH_Finalize(void)3424 void WH_Finalize(void)
3425 {
3426     if (sSysState == WH_SYSSTATE_IDLE)
3427     {
3428         WH_TRACE("already WH_SYSSTATE_IDLE\n");
3429         return;
3430     }
3431 
3432     WH_TRACE("WH_Finalize, state = %d\n", sSysState);
3433 
3434     if (sSysState == WH_SYSSTATE_SCANNING)
3435     {
3436         if (!WH_EndScan())
3437         {
3438             WH_Reset();
3439         }
3440         return;
3441     }
3442 
3443 
3444     if ((sSysState != WH_SYSSTATE_KEYSHARING) &&
3445         (sSysState != WH_SYSSTATE_DATASHARING) && (sSysState != WH_SYSSTATE_CONNECTED))
3446     {
3447         // Resets if there is no connection, there is an error, and so on
3448         WH_ChangeSysState(WH_SYSSTATE_BUSY);
3449         WH_Reset();
3450         return;
3451     }
3452 
3453     WH_ChangeSysState(WH_SYSSTATE_BUSY);
3454 
3455     switch (sConnectMode)
3456     {
3457     case WH_CONNECTMODE_KS_CHILD:
3458         if (!WH_StateInEndChildKeyShare())
3459         {
3460             WH_Reset();
3461         }
3462         break;
3463 
3464     case WH_CONNECTMODE_DS_CHILD:
3465         if (WM_EndDataSharing(&sDSInfo) != WM_ERRCODE_SUCCESS)
3466         {
3467             WH_Reset();
3468             break;
3469         }
3470         // Don't break
3471 
3472     case WH_CONNECTMODE_MP_CHILD:
3473         if (!WH_StateInEndChildMP())
3474         {
3475             WH_Reset();
3476         }
3477         break;
3478 
3479     case WH_CONNECTMODE_KS_PARENT:
3480         if (!WH_StateInEndParentKeyShare())
3481         {
3482             WH_Reset();
3483         }
3484         break;
3485 
3486     case WH_CONNECTMODE_DS_PARENT:
3487         if (WM_EndDataSharing(&sDSInfo) != WM_ERRCODE_SUCCESS)
3488         {
3489             WH_Reset();
3490             break;
3491         }
3492         // Don't break
3493 
3494     case WH_CONNECTMODE_MP_PARENT:
3495         if (!WH_StateInEndParentMP())
3496         {
3497             WH_Reset();
3498         }
3499     }
3500 }
3501 
3502 /*---------------------------------------------------------------------------*
3503   Name:         WH_End
3504 
3505   Description:  Ends wireless communications.
3506 
3507   Arguments:    None.
3508 
3509   Returns:      If it succeeds, returns TRUE.
3510  *---------------------------------------------------------------------------*/
WH_End(void)3511 BOOL WH_End(void)
3512 {
3513     WH_ASSERT(sSysState == WH_SYSSTATE_IDLE);
3514 
3515     WH_ChangeSysState(WH_SYSSTATE_BUSY);
3516     if (WM_End(WH_StateOutEnd) != WM_ERRCODE_OPERATING)
3517     {
3518         WH_ChangeSysState(WH_SYSSTATE_ERROR);
3519 
3520         return FALSE;
3521     }
3522 
3523     whInitialized = 0;
3524 
3525     return TRUE;
3526 }
3527 
3528 /*---------------------------------------------------------------------------*
3529   Name:         WH_GetCurrentAid
3530 
3531   Description:  Gets its own current AID.
3532                 Children may change when they connect or disconnect.
3533 
3534   Arguments:    None.
3535 
3536   Returns:      AID value.
3537  *---------------------------------------------------------------------------*/
WH_GetCurrentAid(void)3538 u16 WH_GetCurrentAid(void)
3539 {
3540     return sMyAid;
3541 }
3542 
3543 /*---------------------------------------------------------------------------*
3544   Name:         WH_SetParentWEPKeyGenerator
3545 
3546   Description:  Sets the function that generates WEP Key.
3547                 If this function is called, WEP will be used for authentication during connection.
3548                 Using a unique algorithm for each game application, it sets the parent and child to the same value before connection.
3549 
3550                 This function is for parents.
3551 
3552   Arguments:    func:    Pointer to the function that generates the WEP Key
3553                         If NULL is specified, WEP Key is not used
3554 
3555   Returns:      None.
3556  *---------------------------------------------------------------------------*/
WH_SetParentWEPKeyGenerator(WHParentWEPKeyGeneratorFunc func)3557 void WH_SetParentWEPKeyGenerator(WHParentWEPKeyGeneratorFunc func)
3558 {
3559     sParentWEPKeyGenerator = func;
3560 }
3561 
3562 /*---------------------------------------------------------------------------*
3563   Name:         WH_SetChildWEPKeyGenerator
3564 
3565   Description:  Sets the function that generates WEP Key.
3566                 If this function is called, WEP will be used for authentication during connection.
3567                 Using a unique algorithm for each game application, it sets the parent and child to the same value before connection.
3568 
3569                 This function is for children.
3570 
3571   Arguments:    func:    Pointer to the function that generates the WEP Key
3572                         If NULL is specified, WEP Key is not used
3573 
3574   Returns:      None.
3575  *---------------------------------------------------------------------------*/
WH_SetChildWEPKeyGenerator(WHChildWEPKeyGeneratorFunc func)3576 void WH_SetChildWEPKeyGenerator(WHChildWEPKeyGeneratorFunc func)
3577 {
3578     sChildWEPKeyGenerator = func;
3579 }
3580 
3581 /*---------------------------------------------------------------------------*
3582   Name:         WH_SetIndCallback
3583 
3584   Description:  Sets the callback function specified in the WM_SetIndCallback function called by WH_Initialize.
3585 
3586                 This function should be called before WH_Initialize is called.
3587                 If a callback function is not specified by this function, the default WH_IndicateHandler will be set as the callback.
3588 
3589 
3590   Arguments:    callback:    Callback for the indication notification specified by WM_SetIndCallback
3591 
3592   Returns:      None.
3593  *---------------------------------------------------------------------------*/
WH_SetIndCallback(WMCallbackFunc callback)3594 void WH_SetIndCallback(WMCallbackFunc callback)
3595 {
3596     sIndicationCallback = callback;
3597 }
3598 
3599 /*---------------------------------------------------------------------------*
3600   Name:         WH_SetSessionUpdateCallback
3601 
3602   Description:  This function registers callbacks to be invoked when there is a connection, disconnection, or new child connection.
3603 
3604   Arguments:    cb: The callback to register
3605 
3606   Returns:      None.
3607  *---------------------------------------------------------------------------*/
WH_SetSessionUpdateCallback(WMCallbackFunc callback)3608 void WH_SetSessionUpdateCallback(WMCallbackFunc callback)
3609 {
3610     sPortExtraCallback = callback;
3611 }
3612 
3613 #if defined(WM_DEMO_WIRELESS_SHARED_WC_WH_CONFIG_H_)
3614 ///////////////////////////////////////////////////////////////////////////////
3615 ///////////////////////////////////////////////////////////////////////////////
3616 ///////////////////////////////////////////////////////////////////////////////
3617 // This is a wrapper layer that implements, in WH, the same features as the existing WC sample module.
3618 // Existing interfaces made public in wc.h are supported unchanged.
3619 
3620 // The major differences between WC and WH are as follows.
3621 //
3622 //   - WC specifies WMParentParam unchanged at initialization, but WH breaks up the parameters and specifies them as function arguments whenever a state transition occurs.
3623 //
3624 //
3625 //   - In past versions of WC, the driver's internal state could become unstable if the user changed the contents of the pointer given to WcInit(). In the future, this kind of behavior will be avoided and pointer contents will be internally duplicated.
3626 //
3627 //
3628 //
3629 //   - A steady wireless state is indicated by WH_SYSSTATE_IDLE (the IDLE state) for WH and WC_STATUS_READY (the READY state) for WC.
3630 //
3631 //     In the future, the IDLE state will be made the steady state for WC, as well.
3632 //
3633 
3634 /*---------------------------------------------------------------------------*
3635   Name:         WcIndicateCallback
3636 
3637   Description:  Indication callback from WH.
3638 
3639   Arguments:    arg:         WMCallback
3640 
3641   Returns:      None.
3642  *---------------------------------------------------------------------------*/
WcIndicateCallback(void * arg)3643 static void WcIndicateCallback(void *arg)
3644 {
3645     WHCompatibleInfoForWC  *info = infoForWC;
3646     WMindCallback *cb = (WMindCallback *)arg;
3647     if (cb->errcode == WM_ERRCODE_FIFO_ERROR)
3648     {
3649         info->wcTarget = WC_STATUS_ERROR;
3650         info->wcStatus = WC_STATUS_ERROR;
3651     }
3652 }
3653 
3654 /*---------------------------------------------------------------------------*
3655   Name:         WcStateScheduler
3656 
3657   Description:  Executes actions that are currently possible for the target state.
3658 
3659   Arguments:    target:      The final state of the transition.
3660 
3661   Returns:      None.
3662  *---------------------------------------------------------------------------*/
WcStateScheduler(WCStatus target)3663 static void WcStateScheduler(WCStatus target)
3664 {
3665     WHCompatibleInfoForWC  *info = infoForWC;
3666     // If there is no error, change the state to which to transition.
3667     if (info->wcStatus != WC_STATUS_ERROR)
3668     {
3669         info->wcTarget = target;
3670         // If possible, perform an action here.
3671         if ((info->wcStatus != WC_STATUS_BUSY) &&
3672             (info->wcStatus != target))
3673         {
3674             // State transition to the MP parent device.
3675             if (target == WC_STATUS_PARENT)
3676             {
3677                 // If currently READY, MP can be started.
3678                 if (info->wcStatus == WC_STATUS_READY)
3679                 {
3680                     info->wcStatus = WC_STATUS_BUSY;
3681                     (void)WH_ParentConnect(info->useDS ? WH_CONNECTMODE_DS_PARENT : WH_CONNECTMODE_MP_PARENT,
3682                                            ++info->tmpTgid, info->targetChannel);
3683                 }
3684                 // If run as an MP child device, change to READY for a moment.
3685                 else if (info->wcStatus == WC_STATUS_CHILD)
3686                 {
3687                     info->wcStatus = WC_STATUS_BUSY;
3688                     WH_Reset();
3689                 }
3690             }
3691             // State transition to the MP child device.
3692             else if (target == WC_STATUS_CHILD)
3693             {
3694                 // If currently READY, MP can be started.
3695                 if (info->wcStatus == WC_STATUS_READY)
3696                 {
3697                     info->wcStatus = WC_STATUS_BUSY;
3698                     {
3699                         static const u8 any[] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,};
3700                         // Simple Pictochat operation.
3701                         if (info->pictoCatchCallback)
3702                         {
3703                             (void)WH_StartScan((WHStartScanCallbackFunc)info->pictoCatchCallback,
3704                                                any, 0);
3705                         }
3706                         // Actual MP child device.
3707                         else
3708                         {
3709                             (void)WH_ChildConnectAuto(info->useDS ? WH_CONNECTMODE_DS_CHILD : WH_CONNECTMODE_MP_CHILD,
3710                                                       any, info->parentParam.channel);
3711                         }
3712                     }
3713                 }
3714                 // If run as an MP parent device, change to READY for a moment.
3715                 else if (info->wcStatus == WC_STATUS_PARENT)
3716                 {
3717                     info->wcStatus = WC_STATUS_BUSY;
3718                     WH_Reset();
3719                 }
3720             }
3721             // State transition to READY.
3722             else if (target == WC_STATUS_READY)
3723             {
3724                 // At any rate, end if MP communication is being performed.
3725                 if (info->wcStatus == WC_STATUS_PARENT)
3726                 {
3727                     info->wcStatus = WC_STATUS_BUSY;
3728                     WH_Reset();
3729                 }
3730                 else if (info->wcStatus == WC_STATUS_CHILD)
3731                 {
3732                     info->wcStatus = WC_STATUS_BUSY;
3733                     WH_Reset();
3734                 }
3735             }
3736         }
3737     }
3738 }
3739 
3740 /*---------------------------------------------------------------------------*
3741   Name:         WcStateCallback
3742 
3743   Description:  A callback invoked whenever the WH state is updated.
3744 
3745   Arguments:    state:       The current state.
3746                 prev:        The previous state.
3747 
3748   Returns:      None.
3749  *---------------------------------------------------------------------------*/
WcStateCallback(int state,int prev)3750 static void WcStateCallback(int state, int prev)
3751 {
3752     WHCompatibleInfoForWC  *info = infoForWC;
3753     BOOL                    needToNotify = TRUE;
3754     // General WM error.
3755     if (state == WH_SYSSTATE_ERROR)
3756     {
3757         // Terminate wireless if the child devices being communicated with were disconnected.
3758         if ((info->wcTarget == WC_STATUS_CHILD) &&
3759             (WH_GetLastError() == WH_ERRCODE_DISCONNECTED))
3760         {
3761             info->wcTarget = WC_STATUS_READY;
3762             if (info->wcStatus != WC_STATUS_BUSY)
3763             {
3764                 WH_Reset();
3765             }
3766         }
3767         // Otherwise, there is a margin to insert a WH_Reset() and retry.
3768         else
3769         {
3770             WH_Reset();
3771         }
3772     }
3773     // Completed the transition to the MP state, as well as CONNECT.
3774     // NOTE: The second time is an MP notification.
3775     // WC state transition.
3776     else if ((state == WH_SYSSTATE_CONNECTED) &&
3777              (prev == WH_SYSSTATE_CONNECTED))
3778     {
3779         info->wcStatus = (info->wcTarget == WC_STATUS_PARENT) ?
3780                           WC_STATUS_PARENT : WC_STATUS_CHILD;
3781         WcStateScheduler(info->wcTarget);
3782     }
3783     // WM_StartDataSharing() complete.
3784     // WC state transition.
3785     else if (state == WH_SYSSTATE_DATASHARING)
3786     {
3787         info->wcStatus = (info->wcTarget == WC_STATUS_PARENT) ?
3788                           WC_STATUS_PARENT : WC_STATUS_CHILD;
3789         WcStateScheduler(info->wcTarget);
3790     }
3791     // Reached the IDLE state.
3792     // WC state transition.
3793     else if (state == WH_SYSSTATE_IDLE)
3794     {
3795         if (!sAutoConnectFlag)
3796         {
3797             info->wcStatus = WC_STATUS_READY;
3798             WcStateScheduler(info->wcTarget);
3799         }
3800     }
3801     // WM_StartConnect() failure.
3802     // CAUTION!
3803     //     Originally, processing for the number of retries must be done.
3804     // Insert WH_Reset() and retry.
3805     else if (state == WH_SYSSTATE_CONNECT_FAIL)
3806     {
3807         WH_Reset();
3808     }
3809     // WM initialization and deallocation, as well as indicator setting functions.
3810     // An error indicating a difficulty in continuing processing because of some failure.
3811     // WC_STATUS_ERROR handling.
3812     else if (state == WH_SYSSTATE_FATAL)
3813     {
3814         info->wcStatus = WC_STATUS_ERROR;
3815         WcStateScheduler(info->wcTarget);
3816     }
3817     // Finish termination processing.
3818     else if (state == WH_SYSSTATE_STOP)
3819     {
3820         info->wcStatus = WC_STATUS_READY;
3821     }
3822     // MeasureChannel completion.
3823     // Read only the value and immediately force a transition to IDLE.
3824     // This callback is recursively notified.
3825     else if (state == WH_SYSSTATE_MEASURECHANNEL)
3826     {
3827         info->targetChannel = WH_GetMeasureChannel();
3828         needToNotify = FALSE;
3829     }
3830     // Anything else is a notification that does not require anything in particular to be done.
3831     else
3832     {
3833         // - WH_SYSSTATE_BUSY
3834         // - WH_SYSSTATE_SCANNING
3835         // - WH_SYSSTATE_KEYSHARING
3836         needToNotify = FALSE;
3837     }
3838     // May be on standby in WcWaitForState(), so send a notification
3839     if (needToNotify)
3840     {
3841         OS_WakeupThread(info->queue);
3842     }
3843 }
3844 
3845 /*---------------------------------------------------------------------------*
3846   Name:         WcWaitForState
3847 
3848   Description:  Blocks until a transition to the specified state, or until the transition fails.
3849                 This is only used in WcFinish().
3850 
3851   Arguments:    target:      State to which a transition must be done.
3852 
3853   Returns:      None.
3854  *---------------------------------------------------------------------------*/
WcWaitForState(int target)3855 static BOOL WcWaitForState(int target)
3856 {
3857     BOOL    succeeded = FALSE;
3858     OSIntrMode  bak_cpsr = OS_DisableInterrupts();
3859     for (;;)
3860     {
3861         int     state = WH_GetSystemState();
3862         if (state == target)
3863         {
3864             succeeded = TRUE;
3865             break;
3866         }
3867         // StartConnect failure.
3868         // Insert WH_Reset() and retry.
3869         // Here, we must add the fact that retries have been exceeded.
3870         else if (state == WH_SYSSTATE_CONNECT_FAIL)
3871         {
3872             break;
3873         }
3874         // WM_API overall errors, such as WM_StartParent.
3875         // Insert WH_Reset() and retry.
3876         else if (state == WH_SYSSTATE_ERROR)
3877         {
3878             break;
3879         }
3880         // Failure in initialization processing, end processing, or indicator setting.
3881         // WC_STATUS_ERROR handling.
3882         else if (state == WH_SYSSTATE_FATAL)
3883         {
3884             break;
3885         }
3886         OS_SleepThread(infoForWC->queue);
3887     }
3888     (void)OS_RestoreInterrupts(bak_cpsr);
3889     return succeeded;
3890 }
3891 
WcInit(const WMParentParam * pp,BOOL dsFlag,BOOL btFlag,u16 framePeriod)3892 SDK_WEAK_SYMBOL void WcInit(const WMParentParam *pp, BOOL dsFlag, BOOL btFlag, u16 framePeriod)
3893 {
3894     WHCompatibleInfoForWC  *info = infoForWC;
3895     // Save information here that is used by WC state transitions.
3896     info->parentParam = *pp;
3897     info->useDS = dsFlag;
3898     (void)btFlag;   // Not referenced
3899     info->targetChannel = info->parentParam.channel;
3900     OS_InitThreadQueue(info->queue);
3901     // set WH members, extended for WC
3902     sStateCallback = WcStateCallback;
3903     sDataSharingDoubleMode = (framePeriod <= 1);
3904     sPortExtraCallback = NULL;
3905     WH_SetGgid(info->parentParam.ggid);
3906     WH_SetIndCallback(WcIndicateCallback);
3907     // begin transitioning to the IDLE state, if necessary
3908     info->wcTarget = WC_STATUS_READY;
3909     if (whInitialized)
3910     {
3911         info->wcStatus = WC_STATUS_READY;
3912     }
3913     else
3914     {
3915         info->wcStatus = WC_STATUS_BUSY;
3916     }
3917     (void)WH_Initialize();
3918 }
3919 
WcFinish(void)3920 SDK_WEAK_SYMBOL void WcFinish(void)
3921 {
3922     WHCompatibleInfoForWC  *info = infoForWC;
3923     {
3924         OSIntrMode  bak_cpsr = OS_DisableInterrupts();
3925         // Wait until WH is entirely finished.
3926         if (info->wcStatus == WC_STATUS_BUSY)
3927         {
3928             WH_Reset();
3929         }
3930         WcEnd();
3931         (void)WcWaitForState(WH_SYSSTATE_IDLE);
3932         info->wcStatus = WC_STATUS_BUSY;
3933         (void)WH_End();
3934         (void)WcWaitForState(WH_SYSSTATE_STOP);
3935         // revert the WH members that were extended for WC to their original values
3936         sStateCallback = NULL;
3937         sDataSharingDoubleMode = TRUE;
3938         sPortExtraCallback = NULL;
3939         sAutoConnectFlag = FALSE;
3940         (void)OS_RestoreInterrupts(bak_cpsr);
3941     }
3942 }
3943 
WcStartParent(void)3944 SDK_WEAK_SYMBOL void WcStartParent(void)
3945 {
3946     WcStateScheduler(WC_STATUS_PARENT);
3947 }
3948 
WcStartChild(void)3949 SDK_WEAK_SYMBOL void WcStartChild(void)
3950 {
3951     WcStateScheduler(WC_STATUS_CHILD);
3952 }
3953 
WcEnd(void)3954 SDK_WEAK_SYMBOL void WcEnd(void)
3955 {
3956     WcStateScheduler(WC_STATUS_READY);
3957 }
3958 
WcGetStatus(void)3959 SDK_WEAK_SYMBOL WCStatus WcGetStatus(void)
3960 {
3961     return infoForWC->wcStatus;
3962 }
3963 
WcGetAid(void)3964 SDK_WEAK_SYMBOL u16 WcGetAid(void)
3965 {
3966     return WH_GetCurrentAid();
3967 }
3968 
WcSetMpReceiveCallback(WCCallbackFunc cb)3969 SDK_WEAK_SYMBOL void WcSetMpReceiveCallback(WCCallbackFunc cb)
3970 {
3971     WH_SetReceiver((WHReceiverFunc)cb);
3972 }
3973 
WcSetBlockTransferCallback(WCBlockTransferCallbackFunc cb)3974 SDK_WEAK_SYMBOL void WcSetBlockTransferCallback(WCBlockTransferCallbackFunc cb)
3975 {
3976     sPortExtraCallback = (WMCallbackFunc)cb;
3977 }
3978 
WcSetParentData(const void * buf,u16 size)3979 SDK_WEAK_SYMBOL void WcSetParentData(const void *buf, u16 size)
3980 {
3981     (void)WH_SendData(buf, size, NULL);
3982 }
3983 
WcSetChildData(const void * buf,u16 size)3984 SDK_WEAK_SYMBOL void WcSetChildData(const void *buf, u16 size)
3985 {
3986     (void)WH_SendData(buf, size, NULL);
3987 }
3988 
WcStepDataSharing(const void * send,u16 * bitmap)3989 SDK_WEAK_SYMBOL BOOL WcStepDataSharing(const void *send, u16 *bitmap)
3990 {
3991     BOOL    succeeded = WH_StepDS(send);
3992     if (succeeded && bitmap)
3993     {
3994         *bitmap = sDataSet.receivedBitmap;
3995     }
3996     return succeeded;
3997 }
3998 
WcGetSharedDataAddress(u16 aid)3999 SDK_WEAK_SYMBOL u8 *WcGetSharedDataAddress(u16 aid)
4000 {
4001     return (u8 *)WH_GetSharedDataAdr(aid);
4002 }
4003 
WcTurnOnPictoCatch(WCPictoCatchCallbackFunc func)4004 SDK_WEAK_SYMBOL void WcTurnOnPictoCatch(WCPictoCatchCallbackFunc func)
4005 {
4006     infoForWC->pictoCatchCallback = func;
4007     WH_TurnOnPictoCatch();
4008 }
4009 
WcTurnOffPictoCatch(void)4010 SDK_WEAK_SYMBOL void WcTurnOffPictoCatch(void)
4011 {
4012     WH_TurnOffPictoCatch();
4013 }
4014 
4015 #endif // WM_DEMO_WIRELESS_SHARED_WC_WH_CONFIG_H_
4016