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