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