Просмотр исходного кода

Merge pull request #1 from frux-c/init_fixes

Init_fixes
Abel Chaka 2 лет назад
Родитель
Сommit
0102dc130f

+ 15 - 7
README.md

@@ -8,8 +8,8 @@ This repository contains a UHF RFID application developed for FlipperZero, a ver
 
 
 ## Features
 ## Features
 
 
-- [ ] Read UHF RFID tags.
-- [x] Write UHF RFID tags.
+- [x] Read UHF RFID tags.
+- [ ] Write UHF RFID tags.
 - [ ] Communicate with the YRM100 module to perform UHF RFID operations.
 - [ ] Communicate with the YRM100 module to perform UHF RFID operations.
 - [ ] Easy-to-use interface on FlipperZero's display.
 - [ ] Easy-to-use interface on FlipperZero's display.
 
 
@@ -22,8 +22,14 @@ To run this application on FlipperZero, you will need:
 
 
 ## Installation
 ## Installation
 
 
-1. Ensure you have set up your FlipperZero device with the YRM100 module properly.
-2. Clone this repository to your FlipperZero using (add the specific instructions or link to the tool used for this).
+1. Ensure you have set up your FlipperZero device with the YRM100 module properly. You can also read more about how to setup the module from the [Md5Stack Docs page](http://docs.m5stack.com/en/unit/uhf_rfid).
+   ![wiring diagram](https://static-cdn.m5stack.com/resource/docs/products/unit/uhf_rfid/uhf_rfid_sch_01.webp)
+2. Clone this repository to the `applications_user` folder of your flipper firmware of your choice
+3. If you have VSCode setup with your flipper firmware.
+   - ### Windows
+     1. Press `Ctrl+Shift+B` on vscode while in the uhf_app folder
+     2. Select the `Launch App on Flipper` option. And watch as the app launches on your flipper
+     - If you don't have vscode setup you can use the cli command `./fbt COMPACT=1 DEBUG=0 launch APPSRC=applications_user\uhf_rfid`
 
 
 ## Usage
 ## Usage
 
 
@@ -45,12 +51,14 @@ This project is licensed under the [MIT License](link_to_license_file). -->
 - Use it at your own risk.
 - Use it at your own risk.
 - I am not responsible for any damage or loss caused by the usage of this app.
 - I am not responsible for any damage or loss caused by the usage of this app.
 
 
+## Extra Resources
+
+- [MagicRF M100&QM100_Firmware_manual_en.pdf](assets/res/MagicRF_M100&QM100_Firmware_manual_en.pdf)
+
 ## Contact
 ## Contact
 
 
 For any inquiries or support, you can reach out to us at :
 For any inquiries or support, you can reach out to us at :
+
 - Personal Email : [frux.infoc@gmail.com](mailto:frux.infoc@gmail.com)
 - Personal Email : [frux.infoc@gmail.com](mailto:frux.infoc@gmail.com)
 - Discord Server: [Flipper Zero Tutorial-Unoffical by @jamisonderek](https://discord.gg/REunuAnTX9)
 - Discord Server: [Flipper Zero Tutorial-Unoffical by @jamisonderek](https://discord.gg/REunuAnTX9)
 - Discord User: [frux.c]()
 - Discord User: [frux.c]()
-
-
-

BIN
assets/res/MagicRF_M100&QM100_Firmware_manual_en.pdf


+ 8 - 17
scenes/uhf_scene_card_menu.c

@@ -5,26 +5,18 @@ enum SubmenuIndex {
     SubmenuIndexChangeKey,
     SubmenuIndexChangeKey,
 };
 };
 
 
-void uhf_scene_card_menu_submenu_callback(void* context, uint32_t index) {
-    UHFApp* uhf_app = context;
+void uhf_scene_card_menu_submenu_callback(void* ctx, uint32_t index) {
+    UHFApp* uhf_app = ctx;
     view_dispatcher_send_custom_event(uhf_app->view_dispatcher, index);
     view_dispatcher_send_custom_event(uhf_app->view_dispatcher, index);
 }
 }
 
 
-void uhf_scene_card_menu_on_enter(void* context) {
-    UHFApp* uhf_app = context;
+void uhf_scene_card_menu_on_enter(void* ctx) {
+    UHFApp* uhf_app = ctx;
 
 
     Submenu* submenu = uhf_app->submenu;
     Submenu* submenu = uhf_app->submenu;
 
 
     submenu_add_item(
     submenu_add_item(
         submenu, "Save", SubmenuIndexSave, uhf_scene_card_menu_submenu_callback, uhf_app);
         submenu, "Save", SubmenuIndexSave, uhf_scene_card_menu_submenu_callback, uhf_app);
-    // if(picopass->dev->dev_data.pacs.record.valid) {
-    //     submenu_add_item(
-    //         submenu,
-    //         "Save as LF",
-    //         SubmenuIndexSaveAsLF,
-    //         picopass_scene_card_menu_submenu_callback,
-    //         picopass);
-    // }
     submenu_add_item(
     submenu_add_item(
         submenu,
         submenu,
         "Change Key",
         "Change Key",
@@ -38,12 +30,11 @@ void uhf_scene_card_menu_on_enter(void* context) {
     view_dispatcher_switch_to_view(uhf_app->view_dispatcher, UHFViewMenu);
     view_dispatcher_switch_to_view(uhf_app->view_dispatcher, UHFViewMenu);
 }
 }
 
 
-bool uhf_scene_card_menu_on_event(void* context, SceneManagerEvent event) {
-    UHFApp* uhf_app = context;
+bool uhf_scene_card_menu_on_event(void* ctx, SceneManagerEvent event) {
+    UHFApp* uhf_app = ctx;
     bool consumed = false;
     bool consumed = false;
 
 
     if(event.type == SceneManagerEventTypeCustom) {
     if(event.type == SceneManagerEventTypeCustom) {
-        FURI_LOG_E("LOG", "%lu", event.event);
         if(event.event == SubmenuIndexSave) {
         if(event.event == SubmenuIndexSave) {
             scene_manager_set_scene_state(
             scene_manager_set_scene_state(
                 uhf_app->scene_manager, UHFSceneCardMenu, SubmenuIndexSave);
                 uhf_app->scene_manager, UHFSceneCardMenu, SubmenuIndexSave);
@@ -64,8 +55,8 @@ bool uhf_scene_card_menu_on_event(void* context, SceneManagerEvent event) {
     return consumed;
     return consumed;
 }
 }
 
 
-void uhf_scene_card_menu_on_exit(void* context) {
-    UHFApp* uhf_app = context;
+void uhf_scene_card_menu_on_exit(void* ctx) {
+    UHFApp* uhf_app = ctx;
 
 
     submenu_reset(uhf_app->submenu);
     submenu_reset(uhf_app->submenu);
 }
 }

+ 1 - 0
scenes/uhf_scene_config.h

@@ -1,3 +1,4 @@
+ADD_SCENE(uhf, verify, Verify)
 ADD_SCENE(uhf, start, Start)
 ADD_SCENE(uhf, start, Start)
 ADD_SCENE(uhf, read_tag, ReadTag)
 ADD_SCENE(uhf, read_tag, ReadTag)
 ADD_SCENE(uhf, read_tag_success, ReadTagSuccess)
 ADD_SCENE(uhf, read_tag_success, ReadTagSuccess)

+ 2 - 3
scenes/uhf_scene_read_tag.c

@@ -12,7 +12,6 @@ void uhf_read_tag_worker_callback(UHFWorkerEvent event, void* ctx) {
 }
 }
 
 
 void uhf_scene_read_tag_on_enter(void* ctx) {
 void uhf_scene_read_tag_on_enter(void* ctx) {
-    // FURI_LOG_E("33", "uhf_scene_read_tag_on_enter was called!");
     UHFApp* uhf_app = ctx;
     UHFApp* uhf_app = ctx;
     dolphin_deed(DolphinDeedNfcRead);
     dolphin_deed(DolphinDeedNfcRead);
 
 
@@ -23,7 +22,8 @@ void uhf_scene_read_tag_on_enter(void* ctx) {
 
 
     // Start worker
     // Start worker
     view_dispatcher_switch_to_view(uhf_app->view_dispatcher, UHFViewPopup);
     view_dispatcher_switch_to_view(uhf_app->view_dispatcher, UHFViewPopup);
-    uhf_worker_start(uhf_app->worker, UHFWorkerStateDetect, uhf_read_tag_worker_callback, uhf_app);
+    uhf_worker_start(
+        uhf_app->worker, UHFWorkerStateDetectSingle, uhf_read_tag_worker_callback, uhf_app);
 
 
     uhf_blink_start(uhf_app);
     uhf_blink_start(uhf_app);
 }
 }
@@ -33,7 +33,6 @@ bool uhf_scene_read_tag_on_event(void* ctx, SceneManagerEvent event) {
     UHFApp* uhf_app = ctx;
     UHFApp* uhf_app = ctx;
     bool consumed = false;
     bool consumed = false;
     if(event.event == UHFCustomEventWorkerExit) {
     if(event.event == UHFCustomEventWorkerExit) {
-        FURI_LOG_E("uhf_scene_read_tag_on_event", "event was registered");
         scene_manager_next_scene(uhf_app->scene_manager, UHFSceneReadTagSuccess);
         scene_manager_next_scene(uhf_app->scene_manager, UHFSceneReadTagSuccess);
         consumed = true;
         consumed = true;
     }
     }

+ 2 - 4
scenes/uhf_scene_read_tag_success.c

@@ -15,10 +15,9 @@ void uhf_scene_read_card_success_widget_callback(GuiButtonType result, InputType
 }
 }
 
 
 void uhf_scene_read_tag_success_on_enter(void* ctx) {
 void uhf_scene_read_tag_success_on_enter(void* ctx) {
-    // UNUSED(ctx);
     UHFApp* uhf_app = ctx;
     UHFApp* uhf_app = ctx;
 
 
-    const uint8_t* read_data = uhf_app->worker->data->data->data;
+    const uint8_t* read_data = uhf_app->worker->response_data->head->data;
 
 
     widget_add_string_element(
     widget_add_string_element(
         uhf_app->widget, 32, 5, AlignLeft, AlignCenter, FontPrimary, "Read Success");
         uhf_app->widget, 32, 5, AlignLeft, AlignCenter, FontPrimary, "Read Success");
@@ -78,7 +77,6 @@ bool uhf_scene_read_tag_success_on_event(void* ctx, SceneManagerEvent event) {
     UHFApp* uhf_app = ctx;
     UHFApp* uhf_app = ctx;
     bool consumed = false;
     bool consumed = false;
     if(event.event == SceneManagerEventTypeBack) {
     if(event.event == SceneManagerEventTypeBack) {
-        // FURI_LOG_E("36", "Back button was pressed");
         uhf_app->worker->state = UHFWorkerStateStop;
         uhf_app->worker->state = UHFWorkerStateStop;
     }
     }
     if(event.type == SceneManagerEventTypeCustom) {
     if(event.type == SceneManagerEventTypeCustom) {
@@ -101,7 +99,7 @@ void uhf_scene_read_tag_success_on_exit(void* ctx) {
     UHFApp* uhf_app = ctx;
     UHFApp* uhf_app = ctx;
 
 
     // // Stop worker
     // // Stop worker
-    // uhf_worker_stop(uhf_app->worker);
+    uhf_worker_stop(uhf_app->worker);
     // Clear view
     // Clear view
     popup_reset(uhf_app->popup);
     popup_reset(uhf_app->popup);
     // clear widget
     // clear widget

+ 2 - 2
scenes/uhf_scene_save_name.c

@@ -45,11 +45,11 @@ void uhf_scene_save_name_on_enter(void* context) {
 
 
 bool uhf_scene_save_name_on_event(void* context, SceneManagerEvent event) {
 bool uhf_scene_save_name_on_event(void* context, SceneManagerEvent event) {
     UHFApp* uhf_app = context;
     UHFApp* uhf_app = context;
-    UHFResponseData* uhf_data_save = uhf_app->worker->data;
+    UHFResponseData* uhf_data_save = uhf_app->worker->response_data;
     bool consumed = false;
     bool consumed = false;
     if(event.type == SceneManagerEventTypeCustom) {
     if(event.type == SceneManagerEventTypeCustom) {
         if(event.event == UHFCustomEventTextInputDone) {
         if(event.event == UHFCustomEventTextInputDone) {
-            if(uhf_save_data(uhf_data_save, uhf_app->storage, uhf_app->text_store)) {
+            if(uhf_save_read_data(uhf_data_save, uhf_app->storage, uhf_app->text_store)) {
                 scene_manager_next_scene(uhf_app->scene_manager, UHFSceneSaveSuccess);
                 scene_manager_next_scene(uhf_app->scene_manager, UHFSceneSaveSuccess);
                 consumed = true;
                 consumed = true;
             } else {
             } else {

+ 0 - 1
scenes/uhf_scene_start.c

@@ -27,7 +27,6 @@ bool uhf_scene_start_on_event(void* ctx, SceneManagerEvent event) {
     UHFApp* uhf_app = ctx;
     UHFApp* uhf_app = ctx;
     bool consumed = false;
     bool consumed = false;
     if(event.type == SceneManagerEventTypeCustom) {
     if(event.type == SceneManagerEventTypeCustom) {
-        // FURI_LOG_E("scene_start_on_event", "%lu", event.event);
         if(event.event == SubmenuIndexRead) {
         if(event.event == SubmenuIndexRead) {
             scene_manager_set_scene_state(uhf_app->scene_manager, UHFSceneStart, SubmenuIndexRead);
             scene_manager_set_scene_state(uhf_app->scene_manager, UHFSceneStart, SubmenuIndexRead);
             scene_manager_next_scene(uhf_app->scene_manager, UHFSceneReadTag);
             scene_manager_next_scene(uhf_app->scene_manager, UHFSceneReadTag);

+ 147 - 0
scenes/uhf_scene_verify.c

@@ -0,0 +1,147 @@
+#include "../uhf_app_i.h"
+
+bool verify_success = false;
+FuriString* temp_str;
+
+void uhf_scene_verify_callback_event(UHFWorkerEvent event, void* ctx) {
+    UNUSED(ctx);
+    UHFApp* uhf_app = ctx;
+    if(event == UHFWorkerEventSuccess) verify_success = true;
+
+    view_dispatcher_send_custom_event(uhf_app->view_dispatcher, UHFCustomEventVerifyDone);
+}
+
+void uhf_scene_verify_widget_callback(GuiButtonType result, InputType type, void* ctx) {
+    furi_assert(ctx);
+    UHFApp* uhf_app = ctx;
+
+    if(type == InputTypeShort) {
+        view_dispatcher_send_custom_event(uhf_app->view_dispatcher, result);
+    }
+}
+
+void uhf_scene_verify_on_enter(void* ctx) {
+    UHFApp* uhf_app = ctx;
+    uhf_worker_start(
+        uhf_app->worker, UHFWorkerStateVerify, uhf_scene_verify_callback_event, uhf_app);
+    temp_str = furi_string_alloc();
+    view_dispatcher_switch_to_view(uhf_app->view_dispatcher, UHFViewWidget);
+}
+
+bool uhf_scene_verify_on_event(void* ctx, SceneManagerEvent event) {
+    UHFApp* uhf_app = ctx;
+    bool consumed = false;
+    if(event.event == SceneManagerEventTypeBack) {
+        uhf_app->worker->state = UHFWorkerStateStop;
+    } else if(event.type == SceneManagerEventTypeCustom) {
+        if(event.event == GuiButtonTypeRight) {
+            scene_manager_next_scene(uhf_app->scene_manager, UHFSceneStart);
+            consumed = true;
+        } else if(event.event == GuiButtonTypeLeft) {
+            if(!verify_success) {
+                widget_reset(uhf_app->widget);
+                furi_string_reset(temp_str);
+                uhf_worker_stop(uhf_app->worker);
+                uhf_worker_start(
+                    uhf_app->worker,
+                    UHFWorkerStateVerify,
+                    uhf_scene_verify_callback_event,
+                    uhf_app);
+            }
+        } else if(event.event == UHFCustomEventVerifyDone) {
+            if(verify_success) {
+                widget_reset(uhf_app->widget);
+                furi_string_reset(temp_str);
+                UHFResponseData* uhf_response_data = uhf_app->worker->response_data;
+                UHFData* hardware_version = uhf_response_data_get_uhf_data(uhf_response_data, 0);
+                UHFData* software_version = uhf_response_data_get_uhf_data(uhf_response_data, 1);
+                UHFData* manufacturer = uhf_response_data_get_uhf_data(uhf_response_data, 2);
+                uint offset = 6;
+                widget_add_string_element(
+                    uhf_app->widget, 64, 5, AlignCenter, AlignCenter, FontPrimary, "Module Info");
+                // hardware info
+                furi_string_cat_str(temp_str, "HW Version: ");
+                for(int i = 0; i < 10; i++) {
+                    furi_string_cat_printf(temp_str, "%c", hardware_version->data[offset + i]);
+                }
+                widget_add_string_element(
+                    uhf_app->widget,
+                    1,
+                    15,
+                    AlignLeft,
+                    AlignCenter,
+                    FontSecondary,
+                    furi_string_get_cstr(temp_str));
+                furi_string_reset(temp_str);
+                // software info
+                furi_string_cat_str(temp_str, "SW Version: ");
+                for(int i = 0; i < 10; i++) {
+                    furi_string_cat_printf(temp_str, "%c", software_version->data[offset + i]);
+                }
+                widget_add_string_element(
+                    uhf_app->widget,
+                    1,
+                    27,
+                    AlignLeft,
+                    AlignCenter,
+                    FontSecondary,
+                    furi_string_get_cstr(temp_str));
+                furi_string_reset(temp_str);
+                // manufacturer info
+                furi_string_cat_str(temp_str, "Manufacturer: ");
+                for(int i = 0; i < 10; i++) {
+                    furi_string_cat_printf(temp_str, "%c", manufacturer->data[offset + i]);
+                }
+                widget_add_string_element(
+                    uhf_app->widget,
+                    1,
+                    39,
+                    AlignLeft,
+                    AlignCenter,
+                    FontSecondary,
+                    furi_string_get_cstr(temp_str));
+
+                widget_add_button_element(
+                    uhf_app->widget,
+                    GuiButtonTypeRight,
+                    "Continue",
+                    uhf_scene_verify_widget_callback,
+                    uhf_app);
+            } else {
+                widget_add_string_element(
+                    uhf_app->widget,
+                    64,
+                    5,
+                    AlignCenter,
+                    AlignCenter,
+                    FontPrimary,
+                    "No UHF Module found");
+                widget_add_button_element(
+                    uhf_app->widget,
+                    GuiButtonTypeLeft,
+                    "Retry",
+                    uhf_scene_verify_widget_callback,
+                    uhf_app);
+                widget_add_button_element(
+                    uhf_app->widget,
+                    GuiButtonTypeRight,
+                    "Skip",
+                    uhf_scene_verify_widget_callback,
+                    uhf_app);
+            }
+        }
+    }
+    return consumed;
+}
+
+void uhf_scene_verify_on_exit(void* ctx) {
+    UHFApp* uhf_app = ctx;
+    // Clear string
+    furi_string_free(temp_str);
+    // Stop worker
+    uhf_worker_stop(uhf_app->worker);
+    // Clear view
+    // popup_reset(uhf_app->popup);
+    // clear widget
+    widget_reset(uhf_app->widget);
+}

+ 20 - 17
uhf_app.c

@@ -3,6 +3,13 @@
 static const char* uhf_file_header = "Flipper UHF device";
 static const char* uhf_file_header = "Flipper UHF device";
 static const uint32_t uhf_file_version = 1;
 static const uint32_t uhf_file_version = 1;
 
 
+// empty callback
+void empty_rx_callback(UartIrqEvent event, uint8_t data, void* ctx) {
+    UNUSED(event);
+    UNUSED(data);
+    UNUSED(ctx);
+}
+
 char* convertToHexString(const uint8_t* array, size_t length) {
 char* convertToHexString(const uint8_t* array, size_t length) {
     if(array == NULL || length == 0) {
     if(array == NULL || length == 0) {
         return NULL;
         return NULL;
@@ -26,7 +33,7 @@ char* convertToHexString(const uint8_t* array, size_t length) {
     return hexArray;
     return hexArray;
 }
 }
 
 
-bool uhf_save_data(UHFResponseData* uhf_response_data, Storage* storage, const char* filename) {
+bool uhf_save_read_data(UHFResponseData* uhf_response_data, Storage* storage, const char* filename) {
     if(!storage_dir_exists(storage, UHF_APPS_DATA_FOLDER)) {
     if(!storage_dir_exists(storage, UHF_APPS_DATA_FOLDER)) {
         storage_simply_mkdir(storage, UHF_APPS_DATA_FOLDER);
         storage_simply_mkdir(storage, UHF_APPS_DATA_FOLDER);
     }
     }
@@ -45,7 +52,7 @@ bool uhf_save_data(UHFResponseData* uhf_response_data, Storage* storage, const c
     if(!flipper_format_write_header_cstr(file, uhf_file_header, uhf_file_version)) return false;
     if(!flipper_format_write_header_cstr(file, uhf_file_header, uhf_file_version)) return false;
     // write epc bank
     // write epc bank
     if(!flipper_format_write_hex(
     if(!flipper_format_write_hex(
-           file, "EPC", uhf_response_data->data->data, uhf_response_data->data->length))
+           file, "EPC", uhf_response_data->head->data, uhf_response_data->head->length))
         return false;
         return false;
     furi_string_free(temp_str);
     furi_string_free(temp_str);
     flipper_format_free(file);
     flipper_format_free(file);
@@ -170,20 +177,6 @@ void uhf_free(UHFApp* uhf_app) {
     free(uhf_app);
     free(uhf_app);
 }
 }
 
 
-// void uhf_text_store_set(UHFApp* uhf_app, const char* text, ...) {
-//     va_list args;
-//     va_start(args, text);
-
-//     vsnprintf(uhf_app->text_store, sizeof(uhf_app->text_store), text, args);
-
-//     va_end(args);
-// }
-
-// void uhf_text_store_clear(UHFApp* uhf_app) {
-//     memset(uhf_app->text_store, 0, sizeof(uhf_app->text_store));
-// }
-
-//  ==================
 static const NotificationSequence uhf_sequence_blink_start_cyan = {
 static const NotificationSequence uhf_sequence_blink_start_cyan = {
     &message_blink_start_10,
     &message_blink_start_10,
     &message_blink_set_color_cyan,
     &message_blink_set_color_cyan,
@@ -222,9 +215,19 @@ int32_t uhf_app_main(void* ctx) {
     UNUSED(ctx);
     UNUSED(ctx);
     UHFApp* uhf_app = uhf_alloc();
     UHFApp* uhf_app = uhf_alloc();
 
 
-    scene_manager_next_scene(uhf_app->scene_manager, UHFSceneStart);
+    // enable 5v pin
+    furi_hal_power_enable_otg();
+
+    scene_manager_next_scene(uhf_app->scene_manager, UHFSceneVerify);
     view_dispatcher_run(uhf_app->view_dispatcher);
     view_dispatcher_run(uhf_app->view_dispatcher);
 
 
+    // disable 5v pin
+    furi_hal_power_disable_otg();
+
+    // set uart callback to none
+    furi_hal_uart_set_irq_cb(FuriHalUartIdUSART1, empty_rx_callback, NULL);
+
+    // exit app
     uhf_free(uhf_app);
     uhf_free(uhf_app);
     return 0;
     return 0;
 }
 }

+ 2 - 4
uhf_app_i.h

@@ -26,9 +26,6 @@
 #include "uhf_worker.h"
 #include "uhf_worker.h"
 #include <uhf_rfid_icons.h>
 #include <uhf_rfid_icons.h>
 
 
-#define UHF_FILE_HEADER            \
-    "Filetype: Flipper uhf data\n" \
-    "Version: 1"
 #define UHF_TEXT_STORE_SIZE 128
 #define UHF_TEXT_STORE_SIZE 128
 #define UHF_APPS_DATA_FOLDER EXT_PATH("apps_data")
 #define UHF_APPS_DATA_FOLDER EXT_PATH("apps_data")
 #define UHF_APPS_STORAGE_FOLDER \
 #define UHF_APPS_STORAGE_FOLDER \
@@ -40,6 +37,7 @@ enum UHFCustomEvent {
     // Reserve first 100 events for button types and indexes, starting from 0
     // Reserve first 100 events for button types and indexes, starting from 0
     UHFCustomEventReserved = 100,
     UHFCustomEventReserved = 100,
 
 
+    UHFCustomEventVerifyDone,
     UHFCustomEventViewExit,
     UHFCustomEventViewExit,
     UHFCustomEventWorkerExit,
     UHFCustomEventWorkerExit,
     UHFCustomEventByteInputDone,
     UHFCustomEventByteInputDone,
@@ -104,4 +102,4 @@ bool uhf_is_memset(const uint8_t* data, const uint8_t pattern, size_t size);
 
 
 char* convertToHexString(const uint8_t* array, size_t length);
 char* convertToHexString(const uint8_t* array, size_t length);
 
 
-bool uhf_save_data(UHFResponseData* uhf_response_data, Storage* storage, const char* filename);
+bool uhf_save_read_data(UHFResponseData* uhf_response_data, Storage* storage, const char* filename);

+ 37 - 15
uhf_data.c

@@ -32,36 +32,58 @@ void uhf_data_reset(UHFData* uhf_data) {
     uhf_data->start = false;
     uhf_data->start = false;
     uhf_data->end = false;
     uhf_data->end = false;
     uhf_data->length = 0;
     uhf_data->length = 0;
+    uhf_data->next = NULL;
 }
 }
 
 
 void uhf_data_free(UHFData* uhf_data) {
 void uhf_data_free(UHFData* uhf_data) {
-    if(uhf_data != NULL) {
-        while(uhf_data != NULL) {
-            UHFData* next = uhf_data->next;
-            free(uhf_data);
-            uhf_data = next;
-        }
+    if(uhf_data == NULL) return;
+    while(uhf_data != NULL) {
+        UHFData* next = uhf_data->next;
+        free(uhf_data);
+        uhf_data = next;
     }
     }
 }
 }
 
 
 UHFResponseData* uhf_response_data_alloc() {
 UHFResponseData* uhf_response_data_alloc() {
     UHFResponseData* uhf_response_data = (UHFResponseData*)malloc(sizeof(UHFResponseData));
     UHFResponseData* uhf_response_data = (UHFResponseData*)malloc(sizeof(UHFResponseData));
-    uhf_response_data->data = uhf_data_alloc();
-    uhf_response_data->size = 0;
+    uhf_response_data->head = uhf_data_alloc();
+    uhf_response_data->tail = uhf_response_data->head;
+    uhf_response_data->size = 1;
     return uhf_response_data;
     return uhf_response_data;
 }
 }
 
 
-UHFData* add_uhf_data_to_uhf_response_data(UHFResponseData* uhf_response_data) {
-    UHFData* next = uhf_response_data->data;
-    while(next->next != NULL) {
-        next = next->next;
+UHFData* uhf_response_data_add_new_uhf_data(UHFResponseData* uhf_response_data) {
+    UHFData* temp = uhf_response_data->head;
+    while(temp->next != NULL) {
+        temp = temp->next;
     }
     }
-    next->next = uhf_data_alloc();
+    temp->next = uhf_data_alloc();
     uhf_response_data->size++;
     uhf_response_data->size++;
-    return next->next;
+    uhf_response_data->tail = temp->next;
+    return temp->next;
+}
+
+UHFData* uhf_response_data_get_uhf_data(UHFResponseData* uhf_response_data, uint index) {
+    if(uhf_response_data == NULL || uhf_response_data->size <= index) return NULL;
+    UHFData* uhf_data = uhf_response_data->head;
+    if(index == 0) return uhf_data;
+    while(uhf_data != NULL && index >= 1) {
+        uhf_data = uhf_data->next;
+        index--;
+    }
+    return uhf_data;
+}
+
+void uhf_response_data_reset(UHFResponseData* uhf_response_data) {
+    uhf_data_reset(uhf_response_data->head);
+    if(uhf_response_data->size == 1) {
+        return;
+    }
+    uhf_data_free(uhf_response_data->head->next);
+    uhf_response_data->size = 1;
 }
 }
 
 
 void uhf_response_data_free(UHFResponseData* uhf_response_data) {
 void uhf_response_data_free(UHFResponseData* uhf_response_data) {
-    uhf_data_free(uhf_response_data->data);
+    uhf_data_free(uhf_response_data->head);
     free(uhf_response_data);
     free(uhf_response_data);
 }
 }

+ 5 - 2
uhf_data.h

@@ -14,7 +14,8 @@ typedef struct UHFData {
 } UHFData;
 } UHFData;
 
 
 typedef struct UHFResponseData {
 typedef struct UHFResponseData {
-    UHFData* data;
+    UHFData* head;
+    UHFData* tail;
     size_t size;
     size_t size;
 
 
 } UHFResponseData;
 } UHFResponseData;
@@ -25,5 +26,7 @@ void uhf_data_reset(UHFData* uhf_data);
 void uhf_data_free(UHFData* uhf_data);
 void uhf_data_free(UHFData* uhf_data);
 
 
 UHFResponseData* uhf_response_data_alloc();
 UHFResponseData* uhf_response_data_alloc();
-UHFData* add_uhf_data_to_uhf_response_data(UHFResponseData* uhf_response_data);
+UHFData* uhf_response_data_add_new_uhf_data(UHFResponseData* uhf_response_data);
+UHFData* uhf_response_data_get_uhf_data(UHFResponseData* uhf_response_data, uint index);
+void uhf_response_data_reset(UHFResponseData* uhf_response_data);
 void uhf_response_data_free(UHFResponseData* uhf_response_data);
 void uhf_response_data_free(UHFResponseData* uhf_response_data);

+ 53 - 11
uhf_worker.c

@@ -1,32 +1,74 @@
 #include "uhf_worker.h"
 #include "uhf_worker.h"
 #include "uhf_cmd.h"
 #include "uhf_cmd.h"
 
 
-void single_poll_rx_callback(UartIrqEvent event, uint8_t data, void* ctx) {
+// uart callback functions
+void module_rx_callback(UartIrqEvent event, uint8_t data, void* ctx) {
     UNUSED(event);
     UNUSED(event);
-    UHFResponseData* response_data = ctx;
-    UHFData* first_data = response_data->data;
-    uhf_data_append(first_data, data);
+    UHFData* uhf_data = ctx;
+    uhf_data_append(uhf_data, data);
+    // FURI_LOG_E("module_rx_callback", "%02x", data);
+}
+
+// yrm100 module commands
+UHFWorkerEvent verify_module_connected(UHFWorker* uhf_worker) {
+    UHFResponseData* uhf_response_data = uhf_worker->response_data;
+    uhf_response_data_reset(uhf_response_data);
+    FURI_LOG_E("log", "freeing done");
+    UHFData* hardware_version = uhf_response_data->head;
+    UHFData* software_version = uhf_response_data_add_new_uhf_data(uhf_response_data);
+    UHFData* manufacturer = uhf_response_data_add_new_uhf_data(uhf_response_data);
+    FURI_LOG_E("log", "alloc done");
+    furi_hal_uart_set_br(FuriHalUartIdUSART1, DEFAULT_BAUD_RATE);
+    // read hardware version
+    furi_hal_uart_set_irq_cb(FuriHalUartIdUSART1, module_rx_callback, hardware_version);
+    furi_hal_uart_tx(FuriHalUartIdUSART1, CMD_HARDWARE_VERSION.cmd, CMD_HARDWARE_VERSION.length);
+    furi_delay_ms(150);
+    // read software version
+    furi_hal_uart_set_irq_cb(FuriHalUartIdUSART1, module_rx_callback, software_version);
+    furi_hal_uart_tx(FuriHalUartIdUSART1, CMD_SOFTWARE_VERSION.cmd, CMD_SOFTWARE_VERSION.length);
+    furi_delay_ms(150);
+    // read manufacturer
+    furi_hal_uart_set_irq_cb(FuriHalUartIdUSART1, module_rx_callback, manufacturer);
+    furi_hal_uart_tx(FuriHalUartIdUSART1, CMD_MANUFACTURERS.cmd, CMD_MANUFACTURERS.length);
+    furi_delay_ms(150);
+    FURI_LOG_E("log", "done sending tx");
+    if(!hardware_version->end || !software_version->end || !manufacturer->end) {
+        return UHFWorkerEventFail;
+    }
+    return UHFWorkerEventSuccess;
 }
 }
 
 
 UHFWorkerEvent read_single_card(UHFWorker* uhf_worker) {
 UHFWorkerEvent read_single_card(UHFWorker* uhf_worker) {
-    UHFResponseData* uhf_response_data = uhf_worker->data;
+    UHFResponseData* uhf_response_data = uhf_worker->response_data;
+    UHFData* uhf_data = uhf_response_data->head;
     furi_hal_uart_set_br(FuriHalUartIdUSART1, DEFAULT_BAUD_RATE);
     furi_hal_uart_set_br(FuriHalUartIdUSART1, DEFAULT_BAUD_RATE);
-    furi_hal_uart_set_irq_cb(FuriHalUartIdUSART1, single_poll_rx_callback, uhf_response_data);
-    UHFData* uhf_data = uhf_response_data->data;
+    furi_hal_uart_set_irq_cb(FuriHalUartIdUSART1, module_rx_callback, uhf_data);
     uhf_data_reset(uhf_data);
     uhf_data_reset(uhf_data);
-    while(!uhf_data->end) {
+    while(true) {
         furi_hal_uart_tx(FuriHalUartIdUSART1, CMD_SINGLE_POLLING.cmd, CMD_SINGLE_POLLING.length);
         furi_hal_uart_tx(FuriHalUartIdUSART1, CMD_SINGLE_POLLING.cmd, CMD_SINGLE_POLLING.length);
         furi_delay_ms(100);
         furi_delay_ms(100);
         if(uhf_worker->state == UHFWorkerStateStop) {
         if(uhf_worker->state == UHFWorkerStateStop) {
             return UHFWorkerEventAborted;
             return UHFWorkerEventAborted;
         }
         }
+        if(uhf_data->end) {
+            // before breaking, check if the response is not an error
+            // index 1 = response type, index 5 = parameter
+            if(uhf_data->data[1] == 0x01 && uhf_data->data[5] == 0x15) {
+                continue;
+            } else if(uhf_data->data[1] == 0x02)
+                break; // success read
+        }
     }
     }
     return UHFWorkerEventSuccess;
     return UHFWorkerEventSuccess;
 }
 }
 
 
 int32_t uhf_worker_task(void* ctx) {
 int32_t uhf_worker_task(void* ctx) {
     UHFWorker* uhf_worker = ctx;
     UHFWorker* uhf_worker = ctx;
-    if(uhf_worker->state == UHFWorkerStateDetect) {
+    if(uhf_worker->state == UHFWorkerStateVerify) {
+        UHFWorkerEvent event = verify_module_connected(uhf_worker);
+        uhf_worker->callback(event, uhf_worker->ctx);
+    }
+    if(uhf_worker->state == UHFWorkerStateDetectSingle) {
         UHFWorkerEvent event = read_single_card(uhf_worker);
         UHFWorkerEvent event = read_single_card(uhf_worker);
         uhf_worker->callback(event, uhf_worker->ctx);
         uhf_worker->callback(event, uhf_worker->ctx);
     }
     }
@@ -36,7 +78,7 @@ int32_t uhf_worker_task(void* ctx) {
 UHFWorker* uhf_worker_alloc() {
 UHFWorker* uhf_worker_alloc() {
     UHFWorker* uhf_worker = (UHFWorker*)malloc(sizeof(UHFWorker));
     UHFWorker* uhf_worker = (UHFWorker*)malloc(sizeof(UHFWorker));
     uhf_worker->thread = furi_thread_alloc_ex("UHFWorker", 8 * 1024, uhf_worker_task, uhf_worker);
     uhf_worker->thread = furi_thread_alloc_ex("UHFWorker", 8 * 1024, uhf_worker_task, uhf_worker);
-    uhf_worker->data = uhf_response_data_alloc();
+    uhf_worker->response_data = uhf_response_data_alloc();
     uhf_worker->callback = NULL;
     uhf_worker->callback = NULL;
     uhf_worker->ctx = NULL;
     uhf_worker->ctx = NULL;
     return uhf_worker;
     return uhf_worker;
@@ -70,6 +112,6 @@ void uhf_worker_stop(UHFWorker* uhf_worker) {
 void uhf_worker_free(UHFWorker* uhf_worker) {
 void uhf_worker_free(UHFWorker* uhf_worker) {
     furi_assert(uhf_worker);
     furi_assert(uhf_worker);
     furi_thread_free(uhf_worker->thread);
     furi_thread_free(uhf_worker->thread);
-    uhf_response_data_free(uhf_worker->data);
+    uhf_response_data_free(uhf_worker->response_data);
     free(uhf_worker);
     free(uhf_worker);
 }
 }

+ 4 - 3
uhf_worker.h

@@ -9,9 +9,10 @@ typedef enum {
     UHFWorkerStateNone,
     UHFWorkerStateNone,
     UHFWorkerStateBroken,
     UHFWorkerStateBroken,
     UHFWorkerStateReady,
     UHFWorkerStateReady,
+    UHFWorkerStateVerify,
     // Main worker states
     // Main worker states
-    UHFWorkerStateDetect,
-    UHFWorkerStateWrite,
+    UHFWorkerStateDetectSingle,
+    UHFWorkerStateWriteSingle,
     UHFWorkerStateWriteKey,
     UHFWorkerStateWriteKey,
     // Transition
     // Transition
     UHFWorkerStateStop,
     UHFWorkerStateStop,
@@ -29,7 +30,7 @@ typedef void (*UHFWorkerCallback)(UHFWorkerEvent event, void* ctx);
 
 
 typedef struct UHFWorker {
 typedef struct UHFWorker {
     FuriThread* thread;
     FuriThread* thread;
-    UHFResponseData* data;
+    UHFResponseData* response_data;
     UHFWorkerCallback callback;
     UHFWorkerCallback callback;
     UHFWorkerState state;
     UHFWorkerState state;
     void* ctx;
     void* ctx;