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