uhf_worker.c 9.2 KB

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