Skip to content

Commit 8aae59e

Browse files
authored
Merge branch 'dev' into portasynthinca3/3947-quick-settings
2 parents ab3e63f + 4895ae5 commit 8aae59e

File tree

14 files changed

+250
-37
lines changed

14 files changed

+250
-37
lines changed

applications/debug/unit_tests/tests/furi/furi_event_loop_test.c

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,55 @@ static int32_t test_furi_event_loop_consumer(void* p) {
446446
return 0;
447447
}
448448

449+
typedef struct {
450+
FuriEventLoop* event_loop;
451+
FuriSemaphore* semaphore;
452+
size_t counter;
453+
} SelfUnsubTestTimerContext;
454+
455+
static void test_self_unsub_semaphore_callback(FuriEventLoopObject* object, void* context) {
456+
furi_event_loop_unsubscribe(context, object); // shouldn't crash here
457+
}
458+
459+
static void test_self_unsub_timer_callback(void* arg) {
460+
SelfUnsubTestTimerContext* context = arg;
461+
462+
if(context->counter == 0) {
463+
furi_semaphore_release(context->semaphore);
464+
} else if(context->counter == 1) {
465+
furi_event_loop_stop(context->event_loop);
466+
}
467+
468+
context->counter++;
469+
}
470+
471+
void test_furi_event_loop_self_unsubscribe(void) {
472+
FuriEventLoop* event_loop = furi_event_loop_alloc();
473+
474+
FuriSemaphore* semaphore = furi_semaphore_alloc(1, 0);
475+
furi_event_loop_subscribe_semaphore(
476+
event_loop,
477+
semaphore,
478+
FuriEventLoopEventIn,
479+
test_self_unsub_semaphore_callback,
480+
event_loop);
481+
482+
SelfUnsubTestTimerContext timer_context = {
483+
.event_loop = event_loop,
484+
.semaphore = semaphore,
485+
.counter = 0,
486+
};
487+
FuriEventLoopTimer* timer = furi_event_loop_timer_alloc(
488+
event_loop, test_self_unsub_timer_callback, FuriEventLoopTimerTypePeriodic, &timer_context);
489+
furi_event_loop_timer_start(timer, furi_ms_to_ticks(20));
490+
491+
furi_event_loop_run(event_loop);
492+
493+
furi_event_loop_timer_free(timer);
494+
furi_semaphore_free(semaphore);
495+
furi_event_loop_free(event_loop);
496+
}
497+
449498
void test_furi_event_loop(void) {
450499
TestFuriEventLoopData data = {};
451500

applications/debug/unit_tests/tests/furi/furi_test.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ void test_furi_concurrent_access(void);
88
void test_furi_pubsub(void);
99
void test_furi_memmgr(void);
1010
void test_furi_event_loop(void);
11+
void test_furi_event_loop_self_unsubscribe(void);
1112
void test_errno_saving(void);
1213
void test_furi_primitives(void);
1314
void test_stdin(void);
@@ -46,6 +47,10 @@ MU_TEST(mu_test_furi_event_loop) {
4647
test_furi_event_loop();
4748
}
4849

50+
MU_TEST(mu_test_furi_event_loop_self_unsubscribe) {
51+
test_furi_event_loop_self_unsubscribe();
52+
}
53+
4954
MU_TEST(mu_test_errno_saving) {
5055
test_errno_saving();
5156
}
@@ -68,6 +73,7 @@ MU_TEST_SUITE(test_suite) {
6873
MU_RUN_TEST(mu_test_furi_pubsub);
6974
MU_RUN_TEST(mu_test_furi_memmgr);
7075
MU_RUN_TEST(mu_test_furi_event_loop);
76+
MU_RUN_TEST(mu_test_furi_event_loop_self_unsubscribe);
7177
MU_RUN_TEST(mu_test_stdio);
7278
MU_RUN_TEST(mu_test_errno_saving);
7379
MU_RUN_TEST(mu_test_furi_primitives);

applications/debug/unit_tests/tests/nfc/nfc_test.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ static void mf_ultralight_reader_test(const char* path) {
262262
nfc_listener_start(mfu_listener, NULL, NULL);
263263

264264
MfUltralightData* mfu_data = mf_ultralight_alloc();
265-
MfUltralightError error = mf_ultralight_poller_sync_read_card(poller, mfu_data);
265+
MfUltralightError error = mf_ultralight_poller_sync_read_card(poller, mfu_data, NULL);
266266
mu_assert(error == MfUltralightErrorNone, "mf_ultralight_poller_sync_read_card() failed");
267267

268268
nfc_listener_stop(mfu_listener);
@@ -315,7 +315,7 @@ MU_TEST(ntag_213_locked_reader) {
315315
nfc_listener_start(mfu_listener, NULL, NULL);
316316

317317
MfUltralightData* mfu_data = mf_ultralight_alloc();
318-
MfUltralightError error = mf_ultralight_poller_sync_read_card(poller, mfu_data);
318+
MfUltralightError error = mf_ultralight_poller_sync_read_card(poller, mfu_data, NULL);
319319
mu_assert(error == MfUltralightErrorNone, "mf_ultralight_poller_sync_read_card() failed");
320320

321321
nfc_listener_stop(mfu_listener);
@@ -353,7 +353,7 @@ static void mf_ultralight_write(void) {
353353
MfUltralightData* mfu_data = mf_ultralight_alloc();
354354

355355
// Initial read
356-
MfUltralightError error = mf_ultralight_poller_sync_read_card(poller, mfu_data);
356+
MfUltralightError error = mf_ultralight_poller_sync_read_card(poller, mfu_data, NULL);
357357
mu_assert(error == MfUltralightErrorNone, "mf_ultralight_poller_sync_read_card() failed");
358358

359359
mu_assert(
@@ -371,7 +371,7 @@ static void mf_ultralight_write(void) {
371371
}
372372

373373
// Verification read
374-
error = mf_ultralight_poller_sync_read_card(poller, mfu_data);
374+
error = mf_ultralight_poller_sync_read_card(poller, mfu_data, NULL);
375375
mu_assert(error == MfUltralightErrorNone, "mf_ultralight_poller_sync_read_card() failed");
376376

377377
nfc_listener_stop(mfu_listener);

furi/core/event_loop.c

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -32,14 +32,6 @@ static void furi_event_loop_item_notify(FuriEventLoopItem* instance);
3232

3333
static bool furi_event_loop_item_is_waiting(FuriEventLoopItem* instance);
3434

35-
static void furi_event_loop_process_pending_callbacks(FuriEventLoop* instance) {
36-
for(; !PendingQueue_empty_p(instance->pending_queue);
37-
PendingQueue_pop_back(NULL, instance->pending_queue)) {
38-
const FuriEventLoopPendingQueueItem* item = PendingQueue_back(instance->pending_queue);
39-
item->callback(item->context);
40-
}
41-
}
42-
4335
static bool furi_event_loop_signal_callback(uint32_t signal, void* arg, void* context) {
4436
furi_assert(context);
4537
FuriEventLoop* instance = context;
@@ -130,12 +122,16 @@ static inline FuriEventLoopProcessStatus
130122
furi_event_loop_unsubscribe(instance, item->object);
131123
}
132124

125+
instance->current_item = item;
126+
133127
if(item->event & FuriEventLoopEventFlagEdge) {
134128
status = furi_event_loop_process_edge_event(item);
135129
} else {
136130
status = furi_event_loop_process_level_event(item);
137131
}
138132

133+
instance->current_item = NULL;
134+
139135
if(item->owner == NULL) {
140136
status = FuriEventLoopProcessStatusFreeLater;
141137
}
@@ -193,6 +189,14 @@ static void furi_event_loop_process_waiting_list(FuriEventLoop* instance) {
193189
furi_event_loop_sync_flags(instance);
194190
}
195191

192+
static void furi_event_loop_process_pending_callbacks(FuriEventLoop* instance) {
193+
for(; !PendingQueue_empty_p(instance->pending_queue);
194+
PendingQueue_pop_back(NULL, instance->pending_queue)) {
195+
const FuriEventLoopPendingQueueItem* item = PendingQueue_back(instance->pending_queue);
196+
item->callback(item->context);
197+
}
198+
}
199+
196200
static void furi_event_loop_restore_flags(FuriEventLoop* instance, uint32_t flags) {
197201
if(flags) {
198202
xTaskNotifyIndexed(
@@ -203,7 +207,6 @@ static void furi_event_loop_restore_flags(FuriEventLoop* instance, uint32_t flag
203207
void furi_event_loop_run(FuriEventLoop* instance) {
204208
furi_check(instance);
205209
furi_check(instance->thread_id == furi_thread_get_current_id());
206-
207210
FuriThread* thread = furi_thread_get_current();
208211

209212
// Set the default signal callback if none was previously set
@@ -213,9 +216,9 @@ void furi_event_loop_run(FuriEventLoop* instance) {
213216

214217
furi_event_loop_init_tick(instance);
215218

216-
while(true) {
217-
instance->state = FuriEventLoopStateIdle;
219+
instance->state = FuriEventLoopStateRunning;
218220

221+
while(true) {
219222
const TickType_t ticks_to_sleep =
220223
MIN(furi_event_loop_get_timer_wait_time(instance),
221224
furi_event_loop_get_tick_wait_time(instance));
@@ -224,8 +227,6 @@ void furi_event_loop_run(FuriEventLoop* instance) {
224227
BaseType_t ret = xTaskNotifyWaitIndexed(
225228
FURI_EVENT_LOOP_FLAG_NOTIFY_INDEX, 0, FuriEventLoopFlagAll, &flags, ticks_to_sleep);
226229

227-
instance->state = FuriEventLoopStateProcessing;
228-
229230
if(ret == pdTRUE) {
230231
if(flags & FuriEventLoopFlagStop) {
231232
instance->state = FuriEventLoopStateStopped;
@@ -448,7 +449,7 @@ void furi_event_loop_unsubscribe(FuriEventLoop* instance, FuriEventLoopObject* o
448449
WaitingList_unlink(item);
449450
}
450451

451-
if(instance->state == FuriEventLoopStateProcessing) {
452+
if(instance->current_item == item) {
452453
furi_event_loop_item_free_later(item);
453454
} else {
454455
furi_event_loop_item_free(item);

furi/core/event_loop_i.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,7 @@ typedef enum {
6464

6565
typedef enum {
6666
FuriEventLoopStateStopped,
67-
FuriEventLoopStateIdle,
68-
FuriEventLoopStateProcessing,
67+
FuriEventLoopStateRunning,
6968
} FuriEventLoopState;
7069

7170
typedef struct {
@@ -81,6 +80,7 @@ struct FuriEventLoop {
8180

8281
// Poller state
8382
volatile FuriEventLoopState state;
83+
volatile FuriEventLoopItem* current_item;
8484

8585
// Event handling
8686
FuriEventLoopTree_t tree;

lib/nfc/protocols/mf_desfire/mf_desfire.c

Lines changed: 118 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,46 @@
44

55
#define MF_DESFIRE_PROTOCOL_NAME "Mifare DESFire"
66

7+
#define MF_DESFIRE_HW_MINOR_TYPE (0x00)
8+
#define MF_DESFIRE_HW_MINOR_TYPE_MF3ICD40 (0x02)
9+
10+
#define MF_DESFIRE_HW_MAJOR_TYPE_EV1 (0x01)
11+
#define MF_DESFIRE_HW_MAJOR_TYPE_EV2 (0x12)
12+
#define MF_DESFIRE_HW_MAJOR_TYPE_EV2_XL (0x22)
13+
#define MF_DESFIRE_HW_MAJOR_TYPE_EV3 (0x33)
14+
#define MF_DESFIRE_HW_MAJOR_TYPE_MF3ICD40 (0x00)
15+
16+
#define MF_DESFIRE_STORAGE_SIZE_2K (0x16)
17+
#define MF_DESFIRE_STORAGE_SIZE_4K (0x18)
18+
#define MF_DESFIRE_STORAGE_SIZE_8K (0x1A)
19+
#define MF_DESFIRE_STORAGE_SIZE_16K (0x1C)
20+
#define MF_DESFIRE_STORAGE_SIZE_32K (0x1E)
21+
#define MF_DESFIRE_STORAGE_SIZE_MF3ICD40 (0xFF)
22+
#define MF_DESFIRE_STORAGE_SIZE_UNKNOWN (0xFF)
23+
24+
#define MF_DESFIRE_TEST_TYPE_MF3ICD40(major, minor, storage) \
25+
(((major) == MF_DESFIRE_HW_MAJOR_TYPE_MF3ICD40) && \
26+
((minor) == MF_DESFIRE_HW_MINOR_TYPE_MF3ICD40) && \
27+
((storage) == MF_DESFIRE_STORAGE_SIZE_MF3ICD40))
28+
29+
static const char* mf_desfire_type_strings[] = {
30+
[MfDesfireTypeMF3ICD40] = "(MF3ICD40)",
31+
[MfDesfireTypeEV1] = "EV1",
32+
[MfDesfireTypeEV2] = "EV2",
33+
[MfDesfireTypeEV2XL] = "EV2 XL",
34+
[MfDesfireTypeEV3] = "EV3",
35+
[MfDesfireTypeUnknown] = "UNK",
36+
};
37+
38+
static const char* mf_desfire_size_strings[] = {
39+
[MfDesfireSize2k] = "2K",
40+
[MfDesfireSize4k] = "4K",
41+
[MfDesfireSize8k] = "8K",
42+
[MfDesfireSize16k] = "16K",
43+
[MfDesfireSize32k] = "32K",
44+
[MfDesfireSizeUnknown] = "",
45+
};
46+
747
const NfcDeviceBase nfc_device_mf_desfire = {
848
.protocol_name = MF_DESFIRE_PROTOCOL_NAME,
949
.alloc = (NfcDeviceAlloc)mf_desfire_alloc,
@@ -26,7 +66,7 @@ MfDesfireData* mf_desfire_alloc(void) {
2666
data->master_key_versions = simple_array_alloc(&mf_desfire_key_version_array_config);
2767
data->application_ids = simple_array_alloc(&mf_desfire_app_id_array_config);
2868
data->applications = simple_array_alloc(&mf_desfire_application_array_config);
29-
69+
data->device_name = furi_string_alloc();
3070
return data;
3171
}
3272

@@ -38,6 +78,7 @@ void mf_desfire_free(MfDesfireData* data) {
3878
simple_array_free(data->application_ids);
3979
simple_array_free(data->master_key_versions);
4080
iso14443_4a_free(data->iso14443_4a_data);
81+
furi_string_free(data->device_name);
4182
free(data);
4283
}
4384

@@ -228,10 +269,83 @@ bool mf_desfire_is_equal(const MfDesfireData* data, const MfDesfireData* other)
228269
simple_array_is_equal(data->applications, other->applications);
229270
}
230271

272+
static MfDesfireType mf_desfire_get_type_from_version(const MfDesfireVersion* const version) {
273+
MfDesfireType type = MfDesfireTypeUnknown;
274+
275+
switch(version->hw_major) {
276+
case MF_DESFIRE_HW_MAJOR_TYPE_EV1:
277+
type = MfDesfireTypeEV1;
278+
break;
279+
case MF_DESFIRE_HW_MAJOR_TYPE_EV2:
280+
type = MfDesfireTypeEV2;
281+
break;
282+
case MF_DESFIRE_HW_MAJOR_TYPE_EV2_XL:
283+
type = MfDesfireTypeEV2XL;
284+
break;
285+
case MF_DESFIRE_HW_MAJOR_TYPE_EV3:
286+
type = MfDesfireTypeEV3;
287+
break;
288+
default:
289+
if(MF_DESFIRE_TEST_TYPE_MF3ICD40(version->hw_major, version->hw_minor, version->hw_storage))
290+
type = MfDesfireTypeMF3ICD40;
291+
break;
292+
}
293+
294+
return type;
295+
}
296+
297+
static MfDesfireSize mf_desfire_get_size_from_version(const MfDesfireVersion* const version) {
298+
MfDesfireSize size = MfDesfireSizeUnknown;
299+
300+
switch(version->hw_storage) {
301+
case MF_DESFIRE_STORAGE_SIZE_2K:
302+
size = MfDesfireSize2k;
303+
break;
304+
case MF_DESFIRE_STORAGE_SIZE_4K:
305+
size = MfDesfireSize4k;
306+
break;
307+
case MF_DESFIRE_STORAGE_SIZE_8K:
308+
size = MfDesfireSize8k;
309+
break;
310+
case MF_DESFIRE_STORAGE_SIZE_16K:
311+
size = MfDesfireSize16k;
312+
break;
313+
case MF_DESFIRE_STORAGE_SIZE_32K:
314+
size = MfDesfireSize32k;
315+
break;
316+
default:
317+
if(MF_DESFIRE_TEST_TYPE_MF3ICD40(version->hw_major, version->hw_minor, version->hw_storage))
318+
size = MfDesfireSize4k;
319+
break;
320+
}
321+
322+
return size;
323+
}
324+
231325
const char* mf_desfire_get_device_name(const MfDesfireData* data, NfcDeviceNameType name_type) {
232-
UNUSED(data);
233-
UNUSED(name_type);
234-
return MF_DESFIRE_PROTOCOL_NAME;
326+
furi_check(data);
327+
328+
const MfDesfireType type = mf_desfire_get_type_from_version(&data->version);
329+
const MfDesfireSize size = mf_desfire_get_size_from_version(&data->version);
330+
331+
if(type == MfDesfireTypeUnknown) {
332+
furi_string_printf(data->device_name, "Unknown %s", MF_DESFIRE_PROTOCOL_NAME);
333+
} else if(name_type == NfcDeviceNameTypeFull) {
334+
furi_string_printf(
335+
data->device_name,
336+
"%s %s %s",
337+
MF_DESFIRE_PROTOCOL_NAME,
338+
mf_desfire_type_strings[type],
339+
mf_desfire_size_strings[size]);
340+
} else {
341+
furi_string_printf(
342+
data->device_name,
343+
"%s %s",
344+
mf_desfire_type_strings[type],
345+
mf_desfire_size_strings[size]);
346+
}
347+
348+
return furi_string_get_cstr(data->device_name);
235349
}
236350

237351
const uint8_t* mf_desfire_get_uid(const MfDesfireData* data, size_t* uid_len) {

0 commit comments

Comments
 (0)