1 /*---------------------------------------------------------------------------*
2 Project: NitroSDK - WXC - libraries -
3 File: wxc_api.c
4
5 Copyright 2003-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:: 2008-12-16#$
14 $Rev: 9661 $
15 $Author: okubata_ryoma $
16 *---------------------------------------------------------------------------*/
17
18 #include <nitro.h>
19
20 #include <nitro/wxc.h>
21
22
23 /*****************************************************************************/
24 /* Declaration */
25
26 /* All work variables of WXC library */
27 typedef struct WXCWork
28 {
29 u32 wm_dma;
30 WXCCallback system_callback;
31 WXCScheduler scheduler;
32 WXCUserInfo user_info[WM_NUM_MAX_CHILD + 1];
33 BOOL stopping;
34 u8 beacon_count; /* Number of beacon sends */
35 u8 padding[3];
36 WMParentParam parent_param ATTRIBUTE_ALIGN(32);
37 WXCDriverWork driver ATTRIBUTE_ALIGN(32);
38 WXCProtocolContext protocol[1] ATTRIBUTE_ALIGN(32);
39 }
40 WXCWork;
41
42 SDK_STATIC_ASSERT(sizeof(WXCWork) <= WXC_WORK_SIZE);
43
44
45 /*****************************************************************************/
46 /* Variables */
47
48 static WXCStateCode state = WXC_STATE_END;
49 static WXCWork *work = NULL;
50
51
52 /*****************************************************************************/
53 /* Functions */
54
55 /*---------------------------------------------------------------------------*
56 Name: WXCi_ChangeState
57
58 Description: Generates a callback at the same time it changes the internal status.
59
60 Arguments: stat: Transitioning status
61 arg: Callback function (changes depending on the status)
62 Returns: None.
63 *---------------------------------------------------------------------------*/
WXCi_ChangeState(WXCStateCode stat,void * arg)64 static inline void WXCi_ChangeState(WXCStateCode stat, void *arg)
65 {
66 OSIntrMode bak_cpsr = OS_DisableInterrupts();
67 {
68 state = stat;
69 if (work->system_callback)
70 {
71 (*work->system_callback) (state, arg);
72 }
73 }
74 (void)OS_RestoreInterrupts(bak_cpsr);
75 }
76
77 /*---------------------------------------------------------------------------*
78 Name: WXCi_SeekNextBlock
79
80 Description: Searches for the next block that should be run.
81
82 Arguments: None.
83
84 Returns: None.
85 *---------------------------------------------------------------------------*/
WXCi_SeekNextBlock(void)86 static void WXCi_SeekNextBlock(void)
87 {
88 /* Selects the next block */
89 WXCProtocolRegistry *target =
90 WXC_FindNextBlock(work->protocol, work->protocol->current_block, 0, FALSE);
91 if (!target)
92 {
93 /* If there is no data registered, it has no choice but to select an empty block */
94 target = WXC_FindNextBlock(work->protocol, NULL, 0, TRUE);
95 }
96 WXC_SetCurrentBlock(work->protocol, target);
97 work->parent_param.ggid = target->ggid;
98 }
99
100 /*---------------------------------------------------------------------------*
101 Name: WXCi_DriverEventCallback
102
103 Description: Event callback from the wireless driver.
104
105 Arguments: event: Notified event
106 arg: Function assigned to each event
107
108 Returns: u32 event result value assigned to each event.
109 *---------------------------------------------------------------------------*/
WXCi_DriverEventCallback(WXCDriverEvent event,void * arg)110 static u32 WXCi_DriverEventCallback(WXCDriverEvent event, void *arg)
111 {
112 u32 result = 0;
113
114 switch (event)
115 {
116 case WXC_DRIVER_EVENT_BEACON_SEND:
117 /*
118 * Beacon update timing (argument is WMParentParam pointer)
119 * Update the beacon state while running.
120 */
121 if (!work->stopping && (WXC_GetStateCode() == WXC_STATE_ACTIVE))
122 {
123 WXC_BeaconSendHook(work->protocol, &work->parent_param);
124 /* Restarts if there is no connection for a period of time */
125 if (work->driver.peer_bitmap == 0)
126 {
127 if (++work->beacon_count > WXC_PARENT_BEACON_SEND_COUNT_OUT)
128 {
129 work->beacon_count = 0;
130 /* Updates the scheduler and if it's still in parent mode, makes a connection */
131 if (WXCi_UpdateScheduler(&work->scheduler))
132 {
133 }
134 /* If it is in child mode, the status is changed */
135 else
136 {
137 WXCi_StartChild(&work->driver);
138 }
139 }
140 }
141 }
142 break;
143
144 case WXC_DRIVER_EVENT_BEACON_RECV:
145 /*
146 * Beacon detection timing (argument is WMBssDesc pointer)
147 * If it is seen as connection target, return TRUE. Otherwise, return FALSE.
148 */
149 {
150 WXCBeaconFoundCallback cb;
151 /* Beacon disconnect first happens in protocol */
152 cb.bssdesc = (const WMBssDesc *)arg;
153 cb.matched = WXC_BeaconRecvHook(work->protocol, cb.bssdesc);
154 /* Based on that result, the user application can also be disconnected */
155 (*work->system_callback) (WXC_STATE_BEACON_RECV, &cb);
156 result = (u32)cb.matched;
157 /* If a connection should be made based on this result, TRUE is returned */
158 if (result)
159 {
160 work->parent_param.ggid = WXC_GetCurrentBlock(work->protocol)->ggid;
161 }
162 }
163 break;
164
165 case WXC_DRIVER_EVENT_STATE_END:
166 /*
167 * Shut down wireless (the argument is work memory allocated to the WXC library)
168 */
169 work->stopping = FALSE;
170 WXCi_ChangeState(WXC_STATE_END, work);
171 break;
172
173 case WXC_DRIVER_EVENT_STATE_STOP:
174 /*
175 * Transition to the STOP state complete (the argument is always NULL)
176 */
177 work->stopping = FALSE;
178 WXCi_ChangeState(WXC_STATE_READY, NULL);
179 break;
180
181 case WXC_DRIVER_EVENT_STATE_IDLE:
182 /*
183 * Transition to the IDLE state complete (the argument is always NULL)
184 */
185 /* If it is preparing to finish, wireless ends here */
186 if (WXC_GetStateCode() != WXC_STATE_ACTIVE)
187 {
188 WXCi_End(&work->driver);
189 }
190 /* If it is preparing to stop, wireless stops here */
191 else if (work->stopping)
192 {
193 WXCi_Stop(&work->driver);
194 }
195 /* Otherwise, it switches between parent and child */
196 else if (WXCi_UpdateScheduler(&work->scheduler))
197 {
198 /* If there is multiple data for exchange registered, GGID switches here */
199 WXCi_SeekNextBlock();
200 /* Initialization of parent settings compatible with GGID happens in protocol */
201 WXC_BeaconSendHook(work->protocol, &work->parent_param);
202 /* Parent start */
203 WXCi_StartParent(&work->driver);
204 }
205 else
206 {
207 WXCi_StartChild(&work->driver);
208 }
209 break;
210
211 case WXC_DRIVER_EVENT_STATE_PARENT:
212 case WXC_DRIVER_EVENT_STATE_CHILD:
213 /*
214 * Transition to the MP state complete (the argument is always NULL)
215 */
216 /* If it is preparing to finish, wireless ends here */
217 if (WXC_GetStateCode() != WXC_STATE_ACTIVE)
218 {
219 WXCi_End(&work->driver);
220 }
221 /* If it is preparing to stop, wireless stops here */
222 else if (work->stopping)
223 {
224 WXCi_Stop(&work->driver);
225 }
226 work->beacon_count = 0;
227 /* Configures its own user settings */
228 {
229 WXCUserInfo *p_user = &work->user_info[work->driver.own_aid];
230 p_user->aid = work->driver.own_aid;
231 OS_GetMacAddress(p_user->macAddress);
232 }
233 break;
234
235 case WXC_DRIVER_EVENT_CONNECTING:
236 /*
237 * Pre-connection notification (the argument is a WMBssDesc pointer)
238 */
239 {
240 WMBssDesc * bss = (WMBssDesc *)arg;
241 WXC_CallPreConnectHook(work->protocol, bss, &bss->ssid[8]);
242 }
243 break;
244
245 case WXC_DRIVER_EVENT_CONNECTED:
246 /*
247 * Connection notification (the argument is a WMStartParentCallback or WMStartConnectCallback)
248 */
249 {
250 const WXCProtocolRegistry *block = WXC_GetCurrentBlock(work->protocol);
251 WMStartParentCallback *cb = (WMStartParentCallback *)arg;
252 const BOOL is_parent = WXC_IsParentMode();
253 const u16 parent_size =
254 (u16)(is_parent ? work->parent_param.
255 parentMaxSize : WXCi_GetParentBssDesc(&work->driver)->gameInfo.parentMaxSize);
256 const u16 child_size =
257 (u16)(is_parent ? work->parent_param.
258 childMaxSize : WXCi_GetParentBssDesc(&work->driver)->gameInfo.childMaxSize);
259 const u16 aid = (u16)(is_parent ? cb->aid : 0);
260 WXCUserInfo *p_user = &work->user_info[aid];
261 const BOOL is_valid_block = (!work->stopping && (WXC_GetStateCode() == WXC_STATE_ACTIVE) && block);
262
263 /* First, copy the user information of the connection partner */
264 p_user->aid = aid;
265 if (is_parent)
266 {
267 WM_CopyBssid16(cb->macAddress, p_user->macAddress);
268 }
269 else
270 {
271 const WMBssDesc *p_bss = WXCi_GetParentBssDesc(&work->driver);
272 WM_CopyBssid16(p_bss->bssid, p_user->macAddress);
273 }
274
275 /* Next, initialize impl in the current MP settings */
276 WXC_ResetSequence(work->protocol, parent_size, child_size);
277
278 /*
279 * If the process is not shutting down and RegisterData is currently valid, automatically register data here
280 *
281 */
282 if (is_valid_block)
283 {
284 /* Data is only registered when there is data to be automatically registered */
285 if ((block->send.buffer != NULL) && (block->recv.buffer != NULL))
286 {
287 WXC_AddBlockSequence(work->protocol,
288 block->send.buffer, block->send.length,
289 block->recv.buffer, block->recv.length);
290 }
291 }
292
293 /* Connection notification to protocol */
294 WXC_ConnectHook(work->protocol, (u16)(1 << aid));
295
296 /* If necessary, it calls back to the user application */
297 if (is_valid_block)
298 {
299 (*work->system_callback) (WXC_STATE_CONNECTED, p_user);
300 }
301
302 /*
303 * If no one has used the AddData function at this point, impl runs so that the !IsExecuting function will be true
304 *
305 */
306 }
307 break;
308
309 case WXC_DRIVER_EVENT_DISCONNECTED:
310 /*
311 * Disconnect notification
312 * This function is called when WM_Disconnect completes, as indicated by WM_StartParent, and in PortRecvCallback, so there may be some overlap.
313 *
314 *
315 *
316 */
317 WXC_DisconnectHook(work->protocol, (u16)(u32)arg);
318 /*
319 * Reset when disconnecting if all data is unregistered and the WXC_End function is run in the completion callback
320 *
321 *
322 */
323 if (!WXC_GetUserBitmap())
324 {
325 if ((WXC_GetStateCode() == WXC_STATE_ACTIVE) ||
326 (WXC_GetStateCode() == WXC_STATE_ENDING) || !WXC_GetCurrentBlock(work->protocol))
327 {
328 work->beacon_count = 0;
329 WXCi_Reset(&work->driver);
330 }
331 }
332 break;
333
334 case WXC_DRIVER_EVENT_DATA_SEND:
335 /* MP packet send hook (argument is the WXCPacketInfo pointer) */
336 WXC_PacketSendHook(work->protocol, (WXCPacketInfo *) arg);
337 break;
338
339 case WXC_DRIVER_EVENT_DATA_RECV:
340 /* MP packet receive hook (argument is the const WXCPacketInfo pointer) */
341 (void)WXC_PacketRecvHook(work->protocol, (const WXCPacketInfo *)arg);
342 /* When it is already disconnected as protocol, it resets */
343 if (!work->protocol->current_block->impl->IsExecuting(work->protocol))
344 {
345 WXCi_Reset(&work->driver);
346 }
347 break;
348
349 default:
350 OS_TPanic("unchecked event implementations!");
351 break;
352 }
353
354 return result;
355 }
356
357 /*---------------------------------------------------------------------------*
358 External Functions
359 *---------------------------------------------------------------------------*/
360
361 /*---------------------------------------------------------------------------*
362 Name: WXC_Init
363
364 Description: Initializes chance encounter communications.
365 Initializes the internal status
366
367 Arguments: work_mem: Work memory used in the work library.
368 The memory must be at least WXC_WORK_SIZE bytes and 32-byte aligned.
369
370 callback: Sends notifications for the various library system states
371 Pointer to the callback
372 dma: DMA channel used in the library
373
374 Returns: None.
375 *---------------------------------------------------------------------------*/
WXC_Init(void * work_mem,WXCCallback callback,u32 dma)376 void WXC_Init(void *work_mem, WXCCallback callback, u32 dma)
377 {
378 OSIntrMode bak_cpsr = OS_DisableInterrupts();
379 // Install various protocols on the first invocation
380 static BOOL initialized = FALSE;
381 if (!initialized)
382 {
383 WXC_InstallProtocolImpl(WXCi_GetProtocolImplCommon());
384 WXC_InstallProtocolImpl(WXCi_GetProtocolImplWPB());
385 WXC_InstallProtocolImpl(WXCi_GetProtocolImplWXC());
386 initialized = TRUE;
387 }
388 {
389 if (WXC_GetStateCode() == WXC_STATE_END)
390 {
391 if (((u32)work_mem & 31) != 0)
392 {
393 OS_TPanic("WXC work buffer must be 32-byte aligned!");
394 }
395 work = (WXCWork *) work_mem;
396 MI_CpuClear32(work, sizeof(WXCWork));
397 work->wm_dma = dma;
398 work->system_callback = callback;
399 WXCi_InitScheduler(&work->scheduler);
400 WXC_InitProtocol(work->protocol);
401 /* Initializes parent settings */
402 work->parent_param.maxEntry = 1; /* Currently only supports 1 to 1 connections */
403 work->parent_param.parentMaxSize = WXC_PACKET_SIZE_MAX;
404 work->parent_param.childMaxSize = WXC_PACKET_SIZE_MAX;
405 work->parent_param.CS_Flag = 1; /* Continuous distribution */
406 WXC_InitDriver(&work->driver, &work->parent_param, WXCi_DriverEventCallback,
407 work->wm_dma);
408 WXCi_ChangeState(WXC_STATE_READY, NULL);
409 }
410 }
411 (void)OS_RestoreInterrupts(bak_cpsr);
412 }
413
414 /*---------------------------------------------------------------------------*
415 Name: WXC_SetParentParameter
416
417 Description: Specifies wireless connection settings
418 The configuration contents are only used when in parent mode.
419 When connected in child mode, the device follows the parent's settings.
420 This function is optional. Call it before the WXC_Start function only when necessary.
421
422
423 Arguments: sendSize: Parent send size.
424 It must be at least WXC_PACKET_SIZE_MIN and no more than WXC_PACKET_SIZE_MAX.
425
426 recvSize: Parent receive size.
427 It must be at least WXC_PACKET_SIZE_MIN and no more than WXC_PACKET_SIZE_MAX.
428
429 maxEntry: Maximum number of connected players.
430 The current implementation supports only a specified value of 1.
431
432 Returns: If the settings are valid, they are applied internally, and TRUE is returned. Otherwise, a warning message is sent to debug output, and FALSE is returned.
433
434 *---------------------------------------------------------------------------*/
WXC_SetParentParameter(u16 sendSize,u16 recvSize,u16 maxEntry)435 BOOL WXC_SetParentParameter(u16 sendSize, u16 recvSize, u16 maxEntry)
436 {
437 BOOL ret = FALSE;
438
439 /* The current implementation only supports communication in pairs */
440 if (maxEntry > 1)
441 {
442 OS_TWarning("unsupported maxEntry. (must be 1)\n");
443 }
444 /* Determines packet size */
445 else if ((sendSize < WXC_PACKET_SIZE_MIN) || (sendSize > WXC_PACKET_SIZE_MAX) ||
446 (recvSize < WXC_PACKET_SIZE_MIN) || (recvSize > WXC_PACKET_SIZE_MAX))
447 {
448 OS_TWarning("packet size is out of range.\n");
449 }
450 /* Determines time required for MP communications */
451 else
452 {
453 /* Evaluation for the time taken to perform MP communications once */
454 int usec = 330 + 4 * (sendSize + 38) + maxEntry * (112 + 4 * (recvSize + 32));
455 const int max_time = 5600;
456 if (usec >= max_time)
457 {
458 OS_TWarning("specified MP setting takes %d[usec]. (should be lower than %d[usec])\n",
459 usec, max_time);
460 }
461 else
462 {
463 work->parent_param.parentMaxSize = sendSize;
464 work->parent_param.childMaxSize = recvSize;
465 ret = TRUE;
466 }
467 }
468 return ret;
469 }
470
471 /*---------------------------------------------------------------------------*
472 Name: WXC_Start
473
474 Description: Starts chance encounter communications.
475 Starts the internal wireless driver.
476
477 Arguments: None.
478
479 Returns: None.
480 *---------------------------------------------------------------------------*/
WXC_Start(void)481 void WXC_Start(void)
482 {
483 OSIntrMode bak_cpsr = OS_DisableInterrupts();
484 {
485 SDK_ASSERT(WXC_GetStateCode() != WXC_STATE_END);
486
487 if (WXC_GetStateCode() == WXC_STATE_READY)
488 {
489 WXCi_Reset(&work->driver);
490 WXCi_ChangeState(WXC_STATE_ACTIVE, NULL);
491 }
492 }
493 (void)OS_RestoreInterrupts(bak_cpsr);
494 }
495
496 /*---------------------------------------------------------------------------*
497 Name: WXC_Stop
498
499 Description: Stops chance encounter communications.
500 Stops the internal wireless driver.
501
502 Arguments: None.
503
504 Returns: None.
505 *---------------------------------------------------------------------------*/
WXC_Stop(void)506 void WXC_Stop(void)
507 {
508 OSIntrMode bak_cpsr = OS_DisableInterrupts();
509 {
510 SDK_ASSERT(WXC_GetStateCode() != WXC_STATE_END);
511
512 switch (WXC_GetStateCode())
513 {
514
515 case WXC_STATE_ACTIVE:
516 if (!work->stopping)
517 {
518 work->stopping = TRUE;
519 /* If currently in a connection, it waits to end while specifying a stop request */
520 if (WXC_GetUserBitmap() == 0)
521 {
522 WXCi_Stop(&work->driver);
523 }
524 }
525 break;
526
527 case WXC_STATE_READY:
528 case WXC_STATE_ENDING:
529 case WXC_STATE_END:
530 /* If the end operation is complete or running, it does not do anything */
531 break;
532
533 }
534 }
535 (void)OS_RestoreInterrupts(bak_cpsr);
536
537 }
538
539 /*---------------------------------------------------------------------------*
540 Name: WXC_End
541
542 Description: Ends chance encounter communications.
543 Ends the internal wireless driver.
544
545 Arguments: None.
546
547 Returns: None.
548 *---------------------------------------------------------------------------*/
WXC_End(void)549 void WXC_End(void)
550 {
551 OSIntrMode bak_cpsr = OS_DisableInterrupts();
552 {
553 switch (WXC_GetStateCode())
554 {
555
556 case WXC_STATE_READY:
557 case WXC_STATE_ACTIVE:
558 WXCi_ChangeState(WXC_STATE_ENDING, NULL);
559 /* If currently in a connection, it waits to end while specifying an end request */
560 if (WXC_GetUserBitmap() == 0)
561 {
562 WXCi_End(&work->driver);
563 }
564 break;
565
566 case WXC_STATE_ENDING:
567 case WXC_STATE_END:
568 /* If the end operation is complete or running, it does not do anything */
569 break;
570
571 }
572 }
573 (void)OS_RestoreInterrupts(bak_cpsr);
574 }
575
576 /*---------------------------------------------------------------------------*
577 Name: WXC_GetStateCode
578
579 Description: Gets the current status of the library.
580
581 Arguments: None.
582
583 Returns: WXCStateCode type that shows the current library status.
584 *---------------------------------------------------------------------------*/
WXC_GetStateCode(void)585 WXCStateCode WXC_GetStateCode(void)
586 {
587 return state;
588 }
589
590 /*---------------------------------------------------------------------------*
591 Name: WXC_IsParentMode
592
593 Description: Determines whether the current wireless state is parent.
594 Only valid in the WXC_STATE_ACTIVE state.
595
596 Arguments: None.
597
598 Returns: If the wireless status is parent mode, TRUE. If it is child mode, FALSE.
599 *---------------------------------------------------------------------------*/
WXC_IsParentMode(void)600 BOOL WXC_IsParentMode(void)
601 {
602 return WXCi_IsParentMode(&work->driver);
603 }
604
605 /*---------------------------------------------------------------------------*
606 Name: WXC_GetParentParam
607
608 Description: Refers to the WMParentParam structure for the current wireless state.
609
610 Arguments: None.
611
612 Returns: WMParentParam structure.
613 *---------------------------------------------------------------------------*/
WXC_GetParentParam(void)614 const WMParentParam *WXC_GetParentParam(void)
615 {
616 return &work->parent_param;
617 }
618
619 /*---------------------------------------------------------------------------*
620 Name: WXC_GetParentBssDesc
621
622 Description: Refers to the WMBssDesc structure for the current connection target.
623
624 Arguments: None.
625
626 Returns: WMBssDesc structure.
627 *---------------------------------------------------------------------------*/
WXC_GetParentBssDesc(void)628 const WMBssDesc *WXC_GetParentBssDesc(void)
629 {
630 return WXCi_GetParentBssDesc(&work->driver);
631 }
632
633 /*---------------------------------------------------------------------------*
634 Name: WXC_GetUserBitmap
635
636 Description: Gets the currently connected user's status with a bitmap.
637
638
639 Arguments: None.
640
641 Returns: WMBssDesc structure.
642 *---------------------------------------------------------------------------*/
WXC_GetUserBitmap(void)643 u16 WXC_GetUserBitmap(void)
644 {
645 u16 bitmap = work->driver.peer_bitmap;
646 if (bitmap != 0)
647 {
648 bitmap = (u16)(bitmap | (1 << work->driver.own_aid));
649 }
650 return bitmap;
651 }
652
653 /*---------------------------------------------------------------------------*
654 Name: WXC_GetCurrentGgid
655
656 Description: Gets the selected GGID in the current connection.
657 If communications are not established, it returns 0.
658 The current communications status can be determined by the WXC_GetUserBitmap function's return value.
659
660 Arguments: None.
661
662 Returns: The selected GGID in the current connection.
663 *---------------------------------------------------------------------------*/
WXC_GetCurrentGgid(void)664 u32 WXC_GetCurrentGgid(void)
665 {
666 u32 ggid = 0;
667 {
668 OSIntrMode bak_cpsr = OS_DisableInterrupts();
669 WXCProtocolRegistry *current = WXC_GetCurrentBlock(work->protocol);
670 if (current)
671 {
672 ggid = current->ggid;
673 /* Modeled on the detected partner ID if ANY */
674 if (ggid == WXC_GGID_COMMON_ANY)
675 {
676 ggid = work->protocol->target_ggid;
677 }
678 }
679 (void)OS_RestoreInterrupts(bak_cpsr);
680 }
681 return ggid;
682 }
683
684 /*---------------------------------------------------------------------------*
685 Name: WXC_GetOwnAid
686
687 Description: Gets its own AID in the current connection.
688 If communications are not established, it returns an inconstant value.
689 The current communications status can be determined by the WXC_GetUserBitmap function's return value.
690
691 Arguments: None.
692
693 Returns: Its own AID in the current connection.
694 *---------------------------------------------------------------------------*/
WXC_GetOwnAid(void)695 u16 WXC_GetOwnAid(void)
696 {
697 return work->driver.own_aid;
698 }
699
700 /*---------------------------------------------------------------------------*
701 Name: WXC_GetUserInfo
702
703 Description: Gets the user information of the user currently connected.
704 Do not change the target of the pointer that is returned.
705
706 Arguments: aid: User AID that gets information
707
708 Returns: If the specified AID is valid, user information. Otherwise, NULL.
709 *---------------------------------------------------------------------------*/
WXC_GetUserInfo(u16 aid)710 const WXCUserInfo *WXC_GetUserInfo(u16 aid)
711 {
712 const WXCUserInfo *ret = NULL;
713
714 {
715 OSIntrMode bak_cpsr = OS_DisableInterrupts();
716 if ((aid <= WM_NUM_MAX_CHILD) && ((WXC_GetUserBitmap() & (1 << aid)) != 0))
717 {
718 ret = &work->user_info[aid];
719 }
720 (void)OS_RestoreInterrupts(bak_cpsr);
721 }
722 return ret;
723 }
724
725 /*---------------------------------------------------------------------------*
726 Name: WXC_SetChildMode
727
728 Description: Wireless is set so that it can only be run on the child side.
729 This function must be called before the WXC_Start function is called.
730
731 Arguments: enable: If it can only be run on the child side, TRUE
732
733 Returns: None.
734 *---------------------------------------------------------------------------*/
WXC_SetChildMode(BOOL enable)735 void WXC_SetChildMode(BOOL enable)
736 {
737 SDK_ASSERT(WXC_GetStateCode() != WXC_STATE_ACTIVE);
738 WXCi_SetChildMode(&work->scheduler, enable);
739 }
740
741 /*---------------------------------------------------------------------------*
742 Name: WXC_AddData
743
744 Description: Data is configured by adding it to a completed block data exchange.
745
746 Arguments: send_buf: Send buffer
747 send_size: Send buffer size
748 recv_buf: Receive buffer
749 recv_max: Receive buffer size
750
751 Returns: None.
752 *---------------------------------------------------------------------------*/
WXC_AddData(const void * send_buf,u32 send_size,void * recv_buf,u32 recv_max)753 void WXC_AddData(const void *send_buf, u32 send_size, void *recv_buf, u32 recv_max)
754 {
755 WXC_AddBlockSequence(work->protocol, send_buf, send_size, recv_buf, recv_max);
756 }
757
758 /*---------------------------------------------------------------------------*
759 Name: WXC_RegisterDataEx
760
761 Description: Registers data for exchange
762
763 Arguments: ggid: GGID of the registered data
764 callback: Callback function to the user (invoked when data exchange is complete)
765 send_ptr: Pointer to registered data
766 send_size: Size of registered data
767 recv_ptr: Pointer to the receive buffer
768 recv_size: Receive buffer size
769 type: Chance encounter communication type (PIType)
770
771 Returns: None.
772 *---------------------------------------------------------------------------*/
WXC_RegisterDataEx(u32 ggid,WXCCallback callback,u8 * send_ptr,u32 send_size,u8 * recv_ptr,u32 recv_size,const char * type)773 void WXC_RegisterDataEx(u32 ggid, WXCCallback callback, u8 *send_ptr, u32 send_size, u8 *recv_ptr,
774 u32 recv_size, const char *type)
775 {
776 OSIntrMode bak_cpsr = OS_DisableInterrupts();
777
778 /*
779 * Do not allow the same GGID to be registered more than once
780 * (because the child device cannot determine which one to use when connecting)
781 */
782 WXCProtocolRegistry *same_ggid = WXC_FindNextBlock(work->protocol, NULL, ggid, TRUE);
783 if (same_ggid != NULL)
784 {
785 OS_TWarning("already registered same GGID!");
786 }
787 /* If not, use an empty block */
788 else
789 {
790 WXCProtocolRegistry *p_data = WXC_FindNextBlock(work->protocol, NULL, 0, TRUE);
791 /* If there is no empty block, fail */
792 if (!p_data)
793 {
794 OS_TPanic("no more memory to register data!");
795 }
796 else
797 {
798 /* Change the registered communication protocol based on the selected protocol */
799 WXCProtocolImpl *impl = WXC_FindProtocolImpl(type);
800 if (!impl)
801 {
802 OS_TPanic("unknown protocol \"%s\"!", type);
803 }
804 WXC_InitProtocolRegistry(p_data, ggid, callback, impl);
805 WXC_SetInitialExchangeBuffers(p_data, send_ptr, send_size, recv_ptr, recv_size);
806 }
807 }
808
809 (void)OS_RestoreInterrupts(bak_cpsr);
810 }
811
812 /*---------------------------------------------------------------------------*
813 Name: WXC_SetInitialData
814
815 Description: The data block used for every exchange is set by the first exchange.
816
817 Arguments: ggid: GGID of the registered data
818 send_ptr: Pointer to registered data
819 send_size: Size of registered data
820 recv_ptr: Pointer to the receive buffer
821 recv_size: Receive buffer size
822
823 Returns: None.
824 *---------------------------------------------------------------------------*/
WXC_SetInitialData(u32 ggid,u8 * send_ptr,u32 send_size,u8 * recv_ptr,u32 recv_size)825 void WXC_SetInitialData(u32 ggid, u8 *send_ptr, u32 send_size, u8 *recv_ptr, u32 recv_size)
826 {
827 OSIntrMode bak_cpsr = OS_DisableInterrupts();
828
829 /* Searches for the specified block */
830 WXCProtocolRegistry *target = WXC_FindNextBlock(work->protocol, NULL, ggid, TRUE);
831 if (target)
832 {
833 WXC_SetInitialExchangeBuffers(target, send_ptr, send_size, recv_ptr, recv_size);
834 }
835 (void)OS_RestoreInterrupts(bak_cpsr);
836 }
837
838 /*---------------------------------------------------------------------------*
839 Name: WXC_UnregisterData
840
841 Description: Deletes data for exchange from registration
842
843 Arguments: ggid: GGID related to the deleted block
844
845 Returns: None.
846 *---------------------------------------------------------------------------*/
WXC_UnregisterData(u32 ggid)847 void WXC_UnregisterData(u32 ggid)
848 {
849 OSIntrMode bak_cpsr = OS_DisableInterrupts();
850
851 /* Searches for the specified block */
852 WXCProtocolRegistry *target = WXC_FindNextBlock(work->protocol, NULL, ggid, TRUE);
853 /* Searches once more, including when this is a shared chance encounter communication specification */
854 if (!target)
855 {
856 target = WXC_FindNextBlock(work->protocol, NULL, (u32)(ggid | WXC_GGID_COMMON_BIT), TRUE);
857 }
858 if (target)
859 {
860 /* If it is being used in the current connection, fail */
861 if ((WXC_GetUserBitmap() != 0) && (target == WXC_GetCurrentBlock(work->protocol)))
862 {
863 OS_TWarning("specified data is now using.");
864 }
865 else
866 {
867 /* Releases data */
868 target->ggid = 0;
869 target->callback = NULL;
870 target->send.buffer = NULL;
871 target->send.length = 0;
872 target->recv.buffer = NULL;
873 target->recv.length = 0;
874 }
875 }
876 (void)OS_RestoreInterrupts(bak_cpsr);
877 }
878
879 /*---------------------------------------------------------------------------*
880 Name: WXCi_SetSsid
881
882 Description: Configures the SSID as a child when connecting.
883 Internal function.
884
885 Arguments: buffer: SSID data to configure
886 length: SSID data length
887 Must be less than WM_SIZE_CHILD_SSID
888
889 Returns: None.
890 *---------------------------------------------------------------------------*/
WXCi_SetSsid(const void * buffer,u32 length)891 void WXCi_SetSsid(const void *buffer, u32 length)
892 {
893 OSIntrMode bak_cpsr = OS_DisableInterrupts();
894 WXC_SetDriverSsid(&work->driver, buffer, length);
895 (void)OS_RestoreInterrupts(bak_cpsr);
896 }
897