uhf_worker.c 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. #include "uhf_worker.h"
  2. #include "uhf_tag.h"
  3. // yrm100 module commands
  4. UHFWorkerEvent verify_module_connected(UHFWorker* uhf_worker) {
  5. char* hw_version = m100_get_hardware_version(uhf_worker->module);
  6. char* sw_version = m100_get_software_version(uhf_worker->module);
  7. char* manufacturer = m100_get_manufacturers(uhf_worker->module);
  8. // verify all data exists
  9. if(hw_version == NULL || sw_version == NULL || manufacturer == NULL) return UHFWorkerEventFail;
  10. return UHFWorkerEventSuccess;
  11. }
  12. uint8_t get_epc_length_in_bits(uint8_t pc) {
  13. uint8_t epc_length = pc;
  14. epc_length >>= 3;
  15. return (uint8_t)epc_length * 16; // x-words * 16 bits
  16. }
  17. bool send_set_select_command(UHFData* selected_tag, UHFBank bank) {
  18. bool success = false;
  19. // Set select
  20. UHFData* select_cmd = uhf_data_alloc();
  21. select_cmd->start = true;
  22. select_cmd->length = CMD_SET_SELECT_PARAMETER.length;
  23. memcpy((void*)&select_cmd->data, (void*)&CMD_SET_SELECT_PARAMETER.cmd[0], select_cmd->length);
  24. // set select param
  25. size_t mask_length_bits = (size_t)get_epc_length_in_bits(selected_tag->data[6]);
  26. size_t mask_length_bytes = (size_t)mask_length_bits / 8;
  27. select_cmd->data[5] = bank; // 0x00=rfu, 0x01=epc, 0x10=tid, 0x11=user
  28. // set ptr
  29. select_cmd->data[9] = 0x20; // epc data begins after 0x20
  30. // set mask length
  31. select_cmd->data[10] = mask_length_bits;
  32. // set mask starting position
  33. select_cmd->length = 12;
  34. // set mask
  35. for(size_t i = 0; i < mask_length_bytes; i++) {
  36. uhf_data_append(select_cmd, selected_tag->data[8 + i]);
  37. }
  38. uhf_data_append(select_cmd, 0x00); // add checksum section
  39. uhf_data_append(select_cmd, FRAME_END); // command end
  40. // add checksum
  41. select_cmd->data[select_cmd->length - 2] = uhf_data_calculate_checksum(select_cmd);
  42. UHFData* select_response = uhf_data_alloc();
  43. furi_hal_uart_set_irq_cb(FuriHalUartIdUSART1, module_rx_callback, select_response);
  44. furi_hal_uart_tx(FuriHalUartIdUSART1, select_cmd->data, select_cmd->length);
  45. furi_delay_ms(CB_DELAY);
  46. success = select_response->data[5] == 0x00;
  47. uhf_data_free(select_cmd);
  48. uhf_data_free(select_response);
  49. return success;
  50. }
  51. bool read_bank(UHFData* read_bank_cmd, UHFData* response_bank, UHFBank bank) {
  52. furi_hal_uart_set_irq_cb(FuriHalUartIdUSART1, module_rx_callback, response_bank);
  53. read_bank_cmd->data[9] = bank;
  54. read_bank_cmd->data[read_bank_cmd->length - 2] = uhf_data_calculate_checksum(read_bank_cmd);
  55. uhf_data_reset(response_bank);
  56. furi_hal_uart_tx(FuriHalUartIdUSART1, read_bank_cmd->data, read_bank_cmd->length);
  57. furi_delay_ms(CB_DELAY);
  58. return response_bank->data[2] == read_bank_cmd->data[2];
  59. }
  60. bool write_bank(UHFData* write_bank_cmd, UHFBank bank, uint8_t* bank_data, size_t bank_len) {
  61. UHFData* rp_data = uhf_data_alloc();
  62. write_bank_cmd->end = false;
  63. for(size_t i = 0; i < write_bank_cmd->length; i++) {
  64. continue;
  65. }
  66. furi_hal_uart_set_irq_cb(FuriHalUartIdUSART1, module_rx_callback, rp_data);
  67. for(int i = 5; i < 9; i++) { // no access password for now
  68. write_bank_cmd->data[i] = 0;
  69. }
  70. write_bank_cmd->data[9] = bank;
  71. size_t word_len = bank_len / 2;
  72. write_bank_cmd->data[13] = word_len;
  73. write_bank_cmd->length = 14;
  74. write_bank_cmd->start = true;
  75. for(size_t i = 0; i < bank_len; i++) {
  76. uhf_data_append(write_bank_cmd, bank_data[i]);
  77. }
  78. uhf_data_append(write_bank_cmd, 00);
  79. uhf_data_append(write_bank_cmd, FRAME_END);
  80. write_bank_cmd->data[4] = write_bank_cmd->length - 7;
  81. write_bank_cmd->data[write_bank_cmd->length - 2] = uhf_data_calculate_checksum(write_bank_cmd);
  82. furi_hal_uart_tx(FuriHalUartIdUSART1, write_bank_cmd->data, write_bank_cmd->length);
  83. furi_delay_ms(CB_DELAY);
  84. bool success = rp_data->data[2] == write_bank_cmd->data[2];
  85. uhf_data_free(rp_data);
  86. return success;
  87. }
  88. UHFTag* send_polling_command(UHFWorker* uhf_worker) {
  89. // read epc bank
  90. UHFTag* uhf_tag;
  91. while(true) {
  92. uhf_tag = m100_send_single_poll(uhf_worker->module);
  93. furi_delay_ms(100);
  94. if(uhf_worker->state == UHFWorkerStateStop) {
  95. return NULL;
  96. }
  97. if(uhf_tag != NULL) break;
  98. }
  99. return uhf_tag;
  100. }
  101. UHFWorkerEvent read_single_card(UHFWorker* uhf_worker) {
  102. UHFTag*
  103. // todo : rfu ?
  104. UHFTag* uhf_tag = uhf_worker->uhf_tag;
  105. uhf_tag_reset(uhf_tag);
  106. // add to tag object
  107. UHFData* raw_bank_data = uhf_data_alloc();
  108. size_t epc_length = (size_t)get_epc_length_in_bits(raw_read_data->data[6]) / 8;
  109. size_t offset = (size_t)(8 + epc_length);
  110. UHFData* read_bank_cmd = uhf_data_alloc();
  111. read_bank_cmd->length = CMD_READ_LABEL_DATA_STORAGE.length;
  112. memcpy(
  113. (void*)&read_bank_cmd->data[0],
  114. (void*)&CMD_READ_LABEL_DATA_STORAGE.cmd[0],
  115. read_bank_cmd->length);
  116. if(!send_set_select_command(raw_read_data, EPC_BANK)) return UHFWorkerEventFail;
  117. int retry = 3;
  118. do {
  119. if(read_bank(read_bank_cmd, raw_bank_data, EPC_BANK)) {
  120. uhf_tag_set_epc(uhf_tag, raw_bank_data->data + offset, epc_length + 2);
  121. break;
  122. }
  123. } while(retry--);
  124. // // debug
  125. // furi_string_reset(temp_str);
  126. // for(size_t i = 0; i < raw_bank_data->length; i++) {
  127. // furi_string_cat_printf(temp_str, "%02x ", raw_bank_data->data[i]);
  128. // }
  129. // FURI_LOG_E("TAG", "data = %s", furi_string_get_cstr(temp_str));
  130. // // e-debug
  131. uhf_data_reset(raw_bank_data);
  132. retry = 3;
  133. do {
  134. if(read_bank(read_bank_cmd, raw_bank_data, TID_BANK)) {
  135. uhf_tag_set_tid(uhf_tag, raw_bank_data->data + offset, 16);
  136. break;
  137. }
  138. } while(retry--);
  139. // // debug
  140. // furi_string_reset(temp_str);
  141. // for(size_t i = 0; i < raw_bank_data->length; i++) {
  142. // furi_string_cat_printf(temp_str, "%02x ", raw_bank_data->data[i]);
  143. // }
  144. // FURI_LOG_E("TAG", "data = %s", furi_string_get_cstr(temp_str));
  145. // // e-debug
  146. uhf_data_reset(raw_bank_data);
  147. retry = 3;
  148. if(raw_read_data->data[6] & 0x04) {
  149. do {
  150. if(read_bank(read_bank_cmd, raw_bank_data, USER_BANK)) {
  151. uhf_tag_set_user(uhf_tag, raw_bank_data->data + offset, 16);
  152. break;
  153. }
  154. } while(retry--);
  155. }
  156. // // debug
  157. // furi_string_reset(temp_str);
  158. // for(size_t i = 0; i < raw_bank_data->length; i++) {
  159. // furi_string_cat_printf(temp_str, "%02x ", raw_bank_data->data[i]);
  160. // }
  161. // FURI_LOG_E("TAG", "data = %s", furi_string_get_cstr(temp_str));
  162. // // e-debug
  163. uhf_data_reset(raw_bank_data);
  164. uhf_data_free(raw_bank_data);
  165. uhf_data_free(read_bank_cmd);
  166. // debug
  167. // furi_string_free(temp_str);
  168. // e-debug
  169. return UHFWorkerEventSuccess;
  170. }
  171. UHFWorkerEvent write_single_card(UHFWorker* uhf_worker) {
  172. UHFResponseData* uhf_response_data = uhf_worker->response_data;
  173. uhf_response_data_reset(uhf_response_data);
  174. UHFData* raw_read_data = uhf_response_data_get_uhf_data(uhf_response_data, 0);
  175. furi_hal_uart_set_br(FuriHalUartIdUSART1, DEFAULT_BAUD_RATE);
  176. send_polling_command(uhf_worker, raw_read_data);
  177. // todo : rfu ?
  178. UHFTag* uhf_tag = uhf_worker->uhf_tag;
  179. UHFData* write_bank_cmd = uhf_data_alloc();
  180. write_bank_cmd->length = CMD_WRITE_LABEL_DATA_STORAGE.length;
  181. memcpy(
  182. (void*)&write_bank_cmd->data[0],
  183. (void*)&CMD_WRITE_LABEL_DATA_STORAGE.cmd[0],
  184. write_bank_cmd->length);
  185. if(!send_set_select_command(raw_read_data, EPC_BANK)) return UHFWorkerEventFail;
  186. if(raw_read_data->data[6] & 0x04) {
  187. if(!write_bank(write_bank_cmd, USER_BANK, uhf_tag->user, uhf_tag->user_length))
  188. return UHFWorkerEventFail;
  189. }
  190. uint8_t write_data[uhf_tag->epc_length + 2];
  191. memcpy(&write_data, &raw_read_data->data[raw_read_data->length - 4], 2);
  192. memcpy(&write_data[2], &uhf_tag->epc, uhf_tag->epc_length);
  193. write_data[10] = 0xF1;
  194. if(!write_bank(write_bank_cmd, EPC_BANK, write_data, uhf_tag->epc_length + 2)) {
  195. return UHFWorkerEventFail;
  196. }
  197. return UHFWorkerEventSuccess;
  198. }
  199. int32_t uhf_worker_task(void* ctx) {
  200. UHFWorker* uhf_worker = ctx;
  201. if(uhf_worker->state == UHFWorkerStateVerify) {
  202. UHFWorkerEvent event = verify_module_connected(uhf_worker);
  203. uhf_worker->callback(event, uhf_worker->ctx);
  204. } else if(uhf_worker->state == UHFWorkerStateDetectSingle) {
  205. UHFWorkerEvent event = read_single_card(uhf_worker);
  206. uhf_worker->callback(event, uhf_worker->ctx);
  207. } else if(uhf_worker->state == UHFWorkerStateWriteSingle) {
  208. UHFWorkerEvent event = write_single_card(uhf_worker);
  209. uhf_worker->callback(event, uhf_worker->ctx);
  210. }
  211. return 0;
  212. }
  213. UHFWorker* uhf_worker_alloc() {
  214. UHFWorker* uhf_worker = (UHFWorker*)malloc(sizeof(UHFWorker));
  215. uhf_worker->thread = furi_thread_alloc_ex("UHFWorker", 8 * 1024, uhf_worker_task, uhf_worker);
  216. uhf_worker->module = m100_module_alloc();
  217. uhf_worker->callback = NULL;
  218. uhf_worker->ctx = NULL;
  219. return uhf_worker;
  220. }
  221. void uhf_worker_change_state(UHFWorker* worker, UHFWorkerState state) {
  222. worker->state = state;
  223. }
  224. void uhf_worker_start(
  225. UHFWorker* uhf_worker,
  226. UHFWorkerState state,
  227. UHFWorkerCallback callback,
  228. void* ctx) {
  229. uhf_worker->state = state;
  230. uhf_worker->callback = callback;
  231. uhf_worker->ctx = ctx;
  232. furi_thread_start(uhf_worker->thread);
  233. }
  234. void uhf_worker_stop(UHFWorker* uhf_worker) {
  235. furi_assert(uhf_worker);
  236. furi_assert(uhf_worker->thread);
  237. if(furi_thread_get_state(uhf_worker->thread) != FuriThreadStateStopped) {
  238. uhf_worker_change_state(uhf_worker, UHFWorkerStateStop);
  239. furi_thread_join(uhf_worker->thread);
  240. }
  241. }
  242. void uhf_worker_free(UHFWorker* uhf_worker) {
  243. furi_assert(uhf_worker);
  244. furi_thread_free(uhf_worker->thread);
  245. m100_module_free(uhf_worker->module);
  246. free(uhf_worker);
  247. }