1 /*---------------------------------------------------------------------------*
2 Project: TwlSDK - WM - libraries
3 File: wm_sync.c
4
5 Copyright 2003-2008 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-11-19#$
14 $Rev: 9342 $
15 $Author: okajima_manabu $
16 *---------------------------------------------------------------------------*/
17
18 #include <nitro/wm.h>
19 #include "wm_arm9_private.h"
20
21
22 /*---------------------------------------------------------------------------*
23 Name: WM_SetIndCallback
24
25 Description: Sets a function that is called to the status notification from WM7.
26
27 Arguments: callback - Specifies the callback function called during status notification from the wireless firmware.
28
29
30 Returns: WMErrCode - Returns the processing result.
31 *---------------------------------------------------------------------------*/
WM_SetIndCallback(WMCallbackFunc callback)32 WMErrCode WM_SetIndCallback(WMCallbackFunc callback)
33 {
34 WMErrCode result;
35 OSIntrMode e;
36
37 // Disable interrupts
38 e = OS_DisableInterrupts();
39
40 // Confirm that initialized
41 result = WMi_CheckInitialized();
42 if (result != WM_ERRCODE_SUCCESS)
43 {
44 // End disabling of interrupts
45 (void)OS_RestoreInterrupts(e);
46 return result;
47 }
48
49 // Set the callback for Indication
50 WMi_GetSystemWork()->indCallback = callback;
51 // End disabling of interrupts
52 (void)OS_RestoreInterrupts(e);
53
54 return WM_ERRCODE_SUCCESS;
55 }
56
57 /*---------------------------------------------------------------------------*
58 Name: WM_SetPortCallback
59
60 Description: Sets a function that is called for the communication frame reception notification from WM7.
61
62 Arguments: port - Port number
63 callback: The callback function invoked when there is a receive notification.
64 arg - Argument passed to the callback function as WMPortRecvCallback.arg
65
66
67 Returns: WMErrCode - Returns the processing result.
68 *---------------------------------------------------------------------------*/
WM_SetPortCallback(u16 port,WMCallbackFunc callback,void * arg)69 WMErrCode WM_SetPortCallback(u16 port, WMCallbackFunc callback, void *arg)
70 {
71 WMErrCode result;
72 OSIntrMode e;
73 WMPortRecvCallback cb_Port;
74
75 // Check parameters
76 #ifdef SDK_DEBUG
77 if (port >= WM_NUM_OF_PORT)
78 {
79 WM_WARNING("Parameter \"port\" must be less than 16.\n");
80 return WM_ERRCODE_INVALID_PARAM;
81 }
82 #endif
83
84 if (callback != NULL)
85 {
86 MI_CpuClear8(&cb_Port, sizeof(WMPortRecvCallback));
87 cb_Port.apiid = WM_APIID_PORT_RECV;
88 cb_Port.errcode = WM_ERRCODE_SUCCESS;
89 cb_Port.state = WM_STATECODE_PORT_INIT;
90 cb_Port.port = port;
91 cb_Port.recvBuf = NULL;
92 cb_Port.data = NULL;
93 cb_Port.length = 0;
94 cb_Port.seqNo = 0xffff;
95 cb_Port.arg = arg;
96 cb_Port.aid = 0;
97 OS_GetMacAddress(cb_Port.macAddress);
98 }
99
100 // Disable interrupts
101 e = OS_DisableInterrupts();
102 // Confirm that initialized
103 result = WMi_CheckInitialized();
104 if (result != WM_ERRCODE_SUCCESS)
105 {
106 // End disabling of interrupts
107 (void)OS_RestoreInterrupts(e);
108 return result;
109 }
110
111 // Set the callback for data reception
112 {
113 WMArm9Buf *p = WMi_GetSystemWork();
114
115 p->portCallbackTable[port] = callback;
116 p->portCallbackArgument[port] = arg;
117 }
118
119 if (callback != NULL)
120 {
121 cb_Port.connectedAidBitmap = WM_GetConnectedAIDs();
122 cb_Port.myAid = WM_GetAID();
123 (*callback) ((void *)&cb_Port);
124 }
125
126 // End disabling of interrupts
127 (void)OS_RestoreInterrupts(e);
128
129 return WM_ERRCODE_SUCCESS;
130 }
131
132 /*---------------------------------------------------------------------------*
133 Name: WM_ReadStatus
134
135 Description: Obtains the structure that indicates the status of the wireless library.
136
137 Arguments: statusBuf - Pointer to the variable that obtains the status.
138
139 Returns: WMErrCode - Returns the processing result.
140 *---------------------------------------------------------------------------*/
WM_ReadStatus(WMStatus * statusBuf)141 WMErrCode WM_ReadStatus(WMStatus *statusBuf)
142 {
143 WMErrCode result;
144 WMArm9Buf *p = WMi_GetSystemWork();
145
146 // Confirm that initialized
147 result = WMi_CheckInitialized();
148 WM_CHECK_RESULT(result);
149
150 // Check parameters
151 if (statusBuf == NULL)
152 {
153 WM_WARNING("Parameter \"statusBuf\" must not be NULL.\n");
154 return WM_ERRCODE_INVALID_PARAM;
155 }
156
157 // Copy the WMStatus structure to the CPU
158 DC_InvalidateRange(p->status, sizeof(WMStatus));
159 MI_CpuCopyFast(p->status, statusBuf, sizeof(WMStatus));
160
161 return WM_ERRCODE_SUCCESS;
162 }
163
164 /*---------------------------------------------------------------------------*
165 Name: WM_GetMPSendBufferSize
166
167 Description: Calculates the size of the send buffer for MP communications.
168 At this time, StartParent and StartConnect must be finished.
169
170 Arguments: None.
171
172 Returns: int - Send buffer size to be passed to WM_StartMP.
173 *---------------------------------------------------------------------------*/
WM_GetMPSendBufferSize(void)174 int WM_GetMPSendBufferSize(void)
175 {
176 WMErrCode result;
177 int maxSendSize;
178 WMArm9Buf *p = WMi_GetSystemWork();
179
180 // Check the state
181 result = WMi_CheckStateEx(2, WM_STATE_PARENT, WM_STATE_CHILD);
182 if (result != WM_ERRCODE_SUCCESS)
183 {
184 return 0;
185 }
186
187 // Confirm MP status
188 DC_InvalidateRange(&(p->status->mp_flag), 4); // Invalidates the ARM7 status region cache
189 if (p->status->mp_flag == TRUE)
190 {
191 WM_WARNING("Already started MP protocol. So can't execute request.\n");
192 return 0;
193 }
194
195 // Reference the MWStatus structure for information needed for the calculation
196 DC_InvalidateRange(&(p->status->mp_maxSendSize), 4);
197 maxSendSize = p->status->mp_maxSendSize;
198
199 return ((maxSendSize + 31) & ~0x1f);
200 }
201
202 /*---------------------------------------------------------------------------*
203 Name: WM_GetMPReceiveBufferSize
204
205 Description: Calculates the size of the Receive buffer for MP communications.
206 At this time, StartParent and StartConnect must be finished.
207
208 Arguments: None.
209
210 Returns: int - Receive buffer size to be passed to WM_StartMP.
211 *---------------------------------------------------------------------------*/
WM_GetMPReceiveBufferSize(void)212 int WM_GetMPReceiveBufferSize(void)
213 {
214 WMErrCode result;
215 BOOL isParent;
216 int maxReceiveSize;
217 int maxEntry;
218 WMArm9Buf *p = WMi_GetSystemWork();
219
220 // Check the state
221 result = WMi_CheckStateEx(2, WM_STATE_PARENT, WM_STATE_CHILD);
222 if (result != WM_ERRCODE_SUCCESS)
223 {
224 return 0;
225 }
226
227 // Confirm MP status
228 DC_InvalidateRange(&(p->status->mp_flag), 4);
229 if (p->status->mp_flag == TRUE)
230 {
231 WM_WARNING("Already started MP protocol. So can't execute request.\n");
232 return 0;
233 }
234
235 // Reference the MWStatus structure for information needed for the calculation
236 DC_InvalidateRange(&(p->status->aid), 2);
237 isParent = (p->status->aid == 0) ? TRUE : FALSE;
238 DC_InvalidateRange(&(p->status->mp_maxRecvSize), 2);
239 maxReceiveSize = p->status->mp_maxRecvSize;
240 if (isParent == TRUE)
241 {
242 DC_InvalidateRange(&(p->status->pparam.maxEntry), 2);
243 maxEntry = p->status->pparam.maxEntry;
244 return (int)((sizeof(WMmpRecvHeader) - sizeof(WMmpRecvData) +
245 ((sizeof(WMmpRecvData) + maxReceiveSize - 2 + 2 /*MACBUG*/) * maxEntry)
246 + 31) & ~0x1f) * 2;
247 }
248 else
249 {
250 return (int)((sizeof(WMMpRecvBuf) + maxReceiveSize - 4 + 31) & ~0x1f) * 2;
251 }
252 }
253
254 /*---------------------------------------------------------------------------*
255 Name: WM_ReadMPData
256
257 Description: Extracts only the data of the specified child from the entire received data.
258
259 Arguments: header - Pointer that indicates the entire received data.
260 aid - AID of the child to extract data.
261
262 Returns: WMMpRecvData* - Returns a pointer to the data received from the corresponding child.
263 Returns NULL if extraction fails.
264 *---------------------------------------------------------------------------*/
WM_ReadMPData(const WMMpRecvHeader * header,u16 aid)265 WMMpRecvData *WM_ReadMPData(const WMMpRecvHeader *header, u16 aid)
266 {
267 int i;
268 WMErrCode result;
269 WMMpRecvData *recvdata_p[WM_NUM_MAX_CHILD]; // Array of pointers to data starting position for all child devices (up to 15 devices).
270 WMArm9Buf *p = WMi_GetSystemWork();
271
272 // Check if initialized
273 result = WMi_CheckInitialized();
274 if (result != WM_ERRCODE_SUCCESS)
275 {
276 return NULL;
277 }
278
279 // Check parameters
280 if ((aid < 1) || (aid > WM_NUM_MAX_CHILD))
281 {
282 WM_WARNING("Parameter \"aid\" must be between 1 and %d.\n", WM_NUM_MAX_CHILD);
283 return NULL;
284 }
285
286 // Does child with that AID exist?
287 DC_InvalidateRange(&(p->status->child_bitmap), 2);
288 if (0 == (p->status->child_bitmap & (0x0001 << aid)))
289 {
290 return NULL;
291 }
292
293 // Is there any received data?
294 if (header->count == 0)
295 {
296 return NULL;
297 }
298
299 // Calculate starting position for child data
300 recvdata_p[0] = (WMMpRecvData *)(header->data);
301
302 i = 0;
303 do
304 {
305 // If it is the specified AID's child data, it returns its pointer.
306 if (recvdata_p[i]->aid == aid)
307 return recvdata_p[i];
308
309 ++i;
310 recvdata_p[i] = (WMMpRecvData *)((u32)(recvdata_p[i - 1]) + header->length);
311 }
312 while (i < header->count);
313
314 return NULL;
315 }
316
317 /*---------------------------------------------------------------------------*
318 Name: WM_GetAllowedChannel
319
320 Description: Obtains the channel that was permitted to use for the communication.
321
322 Arguments: None.
323
324 Returns: u16 - Returns the bit field of the permitted channel.
325 The least significant bit indicates channel 1, and the most significant bit indicates channel 16.
326 A channel can be used if its corresponding bit is set to 1 and is prohibited from being used if its corresponding bit is set to 0.
327 Typically, a value is returned with several of the bits corresponding to channels 1-13 set to 1.
328 When 0x0000 is returned, no channels can be used and wireless features are themselves prohibited.
329
330 Also, in case the function failed, such as when it is not yet initialized, 0x8000 is returned.
331 *---------------------------------------------------------------------------*/
WM_GetAllowedChannel(void)332 u16 WM_GetAllowedChannel(void)
333 {
334 #ifdef WM_PRECALC_ALLOWEDCHANNEL
335 WMErrCode result;
336
337 #ifdef SDK_TWL // Return an error if the TWL System Settings are configured not to use wireless.
338 if( OS_IsRunOnTwl() )
339 {
340 if( WMi_CheckEnableFlag() == FALSE )
341 {
342 return 0;
343 }
344 }
345 #endif
346
347 // Check if initialized
348 result = WMi_CheckInitialized();
349 if (result != WM_ERRCODE_SUCCESS)
350 {
351 return WM_GET_ALLOWED_CHANNEL_BEFORE_INIT;
352 }
353 return *((u16 *)((u32)(OS_GetSystemWork()->nvramUserInfo) +
354 ((sizeof(NVRAMConfig) + 3) & ~0x00000003) + 6));
355 #else
356 WMErrCode result;
357 WMArm9Buf *p = WMi_GetSystemWork();
358
359 #ifdef SDK_TWL // Return an error if the TWL System Settings are configured not to use wireless.
360 if( OS_IsRunOnTwl() )
361 {
362 if( WMi_CheckEnableFlag() == FALSE )
363 {
364 return 0;
365 }
366 }
367 #endif
368
369 // Confirm that wireless hardware has started
370 result = WMi_CheckIdle();
371 if (result != WM_ERRCODE_SUCCESS)
372 {
373 return WM_GET_ALLOWED_CHANNEL_BEFORE_INIT;
374 }
375
376 DC_InvalidateRange(&(p->status->allowedChannel), 2);
377 return p->status->allowedChannel;
378 #endif
379 }
380
381 #ifdef WM_PRECALC_ALLOWEDCHANNEL
382 /*---------------------------------------------------------------------------*
383 Name: WM_IsExistAllowedChannel
384
385 Description: Checks if the channel that was permitted to be used for communication actually exists.
386 Possible to determine it properly even before the initialization of WM library.
387
388 Arguments: None.
389
390 Returns: BOOL - Returns TRUE if there is a usable channel and FALSE otherwise.
391
392 *---------------------------------------------------------------------------*/
WM_IsExistAllowedChannel(void)393 BOOL WM_IsExistAllowedChannel(void)
394 {
395 u16 allowedChannel;
396
397 allowedChannel = *((u16 *)((u32)(OS_GetSystemWork()->nvramUserInfo) +
398 ((sizeof(NVRAMConfig) + 3) & ~0x00000003) + 6));
399 if (allowedChannel)
400 {
401 return TRUE;
402 }
403 return FALSE;
404 }
405 #endif
406
407 /*---------------------------------------------------------------------------*
408 Name: WM_GetLinkLevel
409
410 Description: Gets link level during communication. Synchronous function.
411
412 Arguments: None.
413
414 Returns: WMLinkLevel - Returns the link level rated in four levels.
415 *---------------------------------------------------------------------------*/
WM_GetLinkLevel(void)416 WMLinkLevel WM_GetLinkLevel(void)
417 {
418 WMErrCode result;
419 WMArm9Buf *p = WMi_GetSystemWork();
420
421 // Check if initialized
422 result = WMi_CheckInitialized();
423 if (result != WM_ERRCODE_SUCCESS)
424 {
425 return WM_LINK_LEVEL_0; // Lowest radio strength
426 }
427
428 DC_InvalidateRange(&(p->status->state), 2);
429 switch (p->status->state)
430 {
431 case WM_STATE_MP_PARENT:
432 // For parent
433 DC_InvalidateRange(&(p->status->child_bitmap), 2);
434 if (p->status->child_bitmap == 0)
435 {
436 // When there is no child
437 return WM_LINK_LEVEL_0; // Lowest radio strength
438 }
439 case WM_STATE_MP_CHILD:
440 case WM_STATE_DCF_CHILD:
441 // For child
442 DC_InvalidateRange(&(p->status->linkLevel), 2);
443 return (WMLinkLevel)(p->status->linkLevel);
444 }
445
446 // When unconnected
447 return WM_LINK_LEVEL_0; // Lowest radio strength
448 }
449
450 /*---------------------------------------------------------------------------*
451 Name: WM_GetDispersionBeaconPeriod
452
453 Description: Obtains the beacon interval value that should be set when operating as a parent.
454
455 Arguments: None.
456
457 Returns: u16 - Beacon interval value that should be set (ms).
458 *---------------------------------------------------------------------------*/
WM_GetDispersionBeaconPeriod(void)459 u16 WM_GetDispersionBeaconPeriod(void)
460 {
461 u8 mac[6];
462 u16 ret;
463 s32 i;
464
465 OS_GetMacAddress(mac);
466 for (i = 0, ret = 0; i < 6; i++)
467 {
468 ret += mac[i];
469 }
470 ret += OS_GetVBlankCount();
471 ret *= 7;
472 return (u16)(WM_DEFAULT_BEACON_PERIOD + (ret % 20));
473 }
474
475 /*---------------------------------------------------------------------------*
476 Name: WM_GetDispersionScanPeriod
477
478 Description: Obtains the search limit time that should be set for a child to search for a parent.
479
480 Arguments: None.
481
482 Returns: u16 - Search limit time that should be set (ms).
483 *---------------------------------------------------------------------------*/
WM_GetDispersionScanPeriod(void)484 u16 WM_GetDispersionScanPeriod(void)
485 {
486 u8 mac[6];
487 u16 ret;
488 s32 i;
489
490 OS_GetMacAddress(mac);
491 for (i = 0, ret = 0; i < 6; i++)
492 {
493 ret += mac[i];
494 }
495 ret += OS_GetVBlankCount();
496 ret *= 13;
497 return (u16)(WM_DEFAULT_SCAN_PERIOD + (ret % 10));
498 }
499
500 /*---------------------------------------------------------------------------*
501 Name: WM_GetOtherElements
502
503 Description: Gets the extended elements in the beacon.
504 Synchronous function.
505
506 Arguments: bssDesc - Parent information structure.
507 Specifies the structure obtained with WM_StartScan(Ex).
508
509 Returns: WMOtherElements - Extended element structure.
510 *---------------------------------------------------------------------------*/
WM_GetOtherElements(WMBssDesc * bssDesc)511 WMOtherElements WM_GetOtherElements(WMBssDesc *bssDesc)
512 {
513 WMOtherElements elems;
514 u8 *p_elem;
515 int i;
516 u16 curr_elem_len;
517 u16 elems_len; // Length of all elements
518 u16 elems_len_counter; // Counter for checking the length of elements
519
520 // Ends when gameInfo is included
521 if (bssDesc->gameInfoLength != 0)
522 {
523 elems.count = 0;
524 return elems;
525 }
526
527 // Get otherElement count and terminate if 0.
528 elems.count = (u8)(bssDesc->otherElementCount);
529 if (elems.count == 0)
530 return elems;
531
532 // The maximum allowed number of elems is limited to WM_SCAN_OTHER_ELEMENT_MAX.
533 if (elems.count > WM_SCAN_OTHER_ELEMENT_MAX)
534 elems.count = WM_SCAN_OTHER_ELEMENT_MAX;
535
536 // First set the start of elements into gameInfo.
537 p_elem = (u8 *)&(bssDesc->gameInfo);
538
539 // Get length of all elements and initialize counter used for checking.
540 elems_len = (u16)((bssDesc->length * sizeof(u16)) - 64);
541 elems_len_counter = 0;
542
543 // Loop only 'elems' times
544 for (i = 0; i < elems.count; ++i)
545 {
546 elems.element[i].id = p_elem[0];
547 elems.element[i].length = p_elem[1];
548 elems.element[i].body = (u8 *)&(p_elem[2]);
549
550 // Calculate current element length and add to the check counter.
551 curr_elem_len = (u16)(elems.element[i].length + 2);
552 elems_len_counter += curr_elem_len;
553
554 // OS_Printf("eles_len =%d\n", elems_len);
555 // OS_Printf("eles_len_counter=%d\n", elems_len_counter);
556
557 // An error results if the length of all elements is exceeded, and notify that there were no element.
558 //
559 if (elems_len_counter > elems_len)
560 {
561 WM_WARNING("Elements length error.\n");
562 elems.count = 0;
563 return elems;
564 }
565
566 // Calculate the lead address of the next element
567 p_elem = (u8 *)(p_elem + curr_elem_len);
568 }
569
570 return elems;
571 }
572
573 /*---------------------------------------------------------------------------*
574 Name: WM_GetNextTgid
575
576 Description: Gets the automatically generated, unique TGID value.
577 Synchronous function.
578
579 Arguments: None.
580
581 Returns: The first time it is called, it returns a TGID that was generated based on the RTC; thereafter, it returns the value returned the previous time incremented by 1.
582
583 *---------------------------------------------------------------------------*/
WM_GetNextTgid(void)584 u16 WM_GetNextTgid(void)
585 {
586 enum
587 { TGID_DEFAULT = (1 << 16) };
588 static u32 tgid_bak = (u32)TGID_DEFAULT;
589 /* Use the RTC time value the first time so as to preserve the integrity of the unit's own time */
590 if (tgid_bak == (u32)TGID_DEFAULT)
591 {
592 RTCTime rt[1];
593 RTC_Init();
594 if (RTC_GetTime(rt) == RTC_RESULT_SUCCESS)
595 {
596 tgid_bak = (u16)(rt->second + (rt->minute << 8));
597 }
598 else
599 {
600 OS_Warning("failed to get RTC-data to create unique TGID!\n");
601 }
602 }
603 /* Use the unique value and increment each time */
604 tgid_bak = (u16)(tgid_bak + 1);
605 return (u16)tgid_bak;
606 }
607
608
609 /*---------------------------------------------------------------------------*
610 End of file
611 *---------------------------------------------------------------------------*/
612