1 /*---------------------------------------------------------------------------*
2   Project:  TwlSDK - WXC - libraries -
3   File:     wxc_protocol.c
4 
5   Copyright 2005-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/common.h>
21 #include <nitro/wxc/protocol.h>
22 
23 
24 /*****************************************************************************/
25 /* Variables */
26 
27 /* Chance encounter communications protocol added up to this point */
28 static WXCProtocolImpl *impl_list;
29 
30 
31 /*****************************************************************************/
32 /* Functions */
33 
34 /*---------------------------------------------------------------------------*
35   Name:         WXC_InitProtocol
36 
37   Description:  Initializes the WXC library protocol.
38 
39   Arguments:    protocol: WXCProtocolContext structure
40 
41   Returns:      None.
42  *---------------------------------------------------------------------------*/
WXC_InitProtocol(WXCProtocolContext * protocol)43 void WXC_InitProtocol(WXCProtocolContext * protocol)
44 {
45     protocol->current_block = NULL;
46     MI_CpuClear32(protocol, sizeof(protocol));
47 }
48 
49 /*---------------------------------------------------------------------------*
50   Name:         WXC_InstallProtocolImpl
51 
52   Description:  Adds a new selectable protocol.
53 
54   Arguments:    impl: Pointer to the WXCProtocolImpl structure.
55                       This structure is used internally until the library is closed.
56 
57   Returns:      None.
58  *---------------------------------------------------------------------------*/
WXC_InstallProtocolImpl(WXCProtocolImpl * impl)59 void WXC_InstallProtocolImpl(WXCProtocolImpl * impl)
60 {
61     WXCProtocolImpl *p = impl_list;
62     if (!p)
63     {
64         impl_list = impl;
65         impl->next = NULL;
66     }
67     else
68     {
69         for (;; p = p->next)
70         {
71             if (p == impl)
72             {
73                 break;
74             }
75             else if (!p->next)
76             {
77                 p->next = impl;
78                 impl->next = NULL;
79                 break;
80             }
81         }
82     }
83 }
84 
85 /*---------------------------------------------------------------------------*
86   Name:         WXC_FindProtocolImpl
87 
88   Description:  Searches for a protocol with the specified name.
89 
90   Arguments:    name: Protocol name
91 
92   Returns:      If a protocol with the specified name is found, its pointer is returned.
93  *---------------------------------------------------------------------------*/
WXC_FindProtocolImpl(const char * name)94 WXCProtocolImpl *WXC_FindProtocolImpl(const char *name)
95 {
96     WXCProtocolImpl *p = impl_list;
97     for (; p; p = p->next)
98     {
99         if (STD_CompareString(name, p->name) == 0)
100         {
101             break;
102         }
103     }
104     return p;
105 }
106 
107 /*---------------------------------------------------------------------------*
108   Name:         WXC_ResetSequence
109 
110   Description:  Reinitializes the WXC library protocol.
111 
112   Arguments:    protocol: WXCProtocolContext structure
113                 send_max: Maximum send packet size
114                 recv_max: Maximum receive packet size
115 
116   Returns:      None.
117  *---------------------------------------------------------------------------*/
WXC_ResetSequence(WXCProtocolContext * protocol,u16 send_max,u16 recv_max)118 void WXC_ResetSequence(WXCProtocolContext * protocol, u16 send_max, u16 recv_max)
119 {
120     WXC_GetCurrentBlockImpl(protocol)->Init(protocol, send_max, recv_max);
121 }
122 
123 /*---------------------------------------------------------------------------*
124   Name:         WXC_AddBlockSequence
125 
126   Description:  Sets block data exchange.
127 
128   Arguments:    protocol: WXCProtocolContext structure
129                 send_buf: Send buffer
130                 send_size: Send buffer size
131                 recv_buf: Receive buffer
132                 recv_max: Receive buffer size
133 
134   Returns:      None.
135  *---------------------------------------------------------------------------*/
WXC_AddBlockSequence(WXCProtocolContext * protocol,const void * send_buf,u32 send_size,void * recv_buf,u32 recv_max)136 void WXC_AddBlockSequence(WXCProtocolContext * protocol,
137                           const void *send_buf, u32 send_size, void *recv_buf, u32 recv_max)
138 {
139     int     result;
140     result =
141         WXC_GetCurrentBlockImpl(protocol)->AddData(protocol, send_buf, send_size, recv_buf,
142                                                    recv_max);
143     SDK_TASSERTMSG(result, "sequence is now busy.");
144 }
145 
146 /*---------------------------------------------------------------------------*
147   Name:         WXC_FindNextBlock
148 
149   Description:  Specifies a GGID and searches for block data.
150 
151   Arguments:    protocol: WXCProtocolContext structure
152                 from: Starting search location.
153                       If NULL, search from the beginning. Otherwise, start searching from the block after the specified one.
154 
155                 ggid: GGID associated with the search block data.
156                       0 indicates an empty block.
157                 match: Search condition.
158                        If TRUE, data with matching GGID will be search target.
159                        If FALSE, those with non-matching GGID will be search target.
160 
161   Returns:      Returns a pointer to the corresponding block data if it exists and NULL otherwise.
162 
163  *---------------------------------------------------------------------------*/
WXC_FindNextBlock(WXCProtocolContext * protocol,const WXCProtocolRegistry * from,u32 ggid,BOOL match)164 WXCProtocolRegistry *WXC_FindNextBlock(WXCProtocolContext * protocol,
165                                        const WXCProtocolRegistry * from, u32 ggid, BOOL match)
166 {
167     WXCProtocolRegistry *target;
168 
169     /* Search from the top if NULL */
170     if (!from)
171     {
172         from = &protocol->data_array[WXC_REGISTER_DATA_MAX - 1];
173     }
174 
175     target = (WXCProtocolRegistry *) from;
176     for (;;)
177     {
178         BOOL    eq;
179         /* Loop when the next element reach the end of the array */
180         if (++target >= &protocol->data_array[WXC_REGISTER_DATA_MAX])
181         {
182             target = &protocol->data_array[0];
183         }
184         /* Close if a block matching the search criteria is found */
185         eq = (target->ggid == ggid);
186         if ((match && eq) || (!match && !eq))
187         {
188             break;
189         }
190         /* Close if all elements are searched */
191         if (target == from)
192         {
193             target = NULL;
194             break;
195         }
196     }
197     return target;
198 }
199 
200 /*---------------------------------------------------------------------------*
201   Name:         WXC_BeaconSendHook
202 
203   Description:  Hook called at beacon update.
204 
205   Arguments:    protocol: WXCProtocolContext structure
206                 p_param: WMParentParam structure used for next beacon
207                          Change inside the function as necessary.
208 
209   Returns:      None.
210  *---------------------------------------------------------------------------*/
WXC_BeaconSendHook(WXCProtocolContext * protocol,WMParentParam * p_param)211 void WXC_BeaconSendHook(WXCProtocolContext * protocol, WMParentParam *p_param)
212 {
213     WXC_GetCurrentBlockImpl(protocol)->BeaconSend(protocol, p_param);
214 }
215 
216 /*---------------------------------------------------------------------------*
217   Name:         WXC_BeaconRecvHook
218 
219   Description:  Hook called for individual scanned beacons.
220 
221   Arguments:    protocol: WXCProtocolContext structure
222                 p_desc: Scanned WMBssDesc structure
223 
224   Returns:      If it's seen as connection target, return TRUE. Otherwise, return FALSE.
225  *---------------------------------------------------------------------------*/
WXC_BeaconRecvHook(WXCProtocolContext * protocol,const WMBssDesc * p_desc)226 BOOL WXC_BeaconRecvHook(WXCProtocolContext * protocol, const WMBssDesc *p_desc)
227 {
228     BOOL    ret = FALSE;
229 
230     /* GGID 0 is treated as an empty block, so exclude */
231     u32 ggid = p_desc->gameInfo.ggid;
232     if (ggid != 0)
233     {
234         /* Searches for a match from the registered GGIDs */
235         WXCProtocolRegistry *found = NULL;
236         int i;
237         for (i = 0; i < WXC_REGISTER_DATA_MAX; ++i)
238         {
239             WXCProtocolRegistry *p = &protocol->data_array[i];
240             /* Strict match */
241             if (p->ggid == ggid)
242             {
243                 found = p;
244                 break;
245             }
246             /* Both are shared chance encounter */
247             else if (WXC_IsCommonGgid(ggid) && WXC_IsCommonGgid(p->ggid))
248             {
249                 /* Match if any are relay points */
250                 const BOOL is_target_any = (ggid == WXC_GGID_COMMON_PARENT);
251                 const BOOL is_current_any = (p->ggid == WXC_GGID_COMMON_ANY);
252                 if (is_target_any)
253                 {
254                     if (!is_current_any)
255                     {
256                         ggid = p->ggid;
257                         found = p;
258                         break;
259                     }
260                 }
261                 else
262                 {
263                     if (is_current_any)
264                     {
265                         found = p;
266                         break;
267                     }
268                 }
269             }
270         }
271         /* If a match, perform decision process inside the protocol as well */
272         if (found)
273         {
274             ret = found->impl->BeaconRecv(protocol, p_desc);
275             /* If both GGID and protocol matches, change selection */
276             if (ret)
277             {
278                 WXC_SetCurrentBlock(protocol, found);
279                 protocol->target_ggid = ggid;
280             }
281         }
282     }
283     return ret;
284 }
285 
286 /*---------------------------------------------------------------------------*
287   Name:         WXC_PacketSendHook
288 
289   Description:  Hook called at MP packet transmission.
290 
291   Arguments:    protocol: WXCProtocolContext structure
292                 packet: WXCPacketInfo pointer configuring transmission packet information
293 
294   Returns:      None.
295  *---------------------------------------------------------------------------*/
WXC_PacketSendHook(WXCProtocolContext * protocol,WXCPacketInfo * packet)296 void WXC_PacketSendHook(WXCProtocolContext * protocol, WXCPacketInfo * packet)
297 {
298     WXC_GetCurrentBlockImpl(protocol)->PacketSend(protocol, packet);
299 }
300 
301 /*---------------------------------------------------------------------------*
302   Name:         WXC_PacketRecvHook
303 
304   Description:  Hook called at MP packet reception.
305 
306   Arguments:    protocol: WXCProtocolContext structure
307                 packet: WXCPacketInfo pointer configuring reception packet information
308 
309   Returns:      If a single data exchange is completed, return TRUE.
310  *---------------------------------------------------------------------------*/
WXC_PacketRecvHook(WXCProtocolContext * protocol,const WXCPacketInfo * packet)311 BOOL WXC_PacketRecvHook(WXCProtocolContext * protocol, const WXCPacketInfo * packet)
312 {
313     int     ret = FALSE;
314 
315     ret = WXC_GetCurrentBlockImpl(protocol)->PacketRecv(protocol, packet);
316     /*
317      * A single data exchange has completed.
318      * If communication continues here unchanged, !IsExecuting() should be true before long.
319      */
320     if (ret)
321     {
322         /* Notify the user callback of transmission completion */
323         WXCCallback callback = protocol->current_block->callback;
324         if (callback)
325         {
326             (*callback) (WXC_STATE_EXCHANGE_DONE, &protocol->recv);
327         }
328         /*
329          * If AddData() is run in the callback, communication should continue.
330          * Otherwise, processing will advance until !IsExecuting() is true as mentioned before.
331          */
332     }
333 
334     return ret;
335 }
336 
337 /*---------------------------------------------------------------------------*
338   Name:         WXC_ConnectHook
339 
340   Description:  Hook called at connection detection.
341 
342   Arguments:    protocol: WXCProtocolContext structure
343                 bitmap: AID bitmap of the connected target
344 
345   Returns:      None.
346  *---------------------------------------------------------------------------*/
WXC_ConnectHook(WXCProtocolContext * protocol,u16 bitmap)347 void WXC_ConnectHook(WXCProtocolContext * protocol, u16 bitmap)
348 {
349 #pragma unused(protocol)
350 #pragma unused(bitmap)
351 }
352 
353 /*---------------------------------------------------------------------------*
354   Name:         WXC_DisconnectHook
355 
356   Description:  Hook called at disconnection detection.
357 
358   Arguments:    protocol: WXCProtocolContext structure
359                 bitmap: AID bitmap of the disconnected target
360 
361   Returns:      None.
362  *---------------------------------------------------------------------------*/
WXC_DisconnectHook(WXCProtocolContext * protocol,u16 bitmap)363 void WXC_DisconnectHook(WXCProtocolContext * protocol, u16 bitmap)
364 {
365 #pragma unused(protocol)
366 #pragma unused(bitmap)
367 }
368 
369 /*---------------------------------------------------------------------------*
370   Name:         WXC_CallPreConnectHook
371 
372   Description:  Hook called before connecting to the communication target.
373 
374   Arguments:    protocol: WXCProtocolContext structure
375                 p_desc: Connection target WMBssDesc structure
376                 ssid: Buffer that stores the SSID for configuration
377 
378   Returns:      None.
379  *---------------------------------------------------------------------------*/
WXC_CallPreConnectHook(WXCProtocolContext * protocol,WMBssDesc * p_desc,u8 * ssid)380 void    WXC_CallPreConnectHook(WXCProtocolContext * protocol, WMBssDesc *p_desc, u8 *ssid)
381 {
382     WXCProtocolImpl * const impl = WXC_GetCurrentBlockImpl(protocol);
383     if (impl->PreConnectHook)
384     {
385         impl->PreConnectHook(protocol, p_desc, ssid);
386     }
387 }
388 
389 /*---------------------------------------------------------------------------*
390   Name:         WXC_InitProtocolRegistry
391 
392   Description:  Associates GGID and callback to the specified registry structure.
393 
394   Arguments:    p_data: WXCProtocolRegistry structure used for registration
395                 ggid: GGID to be set
396                 callback: Callback function to the user
397                           (Cancel setting if NULL)
398                 impl: Communication protocol to be adopted
399 
400   Returns:      None.
401  *---------------------------------------------------------------------------*/
WXC_InitProtocolRegistry(WXCProtocolRegistry * p_data,u32 ggid,WXCCallback callback,WXCProtocolImpl * impl)402 void WXC_InitProtocolRegistry(WXCProtocolRegistry * p_data, u32 ggid, WXCCallback callback,
403                               WXCProtocolImpl * impl)
404 {
405     p_data->ggid = ggid;
406     p_data->callback = callback;
407     p_data->impl = impl;
408     p_data->send.buffer = NULL;
409     p_data->send.length = 0;
410     p_data->recv.buffer = NULL;
411     p_data->recv.length = 0;
412 }
413 
414 /*---------------------------------------------------------------------------*
415   Name:         WXC_SetInitialExchangeBuffers
416 
417   Description:  Sets automatically used data for the initial data exchange.
418 
419   Arguments:    p_data: WXCProtocolRegistry structure used for registration
420                 send_ptr: Pointer to registered data
421                 send_size: Size of registered data
422                 recv_ptr: Pointer to the receive buffer
423                 recv_size: Receive buffer size
424 
425   Returns:      None.
426  *---------------------------------------------------------------------------*/
WXC_SetInitialExchangeBuffers(WXCProtocolRegistry * p_data,u8 * send_ptr,u32 send_size,u8 * recv_ptr,u32 recv_size)427 void WXC_SetInitialExchangeBuffers(WXCProtocolRegistry * p_data, u8 *send_ptr, u32 send_size,
428                                    u8 *recv_ptr, u32 recv_size)
429 {
430     p_data->send.buffer = send_ptr;
431     p_data->send.length = (u32)send_size;
432 
433     p_data->recv.buffer = recv_ptr;
434     p_data->recv.length = (u32)recv_size;
435 }
436