mirror of
https://github.com/flipperdevices/flipperzero-firmware.git
synced 2025-12-12 20:59:50 +04:00
Add initial ISO7816 support (#3681)
* Add initial ISO7816 support * Format sources and sync API Symbols version * Debug: change VID/PID in ccid test app to opensc detectable generic one Co-authored-by: あく <alleteam@gmail.com>
This commit is contained in:
committed by
GitHub
parent
c93d164785
commit
0d4ead8fbd
@@ -6,8 +6,9 @@
|
|||||||
#include <gui/view_dispatcher.h>
|
#include <gui/view_dispatcher.h>
|
||||||
#include <gui/modules/submenu.h>
|
#include <gui/modules/submenu.h>
|
||||||
#include <gui/gui.h>
|
#include <gui/gui.h>
|
||||||
|
#include "iso7816_callbacks.h"
|
||||||
#include "iso7816_t0_apdu.h"
|
#include "iso7816_t0_apdu.h"
|
||||||
|
#include "iso7816_atr.h"
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
EventTypeInput,
|
EventTypeInput,
|
||||||
@@ -33,38 +34,6 @@ typedef enum {
|
|||||||
CcidTestSubmenuIndexInsertSmartcardReader
|
CcidTestSubmenuIndexInsertSmartcardReader
|
||||||
} SubmenuIndex;
|
} SubmenuIndex;
|
||||||
|
|
||||||
void icc_power_on_callback(uint8_t* atrBuffer, uint32_t* atrlen, void* context) {
|
|
||||||
UNUSED(context);
|
|
||||||
|
|
||||||
iso7816_answer_to_reset(atrBuffer, atrlen);
|
|
||||||
}
|
|
||||||
|
|
||||||
//dataBlock points to the buffer
|
|
||||||
//dataBlockLen tells reader how nany bytes should be read
|
|
||||||
void xfr_datablock_callback(
|
|
||||||
const uint8_t* dataBlock,
|
|
||||||
uint32_t dataBlockLen,
|
|
||||||
uint8_t* responseDataBlock,
|
|
||||||
uint32_t* responseDataBlockLen,
|
|
||||||
void* context) {
|
|
||||||
UNUSED(context);
|
|
||||||
|
|
||||||
struct ISO7816_Command_APDU commandAPDU;
|
|
||||||
iso7816_read_command_apdu(&commandAPDU, dataBlock, dataBlockLen);
|
|
||||||
|
|
||||||
struct ISO7816_Response_APDU responseAPDU;
|
|
||||||
//class not supported
|
|
||||||
responseAPDU.SW1 = 0x6E;
|
|
||||||
responseAPDU.SW2 = 0x00;
|
|
||||||
|
|
||||||
iso7816_write_response_apdu(&responseAPDU, responseDataBlock, responseDataBlockLen);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const CcidCallbacks ccid_cb = {
|
|
||||||
icc_power_on_callback,
|
|
||||||
xfr_datablock_callback,
|
|
||||||
};
|
|
||||||
|
|
||||||
static void ccid_test_app_render_callback(Canvas* canvas, void* ctx) {
|
static void ccid_test_app_render_callback(Canvas* canvas, void* ctx) {
|
||||||
UNUSED(ctx);
|
UNUSED(ctx);
|
||||||
canvas_clear(canvas);
|
canvas_clear(canvas);
|
||||||
@@ -127,6 +96,86 @@ void ccid_test_app_free(CcidTestApp* app) {
|
|||||||
free(app);
|
free(app);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ccid_icc_power_on_callback(uint8_t* atrBuffer, uint32_t* atrlen, void* context) {
|
||||||
|
UNUSED(context);
|
||||||
|
|
||||||
|
iso7816_icc_power_on_callback(atrBuffer, atrlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ccid_xfr_datablock_callback(
|
||||||
|
const uint8_t* pcToReaderDataBlock,
|
||||||
|
uint32_t pcToReaderDataBlockLen,
|
||||||
|
uint8_t* readerToPcDataBlock,
|
||||||
|
uint32_t* readerToPcDataBlockLen,
|
||||||
|
void* context) {
|
||||||
|
UNUSED(context);
|
||||||
|
|
||||||
|
iso7816_xfr_datablock_callback(
|
||||||
|
pcToReaderDataBlock, pcToReaderDataBlockLen, readerToPcDataBlock, readerToPcDataBlockLen);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const CcidCallbacks ccid_cb = {
|
||||||
|
ccid_icc_power_on_callback,
|
||||||
|
ccid_xfr_datablock_callback,
|
||||||
|
};
|
||||||
|
|
||||||
|
void iso7816_answer_to_reset(Iso7816Atr* atr) {
|
||||||
|
//minimum valid ATR: https://smartcard-atr.apdu.fr/parse?ATR=3B+00
|
||||||
|
atr->TS = 0x3B;
|
||||||
|
atr->T0 = 0x00;
|
||||||
|
}
|
||||||
|
|
||||||
|
void iso7816_process_command(
|
||||||
|
const struct ISO7816_Command_APDU* commandAPDU,
|
||||||
|
struct ISO7816_Response_APDU* responseAPDU,
|
||||||
|
const uint8_t* commandApduDataBuffer,
|
||||||
|
uint8_t commandApduDataBufferLen,
|
||||||
|
uint8_t* responseApduDataBuffer,
|
||||||
|
uint8_t* responseApduDataBufferLen) {
|
||||||
|
//example 1: sends a command with no body, receives a response with no body
|
||||||
|
//sends APDU 0x01:0x02:0x00:0x00
|
||||||
|
//receives SW1=0x90, SW2=0x00
|
||||||
|
if(commandAPDU->CLA == 0x01 && commandAPDU->INS == 0x01) {
|
||||||
|
responseAPDU->SW1 = 0x90;
|
||||||
|
responseAPDU->SW2 = 0x00;
|
||||||
|
}
|
||||||
|
//example 2: sends a command with no body, receives a response with a body with two bytes
|
||||||
|
//sends APDU 0x01:0x02:0x00:0x00
|
||||||
|
//receives 'bc' (0x62, 0x63) SW1=0x80, SW2=0x10
|
||||||
|
else if(commandAPDU->CLA == 0x01 && commandAPDU->INS == 0x02) {
|
||||||
|
responseApduDataBuffer[0] = 0x62;
|
||||||
|
responseApduDataBuffer[1] = 0x63;
|
||||||
|
|
||||||
|
*responseApduDataBufferLen = 2;
|
||||||
|
|
||||||
|
responseAPDU->SW1 = 0x90;
|
||||||
|
responseAPDU->SW2 = 0x00;
|
||||||
|
}
|
||||||
|
//example 3: ends a command with a body with two bytes, receives a response with a body with two bytes
|
||||||
|
//sends APDU 0x01:0x03:0x00:0x00:0x02:CA:FE
|
||||||
|
//receives (0xCA, 0xFE) SW1=0x90, SW2=0x02
|
||||||
|
else if(
|
||||||
|
commandAPDU->CLA == 0x01 && commandAPDU->INS == 0x03 && commandApduDataBufferLen == 2 &&
|
||||||
|
commandAPDU->Lc == 2) {
|
||||||
|
//echo command body to response body
|
||||||
|
responseApduDataBuffer[0] = commandApduDataBuffer[0];
|
||||||
|
responseApduDataBuffer[1] = commandApduDataBuffer[1];
|
||||||
|
|
||||||
|
*responseApduDataBufferLen = 2;
|
||||||
|
|
||||||
|
responseAPDU->SW1 = 0x90;
|
||||||
|
responseAPDU->SW2 = 0x00;
|
||||||
|
} else {
|
||||||
|
responseAPDU->SW1 = 0x6A;
|
||||||
|
responseAPDU->SW2 = 0x00;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static const Iso7816Callbacks iso87816_cb = {
|
||||||
|
iso7816_answer_to_reset,
|
||||||
|
iso7816_process_command,
|
||||||
|
};
|
||||||
|
|
||||||
int32_t ccid_test_app(void* p) {
|
int32_t ccid_test_app(void* p) {
|
||||||
UNUSED(p);
|
UNUSED(p);
|
||||||
|
|
||||||
@@ -135,14 +184,16 @@ int32_t ccid_test_app(void* p) {
|
|||||||
|
|
||||||
//setup CCID USB
|
//setup CCID USB
|
||||||
// On linux: set VID PID using: /usr/lib/pcsc/drivers/ifd-ccid.bundle/Contents/Info.plist
|
// On linux: set VID PID using: /usr/lib/pcsc/drivers/ifd-ccid.bundle/Contents/Info.plist
|
||||||
app->ccid_cfg.vid = 0x1234;
|
app->ccid_cfg.vid = 0x076B;
|
||||||
app->ccid_cfg.pid = 0x5678;
|
app->ccid_cfg.pid = 0x3A21;
|
||||||
|
|
||||||
FuriHalUsbInterface* usb_mode_prev = furi_hal_usb_get_config();
|
FuriHalUsbInterface* usb_mode_prev = furi_hal_usb_get_config();
|
||||||
furi_hal_usb_unlock();
|
furi_hal_usb_unlock();
|
||||||
furi_hal_ccid_set_callbacks((CcidCallbacks*)&ccid_cb);
|
furi_hal_ccid_set_callbacks((CcidCallbacks*)&ccid_cb, NULL);
|
||||||
furi_check(furi_hal_usb_set_config(&usb_ccid, &app->ccid_cfg) == true);
|
furi_check(furi_hal_usb_set_config(&usb_ccid, &app->ccid_cfg) == true);
|
||||||
|
|
||||||
|
iso7816_set_callbacks((Iso7816Callbacks*)&iso87816_cb);
|
||||||
|
|
||||||
//handle button events
|
//handle button events
|
||||||
CcidTestAppEvent event;
|
CcidTestAppEvent event;
|
||||||
while(1) {
|
while(1) {
|
||||||
@@ -161,7 +212,9 @@ int32_t ccid_test_app(void* p) {
|
|||||||
|
|
||||||
//tear down USB
|
//tear down USB
|
||||||
furi_hal_usb_set_config(usb_mode_prev, NULL);
|
furi_hal_usb_set_config(usb_mode_prev, NULL);
|
||||||
furi_hal_ccid_set_callbacks(NULL);
|
furi_hal_ccid_set_callbacks(NULL, NULL);
|
||||||
|
|
||||||
|
iso7816_set_callbacks(NULL);
|
||||||
|
|
||||||
//teardown view
|
//teardown view
|
||||||
ccid_test_app_free(app);
|
ccid_test_app_free(app);
|
||||||
|
|||||||
9
applications/debug/ccid_test/iso7816_atr.h
Normal file
9
applications/debug/ccid_test/iso7816_atr.h
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#ifndef _ISO7816_ATR_H_
|
||||||
|
#define _ISO7816_ATR_H_
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t TS;
|
||||||
|
uint8_t T0;
|
||||||
|
} Iso7816Atr;
|
||||||
|
|
||||||
|
#endif //_ISO7816_ATR_H_
|
||||||
76
applications/debug/ccid_test/iso7816_callbacks.c
Normal file
76
applications/debug/ccid_test/iso7816_callbacks.c
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
// 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 "iso7816_t0_apdu.h"
|
||||||
|
#include "iso7816_atr.h"
|
||||||
|
#include "iso7816_callbacks.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <furi.h>
|
||||||
|
|
||||||
|
#define ISO7816_RESPONSE_BUFFER_SIZE 255
|
||||||
|
|
||||||
|
static Iso7816Callbacks* callbacks = NULL;
|
||||||
|
|
||||||
|
void iso7816_set_callbacks(Iso7816Callbacks* cb) {
|
||||||
|
callbacks = cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
void iso7816_icc_power_on_callback(uint8_t* atrBuffer, uint32_t* atrlen) {
|
||||||
|
Iso7816Atr atr;
|
||||||
|
callbacks->iso7816_answer_to_reset(&atr);
|
||||||
|
|
||||||
|
furi_assert(atr.T0 == 0x00);
|
||||||
|
|
||||||
|
uint8_t AtrBuffer[2] = {atr.TS, atr.T0};
|
||||||
|
|
||||||
|
*atrlen = 2;
|
||||||
|
|
||||||
|
memcpy(atrBuffer, AtrBuffer, sizeof(uint8_t) * (*atrlen));
|
||||||
|
}
|
||||||
|
|
||||||
|
//dataBlock points to the buffer
|
||||||
|
//dataBlockLen tells reader how nany bytes should be read
|
||||||
|
void iso7816_xfr_datablock_callback(
|
||||||
|
const uint8_t* pcToReaderDataBlock,
|
||||||
|
uint32_t pcToReaderDataBlockLen,
|
||||||
|
uint8_t* readerToPcDataBlock,
|
||||||
|
uint32_t* readerToPcDataBlockLen) {
|
||||||
|
struct ISO7816_Response_APDU responseAPDU;
|
||||||
|
uint8_t responseApduDataBuffer[ISO7816_RESPONSE_BUFFER_SIZE];
|
||||||
|
uint8_t responseApduDataBufferLen = 0;
|
||||||
|
|
||||||
|
if(callbacks != NULL) {
|
||||||
|
struct ISO7816_Command_APDU commandAPDU;
|
||||||
|
|
||||||
|
const uint8_t* commandApduDataBuffer = NULL;
|
||||||
|
uint8_t commandApduDataBufferLen = 0;
|
||||||
|
|
||||||
|
iso7816_read_command_apdu(&commandAPDU, pcToReaderDataBlock, pcToReaderDataBlockLen);
|
||||||
|
|
||||||
|
if(commandAPDU.Lc > 0) {
|
||||||
|
commandApduDataBufferLen = commandAPDU.Lc;
|
||||||
|
commandApduDataBuffer = &pcToReaderDataBlock[5];
|
||||||
|
}
|
||||||
|
|
||||||
|
callbacks->iso7816_process_command(
|
||||||
|
&commandAPDU,
|
||||||
|
&responseAPDU,
|
||||||
|
commandApduDataBuffer,
|
||||||
|
commandApduDataBufferLen,
|
||||||
|
responseApduDataBuffer,
|
||||||
|
&responseApduDataBufferLen);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
//class not supported
|
||||||
|
responseAPDU.SW1 = 0x6E;
|
||||||
|
responseAPDU.SW2 = 0x00;
|
||||||
|
}
|
||||||
|
|
||||||
|
iso7816_write_response_apdu(
|
||||||
|
&responseAPDU,
|
||||||
|
readerToPcDataBlock,
|
||||||
|
readerToPcDataBlockLen,
|
||||||
|
responseApduDataBuffer,
|
||||||
|
responseApduDataBufferLen);
|
||||||
|
}
|
||||||
28
applications/debug/ccid_test/iso7816_callbacks.h
Normal file
28
applications/debug/ccid_test/iso7816_callbacks.h
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
#ifndef _ISO7816_CALLBACKS_H_
|
||||||
|
#define _ISO7816_CALLBACKS_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "iso7816_atr.h"
|
||||||
|
#include "iso7816_t0_apdu.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
void (*iso7816_answer_to_reset)(Iso7816Atr* atr);
|
||||||
|
void (*iso7816_process_command)(
|
||||||
|
const struct ISO7816_Command_APDU* command,
|
||||||
|
struct ISO7816_Response_APDU* response,
|
||||||
|
const uint8_t* commandApduDataBuffer,
|
||||||
|
uint8_t commandApduDataBufferLen,
|
||||||
|
uint8_t* responseApduDataBuffer,
|
||||||
|
uint8_t* responseApduDataBufferLen);
|
||||||
|
} Iso7816Callbacks;
|
||||||
|
|
||||||
|
void iso7816_set_callbacks(Iso7816Callbacks* cb);
|
||||||
|
|
||||||
|
void iso7816_icc_power_on_callback(uint8_t* atrBuffer, uint32_t* atrlen);
|
||||||
|
void iso7816_xfr_datablock_callback(
|
||||||
|
const uint8_t* dataBlock,
|
||||||
|
uint32_t dataBlockLen,
|
||||||
|
uint8_t* responseDataBlock,
|
||||||
|
uint32_t* responseDataBlockLen);
|
||||||
|
|
||||||
|
#endif //_ISO7816_CALLBACKS_H_
|
||||||
@@ -4,22 +4,14 @@
|
|||||||
#include <furi.h>
|
#include <furi.h>
|
||||||
#include "iso7816_t0_apdu.h"
|
#include "iso7816_t0_apdu.h"
|
||||||
|
|
||||||
void iso7816_answer_to_reset(uint8_t* dataBuffer, uint32_t* atrlen) {
|
//reads dataBuffer with dataLen size, translate it into a ISO7816_Command_APDU type
|
||||||
//minimum valid ATR: https://smartcard-atr.apdu.fr/parse?ATR=3B+00
|
//extra data will be pointed to commandDataBuffer
|
||||||
uint8_t AtrBuffer[2] = {
|
|
||||||
0x3B, //TS (direct convention)
|
|
||||||
0x00 // T0 (Y(1): b0000, K: 0 (historical bytes))
|
|
||||||
};
|
|
||||||
*atrlen = 2;
|
|
||||||
|
|
||||||
memcpy(dataBuffer, AtrBuffer, sizeof(uint8_t) * (*atrlen));
|
|
||||||
}
|
|
||||||
|
|
||||||
void iso7816_read_command_apdu(
|
void iso7816_read_command_apdu(
|
||||||
struct ISO7816_Command_APDU* command,
|
struct ISO7816_Command_APDU* command,
|
||||||
const uint8_t* dataBuffer,
|
const uint8_t* dataBuffer,
|
||||||
uint32_t dataLen) {
|
uint32_t dataLen) {
|
||||||
UNUSED(dataLen);
|
UNUSED(dataLen);
|
||||||
|
|
||||||
command->CLA = dataBuffer[0];
|
command->CLA = dataBuffer[0];
|
||||||
command->INS = dataBuffer[1];
|
command->INS = dataBuffer[1];
|
||||||
command->P1 = dataBuffer[2];
|
command->P1 = dataBuffer[2];
|
||||||
@@ -27,11 +19,30 @@ void iso7816_read_command_apdu(
|
|||||||
command->Lc = dataBuffer[4];
|
command->Lc = dataBuffer[4];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//data buffer countains the whole APU response (response + trailer (SW1+SW2))
|
||||||
void iso7816_write_response_apdu(
|
void iso7816_write_response_apdu(
|
||||||
const struct ISO7816_Response_APDU* response,
|
const struct ISO7816_Response_APDU* response,
|
||||||
uint8_t* dataBuffer,
|
uint8_t* readerToPcDataBlock,
|
||||||
uint32_t* dataLen) {
|
uint32_t* readerToPcDataBlockLen,
|
||||||
dataBuffer[0] = response->SW1;
|
uint8_t* responseDataBuffer,
|
||||||
dataBuffer[1] = response->SW2;
|
uint32_t responseDataLen) {
|
||||||
*dataLen = 2;
|
uint32_t responseDataBufferIndex = 0;
|
||||||
|
|
||||||
|
//response body
|
||||||
|
if(responseDataLen > 0) {
|
||||||
|
while(responseDataBufferIndex < responseDataLen) {
|
||||||
|
readerToPcDataBlock[responseDataBufferIndex] =
|
||||||
|
responseDataBuffer[responseDataBufferIndex];
|
||||||
|
responseDataBufferIndex++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//trailer
|
||||||
|
readerToPcDataBlock[responseDataBufferIndex] = response->SW1;
|
||||||
|
responseDataBufferIndex++;
|
||||||
|
|
||||||
|
readerToPcDataBlock[responseDataBufferIndex] = response->SW2;
|
||||||
|
responseDataBufferIndex++;
|
||||||
|
|
||||||
|
*readerToPcDataBlockLen = responseDataBufferIndex;
|
||||||
}
|
}
|
||||||
@@ -2,6 +2,8 @@
|
|||||||
#define _ISO7816_T0_APDU_H_
|
#define _ISO7816_T0_APDU_H_
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include "iso7816_atr.h"
|
||||||
|
#include "core/common_defines.h"
|
||||||
|
|
||||||
struct ISO7816_Command_APDU {
|
struct ISO7816_Command_APDU {
|
||||||
//header
|
//header
|
||||||
@@ -20,13 +22,15 @@ struct ISO7816_Response_APDU {
|
|||||||
uint8_t SW2;
|
uint8_t SW2;
|
||||||
} FURI_PACKED;
|
} FURI_PACKED;
|
||||||
|
|
||||||
void iso7816_answer_to_reset(uint8_t* atrBuffer, uint32_t* atrlen);
|
void iso7816_answer_to_reset(Iso7816Atr* atr);
|
||||||
void iso7816_read_command_apdu(
|
void iso7816_read_command_apdu(
|
||||||
struct ISO7816_Command_APDU* command,
|
struct ISO7816_Command_APDU* command,
|
||||||
const uint8_t* dataBuffer,
|
const uint8_t* dataBuffer,
|
||||||
uint32_t dataLen);
|
uint32_t dataLen);
|
||||||
void iso7816_write_response_apdu(
|
void iso7816_write_response_apdu(
|
||||||
const struct ISO7816_Response_APDU* response,
|
const struct ISO7816_Response_APDU* response,
|
||||||
uint8_t* dataBuffer,
|
uint8_t* readerToPcDataBlock,
|
||||||
uint32_t* dataLen);
|
uint32_t* readerToPcDataBlockLen,
|
||||||
|
uint8_t* responseDataBuffer,
|
||||||
|
uint32_t responseDataLen);
|
||||||
#endif //_ISO7816_T0_APDU_H_
|
#endif //_ISO7816_T0_APDU_H_
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
entry,status,name,type,params
|
entry,status,name,type,params
|
||||||
Version,+,62.3,,
|
Version,+,63.0,,
|
||||||
Header,+,applications/services/bt/bt_service/bt.h,,
|
Header,+,applications/services/bt/bt_service/bt.h,,
|
||||||
Header,+,applications/services/bt/bt_service/bt_keys_storage.h,,
|
Header,+,applications/services/bt/bt_service/bt_keys_storage.h,,
|
||||||
Header,+,applications/services/cli/cli.h,,
|
Header,+,applications/services/cli/cli.h,,
|
||||||
@@ -1157,7 +1157,7 @@ Function,+,furi_hal_bus_is_enabled,_Bool,FuriHalBus
|
|||||||
Function,+,furi_hal_bus_reset,void,FuriHalBus
|
Function,+,furi_hal_bus_reset,void,FuriHalBus
|
||||||
Function,+,furi_hal_ccid_ccid_insert_smartcard,void,
|
Function,+,furi_hal_ccid_ccid_insert_smartcard,void,
|
||||||
Function,+,furi_hal_ccid_ccid_remove_smartcard,void,
|
Function,+,furi_hal_ccid_ccid_remove_smartcard,void,
|
||||||
Function,+,furi_hal_ccid_set_callbacks,void,CcidCallbacks*
|
Function,+,furi_hal_ccid_set_callbacks,void,"CcidCallbacks*, void*"
|
||||||
Function,+,furi_hal_cdc_get_ctrl_line_state,uint8_t,uint8_t
|
Function,+,furi_hal_cdc_get_ctrl_line_state,uint8_t,uint8_t
|
||||||
Function,+,furi_hal_cdc_get_port_settings,usb_cdc_line_coding*,uint8_t
|
Function,+,furi_hal_cdc_get_port_settings,usb_cdc_line_coding*,uint8_t
|
||||||
Function,+,furi_hal_cdc_receive,int32_t,"uint8_t, uint8_t*, uint16_t"
|
Function,+,furi_hal_cdc_receive,int32_t,"uint8_t, uint8_t*, uint16_t"
|
||||||
|
|||||||
|
@@ -1,5 +1,5 @@
|
|||||||
entry,status,name,type,params
|
entry,status,name,type,params
|
||||||
Version,+,62.3,,
|
Version,+,63.0,,
|
||||||
Header,+,applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.h,,
|
Header,+,applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.h,,
|
||||||
Header,+,applications/services/bt/bt_service/bt.h,,
|
Header,+,applications/services/bt/bt_service/bt.h,,
|
||||||
Header,+,applications/services/bt/bt_service/bt_keys_storage.h,,
|
Header,+,applications/services/bt/bt_service/bt_keys_storage.h,,
|
||||||
@@ -1256,7 +1256,7 @@ Function,+,furi_hal_bus_is_enabled,_Bool,FuriHalBus
|
|||||||
Function,+,furi_hal_bus_reset,void,FuriHalBus
|
Function,+,furi_hal_bus_reset,void,FuriHalBus
|
||||||
Function,+,furi_hal_ccid_ccid_insert_smartcard,void,
|
Function,+,furi_hal_ccid_ccid_insert_smartcard,void,
|
||||||
Function,+,furi_hal_ccid_ccid_remove_smartcard,void,
|
Function,+,furi_hal_ccid_ccid_remove_smartcard,void,
|
||||||
Function,+,furi_hal_ccid_set_callbacks,void,CcidCallbacks*
|
Function,+,furi_hal_ccid_set_callbacks,void,"CcidCallbacks*, void*"
|
||||||
Function,+,furi_hal_cdc_get_ctrl_line_state,uint8_t,uint8_t
|
Function,+,furi_hal_cdc_get_ctrl_line_state,uint8_t,uint8_t
|
||||||
Function,+,furi_hal_cdc_get_port_settings,usb_cdc_line_coding*,uint8_t
|
Function,+,furi_hal_cdc_get_port_settings,usb_cdc_line_coding*,uint8_t
|
||||||
Function,+,furi_hal_cdc_receive,int32_t,"uint8_t, uint8_t*, uint16_t"
|
Function,+,furi_hal_cdc_receive,int32_t,"uint8_t, uint8_t*, uint16_t"
|
||||||
|
|||||||
|
@@ -184,6 +184,7 @@ static usbd_device* usb_dev;
|
|||||||
static bool connected = false;
|
static bool connected = false;
|
||||||
static bool smartcard_inserted = true;
|
static bool smartcard_inserted = true;
|
||||||
static CcidCallbacks* callbacks[CCID_TOTAL_SLOTS] = {NULL};
|
static CcidCallbacks* callbacks[CCID_TOTAL_SLOTS] = {NULL};
|
||||||
|
static void* cb_ctx[CCID_TOTAL_SLOTS];
|
||||||
|
|
||||||
static void* ccid_set_string_descr(char* str) {
|
static void* ccid_set_string_descr(char* str) {
|
||||||
furi_check(str);
|
furi_check(str);
|
||||||
@@ -330,7 +331,9 @@ void CALLBACK_CCID_IccPowerOn(
|
|||||||
if(smartcard_inserted) {
|
if(smartcard_inserted) {
|
||||||
if(callbacks[CCID_SLOT_INDEX] != NULL) {
|
if(callbacks[CCID_SLOT_INDEX] != NULL) {
|
||||||
callbacks[CCID_SLOT_INDEX]->icc_power_on_callback(
|
callbacks[CCID_SLOT_INDEX]->icc_power_on_callback(
|
||||||
responseDataBlock->abData, &responseDataBlock->dwLength, NULL);
|
responseDataBlock->abData,
|
||||||
|
&responseDataBlock->dwLength,
|
||||||
|
cb_ctx[CCID_SLOT_INDEX]);
|
||||||
responseDataBlock->bStatus = CCID_COMMANDSTATUS_PROCESSEDWITHOUTERROR |
|
responseDataBlock->bStatus = CCID_COMMANDSTATUS_PROCESSEDWITHOUTERROR |
|
||||||
CCID_ICCSTATUS_PRESENTANDACTIVE;
|
CCID_ICCSTATUS_PRESENTANDACTIVE;
|
||||||
} else {
|
} else {
|
||||||
@@ -364,7 +367,7 @@ void CALLBACK_CCID_XfrBlock(
|
|||||||
receivedXfrBlock->dwLength,
|
receivedXfrBlock->dwLength,
|
||||||
responseDataBlock->abData,
|
responseDataBlock->abData,
|
||||||
&responseDataBlock->dwLength,
|
&responseDataBlock->dwLength,
|
||||||
NULL);
|
cb_ctx[CCID_SLOT_INDEX]);
|
||||||
responseDataBlock->bStatus = CCID_COMMANDSTATUS_PROCESSEDWITHOUTERROR |
|
responseDataBlock->bStatus = CCID_COMMANDSTATUS_PROCESSEDWITHOUTERROR |
|
||||||
CCID_ICCSTATUS_PRESENTANDACTIVE;
|
CCID_ICCSTATUS_PRESENTANDACTIVE;
|
||||||
} else {
|
} else {
|
||||||
@@ -389,8 +392,9 @@ void furi_hal_ccid_ccid_remove_smartcard(void) {
|
|||||||
smartcard_inserted = false;
|
smartcard_inserted = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void furi_hal_ccid_set_callbacks(CcidCallbacks* cb) {
|
void furi_hal_ccid_set_callbacks(CcidCallbacks* cb, void* context) {
|
||||||
callbacks[CCID_SLOT_INDEX] = cb;
|
callbacks[CCID_SLOT_INDEX] = cb;
|
||||||
|
cb_ctx[CCID_SLOT_INDEX] = context;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ccid_rx_ep_callback(usbd_device* dev, uint8_t event, uint8_t ep) {
|
static void ccid_rx_ep_callback(usbd_device* dev, uint8_t event, uint8_t ep) {
|
||||||
|
|||||||
@@ -19,14 +19,14 @@ typedef struct {
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
void (*icc_power_on_callback)(uint8_t* dataBlock, uint32_t* dataBlockLen, void* context);
|
void (*icc_power_on_callback)(uint8_t* dataBlock, uint32_t* dataBlockLen, void* context);
|
||||||
void (*xfr_datablock_callback)(
|
void (*xfr_datablock_callback)(
|
||||||
const uint8_t* dataBlock,
|
const uint8_t* pcToReaderDataBlock,
|
||||||
uint32_t dataBlockLen,
|
uint32_t pcToReaderDataBlockLen,
|
||||||
uint8_t* responseDataBlock,
|
uint8_t* readerToPcDataBlock,
|
||||||
uint32_t* responseDataBlockLen,
|
uint32_t* readerToPcDataBlockLen,
|
||||||
void* context);
|
void* context);
|
||||||
} CcidCallbacks;
|
} CcidCallbacks;
|
||||||
|
|
||||||
void furi_hal_ccid_set_callbacks(CcidCallbacks* cb);
|
void furi_hal_ccid_set_callbacks(CcidCallbacks* cb, void* context);
|
||||||
|
|
||||||
void furi_hal_ccid_ccid_insert_smartcard(void);
|
void furi_hal_ccid_ccid_insert_smartcard(void);
|
||||||
void furi_hal_ccid_ccid_remove_smartcard(void);
|
void furi_hal_ccid_ccid_remove_smartcard(void);
|
||||||
|
|||||||
Reference in New Issue
Block a user