Skip to content

Commit db57ff9

Browse files
committed
Merge branch 'ofw_dev' into dev
2 parents 2d860b4 + 8c4716f commit db57ff9

File tree

13 files changed

+360
-169
lines changed

13 files changed

+360
-169
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include "nfc_supported_cards.h"
2+
23
#include "../plugins/supported_cards/nfc_supported_card_plugin.h"
34

45
#include <flipper_application/flipper_application.h>
@@ -7,22 +8,72 @@
78

89
#include <furi.h>
910
#include <path.h>
11+
#include <m-array.h>
1012

1113
#define TAG "NfcSupportedCards"
1214

1315
#define NFC_SUPPORTED_CARDS_PLUGINS_PATH APP_DATA_PATH("plugins")
1416
#define NFC_SUPPORTED_CARDS_PLUGIN_SUFFIX "_parser.fal"
1517

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+
1639
typedef struct {
1740
Storage* storage;
1841
File* directory;
1942
FuriString* file_path;
2043
char file_name[256];
2144
FlipperApplication* app;
22-
} NfcSupportedCards;
45+
} NfcSupportedCardsLoadContext;
2346

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() {
2554
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));
2677

2778
instance->storage = furi_record_open(RECORD_STORAGE);
2879
instance->directory = storage_file_alloc(instance->storage);
@@ -35,7 +86,7 @@ static NfcSupportedCards* nfc_supported_cards_alloc() {
3586
return instance;
3687
}
3788

38-
static void nfc_supported_cards_free(NfcSupportedCards* instance) {
89+
static void nfc_supported_cards_load_context_free(NfcSupportedCardsLoadContext* instance) {
3990
if(instance->app) {
4091
flipper_application_free(instance->app);
4192
}
@@ -50,7 +101,36 @@ static void nfc_supported_cards_free(NfcSupportedCards* instance) {
50101
}
51102

52103
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) {
54134
const NfcSupportedCardsPlugin* plugin = NULL;
55135

56136
do {
@@ -65,83 +145,137 @@ static const NfcSupportedCardsPlugin*
65145

66146
path_concat(NFC_SUPPORTED_CARDS_PLUGINS_PATH, instance->file_name, instance->file_path);
67147

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
70150

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+
}
75153

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);
78156

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;
81161

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+
}
83183

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);
86185

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+
}
89194

90-
return plugin;
195+
} while(false);
91196
}
92197

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);
94200
furi_assert(device);
95201
furi_assert(nfc);
96202

97203
bool card_read = false;
98-
99-
NfcSupportedCards* supported_cards = nfc_supported_cards_alloc();
204+
NfcProtocol protocol = nfc_device_get_protocol(device);
100205

101206
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+
}
115233
}
116234

117-
} while(!card_read);
235+
nfc_supported_cards_load_context_free(instance->load_context);
236+
} while(false);
118237

119-
nfc_supported_cards_free(supported_cards);
120238
return card_read;
121239
}
122240

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);
124246
furi_assert(device);
125247
furi_assert(parsed_data);
126248

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);
130251

131252
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+
}
141275
}
142276

143-
} while(!parsed);
277+
nfc_supported_cards_load_context_free(instance->load_context);
278+
} while(false);
144279

145-
nfc_supported_cards_free(supported_cards);
146-
return parsed;
280+
return card_parsed;
147281
}

applications/main/nfc/helpers/nfc_supported_cards.h

+35-2
Original file line numberDiff line numberDiff line change
@@ -15,20 +15,49 @@
1515
extern "C" {
1616
#endif
1717

18+
/**
19+
* @brief NfcSupportedCards opaque type definition.
20+
*/
21+
typedef struct NfcSupportedCards NfcSupportedCards;
22+
23+
/**
24+
* @brief Allocate NfcSupportedCards instance.
25+
*
26+
* @return pointer to allocated NfcSupportedCards instance.
27+
*/
28+
NfcSupportedCards* nfc_supported_cards_alloc();
29+
30+
/**
31+
* @brief Delete an NfcSupportedCards instance
32+
*
33+
* @param[in] instance pointer to instance to be deleted.
34+
*/
35+
void nfc_supported_cards_free(NfcSupportedCards* instance);
36+
37+
/**
38+
* @brief Load plugins information to cache.
39+
*
40+
* @note This function must be called before calling read and parse fanctions.
41+
*
42+
* @param[in, out] instance pointer to NfcSupportedCards instance.
43+
*/
44+
void nfc_supported_cards_load_cache(NfcSupportedCards* instance);
45+
1846
/**
1947
* @brief Read the card using a custom procedure.
2048
*
2149
* This function will load all suitable supported card plugins one by one and
2250
* try to execute the custom read procedure specified in each. Upon first success,
2351
* no further attempts will be made and the function will return.
2452
*
53+
* @param[in, out] instance pointer to NfcSupportedCards instance.
2554
* @param[in,out] device pointer to a device instance to hold the read data.
2655
* @param[in,out] nfc pointer to an Nfc instance.
2756
* @returns true if the card was successfully read, false otherwise.
2857
*
2958
* @see NfcSupportedCardPluginRead for detailed description.
3059
*/
31-
bool nfc_supported_cards_read(NfcDevice* device, Nfc* nfc);
60+
bool nfc_supported_cards_read(NfcSupportedCards* instance, NfcDevice* device, Nfc* nfc);
3261

3362
/**
3463
* @brief Parse raw data into human-readable representation.
@@ -37,13 +66,17 @@ bool nfc_supported_cards_read(NfcDevice* device, Nfc* nfc);
3766
* try to parse the data according to each implementation. Upon first success,
3867
* no further attempts will be made and the function will return.
3968
*
69+
* @param[in, out] instance pointer to NfcSupportedCards instance.
4070
* @param[in] device pointer to a device instance holding the data is to be parsed.
4171
* @param[out] parsed_data pointer to the string to contain the formatted result.
4272
* @returns true if the card was successfully parsed, false otherwise.
4373
*
4474
* @see NfcSupportedCardPluginParse for detailed description.
4575
*/
46-
bool nfc_supported_cards_parse(const NfcDevice* device, FuriString* parsed_data);
76+
bool nfc_supported_cards_parse(
77+
NfcSupportedCards* instance,
78+
NfcDevice* device,
79+
FuriString* parsed_data);
4780

4881
#ifdef __cplusplus
4982
}

0 commit comments

Comments
 (0)