Chaka 2 лет назад
Родитель
Сommit
816f4f1608
5 измененных файлов с 101 добавлено и 165 удалено
  1. 21 83
      README.md
  2. BIN
      assets/img/uhf_demo_app2.jpg
  3. 41 38
      uhf_module.c
  4. 2 2
      uhf_module.h
  5. 37 42
      uhf_worker.c

+ 21 - 83
README.md

@@ -1,21 +1,33 @@
 # [UHF]RFID App for FlipperZero
 
-![FlipperZero](assets/img/uhf_demo_app.jpg)
+![FlipperZero](assets/img/uhf_demo_app2.jpg)
 
 ## Overview
 
 This repository contains a UHF RFID application developed for FlipperZero, a versatile multi-tool device. The app leverages the YRM100 module to enable UHF RFID functionality.
 
+## What's Changed
+
+- A complete refractor from the concept code to covert to a framework. So that it's easy to refractor for different possible module's. See [module.h](uhf_module.h) for more info.
+- Reading bank now can automatically detect bank size, for cases that PC(protocol control) bits aren't properly written to tag.
+- Can now view tag from saved.
+- Can now write tags from saved.
+
 ## Features
 
 - [x] Read Single UHF RFID tag.
 - [x] View saved UHF RFID tag.
-- [ ] Write Single UHF RFID tag. __(in progress)__
-- [ ] Change Module setting parameters.
-- [ ] Easy-to-use interface on FlipperZero's display.
-    - Extras
-        - [ ] Read multiple tags at once
-        - [ ] View multiple on a list view
+- [x] Write Single UHF RFID tag.
+- [ ] Change Module setting parameters. __(In Progress)__
+    - [ ] Set/Reset Access Password
+    - [ ] Set Kill Password
+    - [ ] Kill Tag
+    - [ ] TBD
+- [ ] Edit/Create new data to write.
+- Extras
+    - [ ] Read multiple tags at once
+    - [ ] View multiple on a list view
+
 
 ## Requirements
 
@@ -49,82 +61,6 @@ To run this application on FlipperZero, you will need:
 
 As this app is still in the development stage, I welcome contributions to this project. If you find any issues or want to enhance the application, feel free to create a pull request.
 
-<!-- ## License
-
-This project is licensed under the [MIT License](link_to_license_file). -->
-
-## Future Plans
-- Code cleanup
-- Build a framework around the chip communication commands
-- Build a proper tag class
-```c
-// Ideal concept
-#include <stdint.h>
-#include <stdio.h>
-#include <string.h>
-
-typedef struct {
-    int uart_fd; // UART file descriptor or other identifier
-} YRM100_RFID;
-
-void sendCommand(YRM100_RFID *rfid, const uint8_t *command, size_t length) {
-    // Implementation to send the command through UART
-    // Write the command to the UART interface using rfid->uart_fd
-}
-
-// Configuration functions:
-
-void setCommunicationBaudRate(YRM100_RFID *rfid) {
-    uint8_t command[] = {0xBB, 0x00, 0x11, 0x00, 0x02, 0x00, 0xC0, 0xD3, 0x7E};
-    sendCommand(rfid, command, sizeof(command));
-}
-
-void setWorkingArea(YRM100_RFID *rfid, uint8_t area) {
-    uint8_t command[] = {0xBB, 0x00, 0x07, 0x00, 0x01, area, 0x09, 0x7E}; 
-    sendCommand(rfid, command, sizeof(command));
-}
-
-// other method etc ... 
-```
-
-```c
-// Ideal concept
-#include <stdint.h>
-#include <stdlib.h>
-
-typedef struct {
-    uint8_t *killPassword;
-    uint8_t *accessPassword;
-    size_t size;
-} ReservedMemory;
-
-typedef struct {
-    uint8_t *header;
-    uint8_t *filter;
-    uint8_t *partition;
-    uint8_t *companyPrefix;
-    uint8_t *itemReference;
-    size_t size;
-} EPCMemory;
-
-typedef struct {
-    uint8_t *tid;
-    size_t size;
-} TIDMemory;
-
-typedef struct {
-    uint8_t *userMemory;
-    size_t size;
-} UserMemory;
-
-typedef struct {
-    ReservedMemory reserved;
-    EPCMemory epc;
-    TIDMemory tid;
-    UserMemory user;
-} ISO18000_6C_Tag;
-```
-
 ## Disclaimer
 
 - This application is provided as-is and may contain bugs or issues.
@@ -134,6 +70,8 @@ typedef struct {
 ## Extra Resources
 
 - [MagicRF M100&QM100_Firmware_manual_en.pdf](assets/res/MagicRF_M100&QM100_Firmware_manual_en.pdf)
+- [TDS_1_9_Standard.pdf](assets/res/TDS_1_9_Standard.pdf)
+- [M5Stack Docs](https://docs.m5stack.com/en/unit/uhf_rfid)
 
 ## Contact
 

BIN
assets/img/uhf_demo_app2.jpg


+ 41 - 38
uhf_module.c

@@ -180,6 +180,8 @@ M100ResponseType m100_set_select(M100Module* module, UHFTag* uhf_tag) {
     // payload len = sel param len + ptr len + mask len + epc len
     size_t payload_len = 7 + mask_length_bytes;
     memcpy(cmd, CMD_SET_SELECT_PARAMETER.cmd, cmd_length);
+    // set new length
+    cmd_length = 12 + mask_length_bytes + 2;
     // set payload length
     cmd[3] = (payload_len >> 8) & 0xFF;
     cmd[4] = payload_len & 0xFF;
@@ -193,10 +195,11 @@ M100ResponseType m100_set_select(M100Module* module, UHFTag* uhf_tag) {
     cmd[11] = false;
     // set mask
     memcpy((void*)&cmd[12], uhf_tag->epc->data, mask_length_bytes);
+
     // set checksum
-    cmd[12 + mask_length_bytes + 1] = checksum(cmd + 1, 11 + mask_length_bytes);
+    cmd[cmd_length - 2] = checksum(cmd + 1, 11 + mask_length_bytes);
     // end frame
-    cmd[12 + mask_length_bytes + 2] = FRAME_END;
+    cmd[cmd_length - 1] = FRAME_END;
     furi_hal_uart_set_irq_cb(FuriHalUartIdLPUART1, rx_callback, module->buf);
     furi_hal_uart_tx(FuriHalUartIdUSART1, cmd, 12 + mask_length_bytes + 3);
     furi_delay_ms(DELAY_MS);
@@ -208,8 +211,18 @@ M100ResponseType m100_set_select(M100Module* module, UHFTag* uhf_tag) {
     return M100Success;
 }
 
-UHFTag* m100_get_select_param(M100Module module) {
-    UNUSED(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_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();
+    // uint8_t* data = buffer_get_data(module->buf);
+    // size_t mask_length =
+    // uhf_tag_set_epc(uhf_tag, data + 12, )
     return NULL;
 }
 
@@ -251,22 +264,18 @@ M100ResponseType m100_read_label_data_storage(
         if(payload_len == 0x0001) return M100NoTagResponse;
         return M100MemoryOverrun;
     }
-    switch(bank) {
-    case TIDBank:
+    if(bank == TIDBank) {
         uhf_tag_set_tid(uhf_tag, data + ptr_offset, bank_data_length);
-        break;
-    case UserBank:
+    } else if(bank == 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,
+    UHFTag* saved_tag,
+    UHFTag* selected_tag,
     BankType bank,
     uint16_t source_address,
     uint32_t access_pwd) {
@@ -275,35 +284,28 @@ M100ResponseType m100_write_label_data_storage(
     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:
+    uint16_t data_length = 0;
+    if(bank == ReservedBank) {
         // access pwd len + kill pwd len
         payload_len += 4;
         data_length = 4;
-        break;
-    case EPCBank:
+    } else if(bank == 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);
+        payload_len += 4 + uhf_tag_get_epc_size(saved_tag);
+        data_length = 4 + uhf_tag_get_epc_size(saved_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));
+        tmp_arr[0] = (uint8_t)((uhf_tag_get_epc_crc(selected_tag) >> 8) & 0xFF);
+        tmp_arr[1] = (uint8_t)(uhf_tag_get_epc_crc(selected_tag) & 0xFF);
+        tmp_arr[2] = (uint8_t)((uhf_tag_get_epc_pc(saved_tag) >> 8) & 0xFF);
+        tmp_arr[3] = (uint8_t)(uhf_tag_get_epc_pc(saved_tag) & 0xFF);
         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);
+        memcpy(cmd + 18, uhf_tag_get_epc(saved_tag), uhf_tag_get_epc_size(saved_tag));
+    } else if(bank == UserBank) {
+        payload_len += uhf_tag_get_user_size(saved_tag);
+        data_length = uhf_tag_get_user_size(saved_tag);
         // set data
-        memcpy(cmd + 14, uhf_tag_get_user(uhf_tag), uhf_tag_get_user_size(uhf_tag));
-        break;
-    default:
-        return M100MemoryOverrun;
+        memcpy(cmd + 14, uhf_tag_get_user(saved_tag), uhf_tag_get_user_size(saved_tag));
     }
     // set payload length
     cmd[3] = (payload_len >> 8) & 0xFF;
@@ -323,17 +325,18 @@ M100ResponseType m100_write_label_data_storage(
     cmd[12] = (data_length_words >> 8) & 0xFF;
     cmd[13] = data_length_words & 0xFF;
     // update cmd len
-    cmd_length = 5 + payload_len;
+    cmd_length = 7 + 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 max_wait = 25;
+    while(!buffer_get_size(module->buf)) {
+        furi_delay_ms(DELAY_MS);
+        if(!max_wait--) break;
+    }
     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)

+ 2 - 2
uhf_module.h

@@ -62,7 +62,6 @@ char* m100_get_hardware_version(M100Module* module);
 char* m100_get_software_version(M100Module* module);
 char* m100_get_manufacturers(M100Module* module);
 
-// set attrs
 void m100_set_baudrate(M100Module* module, uint16_t baudrate);
 bool m100_set_working_area(M100Module* module, WorkingArea area);
 bool m100_set_working_channel(M100Module* module, WorkingChannel channel);
@@ -81,7 +80,8 @@ M100ResponseType m100_read_label_data_storage(
 
 M100ResponseType m100_write_label_data_storage(
     M100Module* module,
-    UHFTag* uhf_tag,
+    UHFTag* saved_tag,
+    UHFTag* selected_tag,
     BankType bank,
     uint16_t source_address,
     uint32_t access_pwd);

+ 37 - 42
uhf_worker.c

@@ -26,62 +26,57 @@ UHFTag* send_polling_command(UHFWorker* uhf_worker) {
     return uhf_tag;
 }
 
-UHFWorkerEvent read_single_card(UHFWorker* uhf_worker) {
-    UHFTag* uhf_tag = send_polling_command(uhf_worker);
-    if(uhf_tag == NULL) return UHFWorkerEventAborted;
-    uhf_tag_wrapper_set_tag(uhf_worker->uhf_tag_wrapper, uhf_tag);
-    // Todo : set select here
-    if(!m100_set_select(uhf_worker->module, uhf_tag)) return UHFWorkerEventFail;
-    // Todo : read tid
-    int retry = 3, word_count = 5;
+static UHFWorkerEvent
+    read_bank_till_max_length(UHFWorker* uhf_worker, UHFTag* uhf_tag, BankType bank) {
+    unsigned int retry = 3, word_low = 5, word_high = 100;
+    unsigned int word_size;
+    M100ResponseType status;
     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:
+        if(word_low >= word_high) return UHFWorkerEventSuccess;
+        word_size = (word_low + word_high) / 2;
+        status = m100_read_label_data_storage(uhf_worker->module, uhf_tag, bank, 0, word_size);
+        if(status == M100Success) {
+            word_low = word_size + 1;
+        } else if(status == M100MemoryOverrun) {
+            word_high = word_size - 1;
+        } else if(status == 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 read_single_card(UHFWorker* uhf_worker) {
+    UHFTag* uhf_tag = send_polling_command(uhf_worker);
+    if(uhf_tag == NULL) return UHFWorkerEventAborted;
+    uhf_tag_wrapper_set_tag(uhf_worker->uhf_tag_wrapper, uhf_tag);
+    // Todo : set select here
+    if(m100_set_select(uhf_worker->module, uhf_tag) != M100Success) return UHFWorkerEventFail;
+    // read tid
+    UHFWorkerEvent event;
+    event = read_bank_till_max_length(uhf_worker, uhf_tag, TIDBank);
+    if(event != UHFWorkerEventSuccess) return event;
+    // read user
+    event = read_bank_till_max_length(uhf_worker, uhf_tag, UserBank);
+    if(event != UHFWorkerEventSuccess) return event;
+    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);
+        M100ResponseType rp_type = m100_write_label_data_storage(
+            uhf_worker->module, uhf_tag_from, uhf_tag_des, UserBank, 0, 0);
+        if(uhf_worker->state == UHFWorkerStateStop) return UHFWorkerEventAborted;
+        if(rp_type == M100Success) break;
+    } while(true);
+    do {
+        M100ResponseType rp_type = m100_write_label_data_storage(
+            uhf_worker->module, uhf_tag_from, uhf_tag_des, EPCBank, 0, 0);
         if(uhf_worker->state == UHFWorkerStateStop) return UHFWorkerEventAborted;
         if(rp_type == M100Success) break;
     } while(true);