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