Files
Momentum-Firmware/applications/debug/ccid_test/iso7816/iso7816_handler.c
Filipe Paz Rodrigues 4a58930247 CCID: App changes (#3837)
- Keep ccid_callback and buffer as private to the iso7816_handler
- set usb ccid callback from iso7816_handler (to ensure the right structure is being passed)
- make iso7816 related code independent from furi related code (goal is to make it independently testable)
- rename vars

Co-authored-by: あく <alleteam@gmail.com>
2024-09-05 16:04:32 +01:00

97 lines
3.1 KiB
C

// transforms low level calls such as XFRCallback or ICC Power on to a structured one
// an application can register these calls and listen for the callbacks defined in Iso7816Callbacks
#include <stdint.h>
#include <stddef.h>
#include <furi.h>
#include <furi_hal.h>
#include "iso7816_handler.h"
#include "iso7816_t0_apdu.h"
#include "iso7816_atr.h"
#include "iso7816_response.h"
static Iso7816Handler* iso7816_handler;
static CcidCallbacks* ccid_callbacks;
static uint8_t* command_apdu_buffer;
static uint8_t* response_apdu_buffer;
void iso7816_icc_power_on_callback(uint8_t* atr_data, uint32_t* atr_data_len, void* context) {
furi_check(context);
Iso7816Handler* handler = (Iso7816Handler*)context;
Iso7816Atr iso7816_atr;
handler->iso7816_answer_to_reset(&iso7816_atr);
furi_assert(iso7816_atr.T0 == 0x00);
uint8_t atr_buffer[2] = {iso7816_atr.TS, iso7816_atr.T0};
*atr_data_len = 2;
memcpy(atr_data, atr_buffer, sizeof(uint8_t) * (*atr_data_len));
}
//dataBlock points to the buffer
//dataBlockLen tells reader how nany bytes should be read
void iso7816_xfr_datablock_callback(
const uint8_t* pc_to_reader_datablock,
uint32_t pc_to_reader_datablock_len,
uint8_t* reader_to_pc_datablock,
uint32_t* reader_to_pc_datablock_len,
void* context) {
furi_check(context);
Iso7816Handler* handler = (Iso7816Handler*)context;
ISO7816_Response_APDU* response_apdu = (ISO7816_Response_APDU*)response_apdu_buffer;
ISO7816_Command_APDU* command_apdu = (ISO7816_Command_APDU*)command_apdu_buffer;
uint8_t result = iso7816_read_command_apdu(
command_apdu, pc_to_reader_datablock, pc_to_reader_datablock_len, CCID_SHORT_APDU_SIZE);
if(result == ISO7816_READ_COMMAND_APDU_OK) {
handler->iso7816_process_command(command_apdu, response_apdu);
furi_assert(response_apdu->DataLen < CCID_SHORT_APDU_SIZE);
} else if(result == ISO7816_READ_COMMAND_APDU_ERROR_WRONG_LE) {
iso7816_set_response(response_apdu, ISO7816_RESPONSE_WRONG_LE);
} else if(result == ISO7816_READ_COMMAND_APDU_ERROR_WRONG_LENGTH) {
iso7816_set_response(response_apdu, ISO7816_RESPONSE_WRONG_LENGTH);
}
iso7816_write_response_apdu(response_apdu, reader_to_pc_datablock, reader_to_pc_datablock_len);
}
Iso7816Handler* iso7816_handler_alloc() {
iso7816_handler = malloc(sizeof(Iso7816Handler));
command_apdu_buffer = malloc(sizeof(ISO7816_Command_APDU) + CCID_SHORT_APDU_SIZE);
response_apdu_buffer = malloc(sizeof(ISO7816_Response_APDU) + CCID_SHORT_APDU_SIZE);
ccid_callbacks = malloc(sizeof(CcidCallbacks));
ccid_callbacks->icc_power_on_callback = iso7816_icc_power_on_callback;
ccid_callbacks->xfr_datablock_callback = iso7816_xfr_datablock_callback;
return iso7816_handler;
}
void iso7816_handler_set_usb_ccid_callbacks() {
furi_hal_usb_ccid_set_callbacks(ccid_callbacks, iso7816_handler);
}
void iso7816_handler_reset_usb_ccid_callbacks() {
furi_hal_usb_ccid_set_callbacks(NULL, NULL);
}
void iso7816_handler_free(Iso7816Handler* handler) {
free(ccid_callbacks);
free(command_apdu_buffer);
free(response_apdu_buffer);
free(handler);
}