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