diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000000..626933f5f08 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.vscode/* +.clang-format diff --git a/as_card_worker.c b/as_card_worker.c index 6ee5f7e0954..bc38932eb59 100644 --- a/as_card_worker.c +++ b/as_card_worker.c @@ -1,7 +1,31 @@ #include "as_card_worker.h" +#include #define TAG "AsCardWorker" +static uint8_t CMD_14A_WTX[4] = {0xf2, 0x01, 0x91, 0x40}; + +#define NFCA_CRC_INIT (0x6363) +uint16_t nfca_get_crc16(uint8_t* buff, uint16_t len) { + uint16_t crc = NFCA_CRC_INIT; + uint8_t byte = 0; + + for(uint8_t i = 0; i < len; i++) { + byte = buff[i]; + byte ^= (uint8_t)(crc & 0xff); + byte ^= byte << 4; + crc = (crc >> 8) ^ (((uint16_t)byte) << 8) ^ (((uint16_t)byte) << 3) ^ + (((uint16_t)byte) >> 4); + } + + return crc; +} +void nfca_append_crc16(uint8_t* buff, uint16_t len) { + uint16_t crc = nfca_get_crc16(buff, len); + buff[len] = (uint8_t)crc; + buff[len + 1] = (uint8_t)(crc >> 8); +} + void as_card_worker_change_state(AsCardWorker* as_card_worker, AsCardWorkerState state) { as_card_worker->state = state; if(as_card_worker->callback) as_card_worker->callback(state, as_card_worker->nfc_relay); @@ -18,15 +42,39 @@ AsCardWorker* as_card_worker_alloc(NfcRelay* nfc_relay) { as_card_worker->comm = comm_alloc(nfc_relay->config); as_card_worker->nfc_relay = nfc_relay; as_card_worker->callback = NULL; - as_card_worker->emu_card_worker = emu_card_worker_alloc(); + as_card_worker->nfc = nfc_alloc(); + as_card_worker->dev_data = iso14443_4a_alloc(); + as_card_worker->bitbuffer = bit_buffer_alloc(256); + as_card_worker->buff_tx = malloc(256); + // TODO: Make the following two configurable + as_card_worker->delayus = 3500; + CMD_14A_WTX[1] = 1; + nfca_append_crc16(&CMD_14A_WTX[0], 2); + return as_card_worker; } void as_card_worker_free(AsCardWorker* as_card_worker) { furi_assert(as_card_worker); + if(as_card_worker->dev_data) { + iso14443_4a_free(as_card_worker->dev_data); + as_card_worker->dev_data = NULL; + } + if(as_card_worker->bitbuffer) { + bit_buffer_free(as_card_worker->bitbuffer); + as_card_worker->bitbuffer = NULL; + } + if(as_card_worker->buff_tx) { + free(as_card_worker->buff_tx); + as_card_worker->buff_tx = NULL; + } + if(as_card_worker->nfc) { + nfc_free(as_card_worker->nfc); + as_card_worker->nfc = NULL; + } + comm_free(as_card_worker->comm); - if(as_card_worker->emu_card_worker) emu_card_worker_free(as_card_worker->emu_card_worker); furi_thread_free(as_card_worker->thread); free(as_card_worker); } @@ -36,8 +84,12 @@ void as_card_worker_stop(AsCardWorker* as_card_worker) { as_card_worker->running = false; comm_deinit(as_card_worker->comm); - if(as_card_worker->emu_card_worker) emu_card_worker_stop(as_card_worker->emu_card_worker); as_card_worker->callback = NULL; + if(as_card_worker->listener) { + nfc_listener_stop(as_card_worker->listener); + nfc_listener_free(as_card_worker->listener); + as_card_worker->listener = NULL; + } furi_thread_join(as_card_worker->thread); } @@ -52,13 +104,112 @@ void as_card_worker_start(AsCardWorker* as_card_worker, AsCardWorkerCallback cal furi_thread_start(as_card_worker->thread); } +NfcCommand emu_callback(NfcGenericEvent event, void* context) { + furi_assert(context); + furi_assert(event.protocol == NfcProtocolIso14443_4a); + furi_assert(event.event_data); + + AsCardWorker* as_card_worker = context; + Iso14443_4aListenerEvent* iso14443_4a_event = event.event_data; + //FURI_LOG_T(TAG, "iso14443_4a_event->type: %d", iso14443_4a_event->type); + if(iso14443_4a_event->type != Iso14443_4aListenerEventTypeReceivedData) { + return NfcCommandContinue; + } + if(bit_buffer_get_size_bytes(iso14443_4a_event->data->buffer) == 0) { + FURI_LOG_E(TAG, "bit_buffer_get_size_bytes(iso14443_4a_event->data->buffer) == 0"); + return NfcCommandContinue; + } + trace_bit_buffer_hexdump(TAG, "Emu Card RX", iso14443_4a_event->data->buffer); + uint8_t rx_bytes = bit_buffer_get_size_bytes(iso14443_4a_event->data->buffer); + const uint8_t* buff_rx = bit_buffer_get_data(iso14443_4a_event->data->buffer); + uint8_t pcb = buff_rx[0]; + + if((pcb & 0xfe) == 0xb2) { + FURI_LOG_D(TAG, "Recv R(NACK)"); + if(as_card_worker->state == AsCardWorkerStateWaitApduResp) { + FURI_LOG_D(TAG, "NACK as WTX Resp"); + memcpy(as_card_worker->buff_tx, &CMD_14A_WTX[0], sizeof(CMD_14A_WTX)); + as_card_worker->buff_tx[0] &= 0xfe; + as_card_worker->buff_tx[0] |= pcb & 0x1; + furi_delay_ms(as_card_worker->delayus / 1000); + bit_buffer_copy_bytes( + as_card_worker->bitbuffer, as_card_worker->buff_tx, sizeof(CMD_14A_WTX)); + nfc_iso14443a_listener_tx_custom_parity( + as_card_worker->nfc, as_card_worker->bitbuffer); + return NfcCommandContinue; + } else { + FURI_LOG_D(TAG, "send 0xa2"); + as_card_worker->buff_tx[0] = 0xa2; + bit_buffer_copy_bytes(as_card_worker->bitbuffer, as_card_worker->buff_tx, 1); + nfc_iso14443a_listener_tx_custom_parity( + as_card_worker->nfc, as_card_worker->bitbuffer); + return NfcCommandContinue; + } + } else if((pcb & 0xfe) == 0xc2) { + FURI_LOG_D(TAG, "Recv S(DESELECT)"); + } else if((pcb & 0xfe) == 0xf2) { + if(as_card_worker->state == AsCardWorkerStateWaitApduResp) { + FURI_LOG_D(TAG, "Recv WTX Resp"); + memcpy(as_card_worker->buff_tx, &CMD_14A_WTX[0], sizeof(CMD_14A_WTX)); + as_card_worker->buff_tx[0] &= 0xfe; + as_card_worker->buff_tx[0] |= pcb & 0x1; + furi_delay_ms(as_card_worker->delayus / 1000); + bit_buffer_copy_bytes( + as_card_worker->bitbuffer, as_card_worker->buff_tx, sizeof(CMD_14A_WTX)); + nfc_iso14443a_listener_tx_custom_parity( + as_card_worker->nfc, as_card_worker->bitbuffer); + + return NfcCommandContinue; + } else if(as_card_worker->state == AsCardWorkerStateGetApduResp) { + FURI_LOG_D(TAG, "Recv WTX Resp, Ready to send Response back"); + memcpy( + as_card_worker->buff_tx, as_card_worker->apdu_buf, as_card_worker->apdu_buf_len); + nfca_append_crc16(&as_card_worker->buff_tx[0], as_card_worker->apdu_buf_len); + + bit_buffer_copy_bytes( + as_card_worker->bitbuffer, + as_card_worker->buff_tx, + as_card_worker->apdu_buf_len + 2); + //nfc_iso14443a_listener_tx_custom_parity(emu_card_worker->nfc, emu_card_worker->bitbuffer); + trace_bit_buffer_hexdump(TAG, "Emu Card TX", as_card_worker->bitbuffer); + NfcError error = nfc_listener_tx(as_card_worker->nfc, as_card_worker->bitbuffer); + if(error != NfcErrorNone) { + FURI_LOG_E(TAG, "Tx error: %d", error); + } + + as_card_worker->state = AsCardWorkerStateWaitApduReq; + return NfcCommandContinue; + } else { + FURI_LOG_E(TAG, "Recv WTX Resp but we hasn't request"); + } + } else if((pcb & 0xfe) == 0x2) { + // I-Block ignore the block number at LSB + FURI_LOG_T(TAG, "Recv I-Block"); + NfcRelayPacket* packet; + packet = packet_alloc_data(NfcRelayPacketApduReq, rx_bytes, &buff_rx[0]); + comm_write_packet(as_card_worker->comm, packet); + as_card_worker_change_state(as_card_worker, AsCardWorkerStateWaitApduResp); + as_card_worker->apdu_buf[0] = buff_rx[0]; + free(packet); + + bit_buffer_copy_bytes(as_card_worker->bitbuffer, &CMD_14A_WTX[0], sizeof(CMD_14A_WTX)); + nfc_iso14443a_listener_tx_custom_parity(as_card_worker->nfc, as_card_worker->bitbuffer); + + as_card_worker->state = AsCardWorkerStateWaitApduResp; + return NfcCommandContinue; + } else { + FURI_LOG_E(TAG, "Something unknown"); + return NfcCommandContinue; + } + + return NfcCommandContinue; +} + // TODO: NfcRelayPakcetErr int32_t as_card_worker_task(void* context) { furi_assert(context); AsCardWorker* as_card_worker = context; NfcRelayPacket* recv_packet = NULL; - FuriHalNfcDevData dev_data = {}; - uint8_t apdu_buf[256]; FURI_LOG_D(TAG, "Send Ping Packet"); comm_send_pingpong(as_card_worker->comm, NfcRelayPacketPing, NfcRelayAsCard); @@ -68,6 +219,7 @@ int32_t as_card_worker_task(void* context) { if(as_card_worker->state == AsCardWorkerStateWaitPong) { if(comm_wait_pong(as_card_worker->comm, NfcRelayAsReader, NfcRelayAsCard)) { FURI_LOG_D(TAG, "comm_wait_pong succ, change state"); + as_card_worker_change_state(as_card_worker, AsCardWorkerStateWaitNfcDevData); } else { continue; @@ -75,17 +227,27 @@ int32_t as_card_worker_task(void* context) { } else if(as_card_worker->state == AsCardWorkerStateWaitNfcDevData) { recv_packet = comm_wait_packet(as_card_worker->comm, NfcRelayPacketNfcDevData); if(!recv_packet) continue; - if(recv_packet->len == sizeof(FuriHalNfcDevData)) { - memcpy(&dev_data, &recv_packet->buf, recv_packet->len); + // TODO: not grace, but do not familiar with FlipperFormat type + if(recv_packet->len > sizeof(SerializedIso14443_4a) && + recv_packet->len == ((SerializedIso14443_4a*)recv_packet->buf)->len_t1_tk + + sizeof(SerializedIso14443_4a)) { + iso14443_4a_reset(as_card_worker->dev_data); + iso14443_4a_deserialize( + as_card_worker->dev_data, (SerializedIso14443_4a*)recv_packet->buf); free(recv_packet); recv_packet = NULL; - FURI_LOG_D(TAG, "Start Emulating"); as_card_worker_change_state(as_card_worker, AsCardWorkerStateWaitApduReq); - if(dev_data.uid_len > 7) { - FURI_LOG_E(TAG, "UID Length > 7, ST25R3916 not supported??"); - dev_data.uid_len = 7; - } - emu_card_worker_start(as_card_worker->emu_card_worker, &dev_data); + //if(dev_data->iso14443_3a_data->uid_len > 7) { + // FURI_LOG_E(TAG, "UID Length > 7, ST25R3916 not supported??"); + // // TODO + // FURI_LOG_E(TAG, "Maybe it is suppported Now?"); + // //dev_data.uid_len = 7; + //} + FURI_LOG_D(TAG, "Start Emulating"); + as_card_worker->listener = nfc_listener_alloc( + as_card_worker->nfc, NfcProtocolIso14443_4a, as_card_worker->dev_data); + nfc_listener_start(as_card_worker->listener, emu_callback, as_card_worker); + FURI_LOG_D(TAG, "Started Emulating"); } else { FURI_LOG_D(TAG, "Recv NfcDevData with wrong size"); @@ -93,37 +255,23 @@ int32_t as_card_worker_task(void* context) { recv_packet = NULL; // TODO: change state or not? } + } else if(as_card_worker->state == AsCardWorkerStateWaitApduReq) { - if(as_card_worker->emu_card_worker->state == EmuCardWorkerStateWaitApduResp) { - uint16_t apdu_len; - NfcRelayPacket* packet; - emu_card_worker_get_apdu(as_card_worker->emu_card_worker, &apdu_buf[0], &apdu_len); - packet = packet_alloc(NfcRelayPacketApduReq, apdu_len, &apdu_buf[0]); - comm_write_packet(as_card_worker->comm, packet); - as_card_worker_change_state(as_card_worker, AsCardWorkerStateWaitApduResp); - continue; - } - recv_packet = comm_read_packet(as_card_worker->comm); - if(!recv_packet) { - continue; - } - FURI_LOG_E(TAG, "? Recv packet when state is AsCardWorkerStateWaitApduReq"); - free(recv_packet); - recv_packet = NULL; + //FURI_LOG_T(TAG, "AsCardWorkerStateWaitApduReq"); + furi_delay_us(10); } else if(as_card_worker->state == AsCardWorkerStateWaitApduResp) { - if(as_card_worker->emu_card_worker->state == EmuCardWorkerStateWaitApduReq) { - as_card_worker_change_state(as_card_worker, AsCardWorkerStateWaitApduReq); - } + //FURI_LOG_D(TAG, "AsCardWorkerStateWaitApduResp"); recv_packet = comm_wait_packet(as_card_worker->comm, NfcRelayPacketApduResp); if(!recv_packet) { continue; } - emu_card_worker_set_apdu( - as_card_worker->emu_card_worker, 1, &recv_packet->buf[0], recv_packet->len); - as_card_worker->emu_card_worker->state = EmuCardWorkerStateGetApduResp; + // leave first pcb byte + as_card_worker->apdu_buf_len = recv_packet->len + 1; + memcpy(&as_card_worker->apdu_buf[1], recv_packet->buf, recv_packet->len); + as_card_worker->state = AsCardWorkerStateGetApduResp; FURI_LOG_D( TAG, - "Recv NfcRelayPacketApduResp, change emu_card_worker state to EmuCardWorkerStateGetApduResp"); + "Recv NfcRelayPacketApduResp, change as_card_worker state to AsCardWorkerStateGetApduResp"); free(recv_packet); recv_packet = NULL; } else { @@ -136,8 +284,8 @@ int32_t as_card_worker_task(void* context) { recv_packet = NULL; } } - furi_hal_nfc_ll_txrx_off(); - furi_hal_nfc_sleep(); + + FURI_LOG_D(TAG, "as_card_worker stop running"); return 0; -} \ No newline at end of file +} diff --git a/as_card_worker.h b/as_card_worker.h index 24c705b86b1..a1fe5dfcf7b 100644 --- a/as_card_worker.h +++ b/as_card_worker.h @@ -1,14 +1,16 @@ #pragma once #include +#include +#include #include "nfc_relay.h" #include "comm.h" -#include "emu_card_worker.h" typedef enum { AsCardWorkerStateWaitPong, AsCardWorkerStateWaitNfcDevData, AsCardWorkerStateWaitApduReq, AsCardWorkerStateWaitApduResp, + AsCardWorkerStateGetApduResp, } AsCardWorkerState; typedef bool (*AsCardWorkerCallback)(AsCardWorkerState event, void* context); @@ -19,7 +21,15 @@ typedef struct AsCardWorker { Comm* comm; NfcRelay* nfc_relay; AsCardWorkerCallback callback; - EmuCardWorker* emu_card_worker; + + Iso14443_4aData* dev_data; + Nfc* nfc; + NfcListener* listener; + BitBuffer* bitbuffer; + uint8_t* buff_tx; + uint32_t delayus; + uint16_t apdu_buf_len; + uint8_t apdu_buf[260]; bool running; } AsCardWorker; diff --git a/as_reader_worker.c b/as_reader_worker.c index 20d8bffd0f5..fd397ffda40 100644 --- a/as_reader_worker.c +++ b/as_reader_worker.c @@ -1,6 +1,10 @@ #include "as_reader_worker.h" +#include #define TAG "AsReaderWorker" +#define WORKERSTOP (1UL << 0UL) +#define POLLERFINISH (1UL << 1UL) +#define POLLERTRXFINISH (1UL << 2UL) void as_reader_worker_change_state(AsReaderWorker* as_reader_worker, AsReaderWorkerState state) { as_reader_worker->state = state; @@ -13,9 +17,12 @@ AsReaderWorker* as_reader_worker_alloc(NfcRelay* nfc_relay) { AsReaderWorker* as_reader_worker = malloc(sizeof(AsReaderWorker)); as_reader_worker->thread = furi_thread_alloc_ex( - "AsReaderWorkerThread", 8192, as_reader_worker_task, as_reader_worker); + "AsReaderWorkerThread", 2048, as_reader_worker_task, as_reader_worker); as_reader_worker->running = false; as_reader_worker->comm = comm_alloc(nfc_relay->config); + as_reader_worker->nfc = nfc_alloc(); + as_reader_worker->bitbuffer_rx = bit_buffer_alloc(256); + as_reader_worker->bitbuffer_tx = bit_buffer_alloc(256); as_reader_worker->nfc_relay = nfc_relay; as_reader_worker->callback = NULL; return as_reader_worker; @@ -23,20 +30,25 @@ AsReaderWorker* as_reader_worker_alloc(NfcRelay* nfc_relay) { void as_reader_worker_free(AsReaderWorker* as_reader_worker) { furi_assert(as_reader_worker); + FURI_LOG_D(TAG, "as_reader_worker_free"); comm_free(as_reader_worker->comm); + nfc_free(as_reader_worker->nfc); + bit_buffer_free(as_reader_worker->bitbuffer_rx); + bit_buffer_free(as_reader_worker->bitbuffer_tx); furi_thread_free(as_reader_worker->thread); free(as_reader_worker); } void as_reader_worker_stop(AsReaderWorker* as_reader_worker) { furi_assert(as_reader_worker); + FURI_LOG_D(TAG, "as_reader_worker_stop"); as_reader_worker->running = false; + furi_thread_flags_set(furi_thread_get_id(as_reader_worker->thread), WORKERSTOP); + furi_thread_join(as_reader_worker->thread); comm_deinit(as_reader_worker->comm); as_reader_worker->callback = NULL; - - furi_thread_join(as_reader_worker->thread); } void as_reader_worker_start(AsReaderWorker* as_reader_worker, AsReaderWorkerCallback callback) { @@ -49,46 +61,108 @@ void as_reader_worker_start(AsReaderWorker* as_reader_worker, AsReaderWorkerCall furi_thread_start(as_reader_worker->thread); } -int32_t as_reader_worker_task(void* context) { +static NfcCommand as_reader_worker_poller_trx_callback(NfcGenericEvent event, void* context) { + furi_assert(event.protocol == NfcProtocolIso14443_4a); furi_assert(context); + AsReaderWorker* as_reader_worker = context; + const Iso14443_4aPollerEvent* iso14443_4a_event = event.event_data; + + if(iso14443_4a_event->type == Iso14443_4aPollerEventTypeReady) { + if(as_reader_worker->state == AsReaderWorkerStateCardSearch) { + //FURI_LOG_D(TAG, "Card Found"); + as_reader_worker_change_state(as_reader_worker, AsReaderWorkerStateCardFound); + furi_thread_flags_set(furi_thread_get_id(as_reader_worker->thread), POLLERFINISH); + return NfcCommandContinue; + } else if(as_reader_worker->state == AsReaderWorkerStateInteractive) { + if(as_reader_worker->apdu_ready) { + FURI_LOG_D(TAG, "Card Found, Send TX"); + Iso14443_4aError err = iso14443_4a_poller_send_block( + event.instance, + as_reader_worker->bitbuffer_tx, + as_reader_worker->bitbuffer_rx); + trace_bit_buffer_hexdump(TAG, "Emu Reader TX", as_reader_worker->bitbuffer_tx); + if(err == Iso14443_4aErrorNone) { + trace_bit_buffer_hexdump(TAG, "Emu Reader RX", as_reader_worker->bitbuffer_rx); + FURI_LOG_D(TAG, "Card Found, Recv RX"); + NfcRelayPacket* packet = packet_alloc_data( + NfcRelayPacketApduResp, + bit_buffer_get_size_bytes(as_reader_worker->bitbuffer_rx), + bit_buffer_get_data(as_reader_worker->bitbuffer_rx)); + comm_write_packet(as_reader_worker->comm, packet); + free(packet); + FURI_LOG_D(TAG, "Card Found, Sent Relay Packet"); + } else { + FURI_LOG_E(TAG, "NfcError: %d", err); + } + as_reader_worker->apdu_ready = false; + furi_thread_flags_set( + furi_thread_get_id(as_reader_worker->thread), POLLERTRXFINISH); + return NfcCommandContinue; + } else { + //FURI_LOG_T(TAG, "Card Ready, but apdu data not"); + furi_delay_ms(1); + return NfcCommandContinue; + } + } else if(as_reader_worker->state == AsReaderWorkerStateCardFound) { + FURI_LOG_D(TAG, "still in AsReaderWorkerStateCardFound"); + furi_delay_ms(1000); + return NfcCommandContinue; + } else { + FURI_LOG_D(TAG, "WHAT?"); + return NfcCommandStop; + } + } + furi_thread_flags_set(furi_thread_get_id(as_reader_worker->thread), POLLERTRXFINISH); + return NfcCommandContinue; +} - furi_hal_nfc_deinit(); - furi_hal_nfc_init(); +int32_t as_reader_worker_task(void* context) { + furi_assert(context); + AsReaderWorker* as_reader_worker = context; FURI_LOG_D(TAG, "Send Ping Packet"); comm_send_pingpong(as_reader_worker->comm, NfcRelayPacketPing, NfcRelayAsReader); NfcRelayPacket* packet = NULL; - FuriHalNfcTxRxContext tx_rx = {}; - FuriHalNfcDevData dev_data = {}; - while(1) { if(!as_reader_worker->running) { + FURI_LOG_D(TAG, "as_reader_worker stop running, break"); break; } if(as_reader_worker->state == AsReaderWorkerStateWaitPong) { if(comm_wait_pong(as_reader_worker->comm, NfcRelayAsCard, NfcRelayAsReader)) { FURI_LOG_D(TAG, "comm_wait_pong succ, change state"); as_reader_worker_change_state(as_reader_worker, AsReaderWorkerStateCardSearch); + as_reader_worker->poller = + nfc_poller_alloc(as_reader_worker->nfc, NfcProtocolIso14443_4a); + nfc_poller_start( + as_reader_worker->poller, + as_reader_worker_poller_trx_callback, + as_reader_worker); } else { + furi_delay_ms(100); continue; } } else if(as_reader_worker->state == AsReaderWorkerStateCardSearch) { - if(!furi_hal_nfc_detect(&dev_data, 300)) { - FURI_LOG_I(TAG, "No Card Detected"); - continue; - } - - FURI_LOG_D( - TAG, "packet alloc sizeof(FuriHalNfcDevData)=%d", sizeof(FuriHalNfcDevData)); - packet = packet_alloc(NfcRelayPacketNfcDevData, sizeof(FuriHalNfcDevData), &dev_data); + FURI_LOG_D(TAG, "AsReaderWorkerStateCardSearch"); + furi_thread_flags_wait(POLLERFINISH || WORKERSTOP, FuriFlagWaitAny, 1000); + continue; + } else if(as_reader_worker->state == AsReaderWorkerStateCardFound) { + FURI_LOG_D(TAG, "Card Found"); + const Iso14443_4aData* dev_data = nfc_poller_get_data(as_reader_worker->poller); + SerializedIso14443_4a* serialized = iso14443_4a_serialize(dev_data); + packet = packet_alloc_data( + NfcRelayPacketNfcDevData, sizeof(*serialized) + serialized->len_t1_tk, serialized); FURI_LOG_D(TAG, "packet->len: %d", packet->len); comm_write_packet(as_reader_worker->comm, packet); free(packet); packet = NULL; - as_reader_worker_change_state(as_reader_worker, AsReaderWorkerStateCardFound); - } else if(as_reader_worker->state == AsReaderWorkerStateCardFound) { + free(serialized); + serialized = NULL; + as_reader_worker_change_state(as_reader_worker, AsReaderWorkerStateInteractive); + continue; + } else if(as_reader_worker->state == AsReaderWorkerStateInteractive) { NfcRelayPacket* recv_packet; recv_packet = comm_wait_packet(as_reader_worker->comm, NfcRelayPacketApduReq); if(!recv_packet) { @@ -96,27 +170,21 @@ int32_t as_reader_worker_task(void* context) { } FURI_LOG_D(TAG, "Recv NfcRelayPacketApduReq"); // drop PCB - memcpy(tx_rx.tx_data, &recv_packet->buf[1], recv_packet->len - 1); - tx_rx.tx_bits = (recv_packet->len - 1) * 8; - if(!furi_hal_nfc_tx_rx(&tx_rx, 300)) { - FURI_LOG_E(TAG, "furi_hal_nfc_tx_rx failed"); - packet = packet_no_data_alloc(NfcRelayPacketErr); - comm_write_packet(as_reader_worker->comm, packet); - free(recv_packet); - free(packet); - recv_packet = NULL; - packet = NULL; - } - packet = packet_alloc(NfcRelayPacketApduResp, (tx_rx.rx_bits + 7) / 8, tx_rx.rx_data); - comm_write_packet(as_reader_worker->comm, packet); + bit_buffer_copy_bytes( + as_reader_worker->bitbuffer_tx, &recv_packet->buf[1], recv_packet->len - 1); + trace_bit_buffer_hexdump(TAG, "Reader apdu recv", as_reader_worker->bitbuffer_tx); free(recv_packet); - free(packet); recv_packet = NULL; - packet = NULL; + as_reader_worker->apdu_ready = true; + furi_thread_flags_wait(POLLERTRXFINISH || WORKERSTOP, FuriFlagWaitAny, 100); } } - furi_hal_nfc_ll_txrx_off(); - furi_hal_nfc_sleep(); + if(as_reader_worker->poller) { + nfc_poller_stop(as_reader_worker->poller); + nfc_poller_free(as_reader_worker->poller); + as_reader_worker->poller = NULL; + } + FURI_LOG_D(TAG, "as_reader_worker stop running, poller freed"); return 0; } \ No newline at end of file diff --git a/as_reader_worker.h b/as_reader_worker.h index bfb5e2b8ca9..1edee3dc32a 100644 --- a/as_reader_worker.h +++ b/as_reader_worker.h @@ -1,5 +1,6 @@ #pragma once #include +#include #include "nfc_relay.h" #include "comm.h" @@ -7,6 +8,7 @@ typedef enum { AsReaderWorkerStateWaitPong, AsReaderWorkerStateCardSearch, AsReaderWorkerStateCardFound, + AsReaderWorkerStateInteractive, } AsReaderWorkerState; typedef bool (*AsReaderWorkerCallback)(AsReaderWorkerState event, void* context); @@ -14,6 +16,11 @@ typedef bool (*AsReaderWorkerCallback)(AsReaderWorkerState event, void* context) typedef struct AsReaderWorker { FuriThread* thread; AsReaderWorkerState state; + Nfc* nfc; + NfcPoller* poller; + BitBuffer* bitbuffer_rx; + BitBuffer* bitbuffer_tx; + bool apdu_ready; Comm* comm; NfcRelay* nfc_relay; AsReaderWorkerCallback callback; diff --git a/comm.c b/comm.c index d87040dea2e..18b07ec0ec4 100644 --- a/comm.c +++ b/comm.c @@ -46,14 +46,14 @@ void comm_free(Comm* comm) { void comm_send_no_data(Comm* comm, NfcRelayPacketType typ) { NfcRelayPacket* packet; - packet = packet_no_data_alloc(typ); + packet = packet_alloc_empty(typ); comm_write_packet(comm, packet); free(packet); } void comm_send_pingpong(Comm* comm, NfcRelayPacketType typ, NfcRelayRole who) { NfcRelayPacket* packet; - packet = packet_alloc(typ, 1, &who); + packet = packet_alloc_data(typ, 1, &who); comm_write_packet(comm, packet); free(packet); } diff --git a/emu_card_worker.c b/emu_card_worker.c deleted file mode 100644 index bc0d863fec2..00000000000 --- a/emu_card_worker.c +++ /dev/null @@ -1,208 +0,0 @@ -#include "emu_card_worker.h" - -#define TAG "EmuCardWorker" - -static uint8_t CMD_14A_WTX[4] = {0xf2, 0x01, 0x91, 0x40}; - -bool emu_card_worker_set_apdu( - EmuCardWorker* emu_card_worker, - uint8_t offset, - uint8_t* data, - uint16_t len) { - furi_assert(len + offset < sizeof(emu_card_worker->apdu_buf)); - memcpy(&emu_card_worker->apdu_buf[offset], data, len); - emu_card_worker->apdu_buf_len = len + offset; - return false; -} - -bool emu_card_worker_get_apdu(EmuCardWorker* emu_card_worker, uint8_t* data, uint16_t* len) { - if(!emu_card_worker->apdu_buf_len) { - return false; - } - memcpy(data, &emu_card_worker->apdu_buf[0], emu_card_worker->apdu_buf_len); - *len = emu_card_worker->apdu_buf_len; - emu_card_worker->apdu_buf_len = 0; - return true; -} - -#define NFCA_CRC_INIT (0x6363) -uint16_t nfca_get_crc16(uint8_t* buff, uint16_t len) { - uint16_t crc = NFCA_CRC_INIT; - uint8_t byte = 0; - - for(uint8_t i = 0; i < len; i++) { - byte = buff[i]; - byte ^= (uint8_t)(crc & 0xff); - byte ^= byte << 4; - crc = (crc >> 8) ^ (((uint16_t)byte) << 8) ^ (((uint16_t)byte) << 3) ^ - (((uint16_t)byte) >> 4); - } - - return crc; -} -void nfca_append_crc16(uint8_t* buff, uint16_t len) { - uint16_t crc = nfca_get_crc16(buff, len); - buff[len] = (uint8_t)crc; - buff[len + 1] = (uint8_t)(crc >> 8); -} - -static bool emu_callback( - uint8_t* buff_rx, - uint16_t buff_rx_len, - uint8_t* buff_tx, - uint16_t* buff_tx_len, - uint32_t* flags, - void* context) { -#ifdef FURI_DEBUG - FuriString* debug_buf; - debug_buf = furi_string_alloc(); - for(int i = 0; i < (buff_rx_len + 7) / 8; ++i) { - furi_string_cat_printf(debug_buf, "%02x ", buff_rx[i]); - } - furi_string_trim(debug_buf); - FURI_LOG_T(TAG, "Emu RX (%d): %s", buff_rx_len, furi_string_get_cstr(debug_buf)); - furi_string_reset(debug_buf); -#endif - - furi_assert(context); - EmuCardWorker* emu_card_worker = context; - if(buff_rx_len == 0) { - FURI_LOG_E(TAG, "buff_rx_len=0 ?"); - return false; - } - uint8_t rx_bytes = buff_rx_len / 8; - uint8_t pcb = buff_rx[0]; - - if((pcb & 0xfe) == 0xb2) { - FURI_LOG_D(TAG, "Recv R(NACK)"); - if(emu_card_worker->state == EmuCardWorkerStateWaitApduResp) { - FURI_LOG_D(TAG, "NACK as WTX Resp"); - memcpy(buff_tx, &CMD_14A_WTX[0], sizeof(CMD_14A_WTX)); - buff_tx[0] &= 0xfe; - buff_tx[0] |= pcb & 0x1; - furi_delay_us(emu_card_worker->delayus); - *buff_tx_len = sizeof(CMD_14A_WTX) * 8; - *flags = FURI_HAL_NFC_TX_RAW_RX_DEFAULT; - return true; - } else { - FURI_LOG_D(TAG, "send 0xa2"); - buff_tx[0] = 0xa2; - *buff_tx_len = 1 * 8; - return true; - } - } else if((pcb & 0xfe) == 0xc2) { - FURI_LOG_D(TAG, "Recv S(DESELECT)"); - } else if((pcb & 0xfe) == 0xf2) { - if(emu_card_worker->state == EmuCardWorkerStateWaitApduResp) { - FURI_LOG_T(TAG, "Recv WTX Resp"); - memcpy(buff_tx, &CMD_14A_WTX[0], sizeof(CMD_14A_WTX)); - buff_tx[0] &= 0xfe; - buff_tx[0] |= pcb & 0x1; - furi_delay_us(emu_card_worker->delayus); - *buff_tx_len = sizeof(CMD_14A_WTX) * 8; - *flags = FURI_HAL_NFC_TX_RAW_RX_DEFAULT; - return true; - } else if(emu_card_worker->state == EmuCardWorkerStateGetApduResp) { - FURI_LOG_D(TAG, "Recv WTX Resp, Ready to send Response back"); - memcpy(&buff_tx[0], &emu_card_worker->apdu_buf[0], emu_card_worker->apdu_buf_len); - nfca_append_crc16(&buff_tx[0], emu_card_worker->apdu_buf_len); - *buff_tx_len = (emu_card_worker->apdu_buf_len + 2) * 8; - *flags = FURI_HAL_NFC_TX_RAW_RX_DEFAULT; -#ifdef FURI_DEBUG - debug_buf = furi_string_alloc(); - for(int i = 0; i < (*buff_tx_len + 7) / 8; ++i) { - furi_string_cat_printf(debug_buf, "%02x ", buff_tx[i]); - } - furi_string_trim(debug_buf); - FURI_LOG_T(TAG, "Emu Send (%d): %s", *buff_tx_len, furi_string_get_cstr(debug_buf)); - furi_string_reset(debug_buf); -#endif - emu_card_worker->state = EmuCardWorkerStateWaitApduReq; - return true; - } else { - FURI_LOG_E(TAG, "Recv WTX Resp but we hasn't request"); - } - } else if((pcb & 0xfe) == 0x2) { - // I-Block ignore the block number at LSB - FURI_LOG_T(TAG, "Recv I-Block"); - emu_card_worker_set_apdu(emu_card_worker, 0, buff_rx, rx_bytes); - - FURI_LOG_D(TAG, "Start send WTX"); - memcpy(buff_tx, &CMD_14A_WTX[0], sizeof(CMD_14A_WTX)); - *buff_tx_len = sizeof(CMD_14A_WTX) * 8; - *flags = FURI_HAL_NFC_TX_RAW_RX_DEFAULT; - emu_card_worker->state = EmuCardWorkerStateWaitApduResp; - return true; - } else { - FURI_LOG_E(TAG, "Something unknown"); - *buff_tx_len = UINT16_MAX; - *flags = FURI_HAL_NFC_TX_RAW_RX_DEFAULT; - return true; - } - FURI_LOG_E(TAG, "?"); - *buff_tx_len = UINT16_MAX; - *flags = FURI_HAL_NFC_TX_RAW_RX_DEFAULT; - return false; -} - -EmuCardWorker* emu_card_worker_alloc() { - EmuCardWorker* emu_card_worker = malloc(sizeof(EmuCardWorker)); - - emu_card_worker->thread = - furi_thread_alloc_ex("EmuCardWorker", 2048, emu_card_worker_task, emu_card_worker); - - emu_card_worker->state = EmuCardWorkerStateStop; - emu_card_worker->delayus = 3000; //TODO: Make that configurable - - return emu_card_worker; -} - -void emu_card_worker_free(EmuCardWorker* emu_card_worker) { - furi_assert(emu_card_worker); - - furi_thread_free(emu_card_worker->thread); - free(emu_card_worker); -} - -void emu_card_worker_stop(EmuCardWorker* emu_card_worker) { - furi_assert(emu_card_worker); - - emu_card_worker->state = EmuCardWorkerStateStop; - furi_thread_join(emu_card_worker->thread); -} - -void emu_card_worker_start(EmuCardWorker* emu_card_worker, FuriHalNfcDevData* dev_data) { - furi_assert(emu_card_worker); - furi_hal_nfc_deinit(); - furi_hal_nfc_init(); - - memcpy(&emu_card_worker->dev_data, dev_data, sizeof(FuriHalNfcDevData)); - furi_thread_start(emu_card_worker->thread); -} - -int32_t emu_card_worker_task(void* context) { - furi_assert(context); - EmuCardWorker* emu_card_worker = context; - FURI_LOG_D(TAG, "task start"); - while(furi_hal_nfc_is_busy()) { - furi_delay_ms(10); - FURI_LOG_D(TAG, "busy"); - } - - emu_card_worker->state = EmuCardWorkerStateWaitApduReq; - while(1) { - if(emu_card_worker->state == EmuCardWorkerStateStop) break; - FURI_LOG_D(TAG, "one round"); - furi_hal_nfc_emulate_nfca( - emu_card_worker->dev_data.uid, - emu_card_worker->dev_data.uid_len, - emu_card_worker->dev_data.atqa, - emu_card_worker->dev_data.sak, - emu_callback, - emu_card_worker, - 5000); - } - emu_card_worker->state = EmuCardWorkerStateStop; - FURI_LOG_D(TAG, "task end"); - return 0; -} \ No newline at end of file diff --git a/emu_card_worker.h b/emu_card_worker.h deleted file mode 100644 index e3a812a6fb9..00000000000 --- a/emu_card_worker.h +++ /dev/null @@ -1,34 +0,0 @@ -#pragma once -#include -#include -#include "comm.h" - -typedef enum { - EmuCardWorkerStateStop, - EmuCardWorkerStateWaitApduReq, - EmuCardWorkerStateWaitApduResp, - EmuCardWorkerStateGetApduResp, -} EmuCardWorkerState; - -typedef struct EmuCardWorker { - FuriThread* thread; - FuriHalNfcDevData dev_data; - EmuCardWorkerState state; - uint32_t delayus; - //AsCardWorker* as_card_wroker; - //bool running; - uint16_t apdu_buf_len; - uint8_t apdu_buf[260]; -} EmuCardWorker; - -EmuCardWorker* emu_card_worker_alloc(); -bool emu_card_worker_set_apdu( - EmuCardWorker* emu_card_worker, - uint8_t offset, - uint8_t* data, - uint16_t len); -bool emu_card_worker_get_apdu(EmuCardWorker* emu_card_worker, uint8_t* data, uint16_t* len); -void emu_card_worker_start(EmuCardWorker* emu_card_worker, FuriHalNfcDevData* dev_data); -void emu_card_worker_stop(EmuCardWorker* emu_card_worker); -void emu_card_worker_free(EmuCardWorker* emu_card_worker); -int32_t emu_card_worker_task(void* context); diff --git a/nfc_relay.c b/nfc_relay.c index eb806e37228..c1fcd76368c 100644 --- a/nfc_relay.c +++ b/nfc_relay.c @@ -23,15 +23,13 @@ void nfc_relay_tick_event_callback(void* context) { void nfc_relay_show_loading_popup(void* context, bool show) { NfcRelay* nfc_relay = context; - TaskHandle_t timer_task = xTaskGetHandle(configTIMER_SERVICE_TASK_NAME); - if(show) { // Raise timer priority so that animations can play - vTaskPrioritySet(timer_task, configMAX_PRIORITIES - 1); + furi_timer_set_thread_priority(FuriTimerThreadPriorityElevated); view_dispatcher_switch_to_view(nfc_relay->view_dispatcher, NfcRelayViewLoading); } else { // Restore default timer priority - vTaskPrioritySet(timer_task, configTIMER_TASK_PRIORITY); + furi_timer_set_thread_priority(FuriTimerThreadPriorityNormal); } } @@ -48,9 +46,6 @@ NfcRelay* nfc_relay_alloc() { view_dispatcher_set_tick_event_callback( nfc_relay->view_dispatcher, nfc_relay_tick_event_callback, 100); - view_dispatcher_set_navigation_event_callback( - nfc_relay->view_dispatcher, nfc_relay_back_event_callback); - nfc_relay->gui = furi_record_open(RECORD_GUI); view_dispatcher_attach_to_gui( nfc_relay->view_dispatcher, nfc_relay->gui, ViewDispatcherTypeFullscreen); @@ -87,7 +82,7 @@ NfcRelay* nfc_relay_alloc() { nfc_relay->config = malloc(sizeof(NfcRelayConfig)); nfc_relay->config->mode = NfcRelayModeUart; nfc_relay->config->uart_config.baudrate = 38400; //115200; - nfc_relay->config->uart_config.uartId = FuriHalUartIdLPUART1; + nfc_relay->config->uart_config.serialId = FuriHalSerialIdLpuart; return nfc_relay; } @@ -135,3 +130,26 @@ int32_t nfc_relay_app(void* p) { return 0; } + +void trace_bit_buffer_hexdump(char* tag, char* prompt, BitBuffer* bitbuffer) { +#ifdef TRACE_TRX + FuriString* debug_buf; + debug_buf = furi_string_alloc(); + for(size_t i = 0; i < bit_buffer_get_size_bytes(bitbuffer); i++) { + furi_string_cat_printf(debug_buf, " %02X", bit_buffer_get_byte(bitbuffer, i)); + } + furi_string_trim(debug_buf); + FURI_LOG_T( + tag, + "%s (%d): %s", + prompt, + bit_buffer_get_size(bitbuffer), + furi_string_get_cstr(debug_buf)); + furi_string_free(debug_buf); +#else + UNUSED(tag); + UNUSED(prompt); + UNUSED(bitbuffer); +#endif + return; +} \ No newline at end of file diff --git a/nfc_relay.h b/nfc_relay.h index 73ddd54a3b0..f6c2327929a 100644 --- a/nfc_relay.h +++ b/nfc_relay.h @@ -14,6 +14,7 @@ #include "nfc_relay_icons.h" #include +#include #include @@ -22,7 +23,7 @@ typedef enum { } NfcRelayMode; typedef struct NfcRelayConfigUart { - FuriHalUartId uartId; + FuriHalSerialId serialId; uint32_t baudrate; } NfcRelayConfigUart; @@ -56,4 +57,7 @@ typedef enum { NfcRelayViewLoading, NfcRelayViewTextInput, NfcRelayViewWidget, -} NfcRelayView; \ No newline at end of file +} NfcRelayView; + +#define TRACE_TRX +void trace_bit_buffer_hexdump(char* tag, char* prompt, BitBuffer* bitbuffer); \ No newline at end of file diff --git a/packet.c b/packet.c index b940af8b125..87fda01cac6 100644 --- a/packet.c +++ b/packet.c @@ -2,17 +2,54 @@ #include #include -NfcRelayPacket* packet_no_data_alloc(NfcRelayPacketType typ) { - NfcRelayPacket* packet = malloc(sizeof(NfcRelayPacket)); - packet->typ = typ; - packet->len = 0; - return packet; +NfcRelayPacket* packet_alloc_empty(NfcRelayPacketType typ) { + return packet_alloc(typ, 0); } -NfcRelayPacket* packet_alloc(NfcRelayPacketType typ, uint8_t len, void* data) { +NfcRelayPacket* packet_alloc(NfcRelayPacketType typ, size_t len) { NfcRelayPacket* packet = malloc(sizeof(NfcRelayPacket) + len); packet->typ = typ; packet->len = len; - memcpy(&packet->buf, data, len); return packet; +} + +NfcRelayPacket* + packet_setdata(NfcRelayPacket* packet, size_t offset, size_t len, const void* data) { + memcpy(packet->buf + offset, data, len); + return packet; +} + +NfcRelayPacket* packet_alloc_data(NfcRelayPacketType typ, size_t len, const void* data) { + NfcRelayPacket* packet = packet_alloc(typ, len); + packet_setdata(packet, 0, len, data); + return packet; +} + +SerializedIso14443_4a* iso14443_4a_serialize(const Iso14443_4aData* data) { + size_t total_len = + sizeof(SerializedIso14443_4a) + simple_array_get_count(data->ats_data.t1_tk); + SerializedIso14443_4a* s = malloc(total_len); + memcpy(s->buf_3aData, data->iso14443_3a_data, sizeof(Iso14443_3aData)); + memcpy(s->buf_4aAtsData1, &data->ats_data, sizeof(Iso14443_4aAtsData) - sizeof(SimpleArray*)); + s->len_t1_tk = simple_array_get_count(data->ats_data.t1_tk); + simple_array_cget_data(data->ats_data.t1_tk); + memcpy(&s->buf_t1_tk, simple_array_cget_data(data->ats_data.t1_tk), s->len_t1_tk); + return s; +} + +void iso14443_4a_deserialize(Iso14443_4aData* obj, const SerializedIso14443_4a* serialized) { + iso14443_3a_copy(obj->iso14443_3a_data, (Iso14443_3aData*)serialized->buf_3aData); + memcpy( + &obj->ats_data, + serialized->buf_4aAtsData1, + sizeof(Iso14443_4aAtsData) - sizeof(SimpleArray*)); + + if(serialized->len_t1_tk > 0) { + simple_array_init(obj->ats_data.t1_tk, serialized->len_t1_tk); + memcpy( + simple_array_get_data(obj->ats_data.t1_tk), + serialized->buf_t1_tk, + serialized->len_t1_tk); + } + return; } \ No newline at end of file diff --git a/packet.h b/packet.h index c25e4ec1589..d9d34f68179 100644 --- a/packet.h +++ b/packet.h @@ -1,5 +1,6 @@ #pragma once -#include +#include +#include typedef enum { NfcRelayPacketPing = 0x60, @@ -8,18 +9,30 @@ typedef enum { NfcRelayPacketApduReq, NfcRelayPacketApduResp, NfcRelayPacketErr, -} __attribute__((__packed__)) NfcRelayPacketType; +} NfcRelayPacketType; typedef enum { NfcRelayAsReader, NfcRelayAsCard, -} __attribute__((__packed__)) NfcRelayRole; +} NfcRelayRole; typedef struct NfcRelayPacket { NfcRelayPacketType typ; uint8_t len; uint8_t buf[]; -} __attribute__((aligned(1))) NfcRelayPacket; +} __attribute__((packed, aligned(1))) NfcRelayPacket; -NfcRelayPacket* packet_no_data_alloc(NfcRelayPacketType typ); -NfcRelayPacket* packet_alloc(NfcRelayPacketType typ, uint8_t len, void* data); \ No newline at end of file +typedef struct SerializedIso14443_4a { + uint8_t buf_3aData[sizeof(Iso14443_3aData)]; + uint8_t buf_4aAtsData1[sizeof(Iso14443_4aAtsData) - sizeof(SimpleArray*)]; + size_t len_t1_tk; + uint8_t buf_t1_tk[]; +} __attribute__((packed, aligned(1))) SerializedIso14443_4a; + +NfcRelayPacket* packet_alloc_empty(NfcRelayPacketType typ); +NfcRelayPacket* packet_alloc(NfcRelayPacketType typ, size_t len); +NfcRelayPacket* + packet_setdata(NfcRelayPacket* packet, size_t offset, size_t len, const void* data); +NfcRelayPacket* packet_alloc_data(NfcRelayPacketType typ, size_t len, const void* data); +SerializedIso14443_4a* iso14443_4a_serialize(const Iso14443_4aData* data); +void iso14443_4a_deserialize(Iso14443_4aData* obj, const SerializedIso14443_4a* serialized); \ No newline at end of file diff --git a/uart_worker.c b/uart_worker.c index e55c728586c..342fb062744 100644 --- a/uart_worker.c +++ b/uart_worker.c @@ -1,6 +1,4 @@ #include "uart_worker.h" -#include -#include #define TAG "UartWorker" @@ -8,15 +6,18 @@ void uart_worker_change_state(UartWorker* uart_worker, UartWorkerState state) { furi_assert(uart_worker); uart_worker->state = state; + furi_thread_flags_set(furi_thread_get_id(uart_worker->thread), 1); } void uart_worker_change_rx_sub_state(UartWorker* uart_worker, UartWorkerStateRxSub rx_sub_state) { furi_assert(uart_worker); uart_worker->rxSubState = rx_sub_state; + furi_thread_flags_set(furi_thread_get_id(uart_worker->thread), 1); } UartWorker* uart_worker_alloc(NfcRelayConfigUart config) { + FURI_LOG_D(TAG, "uart_worker_alloc"); UartWorker* uart_worker = malloc(sizeof(UartWorker)); uart_worker->thread = furi_thread_alloc_ex("UartWorker", 2048, uart_worker_task, uart_worker); @@ -32,6 +33,7 @@ UartWorker* uart_worker_alloc(NfcRelayConfigUart config) { void uart_worker_free(UartWorker* uart_worker) { furi_assert(uart_worker); + FURI_LOG_D(TAG, "uart_worker_free"); furi_thread_free(uart_worker->thread); furi_stream_buffer_free(uart_worker->rx_stream); @@ -41,24 +43,29 @@ void uart_worker_free(UartWorker* uart_worker) { void uart_worker_stop(UartWorker* uart_worker) { furi_assert(uart_worker); + FURI_LOG_D(TAG, "uart_worker_stop"); uart_worker_change_state(uart_worker, UartWorkerStateStop); - furi_hal_uart_set_irq_cb(uart_worker->config.uartId, NULL, NULL); - if(uart_worker->config.uartId == FuriHalUartIdUSART1) { - furi_hal_console_enable(); - } else if(uart_worker->config.uartId == FuriHalUartIdLPUART1) { - furi_hal_uart_deinit(FuriHalUartIdLPUART1); - } + //furi_hal_uart_set_irq_cb(uart_worker->config.uartId, NULL, NULL); + //if(uart_worker->config.uartId == FuriHalUartIdUSART1) { + // furi_hal_console_enable(); + //} else if(uart_worker->config.uartId == FuriHalUartIdLPUART1) { + // furi_hal_uart_deinit(FuriHalUartIdLPUART1); + //} + furi_hal_serial_deinit(uart_worker->serial); + furi_hal_serial_control_release(uart_worker->serial); furi_thread_join(uart_worker->thread); } -static void uart_worker_on_irq_cb(UartIrqEvent ev, uint8_t data, void* context) { +static void + uart_worker_on_irq_cb(FuriHalSerialHandle* handle, FuriHalSerialRxEvent event, void* context) { furi_assert(context); UartWorker* uart_worker = context; - if(ev == UartIrqEventRXNE) { + if(event == FuriHalSerialRxEventData) { + uint8_t data = furi_hal_serial_async_rx(handle); furi_stream_buffer_send(uart_worker->rx_stream, &data, 1, 0); //furi_thread_flags_set(furi_thread_get_id(app->worker_thread), WorkerEventRx); uart_worker_change_state(uart_worker, UartWorkerStateRx); @@ -67,13 +74,17 @@ static void uart_worker_on_irq_cb(UartIrqEvent ev, uint8_t data, void* context) void uart_worker_start(UartWorker* uart_worker) { furi_assert(uart_worker); - if(uart_worker->config.uartId == FuriHalUartIdUSART1) { - furi_hal_console_disable(); - furi_hal_uart_set_br(FuriHalUartIdUSART1, uart_worker->config.baudrate); - } else if(uart_worker->config.uartId == FuriHalUartIdLPUART1) { - furi_hal_uart_init(FuriHalUartIdLPUART1, uart_worker->config.baudrate); - } - furi_hal_uart_set_irq_cb(uart_worker->config.uartId, uart_worker_on_irq_cb, uart_worker); + //if(uart_worker->config.uartId == FuriHalUartIdUSART1) { + // furi_hal_console_disable(); + // furi_hal_uart_set_br(FuriHalUartIdUSART1, uart_worker->config.baudrate); + //} else if(uart_worker->config.uartId == FuriHalUartIdLPUART1) { + // furi_hal_uart_init(FuriHalUartIdLPUART1, uart_worker->config.baudrate); + //} + //furi_hal_uart_set_irq_cb(uart_worker->config.uartId, uart_worker_on_irq_cb, uart_worker); + uart_worker->serial = furi_hal_serial_control_acquire(uart_worker->config.serialId); + furi_check(uart_worker->serial); + furi_hal_serial_init(uart_worker->serial, uart_worker->config.baudrate); + furi_hal_serial_async_rx_start(uart_worker->serial, uart_worker_on_irq_cb, uart_worker, true); furi_thread_start(uart_worker->thread); } @@ -82,7 +93,8 @@ void uart_worker_tx(UartWorker* uart_worker, uint8_t* data, size_t len) { furi_assert(uart_worker); furi_assert(data); - furi_hal_uart_tx(uart_worker->config.uartId, data, len); + //furi_hal_uart_tx(uart_worker->config.uartId, data, len); + furi_hal_serial_tx(uart_worker->serial, data, len); } void uart_worker_tx_packet(UartWorker* uart_worker, NfcRelayPacket* packet) { @@ -112,6 +124,8 @@ int32_t uart_worker_task(void* context) { uint8_t tmpdata[256]; uint8_t recv_len = 0; while(1) { + furi_thread_flags_wait(1, FuriFlagWaitAny, FuriWaitForever); + FURI_LOG_D(TAG, "uart_worker_task one round"); if(uart_worker->state == UartWorkerStateStop) break; if(uart_worker->rxSubState == UartWorkerStateRxSubReadTyp && (!uart_worker->packet)) { @@ -163,6 +177,7 @@ int32_t uart_worker_task(void* context) { continue; } } + FURI_LOG_D(TAG, "uart_worker_task return"); return 0; } diff --git a/uart_worker.h b/uart_worker.h index fc6ee40e575..79e84d7bf8c 100644 --- a/uart_worker.h +++ b/uart_worker.h @@ -23,6 +23,7 @@ typedef struct UartWorker { UartWorkerStateRxSub rxSubState; FuriStreamBuffer* rx_stream; NfcRelayPacket* packet; + FuriHalSerialHandle* serial; NfcRelayConfigUart config; } UartWorker;