uhf_worker.c 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. #include "uhf_worker.h"
  2. #include "uhf_cmd.h"
  3. #define CB_DELAY 50
  4. // uart callback functions
  5. void module_rx_callback(UartIrqEvent event, uint8_t data, void* ctx) {
  6. UNUSED(event);
  7. UHFData* uhf_data = ctx;
  8. uhf_data_append(uhf_data, data);
  9. // FURI_LOG_E("module_rx_callback", "%02x", data);
  10. }
  11. // yrm100 module commands
  12. UHFWorkerEvent verify_module_connected(UHFWorker* uhf_worker) {
  13. UHFResponseData* uhf_response_data = uhf_worker->response_data;
  14. uhf_response_data_reset(uhf_response_data);
  15. // FURI_LOG_E("log", "freeing done");
  16. UHFData* hardware_version = uhf_response_data->head;
  17. UHFData* software_version = uhf_response_data_add_new_uhf_data(uhf_response_data);
  18. UHFData* manufacturer = uhf_response_data_add_new_uhf_data(uhf_response_data);
  19. // FURI_LOG_E("log", "alloc done");
  20. furi_hal_uart_set_br(FuriHalUartIdUSART1, DEFAULT_BAUD_RATE);
  21. // read hardware version
  22. furi_hal_uart_set_irq_cb(FuriHalUartIdUSART1, module_rx_callback, hardware_version);
  23. furi_hal_uart_tx(FuriHalUartIdUSART1, CMD_HARDWARE_VERSION.cmd, CMD_HARDWARE_VERSION.length);
  24. furi_delay_ms(CB_DELAY);
  25. // read software version
  26. furi_hal_uart_set_irq_cb(FuriHalUartIdUSART1, module_rx_callback, software_version);
  27. furi_hal_uart_tx(FuriHalUartIdUSART1, CMD_SOFTWARE_VERSION.cmd, CMD_SOFTWARE_VERSION.length);
  28. furi_delay_ms(CB_DELAY);
  29. // read manufacturer
  30. furi_hal_uart_set_irq_cb(FuriHalUartIdUSART1, module_rx_callback, manufacturer);
  31. furi_hal_uart_tx(FuriHalUartIdUSART1, CMD_MANUFACTURERS.cmd, CMD_MANUFACTURERS.length);
  32. furi_delay_ms(CB_DELAY);
  33. // verify that we received all data
  34. if(!hardware_version->end || !software_version->end || !manufacturer->end) {
  35. return UHFWorkerEventFail;
  36. }
  37. // verify all data was received correctly
  38. if(!uhf_data_verfiy_checksum(hardware_version) ||
  39. !uhf_data_verfiy_checksum(software_version) || !uhf_data_verfiy_checksum(manufacturer))
  40. return UHFWorkerEventFail;
  41. return UHFWorkerEventSuccess;
  42. }
  43. static bool send_set_select_command(UHFData* selected_tag) {
  44. bool success = false;
  45. uint16_t pc = 0;
  46. uint16_t mask_length_bits = 0xF800;
  47. size_t mask_length_word = 2;
  48. // Set select
  49. UHFData* select_cmd = uhf_data_alloc();
  50. select_cmd->length = CMD_SET_SELECT_PARAMETER.length;
  51. memcpy((void*)&select_cmd->data, (void*)&CMD_SET_SELECT_PARAMETER.cmd[0], select_cmd->length);
  52. pc += selected_tag->data[6];
  53. pc <<= 8;
  54. pc |= selected_tag->data[7];
  55. mask_length_bits &= pc;
  56. mask_length_bits >>= 11; // shift right 11 bits to only get 10h-14h
  57. // mask length word
  58. mask_length_word *= (size_t)(mask_length_bits);
  59. // mask length in bits
  60. mask_length_bits *= 16;
  61. // set select param
  62. select_cmd->data[5] = 0x01; // 0x00=rfu, 0x01=epc, 0x10=tid, 0x11=user
  63. // set ptr
  64. select_cmd->data[9] = 0x20;
  65. // set mask length
  66. select_cmd->data[10] = mask_length_bits;
  67. // set mask starting position
  68. select_cmd->length = 11;
  69. // set mask
  70. FURI_LOG_E("TAG", "Mask length (bits=%d, words=%d)", mask_length_bits, mask_length_word);
  71. for(size_t i = 0; i < mask_length_word; i++) {
  72. uhf_data_append(select_cmd, selected_tag->data[8 + i]);
  73. }
  74. uhf_data_append(select_cmd, 0x00); // add checksum section
  75. uhf_data_append(select_cmd, FRAME_END); // command end
  76. // add checksum
  77. select_cmd->data[select_cmd->length - 2] = uhf_data_calculate_checksum(select_cmd);
  78. UHFData* select_response = uhf_data_alloc();
  79. furi_hal_uart_set_irq_cb(FuriHalUartIdUSART1, module_rx_callback, select_response);
  80. furi_hal_uart_tx(FuriHalUartIdUSART1, select_cmd->data, select_cmd->length);
  81. furi_delay_ms(CB_DELAY);
  82. success = select_response->data[5] == 0x00;
  83. uhf_data_free(select_cmd);
  84. uhf_data_free(select_response);
  85. return success;
  86. }
  87. static bool read_bank(UHFData* read_bank_cmd, UHFData* response_bank, UHFBank bank) {
  88. furi_hal_uart_set_irq_cb(FuriHalUartIdUSART1, module_rx_callback, response_bank);
  89. read_bank_cmd->data[9] = bank;
  90. read_bank_cmd->data[read_bank_cmd->length - 2] = uhf_data_calculate_checksum(read_bank_cmd);
  91. uhf_data_reset(response_bank);
  92. furi_hal_uart_tx(FuriHalUartIdUSART1, read_bank_cmd->data, read_bank_cmd->length);
  93. furi_delay_ms(CB_DELAY);
  94. return response_bank->data[2] == read_bank_cmd->data[2];
  95. }
  96. UHFWorkerEvent read_single_card(UHFWorker* uhf_worker) {
  97. FuriString* temp_str;
  98. temp_str = furi_string_alloc();
  99. UHFResponseData* uhf_response_data = uhf_worker->response_data;
  100. uhf_response_data_reset(uhf_response_data);
  101. UHFData* raw_read_data = uhf_response_data_get_uhf_data(uhf_response_data, 0);
  102. furi_hal_uart_set_br(FuriHalUartIdUSART1, DEFAULT_BAUD_RATE);
  103. furi_hal_uart_set_irq_cb(FuriHalUartIdUSART1, module_rx_callback, raw_read_data);
  104. uhf_data_reset(raw_read_data);
  105. // read epc bank
  106. while(true) {
  107. furi_hal_uart_tx(FuriHalUartIdUSART1, CMD_SINGLE_POLLING.cmd, CMD_SINGLE_POLLING.length);
  108. furi_delay_ms(100);
  109. if(uhf_worker->state == UHFWorkerStateStop) {
  110. return UHFWorkerEventAborted;
  111. }
  112. if(raw_read_data->end) {
  113. for(size_t i = 0; i < raw_read_data->length; i++) {
  114. furi_string_cat_printf(temp_str, "%02x ", raw_read_data->data[i]);
  115. }
  116. FURI_LOG_E("TAG", furi_string_get_cstr(temp_str));
  117. furi_string_reset(temp_str);
  118. if(raw_read_data->data[1] == 0x01 && raw_read_data->data[5] == 0x15) {
  119. uhf_data_reset(raw_read_data);
  120. continue;
  121. } else if(raw_read_data->data[1] == 0x02)
  122. break; // read success
  123. }
  124. }
  125. if(!send_set_select_command(raw_read_data)) return UHFWorkerEventFail;
  126. UHFData* read_bank_cmd = uhf_data_alloc();
  127. read_bank_cmd->length = CMD_READ_LABEL_DATA_STORAGE.length;
  128. memcpy(
  129. (void*)&read_bank_cmd->data[0],
  130. (void*)&CMD_READ_LABEL_DATA_STORAGE.cmd[0],
  131. read_bank_cmd->length);
  132. // int retry = 10;
  133. // read rfu bank
  134. UHFData* rfu_bank = uhf_response_data_add_new_uhf_data(uhf_response_data);
  135. if(!read_bank(read_bank_cmd, rfu_bank, RFU_BANK)) {
  136. uhf_data_reset(rfu_bank);
  137. }
  138. // read epc bank
  139. UHFData* epc_bank = uhf_response_data_add_new_uhf_data(uhf_response_data);
  140. if(!read_bank(read_bank_cmd, epc_bank, EPC_BANK)) {
  141. uhf_data_reset(epc_bank);
  142. }
  143. // read tid bank
  144. UHFData* tid_bank = uhf_response_data_add_new_uhf_data(uhf_response_data);
  145. if(!read_bank(read_bank_cmd, tid_bank, TID_BANK)) {
  146. uhf_data_reset(tid_bank);
  147. }
  148. // read user bank
  149. UHFData* user_bank = uhf_response_data_add_new_uhf_data(uhf_response_data);
  150. if(!read_bank(read_bank_cmd, user_bank, USER_BANK)) {
  151. uhf_data_reset(user_bank);
  152. }
  153. // FuriString* str;
  154. // str = furi_string_alloc();
  155. // furi_string_cat(str, "RFU : ");
  156. // for(int i = 0; i < (int)rfu_bank->length; i++) {
  157. // furi_string_cat_printf(str, "%02x ", rfu_bank->data[i]);
  158. // }
  159. // FURI_LOG_E("TAG", furi_string_get_cstr(str));
  160. // furi_string_reset(str);
  161. // furi_string_cat(str, "EPC : ");
  162. // for(int i = 0; i < (int)epc_bank->length; i++) {
  163. // furi_string_cat_printf(str, "%02x ", epc_bank->data[i]);
  164. // }
  165. // FURI_LOG_E("TAG", furi_string_get_cstr(str));
  166. // furi_string_reset(str);
  167. // furi_string_cat(str, "TID : ");
  168. // for(int i = 0; i < (int)tid_bank->length; i++) {
  169. // furi_string_cat_printf(str, "%02x ", tid_bank->data[i]);
  170. // }
  171. // FURI_LOG_E("TAG", furi_string_get_cstr(str));
  172. // furi_string_reset(str);
  173. // furi_string_cat(str, "USER : ");
  174. // for(int i = 0; i < (int)user_bank->length; i++) {
  175. // furi_string_cat_printf(str, "%02x ", user_bank->data[i]);
  176. // }
  177. // FURI_LOG_E("TAG", furi_string_get_cstr(str));
  178. // furi_string_reset(str);
  179. furi_string_free(temp_str);
  180. uhf_data_free(read_bank_cmd);
  181. return UHFWorkerEventSuccess;
  182. }
  183. int32_t uhf_worker_task(void* ctx) {
  184. UHFWorker* uhf_worker = ctx;
  185. if(uhf_worker->state == UHFWorkerStateVerify) {
  186. UHFWorkerEvent event = verify_module_connected(uhf_worker);
  187. uhf_worker->callback(event, uhf_worker->ctx);
  188. }
  189. if(uhf_worker->state == UHFWorkerStateDetectSingle) {
  190. UHFWorkerEvent event = read_single_card(uhf_worker);
  191. uhf_worker->callback(event, uhf_worker->ctx);
  192. }
  193. return 0;
  194. }
  195. UHFWorker* uhf_worker_alloc() {
  196. UHFWorker* uhf_worker = (UHFWorker*)malloc(sizeof(UHFWorker));
  197. uhf_worker->thread = furi_thread_alloc_ex("UHFWorker", 8 * 1024, uhf_worker_task, uhf_worker);
  198. uhf_worker->response_data = uhf_response_data_alloc();
  199. uhf_worker->callback = NULL;
  200. uhf_worker->ctx = NULL;
  201. return uhf_worker;
  202. }
  203. void uhf_worker_change_state(UHFWorker* worker, UHFWorkerState state) {
  204. worker->state = state;
  205. }
  206. void uhf_worker_start(
  207. UHFWorker* uhf_worker,
  208. UHFWorkerState state,
  209. UHFWorkerCallback callback,
  210. void* ctx) {
  211. uhf_worker->state = state;
  212. uhf_worker->callback = callback;
  213. uhf_worker->ctx = ctx;
  214. furi_thread_start(uhf_worker->thread);
  215. }
  216. void uhf_worker_stop(UHFWorker* uhf_worker) {
  217. furi_assert(uhf_worker);
  218. furi_assert(uhf_worker->thread);
  219. if(furi_thread_get_state(uhf_worker->thread) != FuriThreadStateStopped) {
  220. uhf_worker_change_state(uhf_worker, UHFWorkerStateStop);
  221. furi_thread_join(uhf_worker->thread);
  222. }
  223. }
  224. void uhf_worker_free(UHFWorker* uhf_worker) {
  225. furi_assert(uhf_worker);
  226. furi_thread_free(uhf_worker->thread);
  227. uhf_response_data_free(uhf_worker->response_data);
  228. free(uhf_worker);
  229. }