Sfoglia il codice sorgente

refractoring write

Chaka 2 anni fa
parent
commit
90b658c87b
11 ha cambiato i file con 342 aggiunte e 247 eliminazioni
  1. 1 1
      scenes/uhf_scene_device_info.c
  2. 0 1
      scenes/uhf_scene_read_tag.c
  3. 5 3
      scenes/uhf_scene_verify.c
  4. 3 1
      uhf_app.c
  5. 36 16
      uhf_device.c
  6. 2 11
      uhf_device.h
  7. 135 33
      uhf_module.c
  8. 37 18
      uhf_module.h
  9. 59 0
      uhf_tag.c
  10. 5 0
      uhf_tag.h
  11. 59 163
      uhf_worker.c

+ 1 - 1
scenes/uhf_scene_device_info.c

@@ -81,7 +81,7 @@ void change_view_on_event(UHFApp* uhf_app) {
         furi_string_get_cstr(furi_temp_str));
 
     widget_add_string_multiline_element(
-        uhf_app->widget, 3, 24, AlignLeft, AlignTop, FontBatteryPercent, temp_str);
+        uhf_app->widget, 3, 24, AlignLeft, AlignTop, FontKeyboard, temp_str);
 
     widget_add_button_element(
         uhf_app->widget,

+ 0 - 1
scenes/uhf_scene_read_tag.c

@@ -44,6 +44,5 @@ void uhf_scene_read_tag_on_exit(void* ctx) {
     uhf_worker_stop(uhf_app->worker);
     // Clear view
     popup_reset(uhf_app->popup);
-
     uhf_blink_stop(uhf_app);
 }

+ 5 - 3
scenes/uhf_scene_verify.c

@@ -42,6 +42,10 @@ bool uhf_scene_verify_on_event(void* ctx, SceneManagerEvent event) {
                 widget_reset(uhf_app->widget);
                 furi_string_reset(temp_str);
                 uhf_worker_stop(uhf_app->worker);
+                // furi_hal_gpio_write(&gpio_ext, false);
+                // furi_delay_ms(50);
+                // furi_hal_gpio_write(&gpio_ext_pa7, true);
+                // furi_delay_ms(50);
                 uhf_worker_start(
                     uhf_app->worker,
                     UHFWorkerStateVerify,
@@ -113,7 +117,7 @@ bool uhf_scene_verify_on_event(void* ctx, SceneManagerEvent event) {
                     AlignCenter,
                     AlignCenter,
                     FontSecondary,
-                    "Please connect your module.\nPlease refer to the git@frux-c/uhf_rfid for help.");
+                    "Please refer to the git@frux-c/uhf_rfid for help.");
                 widget_add_button_element(
                     uhf_app->widget,
                     GuiButtonTypeLeft,
@@ -138,8 +142,6 @@ void uhf_scene_verify_on_exit(void* ctx) {
     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);
 }

+ 3 - 1
uhf_app.c

@@ -187,13 +187,15 @@ int32_t uhf_app_main(void* ctx) {
 
     // enable 5v pin
     furi_hal_power_enable_otg();
+    // init pin a2
+    // furi_hal_gpio_init_simple(&gpio_ext_pa7, GpioModeOutputPushPull);
 
     scene_manager_next_scene(uhf_app->scene_manager, UHFSceneVerify);
     view_dispatcher_run(uhf_app->view_dispatcher);
 
     // disable 5v pin
     furi_hal_power_disable_otg();
-
+    // furi_hal_gpio_disable_int_callback()
     // exit app
     uhf_free(uhf_app);
     return 0;

+ 36 - 16
uhf_device.c

@@ -55,23 +55,35 @@ static bool uhf_device_save_file(
         // Reserved bank might be added
         // todo : maybe
         uint32_t temp_arr[1];
+        uint8_t temp_arr2[2];
+        // write pc
+        temp_arr2[0] = (uint8_t)(uhf_tag_get_epc_pc(uhf_tag) >> 8) & 0xFF;
+        temp_arr2[1] = (uint8_t)(uhf_tag_get_epc_pc(uhf_tag) & 0xFF);
+        if(!flipper_format_write_hex(file, UHF_EPC_PC_LABEL, temp_arr2, 2)) break;
+        // write crc
+        temp_arr2[0] = (uint8_t)(uhf_tag_get_epc_crc(uhf_tag) >> 8) & 0xFF;
+        temp_arr2[1] = (uint8_t)(uhf_tag_get_epc_crc(uhf_tag) & 0xFF);
+        if(!flipper_format_write_hex(file, UHF_EPC_CRC_LABEL, temp_arr2, 2)) break;
         // write epc
-        temp_arr[0] = uhf_tag->epc->size;
+        temp_arr[0] = uhf_tag_get_epc_size(uhf_tag);
         if(!flipper_format_write_uint32(file, UHF_EPC_BANK_LENGTH_LABEL, temp_arr, 1)) break;
         if(!flipper_format_write_hex(
-               file, UHF_EPC_BANK_LABEL, uhf_tag->epc->data, uhf_tag->epc->size))
+               file, UHF_EPC_BANK_LABEL, uhf_tag_get_epc(uhf_tag), uhf_tag_get_epc_size(uhf_tag)))
             break;
         // write tid
-        temp_arr[0] = uhf_tag->tid->size;
+        temp_arr[0] = uhf_tag_get_tid_size(uhf_tag);
         if(!flipper_format_write_uint32(file, UHF_TID_BANK_LENGTH_LABEL, temp_arr, 1)) break;
         if(!flipper_format_write_hex(
-               file, UHF_TID_BANK_LABEL, uhf_tag->tid->data, uhf_tag->tid->size))
+               file, UHF_TID_BANK_LABEL, uhf_tag_get_tid(uhf_tag), uhf_tag_get_tid_size(uhf_tag)))
             break;
         // write user
-        temp_arr[0] = uhf_tag->user->size;
+        temp_arr[0] = uhf_tag_get_user_size(uhf_tag);
         if(!flipper_format_write_uint32(file, UHF_USER_BANK_LENGTH_LABEL, temp_arr, 1)) break;
         if(!flipper_format_write_hex(
-               file, UHF_USER_BANK_LABEL, uhf_tag->user->data, uhf_tag->user->size))
+               file,
+               UHF_USER_BANK_LABEL,
+               uhf_tag_get_user(uhf_tag),
+               uhf_tag_get_user_size(uhf_tag)))
             break;
         saved = true;
     } while(0);
@@ -99,7 +111,7 @@ static bool uhf_device_load_data(UHFDevice* dev, FuriString* path, bool show_dia
     FuriString* temp_str;
     temp_str = furi_string_alloc();
     bool deprecated_version = false;
-    UHFTag* uhf_tag = dev->uhf_tag_wrapper->uhf_tag;
+    UHFTag* uhf_tag = uhf_tag_alloc();
     uhf_tag_reset(uhf_tag);
     uint32_t temp_arr[1];
     if(dev->loading_cb) {
@@ -116,25 +128,34 @@ static bool uhf_device_load_data(UHFDevice* dev, FuriString* path, bool show_dia
             deprecated_version = true;
             break;
         }
+        // read pc
+        uint8_t temp_arr2[2];
+        if(!flipper_format_read_hex(file, UHF_EPC_PC_LABEL, temp_arr2, 2)) break;
+        uhf_tag_set_epc_pc(uhf_tag, (temp_arr2[0] << 8) + temp_arr2[1]);
+        // read crc
+        if(!flipper_format_read_hex(file, UHF_EPC_CRC_LABEL, temp_arr2, 2)) break;
+        uhf_tag_set_epc_crc(uhf_tag, (temp_arr2[0] << 8) + temp_arr2[1]);
         // read epc
         if(!flipper_format_read_uint32(file, UHF_EPC_BANK_LENGTH_LABEL, temp_arr, 1)) break;
-        uhf_tag->epc->size = temp_arr[0];
+        uhf_tag_set_epc_size(uhf_tag, temp_arr[0]);
         if(!flipper_format_read_hex(
-               file, UHF_EPC_BANK_LABEL, uhf_tag->epc->data, uhf_tag->epc->size))
+               file, UHF_EPC_BANK_LABEL, uhf_tag_get_epc(uhf_tag), uhf_tag_get_epc_size(uhf_tag)))
             break;
 
         // read tid
         if(!flipper_format_read_uint32(file, UHF_TID_BANK_LENGTH_LABEL, temp_arr, 1)) break;
-        uhf_tag->tid->size = temp_arr[0];
+        uhf_tag_set_tid_size(uhf_tag, temp_arr[0]);
         if(!flipper_format_read_hex(
-               file, UHF_TID_BANK_LABEL, uhf_tag->tid->data, uhf_tag->tid->size))
+               file, UHF_TID_BANK_LABEL, uhf_tag_get_tid(uhf_tag), uhf_tag_get_tid_size(uhf_tag)))
             break;
-
         // read user
         if(!flipper_format_read_uint32(file, UHF_USER_BANK_LENGTH_LABEL, temp_arr, 1)) break;
-        uhf_tag->user->size = temp_arr[0];
+        uhf_tag_set_user_size(uhf_tag, temp_arr[0]);
         if(!flipper_format_read_hex(
-               file, UHF_USER_BANK_LABEL, uhf_tag->user->data, uhf_tag->user->size))
+               file,
+               UHF_USER_BANK_LABEL,
+               uhf_tag_get_user(uhf_tag),
+               uhf_tag_get_user_size(uhf_tag)))
             break;
 
         parsed = true;
@@ -151,10 +172,9 @@ static bool uhf_device_load_data(UHFDevice* dev, FuriString* path, bool show_dia
             dialog_message_show_storage_error(dev->dialogs, "Can not parse\nfile");
         }
     }
-
+    uhf_tag_wrapper_set_tag(dev->uhf_tag_wrapper, uhf_tag);
     furi_string_free(temp_str);
     flipper_format_free(file);
-
     return parsed;
 }
 

+ 2 - 11
uhf_device.h

@@ -7,21 +7,12 @@
 #include <mbedtls/des.h>
 #include "uhf_tag.h"
 
-// #include "rfal_picopass.h"
-
 #define UHF_DEV_NAME_MAX_LEN 22
-// #define PICOPASS_READER_DATA_MAX_SIZE 64
-// #define PICOPASS_BLOCK_LEN 8
-// #define PICOPASS_MAX_APP_LIMIT 32
-#define UHF_BANK_DOES_NOT_EXIST                                                                   \
-    (uint8_t[]) {                                                                                 \
-        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, \
-            0xFF                                                                                  \
-    }
-
 #define UHF_EPC_BANK_LENGTH_LABEL "EPC_LENGTH"
 #define UHF_TID_BANK_LENGTH_LABEL "TID_LENGTH"
 #define UHF_USER_BANK_LENGTH_LABEL "USER_LENGTH"
+#define UHF_EPC_PC_LABEL "PC"
+#define UHF_EPC_CRC_LABEL "CRC"
 #define UHF_RFU_BANK_LABEL "RFU"
 #define UHF_EPC_BANK_LABEL "EPC"
 #define UHF_TID_BANK_LABEL "TID"

+ 135 - 33
uhf_module.c

@@ -1,7 +1,7 @@
 #include "uhf_module.h"
 #include "uhf_module_cmd.h"
 
-#define DELAY_MS 50
+#define DELAY_MS 100
 
 void rx_callback(UartIrqEvent event, uint8_t data, void* ctx) {
     UNUSED(event);
@@ -68,7 +68,10 @@ uint16_t crc16_genibus(const uint8_t* data, size_t length) {
 }
 
 char* m100_get_hardware_version(M100Module* module) {
-    if(module->info->hw_version != NULL) return module->info->hw_version;
+    if(module->info->hw_version != NULL) {
+        free(module->info->hw_version);
+        module->info->hw_version = NULL;
+    }
     buffer_reset(module->buf);
     furi_hal_uart_set_irq_cb(FuriHalUartIdUSART1, rx_callback, module->buf);
     furi_hal_uart_tx(FuriHalUartIdUSART1, (uint8_t*)&CMD_HW_VERSION.cmd[0], CMD_HW_VERSION.length);
@@ -88,7 +91,10 @@ char* m100_get_hardware_version(M100Module* module) {
     return module->info->hw_version;
 }
 char* m100_get_software_version(M100Module* module) {
-    if(module->info->sw_version != NULL) return module->info->sw_version;
+    if(module->info->sw_version != NULL) {
+        free(module->info->sw_version);
+        module->info->sw_version = NULL;
+    }
     buffer_reset(module->buf);
     furi_hal_uart_set_irq_cb(FuriHalUartIdUSART1, rx_callback, module->buf);
     furi_hal_uart_tx(FuriHalUartIdUSART1, (uint8_t*)&CMD_SW_VERSION.cmd[0], CMD_SW_VERSION.length);
@@ -108,7 +114,10 @@ char* m100_get_software_version(M100Module* module) {
     return module->info->sw_version;
 }
 char* m100_get_manufacturers(M100Module* module) {
-    if(module->info->manufacturer != NULL) return module->info->manufacturer;
+    if(module->info->manufacturer != NULL) {
+        free(module->info->manufacturer);
+        module->info->manufacturer = NULL;
+    }
     buffer_reset(module->buf);
     furi_hal_uart_set_irq_cb(FuriHalUartIdUSART1, rx_callback, module->buf);
     furi_hal_uart_tx(
@@ -129,7 +138,7 @@ char* m100_get_manufacturers(M100Module* module) {
     return module->info->manufacturer;
 }
 
-UHFTag* m100_send_single_poll(M100Module* module) {
+M100ResponseType m100_send_single_poll(M100Module* module, UHFTag* uhf_tag) {
     buffer_reset(module->buf);
     furi_hal_uart_set_irq_cb(FuriHalUartIdUSART1, rx_callback, module->buf);
     furi_hal_uart_tx(
@@ -137,7 +146,7 @@ UHFTag* m100_send_single_poll(M100Module* module) {
     furi_delay_ms(DELAY_MS);
     uint8_t* data = buffer_get_data(module->buf);
     size_t length = buffer_get_size(module->buf);
-    if(length <= 8 && data[2] == 0xFF) return NULL;
+    if(length <= 8 && data[2] == 0xFF) return M100NoTagResponse;
     uint16_t pc = data[6];
     uint16_t crc = 0;
     // mask out epc length from protocol control
@@ -152,26 +161,16 @@ UHFTag* m100_send_single_poll(M100Module* module) {
     crc <<= 8;
     crc += data[8 + epc_len + 1];
     // validate checksum
-    uint8_t cs = checksum(data + 1, length - 3);
-    for(size_t i = 0; i < length; i++){
-        FURI_LOG_E("m100", "data[%d]=%02X", i, data[i]);
-    }
-    if(cs != data[length - 2]) return NULL;
-    FURI_LOG_E("m100", "checksum pass");
+    if(checksum(data + 1, length - 3) != data[length - 2]) return M100ValidationFail;
     // validate crc
-    uint16_t ccrc = crc16_genibus(data + 6, epc_len + 2);
-    FURI_LOG_E("m100", "crc found = %04X, calculated crc = %04X", crc, ccrc);
-    if(ccrc != crc) return NULL;
-    FURI_LOG_E("m100", "crc pass");
-    UHFTag* uhf_tag = uhf_tag_alloc();
+    if(crc16_genibus(data + 6, epc_len + 2) != crc) return M100ValidationFail;
     uhf_tag_set_epc_pc(uhf_tag, pc);
     uhf_tag_set_epc_crc(uhf_tag, crc);
     uhf_tag_set_epc(uhf_tag, data + 8, epc_len);
-    FURI_LOG_E("m100", "returning tag");
-    return uhf_tag;
+    return M100Success;
 }
 
-bool m100_set_select(M100Module* module, UHFTag* uhf_tag) {
+M100ResponseType m100_set_select(M100Module* module, UHFTag* uhf_tag) {
     buffer_reset(module->buf);
     // Set select
     uint8_t cmd[MAX_BUFFER_SIZE];
@@ -203,10 +202,10 @@ bool m100_set_select(M100Module* module, UHFTag* uhf_tag) {
     furi_delay_ms(DELAY_MS);
 
     uint8_t* data = buffer_get_data(module->buf);
-    if(checksum(data + 1, 5) != data[6]) return false; // error in rx
-    if(data[5] != 0x00) return false; // error if not 0
+    if(checksum(data + 1, 5) != data[6]) return M100ValidationFail; // error in rx
+    if(data[5] != 0x00) return M100ValidationFail; // error if not 0
 
-    return true;
+    return M100Success;
 }
 
 UHFTag* m100_get_select_param(M100Module module) {
@@ -214,16 +213,20 @@ UHFTag* m100_get_select_param(M100Module module) {
     return NULL;
 }
 
-bool m100_read_label_data_storage(
+M100ResponseType m100_read_label_data_storage(
     M100Module* module,
     UHFTag* uhf_tag,
     BankType bank,
-    uint32_t access_pwd) {
-    UNUSED(uhf_tag);
+    uint32_t access_pwd,
+    uint16_t word_count) {
+    /*
+    Will probably remove UHFTag as param and get it from get selected tag
+        */
+    if(bank == EPCBank) return M100Success;
     buffer_reset(module->buf);
     uint8_t cmd[MAX_BUFFER_SIZE];
-    size_t length = CMD_READ_LABEL_DATA_STORAGE_AREA.length;
-    memcpy(cmd, CMD_READ_LABEL_DATA_STORAGE_AREA.cmd, length);
+    size_t cmd_length = CMD_READ_LABEL_DATA_STORAGE_AREA.length;
+    memcpy(cmd, CMD_READ_LABEL_DATA_STORAGE_AREA.cmd, cmd_length);
     // set access password
     cmd[5] = (access_pwd >> 24) & 0xFF;
     cmd[6] = (access_pwd >> 16) & 0xFF;
@@ -231,14 +234,114 @@ bool m100_read_label_data_storage(
     cmd[8] = access_pwd & 0xFF;
     // set mem bank
     cmd[9] = (uint8_t)bank;
-    // recalc checksum
-    cmd[length - 2] = checksum(cmd + 1, length - 3);
+    // set word counter
+    cmd[12] = (word_count >> 8) & 0xFF;
+    cmd[13] = word_count & 0xFF;
+    // calc checksum
+    cmd[cmd_length - 2] = checksum(cmd + 1, cmd_length - 3);
     furi_hal_uart_set_irq_cb(FuriHalUartIdUSART1, rx_callback, module->buf);
-    furi_hal_uart_tx(FuriHalUartIdUSART1, cmd, length);
+    furi_hal_uart_tx(FuriHalUartIdUSART1, cmd, cmd_length);
     furi_delay_ms(DELAY_MS);
-    return true;
+    uint8_t* data = buffer_get_data(module->buf);
+    uint16_t payload_len = data[3];
+    payload_len = (payload_len << 8) + data[4];
+    size_t ptr_offset = 5 /*<-ptr offset*/ + uhf_tag->epc->size + 3 /*<-pc + ul*/;
+    size_t bank_data_length = payload_len - (ptr_offset - 5 /*dont include the offset*/);
+    if(data[2] == 0xFF) {
+        if(payload_len == 0x0001) return M100NoTagResponse;
+        return M100MemoryOverrun;
+    }
+    switch(bank) {
+    case TIDBank:
+        uhf_tag_set_tid(uhf_tag, data + ptr_offset, bank_data_length);
+        break;
+    case UserBank:
+        uhf_tag_set_user(uhf_tag, data + ptr_offset, bank_data_length);
+        break;
+    default:
+        return M100Success;
+    }
+    return M100Success;
 }
 
+M100ResponseType m100_write_label_data_storage(
+    M100Module* module,
+    UHFTag* uhf_tag,
+    BankType bank,
+    uint16_t source_address,
+    uint32_t access_pwd) {
+    buffer_reset(module->buf);
+    uint8_t cmd[MAX_BUFFER_SIZE];
+    size_t cmd_length = CMD_WRITE_LABEL_DATA_STORE.length;
+    memcpy(cmd, CMD_WRITE_LABEL_DATA_STORE.cmd, cmd_length);
+    uint16_t payload_len = 9;
+    uint16_t data_length;
+    switch(bank) {
+    case ReservedBank:
+        // access pwd len + kill pwd len
+        payload_len += 4;
+        data_length = 4;
+        break;
+    case EPCBank:
+        // epc len + pc len
+        payload_len += 4 + uhf_tag_get_epc_size(uhf_tag);
+        data_length = 4 + uhf_tag_get_epc_size(uhf_tag);
+        // set data
+        uint8_t tmp_arr[4];
+        tmp_arr[0] = (uint8_t)((uhf_tag_get_epc_crc(uhf_tag) >> 8) & 0xFF);
+        tmp_arr[1] = (uint8_t)(uhf_tag_get_epc_crc(uhf_tag) & 0xFF);
+        tmp_arr[2] = (uint8_t)((uhf_tag_get_epc_pc(uhf_tag) >> 8) & 0xFF);
+        tmp_arr[3] = (uint8_t)(uhf_tag_get_epc_pc(uhf_tag) & 0xFF);
+        FURI_LOG_E("wkr", "%04X", uhf_tag_get_epc_pc(uhf_tag));
+        memcpy(cmd + 14, tmp_arr, 4);
+        memcpy(cmd + 18, uhf_tag_get_epc(uhf_tag), uhf_tag_get_epc_size(uhf_tag));
+        break;
+    case UserBank:
+        payload_len += uhf_tag_get_user_size(uhf_tag);
+        data_length = uhf_tag_get_user_size(uhf_tag);
+        // set data
+        memcpy(cmd + 14, uhf_tag_get_user(uhf_tag), uhf_tag_get_user_size(uhf_tag));
+        break;
+    default:
+        return M100MemoryOverrun;
+    }
+    // set payload length
+    cmd[3] = (payload_len >> 8) & 0xFF;
+    cmd[4] = payload_len & 0xFF;
+    // set access password
+    cmd[5] = (access_pwd >> 24) & 0xFF;
+    cmd[6] = (access_pwd >> 16) & 0xFF;
+    cmd[7] = (access_pwd >> 8) & 0xFF;
+    cmd[8] = access_pwd & 0xFF;
+    // set membank
+    cmd[9] = (uint8_t)bank;
+    // set source address
+    cmd[10] = (source_address >> 8) & 0xFF;
+    cmd[11] = source_address & 0xFF;
+    // set data length
+    size_t data_length_words = data_length / 2;
+    cmd[12] = (data_length_words >> 8) & 0xFF;
+    cmd[13] = data_length_words & 0xFF;
+    // update cmd len
+    cmd_length = 5 + payload_len;
+    // calculate checksum
+    cmd[cmd_length - 2] = checksum(cmd + 1, cmd_length - 3);
+    cmd[cmd_length - 1] = FRAME_END;
+    // send cmd
+    for(size_t i = 0; i < cmd_length; i++) {
+        FURI_LOG_E("m100", "cmd[%d]=%02X", i, cmd[i]);
+    }
+    furi_hal_uart_set_irq_cb(FuriHalUartIdUSART1, rx_callback, module->buf);
+    furi_hal_uart_tx(FuriHalUartIdUSART1, cmd, cmd_length);
+    furi_delay_ms(DELAY_MS);
+    uint8_t* buff_data = buffer_get_data(module->buf);
+    size_t buff_length = buffer_get_size(module->buf);
+    if(buff_data[2] == 0xFF && buff_length == 8)
+        return M100NoTagResponse;
+    else if(buff_data[2] == 0xFF)
+        return M100ValidationFail;
+    return M100Success;
+}
 void m100_set_baudrate(M100Module* module, uint16_t baudrate) {
     size_t length = CMD_SET_COMMUNICATION_BAUD_RATE.length;
     uint8_t cmd[length];
@@ -246,7 +349,6 @@ void m100_set_baudrate(M100Module* module, uint16_t baudrate) {
     uint16_t br_mod = baudrate / 100; // module format
     cmd[6] = 0xFF & br_mod; // pow LSB
     cmd[5] = 0xFF & (br_mod >> 4); // pow MSB
-    // furi_hal_uart_set_irq_cb(FuriHalUartIdUSART1, NULL, NULL);
     furi_hal_uart_tx(FuriHalUartIdUSART1, cmd, length);
     furi_hal_uart_set_br(FuriHalUartIdUSART1, baudrate);
     module->baudrate = baudrate;

+ 37 - 18
uhf_module.h

@@ -10,29 +10,36 @@
 #define FRAME_END 0x7E
 #define DEFAULT_BAUDRATE 115200
 
-typedef struct{
+typedef struct {
     char* hw_version;
     char* sw_version;
     char* manufacturer;
-}M100ModuleInfo;
+} M100ModuleInfo;
 
-typedef enum{
-    WA_CHINA_900 = 1,  // Freq_CH-920.125M
-    WA_US,             // Freq_CH-902.25M
-    WA_EU,             // Freq_CH-865.1M
-    WA_CHINA_800,      // Freq_CH-840.125M
-    WA_KOREA = 6       // Freq_CH-917.1M
+typedef enum {
+    WA_CHINA_900 = 1,   // Freq_CH-920.125M
+    WA_US,              // Freq_CH-902.25M
+    WA_EU,              // Freq_CH-865.1M
+    WA_CHINA_800,       // Freq_CH-840.125M
+    WA_KOREA = 6        // Freq_CH-917.1M
 } WorkingArea;
 
-typedef enum{
-    WC_CHINA_900 = 1,  // CH_Index(CN,900MHz) = (Freq_CH-920.125M)/0.25M
-    WC_US,             // CH_Index(US) = (Freq_CH-902.25M)/0.5M
-    WC_EU,             // CH_Index(EU) = (Freq_CH-865.1M)/0.2M
-    WC_CHINA_800,      // CH_Index(CN,800MHz) = (Freq_CH-840.125M)/0.25M
-    WC_KOREA = 6       // CH_Index(Korea) = (Freq_CH-917.1M)/0.2M
+typedef enum {
+    WC_CHINA_900 = 1,   // CH_Index(CN,900MHz) = (Freq_CH-920.125M)/0.25M
+    WC_US,              // CH_Index(US) = (Freq_CH-902.25M)/0.5M
+    WC_EU,              // CH_Index(EU) = (Freq_CH-865.1M)/0.2M
+    WC_CHINA_800,       // CH_Index(CN,800MHz) = (Freq_CH-840.125M)/0.25M
+    WC_KOREA = 6        // CH_Index(Korea) = (Freq_CH-917.1M)/0.2M
 } WorkingChannel;
 
-typedef struct{
+typedef enum {
+    M100Success,
+    M100ValidationFail,
+    M100NoTagResponse,
+    M100MemoryOverrun
+} M100ResponseType;
+
+typedef struct {
     M100ModuleInfo* info;
     uint16_t baudrate;
     WorkingArea area;
@@ -63,6 +70,18 @@ bool m100_set_transmitting_power(M100Module* module, uint16_t power);
 bool m100_set_freq_hopping(M100Module* module, bool hopping);
 
 // gen2 cmds
-UHFTag* m100_send_single_poll(M100Module* module);
-bool m100_set_select(M100Module* module, UHFTag* uhf_tag);
-bool m100_read_label_data_storage(M100Module* module, UHFTag* uhf_tag, BankType bank, uint32_t access_pwd);
+M100ResponseType m100_send_single_poll(M100Module* module, UHFTag* uhf_tag);
+M100ResponseType m100_set_select(M100Module* module, UHFTag* uhf_tag);
+M100ResponseType m100_read_label_data_storage(
+    M100Module* module,
+    UHFTag* uhf_tag,
+    BankType bank,
+    uint32_t access_pwd,
+    uint16_t word_count);
+
+M100ResponseType m100_write_label_data_storage(
+    M100Module* module,
+    UHFTag* uhf_tag,
+    BankType bank,
+    uint16_t source_address,
+    uint32_t access_pwd);

+ 59 - 0
uhf_tag.c

@@ -9,6 +9,9 @@ UHFTagWrapper* uhf_tag_wrapper_alloc() {
 }
 
 void uhf_tag_wrapper_set_tag(UHFTagWrapper* uhf_tag_wrapper, UHFTag* uhf_tag) {
+    if(uhf_tag_wrapper->uhf_tag != NULL) {
+        uhf_tag_free(uhf_tag_wrapper->uhf_tag);
+    }
     uhf_tag_wrapper->uhf_tag = uhf_tag;
 }
 
@@ -54,4 +57,60 @@ void uhf_tag_set_epc_crc(UHFTag* uhf_tag, uint16_t crc) {
 void uhf_tag_set_epc(UHFTag* uhf_tag, uint8_t* data_in, size_t size) {
     memcpy(uhf_tag->epc->data, data_in, size);
     uhf_tag->epc->size = size;
+}
+
+void uhf_tag_set_epc_size(UHFTag* uhf_tag, size_t size) {
+    uhf_tag->epc->size = size;
+}
+
+void uhf_tag_set_tid(UHFTag* uhf_tag, uint8_t* data_in, size_t size) {
+    memcpy(uhf_tag->tid->data, data_in, size);
+    uhf_tag->tid->size = size;
+}
+
+void uhf_tag_set_tid_size(UHFTag* uhf_tag, size_t size) {
+    uhf_tag->tid->size = size;
+}
+
+void uhf_tag_set_user(UHFTag* uhf_tag, uint8_t* data_in, size_t size) {
+    memcpy(uhf_tag->user->data, data_in, size);
+    uhf_tag->user->size = size;
+}
+
+void uhf_tag_set_user_size(UHFTag* uhf_tag, size_t size) {
+    uhf_tag->user->size = size;
+}
+
+// getters
+
+uint8_t* uhf_tag_get_epc(UHFTag* uhf_tag) {
+    return uhf_tag->epc->data;
+}
+
+size_t uhf_tag_get_epc_size(UHFTag* uhf_tag) {
+    return uhf_tag->epc->size;
+}
+
+uint16_t uhf_tag_get_epc_pc(UHFTag* uhf_tag) {
+    return uhf_tag->epc->pc;
+}
+
+uint16_t uhf_tag_get_epc_crc(UHFTag* uhf_tag) {
+    return uhf_tag->epc->crc;
+}
+
+uint8_t* uhf_tag_get_tid(UHFTag* uhf_tag) {
+    return uhf_tag->tid->data;
+}
+
+size_t uhf_tag_get_tid_size(UHFTag* uhf_tag) {
+    return uhf_tag->tid->size;
+}
+
+uint8_t* uhf_tag_get_user(UHFTag* uhf_tag) {
+    return uhf_tag->user->data;
+}
+
+size_t uhf_tag_get_user_size(UHFTag* uhf_tag) {
+    return uhf_tag->user->size;
 }

+ 5 - 0
uhf_tag.h

@@ -58,12 +58,17 @@ void uhf_tag_set_access_pwd(UHFTag* uhf_tag, uint8_t* data_in);
 void uhf_tag_set_epc_pc(UHFTag* uhf_tag, uint16_t pc);
 void uhf_tag_set_epc_crc(UHFTag* uhf_tag, uint16_t crc);
 void uhf_tag_set_epc(UHFTag* uhf_tag, uint8_t* data_in, size_t size);
+void uhf_tag_set_epc_size(UHFTag* uhf_tag, size_t size);
 void uhf_tag_set_tid(UHFTag* uhf_tag, uint8_t* data_in, size_t size);
+void uhf_tag_set_tid_size(UHFTag* uhf_tag, size_t size);
 void uhf_tag_set_user(UHFTag* uhf_tag, uint8_t* data_in, size_t size);
+void uhf_tag_set_user_size(UHFTag* uhf_tag, size_t size);
 
 uint8_t* uhf_tag_get_kill_pwd(UHFTag* uhf_tag);
 uint8_t* uhf_tag_get_access_pwd(UHFTag* uhf_tag);
 uint8_t* uhf_tag_get_epc(UHFTag* uhf_tag);
+uint16_t uhf_tag_get_epc_pc(UHFTag* uhf_tag);
+uint16_t uhf_tag_get_epc_crc(UHFTag* uhf_tag);
 size_t uhf_tag_get_epc_size(UHFTag* uhf_tag);
 uint8_t* uhf_tag_get_tid(UHFTag* uhf_tag);
 size_t uhf_tag_get_tid_size(UHFTag* uhf_tag);

+ 59 - 163
uhf_worker.c

@@ -11,62 +11,17 @@ UHFWorkerEvent verify_module_connected(UHFWorker* uhf_worker) {
     return UHFWorkerEventSuccess;
 }
 
-uint8_t get_epc_length_in_bits(uint8_t pc) {
-    uint8_t epc_length = pc;
-    epc_length >>= 3;
-    return (uint8_t)epc_length * 16; // x-words * 16 bits
-}
-
-// bool read_bank(UHFData* read_bank_cmd, UHFData* response_bank, UHFBank bank) {
-//     furi_hal_uart_set_irq_cb(FuriHalUartIdUSART1, module_rx_callback, response_bank);
-//     read_bank_cmd->data[9] = bank;
-//     read_bank_cmd->data[read_bank_cmd->length - 2] = uhf_data_calculate_checksum(read_bank_cmd);
-//     uhf_data_reset(response_bank);
-//     furi_hal_uart_tx(FuriHalUartIdUSART1, read_bank_cmd->data, read_bank_cmd->length);
-//     furi_delay_ms(CB_DELAY);
-//     return response_bank->data[2] == read_bank_cmd->data[2];
-// }
-
-// bool write_bank(UHFData* write_bank_cmd, UHFBank bank, uint8_t* bank_data, size_t bank_len) {
-//     UHFData* rp_data = uhf_data_alloc();
-//     write_bank_cmd->end = false;
-//     for(size_t i = 0; i < write_bank_cmd->length; i++) {
-//         continue;
-//     }
-//     furi_hal_uart_set_irq_cb(FuriHalUartIdUSART1, module_rx_callback, rp_data);
-//     for(int i = 5; i < 9; i++) { // no access password for now
-//         write_bank_cmd->data[i] = 0;
-//     }
-//     write_bank_cmd->data[9] = bank;
-//     size_t word_len = bank_len / 2;
-//     write_bank_cmd->data[13] = word_len;
-//     write_bank_cmd->length = 14;
-//     write_bank_cmd->start = true;
-//     for(size_t i = 0; i < bank_len; i++) {
-//         uhf_data_append(write_bank_cmd, bank_data[i]);
-//     }
-//     uhf_data_append(write_bank_cmd, 00);
-//     uhf_data_append(write_bank_cmd, FRAME_END);
-//     write_bank_cmd->data[4] = write_bank_cmd->length - 7;
-//     write_bank_cmd->data[write_bank_cmd->length - 2] = uhf_data_calculate_checksum(write_bank_cmd);
-//     furi_hal_uart_tx(FuriHalUartIdUSART1, write_bank_cmd->data, write_bank_cmd->length);
-//     furi_delay_ms(CB_DELAY);
-//     bool success = rp_data->data[2] == write_bank_cmd->data[2];
-//     uhf_data_free(rp_data);
-//     return success;
-// }
-
 UHFTag* send_polling_command(UHFWorker* uhf_worker) {
     // read epc bank
-    UHFTag* uhf_tag;
+    UHFTag* uhf_tag = uhf_tag_alloc();
     while(true) {
-        uhf_tag = m100_send_single_poll(uhf_worker->module);
+        M100ResponseType status = m100_send_single_poll(uhf_worker->module, uhf_tag);
         furi_delay_ms(100);
         if(uhf_worker->state == UHFWorkerStateStop) {
+            uhf_tag_free(uhf_tag);
             return NULL;
         }
-        if(uhf_tag != NULL) break;
-        FURI_LOG_E("WKR", "null still");
+        if(status == M100Success) break;
     }
     return uhf_tag;
 }
@@ -76,120 +31,62 @@ UHFWorkerEvent read_single_card(UHFWorker* uhf_worker) {
     if(uhf_tag == NULL) return UHFWorkerEventAborted;
     uhf_tag_wrapper_set_tag(uhf_worker->uhf_tag_wrapper, uhf_tag);
     // Todo : set select here
-    bool select_success = m100_set_select(uhf_worker->module, uhf_tag);
-    FURI_LOG_E("TAG", "select success = %d", select_success);
-
-    // Todo : read rfu
-    m100_read_label_data_storage(uhf_worker->module, uhf_tag, ReservedBank, 0);
-    // Todo : read epc
-    m100_read_label_data_storage(uhf_worker->module, uhf_tag, EPCBank, 0);
+    if(!m100_set_select(uhf_worker->module, uhf_tag)) return UHFWorkerEventFail;
     // Todo : read tid
-    m100_read_label_data_storage(uhf_worker->module, uhf_tag, TIDBank, 0);
-    // Todo : read user
-    m100_read_label_data_storage(uhf_worker->module, uhf_tag, UserBank, 0);
-    // add to tag object
-    // UHFData* raw_bank_data = uhf_data_alloc();
-    // size_t epc_length = (size_t)get_epc_length_in_bits(raw_read_data->data[6]) / 8;
-    // size_t offset = (size_t)(8 + epc_length);
-
-    // UHFData* read_bank_cmd = uhf_data_alloc();
-    // read_bank_cmd->length = CMD_READ_LABEL_DATA_STORAGE.length;
-    // memcpy(
-    //     (void*)&read_bank_cmd->data[0],
-    //     (void*)&CMD_READ_LABEL_DATA_STORAGE.cmd[0],
-    //     read_bank_cmd->length);
-
-    // if(!send_set_select_command(raw_read_data, EPC_BANK)) return UHFWorkerEventFail;
-
-    // int retry = 3;
-    // do {
-    //     if(read_bank(read_bank_cmd, raw_bank_data, EPC_BANK)) {
-    //         uhf_tag_set_epc(uhf_tag, raw_bank_data->data + offset, epc_length + 2);
-    //         break;
-    //     }
-
-    // } while(retry--);
-    // // // debug
-    // // furi_string_reset(temp_str);
-    // // for(size_t i = 0; i < raw_bank_data->length; i++) {
-    // //     furi_string_cat_printf(temp_str, "%02x ", raw_bank_data->data[i]);
-    // // }
-    // // FURI_LOG_E("TAG", "data = %s", furi_string_get_cstr(temp_str));
-    // // // e-debug
-    // uhf_data_reset(raw_bank_data);
-    // retry = 3;
-    // do {
-    //     if(read_bank(read_bank_cmd, raw_bank_data, TID_BANK)) {
-    //         uhf_tag_set_tid(uhf_tag, raw_bank_data->data + offset, 16);
-    //         break;
-    //     }
-    // } while(retry--);
-    // // // debug
-    // // furi_string_reset(temp_str);
-    // // for(size_t i = 0; i < raw_bank_data->length; i++) {
-    // //     furi_string_cat_printf(temp_str, "%02x ", raw_bank_data->data[i]);
-    // // }
-    // // FURI_LOG_E("TAG", "data = %s", furi_string_get_cstr(temp_str));
-    // // // e-debug
-    // uhf_data_reset(raw_bank_data);
-    // retry = 3;
-    // if(raw_read_data->data[6] & 0x04) {
-    //     do {
-    //         if(read_bank(read_bank_cmd, raw_bank_data, USER_BANK)) {
-    //             uhf_tag_set_user(uhf_tag, raw_bank_data->data + offset, 16);
-    //             break;
-    //         }
-    //     } while(retry--);
-    // }
-    // // // debug
-    // // furi_string_reset(temp_str);
-    // // for(size_t i = 0; i < raw_bank_data->length; i++) {
-    // //     furi_string_cat_printf(temp_str, "%02x ", raw_bank_data->data[i]);
-    // // }
-    // // FURI_LOG_E("TAG", "data = %s", furi_string_get_cstr(temp_str));
-    // // // e-debug
-    // uhf_data_reset(raw_bank_data);
-    // uhf_data_free(raw_bank_data);
-    // uhf_data_free(read_bank_cmd);
-    // // debug
-    // // furi_string_free(temp_str);
-    // // e-debug
-
+    int retry = 3, word_count = 5;
+    do {
+        if(uhf_worker->state == UHFWorkerStateStop) return UHFWorkerEventAborted;
+        M100ResponseType status =
+            m100_read_label_data_storage(uhf_worker->module, uhf_tag, TIDBank, 0, word_count);
+        switch(status) {
+        case M100Success:
+            word_count++;
+            break;
+        case M100NoTagResponse:
+            retry--;
+            break;
+        default:
+            retry = 0;
+            break;
+        }
+    } while(retry);
+    retry = 3;
+    word_count = 5;
+    do {
+        if(uhf_worker->state == UHFWorkerStateStop) return UHFWorkerEventAborted;
+        M100ResponseType status =
+            m100_read_label_data_storage(uhf_worker->module, uhf_tag, UserBank, 0, word_count);
+        switch(status) {
+        case M100Success:
+            word_count++;
+            break;
+        case M100NoTagResponse:
+            retry--;
+            break;
+        default:
+            retry = 0;
+            break;
+        }
+    } while(retry);
     return UHFWorkerEventSuccess;
 }
 
-// UHFWorkerEvent write_single_card(UHFWorker* uhf_worker) {
-//     UHFResponseData* uhf_response_data = uhf_worker->response_data;
-//     uhf_response_data_reset(uhf_response_data);
-//     UHFData* raw_read_data = uhf_response_data_get_uhf_data(uhf_response_data, 0);
-//     furi_hal_uart_set_br(FuriHalUartIdUSART1, DEFAULT_BAUD_RATE);
-
-//     send_polling_command(uhf_worker, raw_read_data);
-//     // todo : rfu ?
-//     UHFTag* uhf_tag = uhf_worker->uhf_tag;
-
-//     UHFData* write_bank_cmd = uhf_data_alloc();
-//     write_bank_cmd->length = CMD_WRITE_LABEL_DATA_STORAGE.length;
-
-//     memcpy(
-//         (void*)&write_bank_cmd->data[0],
-//         (void*)&CMD_WRITE_LABEL_DATA_STORAGE.cmd[0],
-//         write_bank_cmd->length);
-//     if(!send_set_select_command(raw_read_data, EPC_BANK)) return UHFWorkerEventFail;
-
-//     if(raw_read_data->data[6] & 0x04) {
-//         if(!write_bank(write_bank_cmd, USER_BANK, uhf_tag->user, uhf_tag->user_length))
-//             return UHFWorkerEventFail;
-//     }
-//     uint8_t write_data[uhf_tag->epc_length + 2];
-//     memcpy(&write_data, &raw_read_data->data[raw_read_data->length - 4], 2);
-//     memcpy(&write_data[2], &uhf_tag->epc, uhf_tag->epc_length);
-//     write_data[10] = 0xF1;
-//     if(!write_bank(write_bank_cmd, EPC_BANK, write_data, uhf_tag->epc_length + 2)) {
-//         return UHFWorkerEventFail;
-//     }
-//     return UHFWorkerEventSuccess;
-// }
+UHFWorkerEvent write_single_card(UHFWorker* uhf_worker) {
+    UHFTag* uhf_tag_des = send_polling_command(uhf_worker);
+    if(uhf_tag_des == NULL) return UHFWorkerEventAborted;
+    FURI_LOG_E("wkr", "read success");
+    UHFTag* uhf_tag_from = uhf_worker->uhf_tag_wrapper->uhf_tag;
+    if(m100_set_select(uhf_worker->module, uhf_tag_des) != M100Success) return UHFWorkerEventFail;
+    FURI_LOG_E("wkr", "set select success");
+    do {
+        M100ResponseType rp_type =
+            m100_write_label_data_storage(uhf_worker->module, uhf_tag_from, EPCBank, 0, 0);
+        FURI_LOG_E("wkr", "try to write %d", rp_type);
+        if(uhf_worker->state == UHFWorkerStateStop) return UHFWorkerEventAborted;
+        if(rp_type == M100Success) break;
+    } while(true);
+    return UHFWorkerEventSuccess;
+}
 
 int32_t uhf_worker_task(void* ctx) {
     UHFWorker* uhf_worker = ctx;
@@ -199,11 +96,10 @@ int32_t uhf_worker_task(void* ctx) {
     } else if(uhf_worker->state == UHFWorkerStateDetectSingle) {
         UHFWorkerEvent event = read_single_card(uhf_worker);
         uhf_worker->callback(event, uhf_worker->ctx);
+    } else if(uhf_worker->state == UHFWorkerStateWriteSingle) {
+        UHFWorkerEvent event = write_single_card(uhf_worker);
+        uhf_worker->callback(event, uhf_worker->ctx);
     }
-    // else if(uhf_worker->state == UHFWorkerStateWriteSingle) {
-    //     UHFWorkerEvent event = write_single_card(uhf_worker);
-    //     uhf_worker->callback(event, uhf_worker->ctx);
-    // }
     return 0;
 }