1
1
#include "nfc_supported_cards.h"
2
+
2
3
#include "../plugins/supported_cards/nfc_supported_card_plugin.h"
3
4
4
5
#include <flipper_application/flipper_application.h>
7
8
8
9
#include <furi.h>
9
10
#include <path.h>
11
+ #include <m-array.h>
10
12
11
13
#define TAG "NfcSupportedCards"
12
14
13
15
#define NFC_SUPPORTED_CARDS_PLUGINS_PATH APP_DATA_PATH("plugins")
14
16
#define NFC_SUPPORTED_CARDS_PLUGIN_SUFFIX "_parser.fal"
15
17
18
+ typedef enum {
19
+ NfcSupportedCardsPluginFeatureHasVerify = (1U << 0 ),
20
+ NfcSupportedCardsPluginFeatureHasRead = (1U << 1 ),
21
+ NfcSupportedCardsPluginFeatureHasParse = (1U << 2 ),
22
+ } NfcSupportedCardsPluginFeature ;
23
+
24
+ typedef struct {
25
+ FuriString * path ;
26
+ NfcProtocol protocol ;
27
+ NfcSupportedCardsPluginFeature feature ;
28
+ } NfcSupportedCardsPluginCache ;
29
+
30
+ ARRAY_DEF (NfcSupportedCardsPluginCache , NfcSupportedCardsPluginCache , M_POD_OPLIST );
31
+
32
+ typedef enum {
33
+ NfcSupportedCardsLoadStateIdle ,
34
+ NfcSupportedCardsLoadStateInProgress ,
35
+ NfcSupportedCardsLoadStateSuccess ,
36
+ NfcSupportedCardsLoadStateFail ,
37
+ } NfcSupportedCardsLoadState ;
38
+
16
39
typedef struct {
17
40
Storage * storage ;
18
41
File * directory ;
19
42
FuriString * file_path ;
20
43
char file_name [256 ];
21
44
FlipperApplication * app ;
22
- } NfcSupportedCards ;
45
+ } NfcSupportedCardsLoadContext ;
23
46
24
- static NfcSupportedCards * nfc_supported_cards_alloc () {
47
+ struct NfcSupportedCards {
48
+ NfcSupportedCardsPluginCache_t plugins_cache_arr ;
49
+ NfcSupportedCardsLoadState load_state ;
50
+ NfcSupportedCardsLoadContext * load_context ;
51
+ };
52
+
53
+ NfcSupportedCards * nfc_supported_cards_alloc () {
25
54
NfcSupportedCards * instance = malloc (sizeof (NfcSupportedCards ));
55
+ NfcSupportedCardsPluginCache_init (instance -> plugins_cache_arr );
56
+
57
+ return instance ;
58
+ }
59
+
60
+ void nfc_supported_cards_free (NfcSupportedCards * instance ) {
61
+ furi_assert (instance );
62
+
63
+ NfcSupportedCardsPluginCache_it_t iter ;
64
+ for (NfcSupportedCardsPluginCache_it (iter , instance -> plugins_cache_arr );
65
+ !NfcSupportedCardsPluginCache_end_p (iter );
66
+ NfcSupportedCardsPluginCache_next (iter )) {
67
+ NfcSupportedCardsPluginCache * plugin_cache = NfcSupportedCardsPluginCache_ref (iter );
68
+ furi_string_free (plugin_cache -> path );
69
+ }
70
+
71
+ NfcSupportedCardsPluginCache_clear (instance -> plugins_cache_arr );
72
+ free (instance );
73
+ }
74
+
75
+ static NfcSupportedCardsLoadContext * nfc_supported_cards_load_context_alloc () {
76
+ NfcSupportedCardsLoadContext * instance = malloc (sizeof (NfcSupportedCardsLoadContext ));
26
77
27
78
instance -> storage = furi_record_open (RECORD_STORAGE );
28
79
instance -> directory = storage_file_alloc (instance -> storage );
@@ -35,7 +86,7 @@ static NfcSupportedCards* nfc_supported_cards_alloc() {
35
86
return instance ;
36
87
}
37
88
38
- static void nfc_supported_cards_free ( NfcSupportedCards * instance ) {
89
+ static void nfc_supported_cards_load_context_free ( NfcSupportedCardsLoadContext * instance ) {
39
90
if (instance -> app ) {
40
91
flipper_application_free (instance -> app );
41
92
}
@@ -50,7 +101,36 @@ static void nfc_supported_cards_free(NfcSupportedCards* instance) {
50
101
}
51
102
52
103
static const NfcSupportedCardsPlugin *
53
- nfc_supported_cards_get_next_plugin (NfcSupportedCards * instance ) {
104
+ nfc_supported_cards_get_plugin (NfcSupportedCardsLoadContext * instance , FuriString * path ) {
105
+ furi_assert (instance );
106
+ furi_assert (path );
107
+
108
+ const NfcSupportedCardsPlugin * plugin = NULL ;
109
+ do {
110
+ if (instance -> app ) flipper_application_free (instance -> app );
111
+ instance -> app = flipper_application_alloc (instance -> storage , firmware_api_interface );
112
+ if (flipper_application_preload (instance -> app , furi_string_get_cstr (path )) !=
113
+ FlipperApplicationPreloadStatusSuccess )
114
+ break ;
115
+ if (!flipper_application_is_plugin (instance -> app )) break ;
116
+ if (flipper_application_map_to_memory (instance -> app ) != FlipperApplicationLoadStatusSuccess )
117
+ break ;
118
+ const FlipperAppPluginDescriptor * descriptor =
119
+ flipper_application_plugin_get_descriptor (instance -> app );
120
+
121
+ if (descriptor == NULL ) break ;
122
+
123
+ if (strcmp (descriptor -> appid , NFC_SUPPORTED_CARD_PLUGIN_APP_ID ) != 0 ) break ;
124
+ if (descriptor -> ep_api_version != NFC_SUPPORTED_CARD_PLUGIN_API_VERSION ) break ;
125
+
126
+ plugin = descriptor -> entry_point ;
127
+ } while (false);
128
+
129
+ return plugin ;
130
+ }
131
+
132
+ static const NfcSupportedCardsPlugin *
133
+ nfc_supported_cards_get_next_plugin (NfcSupportedCardsLoadContext * instance ) {
54
134
const NfcSupportedCardsPlugin * plugin = NULL ;
55
135
56
136
do {
@@ -65,83 +145,137 @@ static const NfcSupportedCardsPlugin*
65
145
66
146
path_concat (NFC_SUPPORTED_CARDS_PLUGINS_PATH , instance -> file_name , instance -> file_path );
67
147
68
- if (instance -> app ) flipper_application_free ( instance -> app );
69
- instance -> app = flipper_application_alloc ( instance -> storage , firmware_api_interface );
148
+ plugin = nfc_supported_cards_get_plugin (instance , instance -> file_path );
149
+ } while ( plugin == NULL ); //-V654
70
150
71
- if (flipper_application_preload (instance -> app , furi_string_get_cstr (instance -> file_path )) !=
72
- FlipperApplicationPreloadStatusSuccess )
73
- continue ;
74
- if (!flipper_application_is_plugin (instance -> app )) continue ;
151
+ return plugin ;
152
+ }
75
153
76
- if ( flipper_application_map_to_memory ( instance -> app ) != FlipperApplicationLoadStatusSuccess )
77
- continue ;
154
+ void nfc_supported_cards_load_cache ( NfcSupportedCards * instance ) {
155
+ furi_assert ( instance ) ;
78
156
79
- const FlipperAppPluginDescriptor * descriptor =
80
- flipper_application_plugin_get_descriptor (instance -> app );
157
+ do {
158
+ if ((instance -> load_state == NfcSupportedCardsLoadStateSuccess ) ||
159
+ (instance -> load_state == NfcSupportedCardsLoadStateFail ))
160
+ break ;
81
161
82
- if (descriptor == NULL ) continue ;
162
+ instance -> load_context = nfc_supported_cards_load_context_alloc ();
163
+
164
+ while (true) {
165
+ const NfcSupportedCardsPlugin * plugin =
166
+ nfc_supported_cards_get_next_plugin (instance -> load_context );
167
+ if (plugin == NULL ) break ; //-V547
168
+
169
+ NfcSupportedCardsPluginCache plugin_cache = {}; //-V779
170
+ plugin_cache .path = furi_string_alloc_set (instance -> load_context -> file_path );
171
+ plugin_cache .protocol = plugin -> protocol ;
172
+ if (plugin -> verify ) {
173
+ plugin_cache .feature |= NfcSupportedCardsPluginFeatureHasVerify ;
174
+ }
175
+ if (plugin -> read ) {
176
+ plugin_cache .feature |= NfcSupportedCardsPluginFeatureHasRead ;
177
+ }
178
+ if (plugin -> parse ) {
179
+ plugin_cache .feature |= NfcSupportedCardsPluginFeatureHasParse ;
180
+ }
181
+ NfcSupportedCardsPluginCache_push_back (instance -> plugins_cache_arr , plugin_cache );
182
+ }
83
183
84
- if (strcmp (descriptor -> appid , NFC_SUPPORTED_CARD_PLUGIN_APP_ID ) != 0 ) continue ;
85
- if (descriptor -> ep_api_version != NFC_SUPPORTED_CARD_PLUGIN_API_VERSION ) continue ;
184
+ nfc_supported_cards_load_context_free (instance -> load_context );
86
185
87
- plugin = descriptor -> entry_point ;
88
- } while (plugin == NULL ); //-V654
186
+ size_t plugins_loaded = NfcSupportedCardsPluginCache_size (instance -> plugins_cache_arr );
187
+ if (plugins_loaded == 0 ) {
188
+ FURI_LOG_D (TAG , "Plugins not found" );
189
+ instance -> load_state = NfcSupportedCardsLoadStateFail ;
190
+ } else {
191
+ FURI_LOG_D (TAG , "Loaded %zu plugins" , plugins_loaded );
192
+ instance -> load_state = NfcSupportedCardsLoadStateSuccess ;
193
+ }
89
194
90
- return plugin ;
195
+ } while (false) ;
91
196
}
92
197
93
- bool nfc_supported_cards_read (NfcDevice * device , Nfc * nfc ) {
198
+ bool nfc_supported_cards_read (NfcSupportedCards * instance , NfcDevice * device , Nfc * nfc ) {
199
+ furi_assert (instance );
94
200
furi_assert (device );
95
201
furi_assert (nfc );
96
202
97
203
bool card_read = false;
98
-
99
- NfcSupportedCards * supported_cards = nfc_supported_cards_alloc ();
204
+ NfcProtocol protocol = nfc_device_get_protocol (device );
100
205
101
206
do {
102
- const NfcSupportedCardsPlugin * plugin =
103
- nfc_supported_cards_get_next_plugin (supported_cards );
104
- if (plugin == NULL ) break ; //-V547
105
-
106
- const NfcProtocol protocol = nfc_device_get_protocol (device ); //-V779
107
- if (plugin -> protocol != protocol ) continue ;
108
-
109
- if (plugin -> verify ) {
110
- if (!plugin -> verify (nfc )) continue ;
111
- }
112
-
113
- if (plugin -> read ) {
114
- card_read = plugin -> read (nfc , device );
207
+ if (instance -> load_state != NfcSupportedCardsLoadStateSuccess ) break ;
208
+
209
+ instance -> load_context = nfc_supported_cards_load_context_alloc ();
210
+
211
+ NfcSupportedCardsPluginCache_it_t iter ;
212
+ for (NfcSupportedCardsPluginCache_it (iter , instance -> plugins_cache_arr );
213
+ !NfcSupportedCardsPluginCache_end_p (iter );
214
+ NfcSupportedCardsPluginCache_next (iter )) {
215
+ NfcSupportedCardsPluginCache * plugin_cache = NfcSupportedCardsPluginCache_ref (iter );
216
+ if (plugin_cache -> protocol != protocol ) continue ;
217
+ if ((plugin_cache -> feature & NfcSupportedCardsPluginFeatureHasRead ) == 0 ) continue ;
218
+
219
+ const NfcSupportedCardsPlugin * plugin =
220
+ nfc_supported_cards_get_plugin (instance -> load_context , plugin_cache -> path );
221
+ if (plugin == NULL ) continue ;
222
+
223
+ if (plugin -> verify ) {
224
+ if (!plugin -> verify (nfc )) continue ;
225
+ }
226
+
227
+ if (plugin -> read ) {
228
+ if (plugin -> read (nfc , device )) {
229
+ card_read = true;
230
+ break ;
231
+ }
232
+ }
115
233
}
116
234
117
- } while (!card_read );
235
+ nfc_supported_cards_load_context_free (instance -> load_context );
236
+ } while (false);
118
237
119
- nfc_supported_cards_free (supported_cards );
120
238
return card_read ;
121
239
}
122
240
123
- bool nfc_supported_cards_parse (const NfcDevice * device , FuriString * parsed_data ) {
241
+ bool nfc_supported_cards_parse (
242
+ NfcSupportedCards * instance ,
243
+ NfcDevice * device ,
244
+ FuriString * parsed_data ) {
245
+ furi_assert (instance );
124
246
furi_assert (device );
125
247
furi_assert (parsed_data );
126
248
127
- bool parsed = false;
128
-
129
- NfcSupportedCards * supported_cards = nfc_supported_cards_alloc ();
249
+ bool card_parsed = false;
250
+ NfcProtocol protocol = nfc_device_get_protocol (device );
130
251
131
252
do {
132
- const NfcSupportedCardsPlugin * plugin =
133
- nfc_supported_cards_get_next_plugin (supported_cards );
134
- if (plugin == NULL ) break ; //-V547
135
-
136
- const NfcProtocol protocol = nfc_device_get_protocol (device ); //-V779
137
- if (plugin -> protocol != protocol ) continue ;
138
-
139
- if (plugin -> parse ) {
140
- parsed = plugin -> parse (device , parsed_data );
253
+ if (instance -> load_state != NfcSupportedCardsLoadStateSuccess ) break ;
254
+
255
+ instance -> load_context = nfc_supported_cards_load_context_alloc ();
256
+
257
+ NfcSupportedCardsPluginCache_it_t iter ;
258
+ for (NfcSupportedCardsPluginCache_it (iter , instance -> plugins_cache_arr );
259
+ !NfcSupportedCardsPluginCache_end_p (iter );
260
+ NfcSupportedCardsPluginCache_next (iter )) {
261
+ NfcSupportedCardsPluginCache * plugin_cache = NfcSupportedCardsPluginCache_ref (iter );
262
+ if (plugin_cache -> protocol != protocol ) continue ;
263
+ if ((plugin_cache -> feature & NfcSupportedCardsPluginFeatureHasParse ) == 0 ) continue ;
264
+
265
+ const NfcSupportedCardsPlugin * plugin =
266
+ nfc_supported_cards_get_plugin (instance -> load_context , plugin_cache -> path );
267
+ if (plugin == NULL ) continue ;
268
+
269
+ if (plugin -> parse ) {
270
+ if (plugin -> parse (device , parsed_data )) {
271
+ card_parsed = true;
272
+ break ;
273
+ }
274
+ }
141
275
}
142
276
143
- } while (!parsed );
277
+ nfc_supported_cards_load_context_free (instance -> load_context );
278
+ } while (false);
144
279
145
- nfc_supported_cards_free (supported_cards );
146
- return parsed ;
280
+ return card_parsed ;
147
281
}
0 commit comments