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