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:: 2009-06-19#$
14 $Rev: 10786 $
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: 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 // Prohibit interrupts
38 e = OS_DisableInterrupts();
39
40 // Confirm that initialized
41 result = WMi_CheckInitialized();
42 if (result != WM_ERRCODE_SUCCESS)
43 {
44 // End prohibiting 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 prohibiting 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: 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 // Prohibit interrupts
101 e = OS_DisableInterrupts();
102 // Confirm that initialized
103 result = WMi_CheckInitialized();
104 if (result != WM_ERRCODE_SUCCESS)
105 {
106 // End prohibiting 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 prohibiting of interrupts
127 (void)OS_RestoreInterrupts(e);
128
129 return WM_ERRCODE_SUCCESS;
130 }
131
132 /*---------------------------------------------------------------------------*
133 Name: WM_ReadStatus
134
135 Description: Gets the structure that indicates the status of the wireless library.
136
137 Arguments: statusBuf: Pointer to the variable that gets 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? || Is the 'count' field value erroneous?
294 if (header->count == 0 || header->count > WM_NUM_MAX_CHILD)
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 {
308 return recvdata_p[i];
309 }
310 ++i;
311 recvdata_p[i] = (WMMpRecvData *)((u32)(recvdata_p[i - 1]) + header->length);
312 }
313 while (i < header->count);
314
315 return NULL;
316 }
317
318 /*---------------------------------------------------------------------------*
319 Name: WM_GetAllowedChannel
320
321 Description: Gets the channel that was permitted to use for the communication.
322
323 Arguments: None.
324
325 Returns: u16: Returns the bit field of the permitted channel. 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 Also, in case the function failed, such as when it is not yet initialized, 0x8000 is returned.
330
331
332 *---------------------------------------------------------------------------*/
WM_GetAllowedChannel(void)333 u16 WM_GetAllowedChannel(void)
334 {
335 #ifdef WM_PRECALC_ALLOWEDCHANNEL
336 WMErrCode result;
337
338 #ifdef SDK_TWL // Return an error if the TWL System Settings are configured not to use wireless
339 if( OS_IsRunOnTwl() )
340 {
341 if( WMi_CheckEnableFlag() == FALSE )
342 {
343 return 0;
344 }
345 }
346 #endif
347
348 // Check if initialized
349 result = WMi_CheckInitialized();
350 if (result != WM_ERRCODE_SUCCESS)
351 {
352 return WM_GET_ALLOWED_CHANNEL_BEFORE_INIT;
353 }
354 return *((u16 *)((u32)(OS_GetSystemWork()->nvramUserInfo) +
355 ((sizeof(NVRAMConfig) + 3) & ~0x00000003) + 6));
356 #else
357 WMErrCode result;
358 WMArm9Buf *p = WMi_GetSystemWork();
359
360 #ifdef SDK_TWL // Return an error if the TWL System Settings are configured not to use wireless
361 if( OS_IsRunOnTwl() )
362 {
363 if( WMi_CheckEnableFlag() == FALSE )
364 {
365 return 0;
366 }
367 }
368 #endif
369
370 // Confirm that wireless hardware has started
371 result = WMi_CheckIdle();
372 if (result != WM_ERRCODE_SUCCESS)
373 {
374 return WM_GET_ALLOWED_CHANNEL_BEFORE_INIT;
375 }
376
377 DC_InvalidateRange(&(p->status->allowedChannel), 2);
378 return p->status->allowedChannel;
379 #endif
380 }
381
382 #ifdef WM_PRECALC_ALLOWEDCHANNEL
383 /*---------------------------------------------------------------------------*
384 Name: WM_IsExistAllowedChannel
385
386 Description: Checks whether the channel that was permitted to be used for communication actually exists.
387 Possible to determine it properly even before the initialization of WM library.
388
389 Arguments: None.
390
391 Returns: BOOL: Returns TRUE if there is a usable channel and FALSE otherwise.
392
393 *---------------------------------------------------------------------------*/
WM_IsExistAllowedChannel(void)394 BOOL WM_IsExistAllowedChannel(void)
395 {
396 u16 allowedChannel;
397
398 allowedChannel = *((u16 *)((u32)(OS_GetSystemWork()->nvramUserInfo) +
399 ((sizeof(NVRAMConfig) + 3) & ~0x00000003) + 6));
400 if (allowedChannel)
401 {
402 return TRUE;
403 }
404 return FALSE;
405 }
406 #endif
407
408 /*---------------------------------------------------------------------------*
409 Name: WM_GetLinkLevel
410
411 Description: Gets link level during communication. Synchronous function.
412
413 Arguments: None.
414
415 Returns: WMLinkLevel: Link level rated in four levels.
416 *---------------------------------------------------------------------------*/
WM_GetLinkLevel(void)417 WMLinkLevel WM_GetLinkLevel(void)
418 {
419 WMErrCode result;
420 WMArm9Buf *p = WMi_GetSystemWork();
421
422 // Check if initialized
423 result = WMi_CheckInitialized();
424 if (result != WM_ERRCODE_SUCCESS)
425 {
426 return WM_LINK_LEVEL_0; // Lowest radio strength
427 }
428
429 DC_InvalidateRange(&(p->status->state), 2);
430 switch (p->status->state)
431 {
432 case WM_STATE_MP_PARENT:
433 // For parent
434 DC_InvalidateRange(&(p->status->child_bitmap), 2);
435 if (p->status->child_bitmap == 0)
436 {
437 // When there is no child
438 return WM_LINK_LEVEL_0; // Lowest radio strength
439 }
440 case WM_STATE_MP_CHILD:
441 case WM_STATE_DCF_CHILD:
442 // For child
443 DC_InvalidateRange(&(p->status->linkLevel), 2);
444 return (WMLinkLevel)(p->status->linkLevel);
445 }
446
447 // When unconnected
448 return WM_LINK_LEVEL_0; // Lowest radio strength
449 }
450
451 /*---------------------------------------------------------------------------*
452 Name: WM_GetDispersionBeaconPeriod
453
454 Description: Gets the beacon interval value that should be set when operating as a parent.
455
456 Arguments: None.
457
458 Returns: u16: Beacon interval value that should be set (ms).
459 *---------------------------------------------------------------------------*/
WM_GetDispersionBeaconPeriod(void)460 u16 WM_GetDispersionBeaconPeriod(void)
461 {
462 u8 mac[6];
463 u16 ret;
464 s32 i;
465
466 OS_GetMacAddress(mac);
467 for (i = 0, ret = 0; i < 6; i++)
468 {
469 ret += mac[i];
470 }
471 ret += OS_GetVBlankCount();
472 ret *= 7;
473 return (u16)(WM_DEFAULT_BEACON_PERIOD + (ret % 20));
474 }
475
476 /*---------------------------------------------------------------------------*
477 Name: WM_GetDispersionScanPeriod
478
479 Description: Gets the search limit time that should be set for a child to search for a parent.
480
481 Arguments: None.
482
483 Returns: u16: Search limit time that should be set (ms).
484 *---------------------------------------------------------------------------*/
WM_GetDispersionScanPeriod(void)485 u16 WM_GetDispersionScanPeriod(void)
486 {
487 u8 mac[6];
488 u16 ret;
489 s32 i;
490
491 OS_GetMacAddress(mac);
492 for (i = 0, ret = 0; i < 6; i++)
493 {
494 ret += mac[i];
495 }
496 ret += OS_GetVBlankCount();
497 ret *= 13;
498 return (u16)(WM_DEFAULT_SCAN_PERIOD + (ret % 10));
499 }
500
501 /*---------------------------------------------------------------------------*
502 Name: WM_GetOtherElements
503
504 Description: Gets the extended elements in the beacon.
505 Synchronous function.
506
507 Arguments: bssDesc: Parent information structure.
508 Specifies the structure obtained with WM_StartScan(Ex).
509
510 Returns: WMOtherElements: Extended element structure.
511 *---------------------------------------------------------------------------*/
WM_GetOtherElements(WMBssDesc * bssDesc)512 WMOtherElements WM_GetOtherElements(WMBssDesc *bssDesc)
513 {
514 WMOtherElements elems;
515 u8 *p_elem;
516 int i;
517 u16 curr_elem_len;
518 u16 elems_len; // Length of all elements
519 u16 elems_len_counter; // Counter for checking the length of elements
520
521 // Ends when gameInfo is included
522 if (bssDesc->gameInfoLength != 0)
523 {
524 elems.count = 0;
525 return elems;
526 }
527
528 // Get otherElement count and terminate if 0
529 elems.count = (u8)(bssDesc->otherElementCount);
530 if (elems.count == 0)
531 return elems;
532
533 // The maximum allowed number of elems is limited to WM_SCAN_OTHER_ELEMENT_MAX
534 if (elems.count > WM_SCAN_OTHER_ELEMENT_MAX)
535 elems.count = WM_SCAN_OTHER_ELEMENT_MAX;
536
537 // First set the start of elements into gameInfo
538 p_elem = (u8 *)&(bssDesc->gameInfo);
539
540 // Get length of all elements and initialize counter used for checking
541 elems_len = (u16)((bssDesc->length * sizeof(u16)) - 64);
542 elems_len_counter = 0;
543
544 // Loop only 'elems' times
545 for (i = 0; i < elems.count; ++i)
546 {
547 elems.element[i].id = p_elem[0];
548 elems.element[i].length = p_elem[1];
549 elems.element[i].body = (u8 *)&(p_elem[2]);
550
551 // Calculate current element length and add to the check counter
552 curr_elem_len = (u16)(elems.element[i].length + 2);
553 elems_len_counter += curr_elem_len;
554
555 // OS_TPrintf("eles_len =%d\n", elems_len);
556 // OS_TPrintf("eles_len_counter=%d\n", elems_len_counter);
557
558 // An error results if the length of all elements is exceeded, and notify that there were no element
559 //
560 if (elems_len_counter > elems_len)
561 {
562 WM_WARNING("Elements length error.\n");
563 elems.count = 0;
564 return elems;
565 }
566
567 // Calculate the lead address of the next element
568 p_elem = (u8 *)(p_elem + curr_elem_len);
569 }
570
571 return elems;
572 }
573
574 /*---------------------------------------------------------------------------*
575 Name: WM_GetNextTgid
576
577 Description: Gets the automatically generated, unique TGID value.
578 Synchronous function.
579
580 Arguments: None.
581
582 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.
583
584 *---------------------------------------------------------------------------*/
WM_GetNextTgid(void)585 u16 WM_GetNextTgid(void)
586 {
587 enum
588 { TGID_DEFAULT = (1 << 16) };
589 static u32 tgid_bak = (u32)TGID_DEFAULT;
590 /* Use the RTC time value the first time so as to preserve the integrity of the unit's own time */
591 if (tgid_bak == (u32)TGID_DEFAULT)
592 {
593 RTCTime rt[1];
594 RTC_Init();
595 if (RTC_GetTime(rt) == RTC_RESULT_SUCCESS)
596 {
597 tgid_bak = (u16)(rt->second + (rt->minute << 8));
598 }
599 else
600 {
601 OS_TWarning("failed to get RTC-data to create unique TGID!\n");
602 }
603 }
604 /* Use the unique value and increment each time */
605 tgid_bak = (u16)(tgid_bak + 1);
606 return (u16)tgid_bak;
607 }
608
609
610 /*---------------------------------------------------------------------------*
611 End of file
612 *---------------------------------------------------------------------------*/
613