From 83e4bcc35a1a9d381550902a38e6f74c81cab73e Mon Sep 17 00:00:00 2001 From: Skorpionm <85568270+Skorpionm@users.noreply.github.com> Date: Sat, 1 Jun 2024 15:15:24 +0400 Subject: [PATCH 1/3] SubGhz: Princeton protocol add custom guard time (#3671) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * SubGhz: Princeton protocol add custom guard time * SubGhz: fix type var * SubGhz: fix syntax * SubGhz: add define PRINCETON_GUARD_TIME_DEFALUT * Update princeton.c Co-authored-by: あく --- .../helpers/subghz_txrx_create_protocol_key.c | 8 ++++++ lib/subghz/protocols/princeton.c | 25 +++++++++++++++++-- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/applications/main/subghz/helpers/subghz_txrx_create_protocol_key.c b/applications/main/subghz/helpers/subghz_txrx_create_protocol_key.c index 0413173e6..bafaef5ee 100644 --- a/applications/main/subghz/helpers/subghz_txrx_create_protocol_key.c +++ b/applications/main/subghz/helpers/subghz_txrx_create_protocol_key.c @@ -80,6 +80,14 @@ SubGhzProtocolStatus subghz_txrx_gen_data_protocol_and_te( FURI_LOG_E(TAG, "Unable to update Te"); } } + if(ret == SubGhzProtocolStatusOk) { + uint32_t guard_time = 30; + if(!flipper_format_update_uint32( + instance->fff_data, "Guard_time", (uint32_t*)&guard_time, 1)) { + ret = SubGhzProtocolStatusErrorParserOthers; + FURI_LOG_E(TAG, "Unable to update Guard_time"); + } + } return ret; } diff --git a/lib/subghz/protocols/princeton.c b/lib/subghz/protocols/princeton.c index aa15b8b41..60b394e78 100644 --- a/lib/subghz/protocols/princeton.c +++ b/lib/subghz/protocols/princeton.c @@ -13,6 +13,7 @@ */ #define TAG "SubGhzProtocolPrinceton" +#define PRINCETON_GUARD_TIME_DEFALUT 30 //GUARD_TIME = PRINCETON_GUARD_TIME_DEFALUT * TE static const SubGhzBlockConst subghz_protocol_princeton_const = { .te_short = 390, @@ -29,6 +30,7 @@ struct SubGhzProtocolDecoderPrinceton { uint32_t te; uint32_t last_data; + uint32_t guard_time; }; struct SubGhzProtocolEncoderPrinceton { @@ -38,6 +40,7 @@ struct SubGhzProtocolEncoderPrinceton { SubGhzBlockGeneric generic; uint32_t te; + uint32_t guard_time; }; typedef enum { @@ -135,8 +138,9 @@ static bool //Send Stop bit instance->encoder.upload[index++] = level_duration_make(true, (uint32_t)instance->te); - //Send PT_GUARD - instance->encoder.upload[index++] = level_duration_make(false, (uint32_t)instance->te * 30); + //Send PT_GUARD_TIME + instance->encoder.upload[index++] = + level_duration_make(false, (uint32_t)instance->te * instance->guard_time); return true; } @@ -165,6 +169,11 @@ SubGhzProtocolStatus break; } //optional parameter parameter + if(!flipper_format_read_uint32( + flipper_format, "Guard_time", (uint32_t*)&instance->guard_time, 1)) { + instance->guard_time = PRINCETON_GUARD_TIME_DEFALUT; + } + flipper_format_read_uint32( flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); @@ -235,6 +244,7 @@ void subghz_protocol_decoder_princeton_feed(void* context, bool level, uint32_t instance->decoder.decode_data = 0; instance->decoder.decode_count_bit = 0; instance->te = 0; + instance->guard_time = PRINCETON_GUARD_TIME_DEFALUT; } break; case PrincetonDecoderStepSaveDuration: @@ -257,6 +267,7 @@ void subghz_protocol_decoder_princeton_feed(void* context, bool level, uint32_t instance->generic.data = instance->decoder.decode_data; instance->generic.data_count_bit = instance->decoder.decode_count_bit; + instance->guard_time = round((float)duration / instance->te); if(instance->base.callback) instance->base.callback(&instance->base, instance->base.context); @@ -323,6 +334,12 @@ SubGhzProtocolStatus subghz_protocol_decoder_princeton_serialize( FURI_LOG_E(TAG, "Unable to add TE"); ret = SubGhzProtocolStatusErrorParserTe; } + if((ret == SubGhzProtocolStatusOk) && + !flipper_format_write_uint32(flipper_format, "Guard_time", &instance->guard_time, 1)) { + FURI_LOG_E(TAG, "Unable to add Guard_time"); + ret = SubGhzProtocolStatusErrorParserOthers; + } + return ret; } @@ -349,6 +366,10 @@ SubGhzProtocolStatus ret = SubGhzProtocolStatusErrorParserTe; break; } + if(!flipper_format_read_uint32( + flipper_format, "Guard_time", (uint32_t*)&instance->guard_time, 1)) { + instance->guard_time = PRINCETON_GUARD_TIME_DEFALUT; + } } while(false); return ret; From c93d1647855b9cae55ef1686ebb2c833685fce85 Mon Sep 17 00:00:00 2001 From: hedger Date: Sat, 1 Jun 2024 16:20:51 +0400 Subject: [PATCH 2/3] fbt, vscode: tweaks for cdb generation for clangd (#3680) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fbt, vscode: tweaks for cdb generation for clangd * .clangd: updated config * vscode: disabled auto header insertion for clangd * .clangd: updated config, ignoring format warnings * Add sublime text project * vscode: enabled clang-tidy for clangd * clangd: strict include checks for sources only Co-authored-by: あく --- .clangd | 13 ++++++++++++ .gitignore | 3 +++ .sublime-project | 21 ++++++++++++++++++ .vscode/example/settings.json | 4 +++- firmware.scons | 1 + scripts/fbt_tools/ccache.py | 1 + scripts/fbt_tools/compilation_db.py | 33 ++++++++++++++++++----------- scripts/ufbt/SConstruct | 1 + 8 files changed, 64 insertions(+), 13 deletions(-) create mode 100644 .clangd create mode 100644 .sublime-project diff --git a/.clangd b/.clangd new file mode 100644 index 000000000..3e0024e8c --- /dev/null +++ b/.clangd @@ -0,0 +1,13 @@ +CompileFlags: + Add: + - -Wno-unknown-warning-option + - -Wno-format + Remove: + - -mword-relocations + +--- + +If: + PathMatch: .*\.h +Diagnostics: + UnusedIncludes: None diff --git a/.gitignore b/.gitignore index d60dcec3f..56c836338 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,9 @@ compile_commands.json # JetBrains IDEs .idea/ +# Sublime Text +.sublime-project.sublime-workspace + # Python VirtEnvironments .env .venv diff --git a/.sublime-project b/.sublime-project new file mode 100644 index 000000000..4912c9974 --- /dev/null +++ b/.sublime-project @@ -0,0 +1,21 @@ +{ + "folders": + [ + { + "path": ".", + } + ], + "settings": { + "LSP": { + "clangd": { + "initializationOptions": { + "clangd.compile-commands-dir": "build/latest", + "clangd.header-insertion": null, + "clangd.query-driver": "**", + "clangd.clang-tidy": true, + }, + "enabled": true, + }, + }, + }, +} diff --git a/.vscode/example/settings.json b/.vscode/example/settings.json index a59194901..9afabf926 100644 --- a/.vscode/example/settings.json +++ b/.vscode/example/settings.json @@ -19,6 +19,8 @@ "clangd.arguments": [ // We might be able to tighten this a bit more to only include the correct toolchain. "--query-driver=**", - "--compile-commands-dir=${workspaceFolder}/build/latest" + "--compile-commands-dir=${workspaceFolder}/build/latest", + "--clang-tidy", + "--header-insertion=never" ] } \ No newline at end of file diff --git a/firmware.scons b/firmware.scons index bf3f46a9b..62b1184eb 100644 --- a/firmware.scons +++ b/firmware.scons @@ -20,6 +20,7 @@ env = ENV.Clone( "fbt_resources", ], COMPILATIONDB_USE_ABSPATH=False, + COMPILATIONDB_USE_BINARY_ABSPATH=True, BUILD_DIR=fw_build_meta["build_dir"], IS_BASE_FIRMWARE=fw_build_meta["type"] == "firmware", FW_FLAVOR=fw_build_meta["flavor"], diff --git a/scripts/fbt_tools/ccache.py b/scripts/fbt_tools/ccache.py index 63577ab78..a7e546422 100644 --- a/scripts/fbt_tools/ccache.py +++ b/scripts/fbt_tools/ccache.py @@ -12,3 +12,4 @@ def generate(env): env["LINK"] = env["CXX"] env["CXX_NOCACHE"] = env["CXX"] env["CXX"] = "$CCACHE $CXX_NOCACHE" + env.AppendUnique(COMPILATIONDB_OMIT_BINARIES=["ccache"]) diff --git a/scripts/fbt_tools/compilation_db.py b/scripts/fbt_tools/compilation_db.py index 3d5e469f4..6bad96b2d 100644 --- a/scripts/fbt_tools/compilation_db.py +++ b/scripts/fbt_tools/compilation_db.py @@ -32,7 +32,7 @@ which is the name that most clang tools search for by default. import fnmatch import itertools import json -from shlex import quote +from shlex import join, split import SCons from SCons.Tool.asm import ASPPSuffixes, ASSuffixes @@ -108,6 +108,10 @@ def make_emit_compilation_DB_entry(comstr): return emit_compilation_db_entry +def __is_value_true(value): + return value in [True, 1, "True", "true"] + + def compilation_db_entry_action(target, source, env, **kw): """ Create a dictionary with evaluated command line, target, source @@ -126,16 +130,19 @@ def compilation_db_entry_action(target, source, env, **kw): env=env["__COMPILATIONDB_ENV"], ) - # We assume first non-space character is the executable - executable = command.split(" ", 1)[0] - if not (tool_path := _TOOL_PATH_CACHE.get(executable, None)): - tool_path = env.WhereIs(executable) or executable - _TOOL_PATH_CACHE[executable] = tool_path - # If there are spaces in the executable path, we need to quote it - if " " in tool_path: - tool_path = quote(tool_path) - # Replacing the executable with the full path - command = tool_path + command[len(executable) :] + cmdline = split(command) + binaries_to_omit = env["COMPILATIONDB_OMIT_BINARIES"] + while (executable := cmdline[0]) in binaries_to_omit: + cmdline.pop(0) + + if __is_value_true(env["COMPILATIONDB_USE_BINARY_ABSPATH"]): + if not (tool_path := _TOOL_PATH_CACHE.get(executable, None)): + tool_path = env.WhereIs(executable) or executable + _TOOL_PATH_CACHE[executable] = tool_path + # Replacing the executable with the full path + executable = tool_path + + command = join((executable, *cmdline[1:])) entry = { "directory": env.Dir("#").abspath, @@ -150,7 +157,7 @@ def compilation_db_entry_action(target, source, env, **kw): def write_compilation_db(target, source, env): entries = [] - use_abspath = env["COMPILATIONDB_USE_ABSPATH"] in [True, 1, "True", "true"] + use_abspath = __is_value_true(env["COMPILATIONDB_USE_ABSPATH"]) use_path_filter = env.subst("$COMPILATIONDB_PATH_FILTER") use_srcpath_filter = env.subst("$COMPILATIONDB_SRCPATH_FILTER") @@ -225,6 +232,8 @@ def generate(env, **kwargs): COMPILATIONDB_USE_ABSPATH=False, COMPILATIONDB_PATH_FILTER="", COMPILATIONDB_SRCPATH_FILTER="", + COMPILATIONDB_OMIT_BINARIES=[], + COMPILATIONDB_USE_BINARY_ABSPATH=False, ) components_by_suffix = itertools.chain( diff --git a/scripts/ufbt/SConstruct b/scripts/ufbt/SConstruct index 784d66161..26b1046ee 100644 --- a/scripts/ufbt/SConstruct +++ b/scripts/ufbt/SConstruct @@ -102,6 +102,7 @@ env = core_env.Clone( core_env.subst("$SDK_DEFINITION"), load_version_only=True ).version, APPCHECK_COMSTR="\tAPPCHK\t${SOURCE}\n\t\tTarget: ${TARGET_HW}, API: ${UFBT_API_VERSION}", + COMPILATIONDB_USE_BINARY_ABSPATH=True, ) wrap_tempfile(env, "LINKCOM") From 0d4ead8fbd836142da52b5f0c0c0cf76f250204b Mon Sep 17 00:00:00 2001 From: Filipe Paz Rodrigues Date: Sat, 1 Jun 2024 11:45:27 -0500 Subject: [PATCH 3/3] Add initial ISO7816 support (#3681) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 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: あく --- applications/debug/ccid_test/ccid_test_app.c | 127 +++++++++++++----- applications/debug/ccid_test/iso7816_atr.h | 9 ++ .../debug/ccid_test/iso7816_callbacks.c | 76 +++++++++++ .../debug/ccid_test/iso7816_callbacks.h | 28 ++++ .../debug/ccid_test/iso7816_t0_apdu.c | 43 +++--- .../debug/ccid_test/iso7816_t0_apdu.h | 10 +- targets/f18/api_symbols.csv | 4 +- targets/f7/api_symbols.csv | 4 +- targets/f7/furi_hal/furi_hal_usb_ccid.c | 10 +- targets/furi_hal_include/furi_hal_usb_ccid.h | 10 +- 10 files changed, 253 insertions(+), 68 deletions(-) create mode 100644 applications/debug/ccid_test/iso7816_atr.h create mode 100644 applications/debug/ccid_test/iso7816_callbacks.c create mode 100644 applications/debug/ccid_test/iso7816_callbacks.h diff --git a/applications/debug/ccid_test/ccid_test_app.c b/applications/debug/ccid_test/ccid_test_app.c index 50b356696..be7f7f9e6 100644 --- a/applications/debug/ccid_test/ccid_test_app.c +++ b/applications/debug/ccid_test/ccid_test_app.c @@ -6,8 +6,9 @@ #include #include #include - +#include "iso7816_callbacks.h" #include "iso7816_t0_apdu.h" +#include "iso7816_atr.h" typedef enum { EventTypeInput, @@ -33,38 +34,6 @@ typedef enum { CcidTestSubmenuIndexInsertSmartcardReader } 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) { UNUSED(ctx); canvas_clear(canvas); @@ -127,6 +96,86 @@ void ccid_test_app_free(CcidTestApp* 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) { UNUSED(p); @@ -135,14 +184,16 @@ int32_t ccid_test_app(void* p) { //setup CCID USB // On linux: set VID PID using: /usr/lib/pcsc/drivers/ifd-ccid.bundle/Contents/Info.plist - app->ccid_cfg.vid = 0x1234; - app->ccid_cfg.pid = 0x5678; + app->ccid_cfg.vid = 0x076B; + app->ccid_cfg.pid = 0x3A21; FuriHalUsbInterface* usb_mode_prev = furi_hal_usb_get_config(); 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); + iso7816_set_callbacks((Iso7816Callbacks*)&iso87816_cb); + //handle button events CcidTestAppEvent event; while(1) { @@ -161,7 +212,9 @@ int32_t ccid_test_app(void* p) { //tear down USB 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 ccid_test_app_free(app); diff --git a/applications/debug/ccid_test/iso7816_atr.h b/applications/debug/ccid_test/iso7816_atr.h new file mode 100644 index 000000000..050457f8c --- /dev/null +++ b/applications/debug/ccid_test/iso7816_atr.h @@ -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_ diff --git a/applications/debug/ccid_test/iso7816_callbacks.c b/applications/debug/ccid_test/iso7816_callbacks.c new file mode 100644 index 000000000..1a66fa775 --- /dev/null +++ b/applications/debug/ccid_test/iso7816_callbacks.c @@ -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 +#include +#include + +#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); +} diff --git a/applications/debug/ccid_test/iso7816_callbacks.h b/applications/debug/ccid_test/iso7816_callbacks.h new file mode 100644 index 000000000..3d337d23a --- /dev/null +++ b/applications/debug/ccid_test/iso7816_callbacks.h @@ -0,0 +1,28 @@ +#ifndef _ISO7816_CALLBACKS_H_ +#define _ISO7816_CALLBACKS_H_ + +#include +#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_ \ No newline at end of file diff --git a/applications/debug/ccid_test/iso7816_t0_apdu.c b/applications/debug/ccid_test/iso7816_t0_apdu.c index 7c690a694..5fb695af1 100644 --- a/applications/debug/ccid_test/iso7816_t0_apdu.c +++ b/applications/debug/ccid_test/iso7816_t0_apdu.c @@ -4,22 +4,14 @@ #include #include "iso7816_t0_apdu.h" -void iso7816_answer_to_reset(uint8_t* dataBuffer, uint32_t* atrlen) { - //minimum valid ATR: https://smartcard-atr.apdu.fr/parse?ATR=3B+00 - 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)); -} - +//reads dataBuffer with dataLen size, translate it into a ISO7816_Command_APDU type +//extra data will be pointed to commandDataBuffer void iso7816_read_command_apdu( struct ISO7816_Command_APDU* command, const uint8_t* dataBuffer, uint32_t dataLen) { UNUSED(dataLen); + command->CLA = dataBuffer[0]; command->INS = dataBuffer[1]; command->P1 = dataBuffer[2]; @@ -27,11 +19,30 @@ void iso7816_read_command_apdu( command->Lc = dataBuffer[4]; } +//data buffer countains the whole APU response (response + trailer (SW1+SW2)) void iso7816_write_response_apdu( const struct ISO7816_Response_APDU* response, - uint8_t* dataBuffer, - uint32_t* dataLen) { - dataBuffer[0] = response->SW1; - dataBuffer[1] = response->SW2; - *dataLen = 2; + uint8_t* readerToPcDataBlock, + uint32_t* readerToPcDataBlockLen, + uint8_t* responseDataBuffer, + uint32_t responseDataLen) { + 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; } \ No newline at end of file diff --git a/applications/debug/ccid_test/iso7816_t0_apdu.h b/applications/debug/ccid_test/iso7816_t0_apdu.h index 5ca13eb60..48a189440 100644 --- a/applications/debug/ccid_test/iso7816_t0_apdu.h +++ b/applications/debug/ccid_test/iso7816_t0_apdu.h @@ -2,6 +2,8 @@ #define _ISO7816_T0_APDU_H_ #include +#include "iso7816_atr.h" +#include "core/common_defines.h" struct ISO7816_Command_APDU { //header @@ -20,13 +22,15 @@ struct ISO7816_Response_APDU { uint8_t SW2; } 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( struct ISO7816_Command_APDU* command, const uint8_t* dataBuffer, uint32_t dataLen); void iso7816_write_response_apdu( const struct ISO7816_Response_APDU* response, - uint8_t* dataBuffer, - uint32_t* dataLen); + uint8_t* readerToPcDataBlock, + uint32_t* readerToPcDataBlockLen, + uint8_t* responseDataBuffer, + uint32_t responseDataLen); #endif //_ISO7816_T0_APDU_H_ diff --git a/targets/f18/api_symbols.csv b/targets/f18/api_symbols.csv index 04ceb928c..7eda31675 100644 --- a/targets/f18/api_symbols.csv +++ b/targets/f18/api_symbols.csv @@ -1,5 +1,5 @@ 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_keys_storage.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_ccid_ccid_insert_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_port_settings,usb_cdc_line_coding*,uint8_t Function,+,furi_hal_cdc_receive,int32_t,"uint8_t, uint8_t*, uint16_t" diff --git a/targets/f7/api_symbols.csv b/targets/f7/api_symbols.csv index e7a97aff9..e2e94d063 100644 --- a/targets/f7/api_symbols.csv +++ b/targets/f7/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,62.3,, +Version,+,63.0,, 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_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_ccid_ccid_insert_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_port_settings,usb_cdc_line_coding*,uint8_t Function,+,furi_hal_cdc_receive,int32_t,"uint8_t, uint8_t*, uint16_t" diff --git a/targets/f7/furi_hal/furi_hal_usb_ccid.c b/targets/f7/furi_hal/furi_hal_usb_ccid.c index d8b43fc6c..f7ab2365d 100644 --- a/targets/f7/furi_hal/furi_hal_usb_ccid.c +++ b/targets/f7/furi_hal/furi_hal_usb_ccid.c @@ -184,6 +184,7 @@ static usbd_device* usb_dev; static bool connected = false; static bool smartcard_inserted = true; static CcidCallbacks* callbacks[CCID_TOTAL_SLOTS] = {NULL}; +static void* cb_ctx[CCID_TOTAL_SLOTS]; static void* ccid_set_string_descr(char* str) { furi_check(str); @@ -330,7 +331,9 @@ void CALLBACK_CCID_IccPowerOn( if(smartcard_inserted) { if(callbacks[CCID_SLOT_INDEX] != NULL) { 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 | CCID_ICCSTATUS_PRESENTANDACTIVE; } else { @@ -364,7 +367,7 @@ void CALLBACK_CCID_XfrBlock( receivedXfrBlock->dwLength, responseDataBlock->abData, &responseDataBlock->dwLength, - NULL); + cb_ctx[CCID_SLOT_INDEX]); responseDataBlock->bStatus = CCID_COMMANDSTATUS_PROCESSEDWITHOUTERROR | CCID_ICCSTATUS_PRESENTANDACTIVE; } else { @@ -389,8 +392,9 @@ void furi_hal_ccid_ccid_remove_smartcard(void) { 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; + cb_ctx[CCID_SLOT_INDEX] = context; } static void ccid_rx_ep_callback(usbd_device* dev, uint8_t event, uint8_t ep) { diff --git a/targets/furi_hal_include/furi_hal_usb_ccid.h b/targets/furi_hal_include/furi_hal_usb_ccid.h index 500bafa3d..cbd0bf092 100644 --- a/targets/furi_hal_include/furi_hal_usb_ccid.h +++ b/targets/furi_hal_include/furi_hal_usb_ccid.h @@ -19,14 +19,14 @@ typedef struct { typedef struct { void (*icc_power_on_callback)(uint8_t* dataBlock, uint32_t* dataBlockLen, void* context); void (*xfr_datablock_callback)( - const uint8_t* dataBlock, - uint32_t dataBlockLen, - uint8_t* responseDataBlock, - uint32_t* responseDataBlockLen, + const uint8_t* pcToReaderDataBlock, + uint32_t pcToReaderDataBlockLen, + uint8_t* readerToPcDataBlock, + uint32_t* readerToPcDataBlockLen, void* context); } 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_remove_smartcard(void);