nfc_worker.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763
  1. #include <furi.h>
  2. #include <furi_hal.h>
  3. #include "nfc_apdu_runner.h"
  4. #include <lib/nfc/nfc.h>
  5. #include <lib/nfc/protocols/iso14443_4a/iso14443_4a.h>
  6. #include <lib/nfc/protocols/iso14443_4a/iso14443_4a_poller.h>
  7. #define TAG "NfcWorker"
  8. // APDU上下文结构体,用于在回调中传递APDU命令和结果
  9. typedef struct {
  10. BitBuffer* tx_buffer; // 发送缓冲区
  11. BitBuffer* rx_buffer; // 接收缓冲区
  12. bool ready; // 是否准备好发送
  13. bool is_last; // 是否是最后一条指令
  14. FuriThreadId thread_id; // 线程ID,用于发送标志
  15. } ApduContext;
  16. // 定义线程标志
  17. #define APDU_POLLER_DONE (1 << 0)
  18. #define APDU_POLLER_ERR (1 << 1)
  19. // NFC Worker结构体定义
  20. struct NfcWorker {
  21. FuriThread* thread;
  22. FuriStreamBuffer* stream;
  23. NfcWorkerState state;
  24. NfcWorkerCallback callback;
  25. void* context;
  26. Nfc* nfc;
  27. NfcPoller* poller;
  28. NfcApduScript* script;
  29. NfcApduResponse* responses;
  30. uint32_t response_count;
  31. bool running;
  32. bool card_detected;
  33. bool card_lost;
  34. char* error_message;
  35. };
  36. // 记录APDU数据的辅助函数
  37. static void
  38. nfc_worker_log_apdu_data(const char* cmd, const uint8_t* response, uint16_t response_len) {
  39. FURI_LOG_I(TAG, "APDU命令: %s", cmd);
  40. if(response && response_len > 0) {
  41. FuriString* resp_str = furi_string_alloc();
  42. for(size_t i = 0; i < response_len; i++) {
  43. furi_string_cat_printf(resp_str, "%02X", response[i]);
  44. }
  45. FURI_LOG_I(TAG, "APDU响应: %s", furi_string_get_cstr(resp_str));
  46. furi_string_free(resp_str);
  47. } else {
  48. FURI_LOG_I(TAG, "APDU响应: 无");
  49. }
  50. }
  51. // NFC轮询器回调函数
  52. static NfcCommand nfc_worker_poller_callback(NfcGenericEvent event, void* context) {
  53. NfcWorker* worker = context;
  54. // 检查事件类型
  55. if(event.protocol == NfcProtocolIso14443_4a) {
  56. const Iso14443_4aPollerEvent* iso14443_4a_event = event.event_data;
  57. if(iso14443_4a_event->type == Iso14443_4aPollerEventTypeReady) {
  58. FURI_LOG_I(TAG, "ISO14443-4A卡检测成功");
  59. // 只有当脚本中指定的卡类型是ISO14443-4A时,才认为检测到了卡片
  60. if(worker->script && worker->script->card_type == CardTypeIso14443_4a &&
  61. !worker->card_detected) {
  62. worker->card_detected = true;
  63. worker->callback(NfcWorkerEventCardDetected, worker->context);
  64. // 检测到卡片后立即返回停止命令,避免重复触发
  65. return NfcCommandStop;
  66. } else if(worker->card_detected) {
  67. // 如果已经检测到卡片,不再重复触发回调
  68. FURI_LOG_D(TAG, "已经检测到ISO14443-4A卡,忽略重复事件");
  69. } else {
  70. FURI_LOG_I(TAG, "检测到ISO14443-4A卡,但脚本要求的是其他类型");
  71. }
  72. } else if(iso14443_4a_event->type == Iso14443_4aPollerEventTypeError) {
  73. FURI_LOG_E(TAG, "ISO14443-4A卡检测失败,错误码: %d", iso14443_4a_event->data->error);
  74. }
  75. } else if(event.protocol == NfcProtocolIso14443_4b) {
  76. // 处理ISO14443-4B协议事件
  77. // 注意:这里假设ISO14443-4B的事件结构与ISO14443-4A类似
  78. const Iso14443_4bPollerEvent* iso14443_4b_event = event.event_data;
  79. if(iso14443_4b_event->type == Iso14443_4bPollerEventTypeReady) {
  80. FURI_LOG_I(TAG, "ISO14443-4B卡检测成功");
  81. // 只有当脚本中指定的卡类型是ISO14443-4B时,才认为检测到了卡片
  82. if(worker->script && worker->script->card_type == CardTypeIso14443_4b &&
  83. !worker->card_detected) {
  84. worker->card_detected = true;
  85. worker->callback(NfcWorkerEventCardDetected, worker->context);
  86. // 检测到卡片后立即返回停止命令,避免重复触发
  87. return NfcCommandStop;
  88. } else if(worker->card_detected) {
  89. // 如果已经检测到卡片,不再重复触发回调
  90. FURI_LOG_D(TAG, "已经检测到ISO14443-4B卡,忽略重复事件");
  91. } else {
  92. FURI_LOG_I(TAG, "检测到ISO14443-4B卡,但脚本要求的是其他类型");
  93. }
  94. } else if(iso14443_4b_event->type == Iso14443_4bPollerEventTypeError) {
  95. FURI_LOG_E(TAG, "ISO14443-4B卡检测失败,错误码: %d", iso14443_4b_event->data->error);
  96. }
  97. } else {
  98. FURI_LOG_I(TAG, "收到未知协议事件: %d", event.protocol);
  99. }
  100. // 继续操作
  101. return NfcCommandContinue;
  102. }
  103. // 执行APDU命令的回调函数
  104. static NfcCommand nfc_worker_apdu_poller_callback(NfcGenericEvent event, void* context) {
  105. UNUSED(event);
  106. furi_assert(context);
  107. ApduContext* apdu_ctx = (ApduContext*)context;
  108. // 如果准备好发送,则处理命令
  109. if(apdu_ctx->ready) {
  110. // 设置为未准备好,避免重复处理
  111. apdu_ctx->ready = false;
  112. FURI_LOG_I(TAG, "APDU回调函数处理命令");
  113. // 根据协议类型发送数据块
  114. if(event.protocol == NfcProtocolIso14443_4a) {
  115. // 发送数据块
  116. Iso14443_4aError error = iso14443_4a_poller_send_block(
  117. (Iso14443_4aPoller*)event.instance, apdu_ctx->tx_buffer, apdu_ctx->rx_buffer);
  118. if(error == Iso14443_4aErrorNone) {
  119. // 发送成功,通知线程
  120. furi_thread_flags_set(apdu_ctx->thread_id, APDU_POLLER_DONE);
  121. // 如果是最后一条指令,停止轮询器
  122. if(apdu_ctx->is_last) {
  123. return NfcCommandStop;
  124. }
  125. return NfcCommandContinue;
  126. } else {
  127. // 发送失败,通知线程
  128. FURI_LOG_E(TAG, "ISO14443-4A命令执行失败,错误码: %d", error);
  129. furi_thread_flags_set(apdu_ctx->thread_id, APDU_POLLER_ERR);
  130. return NfcCommandStop;
  131. }
  132. } else if(event.protocol == NfcProtocolIso14443_4b) {
  133. // 发送数据块
  134. Iso14443_4bError error = iso14443_4b_poller_send_block(
  135. (Iso14443_4bPoller*)event.instance, apdu_ctx->tx_buffer, apdu_ctx->rx_buffer);
  136. if(error == Iso14443_4bErrorNone) {
  137. // 发送成功,通知线程
  138. furi_thread_flags_set(apdu_ctx->thread_id, APDU_POLLER_DONE);
  139. // 如果是最后一条指令,停止轮询器
  140. if(apdu_ctx->is_last) {
  141. return NfcCommandStop;
  142. }
  143. return NfcCommandContinue;
  144. } else {
  145. // 发送失败,通知线程
  146. FURI_LOG_E(TAG, "ISO14443-4B命令执行失败,错误码: %d", error);
  147. furi_thread_flags_set(apdu_ctx->thread_id, APDU_POLLER_ERR);
  148. return NfcCommandStop;
  149. }
  150. } else {
  151. // 不支持的协议
  152. FURI_LOG_E(TAG, "不支持的协议: %d", event.protocol);
  153. furi_thread_flags_set(apdu_ctx->thread_id, APDU_POLLER_ERR);
  154. return NfcCommandStop;
  155. }
  156. } else {
  157. // 未准备好,等待
  158. furi_delay_ms(10);
  159. }
  160. return NfcCommandContinue;
  161. }
  162. // 执行APDU命令的线程函数
  163. static int32_t nfc_worker_apdu_thread(void* context) {
  164. NfcWorker* worker = context;
  165. FURI_LOG_I(TAG, "APDU执行线程启动");
  166. // 根据脚本中指定的卡类型创建相应的轮询器
  167. NfcProtocol protocol;
  168. if(worker->script) {
  169. switch(worker->script->card_type) {
  170. case CardTypeIso14443_3a:
  171. protocol = NfcProtocolIso14443_3a;
  172. FURI_LOG_I(TAG, "使用ISO14443-3A协议");
  173. break;
  174. case CardTypeIso14443_3b:
  175. protocol = NfcProtocolIso14443_3b;
  176. FURI_LOG_I(TAG, "使用ISO14443-3B协议");
  177. break;
  178. case CardTypeIso14443_4a:
  179. protocol = NfcProtocolIso14443_4a;
  180. FURI_LOG_I(TAG, "使用ISO14443-4A协议");
  181. break;
  182. case CardTypeIso14443_4b:
  183. protocol = NfcProtocolIso14443_4b;
  184. FURI_LOG_I(TAG, "使用ISO14443-4B协议");
  185. break;
  186. default:
  187. FURI_LOG_E(TAG, "不支持的卡类型: %d", worker->script->card_type);
  188. worker->callback(NfcWorkerEventFail, worker->context);
  189. return -1;
  190. }
  191. } else {
  192. // 如果没有脚本,默认使用ISO14443-4A
  193. protocol = NfcProtocolIso14443_4a;
  194. FURI_LOG_I(TAG, "没有指定脚本,默认使用ISO14443-4A协议");
  195. }
  196. // 创建新的轮询器用于执行APDU命令
  197. worker->poller = nfc_poller_alloc(worker->nfc, protocol);
  198. if(!worker->poller) {
  199. FURI_LOG_E(TAG, "分配APDU执行轮询器失败,协议: %d", protocol);
  200. worker->callback(NfcWorkerEventFail, worker->context);
  201. return -1;
  202. }
  203. FURI_LOG_I(TAG, "APDU执行轮询器分配成功");
  204. // 创建APDU上下文
  205. ApduContext apdu_ctx;
  206. memset(&apdu_ctx, 0, sizeof(ApduContext));
  207. apdu_ctx.tx_buffer = bit_buffer_alloc(MAX_APDU_LENGTH * 8);
  208. apdu_ctx.rx_buffer = bit_buffer_alloc(MAX_APDU_LENGTH * 8);
  209. apdu_ctx.ready = false;
  210. apdu_ctx.is_last = false;
  211. apdu_ctx.thread_id = furi_thread_get_current_id();
  212. // 分配响应内存
  213. worker->responses = malloc(sizeof(NfcApduResponse) * worker->script->command_count);
  214. if(!worker->responses) {
  215. FURI_LOG_E(TAG, "分配响应内存失败");
  216. worker->callback(NfcWorkerEventFail, worker->context);
  217. // 释放资源
  218. bit_buffer_free(apdu_ctx.tx_buffer);
  219. bit_buffer_free(apdu_ctx.rx_buffer);
  220. // 停止轮询器
  221. if(worker->poller) {
  222. nfc_poller_stop(worker->poller);
  223. nfc_poller_free(worker->poller);
  224. worker->poller = NULL;
  225. }
  226. return -1;
  227. }
  228. memset(worker->responses, 0, sizeof(NfcApduResponse) * worker->script->command_count);
  229. // 启动轮询器
  230. nfc_poller_start(worker->poller, nfc_worker_apdu_poller_callback, &apdu_ctx);
  231. FURI_LOG_I(TAG, "APDU执行轮询器启动成功");
  232. // 等待轮询器初始化完成
  233. furi_delay_ms(100);
  234. FURI_LOG_I(TAG, "开始执行APDU命令,共 %lu 条", worker->script->command_count);
  235. bool is_error = false;
  236. uint32_t response_count = 0;
  237. // 循环执行每条APDU命令
  238. for(uint32_t i = 0; i < worker->script->command_count && worker->running; i++) {
  239. const char* cmd = worker->script->commands[i];
  240. FURI_LOG_I(TAG, "准备执行APDU命令 %lu: %s", i, cmd);
  241. // 检查命令长度是否超过限制
  242. size_t cmd_len = strlen(cmd);
  243. if(cmd_len / 2 > MAX_APDU_LENGTH) {
  244. FURI_LOG_E(
  245. TAG, "APDU命令长度超过限制(%zu > %d): %s", cmd_len / 2, MAX_APDU_LENGTH, cmd);
  246. // 设置错误信息
  247. worker->error_message = malloc(100);
  248. if(worker->error_message) {
  249. snprintf(
  250. worker->error_message,
  251. 100,
  252. "Command too long\n%d bytes max\nCommand: %lu",
  253. MAX_APDU_LENGTH,
  254. i + 1);
  255. }
  256. is_error = true;
  257. // 立即调用失败回调,而不是等到线程结束
  258. worker->callback(NfcWorkerEventFail, worker->context);
  259. break;
  260. }
  261. // 解析APDU命令
  262. uint8_t apdu_data[MAX_APDU_LENGTH];
  263. uint16_t apdu_len = 0;
  264. // 将十六进制字符串转换为字节数组
  265. for(size_t j = 0; j < cmd_len; j += 2) {
  266. if(j + 1 >= cmd_len) break;
  267. char hex[3] = {cmd[j], cmd[j + 1], '\0'};
  268. apdu_data[apdu_len++] = (uint8_t)strtol(hex, NULL, 16);
  269. if(apdu_len >= MAX_APDU_LENGTH) break;
  270. }
  271. // 清空缓冲区
  272. bit_buffer_reset(apdu_ctx.tx_buffer);
  273. bit_buffer_reset(apdu_ctx.rx_buffer);
  274. // 将APDU数据复制到发送缓冲区
  275. bit_buffer_copy_bytes(apdu_ctx.tx_buffer, apdu_data, apdu_len);
  276. // 保存命令
  277. worker->responses[response_count].command = strdup(cmd);
  278. // 设置是否是最后一条指令
  279. apdu_ctx.is_last = (i == worker->script->command_count - 1);
  280. // 设置准备好发送
  281. apdu_ctx.ready = true;
  282. // 等待命令执行完成或出错
  283. uint32_t flags =
  284. furi_thread_flags_wait(APDU_POLLER_DONE | APDU_POLLER_ERR, FuriFlagWaitAny, 3000);
  285. if(flags & APDU_POLLER_ERR) {
  286. // 命令执行出错
  287. FURI_LOG_E(TAG, "APDU命令执行出错");
  288. // 设置错误信息
  289. worker->error_message = malloc(100);
  290. if(worker->error_message) {
  291. snprintf(worker->error_message, 100, "APDU command failed\nCommand: %lu", i + 1);
  292. }
  293. worker->responses[response_count].response = NULL;
  294. worker->responses[response_count].response_length = 0;
  295. is_error = true;
  296. // 立即调用失败回调,而不是等到线程结束
  297. worker->callback(NfcWorkerEventFail, worker->context);
  298. response_count++;
  299. break;
  300. } else if(flags & APDU_POLLER_DONE) {
  301. // 命令执行成功
  302. size_t rx_bytes_count = bit_buffer_get_size_bytes(apdu_ctx.rx_buffer);
  303. if(rx_bytes_count > 0) {
  304. // 分配响应内存
  305. uint8_t* response = malloc(rx_bytes_count);
  306. if(!response) {
  307. FURI_LOG_E(TAG, "分配响应内存失败");
  308. worker->responses[response_count].response = NULL;
  309. worker->responses[response_count].response_length = 0;
  310. is_error = true;
  311. response_count++;
  312. break;
  313. }
  314. // 复制响应数据
  315. bit_buffer_write_bytes(apdu_ctx.rx_buffer, response, rx_bytes_count);
  316. // 保存响应
  317. worker->responses[response_count].response = response;
  318. worker->responses[response_count].response_length = rx_bytes_count;
  319. // 记录APDU命令和响应
  320. nfc_worker_log_apdu_data(cmd, response, rx_bytes_count);
  321. FURI_LOG_I(TAG, "APDU命令 %lu 执行成功", i);
  322. } else {
  323. // 没有响应
  324. FURI_LOG_W(TAG, "APDU命令 %lu 执行成功,但没有响应", i);
  325. worker->responses[response_count].response = NULL;
  326. worker->responses[response_count].response_length = 0;
  327. }
  328. response_count++;
  329. } else {
  330. // 超时
  331. FURI_LOG_E(TAG, "APDU命令执行超时");
  332. // 设置错误信息
  333. worker->error_message = malloc(100);
  334. if(worker->error_message) {
  335. snprintf(worker->error_message, 100, "Command timeout\nCommand: %lu", i + 1);
  336. }
  337. worker->responses[response_count].response = NULL;
  338. worker->responses[response_count].response_length = 0;
  339. is_error = true;
  340. // 立即调用失败回调,而不是等到线程结束
  341. worker->callback(NfcWorkerEventFail, worker->context);
  342. response_count++;
  343. break;
  344. }
  345. // 命令之间添加短暂延迟
  346. furi_delay_ms(50);
  347. // 检查是否应该退出
  348. if(!worker->running) {
  349. FURI_LOG_I(TAG, "用户取消操作");
  350. is_error = true;
  351. break;
  352. }
  353. }
  354. // 更新响应计数
  355. worker->response_count = response_count;
  356. // 释放资源
  357. bit_buffer_free(apdu_ctx.tx_buffer);
  358. bit_buffer_free(apdu_ctx.rx_buffer);
  359. // 停止轮询器
  360. if(worker->poller) {
  361. FURI_LOG_I(TAG, "APDU命令执行完成,停止轮询器");
  362. nfc_poller_stop(worker->poller);
  363. nfc_poller_free(worker->poller);
  364. worker->poller = NULL;
  365. }
  366. // 返回结果
  367. if(!worker->running && !is_error) {
  368. // 只有在用户取消操作且没有其他错误时才触发中止事件
  369. FURI_LOG_I(TAG, "用户取消操作");
  370. worker->callback(NfcWorkerEventAborted, worker->context);
  371. return -1;
  372. } else if(!is_error) {
  373. // 没有错误时触发成功事件
  374. FURI_LOG_I(TAG, "执行成功");
  375. worker->callback(NfcWorkerEventSuccess, worker->context);
  376. return 0;
  377. } else {
  378. // 错误已经在上面触发了回调,这里不需要再次触发
  379. FURI_LOG_E(TAG, "执行失败");
  380. return -1;
  381. }
  382. }
  383. // 检测卡片的线程函数
  384. static int32_t nfc_worker_detect_thread(void* context) {
  385. NfcWorker* worker = context;
  386. FURI_LOG_I(TAG, "NFC Worker线程启动");
  387. // 根据脚本中指定的卡类型创建相应的轮询器
  388. NfcProtocol protocol;
  389. if(worker->script) {
  390. switch(worker->script->card_type) {
  391. case CardTypeIso14443_3a:
  392. protocol = NfcProtocolIso14443_3a;
  393. FURI_LOG_I(TAG, "使用ISO14443-3A协议");
  394. break;
  395. case CardTypeIso14443_3b:
  396. protocol = NfcProtocolIso14443_3b;
  397. FURI_LOG_I(TAG, "使用ISO14443-3B协议");
  398. break;
  399. case CardTypeIso14443_4a:
  400. protocol = NfcProtocolIso14443_4a;
  401. FURI_LOG_I(TAG, "使用ISO14443-4A协议");
  402. break;
  403. case CardTypeIso14443_4b:
  404. protocol = NfcProtocolIso14443_4b;
  405. FURI_LOG_I(TAG, "使用ISO14443-4B协议");
  406. break;
  407. default:
  408. FURI_LOG_E(TAG, "不支持的卡类型: %d", worker->script->card_type);
  409. worker->callback(NfcWorkerEventFail, worker->context);
  410. return -1;
  411. }
  412. } else {
  413. // 如果没有脚本,默认使用ISO14443-4A
  414. protocol = NfcProtocolIso14443_4a;
  415. FURI_LOG_I(TAG, "没有指定脚本,默认使用ISO14443-4A协议");
  416. }
  417. // 重置卡片检测标志
  418. worker->card_detected = false;
  419. // 创建NFC轮询器用于检测卡片
  420. worker->poller = nfc_poller_alloc(worker->nfc, protocol);
  421. if(!worker->poller) {
  422. FURI_LOG_E(TAG, "分配轮询器失败,协议: %d", protocol);
  423. worker->callback(NfcWorkerEventFail, worker->context);
  424. return -1;
  425. }
  426. FURI_LOG_I(TAG, "NFC轮询器分配成功");
  427. // 启动轮询器,使用回调
  428. nfc_poller_start(worker->poller, nfc_worker_poller_callback, worker);
  429. FURI_LOG_I(TAG, "NFC轮询器启动成功");
  430. // 等待卡片,持续检测直到找到卡片或用户取消
  431. FURI_LOG_I(TAG, "等待卡片");
  432. // 持续等待,直到检测到卡片或用户取消
  433. uint32_t attempt = 0;
  434. while(!worker->card_detected && worker->running) {
  435. attempt++;
  436. if(attempt % 5 == 0) {
  437. FURI_LOG_I(TAG, "等待卡片中... (%lu秒)", attempt / 2);
  438. // 通知用户放置卡片
  439. worker->callback(NfcWorkerEventCardLost, worker->context);
  440. }
  441. // 使用延迟来等待卡片
  442. furi_delay_ms(500);
  443. // 检查是否应该退出
  444. if(!worker->running) {
  445. FURI_LOG_I(TAG, "用户取消操作");
  446. // 只有在没有错误信息的情况下才触发中止回调
  447. if(!worker->error_message) {
  448. worker->callback(NfcWorkerEventAborted, worker->context);
  449. }
  450. // 停止轮询器
  451. if(worker->poller) {
  452. nfc_poller_stop(worker->poller);
  453. nfc_poller_free(worker->poller);
  454. worker->poller = NULL;
  455. }
  456. return -1;
  457. }
  458. }
  459. // 如果没有检测到卡片,通知用户
  460. if(!worker->card_detected) {
  461. FURI_LOG_E(TAG, "未检测到卡片");
  462. worker->callback(NfcWorkerEventFail, worker->context);
  463. // 停止轮询器
  464. if(worker->poller) {
  465. nfc_poller_stop(worker->poller);
  466. nfc_poller_free(worker->poller);
  467. worker->poller = NULL;
  468. }
  469. return -1;
  470. }
  471. // 检测到卡片后,立即停止检测轮询器
  472. if(worker->poller) {
  473. FURI_LOG_I(TAG, "检测到卡片,停止检测轮询器");
  474. nfc_poller_stop(worker->poller);
  475. nfc_poller_free(worker->poller);
  476. worker->poller = NULL;
  477. }
  478. // 如果只是检测卡片,到这里就完成了
  479. if(worker->state == NfcWorkerStateDetecting) {
  480. worker->callback(NfcWorkerEventSuccess, worker->context);
  481. return 0;
  482. }
  483. // 如果需要执行APDU命令,继续执行
  484. if(worker->state == NfcWorkerStateRunning && worker->card_detected) {
  485. // 短暂延迟,确保之前的轮询器完全停止
  486. furi_delay_ms(500);
  487. // 启动APDU执行线程
  488. FuriThread* apdu_thread =
  489. furi_thread_alloc_ex("NfcWorkerAPDUThread", 8192, nfc_worker_apdu_thread, worker);
  490. furi_thread_start(apdu_thread);
  491. // 等待APDU执行线程完成
  492. furi_thread_join(apdu_thread);
  493. furi_thread_free(apdu_thread);
  494. // 返回结果
  495. if(!worker->running) {
  496. FURI_LOG_I(TAG, "用户取消操作");
  497. // 只有在没有错误信息的情况下才触发中止回调
  498. if(!worker->error_message) {
  499. worker->callback(NfcWorkerEventAborted, worker->context);
  500. }
  501. return -1;
  502. } else {
  503. FURI_LOG_I(TAG, "执行成功");
  504. worker->callback(NfcWorkerEventSuccess, worker->context);
  505. return 0;
  506. }
  507. }
  508. return 0;
  509. }
  510. // 分配NFC Worker
  511. NfcWorker* nfc_worker_alloc(Nfc* nfc) {
  512. NfcWorker* worker = malloc(sizeof(NfcWorker));
  513. worker->thread = NULL;
  514. worker->stream = furi_stream_buffer_alloc(sizeof(NfcWorkerEvent), 8);
  515. worker->nfc = nfc;
  516. worker->poller = NULL;
  517. worker->script = NULL;
  518. worker->responses = NULL;
  519. worker->response_count = 0;
  520. worker->running = false;
  521. worker->card_detected = false;
  522. worker->card_lost = false;
  523. worker->error_message = NULL;
  524. return worker;
  525. }
  526. // 释放NFC Worker
  527. void nfc_worker_free(NfcWorker* worker) {
  528. furi_assert(worker);
  529. // 确保先停止工作线程
  530. nfc_worker_stop(worker);
  531. // 释放响应资源
  532. if(worker->responses) {
  533. for(uint32_t i = 0; i < worker->response_count; i++) {
  534. if(worker->responses[i].command) {
  535. free(worker->responses[i].command);
  536. }
  537. if(worker->responses[i].response) {
  538. free(worker->responses[i].response);
  539. }
  540. }
  541. free(worker->responses);
  542. worker->responses = NULL;
  543. worker->response_count = 0;
  544. }
  545. // 释放错误信息
  546. if(worker->error_message) {
  547. free(worker->error_message);
  548. worker->error_message = NULL;
  549. }
  550. // 释放流缓冲区
  551. if(worker->stream) {
  552. furi_stream_buffer_free(worker->stream);
  553. worker->stream = NULL;
  554. }
  555. // 释放工作线程
  556. if(worker->thread) {
  557. furi_thread_free(worker->thread);
  558. worker->thread = NULL;
  559. }
  560. // 释放工作器本身
  561. free(worker);
  562. }
  563. // 启动NFC Worker
  564. void nfc_worker_start(
  565. NfcWorker* worker,
  566. NfcWorkerState state,
  567. NfcApduScript* script,
  568. NfcWorkerCallback callback,
  569. void* context) {
  570. furi_assert(worker);
  571. furi_assert(callback);
  572. worker->state = state;
  573. worker->script = script;
  574. worker->callback = callback;
  575. worker->context = context;
  576. worker->running = true;
  577. worker->card_detected = false;
  578. worker->card_lost = false;
  579. worker->thread = furi_thread_alloc_ex("NfcWorker", 8192, nfc_worker_detect_thread, worker);
  580. furi_thread_start(worker->thread);
  581. }
  582. // 停止NFC Worker
  583. void nfc_worker_stop(NfcWorker* worker) {
  584. furi_assert(worker);
  585. if(!worker->running) {
  586. // 已经停止,无需再次停止
  587. return;
  588. }
  589. // 设置运行标志为false,通知线程退出
  590. worker->running = false;
  591. // 等待线程退出
  592. if(worker->thread) {
  593. furi_thread_join(worker->thread);
  594. furi_thread_free(worker->thread);
  595. worker->thread = NULL;
  596. }
  597. // 确保轮询器被正确释放
  598. if(worker->poller) {
  599. // 先停止轮询器
  600. nfc_poller_stop(worker->poller);
  601. // 短暂延迟,确保轮询器完全停止
  602. furi_delay_ms(10);
  603. // 然后释放轮询器
  604. nfc_poller_free(worker->poller);
  605. worker->poller = NULL;
  606. }
  607. // 重置状态
  608. worker->card_detected = false;
  609. worker->card_lost = false;
  610. worker->state = NfcWorkerStateReady;
  611. // 如果有错误信息,说明已经触发了错误回调,不需要再触发中止回调
  612. if(worker->callback && !worker->error_message) {
  613. worker->callback(NfcWorkerEventAborted, worker->context);
  614. }
  615. worker->callback = NULL;
  616. worker->context = NULL;
  617. }
  618. // 检查NFC Worker是否正在运行
  619. bool nfc_worker_is_running(NfcWorker* worker) {
  620. furi_assert(worker);
  621. return worker->running;
  622. }
  623. // 获取NFC Worker的响应结果
  624. void nfc_worker_get_responses(
  625. NfcWorker* worker,
  626. NfcApduResponse** out_responses,
  627. uint32_t* out_response_count) {
  628. furi_assert(worker);
  629. furi_assert(out_responses);
  630. furi_assert(out_response_count);
  631. *out_responses = worker->responses;
  632. *out_response_count = worker->response_count;
  633. // 清空worker中的响应,避免重复释放
  634. worker->responses = NULL;
  635. worker->response_count = 0;
  636. }
  637. // 获取NFC Worker的错误信息
  638. const char* nfc_worker_get_error_message(NfcWorker* worker) {
  639. furi_assert(worker);
  640. return worker->error_message;
  641. }