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