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