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