diff --git a/.clang-format b/.clang-format index 4b76f7fa4..ad3484ba0 100644 --- a/.clang-format +++ b/.clang-format @@ -3,22 +3,55 @@ Language: Cpp AccessModifierOffset: -4 AlignAfterOpenBracket: AlwaysBreak AlignArrayOfStructures: None -AlignConsecutiveMacros: None -AlignConsecutiveAssignments: None -AlignConsecutiveBitFields: None -AlignConsecutiveDeclarations: None +AlignConsecutiveAssignments: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + AlignFunctionPointers: false + PadOperators: true +AlignConsecutiveBitFields: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + AlignFunctionPointers: false + PadOperators: true +AlignConsecutiveDeclarations: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + AlignFunctionPointers: false + PadOperators: true +AlignConsecutiveMacros: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCompound: false + AlignFunctionPointers: false + PadOperators: true +AlignConsecutiveShortCaseStatements: + Enabled: false + AcrossEmptyLines: false + AcrossComments: false + AlignCaseColons: false AlignEscapedNewlines: Left AlignOperands: Align -AlignTrailingComments: false +AlignTrailingComments: + Kind: Never + OverEmptyLines: 0 AllowAllArgumentsOnNextLine: true AllowAllParametersOfDeclarationOnNextLine: false -AllowShortEnumsOnASingleLine: true +AllowBreakBeforeNoexceptSpecifier: Never AllowShortBlocksOnASingleLine: Never AllowShortCaseLabelsOnASingleLine: false +AllowShortCompoundRequirementOnASingleLine: true +AllowShortEnumsOnASingleLine: true AllowShortFunctionsOnASingleLine: None -AllowShortLambdasOnASingleLine: All AllowShortIfStatementsOnASingleLine: WithoutElse -AllowShortLoopsOnASingleLine: true +AllowShortLambdasOnASingleLine: All +AllowShortLoopsOnASingleLine: false AlwaysBreakAfterDefinitionReturnType: None AlwaysBreakAfterReturnType: None AlwaysBreakBeforeMultilineStrings: false @@ -27,17 +60,18 @@ AttributeMacros: - __capability BinPackArguments: false BinPackParameters: false +BitFieldColonSpacing: Both BraceWrapping: AfterCaseLabel: false AfterClass: false AfterControlStatement: Never AfterEnum: false + AfterExternBlock: false AfterFunction: false AfterNamespace: false AfterObjCDeclaration: false AfterStruct: false AfterUnion: false - AfterExternBlock: false BeforeCatch: false BeforeElse: false BeforeLambdaBody: false @@ -46,33 +80,29 @@ BraceWrapping: SplitEmptyFunction: true SplitEmptyRecord: true SplitEmptyNamespace: true -BreakBeforeBinaryOperators: None -BreakBeforeConceptDeclarations: true -BreakBeforeBraces: Attach -BreakBeforeInheritanceComma: false -BreakInheritanceList: BeforeColon -BreakBeforeTernaryOperators: false -BreakConstructorInitializersBeforeComma: false -BreakConstructorInitializers: BeforeComma +BreakAdjacentStringLiterals: true +BreakAfterAttributes: Leave BreakAfterJavaFieldAnnotations: false +BreakArrays: true +BreakBeforeBinaryOperators: None +BreakBeforeConceptDeclarations: Always +BreakBeforeBraces: Attach +BreakBeforeInlineASMColon: OnlyMultiline +BreakBeforeTernaryOperators: false +BreakConstructorInitializers: BeforeComma +BreakInheritanceList: BeforeColon BreakStringLiterals: false ColumnLimit: 99 CommentPragmas: '^ IWYU pragma:' -QualifierAlignment: Leave CompactNamespaces: false ConstructorInitializerIndentWidth: 4 ContinuationIndentWidth: 4 Cpp11BracedListStyle: true -DeriveLineEnding: true DerivePointerAlignment: false DisableFormat: false EmptyLineAfterAccessModifier: Never EmptyLineBeforeAccessModifier: LogicalBlock ExperimentalAutoDetectBinPacking: false -PackConstructorInitializers: BinPack -BasedOnStyle: '' -ConstructorInitializerAllOnOneLineOrOnePerLine: false -AllowAllConstructorInitializersOnNextLine: true FixNamespaceComments: false ForEachMacros: - foreach @@ -97,19 +127,30 @@ IncludeCategories: IncludeIsMainRegex: '(Test)?$' IncludeIsMainSourceRegex: '' IndentAccessModifiers: false -IndentCaseLabels: false IndentCaseBlocks: false +IndentCaseLabels: false +IndentExternBlock: AfterExternBlock IndentGotoLabels: true IndentPPDirectives: None -IndentExternBlock: AfterExternBlock -IndentRequires: false +IndentRequiresClause: false IndentWidth: 4 IndentWrappedFunctionNames: true +InsertBraces: false +InsertNewlineAtEOF: false InsertTrailingCommas: None +IntegerLiteralSeparator: + Binary: 0 + BinaryMinDigits: 0 + Decimal: 0 + DecimalMinDigits: 0 + Hex: 0 + HexMinDigits: 0 JavaScriptQuotes: Leave JavaScriptWrapImports: true KeepEmptyLinesAtTheStartOfBlocks: false +KeepEmptyLinesAtEOF: false LambdaBodyIndentation: Signature +LineEnding: DeriveLF MacroBlockBegin: '' MacroBlockEnd: '' MaxEmptyLinesToKeep: 1 @@ -119,34 +160,44 @@ ObjCBlockIndentWidth: 4 ObjCBreakBeforeNestedBlockParam: true ObjCSpaceAfterProperty: true ObjCSpaceBeforeProtocolList: true +PackConstructorInitializers: BinPack PenaltyBreakAssignment: 10 PenaltyBreakBeforeFirstCallParameter: 30 PenaltyBreakComment: 10 PenaltyBreakFirstLessLess: 0 PenaltyBreakOpenParenthesis: 0 +PenaltyBreakScopeResolution: 500 PenaltyBreakString: 10 PenaltyBreakTemplateDeclaration: 10 PenaltyExcessCharacter: 100 -PenaltyReturnTypeOnItsOwnLine: 60 PenaltyIndentedWhitespace: 0 +PenaltyReturnTypeOnItsOwnLine: 60 PointerAlignment: Left PPIndentWidth: -1 +QualifierAlignment: Leave ReferenceAlignment: Pointer ReflowComments: false RemoveBracesLLVM: false +RemoveParentheses: Leave +RemoveSemicolon: false +RequiresClausePosition: OwnLine +RequiresExpressionIndentation: OuterScope SeparateDefinitionBlocks: Leave ShortNamespaceLines: 1 +SkipMacroDefinitionBody: false SortIncludes: Never SortJavaStaticImport: Before -SortUsingDeclarations: false +SortUsingDeclarations: Never SpaceAfterCStyleCast: false SpaceAfterLogicalNot: false SpaceAfterTemplateKeyword: true +SpaceAroundPointerQualifiers: Default SpaceBeforeAssignmentOperators: true SpaceBeforeCaseColon: false SpaceBeforeCpp11BracedList: false SpaceBeforeCtorInitializerColon: true SpaceBeforeInheritanceColon: true +SpaceBeforeJsonColon: false SpaceBeforeParens: Never SpaceBeforeParensOptions: AfterControlStatements: false @@ -155,23 +206,26 @@ SpaceBeforeParensOptions: AfterFunctionDeclarationName: false AfterIfMacros: false AfterOverloadedOperator: false + AfterPlacementOperator: true + AfterRequiresInClause: false + AfterRequiresInExpression: false BeforeNonEmptyParentheses: false -SpaceAroundPointerQualifiers: Default SpaceBeforeRangeBasedForLoopColon: true +SpaceBeforeSquareBrackets: false SpaceInEmptyBlock: false -SpaceInEmptyParentheses: false SpacesBeforeTrailingComments: 1 SpacesInAngles: Never -SpacesInConditionalStatement: false SpacesInContainerLiterals: false -SpacesInCStyleCastParentheses: false SpacesInLineCommentPrefix: Minimum: 1 Maximum: -1 -SpacesInParentheses: false +SpacesInParens: Never +SpacesInParensOptions: + InCStyleCasts: false + InConditionalStatements: false + InEmptyParentheses: false + Other: false SpacesInSquareBrackets: false -SpaceBeforeSquareBrackets: false -BitFieldColonSpacing: Both Standard: c++03 StatementAttributeLikeMacros: - Q_EMIT @@ -179,8 +233,8 @@ StatementMacros: - Q_UNUSED - QT_REQUIRE_VERSION TabWidth: 4 -UseCRLF: false UseTab: Never +VerilogBreakBetweenInstancePorts: true WhitespaceSensitiveMacros: - STRINGIZE - PP_STRINGIZE diff --git a/applications/debug/bt_debug_app/views/bt_test.c b/applications/debug/bt_debug_app/views/bt_test.c index 792ebfd8f..c59c7f09a 100644 --- a/applications/debug/bt_debug_app/views/bt_test.c +++ b/applications/debug/bt_debug_app/views/bt_test.c @@ -384,8 +384,7 @@ BtTestParam* bt_test_param_add( void bt_test_set_rssi(BtTest* bt_test, float rssi) { furi_assert(bt_test); - with_view_model( - bt_test->view, BtTestModel * model, { model->rssi = rssi; }, true); + with_view_model(bt_test->view, BtTestModel * model, { model->rssi = rssi; }, true); } void bt_test_set_packets_tx(BtTest* bt_test, uint32_t packets_num) { diff --git a/applications/debug/ccid_test/ccid_test_app.c b/applications/debug/ccid_test/ccid_test_app.c index 6993901d2..be6f631f4 100644 --- a/applications/debug/ccid_test/ccid_test_app.c +++ b/applications/debug/ccid_test/ccid_test_app.c @@ -9,6 +9,7 @@ #include "iso7816_callbacks.h" #include "iso7816_t0_apdu.h" #include "iso7816_atr.h" +#include "iso7816_response.h" typedef enum { EventTypeInput, @@ -118,6 +119,76 @@ static const CcidCallbacks ccid_cb = { ccid_xfr_datablock_callback, }; +//Instruction 1: returns an OK response unconditionally +//APDU example: 0x01:0x01:0x00:0x00 +//response: SW1=0x90, SW2=0x00 +void handle_instruction_01(ISO7816_Response_APDU* responseAPDU) { + responseAPDU->DataLen = 0; + iso7816_set_response(responseAPDU, ISO7816_RESPONSE_OK); +} + +//Instruction 2: expect command with no body, replies wit with a body with two bytes +//APDU example: 0x01:0x02:0x00:0x00:0x02 +//response: 'bc' (0x62, 0x63) SW1=0x90, SW2=0x00 +void handle_instruction_02( + uint8_t p1, + uint8_t p2, + uint8_t lc, + uint8_t le, + ISO7816_Response_APDU* responseAPDU) { + if(p1 == 0 && p2 == 0 && lc == 0 && le >= 2) { + responseAPDU->Data[0] = 0x62; + responseAPDU->Data[1] = 0x63; + + responseAPDU->DataLen = 2; + + iso7816_set_response(responseAPDU, ISO7816_RESPONSE_OK); + } else if(p1 != 0 || p2 != 0) { + iso7816_set_response(responseAPDU, ISO7816_RESPONSE_WRONG_PARAMETERS_P1_P2); + } else { + iso7816_set_response(responseAPDU, ISO7816_RESPONSE_WRONG_LENGTH); + } +} + +//Instruction 3: sends a command with a body with two bytes, receives a response with no bytes +//APDU example: 0x01:0x03:0x00:0x00:0x02:CA:FE +//response SW1=0x90, SW2=0x00 +void handle_instruction_03(uint8_t p1, uint8_t p2, uint8_t lc, ISO7816_Response_APDU* responseAPDU) { + if(p1 == 0 && p2 == 0 && lc == 2) { + responseAPDU->DataLen = 0; + iso7816_set_response(responseAPDU, ISO7816_RESPONSE_OK); + } else if(p1 != 0 || p2 != 0) { + iso7816_set_response(responseAPDU, ISO7816_RESPONSE_WRONG_PARAMETERS_P1_P2); + } else { + iso7816_set_response(responseAPDU, ISO7816_RESPONSE_WRONG_LENGTH); + } +} + +//instruction 4: sends a command with a body with 'n' bytes, receives a response with 'n' bytes +//APDU example: 0x01:0x04:0x00:0x00:0x04:0x01:0x02:0x03:0x04:0x04 +//receives (0x01, 0x02, 0x03, 0x04) SW1=0x90, SW2=0x00 +void handle_instruction_04( + uint8_t p1, + uint8_t p2, + uint8_t lc, + uint8_t le, + const uint8_t* commandApduDataBuffer, + ISO7816_Response_APDU* responseAPDU) { + if(p1 == 0 && p2 == 0 && lc > 0 && le > 0 && le >= lc) { + for(uint16_t i = 0; i < lc; i++) { + responseAPDU->Data[i] = commandApduDataBuffer[i]; + } + + responseAPDU->DataLen = lc; + + iso7816_set_response(responseAPDU, ISO7816_RESPONSE_OK); + } else if(p1 != 0 || p2 != 0) { + iso7816_set_response(responseAPDU, ISO7816_RESPONSE_WRONG_PARAMETERS_P1_P2); + } else { + iso7816_set_response(responseAPDU, ISO7816_RESPONSE_WRONG_LENGTH); + } +} + void iso7816_answer_to_reset(Iso7816Atr* atr) { //minimum valid ATR: https://smartcard-atr.apdu.fr/parse?ATR=3B+00 atr->TS = 0x3B; @@ -125,48 +196,38 @@ void iso7816_answer_to_reset(Iso7816Atr* atr) { } 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) { + const ISO7816_Command_APDU* commandAPDU, + ISO7816_Response_APDU* responseAPDU) { //example 1: sends a command with no body, receives a response with no body - //sends APDU 0x01:0x02:0x00:0x00 + //sends APDU 0x01:0x01: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; + if(commandAPDU->CLA == 0x01) { + switch(commandAPDU->INS) { + case 0x01: + handle_instruction_01(responseAPDU); + break; + case 0x02: + handle_instruction_02( + commandAPDU->P1, commandAPDU->P2, commandAPDU->Lc, commandAPDU->Le, responseAPDU); + break; + case 0x03: + handle_instruction_03(commandAPDU->P1, commandAPDU->P2, commandAPDU->Lc, responseAPDU); + break; + case 0x04: + handle_instruction_04( + commandAPDU->P1, + commandAPDU->P2, + commandAPDU->Lc, + commandAPDU->Le, + commandAPDU->Data, + responseAPDU); + break; + default: + iso7816_set_response(responseAPDU, ISO7816_RESPONSE_INSTRUCTION_NOT_SUPPORTED); + } } else { - responseAPDU->SW1 = 0x6A; - responseAPDU->SW2 = 0x00; + iso7816_set_response(responseAPDU, ISO7816_RESPONSE_CLASS_NOT_SUPPORTED); } } diff --git a/applications/debug/ccid_test/client/ccid_client.py b/applications/debug/ccid_test/client/ccid_client.py new file mode 100644 index 000000000..5f43deb87 --- /dev/null +++ b/applications/debug/ccid_test/client/ccid_client.py @@ -0,0 +1,116 @@ +# pylint: disable=missing-module-docstring, too-many-arguments, consider-using-f-string, missing-function-docstring +from smartcard.System import readers + + +def test_apdu(connection, test_name, apdu, expected_sw1, expected_sw2, expected_data): + print("Running test: [%s]" % test_name) + data, sw1, sw2 = connection.transmit(apdu) + + failed = [] + + if sw1 != expected_sw1: + failed.append("SW1: Expected %x, actual %x" % (expected_sw1, sw1)) + + if sw2 != expected_sw2: + failed.append("SW2: Expected %x, actual %x" % (expected_sw2, sw2)) + + if len(data) != len(expected_data): + failed.append( + "Data: Sizes differ: Expected %x, actual %x" + % (len(expected_data), len(data)) + ) + print(data) + elif len(data) > 0: + data_matches = True + for i, _ in enumerate(data): + if data[i] != expected_data[i]: + data_matches = False + + if not data_matches: + failed.append("Data: Expected %s, actual %s" % (expected_data, data)) + + if len(failed) > 0: + print("Test failed: ") + for failure in failed: + print("- %s" % failure) + else: + print("Test passed!") + + +def main(): + r = readers() + print("Found following smartcard readers: ") + + for i, sc in enumerate(r): + print("[%d] %s" % (i, sc)) + + print("Select the smartcard reader you want to run tests against:") + + reader_index = int(input()) + + if reader_index < len(r): + connection = r[reader_index].createConnection() + + connection.connect() + + test_apdu( + connection, + "INS 0x01: No Lc, no Data, No Le. Expect no data in return", + [0x01, 0x01, 0x00, 0x00], + 0x90, + 0x00, + [], + ) + + test_apdu( + connection, + "INS 0x02: No Lc, no Data, Le=2. Expect 2 byte data in return", + [0x01, 0x02, 0x00, 0x00, 0x02], + 0x90, + 0x00, + [0x62, 0x63], + ) + + test_apdu( + connection, + "INS 0x03: Lc=2, data=[0xCA, 0xFE], No Le. Expect no data in return", + [0x01, 0x03, 0x00, 0x00, 0x02, 0xCA, 0xFE], + 0x90, + 0x00, + [], + ) + + test_apdu( + connection, + "INS 0x04: Lc=2, data=[0xCA, 0xFE], Le=2. Expect 1 byte data in return", + [0x01, 0x04, 0x00, 0x00, 0x02, 0xCA, 0xFE, 0x02], + 0x90, + 0x00, + [0xCA, 0xFE], + ) + + small_apdu = list(range(0, 0x0F)) + + test_apdu( + connection, + "INS 0x04: Lc=0x0F, data=small_apdu, Le=0x0F. Expect 14 bytes data in return", + [0x01, 0x04, 0x00, 0x00, 0x0F] + small_apdu + [0x0F], + 0x90, + 0x00, + small_apdu, + ) + + max_apdu = list(range(0, 0x30)) + + test_apdu( + connection, + "INS 0x04: Lc=0x30, data=max_apdu, Le=0x30. Expect 0x30 bytes data in return", + [0x01, 0x04, 0x00, 0x00, 0x30] + max_apdu + [0x30], + 0x90, + 0x00, + max_apdu, + ) + + +if __name__ == "__main__": + main() diff --git a/applications/debug/ccid_test/client/requirements.txt b/applications/debug/ccid_test/client/requirements.txt new file mode 100644 index 000000000..fe0a8e539 --- /dev/null +++ b/applications/debug/ccid_test/client/requirements.txt @@ -0,0 +1,2 @@ +pyscard +# or sudo apt install python3-pyscard \ No newline at end of file diff --git a/applications/debug/ccid_test/iso7816_atr.h b/applications/debug/ccid_test/iso7816_atr.h index 050457f8c..215ec60ee 100644 --- a/applications/debug/ccid_test/iso7816_atr.h +++ b/applications/debug/ccid_test/iso7816_atr.h @@ -1,9 +1,6 @@ -#ifndef _ISO7816_ATR_H_ -#define _ISO7816_ATR_H_ +#pragma once 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 index 1a66fa775..6c1bb106a 100644 --- a/applications/debug/ccid_test/iso7816_callbacks.c +++ b/applications/debug/ccid_test/iso7816_callbacks.c @@ -1,17 +1,21 @@ // 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 +#include +#include +#include + #include "iso7816_t0_apdu.h" #include "iso7816_atr.h" #include "iso7816_callbacks.h" -#include -#include -#include - -#define ISO7816_RESPONSE_BUFFER_SIZE 255 +#include "iso7816_response.h" static Iso7816Callbacks* callbacks = NULL; +static uint8_t commandApduBuffer[sizeof(ISO7816_Command_APDU) + CCID_SHORT_APDU_SIZE]; +static uint8_t responseApduBuffer[sizeof(ISO7816_Response_APDU) + CCID_SHORT_APDU_SIZE]; + void iso7816_set_callbacks(Iso7816Callbacks* cb) { callbacks = cb; } @@ -36,41 +40,26 @@ void iso7816_xfr_datablock_callback( 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; + ISO7816_Response_APDU* responseAPDU = (ISO7816_Response_APDU*)&responseApduBuffer; if(callbacks != NULL) { - struct ISO7816_Command_APDU commandAPDU; + ISO7816_Command_APDU* commandAPDU = (ISO7816_Command_APDU*)&commandApduBuffer; - const uint8_t* commandApduDataBuffer = NULL; - uint8_t commandApduDataBufferLen = 0; + uint8_t result = + iso7816_read_command_apdu(commandAPDU, pcToReaderDataBlock, pcToReaderDataBlockLen); - iso7816_read_command_apdu(&commandAPDU, pcToReaderDataBlock, pcToReaderDataBlockLen); + if(result == ISO7816_READ_COMMAND_APDU_OK) { + callbacks->iso7816_process_command(commandAPDU, responseAPDU); - if(commandAPDU.Lc > 0) { - commandApduDataBufferLen = commandAPDU.Lc; - commandApduDataBuffer = &pcToReaderDataBlock[5]; + furi_assert(responseAPDU->DataLen < CCID_SHORT_APDU_SIZE); + } else if(result == ISO7816_READ_COMMAND_APDU_ERROR_WRONG_LE) { + iso7816_set_response(responseAPDU, ISO7816_RESPONSE_WRONG_LE); + } else if(result == ISO7816_READ_COMMAND_APDU_ERROR_WRONG_LENGTH) { + iso7816_set_response(responseAPDU, ISO7816_RESPONSE_WRONG_LENGTH); } - - callbacks->iso7816_process_command( - &commandAPDU, - &responseAPDU, - commandApduDataBuffer, - commandApduDataBufferLen, - responseApduDataBuffer, - &responseApduDataBufferLen); - } else { - //class not supported - responseAPDU.SW1 = 0x6E; - responseAPDU.SW2 = 0x00; + iso7816_set_response(responseAPDU, ISO7816_RESPONSE_INTERNAL_EXCEPTION); } - iso7816_write_response_apdu( - &responseAPDU, - readerToPcDataBlock, - readerToPcDataBlockLen, - responseApduDataBuffer, - responseApduDataBufferLen); + iso7816_write_response_apdu(responseAPDU, readerToPcDataBlock, readerToPcDataBlockLen); } diff --git a/applications/debug/ccid_test/iso7816_callbacks.h b/applications/debug/ccid_test/iso7816_callbacks.h index 3d337d23a..7288b021a 100644 --- a/applications/debug/ccid_test/iso7816_callbacks.h +++ b/applications/debug/ccid_test/iso7816_callbacks.h @@ -1,5 +1,4 @@ -#ifndef _ISO7816_CALLBACKS_H_ -#define _ISO7816_CALLBACKS_H_ +#pragma once #include #include "iso7816_atr.h" @@ -8,12 +7,8 @@ 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); + const ISO7816_Command_APDU* command, + ISO7816_Response_APDU* response); } Iso7816Callbacks; void iso7816_set_callbacks(Iso7816Callbacks* cb); @@ -23,6 +18,4 @@ 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 + uint32_t* responseDataBlockLen); \ No newline at end of file diff --git a/applications/debug/ccid_test/iso7816_response.c b/applications/debug/ccid_test/iso7816_response.c new file mode 100644 index 000000000..3a65486b6 --- /dev/null +++ b/applications/debug/ccid_test/iso7816_response.c @@ -0,0 +1,8 @@ +#include +#include "iso7816_t0_apdu.h" +#include "iso7816_response.h" + +void iso7816_set_response(ISO7816_Response_APDU* responseAPDU, uint16_t responseCode) { + responseAPDU->SW1 = (responseCode >> (8 * 1)) & 0xff; + responseAPDU->SW2 = (responseCode >> (8 * 0)) & 0xff; +} \ No newline at end of file diff --git a/applications/debug/ccid_test/iso7816_response.h b/applications/debug/ccid_test/iso7816_response.h new file mode 100644 index 000000000..7c2e74257 --- /dev/null +++ b/applications/debug/ccid_test/iso7816_response.h @@ -0,0 +1,12 @@ +#pragma once + +#define ISO7816_RESPONSE_OK 0x9000 + +#define ISO7816_RESPONSE_WRONG_LENGTH 0x6700 +#define ISO7816_RESPONSE_WRONG_PARAMETERS_P1_P2 0x6A00 +#define ISO7816_RESPONSE_WRONG_LE 0x6C00 +#define ISO7816_RESPONSE_INSTRUCTION_NOT_SUPPORTED 0x6D00 +#define ISO7816_RESPONSE_CLASS_NOT_SUPPORTED 0x6E00 +#define ISO7816_RESPONSE_INTERNAL_EXCEPTION 0x6F00 + +void iso7816_set_response(ISO7816_Response_APDU* responseAPDU, uint16_t responseCode); \ 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 5fb695af1..916983229 100644 --- a/applications/debug/ccid_test/iso7816_t0_apdu.c +++ b/applications/debug/ccid_test/iso7816_t0_apdu.c @@ -2,37 +2,73 @@ #include #include #include +#include #include "iso7816_t0_apdu.h" //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, +uint8_t iso7816_read_command_apdu( + 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]; command->P2 = dataBuffer[3]; - command->Lc = dataBuffer[4]; + + if(dataLen == 4) { + command->Lc = 0; + command->Le = 0; + command->LePresent = false; + + return ISO7816_READ_COMMAND_APDU_OK; + } else if(dataLen == 5) { + //short le + + command->Lc = 0; + command->Le = dataBuffer[4]; + command->LePresent = true; + + return ISO7816_READ_COMMAND_APDU_OK; + } else if(dataLen > 5 && dataBuffer[4] != 0x00) { + //short lc + + command->Lc = dataBuffer[4]; + if(command->Lc > 0 && command->Lc < CCID_SHORT_APDU_SIZE) { //-V560 + memcpy(command->Data, &dataBuffer[5], command->Lc); + + //does it have a short le too? + if(dataLen == (uint32_t)(command->Lc + 5)) { + command->Le = 0; + command->LePresent = false; + return ISO7816_READ_COMMAND_APDU_OK; + } else if(dataLen == (uint32_t)(command->Lc + 6)) { + command->Le = dataBuffer[dataLen - 1]; + command->LePresent = true; + + return ISO7816_READ_COMMAND_APDU_OK; + } else { + return ISO7816_READ_COMMAND_APDU_ERROR_WRONG_LENGTH; + } + } else { + return ISO7816_READ_COMMAND_APDU_ERROR_WRONG_LENGTH; + } + } else { + return ISO7816_READ_COMMAND_APDU_ERROR_WRONG_LENGTH; + } } -//data buffer countains the whole APU response (response + trailer (SW1+SW2)) +//data buffer contains the whole APU response (response + trailer (SW1+SW2)) void iso7816_write_response_apdu( - const struct ISO7816_Response_APDU* response, + const ISO7816_Response_APDU* response, uint8_t* readerToPcDataBlock, - uint32_t* readerToPcDataBlockLen, - uint8_t* responseDataBuffer, - uint32_t responseDataLen) { + uint32_t* readerToPcDataBlockLen) { uint32_t responseDataBufferIndex = 0; //response body - if(responseDataLen > 0) { - while(responseDataBufferIndex < responseDataLen) { - readerToPcDataBlock[responseDataBufferIndex] = - responseDataBuffer[responseDataBufferIndex]; + if(response->DataLen > 0) { + while(responseDataBufferIndex < response->DataLen) { + readerToPcDataBlock[responseDataBufferIndex] = response->Data[responseDataBufferIndex]; responseDataBufferIndex++; } } diff --git a/applications/debug/ccid_test/iso7816_t0_apdu.h b/applications/debug/ccid_test/iso7816_t0_apdu.h index 48a189440..3b3450909 100644 --- a/applications/debug/ccid_test/iso7816_t0_apdu.h +++ b/applications/debug/ccid_test/iso7816_t0_apdu.h @@ -1,11 +1,14 @@ -#ifndef _ISO7816_T0_APDU_H_ -#define _ISO7816_T0_APDU_H_ +#pragma once #include #include "iso7816_atr.h" #include "core/common_defines.h" -struct ISO7816_Command_APDU { +#define ISO7816_READ_COMMAND_APDU_OK 0 +#define ISO7816_READ_COMMAND_APDU_ERROR_WRONG_LE 1 +#define ISO7816_READ_COMMAND_APDU_ERROR_WRONG_LENGTH 2 + +typedef struct { //header uint8_t CLA; uint8_t INS; @@ -13,24 +16,27 @@ struct ISO7816_Command_APDU { uint8_t P2; //body - uint8_t Lc; - uint8_t Le; -} FURI_PACKED; + uint16_t Lc; //data length + uint16_t Le; //maximum response data length expected by client -struct ISO7816_Response_APDU { + //Le can have value of 0x00, which actually meand 0x100 = 256 + bool LePresent; + uint8_t Data[0]; +} FURI_PACKED ISO7816_Command_APDU; + +typedef struct { uint8_t SW1; uint8_t SW2; -} FURI_PACKED; + uint16_t DataLen; + uint8_t Data[0]; +} FURI_PACKED ISO7816_Response_APDU; void iso7816_answer_to_reset(Iso7816Atr* atr); -void iso7816_read_command_apdu( - struct ISO7816_Command_APDU* command, - const uint8_t* dataBuffer, - uint32_t dataLen); +uint8_t iso7816_read_command_apdu( + ISO7816_Command_APDU* command, + const uint8_t* pcToReaderDataBlock, + uint32_t pcToReaderDataBlockLen); void iso7816_write_response_apdu( - const struct ISO7816_Response_APDU* response, + const ISO7816_Response_APDU* response, uint8_t* readerToPcDataBlock, - uint32_t* readerToPcDataBlockLen, - uint8_t* responseDataBuffer, - uint32_t responseDataLen); -#endif //_ISO7816_T0_APDU_H_ + uint32_t* readerToPcDataBlockLen); diff --git a/applications/debug/display_test/view_display_test.c b/applications/debug/display_test/view_display_test.c index d4fe433ef..31003ae0b 100644 --- a/applications/debug/display_test/view_display_test.c +++ b/applications/debug/display_test/view_display_test.c @@ -150,8 +150,7 @@ static void view_display_test_exit(void* context) { static void view_display_test_timer_callback(void* context) { ViewDisplayTest* instance = context; - with_view_model( - instance->view, ViewDisplayTestModel * model, { model->counter++; }, true); + with_view_model(instance->view, ViewDisplayTestModel * model, { model->counter++; }, true); } ViewDisplayTest* view_display_test_alloc(void) { diff --git a/applications/debug/lfrfid_debug/views/lfrfid_debug_view_tune.c b/applications/debug/lfrfid_debug/views/lfrfid_debug_view_tune.c index ddca372e3..7b28b66bf 100644 --- a/applications/debug/lfrfid_debug/views/lfrfid_debug_view_tune.c +++ b/applications/debug/lfrfid_debug/views/lfrfid_debug_view_tune.c @@ -223,16 +223,14 @@ bool lfrfid_debug_view_tune_is_dirty(LfRfidTuneView* tune_view) { uint32_t lfrfid_debug_view_tune_get_arr(LfRfidTuneView* tune_view) { uint32_t result = false; - with_view_model( - tune_view->view, LfRfidTuneViewModel * model, { result = model->ARR; }, false); + with_view_model(tune_view->view, LfRfidTuneViewModel * model, { result = model->ARR; }, false); return result; } uint32_t lfrfid_debug_view_tune_get_ccr(LfRfidTuneView* tune_view) { uint32_t result = false; - with_view_model( - tune_view->view, LfRfidTuneViewModel * model, { result = model->CCR; }, false); + with_view_model(tune_view->view, LfRfidTuneViewModel * model, { result = model->CCR; }, false); return result; } diff --git a/applications/debug/uart_echo/uart_echo.c b/applications/debug/uart_echo/uart_echo.c index 9c65910a0..0b6ae0e0d 100644 --- a/applications/debug/uart_echo/uart_echo.c +++ b/applications/debug/uart_echo/uart_echo.c @@ -206,8 +206,7 @@ static int32_t uart_echo_worker(void* context) { } while(length > 0); notification_message(app->notification, &sequence_notification); - with_view_model( - app->view, UartDumpModel * model, { UNUSED(model); }, true); + with_view_model(app->view, UartDumpModel * model, { UNUSED(model); }, true); } if(events & WorkerEventRxIdle) { diff --git a/applications/debug/unit_tests/tests/furi_hal/furi_hal_tests.c b/applications/debug/unit_tests/tests/furi_hal/furi_hal_tests.c index 4b515206c..a2af1d1b9 100644 --- a/applications/debug/unit_tests/tests/furi_hal/furi_hal_tests.c +++ b/applications/debug/unit_tests/tests/furi_hal/furi_hal_tests.c @@ -74,7 +74,8 @@ MU_TEST(furi_hal_i2c_int_3b) { DATA_SIZE - 1, LP5562_I2C_TIMEOUT); mu_assert(ret, "4 rx failed"); - for(size_t i = 0; i < DATA_SIZE; i++) mu_assert(data_many[i] != 0, "4 invalid data_many"); + for(size_t i = 0; i < DATA_SIZE; i++) + mu_assert(data_many[i] != 0, "4 invalid data_many"); ret = furi_hal_i2c_tx( &furi_hal_i2c_handle_power, LP5562_ADDRESS, data_many, DATA_SIZE, LP5562_I2C_TIMEOUT); @@ -90,7 +91,8 @@ MU_TEST(furi_hal_i2c_int_3b) { DATA_SIZE - 1, LP5562_I2C_TIMEOUT); mu_assert(ret, "7 rx failed"); - for(size_t i = 0; i < DATA_SIZE; i++) mu_assert(data_many[i] != 0, "7 invalid data_many"); + for(size_t i = 0; i < DATA_SIZE; i++) + mu_assert(data_many[i] != 0, "7 invalid data_many"); } MU_TEST(furi_hal_i2c_int_1b_fail) { diff --git a/applications/debug/unit_tests/tests/lfrfid/lfrfid_protocols.c b/applications/debug/unit_tests/tests/lfrfid/lfrfid_protocols.c index 8bf7753c0..56ff64c09 100644 --- a/applications/debug/unit_tests/tests/lfrfid/lfrfid_protocols.c +++ b/applications/debug/unit_tests/tests/lfrfid/lfrfid_protocols.c @@ -6,8 +6,7 @@ #define LF_RFID_READ_TIMING_MULTIPLIER 8 -#define EM_TEST_DATA \ - { 0x58, 0x00, 0x85, 0x64, 0x02 } +#define EM_TEST_DATA {0x58, 0x00, 0x85, 0x64, 0x02} #define EM_TEST_DATA_SIZE 5 #define EM_TEST_EMULATION_TIMINGS_COUNT (64 * 2) @@ -21,8 +20,7 @@ const int8_t em_test_timings[EM_TEST_EMULATION_TIMINGS_COUNT] = { -32, 32, 32, -32, -32, 32, -32, 32, -32, 32, -32, 32, -32, 32, }; -#define HID10301_TEST_DATA \ - { 0x8D, 0x48, 0xA8 } +#define HID10301_TEST_DATA {0x8D, 0x48, 0xA8} #define HID10301_TEST_DATA_SIZE 3 #define HID10301_TEST_EMULATION_TIMINGS_COUNT (541 * 2) @@ -71,8 +69,7 @@ const int8_t hid10301_test_timings[HID10301_TEST_EMULATION_TIMINGS_COUNT] = { 5, -5, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, }; -#define IOPROX_XSF_TEST_DATA \ - { 0x65, 0x01, 0x05, 0x39 } +#define IOPROX_XSF_TEST_DATA {0x65, 0x01, 0x05, 0x39} #define IOPROX_XSF_TEST_DATA_SIZE 4 #define IOPROX_XSF_TEST_EMULATION_TIMINGS_COUNT (468 * 2) @@ -116,8 +113,7 @@ const int8_t ioprox_xsf_test_timings[IOPROX_XSF_TEST_EMULATION_TIMINGS_COUNT] = }; #define INDALA26_EMULATION_TIMINGS_COUNT (1024 * 2) -#define INDALA26_TEST_DATA \ - { 0x3B, 0x73, 0x64, 0xA8 } +#define INDALA26_TEST_DATA {0x3B, 0x73, 0x64, 0xA8} #define INDALA26_TEST_DATA_SIZE 4 const int8_t indala26_test_timings[INDALA26_EMULATION_TIMINGS_COUNT] = { @@ -209,8 +205,7 @@ const int8_t indala26_test_timings[INDALA26_EMULATION_TIMINGS_COUNT] = { -1, 1, -1, 1, -1, 1, -1, 1, }; -#define FDXB_TEST_DATA \ - { 0x44, 0x88, 0x23, 0xF2, 0x5A, 0x6F, 0x00, 0x01, 0x00, 0x00, 0x00 } +#define FDXB_TEST_DATA {0x44, 0x88, 0x23, 0xF2, 0x5A, 0x6F, 0x00, 0x01, 0x00, 0x00, 0x00} #define FDXB_TEST_DATA_SIZE 11 #define FDXB_TEST_EMULATION_TIMINGS_COUNT (206) diff --git a/applications/main/nfc/helpers/nfc_supported_cards.c b/applications/main/nfc/helpers/nfc_supported_cards.c index 04372e2ad..d2950b584 100644 --- a/applications/main/nfc/helpers/nfc_supported_cards.c +++ b/applications/main/nfc/helpers/nfc_supported_cards.c @@ -41,7 +41,6 @@ typedef enum { typedef struct { Storage* storage; File* directory; - FuriString* file_path; char file_name[256]; FlipperApplication* app; } NfcSupportedCardsLoadContext; @@ -86,7 +85,6 @@ static NfcSupportedCardsLoadContext* nfc_supported_cards_load_context_alloc(void instance->storage = furi_record_open(RECORD_STORAGE); instance->directory = storage_file_alloc(instance->storage); - instance->file_path = furi_string_alloc(); if(!storage_dir_open(instance->directory, NFC_SUPPORTED_CARDS_PLUGINS_PATH)) { FURI_LOG_D(TAG, "Failed to open directory: %s", NFC_SUPPORTED_CARDS_PLUGINS_PATH); @@ -100,8 +98,6 @@ static void nfc_supported_cards_load_context_free(NfcSupportedCardsLoadContext* flipper_application_free(instance->app); } - furi_string_free(instance->file_path); - storage_dir_close(instance->directory); storage_file_free(instance->directory); @@ -117,15 +113,13 @@ static const NfcSupportedCardsPlugin* nfc_supported_cards_get_plugin( furi_assert(name); const NfcSupportedCardsPlugin* plugin = NULL; + FuriString* plugin_path = furi_string_alloc_printf( + "%s/%s%s", NFC_SUPPORTED_CARDS_PLUGINS_PATH, name, NFC_SUPPORTED_CARDS_PLUGIN_SUFFIX); do { if(instance->app) flipper_application_free(instance->app); instance->app = flipper_application_alloc(instance->storage, api_interface); - // Reconstruct path - path_concat(NFC_SUPPORTED_CARDS_PLUGINS_PATH, name, instance->file_path); - furi_string_cat(instance->file_path, NFC_SUPPORTED_CARDS_PLUGIN_SUFFIX); - - if(flipper_application_preload(instance->app, furi_string_get_cstr(instance->file_path)) != + if(flipper_application_preload(instance->app, furi_string_get_cstr(plugin_path)) != FlipperApplicationPreloadStatusSuccess) break; if(!flipper_application_is_plugin(instance->app)) break; @@ -141,6 +135,7 @@ static const NfcSupportedCardsPlugin* nfc_supported_cards_get_plugin( plugin = descriptor->entry_point; } while(false); + furi_string_free(plugin_path); return plugin; } @@ -156,13 +151,19 @@ static const NfcSupportedCardsPlugin* nfc_supported_cards_get_next_plugin( instance->directory, NULL, instance->file_name, sizeof(instance->file_name))) break; - furi_string_set(instance->file_path, instance->file_name); - if(!furi_string_end_with_str(instance->file_path, NFC_SUPPORTED_CARDS_PLUGIN_SUFFIX)) - continue; + const size_t suffix_len = strlen(NFC_SUPPORTED_CARDS_PLUGIN_SUFFIX); + const size_t file_name_len = strlen(instance->file_name); + if(file_name_len <= suffix_len) break; - size_t trim_suffix = - furi_string_size(instance->file_path) - strlen(NFC_SUPPORTED_CARDS_PLUGIN_SUFFIX); - instance->file_name[trim_suffix] = '\0'; + size_t suffix_start_pos = file_name_len - suffix_len; + if(memcmp( + &instance->file_name[suffix_start_pos], + NFC_SUPPORTED_CARDS_PLUGIN_SUFFIX, + suffix_len) != 0) //-V1051 + break; + + // Trim suffix from file_name to save memory. The suffix will be concatenated on plugin load. + instance->file_name[suffix_start_pos] = '\0'; plugin = nfc_supported_cards_get_plugin(instance, instance->file_name, api_interface); } while(plugin == NULL); //-V654 diff --git a/applications/main/u2f/views/u2f_view.c b/applications/main/u2f/views/u2f_view.c index bdbe8bcec..a110b3f4f 100644 --- a/applications/main/u2f/views/u2f_view.c +++ b/applications/main/u2f/views/u2f_view.c @@ -97,6 +97,5 @@ void u2f_view_set_ok_callback(U2fView* u2f, U2fOkCallback callback, void* contex } void u2f_view_set_state(U2fView* u2f, U2fViewMsg msg) { - with_view_model( - u2f->view, U2fModel * model, { model->display_msg = msg; }, true); + with_view_model(u2f->view, U2fModel * model, { model->display_msg = msg; }, true); } diff --git a/applications/services/cli/cli_commands.c b/applications/services/cli/cli_commands.c index 1e72647cf..797b1a8d7 100644 --- a/applications/services/cli/cli_commands.c +++ b/applications/services/cli/cli_commands.c @@ -65,7 +65,8 @@ void cli_command_help(Cli* cli, FuriString* args, void* context) { CliCommandTree_it(it_left, cli->commands); CliCommandTree_it_t it_right; CliCommandTree_it(it_right, cli->commands); - for(size_t i = 0; i < commands_count_mid; i++) CliCommandTree_next(it_right); + for(size_t i = 0; i < commands_count_mid; i++) + CliCommandTree_next(it_right); // Iterate throw tree for(size_t i = 0; i < commands_count_mid; i++) { @@ -408,8 +409,9 @@ static void cli_command_top(Cli* cli, FuriString* args, void* context) { uint32_t uptime = tick / furi_kernel_get_tick_frequency(); printf( - "Threads: %zu, Uptime: %luh%lum%lus\r\n", + "Threads: %zu, ISR Time: %0.2f%%, Uptime: %luh%lum%lus\r\n", furi_thread_list_size(thread_list), + (double)furi_thread_list_get_isr_time(thread_list), uptime / 60 / 60, uptime / 60 % 60, uptime % 60); diff --git a/applications/services/gui/modules/button_menu.c b/applications/services/gui/modules/button_menu.c index ed76bd2b3..df3e4ca4a 100644 --- a/applications/services/gui/modules/button_menu.c +++ b/applications/services/gui/modules/button_menu.c @@ -321,8 +321,7 @@ void button_menu_reset(ButtonMenu* button_menu) { void button_menu_set_header(ButtonMenu* button_menu, const char* header) { furi_check(button_menu); - with_view_model( - button_menu->view, ButtonMenuModel * model, { model->header = header; }, true); + with_view_model(button_menu->view, ButtonMenuModel * model, { model->header = header; }, true); } ButtonMenuItem* button_menu_add_item( diff --git a/applications/services/gui/modules/byte_input.c b/applications/services/gui/modules/byte_input.c index 4c3da820b..1da36b2dc 100644 --- a/applications/services/gui/modules/byte_input.c +++ b/applications/services/gui/modules/byte_input.c @@ -868,6 +868,5 @@ void byte_input_set_result_callback( void byte_input_set_header_text(ByteInput* byte_input, const char* text) { furi_check(byte_input); - with_view_model( - byte_input->view, ByteInputModel * model, { model->header = text; }, true); + with_view_model(byte_input->view, ByteInputModel * model, { model->header = text; }, true); } diff --git a/applications/services/gui/modules/dialog_ex.c b/applications/services/gui/modules/dialog_ex.c index 5fd42be6c..7171f6892 100644 --- a/applications/services/gui/modules/dialog_ex.c +++ b/applications/services/gui/modules/dialog_ex.c @@ -257,20 +257,17 @@ void dialog_ex_set_icon(DialogEx* dialog_ex, uint8_t x, uint8_t y, const Icon* i void dialog_ex_set_left_button_text(DialogEx* dialog_ex, const char* text) { furi_check(dialog_ex); - with_view_model( - dialog_ex->view, DialogExModel * model, { model->left_text = text; }, true); + with_view_model(dialog_ex->view, DialogExModel * model, { model->left_text = text; }, true); } void dialog_ex_set_center_button_text(DialogEx* dialog_ex, const char* text) { furi_check(dialog_ex); - with_view_model( - dialog_ex->view, DialogExModel * model, { model->center_text = text; }, true); + with_view_model(dialog_ex->view, DialogExModel * model, { model->center_text = text; }, true); } void dialog_ex_set_right_button_text(DialogEx* dialog_ex, const char* text) { furi_check(dialog_ex); - with_view_model( - dialog_ex->view, DialogExModel * model, { model->right_text = text; }, true); + with_view_model(dialog_ex->view, DialogExModel * model, { model->right_text = text; }, true); } void dialog_ex_reset(DialogEx* dialog_ex) { diff --git a/applications/services/gui/modules/file_browser.c b/applications/services/gui/modules/file_browser.c index c4a0a1b52..77e1722ec 100644 --- a/applications/services/gui/modules/file_browser.c +++ b/applications/services/gui/modules/file_browser.c @@ -174,15 +174,13 @@ static void browser_long_load_cb(void* context); static void file_browser_scroll_timer_callback(void* context) { furi_check(context); FileBrowser* browser = context; - with_view_model( - browser->view, FileBrowserModel * model, { model->scroll_counter++; }, true); + with_view_model(browser->view, FileBrowserModel * model, { model->scroll_counter++; }, true); } static void file_browser_view_enter_callback(void* context) { furi_check(context); FileBrowser* browser = context; - with_view_model( - browser->view, FileBrowserModel * model, { model->scroll_counter = 0; }, true); + with_view_model(browser->view, FileBrowserModel * model, { model->scroll_counter = 0; }, true); furi_timer_start(browser->scroll_timer, SCROLL_INTERVAL); } diff --git a/applications/services/gui/modules/menu.c b/applications/services/gui/modules/menu.c index 845295193..4c526bf92 100644 --- a/applications/services/gui/modules/menu.c +++ b/applications/services/gui/modules/menu.c @@ -149,8 +149,7 @@ void menu_free(Menu* menu) { furi_check(menu); menu_reset(menu); - with_view_model( - menu->view, MenuModel * model, { MenuItemArray_clear(model->items); }, false); + with_view_model(menu->view, MenuModel * model, { MenuItemArray_clear(model->items); }, false); view_free(menu->view); free(menu); diff --git a/applications/services/gui/modules/text_box.c b/applications/services/gui/modules/text_box.c index c3bff00d0..86455dd5c 100644 --- a/applications/services/gui/modules/text_box.c +++ b/applications/services/gui/modules/text_box.c @@ -355,13 +355,11 @@ void text_box_set_text(TextBox* text_box, const char* text) { void text_box_set_font(TextBox* text_box, TextBoxFont font) { furi_check(text_box); - with_view_model( - text_box->view, TextBoxModel * model, { model->font = font; }, true); + with_view_model(text_box->view, TextBoxModel * model, { model->font = font; }, true); } void text_box_set_focus(TextBox* text_box, TextBoxFocus focus) { furi_check(text_box); - with_view_model( - text_box->view, TextBoxModel * model, { model->focus = focus; }, true); + with_view_model(text_box->view, TextBoxModel * model, { model->focus = focus; }, true); } diff --git a/applications/services/gui/modules/text_input.c b/applications/services/gui/modules/text_input.c index c96510bcc..1ec9772fe 100644 --- a/applications/services/gui/modules/text_input.c +++ b/applications/services/gui/modules/text_input.c @@ -649,6 +649,5 @@ void* text_input_get_validator_callback_context(TextInput* text_input) { void text_input_set_header_text(TextInput* text_input, const char* text) { furi_check(text_input); - with_view_model( - text_input->view, TextInputModel * model, { model->header = text; }, true); + with_view_model(text_input->view, TextInputModel * model, { model->header = text; }, true); } diff --git a/applications/services/gui/view_holder.c b/applications/services/gui/view_holder.c index d9b382c17..ca2f9b04e 100644 --- a/applications/services/gui/view_holder.c +++ b/applications/services/gui/view_holder.c @@ -104,7 +104,8 @@ void view_holder_start(ViewHolder* view_holder) { } void view_holder_stop(ViewHolder* view_holder) { - while(view_holder->ongoing_input) furi_delay_tick(1); + while(view_holder->ongoing_input) + furi_delay_tick(1); view_port_enabled_set(view_holder->view_port, false); } diff --git a/applications/services/input/input.c b/applications/services/input/input.c index a7610688e..ec9384e76 100644 --- a/applications/services/input/input.c +++ b/applications/services/input/input.c @@ -137,7 +137,8 @@ int32_t input_srv(void* p) { } else { event.sequence_counter = pin_states[i].counter; furi_timer_stop(pin_states[i].press_timer); - while(furi_timer_is_running(pin_states[i].press_timer)) furi_delay_tick(1); + while(furi_timer_is_running(pin_states[i].press_timer)) + furi_delay_tick(1); if(pin_states[i].press_counter < INPUT_LONG_PRESS_COUNTS) { event.type = InputTypeShort; furi_pubsub_publish(event_pubsub, &event); diff --git a/applications/system/hid_app/views/hid_keyboard.c b/applications/system/hid_app/views/hid_keyboard.c index 9dd2ad655..429f223c1 100644 --- a/applications/system/hid_app/views/hid_keyboard.c +++ b/applications/system/hid_app/views/hid_keyboard.c @@ -400,8 +400,7 @@ HidKeyboard* hid_keyboard_alloc(Hid* bt_hid) { view_set_draw_callback(hid_keyboard->view, hid_keyboard_draw_callback); view_set_input_callback(hid_keyboard->view, hid_keyboard_input_callback); - with_view_model( - hid_keyboard->view, HidKeyboardModel * model, { model->y = 1; }, true); + with_view_model(hid_keyboard->view, HidKeyboardModel * model, { model->y = 1; }, true); return hid_keyboard; } diff --git a/applications/system/updater/util/update_task.c b/applications/system/updater/util/update_task.c index 17f1a2680..0eae0eaf5 100644 --- a/applications/system/updater/util/update_task.c +++ b/applications/system/updater/util/update_task.c @@ -237,7 +237,10 @@ typedef struct { } UpdateTaskStageGroupMap; #define STAGE_DEF(GROUP, WEIGHT) \ - { .group = (GROUP), .weight = (WEIGHT), } + { \ + .group = (GROUP), \ + .weight = (WEIGHT), \ + } static const UpdateTaskStageGroupMap update_task_stage_progress[] = { [UpdateTaskStageProgress] = STAGE_DEF(UpdateTaskStageGroupMisc, 0), diff --git a/furi/core/common_defines.h b/furi/core/common_defines.h index 0f6230c19..20883332b 100644 --- a/furi/core/common_defines.h +++ b/furi/core/common_defines.h @@ -29,8 +29,8 @@ extern "C" { #define FURI_PACKED __attribute__((packed)) #endif -#ifndef FURI_ALWAYS_STATIC_INLINE -#define FURI_ALWAYS_STATIC_INLINE __attribute__((always_inline)) static inline +#ifndef FURI_ALWAYS_INLINE +#define FURI_ALWAYS_INLINE __attribute__((always_inline)) inline #endif #ifndef FURI_IS_IRQ_MASKED diff --git a/furi/core/string.h b/furi/core/string.h index 324135e96..bcdf9336c 100644 --- a/furi/core/string.h +++ b/furi/core/string.h @@ -17,7 +17,7 @@ extern "C" { /** * @brief Furi string failure constant. */ -#define FURI_STRING_FAILURE ((size_t)-1) +#define FURI_STRING_FAILURE ((size_t) - 1) /** * @brief Furi string primitive. diff --git a/furi/core/thread_list.c b/furi/core/thread_list.c index 65ee11ad3..86759b66b 100644 --- a/furi/core/thread_list.c +++ b/furi/core/thread_list.c @@ -1,6 +1,8 @@ #include "thread_list.h" #include "check.h" +#include + #include #include @@ -23,6 +25,8 @@ struct FuriThreadList { FuriThreadListItemDict_t search; uint32_t runtime_previous; uint32_t runtime_current; + uint32_t isr_previous; + uint32_t isr_current; }; FuriThreadList* furi_thread_list_alloc(void) { @@ -85,7 +89,10 @@ void furi_thread_list_process(FuriThreadList* instance, uint32_t runtime, uint32 instance->runtime_previous = instance->runtime_current; instance->runtime_current = runtime; - uint32_t runtime_counter = instance->runtime_current - instance->runtime_previous; + instance->isr_previous = instance->isr_current; + instance->isr_current = furi_hal_interrupt_get_time_in_isr_total(); + + const uint32_t runtime_counter = instance->runtime_current - instance->runtime_previous; FuriThreadListItemArray_it_t it; FuriThreadListItemArray_it(it, instance->items); @@ -108,3 +115,10 @@ void furi_thread_list_process(FuriThreadList* instance, uint32_t runtime, uint32 } } } + +float furi_thread_list_get_isr_time(FuriThreadList* instance) { + const uint32_t runtime_counter = instance->runtime_current - instance->runtime_previous; + const uint32_t isr_counter = instance->isr_current - instance->isr_previous; + + return (float)isr_counter / (float)runtime_counter; +} \ No newline at end of file diff --git a/furi/core/thread_list.h b/furi/core/thread_list.h index bf15e4032..d01aa24a0 100644 --- a/furi/core/thread_list.h +++ b/furi/core/thread_list.h @@ -76,6 +76,14 @@ FuriThreadListItem* furi_thread_list_get_or_insert(FuriThreadList* instance, Fur */ void furi_thread_list_process(FuriThreadList* instance, uint32_t runtime, uint32_t tick); +/** Get percent of time spent in ISR + * + * @param instance The instance + * + * @return percent of time spent in ISR + */ +float furi_thread_list_get_isr_time(FuriThreadList* instance); + #ifdef __cplusplus } #endif diff --git a/lib/app-scened-template/generic_scene.hpp b/lib/app-scened-template/generic_scene.hpp index bcdf0b464..580346c8c 100644 --- a/lib/app-scened-template/generic_scene.hpp +++ b/lib/app-scened-template/generic_scene.hpp @@ -4,7 +4,7 @@ public: virtual void on_enter(TApp* app, bool need_restore) = 0; virtual bool on_event(TApp* app, typename TApp::Event* event) = 0; virtual void on_exit(TApp* app) = 0; - virtual ~GenericScene(){}; + virtual ~GenericScene() {}; private: }; diff --git a/lib/app-scened-template/scene_controller.hpp b/lib/app-scened-template/scene_controller.hpp index 052eca731..eb4310958 100644 --- a/lib/app-scened-template/scene_controller.hpp +++ b/lib/app-scened-template/scene_controller.hpp @@ -175,7 +175,8 @@ public: bool switch_to_previous_scene(uint8_t count = 1) { auto previous_scene_index = TApp::SceneType::Start; - for(uint8_t i = 0; i < count; i++) previous_scene_index = get_previous_scene_index(); + for(uint8_t i = 0; i < count; i++) + previous_scene_index = get_previous_scene_index(); if(previous_scene_index == TApp::SceneType::Exit) return true; @@ -198,7 +199,8 @@ public: * */ ~SceneController() { - for(auto& it : scenes) delete it.second; + for(auto& it : scenes) + delete it.second; } private: diff --git a/lib/app-scened-template/view_modules/generic_view_module.h b/lib/app-scened-template/view_modules/generic_view_module.h index 8b74ea3ad..f6c56a911 100644 --- a/lib/app-scened-template/view_modules/generic_view_module.h +++ b/lib/app-scened-template/view_modules/generic_view_module.h @@ -3,8 +3,8 @@ class GenericViewModule { public: - GenericViewModule(){}; - virtual ~GenericViewModule(){}; + GenericViewModule() {}; + virtual ~GenericViewModule() {}; virtual View* get_view() = 0; virtual void clean() = 0; }; diff --git a/lib/bit_lib/bit_lib.h b/lib/bit_lib/bit_lib.h index 7d23cf063..b8cc092c8 100644 --- a/lib/bit_lib/bit_lib.h +++ b/lib/bit_lib/bit_lib.h @@ -7,7 +7,7 @@ extern "C" { #endif -#define TOPBIT(X) (1 << ((X)-1)) +#define TOPBIT(X) (1 << ((X) - 1)) typedef enum { BitLibParityEven, diff --git a/lib/lfrfid/protocols/protocol_pac_stanley.c b/lib/lfrfid/protocols/protocol_pac_stanley.c index 4eabe3659..c59b0871d 100644 --- a/lib/lfrfid/protocols/protocol_pac_stanley.c +++ b/lib/lfrfid/protocols/protocol_pac_stanley.c @@ -137,7 +137,8 @@ bool protocol_pac_stanley_encoder_start(ProtocolPACStanley* protocol) { uint8_to_hex_chars(protocol->data, &idbytes[2], 8); // insert start and stop bits - for(size_t i = 0; i < 16; i++) protocol->encoded_data[i] = 0x40 >> ((i + 3) % 5 * 2); + for(size_t i = 0; i < 16; i++) + protocol->encoded_data[i] = 0x40 >> ((i + 3) % 5 * 2); protocol->encoded_data[0] = 0xFF; // mark + stop protocol->encoded_data[1] = 0x20; // start + reflect8(STX) diff --git a/lib/lfrfid/protocols/protocol_pyramid.c b/lib/lfrfid/protocols/protocol_pyramid.c index 8711fe13a..7143a3acc 100644 --- a/lib/lfrfid/protocols/protocol_pyramid.c +++ b/lib/lfrfid/protocols/protocol_pyramid.c @@ -126,7 +126,8 @@ bool protocol_pyramid_decoder_feed(ProtocolPyramid* protocol, bool level, uint32 bool protocol_pyramid_get_parity(const uint8_t* bits, uint8_t type, int length) { int x; - for(x = 0; length > 0; --length) x += bit_lib_get_bit(bits, length - 1); + for(x = 0; length > 0; --length) + x += bit_lib_get_bit(bits, length - 1); x %= 2; return x ^ type; } diff --git a/lib/nanopb b/lib/nanopb index afc499f9a..6cfe48d6f 160000 --- a/lib/nanopb +++ b/lib/nanopb @@ -1 +1 @@ -Subproject commit afc499f9a410fc9bbf6c9c48cdd8d8b199d49eb4 +Subproject commit 6cfe48d6f1593f8fa5c0f90437f5e6522587745e diff --git a/lib/nfc/helpers/crypto1.c b/lib/nfc/helpers/crypto1.c index 938d2765a..571c4ac31 100644 --- a/lib/nfc/helpers/crypto1.c +++ b/lib/nfc/helpers/crypto1.c @@ -84,7 +84,8 @@ uint32_t crypto1_word(Crypto1* crypto1, uint32_t in, int is_encrypted) { uint32_t prng_successor(uint32_t x, uint32_t n) { SWAPENDIAN(x); - while(n--) x = x >> 1 | (x >> 16 ^ x >> 18 ^ x >> 19 ^ x >> 21) << 31; + while(n--) + x = x >> 1 | (x >> 16 ^ x >> 18 ^ x >> 19 ^ x >> 21) << 31; return SWAPENDIAN(x); } diff --git a/lib/nfc/nfc_poller.c b/lib/nfc/nfc_poller.c index 114ff3695..2fe50b3fc 100644 --- a/lib/nfc/nfc_poller.c +++ b/lib/nfc/nfc_poller.c @@ -190,7 +190,8 @@ void nfc_poller_start_ex(NfcPoller* instance, NfcGenericCallbackEx callback, voi NfcProtocol parent_protocol = nfc_protocol_get_parent(instance->protocol); if(parent_protocol != NfcProtocolInvalid) { NfcPollerListElement* iter = instance->list.head; - while(iter->protocol != parent_protocol) iter = iter->child; + while(iter->protocol != parent_protocol) + iter = iter->child; iter->poller_api->set_callback(iter->poller, nfc_poller_start_ex_tail_callback, instance); } @@ -254,7 +255,8 @@ bool nfc_poller_detect(NfcPoller* instance) { NfcPollerListElement* iter = instance->list.head; if(tail_poller != instance->list.head) { - while(iter->child != tail_poller) iter = iter->child; + while(iter->child != tail_poller) + iter = iter->child; iter->poller_api->set_callback(iter->poller, nfc_poller_detect_tail_callback, instance); } diff --git a/lib/nfc/protocols/mf_ultralight/mf_ultralight_listener_i.c b/lib/nfc/protocols/mf_ultralight/mf_ultralight_listener_i.c index 3a9b893aa..d84630b99 100644 --- a/lib/nfc/protocols/mf_ultralight/mf_ultralight_listener_i.c +++ b/lib/nfc/protocols/mf_ultralight/mf_ultralight_listener_i.c @@ -155,7 +155,8 @@ static void mf_ultralight_format_mirror_data( FuriString* str, const uint8_t* const data, const uint8_t data_len) { - for(uint8_t i = 0; i < data_len; i++) furi_string_cat_printf(str, "%02X", data[i]); + for(uint8_t i = 0; i < data_len; i++) + furi_string_cat_printf(str, "%02X", data[i]); } void mf_ultralight_mirror_read_prepare(uint8_t start_page, MfUltralightListener* instance) { diff --git a/lib/one_wire/one_wire_host.c b/lib/one_wire/one_wire_host.c index 9383e0f15..f3f3d953e 100644 --- a/lib/one_wire/one_wire_host.c +++ b/lib/one_wire/one_wire_host.c @@ -224,7 +224,8 @@ void onewire_host_target_search(OneWireHost* host, uint8_t family_code) { furi_check(host); host->saved_rom[0] = family_code; - for(uint8_t i = 1; i < 8; i++) host->saved_rom[i] = 0; + for(uint8_t i = 1; i < 8; i++) + host->saved_rom[i] = 0; host->last_discrepancy = 64; host->last_family_discrepancy = 0; host->last_device_flag = false; @@ -341,7 +342,8 @@ bool onewire_host_search(OneWireHost* host, uint8_t* new_addr, OneWireHostSearch host->last_family_discrepancy = 0; search_result = false; } else { - for(int i = 0; i < 8; i++) new_addr[i] = host->saved_rom[i]; + for(int i = 0; i < 8; i++) + new_addr[i] = host->saved_rom[i]; } return search_result; diff --git a/lib/print/printf_tiny.c b/lib/print/printf_tiny.c index 54f192a60..a1332529c 100644 --- a/lib/print/printf_tiny.c +++ b/lib/print/printf_tiny.c @@ -616,7 +616,8 @@ static size_t _etoa( FLAGS_ZEROPAD | FLAGS_PLUS); // might need to right-pad spaces if(flags & FLAGS_LEFT) { - while(idx - start_idx < width) out(' ', buffer, idx++, maxlen); + while(idx - start_idx < width) + out(' ', buffer, idx++, maxlen); } } return idx; diff --git a/lib/toolbox/keys_dict.c b/lib/toolbox/keys_dict.c index 09fc241ee..602653e8f 100644 --- a/lib/toolbox/keys_dict.c +++ b/lib/toolbox/keys_dict.c @@ -176,7 +176,8 @@ static bool keys_dict_get_next_key_str(KeysDict* instance, FuriString* key) { furi_string_reset(key); - while(!key_read && !is_endfile) key_read = keys_dict_read_key_line(instance, key, &is_endfile); + while(!key_read && !is_endfile) + key_read = keys_dict_read_key_line(instance, key, &is_endfile); return key_read; } diff --git a/lib/u8g2/u8x8_byte.c b/lib/u8g2/u8x8_byte.c index a5af75e11..2d729711d 100644 --- a/lib/u8g2/u8x8_byte.c +++ b/lib/u8g2/u8x8_byte.c @@ -584,7 +584,8 @@ void i2c_transfer(u8x8_t* u8x8, uint8_t adr, uint8_t cnt, uint8_t* data) { uint8_t i; i2c_start(u8x8); i2c_write_byte(u8x8, adr); - for(i = 0; i < cnt; i++) i2c_write_byte(u8x8, data[i]); + for(i = 0; i < cnt; i++) + i2c_write_byte(u8x8, data[i]); i2c_stop(u8x8); } diff --git a/lib/u8g2/u8x8_setup.c b/lib/u8g2/u8x8_setup.c index c59c68d05..b8873fb7d 100644 --- a/lib/u8g2/u8x8_setup.c +++ b/lib/u8g2/u8x8_setup.c @@ -109,7 +109,8 @@ void u8x8_SetupDefaults(u8x8_t* u8x8) { #ifdef U8X8_USE_PINS { uint8_t i; - for(i = 0; i < U8X8_PIN_CNT; i++) u8x8->pins[i] = U8X8_PIN_NONE; + for(i = 0; i < U8X8_PIN_CNT; i++) + u8x8->pins[i] = U8X8_PIN_NONE; } #endif } diff --git a/scripts/fbt_tools/compilation_db.py b/scripts/fbt_tools/compilation_db.py index 6bad96b2d..2988fd67b 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 join, split +from oslex import join, split import SCons from SCons.Tool.asm import ASPPSuffixes, ASSuffixes diff --git a/scripts/flipper/utils/cdc.py b/scripts/flipper/utils/cdc.py index 956408859..ee1125f77 100644 --- a/scripts/flipper/utils/cdc.py +++ b/scripts/flipper/utils/cdc.py @@ -15,4 +15,3 @@ def resolve_port(logger, portname: str = "auto"): logger.error("Failed to find connected Flipper") elif len(flippers) > 1: logger.error("More than one Flipper is attached") - logger.error("Failed to guess which port to use") diff --git a/scripts/testing/await_flipper.py b/scripts/testing/await_flipper.py deleted file mode 100755 index f8dffeb66..000000000 --- a/scripts/testing/await_flipper.py +++ /dev/null @@ -1,61 +0,0 @@ -#!/usr/bin/env python3 -import logging -import os -import sys -import time - - -def flp_serial_by_name(flp_name): - if sys.platform == "darwin": # MacOS - flp_serial = "/dev/cu.usbmodemflip_" + flp_name + "1" - logging.info(f"Darwin, looking for {flp_serial}") - elif sys.platform == "linux": # Linux - flp_serial = ( - "/dev/serial/by-id/usb-Flipper_Devices_Inc._Flipper_" - + flp_name - + "_flip_" - + flp_name - + "-if00" - ) - logging.info(f"linux, looking for {flp_serial}") - - if os.path.exists(flp_serial): - return flp_serial - else: - logging.info(f"Couldn't find {flp_name} on this attempt.") - if os.path.exists(flp_name): - return flp_name - else: - return "" - - -UPDATE_TIMEOUT = 30 * 4 # 4 minutes - - -def main(): - flipper_name = sys.argv[1] - elapsed = 0 - flipper = flp_serial_by_name(flipper_name) - logging.basicConfig( - format="%(asctime)s %(levelname)-8s %(message)s", - level=logging.INFO, - datefmt="%Y-%m-%d %H:%M:%S", - ) - logging.info(f"Waiting for Flipper {flipper_name} to be ready...") - - while flipper == "" and elapsed < UPDATE_TIMEOUT: - elapsed += 1 - time.sleep(1) - flipper = flp_serial_by_name(flipper_name) - - if flipper == "": - logging.error("Flipper not found!") - exit(1) - - logging.info(f"Found Flipper at {flipper}") - - sys.exit(0) - - -if __name__ == "__main__": - main() diff --git a/scripts/testing/units.py b/scripts/testing/units.py deleted file mode 100755 index db302e9da..000000000 --- a/scripts/testing/units.py +++ /dev/null @@ -1,87 +0,0 @@ -#!/usr/bin/env python3 -import logging -import re -import sys - -import serial -from await_flipper import flp_serial_by_name - - -def main(): - logging.basicConfig( - format="%(asctime)s %(levelname)-8s %(message)s", - level=logging.INFO, - datefmt="%Y-%m-%d %H:%M:%S", - ) - logging.info("Trying to run units on flipper") - flp_serial = flp_serial_by_name(sys.argv[1]) - - if flp_serial == "": - logging.error("Flipper not found!") - sys.exit(1) - - with serial.Serial(flp_serial, timeout=150) as flipper: - logging.info(f"Found Flipper at {flp_serial}") - flipper.baudrate = 230400 - flipper.flushOutput() - flipper.flushInput() - - flipper.read_until(b">: ").decode("utf-8") - flipper.write(b"unit_tests\r") - data = flipper.read_until(b">: ").decode("utf-8") - - lines = data.split("\r\n") - - tests_re = r"Failed tests: \d{0,}" - time_re = r"Consumed: \d{0,}" - leak_re = r"Leaked: \d{0,}" - status_re = r"Status: \w{3,}" - - tests_pattern = re.compile(tests_re) - time_pattern = re.compile(time_re) - leak_pattern = re.compile(leak_re) - status_pattern = re.compile(status_re) - - tests, time, leak, status = None, None, None, None - total = 0 - - for line in lines: - logging.info(line) - if "()" in line: - total += 1 - - if not tests: - tests = re.match(tests_pattern, line) - if not time: - time = re.match(time_pattern, line) - if not leak: - leak = re.match(leak_pattern, line) - if not status: - status = re.match(status_pattern, line) - - if None in (tests, time, leak, status): - logging.error(f"Failed to parse output: {leak} {time} {leak} {status}") - sys.exit(1) - - leak = int(re.findall(r"[- ]\d+", leak.group(0))[0]) - status = re.findall(r"\w+", status.group(0))[1] - tests = int(re.findall(r"\d+", tests.group(0))[0]) - time = int(re.findall(r"\d+", time.group(0))[0]) - - if tests > 0 or status != "PASSED": - logging.error(f"Got {tests} failed tests.") - logging.error(f"Leaked (not failing on this stat): {leak}") - logging.error(f"Status: {status}") - logging.error(f"Time: {time/1000} seconds") - sys.exit(1) - - logging.info(f"Leaked (not failing on this stat): {leak}") - logging.info( - f"Tests ran successfully! Time elapsed {time/1000} seconds. Passed {total} tests." - ) - - sys.exit(0) - - -if __name__ == "__main__": - main() diff --git a/scripts/testops.py b/scripts/testops.py new file mode 100644 index 000000000..bf02feaad --- /dev/null +++ b/scripts/testops.py @@ -0,0 +1,129 @@ +#!/usr/bin/env python3 + +import re +import sys +import time +from typing import Optional + +from flipper.app import App +from flipper.storage import FlipperStorage +from flipper.utils.cdc import resolve_port + + +class Main(App): + # this is basic use without sub-commands, simply to reboot flipper / power it off, not meant as a full CLI wrapper + def init(self): + self.parser.add_argument("-p", "--port", help="CDC Port", default="auto") + self.parser.add_argument( + "-t", "--timeout", help="Timeout in seconds", type=int, default=10 + ) + + self.subparsers = self.parser.add_subparsers(help="sub-command help") + + self.parser_await_flipper = self.subparsers.add_parser( + "await_flipper", help="Wait for Flipper to connect or reconnect" + ) + self.parser_await_flipper.set_defaults(func=self.await_flipper) + + self.parser_run_units = self.subparsers.add_parser( + "run_units", help="Run unit tests and post result" + ) + self.parser_run_units.set_defaults(func=self.run_units) + + def _get_flipper(self, retry_count: Optional[int] = 1): + port = None + self.logger.info(f"Attempting to find flipper with {retry_count} attempts.") + + for i in range(retry_count): + self.logger.info(f"Attempt to find flipper #{i}.") + + if port := resolve_port(self.logger, self.args.port): + self.logger.info(f"Found flipper at {port}") + break + time.sleep(1) + + if not port: + self.logger.info(f"Failed to find flipper {port}") + return None + + flipper = FlipperStorage(port) + flipper.start() + return flipper + + def await_flipper(self): + if not (flipper := self._get_flipper(retry_count=self.args.timeout)): + return 1 + + self.logger.info("Flipper started") + flipper.stop() + return 0 + + def run_units(self): + if not (flipper := self._get_flipper(retry_count=10)): + return 1 + + self.logger.info("Running unit tests") + flipper.send("unit_tests" + "\r") + self.logger.info("Waiting for unit tests to complete") + data = flipper.read.until(">: ") + self.logger.info("Parsing result") + + lines = data.decode().split("\r\n") + + tests_re = r"Failed tests: \d{0,}" + time_re = r"Consumed: \d{0,}" + leak_re = r"Leaked: \d{0,}" + status_re = r"Status: \w{3,}" + + tests_pattern = re.compile(tests_re) + time_pattern = re.compile(time_re) + leak_pattern = re.compile(leak_re) + status_pattern = re.compile(status_re) + + tests, elapsed_time, leak, status = None, None, None, None + total = 0 + + for line in lines: + self.logger.info(line) + if "()" in line: + total += 1 + + if not tests: + tests = re.match(tests_pattern, line) + if not elapsed_time: + elapsed_time = re.match(time_pattern, line) + if not leak: + leak = re.match(leak_pattern, line) + if not status: + status = re.match(status_pattern, line) + + if None in (tests, elapsed_time, leak, status): + self.logger.error( + f"Failed to parse output: {tests} {elapsed_time} {leak} {status}" + ) + sys.exit(1) + + leak = int(re.findall(r"[- ]\d+", leak.group(0))[0]) + status = re.findall(r"\w+", status.group(0))[1] + tests = int(re.findall(r"\d+", tests.group(0))[0]) + elapsed_time = int(re.findall(r"\d+", elapsed_time.group(0))[0]) + + if tests > 0 or status != "PASSED": + self.logger.error(f"Got {tests} failed tests.") + self.logger.error(f"Leaked (not failing on this stat): {leak}") + self.logger.error(f"Status: {status}") + self.logger.error(f"Time: {elapsed_time/1000} seconds") + flipper.stop() + return 1 + + self.logger.info(f"Leaked (not failing on this stat): {leak}") + self.logger.info( + f"Tests ran successfully! Time elapsed {elapsed_time/1000} seconds. Passed {total} tests." + ) + + flipper.stop() + return 0 + + +if __name__ == "__main__": + Main()() diff --git a/scripts/toolchain/fbtenv.cmd b/scripts/toolchain/fbtenv.cmd index 29b48369a..635affdd4 100644 --- a/scripts/toolchain/fbtenv.cmd +++ b/scripts/toolchain/fbtenv.cmd @@ -13,7 +13,7 @@ if not ["%FBT_NOENV%"] == [""] ( exit /b 0 ) -set "FLIPPER_TOOLCHAIN_VERSION=33" +set "FLIPPER_TOOLCHAIN_VERSION=37" if ["%FBT_TOOLCHAIN_PATH%"] == [""] ( set "FBT_TOOLCHAIN_PATH=%FBT_ROOT%" diff --git a/scripts/toolchain/fbtenv.sh b/scripts/toolchain/fbtenv.sh index edd5691f2..3730a5539 100755 --- a/scripts/toolchain/fbtenv.sh +++ b/scripts/toolchain/fbtenv.sh @@ -4,7 +4,7 @@ # public variables DEFAULT_SCRIPT_PATH="$(pwd -P)"; -FBT_TOOLCHAIN_VERSION="${FBT_TOOLCHAIN_VERSION:-"33"}"; +FBT_TOOLCHAIN_VERSION="${FBT_TOOLCHAIN_VERSION:-"37"}"; if [ -z ${FBT_TOOLCHAIN_PATH+x} ] ; then FBT_TOOLCHAIN_PATH_WAS_SET=0; diff --git a/targets/f18/api_symbols.csv b/targets/f18/api_symbols.csv index 23e098a91..ae561c98c 100644 --- a/targets/f18/api_symbols.csv +++ b/targets/f18/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,68.0,, +Version,+,68.1,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/bt/bt_service/bt_keys_storage.h,, Header,+,applications/services/cli/cli.h,, @@ -1288,6 +1288,7 @@ Function,+,furi_hal_info_get_api_version,void,"uint16_t*, uint16_t*" Function,-,furi_hal_init,void, Function,-,furi_hal_init_early,void, Function,+,furi_hal_interrupt_get_name,const char*,uint8_t +Function,+,furi_hal_interrupt_get_time_in_isr_total,uint32_t, Function,-,furi_hal_interrupt_init,void, Function,+,furi_hal_interrupt_set_isr,void,"FuriHalInterruptId, FuriHalInterruptISR, void*" Function,+,furi_hal_interrupt_set_isr_ex,void,"FuriHalInterruptId, FuriHalInterruptPriority, FuriHalInterruptISR, void*" @@ -1633,6 +1634,7 @@ Function,+,furi_thread_join,_Bool,FuriThread* Function,+,furi_thread_list_alloc,FuriThreadList*, Function,+,furi_thread_list_free,void,FuriThreadList* Function,+,furi_thread_list_get_at,FuriThreadListItem*,"FuriThreadList*, size_t" +Function,+,furi_thread_list_get_isr_time,float,FuriThreadList* Function,+,furi_thread_list_get_or_insert,FuriThreadListItem*,"FuriThreadList*, FuriThread*" Function,+,furi_thread_list_process,void,"FuriThreadList*, uint32_t, uint32_t" Function,+,furi_thread_list_size,size_t,FuriThreadList* diff --git a/targets/f7/api_symbols.csv b/targets/f7/api_symbols.csv index a5cc7141d..6a83b0057 100644 --- a/targets/f7/api_symbols.csv +++ b/targets/f7/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,68.0,, +Version,+,68.1,, 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,, @@ -1447,6 +1447,7 @@ Function,+,furi_hal_infrared_set_tx_output,void,FuriHalInfraredTxPin Function,-,furi_hal_init,void, Function,-,furi_hal_init_early,void, Function,+,furi_hal_interrupt_get_name,const char*,uint8_t +Function,+,furi_hal_interrupt_get_time_in_isr_total,uint32_t, Function,-,furi_hal_interrupt_init,void, Function,+,furi_hal_interrupt_set_isr,void,"FuriHalInterruptId, FuriHalInterruptISR, void*" Function,+,furi_hal_interrupt_set_isr_ex,void,"FuriHalInterruptId, FuriHalInterruptPriority, FuriHalInterruptISR, void*" @@ -1887,6 +1888,7 @@ Function,+,furi_thread_join,_Bool,FuriThread* Function,+,furi_thread_list_alloc,FuriThreadList*, Function,+,furi_thread_list_free,void,FuriThreadList* Function,+,furi_thread_list_get_at,FuriThreadListItem*,"FuriThreadList*, size_t" +Function,+,furi_thread_list_get_isr_time,float,FuriThreadList* Function,+,furi_thread_list_get_or_insert,FuriThreadListItem*,"FuriThreadList*, FuriThread*" Function,+,furi_thread_list_process,void,"FuriThreadList*, uint32_t, uint32_t" Function,+,furi_thread_list_size,size_t,FuriThreadList* diff --git a/targets/f7/furi_hal/furi_hal_bt.c b/targets/f7/furi_hal/furi_hal_bt.c index 036d50ace..30a4ee7ed 100644 --- a/targets/f7/furi_hal/furi_hal_bt.c +++ b/targets/f7/furi_hal/furi_hal_bt.c @@ -21,8 +21,7 @@ #define TAG "FuriHalBt" -#define furi_hal_bt_DEFAULT_MAC_ADDR \ - { 0x6c, 0x7a, 0xd8, 0xac, 0x57, 0x72 } +#define furi_hal_bt_DEFAULT_MAC_ADDR {0x6c, 0x7a, 0xd8, 0xac, 0x57, 0x72} /* Time, in ms, to wait for mode transition before crashing */ #define C2_MODE_SWITCH_TIMEOUT 10000 diff --git a/targets/f7/furi_hal/furi_hal_flash.c b/targets/f7/furi_hal/furi_hal_flash.c index c50b97b80..cc476c4cd 100644 --- a/targets/f7/furi_hal/furi_hal_flash.c +++ b/targets/f7/furi_hal/furi_hal_flash.c @@ -513,8 +513,7 @@ typedef struct { uint32_t* ob_register_address; } FuriHalFlashObMapping; -#define OB_REG_DEF(INDEX, REG) \ - { .ob_reg = INDEX, .ob_register_address = (uint32_t*)(REG) } +#define OB_REG_DEF(INDEX, REG) {.ob_reg = INDEX, .ob_register_address = (uint32_t*)(REG)} static const FuriHalFlashObMapping furi_hal_flash_ob_reg_map[FURI_HAL_FLASH_OB_TOTAL_WORDS] = { OB_REG_DEF(FuriHalFlashObRegisterUserRead, (&FLASH->OPTR)), diff --git a/targets/f7/furi_hal/furi_hal_gpio.c b/targets/f7/furi_hal/furi_hal_gpio.c index 8e6192ca0..e7b331c97 100644 --- a/targets/f7/furi_hal/furi_hal_gpio.c +++ b/targets/f7/furi_hal/furi_hal_gpio.c @@ -249,7 +249,7 @@ void furi_hal_gpio_remove_int_callback(const GpioPin* gpio) { FURI_CRITICAL_EXIT(); } -FURI_ALWAYS_STATIC_INLINE void furi_hal_gpio_int_call(uint16_t pin_num) { +FURI_ALWAYS_INLINE static void furi_hal_gpio_int_call(uint16_t pin_num) { if(gpio_interrupt[pin_num].callback) { gpio_interrupt[pin_num].callback(gpio_interrupt[pin_num].context); } diff --git a/targets/f7/furi_hal/furi_hal_interrupt.c b/targets/f7/furi_hal/furi_hal_interrupt.c index 15a9a819f..f366cff16 100644 --- a/targets/f7/furi_hal/furi_hal_interrupt.c +++ b/targets/f7/furi_hal/furi_hal_interrupt.c @@ -13,12 +13,22 @@ #define FURI_HAL_INTERRUPT_DEFAULT_PRIORITY (configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY + 5) +#define FURI_HAL_INTERRUPT_ACCOUNT_START() const uint32_t _isr_start = DWT->CYCCNT; +#define FURI_HAL_INTERRUPT_ACCOUNT_END() \ + const uint32_t _time_in_isr = DWT->CYCCNT - _isr_start; \ + furi_hal_interrupt.counter_time_in_isr_total += _time_in_isr; + typedef struct { FuriHalInterruptISR isr; void* context; } FuriHalInterruptISRPair; -FuriHalInterruptISRPair furi_hal_interrupt_isr[FuriHalInterruptIdMax] = {0}; +typedef struct { + FuriHalInterruptISRPair isr[FuriHalInterruptIdMax]; + uint32_t counter_time_in_isr_total; +} FuriHalIterrupt; + +static FuriHalIterrupt furi_hal_interrupt = {}; const IRQn_Type furi_hal_interrupt_irqn[FuriHalInterruptIdMax] = { // TIM1, TIM16, TIM17 @@ -67,12 +77,16 @@ const IRQn_Type furi_hal_interrupt_irqn[FuriHalInterruptIdMax] = { [FuriHalInterruptIdLpUart1] = LPUART1_IRQn, }; -FURI_ALWAYS_STATIC_INLINE void furi_hal_interrupt_call(FuriHalInterruptId index) { - furi_check(furi_hal_interrupt_isr[index].isr); - furi_hal_interrupt_isr[index].isr(furi_hal_interrupt_isr[index].context); +FURI_ALWAYS_INLINE static void furi_hal_interrupt_call(FuriHalInterruptId index) { + const FuriHalInterruptISRPair* isr_descr = &furi_hal_interrupt.isr[index]; + furi_check(isr_descr->isr); + + FURI_HAL_INTERRUPT_ACCOUNT_START(); + isr_descr->isr(isr_descr->context); + FURI_HAL_INTERRUPT_ACCOUNT_END(); } -FURI_ALWAYS_STATIC_INLINE void +FURI_ALWAYS_INLINE static void furi_hal_interrupt_enable(FuriHalInterruptId index, uint16_t priority) { NVIC_SetPriority( furi_hal_interrupt_irqn[index], @@ -80,19 +94,19 @@ FURI_ALWAYS_STATIC_INLINE void NVIC_EnableIRQ(furi_hal_interrupt_irqn[index]); } -FURI_ALWAYS_STATIC_INLINE void furi_hal_interrupt_clear_pending(FuriHalInterruptId index) { +FURI_ALWAYS_INLINE static void furi_hal_interrupt_clear_pending(FuriHalInterruptId index) { NVIC_ClearPendingIRQ(furi_hal_interrupt_irqn[index]); } -FURI_ALWAYS_STATIC_INLINE void furi_hal_interrupt_get_pending(FuriHalInterruptId index) { +FURI_ALWAYS_INLINE static void furi_hal_interrupt_get_pending(FuriHalInterruptId index) { NVIC_GetPendingIRQ(furi_hal_interrupt_irqn[index]); } -FURI_ALWAYS_STATIC_INLINE void furi_hal_interrupt_set_pending(FuriHalInterruptId index) { +FURI_ALWAYS_INLINE static void furi_hal_interrupt_set_pending(FuriHalInterruptId index) { NVIC_SetPendingIRQ(furi_hal_interrupt_irqn[index]); } -FURI_ALWAYS_STATIC_INLINE void furi_hal_interrupt_disable(FuriHalInterruptId index) { +FURI_ALWAYS_INLINE static void furi_hal_interrupt_disable(FuriHalInterruptId index) { NVIC_DisableIRQ(furi_hal_interrupt_irqn[index]); } @@ -137,17 +151,18 @@ void furi_hal_interrupt_set_isr_ex( uint16_t real_priority = FURI_HAL_INTERRUPT_DEFAULT_PRIORITY - priority; + FuriHalInterruptISRPair* isr_descr = &furi_hal_interrupt.isr[index]; if(isr) { // Pre ISR set - furi_check(furi_hal_interrupt_isr[index].isr == NULL); + furi_check(isr_descr->isr == NULL); } else { // Pre ISR clear furi_hal_interrupt_disable(index); furi_hal_interrupt_clear_pending(index); } - furi_hal_interrupt_isr[index].isr = isr; - furi_hal_interrupt_isr[index].context = context; + isr_descr->isr = isr; + isr_descr->context = context; __DMB(); if(isr) { @@ -304,27 +319,37 @@ extern void HW_IPCC_Tx_Handler(void); extern void HW_IPCC_Rx_Handler(void); void SysTick_Handler(void) { + FURI_HAL_INTERRUPT_ACCOUNT_START(); furi_hal_os_tick(); + FURI_HAL_INTERRUPT_ACCOUNT_END(); } void USB_LP_IRQHandler(void) { #ifndef FURI_RAM_EXEC + FURI_HAL_INTERRUPT_ACCOUNT_START(); usbd_poll(&udev); + FURI_HAL_INTERRUPT_ACCOUNT_END(); #endif } void USB_HP_IRQHandler(void) { //-V524 #ifndef FURI_RAM_EXEC + FURI_HAL_INTERRUPT_ACCOUNT_START(); usbd_poll(&udev); + FURI_HAL_INTERRUPT_ACCOUNT_END(); #endif } void IPCC_C1_TX_IRQHandler(void) { + FURI_HAL_INTERRUPT_ACCOUNT_START(); HW_IPCC_Tx_Handler(); + FURI_HAL_INTERRUPT_ACCOUNT_END(); } void IPCC_C1_RX_IRQHandler(void) { + FURI_HAL_INTERRUPT_ACCOUNT_START(); HW_IPCC_Rx_Handler(); + FURI_HAL_INTERRUPT_ACCOUNT_END(); } void FPU_IRQHandler(void) { @@ -499,3 +524,7 @@ const char* furi_hal_interrupt_get_name(uint8_t exception_number) { return NULL; } } + +uint32_t furi_hal_interrupt_get_time_in_isr_total(void) { + return furi_hal_interrupt.counter_time_in_isr_total; +} \ No newline at end of file diff --git a/targets/f7/furi_hal/furi_hal_interrupt.h b/targets/f7/furi_hal/furi_hal_interrupt.h index c06ec23d2..2326d3c0a 100644 --- a/targets/f7/furi_hal/furi_hal_interrupt.h +++ b/targets/f7/furi_hal/furi_hal_interrupt.h @@ -118,6 +118,12 @@ void furi_hal_interrupt_set_isr_ex( */ const char* furi_hal_interrupt_get_name(uint8_t exception_number); +/** Get total time(in CPU clocks) spent in ISR + * + * @return total time in CPU clocks + */ +uint32_t furi_hal_interrupt_get_time_in_isr_total(void); + #ifdef __cplusplus } #endif diff --git a/targets/f7/furi_hal/furi_hal_usb_ccid.c b/targets/f7/furi_hal/furi_hal_usb_ccid.c index 5e2fe77b7..6a6527c3b 100644 --- a/targets/f7/furi_hal/furi_hal_usb_ccid.c +++ b/targets/f7/furi_hal/furi_hal_usb_ccid.c @@ -19,7 +19,8 @@ static const uint8_t USB_DEVICE_NO_PROTOCOL = 0x0; #define CCID_TOTAL_SLOTS 1 #define CCID_SLOT_INDEX 0 -#define CCID_DATABLOCK_SIZE 256 +#define CCID_DATABLOCK_SIZE \ + (4 + 1 + CCID_SHORT_APDU_SIZE + 1) //APDU Header + Lc + Short APDU size + Le #define ENDPOINT_DIR_IN 0x80 #define ENDPOINT_DIR_OUT 0x00 @@ -193,7 +194,8 @@ static void* ccid_set_string_descr(char* str) { struct usb_string_descriptor* dev_str_desc = malloc(len * 2 + 2); dev_str_desc->bLength = len * 2 + 2; dev_str_desc->bDescriptorType = USB_DTYPE_STRING; - for(size_t i = 0; i < len; i++) dev_str_desc->wString[i] = str[i]; + for(size_t i = 0; i < len; i++) + dev_str_desc->wString[i] = str[i]; return dev_str_desc; } diff --git a/targets/f7/furi_hal/furi_hal_usb_hid.c b/targets/f7/furi_hal/furi_hal_usb_hid.c index 9599aa1c1..c83261226 100644 --- a/targets/f7/furi_hal/furi_hal_usb_hid.c +++ b/targets/f7/furi_hal/furi_hal_usb_hid.c @@ -368,7 +368,8 @@ static void* hid_set_string_descr(char* str) { struct usb_string_descriptor* dev_str_desc = malloc(len * 2 + 2); dev_str_desc->bLength = len * 2 + 2; dev_str_desc->bDescriptorType = USB_DTYPE_STRING; - for(size_t i = 0; i < len; i++) dev_str_desc->wString[i] = str[i]; + for(size_t i = 0; i < len; i++) + dev_str_desc->wString[i] = str[i]; return dev_str_desc; } diff --git a/targets/furi_hal_include/furi_hal_usb_ccid.h b/targets/furi_hal_include/furi_hal_usb_ccid.h index cbd0bf092..223f16231 100644 --- a/targets/furi_hal_include/furi_hal_usb_ccid.h +++ b/targets/furi_hal_include/furi_hal_usb_ccid.h @@ -5,6 +5,8 @@ #include "hid_usage_consumer.h" #include "hid_usage_led.h" +#define CCID_SHORT_APDU_SIZE (0xFF) + #ifdef __cplusplus extern "C" { #endif