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