Przeglądaj źródła

Merge uhf_rfid from https://github.com/frux-c/uhf_rfid

Willy-JL 1 rok temu
rodzic
commit
c34786b376

+ 2 - 2
uhf_rfid/application.fam

@@ -8,9 +8,9 @@ App(
         "storage",
         "storage",
         "gui",
         "gui",
     ],
     ],
-    stack_size=8 * 1024,
+    stack_size=10 * 1024,
     order=30,
     order=30,
-    fap_icon="uhf_10px.png",
+    fap_icon="icons/uhf_10px.png",
     fap_category="GPIO",
     fap_category="GPIO",
     fap_icon_assets="icons",
     fap_icon_assets="icons",
     fap_icon_assets_symbol="uhf_rfid",
     fap_icon_assets_symbol="uhf_rfid",

BIN
uhf_rfid/icons/DolphinMafia_115x62.png


BIN
uhf_rfid/icons/DolphinNice_96x59.png


BIN
uhf_rfid/icons/Nfc_10px.png


BIN
uhf_rfid/icons/RFIDDolphinReceive_97x61.png


BIN
uhf_rfid/icons/RFIDDolphinSend_97x61.png


+ 0 - 0
uhf_rfid/uhf_10px.png → uhf_rfid/icons/uhf_10px.png


+ 1 - 3
uhf_rfid/scenes/uhf_scene_save_name.c

@@ -1,5 +1,5 @@
 #include "../uhf_app_i.h"
 #include "../uhf_app_i.h"
-#include <toolbox/name_generator.h>
+#include <lib/toolbox/name_generator.h>
 #include <gui/modules/validators.h>
 #include <gui/modules/validators.h>
 #include <toolbox/path.h>
 #include <toolbox/path.h>
 
 
@@ -14,9 +14,7 @@ void uhf_scene_save_name_on_enter(void* context) {
 
 
     // Setup view
     // Setup view
     TextInput* text_input = uhf_app->text_input;
     TextInput* text_input = uhf_app->text_input;
-
     name_generator_make_auto(uhf_app->text_store, sizeof(uhf_app->text_store), "UHF");
     name_generator_make_auto(uhf_app->text_store, sizeof(uhf_app->text_store), "UHF");
-
     text_input_set_header_text(text_input, "Name the tag");
     text_input_set_header_text(text_input, "Name the tag");
     text_input_set_result_callback(
     text_input_set_result_callback(
         text_input,
         text_input,

+ 5 - 5
uhf_rfid/scenes/uhf_scene_settings.c

@@ -2,15 +2,15 @@
 #include "../uhf_module.h"
 #include "../uhf_module.h"
 
 
 void uhf_settings_set_module_baudrate(VariableItem* item) {
 void uhf_settings_set_module_baudrate(VariableItem* item) {
-    M100Module* uhf_module = variable_item_get_context(item);
+    M100Module* module = variable_item_get_context(item);
     uint8_t index = variable_item_get_current_value_index(item);
     uint8_t index = variable_item_get_current_value_index(item);
     if(index >= BAUD_RATES_COUNT) {
     if(index >= BAUD_RATES_COUNT) {
         return;
         return;
     }
     }
     uint32_t baudrate = BAUD_RATES[index];
     uint32_t baudrate = BAUD_RATES[index];
-    m100_set_baudrate(uhf_module, baudrate);
+    m100_set_baudrate(module, baudrate);
     char text_buf[10];
     char text_buf[10];
-    snprintf(text_buf, sizeof(text_buf), "%lu", uhf_module->baudrate);
+    snprintf(text_buf, sizeof(text_buf), "%lu", module->uart->baudrate);
     variable_item_set_current_value_text(item, text_buf);
     variable_item_set_current_value_text(item, text_buf);
 }
 }
 
 
@@ -40,7 +40,7 @@ void uhf_settings_set_module_working_region(VariableItem* item) {
 
 
 uint8_t uhf_settings_get_module_baudrate_index(M100Module* module) {
 uint8_t uhf_settings_get_module_baudrate_index(M100Module* module) {
     for(uint8_t i = 0; i < BAUD_RATES_COUNT; i++) {
     for(uint8_t i = 0; i < BAUD_RATES_COUNT; i++) {
-        if(BAUD_RATES[i] == module->baudrate) {
+        if(BAUD_RATES[i] == module->uart->baudrate) {
             return i;
             return i;
         }
         }
     }
     }
@@ -73,7 +73,7 @@ void uhf_scene_settings_on_enter(void* ctx) {
 
 
     uint8_t value_index = uhf_settings_get_module_baudrate_index(uhf_module);
     uint8_t value_index = uhf_settings_get_module_baudrate_index(uhf_module);
     char text_buf[10];
     char text_buf[10];
-    snprintf(text_buf, sizeof(text_buf), "%lu", uhf_module->baudrate);
+    snprintf(text_buf, sizeof(text_buf), "%lu", uhf_module->uart->baudrate);
     item = variable_item_list_add(
     item = variable_item_list_add(
         variable_item_list,
         variable_item_list,
         "Baudrate:",
         "Baudrate:",

+ 1 - 6
uhf_rfid/uhf_app.c

@@ -201,7 +201,6 @@ int32_t uhf_app_main(void* ctx) {
     expansion_disable(expansion);
     expansion_disable(expansion);
 
 
     UHFApp* uhf_app = uhf_alloc();
     UHFApp* uhf_app = uhf_alloc();
-
     // enable 5v pin
     // enable 5v pin
     uint8_t attempts = 0;
     uint8_t attempts = 0;
     bool otg_was_enabled = furi_hal_power_is_otg_enabled();
     bool otg_was_enabled = furi_hal_power_is_otg_enabled();
@@ -209,17 +208,13 @@ int32_t uhf_app_main(void* ctx) {
         furi_hal_power_enable_otg();
         furi_hal_power_enable_otg();
         furi_delay_ms(10);
         furi_delay_ms(10);
     }
     }
-    furi_delay_ms(200);
-    // init pin a2
-    // furi_hal_gpio_init_simple(&gpio_ext_pa7, GpioModeOutputPushPull);
+    // enter app
     scene_manager_next_scene(uhf_app->scene_manager, UHFSceneModuleInfo);
     scene_manager_next_scene(uhf_app->scene_manager, UHFSceneModuleInfo);
     view_dispatcher_run(uhf_app->view_dispatcher);
     view_dispatcher_run(uhf_app->view_dispatcher);
-
     // disable 5v pin
     // disable 5v pin
     if(furi_hal_power_is_otg_enabled() && !otg_was_enabled) {
     if(furi_hal_power_is_otg_enabled() && !otg_was_enabled) {
         furi_hal_power_disable_otg();
         furi_hal_power_disable_otg();
     }
     }
-    // furi_hal_gpio_disable_int_callback()
     // exit app
     // exit app
     uhf_free(uhf_app);
     uhf_free(uhf_app);
 
 

+ 0 - 2
uhf_rfid/uhf_app_i.h

@@ -27,8 +27,6 @@
 
 
 #include <uhf_rfid_icons.h>
 #include <uhf_rfid_icons.h>
 
 
-#include <assets_icons.h>
-
 #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

+ 12 - 8
uhf_rfid/uhf_buffer.c

@@ -2,7 +2,7 @@
 #include <stdlib.h>
 #include <stdlib.h>
 #include <string.h>
 #include <string.h>
 
 
-Buffer* buffer_alloc(size_t initial_capacity) {
+Buffer* uhf_buffer_alloc(size_t initial_capacity) {
     Buffer* buf = (Buffer*)malloc(sizeof(Buffer));
     Buffer* buf = (Buffer*)malloc(sizeof(Buffer));
     buf->data = (uint8_t*)malloc(sizeof(uint8_t) * initial_capacity);
     buf->data = (uint8_t*)malloc(sizeof(uint8_t) * initial_capacity);
     if(!buf->data) {
     if(!buf->data) {
@@ -14,7 +14,7 @@ Buffer* buffer_alloc(size_t initial_capacity) {
     return buf;
     return buf;
 }
 }
 
 
-bool buffer_append_single(Buffer* buf, uint8_t data) {
+bool uhf_buffer_append_single(Buffer* buf, uint8_t data) {
     if(buf->closed) return false;
     if(buf->closed) return false;
     if(buf->size + 1 > buf->capacity) {
     if(buf->size + 1 > buf->capacity) {
         size_t new_capacity = buf->capacity * 2;
         size_t new_capacity = buf->capacity * 2;
@@ -27,7 +27,7 @@ bool buffer_append_single(Buffer* buf, uint8_t data) {
     return true;
     return true;
 }
 }
 
 
-bool buffer_append(Buffer* buf, uint8_t* data, size_t data_size) {
+bool uhf_buffer_append(Buffer* buf, uint8_t* data, size_t data_size) {
     if(buf->closed) return false;
     if(buf->closed) return false;
     if(buf->size + data_size > buf->capacity) {
     if(buf->size + data_size > buf->capacity) {
         size_t new_capacity = buf->capacity * 2;
         size_t new_capacity = buf->capacity * 2;
@@ -43,19 +43,23 @@ bool buffer_append(Buffer* buf, uint8_t* data, size_t data_size) {
     return true;
     return true;
 }
 }
 
 
-uint8_t* buffer_get_data(Buffer* buf) {
+uint8_t* uhf_buffer_get_data(Buffer* buf) {
     return buf->data;
     return buf->data;
 }
 }
 
 
-size_t buffer_get_size(Buffer* buf) {
+size_t uhf_buffer_get_size(Buffer* buf) {
     return buf->size;
     return buf->size;
 }
 }
 
 
-void buffer_close(Buffer* buf) {
+bool uhf_is_buffer_closed(Buffer* buf) {
+    return buf->closed;
+}
+
+void uhf_buffer_close(Buffer* buf) {
     buf->closed = true;
     buf->closed = true;
 }
 }
 
 
-void buffer_reset(Buffer* buf) {
+void uhf_buffer_reset(Buffer* buf) {
     for(size_t i = 0; i < MAX_BUFFER_SIZE; i++) {
     for(size_t i = 0; i < MAX_BUFFER_SIZE; i++) {
         buf->data[i] = 0;
         buf->data[i] = 0;
     }
     }
@@ -63,7 +67,7 @@ void buffer_reset(Buffer* buf) {
     buf->closed = false;
     buf->closed = false;
 }
 }
 
 
-void buffer_free(Buffer* buf) {
+void uhf_buffer_free(Buffer* buf) {
     free(buf->data);
     free(buf->data);
     free(buf);
     free(buf);
 }
 }

+ 10 - 8
uhf_rfid/uhf_buffer.h

@@ -12,11 +12,13 @@ typedef struct Buffer {
     bool closed;
     bool closed;
 } Buffer;
 } Buffer;
 
 
-Buffer* buffer_alloc(size_t inital_capacity);
-bool buffer_append_single(Buffer* buf, uint8_t value);
-bool buffer_append(Buffer* buf, uint8_t* data, size_t size);
-uint8_t* buffer_get_data(Buffer* buf);
-size_t buffer_get_size(Buffer* buf);
-void buffer_close(Buffer* buf);
-void buffer_reset(Buffer* buf);
-void buffer_free(Buffer* buf);
+Buffer* uhf_buffer_alloc(size_t inital_capacity);
+bool uhf_buffer_append_single(Buffer* buf, uint8_t value);
+bool uhf_buffer_append(Buffer* buf, uint8_t* data, size_t size);
+
+uint8_t* uhf_buffer_get_data(Buffer* buf);
+size_t uhf_buffer_get_size(Buffer* buf);
+bool uhf_is_buffer_closed(Buffer* buf);
+void uhf_buffer_close(Buffer* buf);
+void uhf_buffer_reset(Buffer* buf);
+void uhf_buffer_free(Buffer* buf);

+ 1 - 104
uhf_rfid/uhf_device.c

@@ -3,14 +3,10 @@
 #include <flipper_format/flipper_format.h>
 #include <flipper_format/flipper_format.h>
 #include <uhf_rfid_icons.h>
 #include <uhf_rfid_icons.h>
 
 
-#include <assets_icons.h>
-
 #define TAG "UHFDevice"
 #define TAG "UHFDevice"
 
 
 static const char* uhf_file_header = "Flipper UHF RFID device";
 static const char* uhf_file_header = "Flipper UHF RFID device";
 static const uint32_t uhf_file_version = 1;
 static const uint32_t uhf_file_version = 1;
-// static const uint8_t bank_data_start = 20;
-// static const uint8_t bank_data_length = 16;
 
 
 UHFDevice* uhf_device_alloc() {
 UHFDevice* uhf_device_alloc() {
     UHFDevice* uhf_device = malloc(sizeof(UHFDevice));
     UHFDevice* uhf_device = malloc(sizeof(UHFDevice));
@@ -180,15 +176,6 @@ static bool uhf_device_load_data(UHFDevice* dev, FuriString* path, bool show_dia
     return parsed;
     return parsed;
 }
 }
 
 
-// void picopass_device_clear(UHFDevice* dev) {
-//     furi_assert(dev);
-
-//     picopass_device_data_clear(&dev->dev_data);
-//     memset(&dev->dev_data, 0, sizeof(dev->dev_data));
-//     dev->format = PicopassDeviceSaveFormatHF;
-//     furi_string_reset(dev->load_path);
-// }
-
 void uhf_device_free(UHFDevice* uhf_dev) {
 void uhf_device_free(UHFDevice* uhf_dev) {
     furi_assert(uhf_dev);
     furi_assert(uhf_dev);
     furi_record_close(RECORD_STORAGE);
     furi_record_close(RECORD_STORAGE);
@@ -226,16 +213,6 @@ bool uhf_file_select(UHFDevice* dev) {
     return res;
     return res;
 }
 }
 
 
-// void uhf_device_data_clear(UHFDevice* dev_data) {
-//     for(size_t i = 0; i < PICOPASS_MAX_APP_LIMIT; i++) {
-//         memset(dev_data->AA1[i].data, 0, sizeof(dev_data->AA1[i].data));
-//     }
-//     dev_data->pacs.legacy = false;
-//     dev_data->pacs.se_enabled = false;
-//     dev_data->pacs.elite_kdf = false;
-//     dev_data->pacs.pin_length = 0;
-// }
-
 bool uhf_device_delete(UHFDevice* dev, bool use_load_path) {
 bool uhf_device_delete(UHFDevice* dev, bool use_load_path) {
     furi_assert(dev);
     furi_assert(dev);
 
 
@@ -267,84 +244,4 @@ void uhf_device_set_loading_callback(UHFDevice* dev, UHFLoadingCallback callback
 
 
     dev->loading_cb = callback;
     dev->loading_cb = callback;
     dev->loading_cb_ctx = context;
     dev->loading_cb_ctx = context;
-}
-
-// ReturnCode picopass_device_decrypt(uint8_t* enc_data, uint8_t* dec_data) {
-//     uint8_t key[32] = {0};
-//     memcpy(key, picopass_iclass_decryptionkey, sizeof(picopass_iclass_decryptionkey));
-//     mbedtls_des3_context ctx;
-//     mbedtls_des3_init(&ctx);
-//     mbedtls_des3_set2key_dec(&ctx, key);
-//     mbedtls_des3_crypt_ecb(&ctx, enc_data, dec_data);
-//     mbedtls_des3_free(&ctx);
-//     return ERR_NONE;
-// }
-
-// ReturnCode picopass_device_parse_credential(PicopassBlock* AA1, PicopassPacs* pacs) {
-//     ReturnCode err;
-
-//     pacs->biometrics = AA1[6].data[4];
-//     pacs->pin_length = AA1[6].data[6] & 0x0F;
-//     pacs->encryption = AA1[6].data[7];
-
-//     if(pacs->encryption == PicopassDeviceEncryption3DES) {
-//         FURI_LOG_D(TAG, "3DES Encrypted");
-//         err = picopass_device_decrypt(AA1[7].data, pacs->credential);
-//         if(err != ERR_NONE) {
-//             FURI_LOG_E(TAG, "decrypt error %d", err);
-//             return err;
-//         }
-
-//         err = picopass_device_decrypt(AA1[8].data, pacs->pin0);
-//         if(err != ERR_NONE) {
-//             FURI_LOG_E(TAG, "decrypt error %d", err);
-//             return err;
-//         }
-
-//         err = picopass_device_decrypt(AA1[9].data, pacs->pin1);
-//         if(err != ERR_NONE) {
-//             FURI_LOG_E(TAG, "decrypt error %d", err);
-//             return err;
-//         }
-//     } else if(pacs->encryption == PicopassDeviceEncryptionNone) {
-//         FURI_LOG_D(TAG, "No Encryption");
-//         memcpy(pacs->credential, AA1[7].data, PICOPASS_BLOCK_LEN);
-//         memcpy(pacs->pin0, AA1[8].data, PICOPASS_BLOCK_LEN);
-//         memcpy(pacs->pin1, AA1[9].data, PICOPASS_BLOCK_LEN);
-//     } else if(pacs->encryption == PicopassDeviceEncryptionDES) {
-//         FURI_LOG_D(TAG, "DES Encrypted");
-//     } else {
-//         FURI_LOG_D(TAG, "Unknown encryption");
-//     }
-
-//     pacs->sio = (AA1[10].data[0] == 0x30); // rough check
-
-//     return ERR_NONE;
-// }
-
-// ReturnCode picopass_device_parse_wiegand(uint8_t* data, PicopassWiegandRecord* record) {
-//     uint32_t* halves = (uint32_t*)data;
-//     if(halves[0] == 0) {
-//         uint8_t leading0s = __builtin_clz(REVERSE_BYTES_U32(halves[1]));
-//         record->bitLength = 31 - leading0s;
-//     } else {
-//         uint8_t leading0s = __builtin_clz(REVERSE_BYTES_U32(halves[0]));
-//         record->bitLength = 63 - leading0s;
-//     }
-//     FURI_LOG_D(TAG, "bitLength: %d", record->bitLength);
-
-//     if(record->bitLength == 26) {
-//         uint8_t* v4 = data + 4;
-//         uint32_t bot = v4[3] | (v4[2] << 8) | (v4[1] << 16) | (v4[0] << 24);
-
-//         record->CardNumber = (bot >> 1) & 0xFFFF;
-//         record->FacilityCode = (bot >> 17) & 0xFF;
-//         FURI_LOG_D(TAG, "FC: %u CN: %u", record->FacilityCode, record->CardNumber);
-//         record->valid = true;
-//     } else {
-//         record->CardNumber = 0;
-//         record->FacilityCode = 0;
-//         record->valid = false;
-//     }
-//     return ERR_NONE;
-// }
+}

+ 45 - 69
uhf_rfid/uhf_module.c

@@ -2,33 +2,23 @@
 #include "uhf_module_cmd.h"
 #include "uhf_module_cmd.h"
 
 
 #define DELAY_MS 100
 #define DELAY_MS 100
-#define WAIT_TICK 8000 // max wait time in between each byte
-
-volatile uint16_t tick = 0;
-
-void rx_callback(FuriHalSerialHandle* handle, FuriHalSerialRxEvent event, void* ctx) {
-    UNUSED(event);
-    Buffer* buffer = ctx;
-    if(buffer->closed) return; // buffer closed
-    if(event == FuriHalSerialRxEventData) {
-        uint8_t data = furi_hal_serial_async_rx(handle);
-        buffer_append_single(buffer, data); // append data
-        if(data == FRAME_END) buffer_close(buffer); // end of frame
-        tick = WAIT_TICK; // reset tick
-    }
-}
+#define WAIT_TICK 4000 // max wait time in between each byte
 
 
 static M100ResponseType setup_and_send_rx(M100Module* module, uint8_t* cmd, size_t cmd_length) {
 static M100ResponseType setup_and_send_rx(M100Module* module, uint8_t* cmd, size_t cmd_length) {
-    buffer_reset(module->buf);
-    tick = WAIT_TICK;
-    furi_hal_serial_tx(module->serial_handle, cmd, cmd_length);
-    while(--tick) {
-        furi_delay_us(5);
+    UHFUart* uart = module->uart;
+    Buffer* buffer = uart->buffer;
+    // clear buffer
+    uhf_buffer_reset(buffer);
+    // send cmd
+    uhf_uart_send_wait(uart, cmd, cmd_length);
+    // wait for response by polling
+    while(!uhf_is_buffer_closed(buffer) && !uhf_uart_tick(uart)) {
     }
     }
-    buffer_close(module->buf);
+    // reset tick
+    uhf_uart_tick_reset(uart);
     // Validation Checks
     // Validation Checks
-    uint8_t* data = buffer_get_data(module->buf);
-    size_t length = buffer_get_size(module->buf);
+    uint8_t* data = uhf_buffer_get_data(buffer);
+    size_t length = uhf_buffer_get_size(buffer);
     // check if size > 0
     // check if size > 0
     if(!length) return M100EmptyResponse;
     if(!length) return M100EmptyResponse;
     // check if data is valid
     // check if data is valid
@@ -44,30 +34,24 @@ M100ModuleInfo* m100_module_info_alloc() {
 }
 }
 
 
 void m100_module_info_free(M100ModuleInfo* module_info) {
 void m100_module_info_free(M100ModuleInfo* module_info) {
-    free(module_info->hw_version);
-    free(module_info->sw_version);
-    free(module_info->manufacturer);
+    if(module_info->hw_version != NULL) free(module_info->hw_version);
+    if(module_info->sw_version != NULL) free(module_info->sw_version);
+    if(module_info->manufacturer != NULL) free(module_info->manufacturer);
     free(module_info);
     free(module_info);
 }
 }
+
 M100Module* m100_module_alloc() {
 M100Module* m100_module_alloc() {
     M100Module* module = (M100Module*)malloc(sizeof(M100Module));
     M100Module* module = (M100Module*)malloc(sizeof(M100Module));
-    module->info = m100_module_info_alloc();
-    module->buf = buffer_alloc(MAX_BUFFER_SIZE);
-    module->baudrate = DEFAULT_BAUDRATE;
     module->transmitting_power = DEFAULT_TRANSMITTING_POWER;
     module->transmitting_power = DEFAULT_TRANSMITTING_POWER;
     module->region = DEFAULT_WORKING_REGION;
     module->region = DEFAULT_WORKING_REGION;
-    module->serial_handle = furi_hal_serial_control_acquire(FuriHalSerialIdUsart);
-    furi_check(module->serial_handle);
-    furi_hal_serial_init(module->serial_handle, module->baudrate);
-    furi_hal_serial_async_rx_start(module->serial_handle, rx_callback, module->buf, false);
+    module->info = m100_module_info_alloc();
+    module->uart = uhf_uart_alloc();
     return module;
     return module;
 }
 }
 
 
 void m100_module_free(M100Module* module) {
 void m100_module_free(M100Module* module) {
-    furi_hal_serial_deinit(module->serial_handle);
-    furi_hal_serial_control_release(module->serial_handle);
     m100_module_info_free(module->info);
     m100_module_info_free(module->info);
-    buffer_free(module->buf);
+    uhf_uart_free(module->uart);
     free(module);
     free(module);
 }
 }
 
 
@@ -100,8 +84,8 @@ uint16_t crc16_genibus(const uint8_t* data, size_t length) {
 }
 }
 
 
 char* _m100_info_helper(M100Module* module, char** info) {
 char* _m100_info_helper(M100Module* module, char** info) {
-    if(!buffer_get_size(module->buf)) return NULL;
-    uint8_t* data = buffer_get_data(module->buf);
+    if(!uhf_buffer_get_size(module->uart->buffer)) return NULL;
+    uint8_t* data = uhf_buffer_get_data(module->uart->buffer);
     uint16_t payload_len = data[3];
     uint16_t payload_len = data[3];
     payload_len = (payload_len << 8) + data[4];
     payload_len = (payload_len << 8) + data[4];
     FuriString* temp_str = furi_string_alloc();
     FuriString* temp_str = furi_string_alloc();
@@ -137,8 +121,7 @@ M100ResponseType m100_single_poll(M100Module* module, UHFTag* uhf_tag) {
     M100ResponseType rp_type =
     M100ResponseType rp_type =
         setup_and_send_rx(module, (uint8_t*)&CMD_SINGLE_POLLING.cmd[0], CMD_SINGLE_POLLING.length);
         setup_and_send_rx(module, (uint8_t*)&CMD_SINGLE_POLLING.cmd[0], CMD_SINGLE_POLLING.length);
     if(rp_type != M100SuccessResponse) return rp_type;
     if(rp_type != M100SuccessResponse) return rp_type;
-    uint8_t* data = buffer_get_data(module->buf);
-    size_t length = buffer_get_size(module->buf);
+    uint8_t* data = uhf_buffer_get_data(module->uart->buffer);
     uint16_t pc = data[6];
     uint16_t pc = data[6];
     uint16_t crc = 0;
     uint16_t crc = 0;
     // mask out epc length from protocol control
     // mask out epc length from protocol control
@@ -152,8 +135,6 @@ M100ResponseType m100_single_poll(M100Module* module, UHFTag* uhf_tag) {
     crc = data[8 + epc_len];
     crc = data[8 + epc_len];
     crc <<= 8;
     crc <<= 8;
     crc += data[8 + epc_len + 1];
     crc += data[8 + epc_len + 1];
-    // validate checksum
-    if(checksum(data + 1, length - 3) != data[length - 2]) return M100ValidationFail;
     // validate crc
     // validate crc
     if(crc16_genibus(data + 6, epc_len + 2) != crc) return M100ValidationFail;
     if(crc16_genibus(data + 6, epc_len + 2) != crc) return M100ValidationFail;
     uhf_tag_set_epc_pc(uhf_tag, pc);
     uhf_tag_set_epc_pc(uhf_tag, pc);
@@ -192,25 +173,26 @@ M100ResponseType m100_set_select(M100Module* module, UHFTag* uhf_tag) {
     // end frame
     // end frame
     cmd[cmd_length - 1] = FRAME_END;
     cmd[cmd_length - 1] = FRAME_END;
 
 
-    setup_and_send_rx(module, cmd, 12 + mask_length_bytes + 3);
+    M100ResponseType rp_type = setup_and_send_rx(module, cmd, 12 + mask_length_bytes + 3);
+
+    if(rp_type != M100SuccessResponse) return rp_type;
 
 
-    uint8_t* data = buffer_get_data(module->buf);
-    if(checksum(data + 1, 5) != data[6]) return M100ValidationFail; // error in rx
+    uint8_t* data = uhf_buffer_get_data(module->uart->buffer);
     if(data[5] != 0x00) return M100ValidationFail; // error if not 0
     if(data[5] != 0x00) return M100ValidationFail; // error if not 0
 
 
     return M100SuccessResponse;
     return M100SuccessResponse;
 }
 }
 
 
 UHFTag* m100_get_select_param(M100Module* module) {
 UHFTag* m100_get_select_param(M100Module* module) {
-    buffer_reset(module->buf);
-    // furi_hal_uart_set_irq_cb(FuriHalUartIdLPUART1, rx_callback, module->buf);
-    furi_hal_serial_tx(
-        module->serial_handle,
-        (uint8_t*)&CMD_GET_SELECT_PARAMETER.cmd,
-        CMD_GET_SELECT_PARAMETER.length);
-    furi_delay_ms(DELAY_MS);
+    uhf_buffer_reset(module->uart->buffer);
+    // furi_hal_uart_set_irq_cb(FuriHalUartIdLPUART1, rx_callback, module->uart->buffer);
+    // furi_hal_uart_tx(
+    //     FuriHalUartIdUSART1,
+    //     (uint8_t*)&CMD_GET_SELECT_PARAMETER.cmd,
+    //     CMD_GET_SELECT_PARAMETER.length);
+    // furi_delay_ms(DELAY_MS);
     // UHFTag* uhf_tag = uhf_tag_alloc();
     // UHFTag* uhf_tag = uhf_tag_alloc();
-    // uint8_t* data = buffer_get_data(module->buf);
+    // uint8_t* data = buffer_get_data(module->uart->buffer);
     // size_t mask_length =
     // size_t mask_length =
     // uhf_tag_set_epc(uhf_tag, data + 12, )
     // uhf_tag_set_epc(uhf_tag, data + 12, )
     // TODO : implement
     // TODO : implement
@@ -246,7 +228,7 @@ M100ResponseType m100_read_label_data_storage(
     M100ResponseType rp_type = setup_and_send_rx(module, cmd, cmd_length);
     M100ResponseType rp_type = setup_and_send_rx(module, cmd, cmd_length);
     if(rp_type != M100SuccessResponse) return rp_type;
     if(rp_type != M100SuccessResponse) return rp_type;
 
 
-    uint8_t* data = buffer_get_data(module->buf);
+    uint8_t* data = uhf_buffer_get_data(module->uart->buffer);
 
 
     uint8_t rtn_command = data[2];
     uint8_t rtn_command = data[2];
     uint16_t payload_len = data[3];
     uint16_t payload_len = data[3];
@@ -326,17 +308,10 @@ M100ResponseType m100_write_label_data_storage(
     cmd[cmd_length - 2] = checksum(cmd + 1, cmd_length - 3);
     cmd[cmd_length - 2] = checksum(cmd + 1, cmd_length - 3);
     cmd[cmd_length - 1] = FRAME_END;
     cmd[cmd_length - 1] = FRAME_END;
     // send cmd
     // send cmd
-    // furi_hal_serial_async_rx_start(module->serial_handle, rx_callback, module->buf, false);
-    // furi_hal_serial_tx(module->serial_handle, cmd, cmd_length);
-    // unsigned int delay = DELAY_MS / 2;
-    // unsigned int timeout = 15;
-    // while(!buffer_get_size(module->buf)) {
-    //     furi_delay_ms(delay);
-    //     if(!timeout--) break;
-    // }
-    setup_and_send_rx(module, cmd, cmd_length);
-    uint8_t* buff_data = buffer_get_data(module->buf);
-    size_t buff_length = buffer_get_size(module->buf);
+    M100ResponseType rp_type = setup_and_send_rx(module, cmd, cmd_length);
+    if(rp_type != M100SuccessResponse) return rp_type;
+    uint8_t* buff_data = uhf_buffer_get_data(module->uart->buffer);
+    size_t buff_length = uhf_buffer_get_size(module->uart->buffer);
     if(buff_data[2] == 0xFF && buff_length == 8)
     if(buff_data[2] == 0xFF && buff_length == 8)
         return M100NoTagResponse;
         return M100NoTagResponse;
     else if(buff_data[2] == 0xFF)
     else if(buff_data[2] == 0xFF)
@@ -351,9 +326,10 @@ void m100_set_baudrate(M100Module* module, uint32_t baudrate) {
     cmd[6] = 0xFF & br_mod; // pow LSB
     cmd[6] = 0xFF & br_mod; // pow LSB
     cmd[5] = 0xFF & (br_mod >> 8); // pow MSB
     cmd[5] = 0xFF & (br_mod >> 8); // pow MSB
     cmd[length - 2] = checksum(cmd + 1, length - 3);
     cmd[length - 2] = checksum(cmd + 1, length - 3);
-    furi_hal_serial_tx(module->serial_handle, cmd, length);
-    furi_hal_serial_set_br(module->serial_handle, baudrate);
-    module->baudrate = baudrate;
+    // setup_and_send_rx(module, cmd, length);
+    uhf_uart_send_wait(module->uart, cmd, length);
+    uhf_uart_set_baudrate(module->uart, baudrate);
+    module->uart->baudrate = baudrate;
 }
 }
 
 
 bool m100_set_working_region(M100Module* module, WorkingRegion region) {
 bool m100_set_working_region(M100Module* module, WorkingRegion region) {
@@ -392,5 +368,5 @@ bool m100_set_power(M100Module* module, uint8_t* power) {
 }
 }
 
 
 uint32_t m100_get_baudrate(M100Module* module) {
 uint32_t m100_get_baudrate(M100Module* module) {
-    return module->baudrate;
+    return module->uart->baudrate;
 }
 }

+ 4 - 7
uhf_rfid/uhf_module.h

@@ -1,13 +1,11 @@
 #pragma once
 #pragma once
-
+#include <furi_hal.h>
 #include <stddef.h>
 #include <stddef.h>
 #include <stdint.h>
 #include <stdint.h>
 #include <stdbool.h>
 #include <stdbool.h>
-#include <furi_hal.h>
+#include "uhf_uart.h"
 #include "uhf_tag.h"
 #include "uhf_tag.h"
 #include "uhf_buffer.h"
 #include "uhf_buffer.h"
-#include "uhf_tag.h"
-#include <furi_hal.h>
 #include "uhf_module_settings.h"
 #include "uhf_module_settings.h"
 
 
 #define FRAME_START 0xBB
 #define FRAME_START 0xBB
@@ -33,13 +31,12 @@ typedef enum {
 
 
 typedef struct {
 typedef struct {
     M100ModuleInfo* info;
     M100ModuleInfo* info;
-    uint32_t baudrate;
     WorkingRegion region;
     WorkingRegion region;
     uint16_t region_frequency;
     uint16_t region_frequency;
     uint16_t transmitting_power;
     uint16_t transmitting_power;
+    uint16_t max_transmitting_power;
     bool freq_hopping;
     bool freq_hopping;
-    Buffer* buf;
-    FuriHalSerialHandle* serial_handle;
+    UHFUart* uart;
 } M100Module;
 } M100Module;
 
 
 M100ModuleInfo* m100_module_info_alloc();
 M100ModuleInfo* m100_module_info_alloc();

+ 129 - 0
uhf_rfid/uhf_uart.c

@@ -0,0 +1,129 @@
+#include "uhf_uart.h"
+
+// int32_t uhf_uart_worker_callback(void *ctx){
+//     UHFUart* uart = (UHFUart*)ctx;
+//     Buffer* buffer = (Buffer*)uart->buffer;
+//     uint32_t events;
+//     size_t length_read = 0;
+//     uint8_t read_buffer[1];
+//     FURI_LOG_E("UHF_UART_WORKER", "UHF UART WORKER STARTED");
+//     do{
+//         events = furi_thread_flags_wait(
+//             UHFUartWorkerWaitingDataFlag | UHFUartWorkerExitingFlag, FuriFlagWaitAny, FuriWaitForever
+//         );
+//         FURI_LOG_E("UHF_UART_WORKER", "events = %lu", events);
+//         if(events & UHFUartWorkerWaitingDataFlag){
+//             FURI_LOG_E("UHF_UART_WORKER", "Waiting data...");
+//             length_read = furi_stream_buffer_receive(uart->rx_buff_stream, read_buffer, 1, 0);
+//             if(length_read){
+//                 do{
+//                     length_read = furi_stream_buffer_receive(uart->rx_buff_stream, read_buffer, 1, 0);
+//                     uhf_buffer_append_single(buffer, read_buffer[0]);
+//                     uhf_uart_tick_reset(uart);
+//                 }while(read_buffer[0] != UHF_UART_FRAME_END && length_read > 0);
+//                 FURI_LOG_E("UHF_UART_WORKER", "UHF Total length read = %u", uhf_buffer_get_size(buffer));
+//                 uhf_buffer_close(buffer);
+//                 furi_stream_buffer_reset(uart->rx_buff_stream);
+//             }
+//         }
+//     }while((events & UHFUartWorkerExitingFlag) != UHFUartWorkerExitingFlag);
+//     return 0;
+// }
+
+void uhf_uart_default_rx_callback(
+    FuriHalSerialHandle* handle,
+    FuriHalSerialRxEvent event,
+    void* ctx) {
+    UHFUart* uart = (UHFUart*)ctx;
+    // FURI_LOG_E("UHF_UART", "UHF UART RX CALLBACK");
+    if((event & FuriHalSerialRxEventData) == FuriHalSerialRxEventData) {
+        uint8_t data = furi_hal_serial_async_rx(handle);
+        // if(data == UHF_UART_FRAME_START){
+        //     uhf_buffer_reset(uart->buffer);
+        // }
+        if(uhf_is_buffer_closed(uart->buffer)) {
+            return;
+        }
+        if(data == UHF_UART_FRAME_END) {
+            uhf_buffer_append_single(uart->buffer, data);
+            uhf_buffer_close(uart->buffer);
+            FURI_LOG_E(
+                "UHF_UART", "UHF Total length read = %u", uhf_buffer_get_size(uart->buffer));
+        }
+        uhf_buffer_append_single(uart->buffer, data);
+        uhf_uart_tick_reset(uart);
+        // furi_stream_buffer_send(uart->rx_buff_stream, (void*)&data, 1, 0);
+        // furi_thread_flags_set(furi_thread_get_id(uart->thread), UHFUartWorkerWaitingDataFlag);
+    }
+}
+
+UHFUart* uhf_uart_alloc() {
+    UHFUart* uart = (UHFUart*)malloc(sizeof(UHFUart));
+    uart->bus = FuriHalBusUSART1;
+    uart->handle = furi_hal_serial_control_acquire(FuriHalSerialIdUsart);
+    // uart->rx_buff_stream = furi_stream_buffer_alloc(UHF_UART_RX_BUFFER_SIZE, 1);
+    uart->init_by_app = !furi_hal_bus_is_enabled(uart->bus);
+    uart->tick = UHF_UART_WAIT_TICK;
+    uart->baudrate = UHF_UART_DEFAULT_BAUDRATE;
+    // expansion_disable();
+    if(uart->init_by_app) {
+        FURI_LOG_E("UHF_UART", "UHF UART INIT BY APP");
+        furi_hal_serial_init(uart->handle, uart->baudrate);
+    } else {
+        FURI_LOG_E("UHF_UART", "UHF UART INIT BY HAL");
+    }
+    uart->buffer = uhf_buffer_alloc(UHF_UART_RX_BUFFER_SIZE);
+    // uart->thread = furi_thread_alloc_ex("UHFUartWorker", UHF_UART_WORKER_STACK_SIZE, uhf_uart_worker_callback, uart);
+    // furi_thread_start(uart->thread);
+    furi_hal_serial_async_rx_start(uart->handle, uhf_uart_default_rx_callback, uart, false);
+    return uart;
+}
+
+void uhf_uart_free(UHFUart* uart) {
+    furi_assert(uart);
+    // furi_assert(uart->thread);
+    // furi_thread_flags_set(furi_thread_get_id(uart->thread), UHFUartWorkerExitingFlag);
+    // furi_thread_join(uart->thread);
+    // furi_thread_free(uart->thread);
+    // furi_stream_buffer_free(uart->rx_buff_stream);
+    uhf_buffer_free(uart->buffer);
+    if(uart->init_by_app) {
+        furi_hal_serial_deinit(uart->handle);
+    }
+    furi_hal_serial_control_release(uart->handle);
+    free(uart);
+}
+
+void uhf_uart_set_receive_byte_callback(
+    UHFUart* uart,
+    FuriHalSerialAsyncRxCallback callback,
+    void* ctx,
+    bool report_errors) {
+    furi_hal_serial_async_rx_start(uart->handle, callback, ctx, report_errors);
+}
+
+void uhf_uart_send(UHFUart* uart, uint8_t* data, size_t size) {
+    furi_hal_serial_tx(uart->handle, data, size);
+}
+
+void uhf_uart_send_wait(UHFUart* uart, uint8_t* data, size_t size) {
+    uhf_uart_send(uart, data, size);
+    furi_hal_serial_tx_wait_complete(uart->handle);
+    // furi_thread_flags_set(furi_thread_get_id(uart->thread), UHFUartWorkerWaitingDataFlag);
+}
+
+void uhf_uart_set_baudrate(UHFUart* uart, uint32_t baudrate) {
+    furi_hal_serial_set_br(uart->handle, baudrate);
+    uart->baudrate = baudrate;
+}
+
+bool uhf_uart_tick(UHFUart* uart) {
+    if(uart->tick > 0) {
+        uart->tick--;
+    }
+    return uart->tick == 0;
+}
+
+void uhf_uart_tick_reset(UHFUart* uart) {
+    uart->tick = UHF_UART_WAIT_TICK;
+}

+ 48 - 0
uhf_rfid/uhf_uart.h

@@ -0,0 +1,48 @@
+#pragma once
+#include <furi_hal.h>
+// #include <expansion/expansion.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include "uhf_buffer.h"
+
+#define UHF_UART_RX_BUFFER_SIZE 250
+// #define UHF_UART_WORKER_STACK_SIZE 1 * 1024
+#define UHF_UART_DEFAULT_BAUDRATE 115200
+#define UHF_UART_FRAME_START 0xBB
+#define UHF_UART_FRAME_END 0x7E
+#define UHF_UART_WAIT_TICK 1000
+
+typedef void (*CallbackFunction)(uint8_t* data, void* ctx);
+
+typedef enum {
+    UHFUartWorkerWaitingDataFlag = 1 << 0,
+    UHFUartWorkerExitingFlag = 1 << 2,
+} UHFUartWorkerEventFlag;
+
+typedef struct {
+    FuriHalBus bus;
+    FuriHalSerialHandle* handle;
+    // FuriStreamBuffer *rx_buff_stream;
+    // FuriThread *thread;
+    CallbackFunction callback;
+    Buffer* buffer;
+    uint32_t baudrate;
+    bool init_by_app;
+    void* ctx;
+    volatile int tick;
+} UHFUart;
+
+int32_t uhf_uart_worker_callback(void* ctx);
+
+UHFUart* uhf_uart_alloc();
+void uhf_uart_free(UHFUart* uart);
+void uhf_uart_send(UHFUart* uart, uint8_t* data, size_t size);
+void uhf_uart_send_wait(UHFUart* uart, uint8_t* data, size_t size);
+void uhf_uart_set_receive_byte_callback(
+    UHFUart* uart,
+    FuriHalSerialAsyncRxCallback callback,
+    void* ctx,
+    bool report_errors);
+void uhf_uart_set_baudrate(UHFUart* uart, uint32_t baudrate);
+bool uhf_uart_tick(UHFUart* uart);
+void uhf_uart_tick_reset(UHFUart* uart);

+ 16 - 11
uhf_rfid/uhf_worker.c

@@ -14,14 +14,14 @@ UHFWorkerEvent verify_module_connected(UHFWorker* uhf_worker) {
 UHFTag* send_polling_command(UHFWorker* uhf_worker) {
 UHFTag* send_polling_command(UHFWorker* uhf_worker) {
     // read epc bank
     // read epc bank
     UHFTag* uhf_tag = uhf_tag_alloc();
     UHFTag* uhf_tag = uhf_tag_alloc();
-    while(true) {
-        M100ResponseType status = m100_single_poll(uhf_worker->module, uhf_tag);
+    M100ResponseType status;
+    do {
         if(uhf_worker->state == UHFWorkerStateStop) {
         if(uhf_worker->state == UHFWorkerStateStop) {
             uhf_tag_free(uhf_tag);
             uhf_tag_free(uhf_tag);
             return NULL;
             return NULL;
         }
         }
-        if(status == M100SuccessResponse) break;
-    }
+        status = m100_single_poll(uhf_worker->module, uhf_tag);
+    } while(status != M100SuccessResponse);
     return uhf_tag;
     return uhf_tag;
 }
 }
 
 
@@ -48,8 +48,8 @@ UHFWorkerEvent read_single_card(UHFWorker* uhf_worker) {
     if(uhf_tag == NULL) return UHFWorkerEventAborted;
     if(uhf_tag == NULL) return UHFWorkerEventAborted;
     uhf_tag_wrapper_set_tag(uhf_worker->uhf_tag_wrapper, uhf_tag);
     uhf_tag_wrapper_set_tag(uhf_worker->uhf_tag_wrapper, uhf_tag);
     // set select
     // set select
-    if(m100_set_select(uhf_worker->module, uhf_tag) != M100SuccessResponse)
-        return UHFWorkerEventFail;
+    while(m100_set_select(uhf_worker->module, uhf_tag) != M100SuccessResponse) {
+    }
     // read tid
     // read tid
     UHFWorkerEvent event;
     UHFWorkerEvent event;
     event = read_bank_till_max_length(uhf_worker, uhf_tag, TIDBank);
     event = read_bank_till_max_length(uhf_worker, uhf_tag, TIDBank);
@@ -64,16 +64,20 @@ UHFWorkerEvent write_single_card(UHFWorker* uhf_worker) {
     UHFTag* uhf_tag_des = send_polling_command(uhf_worker);
     UHFTag* uhf_tag_des = send_polling_command(uhf_worker);
     if(uhf_tag_des == NULL) return UHFWorkerEventAborted;
     if(uhf_tag_des == NULL) return UHFWorkerEventAborted;
     UHFTag* uhf_tag_from = uhf_worker->uhf_tag_wrapper->uhf_tag;
     UHFTag* uhf_tag_from = uhf_worker->uhf_tag_wrapper->uhf_tag;
-    if(m100_set_select(uhf_worker->module, uhf_tag_des) != M100SuccessResponse)
-        return UHFWorkerEventFail;
+    M100ResponseType rp_type;
+    do {
+        rp_type = m100_set_select(uhf_worker->module, uhf_tag_des);
+        if(uhf_worker->state == UHFWorkerStateStop) return UHFWorkerEventAborted;
+        if(rp_type == M100SuccessResponse) break;
+    } while(true);
     do {
     do {
-        M100ResponseType rp_type = m100_write_label_data_storage(
+        rp_type = m100_write_label_data_storage(
             uhf_worker->module, uhf_tag_from, uhf_tag_des, UserBank, 0, 0);
             uhf_worker->module, uhf_tag_from, uhf_tag_des, UserBank, 0, 0);
         if(uhf_worker->state == UHFWorkerStateStop) return UHFWorkerEventAborted;
         if(uhf_worker->state == UHFWorkerStateStop) return UHFWorkerEventAborted;
         if(rp_type == M100SuccessResponse) break;
         if(rp_type == M100SuccessResponse) break;
     } while(true);
     } while(true);
     do {
     do {
-        M100ResponseType rp_type = m100_write_label_data_storage(
+        rp_type = m100_write_label_data_storage(
             uhf_worker->module, uhf_tag_from, uhf_tag_des, EPCBank, 0, 0);
             uhf_worker->module, uhf_tag_from, uhf_tag_des, EPCBank, 0, 0);
         if(uhf_worker->state == UHFWorkerStateStop) return UHFWorkerEventAborted;
         if(uhf_worker->state == UHFWorkerStateStop) return UHFWorkerEventAborted;
         if(rp_type == M100SuccessResponse) break;
         if(rp_type == M100SuccessResponse) break;
@@ -98,7 +102,8 @@ 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", UHF_WORKER_STACK_SIZE, uhf_worker_task, uhf_worker);
     uhf_worker->module = m100_module_alloc();
     uhf_worker->module = m100_module_alloc();
     uhf_worker->callback = NULL;
     uhf_worker->callback = NULL;
     uhf_worker->ctx = NULL;
     uhf_worker->ctx = NULL;

+ 2 - 0
uhf_rfid/uhf_worker.h

@@ -4,6 +4,8 @@
 #include <furi_hal.h>
 #include <furi_hal.h>
 #include "uhf_module.h"
 #include "uhf_module.h"
 
 
+#define UHF_WORKER_STACK_SIZE 1 * 1024
+
 typedef enum {
 typedef enum {
     // Init states
     // Init states
     UHFWorkerStateNone,
     UHFWorkerStateNone,