From 69b9c54b2f17856d105520dc7028d73b0c546b14 Mon Sep 17 00:00:00 2001 From: Evgenii Tereshkov Date: Thu, 6 Oct 2022 23:18:23 +0700 Subject: [PATCH 1/9] Update ac.ir: add Daichi model DA25AVQS1-W (#1819) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: あく --- assets/resources/infrared/assets/ac.ir | 38 ++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/assets/resources/infrared/assets/ac.ir b/assets/resources/infrared/assets/ac.ir index 7866febc6..97c384591 100644 --- a/assets/resources/infrared/assets/ac.ir +++ b/assets/resources/infrared/assets/ac.ir @@ -74,3 +74,41 @@ type: raw frequency: 38000 duty_cycle: 0.330000 data: 8972 4491 592 1651 592 1655 598 532 599 535 597 542 600 541 601 544 598 1656 597 526 595 1652 591 1658 595 539 593 545 597 545 597 546 596 537 594 529 592 535 596 1653 600 534 597 541 601 539 592 552 600 533 598 525 596 530 591 538 593 539 592 1665 598 1662 591 1673 601 533 598 526 595 533 598 532 600 534 597 540 591 548 594 550 592 542 600 523 598 528 593 536 595 537 594 543 599 542 600 543 599 517 594 7937 593 531 601 526 595 535 597 537 594 542 600 541 601 543 599 1654 599 523 598 528 593 536 596 538 594 542 600 541 590 552 600 532 599 524 597 528 593 536 595 537 595 541 601 539 593 551 591 542 600 522 599 527 594 536 595 537 594 543 599 540 591 552 600 532 600 523 598 527 594 535 596 537 595 542 600 540 591 552 600 532 600 523 598 528 593 536 595 538 593 543 599 541 601 543 599 535 596 527 594 532 600 531 601 534 597 540 592 549 593 552 600 534 597 525 596 529 592 1655 598 534 597 1656 597 1661 592 1671 592 1644 599 7934 596 529 592 535 597 535 597 538 593 544 598 543 599 545 597 538 593 1650 593 535 596 534 597 536 595 540 591 547 595 547 595 536 595 526 595 529 592 536 595 535 596 539 593 546 596 547 595 538 593 528 593 531 601 529 592 541 601 536 596 545 597 548 594 540 592 532 600 526 595 535 596 1656 597 541 601 540 592 553 599 534 597 526 595 532 599 531 600 533 598 539 593 548 594 552 600 535 596 1647 596 531 590 538 593 1656 597 538 594 545 597 545 597 518 593 +# +# Model: Daichi DA25AVQS1-W +name: Dh +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 9131 4318 815 389 817 1523 784 391 815 1523 784 1494 813 422 784 391 816 421 785 1524 784 392 814 422 783 1525 782 424 782 422 784 422 784 422 784 396 809 423 783 422 782 423 783 423 783 1496 812 1525 782 424 783 423 783 422 783 423 783 394 811 1526 782 424 782 1524 782 423 783 423 782 1525 782 423 675 19938 810 425 781 424 674 502 811 423 675 531 675 531 675 531 676 530 675 531 675 531 675 502 704 530 675 530 676 530 676 502 704 530 676 530 676 530 675 530 675 530 676 530 675 530 676 530 676 529 677 529 677 529 677 530 677 529 677 1631 676 529 677 1630 678 1631 677 +# +name: Cool_hi +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 9076 4455 677 1629 678 528 677 528 677 1630 677 529 677 530 676 530 676 531 675 531 675 531 675 531 675 531 674 531 675 532 674 531 674 532 674 531 675 532 674 531 674 531 674 532 674 1633 674 1633 674 532 674 532 674 532 674 532 674 532 674 1634 673 533 673 1634 673 533 674 532 674 1633 674 533 673 19965 674 531 674 532 675 531 675 531 675 531 675 531 675 531 675 531 675 532 674 531 675 531 676 531 674 531 675 531 675 531 674 531 675 531 675 532 674 532 674 531 675 532 674 532 674 531 675 531 675 532 674 532 674 532 674 532 674 1633 674 1633 674 532 674 532 674 +# +name: Cool_lo +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 9076 4453 679 1628 703 503 703 503 702 1607 700 506 699 507 699 507 699 507 699 1609 698 1610 698 1609 699 507 699 508 698 508 698 508 698 508 698 508 698 507 699 508 698 508 698 508 697 1609 698 1610 698 508 698 508 698 508 698 508 698 509 697 1610 697 508 698 1610 698 508 698 508 698 1610 697 509 697 19941 699 507 699 507 699 507 699 508 698 508 698 508 698 508 698 508 697 508 698 508 698 507 699 508 698 508 698 508 698 508 698 508 698 508 698 508 697 509 697 509 697 508 698 508 698 508 698 508 698 509 697 508 697 509 697 509 696 509 697 1635 673 533 673 1611 696 +# +name: Heat_hi +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 148 110377 9082 4422 707 499 706 500 704 1603 703 1606 701 505 700 507 699 506 700 507 699 506 700 1607 700 1608 700 1609 699 506 699 507 699 506 699 507 699 507 699 506 700 507 699 507 699 507 699 1608 699 1607 699 507 699 507 699 507 699 507 699 507 699 1609 699 507 699 1608 699 507 699 507 699 1609 699 507 699 19940 700 506 700 506 699 507 699 507 699 506 700 506 700 507 699 507 699 507 700 507 699 506 699 507 699 507 699 507 699 507 699 507 699 507 699 507 699 507 698 507 700 507 699 507 699 507 699 507 699 507 699 508 698 508 698 507 699 507 699 508 698 1610 699 508 698 +# +name: Heat_lo +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 9081 4423 707 499 706 500 704 1604 702 1606 701 505 701 506 700 506 700 506 700 1608 700 1607 700 1609 699 506 700 506 700 506 700 506 700 506 700 507 699 506 700 506 700 507 699 507 699 1608 700 1608 699 507 699 507 699 507 699 507 699 507 699 1608 699 507 698 1609 698 507 699 507 699 1609 699 507 699 19938 699 506 700 506 700 507 699 506 699 506 700 506 699 506 700 507 699 507 699 507 700 506 699 507 699 507 699 507 699 507 699 507 698 507 699 507 699 507 699 507 699 507 699 507 699 507 699 507 700 507 699 507 698 507 699 507 699 1609 699 507 698 1609 699 1609 699 +# +name: Off +type: raw +frequency: 38000 +duty_cycle: 0.330000 +data: 9106 4398 731 499 706 500 705 502 702 504 701 505 701 505 701 1606 701 505 701 1607 701 505 701 506 700 1607 700 506 700 506 700 505 700 505 701 506 700 506 700 506 699 506 700 506 700 1607 700 506 700 506 700 506 700 505 701 506 700 506 700 1608 699 506 700 1608 699 506 700 506 700 1608 700 506 700 19941 701 1606 700 505 701 505 701 506 700 505 700 506 700 506 700 506 700 506 700 506 700 506 700 506 700 506 701 506 700 506 700 506 700 506 700 506 700 506 700 506 700 506 700 506 700 506 700 506 700 506 700 506 699 506 700 506 700 1608 700 1607 700 506 700 506 700 + From 5de2c32c815d3a5322232abb7a5e77bb9052bbcf Mon Sep 17 00:00:00 2001 From: gornekich Date: Thu, 6 Oct 2022 21:58:17 +0500 Subject: [PATCH 2/9] [FL-2864] NFC update detect reader (#1820) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * nfc: update detect reader view * nfc: make detect reader more interractive * nfc: update icons * nfc: fix detect reader gui * nfc: fix gui, fix worker events * nfc: fix notifications * nfc: add nfc_worker NULL assert Co-authored-by: あく --- .../main/nfc/scenes/nfc_scene_detect_reader.c | 45 ++++++++++- .../nfc/scenes/nfc_scene_mfkey_nonces_info.c | 6 +- applications/main/nfc/views/detect_reader.c | 73 ++++++++++++++---- applications/main/nfc/views/detect_reader.h | 13 +++- assets/icons/NFC/Modern_reader_18x34.png | Bin 0 -> 3670 bytes assets/icons/NFC/Move_flipper_26x39.png | Bin 0 -> 3698 bytes assets/icons/NFC/Release_arrow_18x15.png | Bin 0 -> 3631 bytes firmware/targets/f7/api_symbols.csv | 3 + lib/nfc/helpers/mfkey32.c | 2 +- lib/nfc/nfc_worker.c | 21 ++++- lib/nfc/nfc_worker.h | 2 + 11 files changed, 140 insertions(+), 25 deletions(-) create mode 100644 assets/icons/NFC/Modern_reader_18x34.png create mode 100644 assets/icons/NFC/Move_flipper_26x39.png create mode 100644 assets/icons/NFC/Release_arrow_18x15.png diff --git a/applications/main/nfc/scenes/nfc_scene_detect_reader.c b/applications/main/nfc/scenes/nfc_scene_detect_reader.c index 5f4582d8e..e8c2b5ee8 100644 --- a/applications/main/nfc/scenes/nfc_scene_detect_reader.c +++ b/applications/main/nfc/scenes/nfc_scene_detect_reader.c @@ -1,6 +1,15 @@ #include "../nfc_i.h" #include +#define NFC_SCENE_DETECT_READER_PAIR_NONCES_MAX (10U) + +static const NotificationSequence sequence_detect_reader = { + &message_green_255, + &message_blue_255, + &message_do_not_reset, + NULL, +}; + bool nfc_detect_reader_worker_callback(NfcWorkerEvent event, void* context) { UNUSED(event); furi_assert(context); @@ -20,21 +29,26 @@ void nfc_scene_detect_reader_on_enter(void* context) { DOLPHIN_DEED(DolphinDeedNfcEmulate); detect_reader_set_callback(nfc->detect_reader, nfc_scene_detect_reader_callback, nfc); + detect_reader_set_nonces_max(nfc->detect_reader, NFC_SCENE_DETECT_READER_PAIR_NONCES_MAX); + + // Store number of collected nonces in scene state + scene_manager_set_scene_state(nfc->scene_manager, NfcSceneDetectReader, 0); + notification_message(nfc->notifications, &sequence_detect_reader); + nfc_worker_start( nfc->worker, NfcWorkerStateAnalyzeReader, &nfc->dev->dev_data, nfc_detect_reader_worker_callback, nfc); - view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewDetectReader); - - nfc_blink_read_start(nfc); } bool nfc_scene_detect_reader_on_event(void* context, SceneManagerEvent event) { Nfc* nfc = context; bool consumed = false; + uint32_t nonces_collected = + scene_manager_get_scene_state(nfc->scene_manager, NfcSceneDetectReader); if(event.type == SceneManagerEventTypeCustom) { if(event.event == NfcCustomEventViewExit) { @@ -42,8 +56,29 @@ bool nfc_scene_detect_reader_on_event(void* context, SceneManagerEvent event) { scene_manager_next_scene(nfc->scene_manager, NfcSceneMfkeyNoncesInfo); consumed = true; } else if(event.event == NfcWorkerEventDetectReaderMfkeyCollected) { - detect_reader_inc_nonce_cnt(nfc->detect_reader); + nonces_collected += 2; + scene_manager_set_scene_state( + nfc->scene_manager, NfcSceneDetectReader, nonces_collected); + detect_reader_set_nonces_collected(nfc->detect_reader, nonces_collected); + if(nonces_collected >= NFC_SCENE_DETECT_READER_PAIR_NONCES_MAX) { + detect_reader_set_state(nfc->detect_reader, DetectReaderStateDone); + nfc_blink_stop(nfc); + notification_message(nfc->notifications, &sequence_single_vibro); + notification_message(nfc->notifications, &sequence_set_green_255); + nfc_worker_stop(nfc->worker); + } consumed = true; + } else if(event.event == NfcWorkerEventDetectReaderDetected) { + if(nonces_collected < NFC_SCENE_DETECT_READER_PAIR_NONCES_MAX) { + notification_message(nfc->notifications, &sequence_blink_start_cyan); + detect_reader_set_state(nfc->detect_reader, DetectReaderStateReaderDetected); + } + } else if(event.event == NfcWorkerEventDetectReaderLost) { + if(nonces_collected < NFC_SCENE_DETECT_READER_PAIR_NONCES_MAX) { + nfc_blink_stop(nfc); + notification_message(nfc->notifications, &sequence_detect_reader); + detect_reader_set_state(nfc->detect_reader, DetectReaderStateReaderLost); + } } } @@ -59,5 +94,7 @@ void nfc_scene_detect_reader_on_exit(void* context) { // Clear view detect_reader_reset(nfc->detect_reader); + // Stop notifications nfc_blink_stop(nfc); + notification_message(nfc->notifications, &sequence_reset_green); } diff --git a/applications/main/nfc/scenes/nfc_scene_mfkey_nonces_info.c b/applications/main/nfc/scenes/nfc_scene_mfkey_nonces_info.c index 9fd4f5ae0..6d9852f3e 100644 --- a/applications/main/nfc/scenes/nfc_scene_mfkey_nonces_info.c +++ b/applications/main/nfc/scenes/nfc_scene_mfkey_nonces_info.c @@ -16,14 +16,14 @@ void nfc_scene_mfkey_nonces_info_on_enter(void* context) { uint16_t nonces_saved = mfkey32_get_auth_sectors(temp_str); widget_add_text_scroll_element(nfc->widget, 0, 22, 128, 42, furi_string_get_cstr(temp_str)); - furi_string_printf(temp_str, "Nonces saved %d", nonces_saved); + furi_string_printf(temp_str, "Nonce pairs saved: %d", nonces_saved); widget_add_string_element( nfc->widget, 0, 0, AlignLeft, AlignTop, FontPrimary, furi_string_get_cstr(temp_str)); widget_add_string_element( nfc->widget, 0, 12, AlignLeft, AlignTop, FontSecondary, "Authenticated sectors:"); widget_add_button_element( - nfc->widget, GuiButtonTypeRight, "Next", nfc_scene_mfkey_nonces_info_callback, nfc); + nfc->widget, GuiButtonTypeCenter, "OK", nfc_scene_mfkey_nonces_info_callback, nfc); furi_string_free(temp_str); @@ -35,7 +35,7 @@ bool nfc_scene_mfkey_nonces_info_on_event(void* context, SceneManagerEvent event bool consumed = false; if(event.type == SceneManagerEventTypeCustom) { - if(event.event == GuiButtonTypeRight) { + if(event.event == GuiButtonTypeCenter) { scene_manager_next_scene(nfc->scene_manager, NfcSceneMfkeyComplete); consumed = true; } diff --git a/applications/main/nfc/views/detect_reader.c b/applications/main/nfc/views/detect_reader.c index 177c13f75..9a0770438 100644 --- a/applications/main/nfc/views/detect_reader.c +++ b/applications/main/nfc/views/detect_reader.c @@ -10,29 +10,50 @@ struct DetectReader { typedef struct { uint16_t nonces; + uint16_t nonces_max; + DetectReaderState state; } DetectReaderViewModel; static void detect_reader_draw_callback(Canvas* canvas, void* model) { DetectReaderViewModel* m = model; char text[32] = {}; - snprintf(text, sizeof(text), "Tap the reader several times"); - canvas_draw_str_aligned(canvas, 64, 0, AlignCenter, AlignTop, "Tap the reader several times"); + // Draw header and icon + canvas_draw_icon(canvas, 0, 16, &I_Modern_reader_18x34); + if(m->state == DetectReaderStateStart) { + snprintf(text, sizeof(text), "Touch the reader"); + canvas_draw_icon(canvas, 21, 13, &I_Move_flipper_26x39); + } else if(m->state == DetectReaderStateReaderDetected) { + snprintf(text, sizeof(text), "Move the Flipper away"); + canvas_draw_icon(canvas, 24, 25, &I_Release_arrow_18x15); + } else if(m->state == DetectReaderStateReaderLost) { + snprintf(text, sizeof(text), "Touch the reader again"); + canvas_draw_icon(canvas, 21, 13, &I_Move_flipper_26x39); + } - if(m->nonces == 0) { + canvas_draw_str_aligned(canvas, 64, 0, AlignCenter, AlignTop, text); + + // Draw collected nonces + if(m->state == DetectReaderStateStart) { canvas_set_font(canvas, FontPrimary); - canvas_draw_str_aligned(canvas, 52, 22, AlignLeft, AlignTop, "Emulating..."); + canvas_draw_str_aligned(canvas, 51, 22, AlignLeft, AlignTop, "Emulating..."); canvas_set_font(canvas, FontSecondary); - canvas_draw_str_aligned(canvas, 52, 35, AlignLeft, AlignTop, "MIFARE Classic"); - canvas_draw_icon(canvas, 0, 13, &I_Tap_reader_36x38); + canvas_draw_str_aligned(canvas, 51, 35, AlignLeft, AlignTop, "MIFARE MFkey32"); } else { - canvas_set_font(canvas, FontPrimary); - canvas_draw_str_aligned(canvas, 54, 22, AlignLeft, AlignTop, "Collecting..."); + if(m->state == DetectReaderStateDone) { + canvas_set_font(canvas, FontPrimary); + canvas_draw_str_aligned(canvas, 51, 22, AlignLeft, AlignTop, "Completed!"); + } else { + canvas_set_font(canvas, FontPrimary); + canvas_draw_str_aligned(canvas, 51, 22, AlignLeft, AlignTop, "Collecting..."); + } canvas_set_font(canvas, FontSecondary); - snprintf(text, sizeof(text), "Nonces: %d", m->nonces); - canvas_draw_str_aligned(canvas, 54, 35, AlignLeft, AlignTop, text); - elements_button_right(canvas, "Next"); - canvas_draw_icon(canvas, 6, 15, &I_ArrowC_1_36x36); + snprintf(text, sizeof(text), "Nonce pairs: %d/%d", m->nonces, m->nonces_max); + canvas_draw_str_aligned(canvas, 51, 35, AlignLeft, AlignTop, text); + } + // Draw button + if(m->nonces > 0) { + elements_button_center(canvas, "Done"); } } @@ -49,7 +70,7 @@ static bool detect_reader_input_callback(InputEvent* event, void* context) { }); if(event->type == InputTypeShort) { - if(event->key == InputKeyRight) { + if(event->key == InputKeyOk) { if(nonces > 0) { detect_reader->callback(detect_reader->context); consumed = true; @@ -84,6 +105,8 @@ void detect_reader_reset(DetectReader* detect_reader) { with_view_model( detect_reader->view, (DetectReaderViewModel * model) { model->nonces = 0; + model->nonces_max = 0; + model->state = DetectReaderStateStart; return false; }); } @@ -105,11 +128,31 @@ void detect_reader_set_callback( detect_reader->context = context; } -void detect_reader_inc_nonce_cnt(DetectReader* detect_reader) { +void detect_reader_set_nonces_max(DetectReader* detect_reader, uint16_t nonces_max) { furi_assert(detect_reader); + with_view_model( detect_reader->view, (DetectReaderViewModel * model) { - model->nonces++; + model->nonces_max = nonces_max; return false; }); } + +void detect_reader_set_nonces_collected(DetectReader* detect_reader, uint16_t nonces_collected) { + furi_assert(detect_reader); + + with_view_model( + detect_reader->view, (DetectReaderViewModel * model) { + model->nonces = nonces_collected; + return false; + }); +} + +void detect_reader_set_state(DetectReader* detect_reader, DetectReaderState state) { + furi_assert(detect_reader); + with_view_model( + detect_reader->view, (DetectReaderViewModel * model) { + model->state = state; + return true; + }); +} diff --git a/applications/main/nfc/views/detect_reader.h b/applications/main/nfc/views/detect_reader.h index 12cd03db4..aabdd7c87 100644 --- a/applications/main/nfc/views/detect_reader.h +++ b/applications/main/nfc/views/detect_reader.h @@ -5,6 +5,13 @@ typedef struct DetectReader DetectReader; +typedef enum { + DetectReaderStateStart, + DetectReaderStateReaderDetected, + DetectReaderStateReaderLost, + DetectReaderStateDone, +} DetectReaderState; + typedef void (*DetectReaderDoneCallback)(void* context); DetectReader* detect_reader_alloc(); @@ -20,4 +27,8 @@ void detect_reader_set_callback( DetectReaderDoneCallback callback, void* context); -void detect_reader_inc_nonce_cnt(DetectReader* detect_reader); +void detect_reader_set_nonces_max(DetectReader* detect_reader, uint16_t nonces_max); + +void detect_reader_set_nonces_collected(DetectReader* detect_reader, uint16_t nonces_collected); + +void detect_reader_set_state(DetectReader* detect_reader, DetectReaderState state); diff --git a/assets/icons/NFC/Modern_reader_18x34.png b/assets/icons/NFC/Modern_reader_18x34.png new file mode 100644 index 0000000000000000000000000000000000000000..b19c0f30c9f3928d3129acc9da92d5a9e962d084 GIT binary patch literal 3670 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 literal 0 HcmV?d00001 diff --git a/assets/icons/NFC/Move_flipper_26x39.png b/assets/icons/NFC/Move_flipper_26x39.png new file mode 100644 index 0000000000000000000000000000000000000000..ff4af9ff05989e5ff04d3888971b7f7801c59ed4 GIT binary patch literal 3698 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 literal 0 HcmV?d00001 diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv index a140ff0be..4e1704d06 100644 --- a/firmware/targets/f7/api_symbols.csv +++ b/firmware/targets/f7/api_symbols.csv @@ -2693,6 +2693,8 @@ Variable,+,I_Lock_7x8,const Icon, Variable,+,I_Lock_8x8,const Icon, Variable,+,I_MHz_25x11,const Icon, Variable,+,I_Medium_chip_22x21,const Icon, +Variable,+,I_Modern_reader_18x34,const Icon, +Variable,+,I_Move_flipper_26x39,const Icon, Variable,+,I_Mute_25x27,const Icon, Variable,+,I_Mute_hvr_25x27,const Icon, Variable,+,I_NFC_manual_60x50,const Icon, @@ -2720,6 +2722,7 @@ Variable,+,I_RFIDDolphinReceive_97x61,const Icon, Variable,+,I_RFIDDolphinSend_97x61,const Icon, Variable,+,I_RFIDDolphinSuccess_108x57,const Icon, Variable,+,I_Reader_detect_43x40,const Icon, +Variable,+,I_Release_arrow_18x15,const Icon, Variable,+,I_Restoring_38x32,const Icon, Variable,+,I_Right_mouse_icon_9x9,const Icon, Variable,+,I_SDQuestion_35x43,const Icon, diff --git a/lib/nfc/helpers/mfkey32.c b/lib/nfc/helpers/mfkey32.c index 8eb417eb1..fa5713f27 100644 --- a/lib/nfc/helpers/mfkey32.c +++ b/lib/nfc/helpers/mfkey32.c @@ -92,7 +92,7 @@ void mfkey32_set_callback(Mfkey32* instance, Mfkey32ParseDataCallback callback, static bool mfkey32_write_params(Mfkey32* instance, Mfkey32Params* params) { FuriString* str = furi_string_alloc_printf( - "Sector %d key %c cuid %08x nt0 %08x nr0 %08x ar0 %08x nt1 %08x nr1 %08x ar1 %08x\n", + "Sec %d key %c cuid %08x nt0 %08x nr0 %08x ar0 %08x nt1 %08x nr1 %08x ar1 %08x\n", params->sector, params->key == MfClassicKeyA ? 'A' : 'B', params->cuid, diff --git a/lib/nfc/nfc_worker.c b/lib/nfc/nfc_worker.c index 2feae443f..996e68f0d 100644 --- a/lib/nfc/nfc_worker.c +++ b/lib/nfc/nfc_worker.c @@ -647,7 +647,8 @@ static void nfc_worker_reader_analyzer_callback(ReaderAnalyzerEvent event, void* furi_assert(context); NfcWorker* nfc_worker = context; - if(event == ReaderAnalyzerEventMfkeyCollected) { + if((nfc_worker->state == NfcWorkerStateAnalyzeReader) && + (event == ReaderAnalyzerEventMfkeyCollected)) { if(nfc_worker->callback) { nfc_worker->callback(NfcWorkerEventDetectReaderMfkeyCollected, nfc_worker->context); } @@ -655,6 +656,9 @@ static void nfc_worker_reader_analyzer_callback(ReaderAnalyzerEvent event, void* } void nfc_worker_analyze_reader(NfcWorker* nfc_worker) { + furi_assert(nfc_worker); + furi_assert(nfc_worker->callback); + FuriHalNfcTxRxContext tx_rx = {}; ReaderAnalyzer* reader_analyzer = nfc_worker->reader_analyzer; @@ -673,17 +677,32 @@ void nfc_worker_analyze_reader(NfcWorker* nfc_worker) { rfal_platform_spi_acquire(); FURI_LOG_D(TAG, "Start reader analyzer"); + + uint8_t reader_no_data_received_cnt = 0; + bool reader_no_data_notified = true; + while(nfc_worker->state == NfcWorkerStateAnalyzeReader) { furi_hal_nfc_stop_cmd(); furi_delay_ms(5); furi_hal_nfc_listen_start(nfc_data); if(furi_hal_nfc_listen_rx(&tx_rx, 300)) { + if(reader_no_data_notified) { + nfc_worker->callback(NfcWorkerEventDetectReaderDetected, nfc_worker->context); + } + reader_no_data_received_cnt = 0; + reader_no_data_notified = false; NfcProtocol protocol = reader_analyzer_guess_protocol(reader_analyzer, tx_rx.rx_data, tx_rx.rx_bits / 8); if(protocol == NfcDeviceProtocolMifareClassic) { mf_classic_emulator(&emulator, &tx_rx); } } else { + reader_no_data_received_cnt++; + if(!reader_no_data_notified && (reader_no_data_received_cnt > 5)) { + nfc_worker->callback(NfcWorkerEventDetectReaderLost, nfc_worker->context); + reader_no_data_received_cnt = 0; + reader_no_data_notified = true; + } FURI_LOG_D(TAG, "No data from reader"); continue; } diff --git a/lib/nfc/nfc_worker.h b/lib/nfc/nfc_worker.h index b7bf4da9a..84615f5d8 100644 --- a/lib/nfc/nfc_worker.h +++ b/lib/nfc/nfc_worker.h @@ -56,6 +56,8 @@ typedef enum { NfcWorkerEventFoundKeyB, // Detect Reader events + NfcWorkerEventDetectReaderDetected, + NfcWorkerEventDetectReaderLost, NfcWorkerEventDetectReaderMfkeyCollected, // Mifare Ultralight events From 6dde5586af130a8ca85416c502bee1a69da5220e Mon Sep 17 00:00:00 2001 From: Astra <93453568+Astrrra@users.noreply.github.com> Date: Thu, 6 Oct 2022 20:07:56 +0300 Subject: [PATCH 3/9] [FL-2803] Mifare Classic read improvements Part 1 (#1822) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Reuse found keys when reading a card * Fix keys not being read if no newline at the end of the file * Actually read all keys from the dictionary * Support for furi_string * Check only for re-used key after the current sector * Declare the key attack function as static * nfc: change logs, check worker state Co-authored-by: gornekich Co-authored-by: あく --- lib/nfc/helpers/mf_classic_dict.c | 13 ++++++-- lib/nfc/nfc_worker.c | 53 +++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 2 deletions(-) diff --git a/lib/nfc/helpers/mf_classic_dict.c b/lib/nfc/helpers/mf_classic_dict.c index 57841afc1..356f6f7c7 100644 --- a/lib/nfc/helpers/mf_classic_dict.c +++ b/lib/nfc/helpers/mf_classic_dict.c @@ -69,9 +69,18 @@ MfClassicDict* mf_classic_dict_alloc(MfClassicDictType dict_type) { FuriString* next_line; next_line = furi_string_alloc(); while(true) { - if(!stream_read_line(dict->stream, next_line)) break; + if(!stream_read_line(dict->stream, next_line)) { + FURI_LOG_T(TAG, "No keys left in dict"); + break; + } + furi_string_trim(next_line); + FURI_LOG_T( + TAG, + "Read line: %s, len: %d", + furi_string_get_cstr(next_line), + furi_string_size(next_line)); if(furi_string_get_char(next_line, 0) == '#') continue; - if(furi_string_size(next_line) != NFC_MF_CLASSIC_KEY_LEN) continue; + if(furi_string_size(next_line) != NFC_MF_CLASSIC_KEY_LEN - 1) continue; dict->total_keys++; } furi_string_free(next_line); diff --git a/lib/nfc/nfc_worker.c b/lib/nfc/nfc_worker.c index 996e68f0d..c61ad444c 100644 --- a/lib/nfc/nfc_worker.c +++ b/lib/nfc/nfc_worker.c @@ -453,6 +453,54 @@ void nfc_worker_emulate_mf_ultralight(NfcWorker* nfc_worker) { } } +static void nfc_worker_mf_classic_key_attack( + NfcWorker* nfc_worker, + uint64_t key, + FuriHalNfcTxRxContext* tx_rx, + uint16_t start_sector) { + furi_assert(nfc_worker); + + MfClassicData* data = &nfc_worker->dev_data->mf_classic_data; + uint32_t total_sectors = mf_classic_get_total_sectors_num(data->type); + + furi_assert(start_sector < total_sectors); + + // Check every sector's A and B keys with the given key + for(size_t i = start_sector; i < total_sectors; i++) { + uint8_t block_num = mf_classic_get_sector_trailer_block_num_by_sector(i); + if(mf_classic_is_sector_read(data, i)) continue; + if(!mf_classic_is_key_found(data, i, MfClassicKeyA)) { + FURI_LOG_D( + TAG, + "Trying A key for sector %d, key: %04lx%08lx", + i, + (uint32_t)(key >> 32), + (uint32_t)key); + if(mf_classic_authenticate(tx_rx, block_num, key, MfClassicKeyA)) { + mf_classic_set_key_found(data, i, MfClassicKeyA, key); + FURI_LOG_D(TAG, "Key found"); + nfc_worker->callback(NfcWorkerEventFoundKeyA, nfc_worker->context); + } + } + if(!mf_classic_is_key_found(data, i, MfClassicKeyB)) { + FURI_LOG_D( + TAG, + "Trying B key for sector %d, key: %04lx%08lx", + i, + (uint32_t)(key >> 32), + (uint32_t)key); + if(mf_classic_authenticate(tx_rx, block_num, key, MfClassicKeyB)) { + mf_classic_set_key_found(data, i, MfClassicKeyB, key); + FURI_LOG_D(TAG, "Key found"); + nfc_worker->callback(NfcWorkerEventFoundKeyB, nfc_worker->context); + } + } + if(mf_classic_is_sector_read(data, i)) continue; + mf_classic_read_sector(tx_rx, data, i); + if(nfc_worker->state != NfcWorkerStateMfClassicDictAttack) break; + } +} + void nfc_worker_mf_classic_dict_attack(NfcWorker* nfc_worker) { furi_assert(nfc_worker); furi_assert(nfc_worker->callback); @@ -484,6 +532,7 @@ void nfc_worker_mf_classic_dict_attack(NfcWorker* nfc_worker) { bool is_key_b_found = mf_classic_is_key_found(data, i, MfClassicKeyB); uint16_t key_index = 0; while(mf_classic_dict_get_next_key(dict, &key)) { + FURI_LOG_T(TAG, "Key %d", key_index); if(++key_index % NFC_DICT_KEY_BATCH_SIZE == 0) { nfc_worker->callback(NfcWorkerEventNewDictKeyBatch, nfc_worker->context); } @@ -505,15 +554,19 @@ void nfc_worker_mf_classic_dict_attack(NfcWorker* nfc_worker) { is_key_a_found = mf_classic_is_key_found(data, i, MfClassicKeyA); if(mf_classic_authenticate(&tx_rx, block_num, key, MfClassicKeyA)) { mf_classic_set_key_found(data, i, MfClassicKeyA, key); + FURI_LOG_D(TAG, "Key found"); nfc_worker->callback(NfcWorkerEventFoundKeyA, nfc_worker->context); + nfc_worker_mf_classic_key_attack(nfc_worker, key, &tx_rx, i + 1); } furi_hal_nfc_sleep(); } if(!is_key_b_found) { is_key_b_found = mf_classic_is_key_found(data, i, MfClassicKeyB); if(mf_classic_authenticate(&tx_rx, block_num, key, MfClassicKeyB)) { + FURI_LOG_D(TAG, "Key found"); mf_classic_set_key_found(data, i, MfClassicKeyB, key); nfc_worker->callback(NfcWorkerEventFoundKeyB, nfc_worker->context); + nfc_worker_mf_classic_key_attack(nfc_worker, key, &tx_rx, i + 1); } } if(is_key_a_found && is_key_b_found) break; From 01f7a3e5b52fa1842bb3117d7adddf059807c9ef Mon Sep 17 00:00:00 2001 From: gornekich Date: Thu, 6 Oct 2022 22:12:45 +0500 Subject: [PATCH 4/9] [FL-2874] Remove bank card uid emulation (#1823) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * nfc: open bank card info from archive * nfc: remove emulate uid option from bank cards menu Co-authored-by: あく --- applications/main/nfc/nfc.c | 2 ++ applications/main/nfc/scenes/nfc_scene_saved_menu.c | 3 +-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/applications/main/nfc/nfc.c b/applications/main/nfc/nfc.c index 44a0f6368..0b685f545 100644 --- a/applications/main/nfc/nfc.c +++ b/applications/main/nfc/nfc.c @@ -277,6 +277,8 @@ int32_t nfc_app(void* p) { scene_manager_next_scene(nfc->scene_manager, NfcSceneMfUltralightEmulate); } else if(nfc->dev->format == NfcDeviceSaveFormatMifareClassic) { scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicEmulate); + } else if(nfc->dev->format == NfcDeviceSaveFormatBankCard) { + scene_manager_next_scene(nfc->scene_manager, NfcSceneDeviceInfo); } else { scene_manager_next_scene(nfc->scene_manager, NfcSceneEmulateUid); } diff --git a/applications/main/nfc/scenes/nfc_scene_saved_menu.c b/applications/main/nfc/scenes/nfc_scene_saved_menu.c index c1043b3a7..fe65b5b8a 100644 --- a/applications/main/nfc/scenes/nfc_scene_saved_menu.c +++ b/applications/main/nfc/scenes/nfc_scene_saved_menu.c @@ -20,8 +20,7 @@ void nfc_scene_saved_menu_on_enter(void* context) { Submenu* submenu = nfc->submenu; if(nfc->dev->format == NfcDeviceSaveFormatUid || - nfc->dev->format == NfcDeviceSaveFormatMifareDesfire || - nfc->dev->format == NfcDeviceSaveFormatBankCard) { + nfc->dev->format == NfcDeviceSaveFormatMifareDesfire) { submenu_add_item( submenu, "Emulate UID", From 19cb469e4b884c31cad69e711ede34c2acda60ae Mon Sep 17 00:00:00 2001 From: Astra <93453568+Astrrra@users.noreply.github.com> Date: Thu, 6 Oct 2022 20:19:35 +0300 Subject: [PATCH 5/9] [FL-2877] Don't turn off the backlight on MFC dict attack #1826 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: あく --- applications/main/nfc/scenes/nfc_scene_mf_classic_dict_attack.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/applications/main/nfc/scenes/nfc_scene_mf_classic_dict_attack.c b/applications/main/nfc/scenes/nfc_scene_mf_classic_dict_attack.c index b23f4b8f1..813546905 100644 --- a/applications/main/nfc/scenes/nfc_scene_mf_classic_dict_attack.c +++ b/applications/main/nfc/scenes/nfc_scene_mf_classic_dict_attack.c @@ -91,6 +91,7 @@ void nfc_scene_mf_classic_dict_attack_on_enter(void* context) { nfc_scene_mf_classic_dict_attack_prepare_view(nfc, DictAttackStateIdle); view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewDictAttack); nfc_blink_read_start(nfc); + notification_message(nfc->notifications, &sequence_display_backlight_enforce_on); } bool nfc_scene_mf_classic_dict_attack_on_event(void* context, SceneManagerEvent event) { @@ -167,4 +168,5 @@ void nfc_scene_mf_classic_dict_attack_on_exit(void* context) { } dict_attack_reset(nfc->dict_attack); nfc_blink_stop(nfc); + notification_message(nfc->notifications, &sequence_display_backlight_enforce_auto); } From 72b3d7f41424c2489bb9466d2b131e0d4ff3e4e1 Mon Sep 17 00:00:00 2001 From: Georgii Surkov <37121527+gsurkov@users.noreply.github.com> Date: Thu, 6 Oct 2022 20:25:54 +0300 Subject: [PATCH 6/9] [FL-2620] Infrared error message (#1827) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Show an error message if the remote could not be saved/renamed Co-authored-by: あく --- .../main/infrared/scenes/infrared_scene_learn_enter_name.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/applications/main/infrared/scenes/infrared_scene_learn_enter_name.c b/applications/main/infrared/scenes/infrared_scene_learn_enter_name.c index b7f4179ea..b6a7eac0d 100644 --- a/applications/main/infrared/scenes/infrared_scene_learn_enter_name.c +++ b/applications/main/infrared/scenes/infrared_scene_learn_enter_name.c @@ -50,8 +50,10 @@ bool infrared_scene_learn_enter_name_on_event(void* context, SceneManagerEvent e if(success) { scene_manager_next_scene(scene_manager, InfraredSceneLearnDone); } else { - scene_manager_search_and_switch_to_previous_scene( - scene_manager, InfraredSceneRemoteList); + dialog_message_show_storage_error(infrared->dialogs, "Failed to save file"); + const uint32_t possible_scenes[] = {InfraredSceneRemoteList, InfraredSceneStart}; + scene_manager_search_and_switch_to_previous_scene_one_of( + scene_manager, possible_scenes, COUNT_OF(possible_scenes)); } consumed = true; } From dde18cd343a67a2ed42b2fe20b42bdffd05ad693 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Kimminich?= Date: Thu, 6 Oct 2022 19:40:18 +0200 Subject: [PATCH 7/9] Add exit label to keyboard connection screen (#1830) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add exit label to keyboard connection screen (resolves #1814) * BtHid: align baselines on connection screen Co-authored-by: あく --- applications/plugins/bt_hid_app/views/bt_hid_keyboard.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/applications/plugins/bt_hid_app/views/bt_hid_keyboard.c b/applications/plugins/bt_hid_app/views/bt_hid_keyboard.c index 3617dc0f1..8b9ae593a 100644 --- a/applications/plugins/bt_hid_app/views/bt_hid_keyboard.c +++ b/applications/plugins/bt_hid_app/views/bt_hid_keyboard.c @@ -209,6 +209,11 @@ static void bt_hid_keyboard_draw_callback(Canvas* canvas, void* context) { canvas_draw_icon(canvas, 0, 0, &I_Ble_disconnected_15x15); canvas_set_font(canvas, FontPrimary); elements_multiline_text_aligned(canvas, 17, 3, AlignLeft, AlignTop, "Keyboard"); + + canvas_draw_icon(canvas, 68, 3, &I_Pin_back_arrow_10x8); + canvas_set_font(canvas, FontSecondary); + elements_multiline_text_aligned(canvas, 127, 4, AlignRight, AlignTop, "Hold to exit"); + elements_multiline_text_aligned( canvas, 4, 60, AlignLeft, AlignBottom, "Waiting for Connection..."); return; // Dont render the keyboard if we are not yet connected From eaa3adf98ac4dcad5dec8d5f7eb716c242eb9ee4 Mon Sep 17 00:00:00 2001 From: Astra <93453568+Astrrra@users.noreply.github.com> Date: Thu, 6 Oct 2022 21:51:30 +0300 Subject: [PATCH 8/9] [FL-2868] Remove string_push_uint64 (#1832) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Remove string_pust_uint64 * Oops, furi strings now * Remove dead code * Remove unneeded import Co-authored-by: あく --- lib/nfc/parsers/plantain_4k_parser.c | 14 +---------- lib/nfc/parsers/plantain_parser.c | 36 +--------------------------- lib/nfc/parsers/plantain_parser.h | 2 -- lib/nfc/parsers/two_cities.c | 13 +--------- 4 files changed, 3 insertions(+), 62 deletions(-) diff --git a/lib/nfc/parsers/plantain_4k_parser.c b/lib/nfc/parsers/plantain_4k_parser.c index c970d74e5..eddebac23 100644 --- a/lib/nfc/parsers/plantain_4k_parser.c +++ b/lib/nfc/parsers/plantain_4k_parser.c @@ -1,5 +1,4 @@ #include "nfc_supported_card.h" -#include "plantain_parser.h" // For luhn and string_push_uint64 #include #include @@ -121,26 +120,15 @@ bool plantain_4k_parser_parse(NfcDeviceData* dev_data) { FuriString* card_number_str; card_number_str = furi_string_alloc(); // Should look like "361301047292848684" - // %llu doesn't work for some reason in sprintf, so we use string_push_uint64 instead - string_push_uint64(card_number, card_number_str); + furi_string_printf(card_number_str, "%llu", card_number); // Add suffix with luhn checksum (1 digit) to the card number string FuriString* card_number_suffix; card_number_suffix = furi_string_alloc(); - // The number to calculate the checksum on doesn't fit into uint64_t, idk - //uint8_t luhn_checksum = plantain_calculate_luhn(card_number); - - // // Convert luhn checksum to string - // FuriString* luhn_checksum_str; - // luhn_checksum_str = furi_string_alloc(); - // string_push_uint64(luhn_checksum, luhn_checksum_str); - furi_string_cat_printf(card_number_suffix, "-"); - // FURI_LOG_D("plant4k", "Card checksum: %d", luhn_checksum); furi_string_cat_printf(card_number_str, furi_string_get_cstr(card_number_suffix)); // Free all not needed strings furi_string_free(card_number_suffix); - // furi_string_free(luhn_checksum_str); furi_string_printf( dev_data->parsed_data, diff --git a/lib/nfc/parsers/plantain_parser.c b/lib/nfc/parsers/plantain_parser.c index 8ef8ee142..ac7a90b24 100644 --- a/lib/nfc/parsers/plantain_parser.c +++ b/lib/nfc/parsers/plantain_parser.c @@ -55,29 +55,6 @@ bool plantain_parser_read(NfcWorker* nfc_worker, FuriHalNfcTxRxContext* tx_rx) { return mf_classic_read_card(tx_rx, &reader, &nfc_worker->dev_data->mf_classic_data) == 16; } -void string_push_uint64(uint64_t input, FuriString* output) { - const uint8_t base = 10; - - do { - char c = input % base; - input /= base; - - if(c < 10) - c += '0'; - else - c += 'A' - 10; - furi_string_push_back(output, c); - } while(input); - - // reverse string - for(uint8_t i = 0; i < furi_string_size(output) / 2; i++) { - char c = furi_string_get_char(output, i); - furi_string_set_char( - output, i, furi_string_get_char(output, furi_string_size(output) - i - 1)); - furi_string_set_char(output, furi_string_size(output) - i - 1, c); - } -} - uint8_t plantain_calculate_luhn(uint64_t number) { // No. UNUSED(number); @@ -116,26 +93,15 @@ bool plantain_parser_parse(NfcDeviceData* dev_data) { FuriString* card_number_str; card_number_str = furi_string_alloc(); // Should look like "361301047292848684" - // %llu doesn't work for some reason in sprintf, so we use string_push_uint64 instead - string_push_uint64(card_number, card_number_str); + furi_string_printf(card_number_str, "%llu", card_number); // Add suffix with luhn checksum (1 digit) to the card number string FuriString* card_number_suffix; card_number_suffix = furi_string_alloc(); - // The number to calculate the checksum on doesn't fit into uint64_t, idk - //uint8_t luhn_checksum = plantain_calculate_luhn(card_number); - - // // Convert luhn checksum to string - // FuriString* luhn_checksum_str; - // luhn_checksum_str = furi_string_alloc(); - // string_push_uint64(luhn_checksum, luhn_checksum_str); - furi_string_cat_printf(card_number_suffix, "-"); - // FURI_LOG_D("plant4k", "Card checksum: %d", luhn_checksum); furi_string_cat_printf(card_number_str, furi_string_get_cstr(card_number_suffix)); // Free all not needed strings furi_string_free(card_number_suffix); - // furi_string_free(luhn_checksum_str); furi_string_printf( dev_data->parsed_data, diff --git a/lib/nfc/parsers/plantain_parser.h b/lib/nfc/parsers/plantain_parser.h index 65f396f1d..1af8c5065 100644 --- a/lib/nfc/parsers/plantain_parser.h +++ b/lib/nfc/parsers/plantain_parser.h @@ -8,6 +8,4 @@ bool plantain_parser_read(NfcWorker* nfc_worker, FuriHalNfcTxRxContext* tx_rx); bool plantain_parser_parse(NfcDeviceData* dev_data); -void string_push_uint64(uint64_t input, FuriString* output); - uint8_t plantain_calculate_luhn(uint64_t number); diff --git a/lib/nfc/parsers/two_cities.c b/lib/nfc/parsers/two_cities.c index 3dc975869..f5e31d51b 100644 --- a/lib/nfc/parsers/two_cities.c +++ b/lib/nfc/parsers/two_cities.c @@ -121,26 +121,15 @@ bool two_cities_parser_parse(NfcDeviceData* dev_data) { FuriString* card_number_str; card_number_str = furi_string_alloc(); // Should look like "361301047292848684" - // %llu doesn't work for some reason in sprintf, so we use string_push_uint64 instead - string_push_uint64(card_number, card_number_str); + furi_string_printf(card_number_str, "%llu", card_number); // Add suffix with luhn checksum (1 digit) to the card number string FuriString* card_number_suffix; card_number_suffix = furi_string_alloc(); - // The number to calculate the checksum on doesn't fit into uint64_t, idk - //uint8_t luhn_checksum = two_cities_calculate_luhn(card_number); - - // // Convert luhn checksum to string - // FuriString* luhn_checksum_str; - // luhn_checksum_str = furi_string_alloc(); - // string_push_uint64(luhn_checksum, luhn_checksum_str); - furi_string_cat_printf(card_number_suffix, "-"); - // FURI_LOG_D("plant4k", "Card checksum: %d", luhn_checksum); furi_string_cat_printf(card_number_str, furi_string_get_cstr(card_number_suffix)); // Free all not needed strings furi_string_free(card_number_suffix); - // furi_string_free(luhn_checksum_str); // ===== // --PLANTAIN-- From 81faca79eec67d789fcb97edd674d78b9a072b7c Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Fri, 7 Oct 2022 00:31:29 +0300 Subject: [PATCH 9/9] remove duplicate allocs from subghz history --- applications/main/subghz/subghz_history.c | 25 +++++++++-------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/applications/main/subghz/subghz_history.c b/applications/main/subghz/subghz_history.c index d4faa0b49..b09002853 100644 --- a/applications/main/subghz/subghz_history.c +++ b/applications/main/subghz/subghz_history.c @@ -13,7 +13,7 @@ #define SUBGHZ_HISTORY_TMP_EXTENSION ".tmp" #define SUBGHZ_HISTORY_TMP_SIGNAL_MAX_LEVEL_DURATION 700 #define SUBGHZ_HISTORY_TMP_SIGNAL_MIN_LEVEL_DURATION 100 -#define SUBGHZ_HISTORY_TMP_REMOVE_FILES false +#define SUBGHZ_HISTORY_TMP_REMOVE_FILES true #define SUBGHZ_HISTORY_TMP_RAW_KEY "RAW_Data" #define TAG "SubGhzHistory" @@ -52,8 +52,7 @@ struct SubGhzHistory { FuriString* subghz_history_generate_temp_filename(uint32_t index) { FuriHalRtcDateTime datetime = {0}; furi_hal_rtc_get_datetime(&datetime); - FuriString* filename = furi_string_alloc_printf("%03d%s", index, SUBGHZ_HISTORY_TMP_EXTENSION); - return filename; + return furi_string_alloc_printf("%03d%s", index, SUBGHZ_HISTORY_TMP_EXTENSION); } bool subghz_history_is_tmp_dir_exists(SubGhzHistory* instance) { @@ -103,7 +102,7 @@ void subghz_history_clear_tmp_dir(SubGhzHistory* instance) { // Nothing to do here! return; } - uint32_t start_time = furi_get_tick(); + //uint32_t start_time = furi_get_tick(); #ifdef SUBGHZ_HISTORY_TMP_REMOVE_FILES // Stage 0 - Dir exists? bool res = subghz_history_is_tmp_dir_exists(instance); @@ -123,8 +122,8 @@ void subghz_history_clear_tmp_dir(SubGhzHistory* instance) { FURI_LOG_E(TAG, "Cannot process temp dir!"); } #endif - uint32_t stop_time = furi_get_tick() - start_time; - FURI_LOG_I(TAG, "Running time (clear_tmp_dir): %d ms", stop_time); + /* uint32_t stop_time = furi_get_tick() - start_time; + FURI_LOG_I(TAG, "Running time (clear_tmp_dir): %d ms", stop_time);*/ } SubGhzHistory* subghz_history_alloc(void) { @@ -237,11 +236,9 @@ FlipperFormat* subghz_history_get_raw_data(SubGhzHistory* instance, uint16_t idx bool result_ok = false; if(instance->write_tmp_files && item->is_file) { // We have files! - FuriString* filename; + FuriString* filename = subghz_history_generate_temp_filename(idx); FuriString* dir_path; - filename = furi_string_alloc(); - dir_path = furi_string_alloc(); - filename = subghz_history_generate_temp_filename(idx); + dir_path = furi_string_alloc_printf( "%s/%s", SUBGHZ_HISTORY_TMP_DIR, furi_string_get_cstr(filename)); @@ -353,8 +350,8 @@ bool subghz_history_add_to_history( FURI_LOG_E(TAG, "Missing Protocol"); break; } else { - item->protocol_name = - furi_string_alloc_printf("%s", furi_string_get_cstr(instance->tmp_string)); + furi_string_printf( + item->protocol_name, "%s", furi_string_get_cstr(instance->tmp_string)); } if(!strcmp(furi_string_get_cstr(instance->tmp_string), "RAW")) { furi_string_printf( @@ -414,12 +411,10 @@ bool subghz_history_add_to_history( // If we can write to files if(instance->write_tmp_files && tmp_file_for_raw) { - FuriString* filename; + FuriString* filename = subghz_history_generate_temp_filename(instance->last_index_write); FuriString* dir_path; - filename = furi_string_alloc(); dir_path = furi_string_alloc(); - filename = subghz_history_generate_temp_filename(instance->last_index_write); furi_string_cat_printf( dir_path, "%s/%s", SUBGHZ_HISTORY_TMP_DIR, furi_string_get_cstr(filename)); #ifdef FURI_DEBUG