diff --git a/ccid.c b/ccid.c index 0b6cabe..695f8e3 100644 --- a/ccid.c +++ b/ccid.c @@ -158,29 +158,60 @@ void seader_ccid_XfrBlockToSlot( uint8_t slot, uint8_t* data, size_t len) { - memset(seader_uart->tx_buf, 0, SEADER_UART_RX_BUF_SIZE); - seader_uart->tx_buf[0] = SYNC; - seader_uart->tx_buf[1] = CTRL; - seader_uart->tx_buf[2 + 0] = CCID_MESSAGE_TYPE_PC_to_RDR_XfrBlock; - seader_uart->tx_buf[2 + 1] = (len >> 0) & 0xff; - seader_uart->tx_buf[2 + 2] = (len >> 8) & 0xff; - seader_uart->tx_buf[2 + 5] = slot; - seader_uart->tx_buf[2 + 6] = getSequence(slot); - seader_uart->tx_buf[2 + 7] = 5; - seader_uart->tx_buf[2 + 8] = 0; - seader_uart->tx_buf[2 + 9] = 0; - uint8_t header_len = 2 + 10; - memcpy(seader_uart->tx_buf + header_len, data, len); - seader_uart->tx_len = header_len + len; - seader_uart->tx_len = seader_add_lrc(seader_uart->tx_buf, seader_uart->tx_len); + if(len > ((size_t)SEADER_UART_RX_BUF_SIZE - header_len)) { + FURI_LOG_E(TAG, "CCID frame too long: %d", (int)(header_len + len)); + return; + } + uint8_t* tx_start = (uint8_t*)seader_uart->tx_buf; + uint8_t* tx_end = tx_start + SEADER_UART_RX_BUF_SIZE; + uint8_t* data_addr = (uint8_t*)data; + bool in_scratchpad = false; + if(data_addr >= tx_start + header_len && data_addr <= tx_end) { + size_t available = (size_t)(tx_end - data_addr); + in_scratchpad = len <= available; + } + uint8_t* frame; + + if(in_scratchpad) { + frame = data - header_len; + seader_uart->tx_len = header_len + len; + // Shift frame to start of tx_buf for UART worker + if(frame != seader_uart->tx_buf) { + memmove(seader_uart->tx_buf, frame, seader_uart->tx_len); + frame = seader_uart->tx_buf; + } + } else { + frame = seader_uart->tx_buf; + memset(frame, 0, header_len); + memcpy(frame + header_len, data, len); + seader_uart->tx_len = header_len + len; + } + + frame[0] = SYNC; + frame[1] = CTRL; + frame[2 + 0] = CCID_MESSAGE_TYPE_PC_to_RDR_XfrBlock; + frame[2 + 1] = (len >> 0) & 0xff; + frame[2 + 2] = (len >> 8) & 0xff; + frame[2 + 3] = (len >> 16) & 0xff; + frame[2 + 4] = (len >> 24) & 0xff; + frame[2 + 5] = slot; + frame[2 + 6] = getSequence(slot); + frame[2 + 7] = 5; + frame[2 + 8] = 0; + frame[2 + 9] = 0; + + seader_uart->tx_len = seader_add_lrc(frame, seader_uart->tx_len); + + /* char* display = malloc(seader_uart->tx_len * 2 + 1); for(uint8_t i = 0; i < seader_uart->tx_len; i++) { - snprintf(display + (i * 2), sizeof(display), "%02x", seader_uart->tx_buf[i]); + snprintf(display + (i * 2), sizeof(display), "%02x", frame[i]); } FURI_LOG_D(TAG, "seader_ccid_XfrBlockToSlot(%d) %d: %s", slot, seader_uart->tx_len, display); free(display); + */ furi_thread_flags_set(furi_thread_get_id(seader_uart->tx_thread), WorkerEvtSamRx); }