1 /*---------------------------------------------------------------------------*
2 Project: TwlSDK - wireless_shared - demos - wfs
3 File: wfs_common.h
4
5 Copyright 2007-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-09-18#$
14 $Rev: 8573 $
15 $Author: okubata_ryoma $
16 *---------------------------------------------------------------------------*/
17 #include <nitro.h>
18
19 #include "wfs.h"
20
21
22 /*---------------------------------------------------------------------------*/
23 /* Constants */
24
25 /* Wireless event */
26 typedef enum WirelessEvent
27 {
28 WIRELESS_EVENT_END, /* Quit */
29 WIRELESS_EVENT_LINKUP, /* Start MP communication */
30 WIRELESS_EVENT_CONNECTED, /* Connection notification */
31 WIRELESS_EVENT_DISCONNECTED, /* Disconnect notification */
32 WIRELESS_EVENT_PACKET_SEND, /* Send packet */
33 WIRELESS_EVENT_PACKET_RECV /* Receive packet */
34 }
35 WirelessEvent;
36
37
38 /*---------------------------------------------------------------------------*/
39 /* Declarations */
40
41 typedef void (*WirelessEventCallback)(void *userdata, WirelessEvent event, void *argument);
42 typedef struct StaticWork
43 {
44 /* Internal state management */
45 WFSState state;
46 WFSStateCallback state_func;
47 u32 available:1;
48 u32 mp_availale:1;
49 u32 initialized:1;
50 u32 linkup_done:1;
51 u32 mp_operating:1;
52 u32 debug_enable:1;
53 u32 flags:26;
54 /* Allocator format change information */
55 MIAllocator allocator[1];
56 WFSAllocator user_alloc;
57 void *user_alloc_arg;
58 /* Dynamic memory for separate parent/child WFS processing */
59 WirelessEventCallback callback;
60 void *context;
61 WFSServerContext *server;
62 WFSClientContext *client;
63 u8 padding[12];
64 /* MP communication settings */
65 int port;
66 u8 packet_buf[1024] ATTRIBUTE_ALIGN(32);
67 WMStatus status_buf[1] ATTRIBUTE_ALIGN(32);
68 }
69 StaticWork;
70
71
72 /*---------------------------------------------------------------------------*/
73 /* Variables */
74
75 static StaticWork static_work[1] ATTRIBUTE_ALIGN(32);
76
77
78 /*---------------------------------------------------------------------------*/
79 /* Functions */
80
81 static void WFSi_PortSendCallback(void *callback);
82
83 /*---------------------------------------------------------------------------*
84 Name: InternalAlloc
85
86 Description: An internal function that converts the demo's old specification allocator.
87
88 Arguments: userdata: StaticWork structure
89 length: The size to be allocated
90 alignment: The required byte-alignment (must be a power of 2)
91
92 Returns: Either the allocated memory or NULL.
93 *---------------------------------------------------------------------------*/
InternalAlloc(void * userdata,u32 length,u32 alignment)94 static void *InternalAlloc(void *userdata, u32 length, u32 alignment)
95 {
96 StaticWork *work = (StaticWork*)userdata;
97 u32 newlen;
98 void *newptr;
99 void *aligned_ptr;
100 alignment = MATH_ROUNDUP(alignment, sizeof(u32));
101 newlen = MATH_ROUNDUP(length, alignment) + alignment;
102 newptr = (*work->user_alloc)(work->user_alloc_arg, newlen, NULL);
103 if (newptr)
104 {
105 aligned_ptr = (void*)MATH_ROUNDUP((u32)newptr + 1, alignment);
106 ((u32*)aligned_ptr)[-1] = (u32)aligned_ptr - (u32)newptr;
107 }
108 return aligned_ptr;
109 }
110
111 /*---------------------------------------------------------------------------*
112 Name: InternalFree
113
114 Description: An internal function that converts the demo's old specification allocator.
115
116 Arguments: userdata: StaticWork structure
117 buffer: The memory to deallocate
118
119 Returns: None.
120 *---------------------------------------------------------------------------*/
InternalFree(void * userdata,void * buffer)121 static void InternalFree(void *userdata, void *buffer)
122 {
123 StaticWork *work = (StaticWork*)userdata;
124 if (buffer)
125 {
126 void *rare_ptr = (u8*)buffer - ((u32*)buffer)[-1];
127 (void)(*work->user_alloc)(work->user_alloc_arg, 0, rare_ptr);
128 }
129 }
130
131 /*---------------------------------------------------------------------------*
132 Name: NotifyWirelessEvent
133
134 Description: Wireless event notification.
135
136 Arguments: work: StaticWork structure
137 event: Notified event
138 argument: Event argument
139
140 Returns: None.
141 *---------------------------------------------------------------------------*/
142 SDK_INLINE
NotifyWirelessEvent(StaticWork * work,WirelessEvent event,void * argument)143 void NotifyWirelessEvent(StaticWork *work, WirelessEvent event, void *argument)
144 {
145 (*work->callback)(work->context, event, argument);
146 }
147
148 /*---------------------------------------------------------------------------*
149 Name: WFSi_NotifySend
150
151 Description: Send packet notification.
152
153 Arguments: work: StaticWork structure
154
155 Returns: None.
156 *---------------------------------------------------------------------------*/
WFSi_NotifySend(StaticWork * work)157 static void WFSi_NotifySend(StaticWork *work)
158 {
159 if (work->mp_availale && work->linkup_done && !work->mp_operating)
160 {
161 /* Notify of a send packet event at the maximum MP setting currently possible. */
162 WFSPacketBuffer packet[1];
163 packet->buffer = work->packet_buf;
164 packet->bitmap = (work->status_buf->aid == 0) ? 0xFFFE : 0x0001;
165 packet->length = (work->status_buf->aid == 0) ?
166 work->status_buf->mp_parentMaxSize :
167 work->status_buf->mp_childMaxSize;
168 NotifyWirelessEvent(work, WIRELESS_EVENT_PACKET_SEND, packet);
169 /* If the packets that should be sent are specified, send them. */
170 if (packet->length > 0)
171 {
172 int ret = WM_SetMPDataToPortEx(WFSi_PortSendCallback,
173 work,
174 (const u16 *)packet->buffer,
175 (u16)packet->length,
176 (u16)packet->bitmap,
177 (u16)work->port,
178 WM_PRIORITY_LOW);
179 work->mp_operating = (ret == WM_ERRCODE_OPERATING);
180 }
181 }
182 }
183
184 /*---------------------------------------------------------------------------*
185 Name: WFSi_NotifyLinkup
186
187 Description: Linkup notification.
188
189 Arguments: wireless: StaticWork structure.
190
191 Returns: None.
192 *---------------------------------------------------------------------------*/
WFSi_NotifyLinkup(StaticWork * work)193 static void WFSi_NotifyLinkup(StaticWork *work)
194 {
195 if (work->mp_availale && work->initialized && !work->linkup_done)
196 {
197 WFSPeerInfo peer[1];
198 peer->aid = work->status_buf->aid;
199 MI_CpuCopy8(work->status_buf->MacAddress, peer->mac, 6);
200 NotifyWirelessEvent(work, WIRELESS_EVENT_LINKUP, peer);
201 work->linkup_done = TRUE;
202 }
203 }
204
205 /*---------------------------------------------------------------------------*
206 Name: WFSi_PortSendCallback
207
208 Description: Process when SetMPData completes.
209
210 Arguments: arg: WMPortSendCallback structure
211
212 Returns: None.
213 *---------------------------------------------------------------------------*/
WFSi_PortSendCallback(void * arg)214 static void WFSi_PortSendCallback(void *arg)
215 {
216 const WMPortSendCallback * const callback = (const WMPortSendCallback *)arg;
217 StaticWork * const work = callback->arg;
218 if (work->mp_availale)
219 {
220 work->mp_operating = FALSE;
221 WFSi_NotifySend(work);
222 }
223 }
224
225 /*---------------------------------------------------------------------------*
226 Name: WFSi_PortCallback
227
228 Description: Port reception callback.
229
230 Arguments: arg: WMPortRecvCallback structure
231
232 Returns: None.
233 *---------------------------------------------------------------------------*/
WFSi_PortCallback(void * arg)234 static void WFSi_PortCallback(void *arg)
235 {
236 const WMPortRecvCallback *const callback = (const WMPortRecvCallback *)arg;
237 StaticWork * const work = callback->arg;
238 if (work->mp_availale && work->linkup_done)
239 {
240 /* Convert to a callback format that matches WFS */
241 WFSPeerInfo peer[1];
242 WFSPacketBuffer packet[1];
243 peer->aid = callback->aid;
244 MI_CpuCopy8(callback->macAddress, peer->mac, 6);
245 packet->buffer = (u8 *)callback->data;
246 packet->length = callback->length;
247 packet->bitmap = (1 << peer->aid);
248 switch (callback->state)
249 {
250 case WM_STATECODE_CONNECTED:
251 NotifyWirelessEvent(work, WIRELESS_EVENT_CONNECTED, peer);
252 break;
253
254 case WM_STATECODE_DISCONNECTED:
255 case WM_STATECODE_DISCONNECTED_FROM_MYSELF:
256 NotifyWirelessEvent(work, WIRELESS_EVENT_DISCONNECTED, peer);
257 break;
258
259 case WM_STATECODE_PORT_RECV:
260 NotifyWirelessEvent(work, WIRELESS_EVENT_PACKET_RECV, packet);
261 /* If MP was stopped, start it up here */
262 WFSi_NotifySend(work);
263 break;
264
265 default:
266 break;
267 }
268 }
269 }
270
271 /*---------------------------------------------------------------------------*
272 Name: WFSi_InitCommon
273
274 Description: Common WFS parent/child initialization processing.
275
276 Arguments: callback: Status notification callback
277 allocator: Memory allocator
278 allocator_arg: Allocator arguments
279 port: Port number to use
280 worksize: Separate parent/child work memory size
281 wireless_proc: Separate parent/child wireless event handler
282
283 Returns: None.
284 *---------------------------------------------------------------------------*/
WFSi_InitCommon(WFSStateCallback callback,WFSAllocator allocator,void * allocator_arg,int port,u32 worksize,WirelessEventCallback wireless_proc)285 static void WFSi_InitCommon(WFSStateCallback callback,
286 WFSAllocator allocator, void *allocator_arg,
287 int port, u32 worksize,
288 WirelessEventCallback wireless_proc)
289 {
290 /* FS library is necessary for both the parent and child */
291 if (!FS_IsAvailable())
292 {
293 OS_TWarning("FS is initialized by WFS (with FS_DMA_NOT_USE)");
294 FS_Init(FS_DMA_NOT_USE);
295 }
296 {
297 OSIntrMode prev_irq = OS_DisableInterrupts();
298 if (!static_work->available)
299 {
300 /* Initialize the allocator */
301 static_work->user_alloc = allocator;
302 static_work->user_alloc_arg = allocator_arg;
303 MI_InitAllocator(static_work->allocator, static_work,
304 InternalAlloc, InternalFree);
305 /* Allocate dynamic memory for the parent and child separately */
306 static_work->context = MI_CallAlloc(static_work->allocator, worksize, 32);
307 if (!static_work->context)
308 {
309 OS_TPanic("cannot allocate enough memory for WFS");
310 }
311 /* Initialize the internal status */
312 static_work->available = TRUE;
313 static_work->state = WFS_STATE_STOP;
314 static_work->state_func = callback;
315 static_work->debug_enable = FALSE;
316 static_work->mp_availale = FALSE;
317 static_work->initialized = FALSE;
318 static_work->linkup_done = FALSE;
319 static_work->mp_operating = FALSE;
320 static_work->callback = wireless_proc;
321 static_work->port = port;
322 static_work->status_buf->aid = 0;
323 static_work->status_buf->mp_parentMaxSize = 0;
324 static_work->status_buf->mp_childMaxSize = 0;
325 }
326 (void)OS_RestoreInterrupts(prev_irq);
327 }
328 }
329
330
331 /*---------------------------------------------------------------------------*
332 Name: ParentWFSEvent
333
334 Description: WFS server event notification.
335
336 Arguments: userdata: User-defined argument
337 event: Event type
338 argument: Arguments unique to event
339
340 Returns: None.
341 *---------------------------------------------------------------------------*/
ParentWFSEvent(void * userdata,WFSEventType event,void * argument)342 static void ParentWFSEvent(void *userdata, WFSEventType event, void *argument)
343 {
344 /* Because we are using the WFS_ExecuteRomServerThread function, there is nothing in particular that needs to be done here */
345 (void)userdata;
346 (void)event;
347 (void)argument;
348 }
349
350 /*---------------------------------------------------------------------------*
351 Name: ParentWirelessEvent
352
353 Description: Event notification from the wireless driver.
354
355 Arguments: userdata: User-defined argument
356 event: Event type
357 argument: Arguments unique to event
358
359 Returns: None.
360 *---------------------------------------------------------------------------*/
ParentWirelessEvent(void * userdata,WirelessEvent event,void * argument)361 static void ParentWirelessEvent(void *userdata, WirelessEvent event, void *argument)
362 {
363 WFSServerContext * const context = (WFSServerContext *)userdata;
364 switch (event)
365 {
366 case WIRELESS_EVENT_END:
367 WFS_EndServer(context);
368 break;
369
370 case WIRELESS_EVENT_LINKUP:
371 /* Immediately move to the READY state */
372 static_work->state = WFS_STATE_READY;
373 if (static_work->state_func)
374 {
375 (*static_work->state_func) (NULL);
376 }
377 break;
378
379 case WIRELESS_EVENT_CONNECTED:
380 WFS_CallServerConnectHook(context, (const WFSPeerInfo*)argument);
381 break;
382
383 case WIRELESS_EVENT_DISCONNECTED:
384 WFS_CallServerDisconnectHook(context, (const WFSPeerInfo*)argument);
385 break;
386
387 case WIRELESS_EVENT_PACKET_SEND:
388 WFS_CallServerPacketSendHook(context, (WFSPacketBuffer *)argument);
389 break;
390
391 case WIRELESS_EVENT_PACKET_RECV:
392 WFS_CallServerPacketRecvHook(context, (const WFSPacketBuffer *)argument);
393 break;
394
395 default:
396 break;
397 }
398 }
399
400 /*---------------------------------------------------------------------------*
401 Name: ChildWFSEvent
402
403 Description: WFS client event notification.
404
405 Arguments: userdata: User-defined argument
406 event: Event type
407 argument: Arguments unique to event
408
409 Returns: None.
410 *---------------------------------------------------------------------------*/
ChildWFSEvent(void * userdata,WFSEventType event,void * argument)411 static void ChildWFSEvent(void *userdata, WFSEventType event, void *argument)
412 {
413 switch (event)
414 {
415 case WFS_EVENT_CLIENT_READY:
416 /* Completion of ROM file table recepetion */
417 {
418 /* Replace the current "rom" archive with WFS */
419 WFSClientContext * const context = (WFSClientContext*)userdata;
420 WFS_ReplaceRomArchive(context);
421 /* Notify the application that WFS has become available for use */
422 static_work->state = WFS_STATE_READY;
423 if (static_work->state_func)
424 {
425 (*static_work->state_func) (NULL);
426 }
427 }
428 break;
429 default:
430 break;
431 }
432 (void)argument;
433 }
434
435 /*---------------------------------------------------------------------------*
436 Name: ChildWirelessEvent
437
438 Description: Event notification from the wireless driver.
439
440 Arguments: userdata: User-defined argument
441 event: Event type
442 argument: Arguments unique to event
443
444 Returns: None.
445 *---------------------------------------------------------------------------*/
ChildWirelessEvent(void * userdata,WirelessEvent event,void * argument)446 static void ChildWirelessEvent(void *userdata, WirelessEvent event, void *argument)
447 {
448 WFSClientContext * const context = (WFSClientContext *)userdata;
449 switch (event)
450 {
451 case WIRELESS_EVENT_END:
452 WFS_EndClient(context);
453 break;
454
455 case WIRELESS_EVENT_LINKUP:
456 WFS_StartClient(context, (const WFSPeerInfo*)argument);
457 break;
458
459 case WIRELESS_EVENT_CONNECTED:
460 WFS_CallClientConnectHook(context, (const WFSPeerInfo*)argument);
461 break;
462
463 case WIRELESS_EVENT_DISCONNECTED:
464 WFS_CallClientDisconnectHook(context, (const WFSPeerInfo*)argument);
465 break;
466
467 case WIRELESS_EVENT_PACKET_SEND:
468 WFS_CallClientPacketSendHook(context, (WFSPacketBuffer*)argument);
469 break;
470
471 case WIRELESS_EVENT_PACKET_RECV:
472 WFS_CallClientPacketRecvHook(context, (const WFSPacketBuffer*)argument);
473 break;
474 }
475 }
476
477 /*---------------------------------------------------------------------------*
478 Name: WFS_InitParent
479
480 Description: Initializes Wireless File System parent parameters.
481
482 Arguments: port Available WM port for WFS
483 callback: Callback of various state-notifications
484 allocator Dynamic memory allocator for WFS
485 allocator_arg Argument of 'allocator'
486 parent_packet Available WM packet for WFS
487 p_rom: Target file that directs SRL-program
488 to export FAT/FNT and OVT.
489 If specified NULL, use own.
490 use_parent_fs: If TRUE, ignore p_rom's FAT/FNT and use own.
491 This setting enables both independent
492 program to share FAT/FNT (except OVT).
493 If p_rom is NULL, always as TRUE.
494
495 Returns: None.
496 *---------------------------------------------------------------------------*/
WFS_InitParent(int port,WFSStateCallback callback,WFSAllocator allocator,void * allocator_arg,int parent_packet,FSFile * p_rom,BOOL use_parent_fs)497 void WFS_InitParent(int port, WFSStateCallback callback,
498 WFSAllocator allocator, void *allocator_arg, int parent_packet,
499 FSFile *p_rom, BOOL use_parent_fs)
500 {
501 /* Common initialization */
502 WFSi_InitCommon(callback, allocator, allocator_arg, port,
503 sizeof(WFSServerContext), ParentWirelessEvent);
504 /* WFS server initialization */
505 {
506 WFSServerContext *server = (WFSServerContext*)static_work->context;
507 static_work->server = server;
508 WFS_InitServer(server, server, ParentWFSEvent, static_work->allocator, parent_packet);
509 if (!WFS_ExecuteRomServerThread(server, p_rom, use_parent_fs))
510 {
511 OS_TPanic("WFS_ExecuteRomServerThread() failed! (specified SRL file seems to be wrong)");
512 }
513 }
514 static_work->state = WFS_STATE_IDLE;
515 static_work->initialized = TRUE;
516 /* Start sending packets if already in the communication-enabled state during initialization */
517 WFSi_NotifyLinkup(static_work);
518 }
519
520 /*---------------------------------------------------------------------------*
521 Name: WFS_InitChild
522
523 Description: Initialization of a child device to use WFS.
524
525 Arguments: port: WM port number assigned for WFS
526 callback: Status notification callback
527 allocator: Allocator for WFS
528 allocator_arg: Allocator arguments
529
530 Returns: None.
531 *---------------------------------------------------------------------------*/
WFS_InitChild(int port,WFSStateCallback callback,WFSAllocator allocator,void * allocator_arg)532 void WFS_InitChild(int port, WFSStateCallback callback, WFSAllocator allocator, void *allocator_arg)
533 {
534 /* Common initialization */
535 WFSi_InitCommon(callback, allocator, allocator_arg, port,
536 sizeof(WFSClientContext), ChildWirelessEvent);
537 /* WFS client initialization */
538 {
539 WFSClientContext *client = (WFSClientContext*)static_work->context;
540 static_work->client = client;
541 WFS_InitClient(client, client, ChildWFSEvent, static_work->allocator);
542 }
543 static_work->state = WFS_STATE_IDLE;
544 static_work->initialized = TRUE;
545 /* Start sending packets if already in the communication-enabled state during initialization */
546 WFSi_NotifyLinkup(static_work);
547 }
548
549 /*---------------------------------------------------------------------------*
550 Name: WFS_Start
551
552 Description: Notify that WFS is able to use MP communication.
553
554 Arguments: None.
555
556 Returns: None.
557 *---------------------------------------------------------------------------*/
WFS_Start(void)558 void WFS_Start(void)
559 {
560 StaticWork *work = static_work;
561 OSIntrMode bak_cpsr = OS_DisableInterrupts();
562 if (work->available && !work->mp_availale)
563 {
564 /* Set the port callback for WM */
565 int result;
566 result = WM_SetPortCallback((u16)work->port, WFSi_PortCallback, work);
567 if (result != WM_ERRCODE_SUCCESS)
568 {
569 OS_TPanic("WM_SetPortCallback failed! (result=%d)", result);
570 }
571 /* Get the WM internal state */
572 result = WM_ReadStatus(work->status_buf);
573 if (result != WM_ERRCODE_SUCCESS)
574 {
575 OS_TPanic("WM_ReadStatus failed! (result=%d)", result);
576 }
577 work->mp_availale = TRUE;
578 WFSi_NotifyLinkup(work);
579 WFSi_NotifySend(work);
580 }
581 (void)OS_RestoreInterrupts(bak_cpsr);
582 }
583
584 /*---------------------------------------------------------------------------*
585 Name: WFS_End
586
587 Description: End WFS.
588
589 Arguments: None.
590
591 Returns: None.
592 *---------------------------------------------------------------------------*/
WFS_End(void)593 void WFS_End(void)
594 {
595 OSIntrMode bak_cpsr = OS_DisableInterrupts();
596 if (static_work->available)
597 {
598 StaticWork *const work = static_work;
599 work->state = WFS_STATE_STOP;
600 work->state_func = NULL;
601 work->available = FALSE;
602 /* Release the WM port callback */
603 if (work->mp_availale)
604 {
605 (void)WM_SetPortCallback((u16)work->port, NULL, NULL);
606 work->mp_availale = FALSE;
607 work->status_buf->aid = 0;
608 }
609 /* Separate parent/child shutdown processing */
610 if (work->initialized)
611 {
612 NotifyWirelessEvent(work, WIRELESS_EVENT_END, NULL);
613 static_work->server = NULL;
614 static_work->client = NULL;
615 work->initialized = FALSE;
616 }
617 /* Release the allocated dynamic memory */
618 MI_CallFree(work->allocator, work->context);
619 }
620 (void)OS_RestoreInterrupts(bak_cpsr);
621 }
622
623 /*---------------------------------------------------------------------------*
624 Name: WFS_GetStatus
625
626 Description: Gets the current WFS status.
627
628 Arguments: None.
629
630 Returns: The current WFS status.
631 *---------------------------------------------------------------------------*/
WFS_GetStatus(void)632 WFSState WFS_GetStatus(void)
633 {
634 return static_work->state;
635 }
636
637 /*---------------------------------------------------------------------------*
638 Name: WFS_SetDebugMode
639
640 Description: Enables/Disables WFS internal debug output.
641
642 Arguments: enable: TRUE if enabling debug output
643
644 Returns: None.
645 *---------------------------------------------------------------------------*/
WFS_SetDebugMode(BOOL enable)646 void WFS_SetDebugMode(BOOL enable)
647 {
648 static_work->debug_enable = enable;
649 }
650
651 /*---------------------------------------------------------------------------*
652 Name: WFS_GetCurrentBitmap
653
654 Description: Gets the current child device group bitmap that WBT is aware of.
655 This function can only be called by the parent.
656
657 Arguments: None.
658
659 Returns: Currently recognized child devices.
660 *---------------------------------------------------------------------------*/
WFS_GetCurrentBitmap(void)661 int WFS_GetCurrentBitmap(void)
662 {
663 return static_work->server ? WFS_GetServerConnectedBitmap(static_work->server) : 0;
664 }
665
666 /*---------------------------------------------------------------------------*
667 Name: WFS_GetSyncBitmap
668
669 Description: Gets bitmap of child group with access sync specified.
670 This function can only be called by the parent.
671
672 Arguments: None.
673
674 Returns: Child devices that are specified to synchronize access
675 *---------------------------------------------------------------------------*/
WFS_GetSyncBitmap(void)676 int WFS_GetSyncBitmap(void)
677 {
678 return static_work->server ? WFS_GetServerSyncBitmap(static_work->server) : 0;
679 }
680
681 /*---------------------------------------------------------------------------*
682 Name: WFS_GetBusyBitmap
683
684 Description: Gets bitmap of child devices that are currently accessing parent.
685 This function can only be called by the parent.
686
687 Arguments: None.
688
689 Returns: Child devices that are currently accessing parent.
690 *---------------------------------------------------------------------------*/
WFS_GetBusyBitmap(void)691 int WFS_GetBusyBitmap(void)
692 {
693 return static_work->server ? WFS_GetServerBusyBitmap(static_work->server) : 0;
694 }
695
696 /*---------------------------------------------------------------------------*
697 Name: WFS_IsBusy
698
699 Description: Determines whether or not the child device of a designated aid is being accessed.
700 This function can only be called by the parent.
701
702 Arguments: aid: AID of child to check
703
704 Returns: If the designated child device is being accessed, TRUE. Otherwise, FALSE.
705 *---------------------------------------------------------------------------*/
WFS_IsBusy(int aid)706 BOOL WFS_IsBusy(int aid)
707 {
708 return ((1 << aid) & WFS_GetBusyBitmap()) != 0;
709 }
710
711 /*---------------------------------------------------------------------------*
712 Name: WFS_GetPacketSize
713
714 Description: Gets MP communication packet size of parent set in WFS.
715
716 Arguments: None.
717
718 Returns: MP communication packet size of parent set in WFS.
719 *---------------------------------------------------------------------------*/
WFS_GetPacketSize(void)720 int WFS_GetPacketSize(void)
721 {
722 return static_work->server ? WFS_GetServerPacketLength(static_work->server) : 0;
723 }
724
725 /*---------------------------------------------------------------------------*
726 Name: WFS_SetPacketSize
727
728 Description: Sets the packet size to send from the parent.
729 This function can only be called before calling WFS_Start() or after all child devices have properly finished connecting.
730
731
732 This function is not guaranteed to work if called at any other time.
733 This function can only be called by the parent.
734
735 Arguments: size: The specified packet size
736
737 Returns: None.
738 *---------------------------------------------------------------------------*/
WFS_SetPacketSize(int size)739 void WFS_SetPacketSize(int size)
740 {
741 if(static_work->server)
742 {
743 WFS_SetServerPacketLength(static_work->server, size);
744 }
745 }
746
747 /*---------------------------------------------------------------------------*
748 Name: WFS_EnableSync
749
750 Description: Configures the settings of the child device group that takes access synchronization on the parent device side.
751 This function achieves efficient transmission rates that utilities unique characteristics of the WBT library; this is done by synchronizing responses to child devices that are all guaranteed to access the same files in precisely the same order.
752
753
754 However, be cautious of the fact that if the synchronization start timing is not logically safe, responses to child devices will become out-of-sync, causing deadlocks to occur.
755
756 This function can only be called by the parent.
757
758 Arguments: sync_bitmap: The AID bitmap of the child device group that takes the access synchronization.
759 The lowest bit 1 indicating the parent device itself is ignored.
760 By assigning 0 for this value, synchronicity does not occur.
761 This is the default state.
762
763 Returns: None.
764 *---------------------------------------------------------------------------*/
WFS_EnableSync(int sync_bitmap)765 void WFS_EnableSync(int sync_bitmap)
766 {
767 if(static_work->server)
768 {
769 WFS_SetServerSync(static_work->server, sync_bitmap);
770 }
771 }
772
773 /*---------------------------------------------------------------------------*
774 Name: WFS_GetCurrentDownloadProgress
775
776 Description: Gets the progress status of the file on which ReadFile is currently being executed.
777
778 Arguments: current: The number of packets that have been received
779 total: The total number of packets expected to receive
780
781 Returns: TRUE if ReadFile is currently executing.
782 *---------------------------------------------------------------------------*/
WFS_GetCurrentDownloadProgress(int * current,int * total)783 BOOL WFS_GetCurrentDownloadProgress(int *current, int *total)
784 {
785 return static_work->client && (WFS_GetClientReadProgress(static_work->client, current, total), TRUE);
786 }
787