Browse Source

Merge pull request #2 from frux-c/detailed_read

Detailed read
Abel Chaka 2 years ago
parent
commit
b7d51b0866
11 changed files with 232 additions and 83 deletions
  1. 12 4
      README.md
  2. 2 2
      scenes/uhf_scene_read_tag_success.c
  3. 6 6
      scenes/uhf_scene_verify.c
  4. 40 5
      uhf_app.c
  5. 1 0
      uhf_app_i.h
  6. 0 9
      uhf_cmd.c
  7. 42 39
      uhf_cmd.h
  8. 0 1
      uhf_data.c
  9. 1 1
      uhf_data.h
  10. 125 15
      uhf_worker.c
  11. 3 1
      uhf_worker.h

+ 12 - 4
README.md

@@ -8,10 +8,14 @@ This repository contains a UHF RFID application developed for FlipperZero, a ver
 
 ## Features
 
-- [x] Read UHF RFID tags.
-- [ ] Write UHF RFID tags.
+- [x] Read Single UHF RFID tag.
+- [ ] View saved UHF RFID tag. __(in progress)__
+- [ ] Write Single UHF RFID tag.
 - [ ] Communicate with the YRM100 module to perform UHF RFID operations.
 - [ ] Easy-to-use interface on FlipperZero's display.
+    - Extras
+        - [ ] Read multiple tags at once
+        - [ ] View multiple on a list view
 
 ## Requirements
 
@@ -30,12 +34,16 @@ To run this application on FlipperZero, you will need:
      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`
+   - ### MacOS
+     ... tbd
 
 ## Usage
 
 1. Power on your FlipperZero device.
-2. Navigate to the UHF RFID app on FlipperZero's menu.
-3. (Add detailed instructions on how to use the UHF RFID app)
+2. Connect the uhf module to the flipper via gpio.
+3. Navigate to the UHF RFID app on FlipperZero's menu.
+4. Currently Reading the EPC tag is the only usable option
+... will further update this page as it development goes
 
 ## Contributions
 

+ 2 - 2
scenes/uhf_scene_read_tag_success.c

@@ -17,7 +17,8 @@ void uhf_scene_read_card_success_widget_callback(GuiButtonType result, InputType
 void uhf_scene_read_tag_success_on_enter(void* ctx) {
     UHFApp* uhf_app = ctx;
 
-    const uint8_t* read_data = uhf_app->worker->response_data->head->data;
+    const uint8_t* read_data =
+        uhf_response_data_get_uhf_data(uhf_app->worker->response_data, 0)->data;
 
     widget_add_string_element(
         uhf_app->widget, 32, 5, AlignLeft, AlignCenter, FontPrimary, "Read Success");
@@ -38,7 +39,6 @@ void uhf_scene_read_tag_success_on_enter(void* ctx) {
         AlignCenter,
         FontKeyboard,
         convertToHexString(read_data + 6, 2));
-
     widget_add_string_element(
         uhf_app->widget,
         96,

+ 6 - 6
scenes/uhf_scene_verify.c

@@ -61,7 +61,7 @@ bool uhf_scene_verify_on_event(void* ctx, SceneManagerEvent event) {
                     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++) {
+                for(int i = 0; i < (int)hardware_version->data[4]; i++) {
                     furi_string_cat_printf(temp_str, "%c", hardware_version->data[offset + i]);
                 }
                 widget_add_string_element(
@@ -69,13 +69,13 @@ bool uhf_scene_verify_on_event(void* ctx, SceneManagerEvent event) {
                     1,
                     15,
                     AlignLeft,
-                    AlignCenter,
+                    AlignTop,
                     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++) {
+                for(int i = 0; i < (int)software_version->data[4]; i++) {
                     furi_string_cat_printf(temp_str, "%c", software_version->data[offset + i]);
                 }
                 widget_add_string_element(
@@ -83,13 +83,13 @@ bool uhf_scene_verify_on_event(void* ctx, SceneManagerEvent event) {
                     1,
                     27,
                     AlignLeft,
-                    AlignCenter,
+                    AlignTop,
                     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++) {
+                for(int i = 0; i < (int)manufacturer->data[4]; i++) {
                     furi_string_cat_printf(temp_str, "%c", manufacturer->data[offset + i]);
                 }
                 widget_add_string_element(
@@ -97,7 +97,7 @@ bool uhf_scene_verify_on_event(void* ctx, SceneManagerEvent event) {
                     1,
                     39,
                     AlignLeft,
-                    AlignCenter,
+                    AlignTop,
                     FontSecondary,
                     furi_string_get_cstr(temp_str));
 

+ 40 - 5
uhf_app.c

@@ -2,6 +2,8 @@
 
 static const char* uhf_file_header = "Flipper UHF device";
 static const uint32_t uhf_file_version = 1;
+static const uint8_t bank_data_start = 20;
+static const uint8_t bank_data_length = 16;
 
 // empty callback
 void empty_rx_callback(UartIrqEvent event, uint8_t data, void* ctx) {
@@ -50,10 +52,44 @@ bool uhf_save_read_data(UHFResponseData* uhf_response_data, Storage* storage, co
     if(!flipper_format_file_open_always(file, furi_string_get_cstr(temp_str))) return false;
     // write header
     if(!flipper_format_write_header_cstr(file, uhf_file_header, uhf_file_version)) return false;
-    // write epc bank
-    if(!flipper_format_write_hex(
-           file, "EPC", uhf_response_data->head->data, uhf_response_data->head->length))
-        return false;
+    // write rfu data to file
+    UHFData* rfu_data = uhf_response_data_get_uhf_data(uhf_response_data, 1);
+    if(rfu_data->length) {
+        if(!flipper_format_write_hex(
+               file, "RFU", rfu_data->data + bank_data_start, bank_data_length))
+            return false;
+    } else {
+        if(!flipper_format_write_hex(file, "RFU", UHF_BANK_DOES_NOT_EXIST, 1)) return false;
+    }
+
+    // write epc data to file
+    UHFData* epc_data = uhf_response_data_get_uhf_data(uhf_response_data, 2);
+    if(epc_data->length) {
+        if(!flipper_format_write_hex(
+               file, "EPC", epc_data->data + bank_data_start, bank_data_length))
+            return false;
+    } else {
+        if(!flipper_format_write_hex(file, "EPC", UHF_BANK_DOES_NOT_EXIST, 1)) return false;
+    }
+
+    // write tid data to file
+    UHFData* tid_data = uhf_response_data_get_uhf_data(uhf_response_data, 3);
+    if(tid_data->length) {
+        if(!flipper_format_write_hex(
+               file, "TID", tid_data->data + bank_data_start, bank_data_length))
+            return false;
+    } else {
+        if(!flipper_format_write_hex(file, "TID", UHF_BANK_DOES_NOT_EXIST, 1)) return false;
+    }
+    // write user data to file
+    UHFData* user_data = uhf_response_data_get_uhf_data(uhf_response_data, 4);
+    if(user_data->length) {
+        if(!flipper_format_write_hex(
+               file, "USER", user_data->data + bank_data_start, bank_data_length))
+            return false;
+    } else {
+        if(!flipper_format_write_hex(file, "USER", UHF_BANK_DOES_NOT_EXIST, 1)) return false;
+    }
     furi_string_free(temp_str);
     flipper_format_free(file);
     return true;
@@ -217,7 +253,6 @@ int32_t uhf_app_main(void* ctx) {
 
     // enable 5v pin
     furi_hal_power_enable_otg();
-
     scene_manager_next_scene(uhf_app->scene_manager, UHFSceneVerify);
     view_dispatcher_run(uhf_app->view_dispatcher);
 

+ 1 - 0
uhf_app_i.h

@@ -26,6 +26,7 @@
 #include "uhf_worker.h"
 #include <uhf_rfid_icons.h>
 
+#define UHF_BANK_DOES_NOT_EXIST (uint8_t[]){0xFF}
 #define UHF_TEXT_STORE_SIZE 128
 #define UHF_APPS_DATA_FOLDER EXT_PATH("apps_data")
 #define UHF_APPS_STORAGE_FOLDER \

+ 0 - 9
uhf_cmd.c

@@ -1,9 +0,0 @@
-// #include "uhf_cmd.h"
-// #include "uhf_app_i.h"
-
-// char* uhf_get_dev_info(UHFApp* uhf_app) {
-// }
-
-// uint8_t* uhf_single_poll(UHFApp* uhf_app){
-
-// }

+ 42 - 39
uhf_cmd.h

@@ -1,4 +1,5 @@
-#pragma once
+#ifndef UHF_CMD_H
+#define UHF_CMD_H
 
 #include <stdint.h>
 #include <stdlib.h>
@@ -27,78 +28,80 @@ typedef enum{
 #define FRAME_END 0x7E
 #define ERROR 0x15
 
-const UHF_RFID_CMD CMD_HARDWARE_VERSION = {.cmd = (uint8_t[]){0xBB, 0x00, 0x03, 0x00, 0x01, 0x00, 0x04, 0x7E}, .length = 8};
+UHF_RFID_CMD CMD_HARDWARE_VERSION = {.cmd = (uint8_t[]){0xBB, 0x00, 0x03, 0x00, 0x01, 0x00, 0x04, 0x7E}, .length = 8};
 
-const UHF_RFID_CMD CMD_SOFTWARE_VERSION = {.cmd = (uint8_t[]){0xBB, 0x00, 0x03, 0x00, 0x01, 0x01, 0x05, 0x7E}, .length = 8};
+UHF_RFID_CMD CMD_SOFTWARE_VERSION = {.cmd = (uint8_t[]){0xBB, 0x00, 0x03, 0x00, 0x01, 0x01, 0x05, 0x7E}, .length = 8};
 
-const UHF_RFID_CMD CMD_MANUFACTURERS = {.cmd = (uint8_t[]){0xBB, 0x00, 0x03, 0x00, 0x01, 0x02, 0x06, 0x7E}, .length = 8};
+UHF_RFID_CMD CMD_MANUFACTURERS = {.cmd = (uint8_t[]){0xBB, 0x00, 0x03, 0x00, 0x01, 0x02, 0x06, 0x7E}, .length = 8};
 
-const UHF_RFID_CMD CMD_SINGLE_POLLING = {.cmd = (uint8_t[]){0xBB, 0x00, 0x22, 0x00, 0x00, 0x22, 0x7E}, .length = 7};
+UHF_RFID_CMD CMD_SINGLE_POLLING = {.cmd = (uint8_t[]){0xBB, 0x00, 0x22, 0x00, 0x00, 0x22, 0x7E}, .length = 7};
 
-const UHF_RFID_CMD CMD_MULTIPLE_POLLING = {.cmd = (uint8_t[]){0xBB, 0x00, 0x27, 0x00, 0x03, 0x22, 0x27, 0x10, 0x83, 0x7E}, .length = 10};
+UHF_RFID_CMD CMD_MULTIPLE_POLLING = {.cmd = (uint8_t[]){0xBB, 0x00, 0x27, 0x00, 0x03, 0x22, 0x27, 0x10, 0x83, 0x7E}, .length = 10};
 
-const UHF_RFID_CMD CMD_STOP_MULTIPLE_POLLING = {.cmd = (uint8_t[]){0xBB, 0x00, 0x28, 0x00, 0x00, 0x28, 0x7E}, .length = 7};
+UHF_RFID_CMD CMD_STOP_MULTIPLE_POLLING = {.cmd = (uint8_t[]){0xBB, 0x00, 0x28, 0x00, 0x00, 0x28, 0x7E}, .length = 7};
 
-const UHF_RFID_CMD CMD_SET_SELECT_PARAMETER = {.cmd = (uint8_t[]){0xBB, 0x00, 0x0C, 0x00, 0x13, 0x01, 0x00, 0x00, 0x00, 0x20, 0x60, 0x00, 0x30, 0x75, 0x1F, 0xEB, 0x70, 0x5C, 0x59, 0x04, 0xE3, 0xD5, 0x0D, 0x70, 0xAD, 0x7E }, .length = 27};
+UHF_RFID_CMD CMD_SET_SELECT_PARAMETER = {.cmd = (uint8_t[]){0xBB, 0x00, 0x0C, 0x00, 0x13, 0x01, 0x00, 0x00, 0x00, 0x20, 0x60, 0x00, 0x30, 0x75, 0x1F, 0xEB, 0x70, 0x5C, 0x59, 0x04, 0xE3, 0xD5, 0x0D, 0x70, 0xAD, 0x7E }, .length = 26};
 
-const UHF_RFID_CMD CMD_GET_SELECT_PARAMETER = {.cmd = (uint8_t[]){0xBB, 0x00, 0x0B, 0x00, 0x00, 0x0B, 0x7E}, .length = 7};
+UHF_RFID_CMD CMD_GET_SELECT_PARAMETER = {.cmd = (uint8_t[]){0xBB, 0x00, 0x0B, 0x00, 0x00, 0x0B, 0x7E}, .length = 7};
 
-const UHF_RFID_CMD CMD_SET_SELECT_MODE = {.cmd = (uint8_t[]){0xBB, 0x00, 0x12, 0x00, 0x01, 0x01, 0x14, 0x7E}, .length = 8};
+UHF_RFID_CMD CMD_SET_SELECT_MODE = {.cmd = (uint8_t[]){0xBB, 0x00, 0x12, 0x00, 0x01, 0x01, 0x14, 0x7E}, .length = 8};
 
-const UHF_RFID_CMD CMD_READ_LABEL_DATA_STORAGE = {.cmd = (uint8_t[]){0xBB, 0x00, 0x39, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x08, 0x4D, 0x7E}, .length = 17};
+UHF_RFID_CMD CMD_READ_LABEL_DATA_STORAGE = {.cmd = (uint8_t[]){0xBB, 0x00, 0x39, 0x00, 0x09, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x08, 0x4D, 0x7E}, .length = 16};
 
-const UHF_RFID_CMD CMD_WRITE_LABEL_DATA_STORAGE = {.cmd = (uint8_t[]){0xBB, 0x00, 0x49, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x71, 0x7E}, .length = 24};
+UHF_RFID_CMD CMD_WRITE_LABEL_DATA_STORAGE = {.cmd = (uint8_t[]){0xBB, 0x00, 0x49, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x71, 0x7E}, .length = 24};
 
-const UHF_RFID_CMD CMD_LOCK_LABEL_DATA_STORAGE = {.cmd = (uint8_t[]){0xBB, 0x00, 0x82, 0x00, 0x07, 0x00, 0x00, 0xFF, 0xFF, 0x02, 0x00, 0x80, 0x09, 0x7E}, .length = 13};
+UHF_RFID_CMD CMD_LOCK_LABEL_DATA_STORAGE = {.cmd = (uint8_t[]){0xBB, 0x00, 0x82, 0x00, 0x07, 0x00, 0x00, 0xFF, 0xFF, 0x02, 0x00, 0x80, 0x09, 0x7E}, .length = 13};
 
-const UHF_RFID_CMD CMD_INACTIVATE_KILL_TAG = {.cmd = (uint8_t[]){0xBB, 0x00, 0x65, 0x00, 0x04, 0x00, 0x00, 0xFF, 0xFF, 0x67, 0x7E}, .length = 11};
+UHF_RFID_CMD CMD_INACTIVATE_KILL_TAG = {.cmd = (uint8_t[]){0xBB, 0x00, 0x65, 0x00, 0x04, 0x00, 0x00, 0xFF, 0xFF, 0x67, 0x7E}, .length = 11};
 
-const UHF_RFID_CMD CMD_SET_COMMUNICATION_BAUD_RATE = {.cmd = (uint8_t[]){0xBB, 0x00, 0x11, 0x00, 0x02, 0x00, 0xC0, 0xD3, 0x7E}, .length = 9};
+UHF_RFID_CMD CMD_SET_COMMUNICATION_BAUD_RATE = {.cmd = (uint8_t[]){0xBB, 0x00, 0x11, 0x00, 0x02, 0x00, 0xC0, 0xD3, 0x7E}, .length = 9};
 
-const UHF_RFID_CMD CMD_GET_QUERY_PARAMETERS = {.cmd = (uint8_t[]){0xBB, 0x00, 0x0D, 0x00, 0x00, 0x0D, 0x7E}, .length = 7};
+UHF_RFID_CMD CMD_GET_QUERY_PARAMETERS = {.cmd = (uint8_t[]){0xBB, 0x00, 0x0D, 0x00, 0x00, 0x0D, 0x7E}, .length = 7};
 
-const UHF_RFID_CMD CMD_SET_QUERY_PARAMETER = {.cmd = (uint8_t[]){0xBB, 0x00, 0x0E, 0x00, 0x02, 0x10, 0x20, 0x40, 0x7E}, .length = 9};
+UHF_RFID_CMD CMD_SET_QUERY_PARAMETER = {.cmd = (uint8_t[]){0xBB, 0x00, 0x0E, 0x00, 0x02, 0x10, 0x20, 0x40, 0x7E}, .length = 9};
 
-const UHF_RFID_CMD CMD_SETUP_WORK_AREA = {.cmd = (uint8_t[]){0xBB, 0x00, 0x07, 0x00, 0x01, 0x01, 0x09, 0x7E}, .length = 8};
+UHF_RFID_CMD CMD_SETUP_WORK_AREA = {.cmd = (uint8_t[]){0xBB, 0x00, 0x07, 0x00, 0x01, 0x01, 0x09, 0x7E}, .length = 8};
 
-const UHF_RFID_CMD CMD_ACQUIRE_WORK_LOCATIONS = {.cmd = (uint8_t[]){0xBB, 0x00, 0x08, 0x00, 0x00, 0x08, 0x7E}, .length = 7};
+UHF_RFID_CMD CMD_ACQUIRE_WORK_LOCATIONS = {.cmd = (uint8_t[]){0xBB, 0x00, 0x08, 0x00, 0x00, 0x08, 0x7E}, .length = 7};
 
-const UHF_RFID_CMD CMD_SETUP_WORKING_CHANNEL = {.cmd = (uint8_t[]){0xBB, 0x00, 0xAB, 0x00, 0x01, 0x01, 0xAC, 0x7E}, .length = 8};
+UHF_RFID_CMD CMD_SETUP_WORKING_CHANNEL = {.cmd = (uint8_t[]){0xBB, 0x00, 0xAB, 0x00, 0x01, 0x01, 0xAC, 0x7E}, .length = 8};
 
-const UHF_RFID_CMD CMD_GET_WORKING_CHANNEL = {.cmd = (uint8_t[]){0xBB, 0x00, 0xAA, 0x00, 0x00, 0xAA, 0x7E}, .length = 7};
+UHF_RFID_CMD CMD_GET_WORKING_CHANNEL = {.cmd = (uint8_t[]){0xBB, 0x00, 0xAA, 0x00, 0x00, 0xAA, 0x7E}, .length = 7};
 
-const UHF_RFID_CMD CMD_SET_AUTO_FREQUENCY_HOPPING = {.cmd = (uint8_t[]){0xBB, 0x00, 0xAD, 0x00, 0x01, 0xFF, 0xAD, 0x7E}, .length = 8};
+UHF_RFID_CMD CMD_SET_AUTO_FREQUENCY_HOPPING = {.cmd = (uint8_t[]){0xBB, 0x00, 0xAD, 0x00, 0x01, 0xFF, 0xAD, 0x7E}, .length = 8};
 
-const UHF_RFID_CMD CMD_INSERT_WORKING_CHANNEL = {.cmd = (uint8_t[]){0xBB, 0x00, 0xA9, 0x00, 0x06, 0x05, 0x01, 0x02,0x03, 0x04, 0x05, 0xC3, 0x7E}, .length = 13};
+UHF_RFID_CMD CMD_INSERT_WORKING_CHANNEL = {.cmd = (uint8_t[]){0xBB, 0x00, 0xA9, 0x00, 0x06, 0x05, 0x01, 0x02,0x03, 0x04, 0x05, 0xC3, 0x7E}, .length = 13};
 
-const UHF_RFID_CMD CMD_ACQUIRE_TRANSMITTING_POWER = {.cmd = (uint8_t[]){0xBB, 0x00, 0xB7, 0x00, 0x00, 0xB7, 0x7E}, .length = 7};
+UHF_RFID_CMD CMD_ACQUIRE_TRANSMITTING_POWER = {.cmd = (uint8_t[]){0xBB, 0x00, 0xB7, 0x00, 0x00, 0xB7, 0x7E}, .length = 7};
 
-const UHF_RFID_CMD CMD_SET_TRANSMITTING_POWER = {.cmd = (uint8_t[]){0xBB, 0x00, 0xB6, 0x00, 0x02, 0x07, 0xD0, 0x8F, 0x7E}, .length = 9};
+UHF_RFID_CMD CMD_SET_TRANSMITTING_POWER = {.cmd = (uint8_t[]){0xBB, 0x00, 0xB6, 0x00, 0x02, 0x07, 0xD0, 0x8F, 0x7E}, .length = 9};
 
-const UHF_RFID_CMD CMD_SET_CONTINUOUS_CARRIER = {.cmd = (uint8_t[]){0xBB, 0x00, 0xB0, 0x00, 0x01, 0xFF, 0xB0, 0x7E}, .length = 8};
+UHF_RFID_CMD CMD_SET_CONTINUOUS_CARRIER = {.cmd = (uint8_t[]){0xBB, 0x00, 0xB0, 0x00, 0x01, 0xFF, 0xB0, 0x7E}, .length = 8};
 
-const UHF_RFID_CMD CMD_GET_DEMODULATOR_PARAMETERS = {.cmd = (uint8_t[]){0xBB, 0x00, 0xF1, 0x00, 0x00, 0xF1, 0x7E}, .length = 7};
+UHF_RFID_CMD CMD_GET_DEMODULATOR_PARAMETERS = {.cmd = (uint8_t[]){0xBB, 0x00, 0xF1, 0x00, 0x00, 0xF1, 0x7E}, .length = 7};
 
-const UHF_RFID_CMD CMD_SET_DEMODULATOR_PARAMETERS = {.cmd = (uint8_t[]){0xBB, 0x00, 0xF0, 0x00, 0x04, 0x03, 0x06, 0x01, 0xB0, 0xAE, 0x7E}, .length = 11};
+UHF_RFID_CMD CMD_SET_DEMODULATOR_PARAMETERS = {.cmd = (uint8_t[]){0xBB, 0x00, 0xF0, 0x00, 0x04, 0x03, 0x06, 0x01, 0xB0, 0xAE, 0x7E}, .length = 11};
 
-const UHF_RFID_CMD CMD_TEST_RF_INPUT_BLOCK_SIGNAL = {.cmd = (uint8_t[]){0xBB, 0x00, 0xF2, 0x00, 0x00, 0xF2, 0x7E}, .length = 7};
+UHF_RFID_CMD CMD_TEST_RF_INPUT_BLOCK_SIGNAL = {.cmd = (uint8_t[]){0xBB, 0x00, 0xF2, 0x00, 0x00, 0xF2, 0x7E}, .length = 7};
 
-const UHF_RFID_CMD CMD_TEST_RSSI_SIGNAL = {.cmd = (uint8_t[]){0xBB, 0x00, 0xF3, 0x00, 0x00, 0xF3, 0x7E}, .length = 7};
+UHF_RFID_CMD CMD_TEST_RSSI_SIGNAL = {.cmd = (uint8_t[]){0xBB, 0x00, 0xF3, 0x00, 0x00, 0xF3, 0x7E}, .length = 7};
 
-const UHF_RFID_CMD CMD_MODULE_HIBERNATION = {.cmd = (uint8_t[]){0xBB, 0x00, 0x17, 0x00, 0x00, 0x17, 0x7E}, .length = 7};
+UHF_RFID_CMD CMD_MODULE_HIBERNATION = {.cmd = (uint8_t[]){0xBB, 0x00, 0x17, 0x00, 0x00, 0x17, 0x7E}, .length = 7};
 
-const UHF_RFID_CMD CMD_IDLE_HIBERNATION_TIME = {.cmd = (uint8_t[]){0xBB, 0x00, 0x1D, 0x00, 0x01, 0x02, 0x20, 0x7E}, .length = 8};
+UHF_RFID_CMD CMD_IDLE_HIBERNATION_TIME = {.cmd = (uint8_t[]){0xBB, 0x00, 0x1D, 0x00, 0x01, 0x02, 0x20, 0x7E}, .length = 8};
 
-const UHF_RFID_CMD CMD_IDLE_MODE = {.cmd = (uint8_t[]){0xBB, 0x00, 0x04, 0x00, 0x03, 0x01, 0x01, 0x03, 0x0C, 0x7E}, .length = 10};
+UHF_RFID_CMD CMD_IDLE_MODE = {.cmd = (uint8_t[]){0xBB, 0x00, 0x04, 0x00, 0x03, 0x01, 0x01, 0x03, 0x0C, 0x7E}, .length = 10};
 
-const UHF_RFID_CMD CMD_NXP_READPROTECT = {.cmd = (uint8_t[]){0xBB, 0x00, 0xE1, 0x00, 0x05, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0xE4, 0x7E}, .length = 12};
+UHF_RFID_CMD CMD_NXP_READPROTECT = {.cmd = (uint8_t[]){0xBB, 0x00, 0xE1, 0x00, 0x05, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0xE4, 0x7E}, .length = 12};
 
-const UHF_RFID_CMD CMD_NXP_CHANGE_EAS = {.cmd = (uint8_t[]){0xBB, 0x00, 0xE3, 0x00, 0x05, 0x00, 0x00, 0xFF, 0xFF, 0x01, 0xE7, 0x7E}, .length = 12};
+UHF_RFID_CMD CMD_NXP_CHANGE_EAS = {.cmd = (uint8_t[]){0xBB, 0x00, 0xE3, 0x00, 0x05, 0x00, 0x00, 0xFF, 0xFF, 0x01, 0xE7, 0x7E}, .length = 12};
 
-const UHF_RFID_CMD CMD_NXP_EAS_ALARM = {.cmd = (uint8_t[]){0xBB, 0x00, 0xE4, 0x00, 0x00, 0xE4, 0x7E}, .length = 7};
+UHF_RFID_CMD CMD_NXP_EAS_ALARM = {.cmd = (uint8_t[]){0xBB, 0x00, 0xE4, 0x00, 0x00, 0xE4, 0x7E}, .length = 7};
 
-const UHF_RFID_CMD CMD_NXP_CONFIG_WORD = {.cmd = (uint8_t[]){0xBB, 0x00, 0xE0, 0x00, 0x06, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xE4, 0x7E}, .length = 13};
+UHF_RFID_CMD CMD_NXP_CONFIG_WORD = {.cmd = (uint8_t[]){0xBB, 0x00, 0xE0, 0x00, 0x06, 0x00, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0xE4, 0x7E}, .length = 13};
 
-const UHF_RFID_CMD CMD_IMPINJ_MONZA4_QT = {.cmd = (uint8_t[]){0xBB, 0x00, 0xE5, 0x00, 0x08, 0x00, 0x00, 0xFF, 0xFF, 0x01, 0x01, 0x40, 0x00, 0x2D, 0x7E}, .length = 15};
+UHF_RFID_CMD CMD_IMPINJ_MONZA4_QT = {.cmd = (uint8_t[]){0xBB, 0x00, 0xE5, 0x00, 0x08, 0x00, 0x00, 0xFF, 0xFF, 0x01, 0x01, 0x40, 0x00, 0x2D, 0x7E}, .length = 15};
 
-const UHF_RFID_CMD CMD_BLOCK_PERMALOCK = {.cmd = (uint8_t[]){0xBB, 0x00, 0xD3, 0x00, 0x0B, 0x00, 0x00, 0xFF,0xFF, 0x01, 0x03, 0x00, 0x00, 0x01, 0x07, 0x00, 0xE8, 0x7E}, .length = 18};
+UHF_RFID_CMD CMD_BLOCK_PERMALOCK = {.cmd = (uint8_t[]){0xBB, 0x00, 0xD3, 0x00, 0x0B, 0x00, 0x00, 0xFF,0xFF, 0x01, 0x03, 0x00, 0x00, 0x01, 0x07, 0x00, 0xE8, 0x7E}, .length = 18};
+
+#endif /* UHF_CMD_H */

+ 0 - 1
uhf_data.c

@@ -1,6 +1,5 @@
 #include <furi.h>
 #include "uhf_data.h"
-// #include "uhf_cmd.h"
 
 UHFData* uhf_data_alloc() {
     UHFData* uhf_data = (UHFData*)malloc(sizeof(UHFData));

+ 1 - 1
uhf_data.h

@@ -3,7 +3,7 @@
 #include <stdint.h>
 #include <stdlib.h>
 
-#define MAX_DATA_SIZE 32
+#define MAX_DATA_SIZE 64
 
 typedef struct UHFData {
     uint8_t data[MAX_DATA_SIZE];

+ 125 - 15
uhf_worker.c

@@ -1,6 +1,23 @@
 #include "uhf_worker.h"
 #include "uhf_cmd.h"
 
+#define CB_DELAY 50
+// inner functions
+uint8_t calculate_checksum(UHFData* uhf_data) {
+    // CheckSum8 Modulo 256
+    // Sum of Bytes % 256
+    uint8_t sum_val = 0x00;
+    size_t length = uhf_data->length - 2;
+    for(size_t i = 1; i < length; i++) {
+        sum_val += uhf_data->data[i];
+    }
+    return sum_val % 256;
+}
+bool validate_checksum(UHFData* uhf_data) {
+    uint8_t data_checksum = uhf_data->data[uhf_data->length - 2];
+    uint8_t actual_checksum = calculate_checksum(uhf_data);
+    return data_checksum == actual_checksum;
+}
 // uart callback functions
 void module_rx_callback(UartIrqEvent event, uint8_t data, void* ctx) {
     UNUSED(event);
@@ -13,25 +30,25 @@ void module_rx_callback(UartIrqEvent event, uint8_t data, void* ctx) {
 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");
+    // 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_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);
+    furi_delay_ms(CB_DELAY);
     // 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);
+    furi_delay_ms(CB_DELAY);
     // 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");
+    furi_delay_ms(CB_DELAY);
+    // FURI_LOG_E("log", "done sending tx");
     if(!hardware_version->end || !software_version->end || !manufacturer->end) {
         return UHFWorkerEventFail;
     }
@@ -40,25 +57,118 @@ UHFWorkerEvent verify_module_connected(UHFWorker* uhf_worker) {
 
 UHFWorkerEvent read_single_card(UHFWorker* uhf_worker) {
     UHFResponseData* uhf_response_data = uhf_worker->response_data;
-    UHFData* uhf_data = uhf_response_data->head;
+    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);
-    furi_hal_uart_set_irq_cb(FuriHalUartIdUSART1, module_rx_callback, uhf_data);
-    uhf_data_reset(uhf_data);
+    furi_hal_uart_set_irq_cb(FuriHalUartIdUSART1, module_rx_callback, raw_read_data);
+    uhf_data_reset(raw_read_data);
+    // read epc bank
     while(true) {
         furi_hal_uart_tx(FuriHalUartIdUSART1, CMD_SINGLE_POLLING.cmd, CMD_SINGLE_POLLING.length);
         furi_delay_ms(100);
         if(uhf_worker->state == UHFWorkerStateStop) {
             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) {
+        if(raw_read_data->end) {
+            if(raw_read_data->data[1] == 0x01 && raw_read_data->data[5] == 0x15) {
+                uhf_data_reset(raw_read_data);
                 continue;
-            } else if(uhf_data->data[1] == 0x02)
-                break; // success read
+            } else if(raw_read_data->data[1] == 0x02)
+                break; // read success
         }
     }
+    // Set select
+    UHFData* select_cmd = uhf_data_alloc();
+    select_cmd->length = CMD_SET_SELECT_PARAMETER.length;
+    memcpy((void*)&select_cmd->data, (void*)&CMD_SET_SELECT_PARAMETER.cmd[0], select_cmd->length);
+    // set select param
+    select_cmd->data[5] = 0x01; // 0x00=rfu, 0x01=epc, 0x10=tid, 0x11=user
+    // set ptr
+    select_cmd->data[9] = 0x20;
+    // set mask
+    for(int i = 0; i < 12; i++) // 96 bits, 12 bytes
+    {
+        select_cmd->data[12 + i] = raw_read_data->data[8 + i];
+    }
+    // checksum
+    select_cmd->data[select_cmd->length - 2] = calculate_checksum(select_cmd);
+    UHFData* select_response = uhf_response_data_add_new_uhf_data(uhf_response_data);
+    furi_hal_uart_set_irq_cb(FuriHalUartIdUSART1, module_rx_callback, select_response);
+    furi_hal_uart_tx(FuriHalUartIdUSART1, select_cmd->data, select_cmd->length);
+    furi_delay_ms(CB_DELAY);
+
+    if(select_response->data[5] != 0x00) return UHFWorkerEventFail;
+
+    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);
+
+    // int retry = 10;
+    // read rfu bank
+    UHFData* rfu_bank = select_response;
+    furi_hal_uart_set_irq_cb(FuriHalUartIdUSART1, module_rx_callback, rfu_bank);
+    read_bank_cmd->data[9] = 0x00;
+    read_bank_cmd->data[read_bank_cmd->length - 2] = calculate_checksum(read_bank_cmd);
+    uhf_data_reset(rfu_bank);
+    furi_hal_uart_tx(FuriHalUartIdUSART1, read_bank_cmd->data, read_bank_cmd->length);
+    furi_delay_ms(CB_DELAY);
+    if(rfu_bank->data[2] != read_bank_cmd->data[2]) {
+        uhf_data_reset(rfu_bank);
+    }
+
+    // read epc bank
+    UHFData* epc_bank = uhf_response_data_add_new_uhf_data(uhf_response_data);
+    furi_hal_uart_set_irq_cb(FuriHalUartIdUSART1, module_rx_callback, epc_bank);
+    read_bank_cmd->data[9] = 0x01;
+    read_bank_cmd->data[read_bank_cmd->length - 2] = calculate_checksum(read_bank_cmd);
+    uhf_data_reset(epc_bank);
+    furi_hal_uart_tx(FuriHalUartIdUSART1, read_bank_cmd->data, read_bank_cmd->length);
+    furi_delay_ms(CB_DELAY);
+    if(epc_bank->data[2] != read_bank_cmd->data[2]) {
+        uhf_data_reset(epc_bank);
+    }
+
+    // read tid bank
+    UHFData* tid_bank = uhf_response_data_add_new_uhf_data(uhf_response_data);
+    furi_hal_uart_set_irq_cb(FuriHalUartIdUSART1, module_rx_callback, tid_bank);
+    read_bank_cmd->data[9] = 0x02;
+    read_bank_cmd->data[read_bank_cmd->length - 2] = calculate_checksum(read_bank_cmd);
+    uhf_data_reset(tid_bank);
+    furi_hal_uart_tx(FuriHalUartIdUSART1, read_bank_cmd->data, read_bank_cmd->length);
+    furi_delay_ms(CB_DELAY);
+    if(tid_bank->data[2] != read_bank_cmd->data[2]) {
+        uhf_data_reset(tid_bank);
+    }
+
+    // read user bank
+    UHFData* user_bank = uhf_response_data_add_new_uhf_data(uhf_response_data);
+    furi_hal_uart_set_irq_cb(FuriHalUartIdUSART1, module_rx_callback, user_bank);
+    read_bank_cmd->data[9] = 0x03;
+    read_bank_cmd->data[read_bank_cmd->length - 2] = calculate_checksum(read_bank_cmd);
+    uhf_data_reset(user_bank);
+    furi_hal_uart_tx(FuriHalUartIdUSART1, read_bank_cmd->data, read_bank_cmd->length);
+    furi_delay_ms(CB_DELAY);
+    if(user_bank->data[2] != read_bank_cmd->data[2]) {
+        uhf_data_reset(user_bank);
+    }
+
+    // for(int i = 0; i < (int)user_bank->length; i++) {
+    //     FURI_LOG_E("user_bank", "data[%d]=%02x", i, user_bank->data[i]);
+    // }
+    // for(int i = 0; i < (int)rfu_bank->length; i++) {
+    //     FURI_LOG_E("rfu_bank", "data[%d]=%02x", i, rfu_bank->data[i]);
+    // }
+    // for(int i = 0; i < (int)epc_bank->length; i++) {
+    //     FURI_LOG_E("epc_bank", "data[%d]=%02x", i, epc_bank->data[i]);
+    // }
+    // for(int i = 0; i < (int)tid_bank->length; i++) {
+    //     FURI_LOG_E("tid_bank", "data[%d]=%02x", i, tid_bank->data[i]);
+    // }
+    uhf_data_free(select_cmd);
+    uhf_data_free(read_bank_cmd);
     return UHFWorkerEventSuccess;
 }
 

+ 3 - 1
uhf_worker.h

@@ -45,4 +45,6 @@ void uhf_worker_start(
     UHFWorkerCallback callback,
     void* ctx);
 void uhf_worker_stop(UHFWorker* uhf_worker);
-void uhf_worker_free(UHFWorker* uhf_worker);
+void uhf_worker_free(UHFWorker* uhf_worker);
+uint8_t calculate_checksum(UHFData* uhf_data);
+bool validate_checksum(UHFData* uhf_data);