1 /*---------------------------------------------------------------------------*
2   Project:  TwlSDK - FS - libraries
3   File:     fs_hook.c
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-17#$
14   $Rev: 8556 $
15   $Author: okubata_ryoma $
16 
17  *---------------------------------------------------------------------------*/
18 
19 #include <nitro/fs/archive.h>
20 #include <nitro/fs/hook.h>
21 #include <nitro/card/common.h>
22 #include <nitro/std/string.h>
23 #ifdef SDK_TWL
24 #include <twl/fatfs/common/types.h>
25 #endif // SDK_TWL
26 
27 /*---------------------------------------------------------------------------*/
28 /* Variables */
29 
30 // Event hook management information
31 typedef struct FSEventHookContext
32 {
33     FSEventHook     *chain;
34     CARDHookContext  hook[1];
35 }
36 FSEventHookContext;
37 
38 static FSEventHookContext FSiEventHookStaticWork[1];
39 
40 
41 /*---------------------------------------------------------------------------*/
42 /* functions */
43 
44 /*---------------------------------------------------------------------------*
45   Name:         FSi_SystemEvents
46 
47   Description:  System event monitoring callback
48 
49   Arguments:    userdata         Any user-defined data
50                 event       Occurred event
51                 argument        Argument for each event
52 
53   Returns:      None.
54  *---------------------------------------------------------------------------*/
FSi_SystemEvents(void * userdata,CARDEvent event,void * argument)55 static void FSi_SystemEvents(void *userdata, CARDEvent event, void *argument)
56 {
57     FSEventHookContext *context = (FSEventHookContext*)userdata;
58     FSArchive  *target = NULL;
59     FSEvent     fsevent = FS_EVENT_NONE;
60     (void)argument;
61     // Convert entire media event of the system to each archive event.
62     if (event == CARD_EVENT_SLOTRESET)
63     {
64         target = FS_FindArchive("rom", 3);
65         fsevent = FS_EVENT_MEDIA_INSERTED;
66     }
67     else if (event == CARD_EVENT_PULLEDOUT)
68     {
69         target = FS_FindArchive("rom", 3);
70         fsevent = FS_EVENT_MEDIA_REMOVED;
71     }
72 #ifdef SDK_TWL
73     else if (event == FATFS_EVENT_SD_INSERTED)
74     {
75         target = FS_FindArchive("sdmc", 4);
76         fsevent = FS_EVENT_MEDIA_INSERTED;
77     }
78     else if (event == FATFS_EVENT_SD_REMOVED)
79     {
80         target = FS_FindArchive("sdmc", 4);
81         fsevent = FS_EVENT_MEDIA_REMOVED;
82     }
83 #endif // SDK_TWL
84     if (fsevent != FS_EVENT_NONE)
85     {
86         FSEventHook   **pp = &context->chain;
87         while (*pp != NULL)
88         {
89             FSEventHook    *hook = *pp;
90             if ((hook->arc == target) && (hook->callback != NULL))
91             {
92                 (*hook->callback)(hook->userdata, fsevent, argument);
93             }
94             if (*pp == hook)
95             {
96                 pp = &(*pp)->next;
97             }
98         }
99     }
100 }
101 
102 /*---------------------------------------------------------------------------*
103   Name:         FS_RegisterEventHook
104 
105   Description:  Registers the hook for events in the archive
106 
107   Arguments:    arcname          Archive of the register target �o�^�Ώۂ̃A�[�J�C�u
108                 hook             FSEventHook structure to register
109                 callback         Callback function when an event occurs
110                 userdata         Arbitrary user defined data (if not necessary, NULL)
111 
112   Returns:      None.
113  *---------------------------------------------------------------------------*/
FS_RegisterEventHook(const char * arcname,FSEventHook * hook,FSEventFunction callback,void * userdata)114 void FS_RegisterEventHook(const char *arcname, FSEventHook *hook, FSEventFunction callback, void *userdata)
115 {
116     FSEventHookContext *context = FSiEventHookStaticWork;
117     OSIntrMode  bak = OS_DisableInterrupts();
118     FSArchive  *arc = FS_FindArchive(arcname, STD_GetStringLength(arcname));
119     if (arc)
120     {
121         // If not explicitly used, consider so that the hook feature is not linked
122         if (!context->hook->callback)
123         {
124             CARDi_RegisterHook(context->hook, FSi_SystemEvents, context);
125         }
126         hook->callback = callback;
127         hook->userdata = userdata;
128         hook->arc = arc;
129         hook->next = context->chain;
130         context->chain = hook;
131     }
132     (void)OS_RestoreInterrupts(bak);
133 }
134 
135 /*---------------------------------------------------------------------------*
136   Name:         FS_UnregisterEventHook
137 
138   Description:  Releases the hook for events in the registered archive.
139 
140   Arguments:    hook           Registered FSEventHook structure
141 
142   Returns:      None.
143  *---------------------------------------------------------------------------*/
FS_UnregisterEventHook(FSEventHook * hook)144 void FS_UnregisterEventHook(FSEventHook *hook)
145 {
146     FSEventHookContext *context = FSiEventHookStaticWork;
147     OSIntrMode      bak = OS_DisableInterrupts();
148     FSEventHook   **pp;
149     for (pp = &context->chain; *pp; pp = &(*pp)->next)
150     {
151         if (*pp == hook)
152         {
153             *pp = (*pp)->next;
154             break;
155         }
156     }
157     (void)OS_RestoreInterrupts(bak);
158 }
159