mirror of
https://github.com/DarkFlippers/unleashed-firmware.git
synced 2025-12-12 04:34:43 +04:00
Merge branch 'dev' into release
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
diff --git a/applications/services/notification/notification_app.c b/applications/services/notification/notification_app.c
|
||||
index 9baa738..91ad7c1 100644
|
||||
index d4c5b91..8b43599 100644
|
||||
--- a/applications/services/notification/notification_app.c
|
||||
+++ b/applications/services/notification/notification_app.c
|
||||
@@ -9,6 +9,7 @@
|
||||
@@ -10,7 +10,7 @@ index 9baa738..91ad7c1 100644
|
||||
|
||||
#define TAG "NotificationSrv"
|
||||
|
||||
@@ -589,6 +590,7 @@ int32_t notification_srv(void* p) {
|
||||
@@ -588,6 +589,7 @@ int32_t notification_srv(void* p) {
|
||||
break;
|
||||
case SaveSettingsMessage:
|
||||
notification_save_settings(app);
|
||||
@@ -19,7 +19,7 @@ index 9baa738..91ad7c1 100644
|
||||
}
|
||||
|
||||
diff --git a/applications/settings/notification_settings/notification_settings_app.c b/applications/settings/notification_settings/notification_settings_app.c
|
||||
index 2a1d988..dda86f3 100644
|
||||
index 7576dcf..ae022e2 100644
|
||||
--- a/applications/settings/notification_settings/notification_settings_app.c
|
||||
+++ b/applications/settings/notification_settings/notification_settings_app.c
|
||||
@@ -3,6 +3,7 @@
|
||||
@@ -99,7 +99,7 @@ index 2a1d988..dda86f3 100644
|
||||
static uint32_t notification_app_settings_exit(void* context) {
|
||||
UNUSED(context);
|
||||
return VIEW_NONE;
|
||||
@@ -192,8 +248,40 @@ static NotificationAppSettings* alloc_settings() {
|
||||
@@ -192,8 +248,40 @@ static NotificationAppSettings* alloc_settings(void) {
|
||||
variable_item_set_current_value_index(item, value_index);
|
||||
variable_item_set_current_value_text(item, contrast_text[value_index]);
|
||||
|
||||
@@ -143,7 +143,7 @@ index 2a1d988..dda86f3 100644
|
||||
variable_item_set_current_value_index(item, value_index);
|
||||
diff --git a/applications/settings/notification_settings/rgb_backlight.c b/applications/settings/notification_settings/rgb_backlight.c
|
||||
new file mode 100644
|
||||
index 0000000..98f0d3a
|
||||
index 0000000..4edd775
|
||||
--- /dev/null
|
||||
+++ b/applications/settings/notification_settings/rgb_backlight.c
|
||||
@@ -0,0 +1,217 @@
|
||||
@@ -169,9 +169,9 @@ index 0000000..98f0d3a
|
||||
+#include <furi_hal.h>
|
||||
+#include <storage/storage.h>
|
||||
+
|
||||
+#define RGB_BACKLIGHT_SETTINGS_VERSION 6
|
||||
+#define RGB_BACKLIGHT_SETTINGS_VERSION 6
|
||||
+#define RGB_BACKLIGHT_SETTINGS_FILE_NAME ".rgb_backlight.settings"
|
||||
+#define RGB_BACKLIGHT_SETTINGS_PATH INT_PATH(RGB_BACKLIGHT_SETTINGS_FILE_NAME)
|
||||
+#define RGB_BACKLIGHT_SETTINGS_PATH INT_PATH(RGB_BACKLIGHT_SETTINGS_FILE_NAME)
|
||||
+
|
||||
+#define COLOR_COUNT (sizeof(colors) / sizeof(RGBBacklightColor))
|
||||
+
|
||||
@@ -263,7 +263,7 @@ index 0000000..98f0d3a
|
||||
+ storage_file_free(file);
|
||||
+ furi_record_close(RECORD_STORAGE);
|
||||
+ rgb_settings.settings_is_loaded = true;
|
||||
+};
|
||||
+}
|
||||
+
|
||||
+void rgb_backlight_save_settings(void) {
|
||||
+ RGBBacklightSettings settings;
|
||||
@@ -294,7 +294,7 @@ index 0000000..98f0d3a
|
||||
+ storage_file_close(file);
|
||||
+ storage_file_free(file);
|
||||
+ furi_record_close(RECORD_STORAGE);
|
||||
+};
|
||||
+}
|
||||
+
|
||||
+RGBBacklightSettings* rgb_backlight_get_settings(void) {
|
||||
+ if(!rgb_settings.settings_is_loaded) {
|
||||
@@ -366,7 +366,7 @@ index 0000000..98f0d3a
|
||||
+}
|
||||
diff --git a/applications/settings/notification_settings/rgb_backlight.h b/applications/settings/notification_settings/rgb_backlight.h
|
||||
new file mode 100644
|
||||
index 0000000..68dacda
|
||||
index 0000000..f215ed3
|
||||
--- /dev/null
|
||||
+++ b/applications/settings/notification_settings/rgb_backlight.h
|
||||
@@ -0,0 +1,91 @@
|
||||
@@ -461,10 +461,9 @@ index 0000000..68dacda
|
||||
+ * @return Указатель на строку с названием цвета
|
||||
+ */
|
||||
+const char* rgb_backlight_get_color_text(uint8_t index);
|
||||
\ No newline at end of file
|
||||
diff --git a/lib/drivers/SK6805.c b/lib/drivers/SK6805.c
|
||||
new file mode 100644
|
||||
index 0000000..572e1df
|
||||
index 0000000..b89f82a
|
||||
--- /dev/null
|
||||
+++ b/lib/drivers/SK6805.c
|
||||
@@ -0,0 +1,101 @@
|
||||
@@ -491,14 +490,14 @@ index 0000000..572e1df
|
||||
+
|
||||
+/* Настройки */
|
||||
+#define SK6805_LED_COUNT 3 //Количество светодиодов на плате подсветки
|
||||
+#define SK6805_LED_PIN &led_pin //Порт подключения светодиодов
|
||||
+#define SK6805_LED_PIN &led_pin //Порт подключения светодиодов
|
||||
+
|
||||
+#ifdef FURI_DEBUG
|
||||
+#define DEBUG_PIN &gpio_ext_pa7
|
||||
+#define DEBUG_INIT() \
|
||||
+ furi_hal_gpio_init(DEBUG_PIN, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh)
|
||||
+#define DEBUG_SET_HIGH() furi_hal_gpio_write(DEBUG_PIN, true)
|
||||
+#define DEBUG_SET_LOW() furi_hal_gpio_write(DEBUG_PIN, false)
|
||||
+#define DEBUG_SET_LOW() furi_hal_gpio_write(DEBUG_PIN, false)
|
||||
+#else
|
||||
+#define DEBUG_INIT()
|
||||
+#define DEBUG_SET_HIGH()
|
||||
@@ -571,7 +570,7 @@ index 0000000..572e1df
|
||||
+}
|
||||
diff --git a/lib/drivers/SK6805.h b/lib/drivers/SK6805.h
|
||||
new file mode 100644
|
||||
index 0000000..7c58956
|
||||
index 0000000..c97054f
|
||||
--- /dev/null
|
||||
+++ b/lib/drivers/SK6805.h
|
||||
@@ -0,0 +1,51 @@
|
||||
@@ -626,9 +625,8 @@ index 0000000..7c58956
|
||||
+void SK6805_update(void);
|
||||
+
|
||||
+#endif /* SK6805_H_ */
|
||||
\ No newline at end of file
|
||||
diff --git a/targets/f7/furi_hal/furi_hal_light.c b/targets/f7/furi_hal/furi_hal_light.c
|
||||
index 83e1603..45798ca 100644
|
||||
index 621478d..ef15153 100644
|
||||
--- a/targets/f7/furi_hal/furi_hal_light.c
|
||||
+++ b/targets/f7/furi_hal/furi_hal_light.c
|
||||
@@ -3,6 +3,7 @@
|
||||
@@ -637,7 +635,7 @@ index 83e1603..45798ca 100644
|
||||
#include <stdint.h>
|
||||
+#include <applications/settings/notification_settings/rgb_backlight.h>
|
||||
|
||||
#define LED_CURRENT_RED (50u)
|
||||
#define LED_CURRENT_RED (50u)
|
||||
#define LED_CURRENT_GREEN (50u)
|
||||
@@ -31,22 +32,21 @@ void furi_hal_light_init(void) {
|
||||
}
|
||||
|
||||
129
.clang-format
129
.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: true
|
||||
AcrossEmptyLines: true
|
||||
AcrossComments: true
|
||||
AlignCompound: false
|
||||
AlignFunctionPointers: false
|
||||
PadOperators: true
|
||||
AlignConsecutiveDeclarations:
|
||||
Enabled: false
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCompound: false
|
||||
AlignFunctionPointers: false
|
||||
PadOperators: true
|
||||
AlignConsecutiveMacros:
|
||||
Enabled: true
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: true
|
||||
AlignCompound: true
|
||||
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: false
|
||||
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,38 +80,35 @@ 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
|
||||
- Q_FOREACH
|
||||
- BOOST_FOREACH
|
||||
- M_EACH
|
||||
IfMacros:
|
||||
- KJ_IF_MAYBE
|
||||
IncludeBlocks: Preserve
|
||||
@@ -97,19 +128,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: true
|
||||
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 +161,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: true
|
||||
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,32 +207,35 @@ 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
|
||||
Standard: c++20
|
||||
StatementAttributeLikeMacros:
|
||||
- Q_EMIT
|
||||
StatementMacros:
|
||||
- Q_UNUSED
|
||||
- QT_REQUIRE_VERSION
|
||||
TabWidth: 4
|
||||
UseCRLF: false
|
||||
UseTab: Never
|
||||
VerilogBreakBetweenInstancePorts: true
|
||||
WhitespaceSensitiveMacros:
|
||||
- STRINGIZE
|
||||
- PP_STRINGIZE
|
||||
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -45,9 +45,6 @@ null.d
|
||||
.sconsign.dblite
|
||||
|
||||
|
||||
# Visual Studio Code
|
||||
/.vscode
|
||||
|
||||
# bundle output
|
||||
/dist
|
||||
/artifacts-default
|
||||
|
||||
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -23,9 +23,6 @@
|
||||
[submodule "lib/mbedtls"]
|
||||
path = lib/mbedtls
|
||||
url = https://github.com/Mbed-TLS/mbedtls.git
|
||||
[submodule "lib/cxxheaderparser"]
|
||||
path = lib/cxxheaderparser
|
||||
url = https://github.com/robotpy/cxxheaderparser.git
|
||||
[submodule "lib/heatshrink"]
|
||||
path = lib/heatshrink
|
||||
url = https://github.com/flipperdevices/heatshrink.git
|
||||
|
||||
@@ -3,10 +3,12 @@
|
||||
//-V:M_EACH:1048,1044
|
||||
//-V:ARRAY_DEF:760,747,568,776,729,712,654,1103
|
||||
//-V:LIST_DEF:760,747,568,712,729,654,776,1103
|
||||
//-V:LIST_DUAL_PUSH_DEF:524,760,774
|
||||
//-V:BPTREE_DEF2:779,1086,557,773,512
|
||||
//-V:DICT_DEF2:779,524,776,760,1044,1001,729,590,568,747,685,1103
|
||||
//-V:ALGO_DEF:1048,747,1044
|
||||
//-V:TUPLE_DEF2:524,590,1001,760
|
||||
//-V:DEQUE_DEF:658,747,760
|
||||
|
||||
# Non-severe malloc/null pointer deref warnings
|
||||
//-V::522:2,3
|
||||
@@ -43,4 +45,4 @@
|
||||
//-V:with_view_model:1044,1048
|
||||
|
||||
# Examples
|
||||
//V_EXCLUDE_PATH applications/examples/
|
||||
//V_EXCLUDE_PATH applications/examples/
|
||||
|
||||
22
.sublime-project
vendored
22
.sublime-project
vendored
@@ -6,16 +6,20 @@
|
||||
}
|
||||
],
|
||||
"settings": {
|
||||
"LSP": {
|
||||
"clangd": {
|
||||
"initializationOptions": {
|
||||
"clangd.compile-commands-dir": "build/latest",
|
||||
"clangd.header-insertion": "never",
|
||||
"clangd.query-driver": "**",
|
||||
"clangd.clang-tidy": true,
|
||||
},
|
||||
"LSP": {
|
||||
"clangd": {
|
||||
"enabled": true,
|
||||
"initializationOptions": {
|
||||
// Use with toolchain version 39+
|
||||
// Set `"binary": "custom",` option in LSP-clangd config to use toolchain clangd
|
||||
// "custom_command": ["toolchain/current/bin/clangd"],
|
||||
|
||||
"clangd.compile-commands-dir": "build/latest",
|
||||
"clangd.header-insertion": "never",
|
||||
"clangd.query-driver": "**/arm-none-eabi-*",
|
||||
"clangd.clang-tidy": true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
8
.vscode/.gitignore
vendored
8
.vscode/.gitignore
vendored
@@ -1,5 +1,3 @@
|
||||
/c_cpp_properties.json
|
||||
/extensions.json
|
||||
/launch.json
|
||||
/settings.json
|
||||
/tasks.json
|
||||
*
|
||||
!example/
|
||||
!ReadMe.md
|
||||
|
||||
@@ -1,11 +1,7 @@
|
||||
{
|
||||
"C_Cpp.default.cStandard": "gnu23",
|
||||
"C_Cpp.default.cppStandard": "c++20",
|
||||
"python.formatting.provider": "black",
|
||||
"workbench.tree.indent": 12,
|
||||
"cortex-debug.enableTelemetry": false,
|
||||
"cortex-debug.variableUseNaturalFormat": true,
|
||||
"cortex-debug.showRTOS": true,
|
||||
"cortex-debug.armToolchainPath": "${workspaceFolder}/toolchain/current/bin",
|
||||
"cortex-debug.openocdPath": "${workspaceFolder}/toolchain/current/bin/openocd",
|
||||
"cortex-debug.gdbPath": "${workspaceFolder}/toolchain/current/bin/arm-none-eabi-gdb-py3",
|
||||
@@ -16,9 +12,9 @@
|
||||
"SConstruct": "python",
|
||||
"*.fam": "python"
|
||||
},
|
||||
// "clangd.path": "${workspaceFolder}/toolchain/current/bin/clangd@FBT_PLATFORM_EXECUTABLE_EXT@",
|
||||
"clangd.arguments": [
|
||||
// We might be able to tighten this a bit more to only include the correct toolchain.
|
||||
"--query-driver=**",
|
||||
"--query-driver=**/arm-none-eabi-*",
|
||||
"--compile-commands-dir=${workspaceFolder}/build/latest",
|
||||
"--clang-tidy",
|
||||
"--header-insertion=never"
|
||||
107
CHANGELOG.md
107
CHANGELOG.md
@@ -1,57 +1,64 @@
|
||||
## Main changes
|
||||
- SubGHz:
|
||||
- Add new protocol - legrand 18bit (by @user890104)
|
||||
- OFW: Princeton protocol add custom guard time support
|
||||
- Princeton fix guard time bounds and show guard time multiplier in UI
|
||||
- NFC:
|
||||
- Fix Mifare DESFire reading (revert of buffer check workaround for rare emv cases) (some emv cards can be read only via Extra Actions -> Read specific card type -> EMV)
|
||||
- Better plugins(parsers) loading - much faster emulation launch from favourites, no more lags in Saved menu
|
||||
- OFW: MF Ultralight Original write support
|
||||
- OFW: Mifare Plus detection support
|
||||
- OFW: Felica emulation
|
||||
- OFW: Write to ultralight cards is now possible (no UID writing)
|
||||
- OFW: Fixed infinite loop in dictionary attack scene
|
||||
* LF RFID: OFW: Added Support for Securakey Protocol
|
||||
* JS: `adc` support in `gpio` module (by @jamisonderek)
|
||||
* JS: `storage` module (without virtual mount API at the moment) (by @Willy-JL)
|
||||
* BadUSB: Add Finnish keyboard layout (by @nicou | PR #761)
|
||||
* Archive: Fix SubGHz Remote files in favourites falling into non working and non removable state
|
||||
- **Novoferm** remotes full support
|
||||
- Fix Decode scene in RAW files
|
||||
- Add manually -> Add Sommer FM238 option for cases when default option doesn't work (named as Sommer fm2)
|
||||
- Remove broken preset modulation
|
||||
- Normstahl, Sommer, MHouse, Aprimatic -> Fixes for button codes and more in Add manually
|
||||
- Custom button improvements for MHouse, Novoferm, Nice Smilo
|
||||
- Hormann EcoStar -> Add manually support, and custom button support
|
||||
- Hormann HSM 44bit static -> Button code decoding fix
|
||||
- Choose RSSI threshold for Hopping mode (by @Willy-JL)
|
||||
- NFC:
|
||||
- OFW: Ultralight C authentication with des key
|
||||
- EMV Transactions less nested, hide if unavailable (by @Willy-JL | PR #771)
|
||||
- Update Mifare Classic default keys dict with new keys from proxmark3 repo and UberGuidoZ repo
|
||||
- LF RFID:
|
||||
- Update T5577 password list (by @korden32 | PR #774)
|
||||
- Add DEZ 8 display form for EM4100 (by @korden32 | PR #776 & (#777 by @mishamyte))
|
||||
- JS:
|
||||
- Refactor widget and keyboard modules, fix crash (by @Willy-JL | PR #770)
|
||||
- SubGHz module fixes and improvements (by @Willy-JL)
|
||||
* OFW: Infrared: check for negative timings
|
||||
* OFW: Fix iButton/LFRFID Add Manually results being discarded
|
||||
* OFW: Event Loop Timers
|
||||
* OFW: Updater: resource compression
|
||||
* Apps: **Check out more Apps updates and fixes by following** [this link](https://github.com/xMasterX/all-the-plugins/commits/dev)
|
||||
## Other changes
|
||||
* SubGHz: Fix add manually princeton
|
||||
* SubGHz: Sync signal delete scene with OFW
|
||||
* SubGHz: Fix incorrect rx key state when opening Read menu
|
||||
* SubGHz: Fix incorrect state in decode raw exit - causing keys to be not removed from history and showing up in Read menu after exit from decode raw
|
||||
* Misc: Remove outdated brew sdk install files
|
||||
* Misc: Revert USB CDC changes to fix usb serial
|
||||
* Misc: Fix usage of deprecated `icon_get_data`
|
||||
* Loader: Better API Mismatch message (by @Willy-JL)
|
||||
* CLI: Move part of the CLI to microsd to free up space for COMPACT 0 builds (by @Willy-JL)
|
||||
* NFC: Fix typo in parsers
|
||||
* Apps: Fix `input_callback` and `timer_callback` usage of non `void` argument as input
|
||||
* LF RFID: OFW PR 3728: Securakey - Add Support for RKKTH Plain Text Format (by @zinongli)
|
||||
* OFW: ReadMe: update outdated bits and pieces
|
||||
* OFW: Debug: backup openocd work area, fix crash after fresh debugger connect and continue
|
||||
* OFW: ELF, Flipper application: do not crash on "out of memory"
|
||||
* OFW: MF Plus - Don't crash on reading weird cards
|
||||
* OFW: SubGhz: fix Missed the "Deleted" screen when deleting RAW Subghz (by @Skorpionm)
|
||||
* OFW: JS: Disable logging in mjs +2k free flash (by @hedger)
|
||||
* OFW: Archive: fix memory leak in favorites add/remove
|
||||
* OFW: Furi: Fix EventLoop state persisting on same thread after free
|
||||
* OFW: Cli: top
|
||||
* OFW: Desktop lockup fix, GUI improvements
|
||||
* OFW: Loader: fix crash on "locked via cli loader"
|
||||
* OFW: SubGhz: fix navigation GUI
|
||||
* OFW: Furi: event loop
|
||||
* OFW: Code Cleanup: unused includes, useless checks, unused variables, etc...
|
||||
* OFW: SubGhz: fix gui "No transition to the "Saved" menu when deleting a SubGHz RAW file"
|
||||
* OFW: RPC: Add TarExtract command, some small fixes
|
||||
* OFW: Use static synchronisation primitives
|
||||
* OFW: cleanup of various warnings from clangd
|
||||
* OFW: Add initial ISO7816 support
|
||||
* OFW: fbt, vscode: tweaks for cdb generation for clangd
|
||||
* OFW: Updater: fix inability to update with bigger updater.bin
|
||||
* OFW: Furi: wrap message queue in container, prepare it for epoll. Accessor: disable expansion service on start.
|
||||
* OFW: HID/BLE Keyboard UI refactoring
|
||||
* OFW: CCID: Add CCIDWorker
|
||||
* OFW: Disabled ISR runtime stats collection for updater builds
|
||||
* OFW: VSCode fixes: .gitignore & clangd
|
||||
* OFW: ufbt: synced .clang-format rules with main
|
||||
* OFW: Code formatting update
|
||||
* OFW: scripts: runfap: fixed starting apps with spaces in path
|
||||
* OFW: toolchain: v38. clangd as default language server
|
||||
* OFW: NFC: ISO15693 Render Typo Fix
|
||||
* OFW: tar archive: fix double free
|
||||
* OFW: ufbt: added ARGS to commandline parser
|
||||
* OFW: lib: sconscript todo cleanup
|
||||
* OFW: Intruder animation
|
||||
* OFW: Desktop: allow to close blocking bad sd animation
|
||||
* OFW: Updater: reset various debug flags on production build flash (was done in same way in UL before)
|
||||
* OFW: Fix PVS Warnings
|
||||
* OFW: CCID: Improve request and response data handling
|
||||
* OFW: Furi: count ISR time. Cli: show ISR time in top.
|
||||
* OFW: toolchain: v37
|
||||
* OFW: NFC: Cache plugin name not full path, saves some RAM (by @Willy-JL)
|
||||
* OFW: copro: bumped to 1.20.0
|
||||
* OFW: input_srv: Put input state data on the stack of the service
|
||||
* OFW: Coalesce some allocations
|
||||
* OFW: updater: slightly smaller image
|
||||
* OFW: Updater: Fix double dir cleanup
|
||||
* OFW: cli: storage: minor subcommand lookup refactor
|
||||
* OFW: LFRFID Securakey: Add Support for RKKTH Plain Text Format
|
||||
* OFW: NFC: Add mf_classic_set_sector_trailer_read function
|
||||
* OFW: Separate editing and renaming in iButton and LFRFID
|
||||
* OFW: New js modules documentation added
|
||||
* OFW: Update link to mfkey32
|
||||
* OFW: NFC: Desfire Renderer Minor Debug
|
||||
* OFW: RPC: Fix input lockup on disconnect
|
||||
* OFW: Thread Signals
|
||||
<br><br>
|
||||
#### Known NFC post-refactor regressions list:
|
||||
- Mifare Mini clones reading is broken (original mini working fine) (OFW)
|
||||
|
||||
11
ReadMe.md
11
ReadMe.md
@@ -79,6 +79,7 @@
|
||||
- Infrared -> External IR modules support (with autodetect by OFW)
|
||||
- **NFC/RFID/iButton**
|
||||
* LFRFID and iButton Fuzzer plugins
|
||||
* Add DEZ 8 display form for EM4100 (by @korden32)
|
||||
* Extra Mifare Classic keys in system dict
|
||||
* EMV Protocol + Public data parser (by @Leptopt1los and @wosk)
|
||||
* NFC `Add manually` -> Mifare Classic with custom UID
|
||||
@@ -104,18 +105,18 @@ Thanks to Official team (to their SubGHz Developer, Skorp) for implementing supp
|
||||
|
||||
Keeloq [Not ALL systems supported for decode or emulation!] - [Supported manufacturers list](https://pastes.io/raw/unuj9bhe4m)
|
||||
|
||||
Encoders or emulation support made by @xMasterX:
|
||||
Encoders or emulation (+ programming mode) support made by @xMasterX:
|
||||
- Nero Radio 57bit (+ 56bit support)
|
||||
- CAME 12bit/24bit encoder fixes (Fixes are now merged in OFW)
|
||||
- Keeloq: Dea Mio, Genius Bravo, GSN, HCS101, AN-Motors, JCM Tech, MHouse, Nice Smilo, DTM Neo, FAAC RC,XT, Mutancode, Normstahl, Beninca + Allmatic, Stilmatic, CAME Space, Aprimatic (model TR and similar), Centurion Nova (thanks Carlos !)
|
||||
- Keeloq: Dea Mio, Genius Bravo, GSN, HCS101, AN-Motors, JCM Tech, MHouse, Nice Smilo, DTM Neo, FAAC RC,XT, Mutancode, Normstahl, Beninca + Allmatic, Stilmatic, CAME Space, Aprimatic (model TR and similar), Centurion Nova (thanks Carlos !), Hormann EcoStar, Novoferm
|
||||
|
||||
Encoders or emulation made by @Eng1n33r(first implementation in Q2 2022) and @xMasterX (current version):
|
||||
Protocols support made by Skorp (original implementation) and @xMasterX (current version):
|
||||
- CAME Atomo -> Update! check out new [instructions](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/SubGHzRemoteProg.md)
|
||||
- Nice Flor S -> How to create new remote - [instructions](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/SubGHzRemoteProg.md)
|
||||
- FAAC SLH (Spa) -> Update!!! Check out new [instructions](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/SubGHzRemoteProg.md)
|
||||
- FAAC SLH (Spa) -> Update!!! (Programming mode!) Check out new [instructions](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/SubGHzRemoteProg.md)
|
||||
- Keeloq: BFT Mitto -> Update! Check out new [instructions](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/SubGHzRemoteProg.md)
|
||||
- Star Line
|
||||
- Security+ v1 & v2 (encoders was made in OFW)
|
||||
- Security+ v1 & v2
|
||||
|
||||
Encoders made by @assasinfil and @xMasterX:
|
||||
- Somfy Telis -> How to create new remote - [instructions](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/SubGHzRemoteProg.md)
|
||||
|
||||
17
SConstruct
17
SConstruct
@@ -43,10 +43,10 @@ distenv = coreenv.Clone(
|
||||
"blackmagic",
|
||||
"jflash",
|
||||
"doxygen",
|
||||
"textfile",
|
||||
],
|
||||
ENV=os.environ,
|
||||
UPDATE_BUNDLE_DIR="dist/${DIST_DIR}/f${TARGET_HW}-update-${DIST_SUFFIX}",
|
||||
VSCODE_LANG_SERVER=ARGUMENTS.get("LANG_SERVER", "cpptools"),
|
||||
)
|
||||
|
||||
firmware_env = distenv.AddFwProject(
|
||||
@@ -403,14 +403,23 @@ distenv.PhonyTarget(
|
||||
)
|
||||
|
||||
# Prepare vscode environment
|
||||
VSCODE_LANG_SERVER = cmd_environment["LANG_SERVER"]
|
||||
vscode_dist = distenv.Install(
|
||||
"#.vscode",
|
||||
[
|
||||
distenv.Glob("#.vscode/example/*.json"),
|
||||
distenv.Glob(f"#.vscode/example/{VSCODE_LANG_SERVER}/*.json"),
|
||||
distenv.Glob("#.vscode/example/*.json", exclude="*.tmpl"),
|
||||
distenv.Glob("#.vscode/example/${LANG_SERVER}/*.json"),
|
||||
],
|
||||
)
|
||||
for template_file in distenv.Glob("#.vscode/example/*.tmpl"):
|
||||
vscode_dist.append(
|
||||
distenv.Substfile(
|
||||
distenv.Dir("#.vscode").File(template_file.name.replace(".tmpl", "")),
|
||||
template_file,
|
||||
SUBST_DICT={
|
||||
"@FBT_PLATFORM_EXECUTABLE_EXT@": ".exe" if os.name == "nt" else ""
|
||||
},
|
||||
)
|
||||
)
|
||||
distenv.Precious(vscode_dist)
|
||||
distenv.NoClean(vscode_dist)
|
||||
distenv.Alias("vscode_dist", (vscode_dist, firmware_env["FW_CDB"]))
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#include <gui/elements.h>
|
||||
#include <assets_icons.h>
|
||||
|
||||
#define LOW_CHARGE_THRESHOLD 10
|
||||
#define LOW_CHARGE_THRESHOLD 10
|
||||
#define HIGH_DRAIN_CURRENT_THRESHOLD 100
|
||||
|
||||
struct BatteryInfo {
|
||||
@@ -17,7 +17,7 @@ static void draw_stat(Canvas* canvas, int x, int y, const Icon* icon, char* val)
|
||||
canvas_draw_box(canvas, x - 4, y + 16, 24, 6);
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
canvas_draw_str_aligned(canvas, x + 8, y + 22, AlignCenter, AlignBottom, val);
|
||||
};
|
||||
}
|
||||
|
||||
static void draw_battery(Canvas* canvas, BatteryInfoModel* data, int x, int y) {
|
||||
char emote[20] = {};
|
||||
@@ -85,7 +85,7 @@ static void draw_battery(Canvas* canvas, BatteryInfoModel* data, int x, int y) {
|
||||
canvas_draw_str_aligned(canvas, 92, y + 3, AlignCenter, AlignCenter, emote);
|
||||
canvas_draw_str_aligned(canvas, 92, y + 15, AlignCenter, AlignCenter, header);
|
||||
canvas_draw_str_aligned(canvas, 92, y + 27, AlignCenter, AlignCenter, value);
|
||||
};
|
||||
}
|
||||
|
||||
static void battery_info_draw_callback(Canvas* canvas, void* context) {
|
||||
furi_assert(context);
|
||||
|
||||
@@ -39,7 +39,7 @@ typedef struct {
|
||||
} BtTestModel;
|
||||
|
||||
#define BT_TEST_START_MESSAGE "Ok - Start"
|
||||
#define BT_TEST_STOP_MESSAGE "Ok - Stop"
|
||||
#define BT_TEST_STOP_MESSAGE "Ok - Stop"
|
||||
|
||||
static void bt_test_process_up(BtTest* bt_test);
|
||||
static void bt_test_process_down(BtTest* bt_test);
|
||||
@@ -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) {
|
||||
|
||||
@@ -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,80 @@ 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,
|
||||
uint16_t lc,
|
||||
uint16_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,
|
||||
uint16_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,
|
||||
uint16_t lc,
|
||||
uint16_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 +200,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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -188,8 +253,10 @@ int32_t ccid_test_app(void* p) {
|
||||
|
||||
FuriHalUsbInterface* usb_mode_prev = furi_hal_usb_get_config();
|
||||
furi_hal_usb_unlock();
|
||||
furi_hal_ccid_set_callbacks((CcidCallbacks*)&ccid_cb, NULL);
|
||||
|
||||
furi_check(furi_hal_usb_set_config(&usb_ccid, &app->ccid_cfg) == true);
|
||||
furi_hal_usb_ccid_set_callbacks((CcidCallbacks*)&ccid_cb, NULL);
|
||||
furi_hal_usb_ccid_insert_smartcard();
|
||||
|
||||
iso7816_set_callbacks((Iso7816Callbacks*)&iso87816_cb);
|
||||
|
||||
@@ -210,8 +277,8 @@ int32_t ccid_test_app(void* p) {
|
||||
}
|
||||
|
||||
//tear down USB
|
||||
furi_hal_usb_ccid_set_callbacks(NULL, NULL);
|
||||
furi_hal_usb_set_config(usb_mode_prev, NULL);
|
||||
furi_hal_ccid_set_callbacks(NULL, NULL);
|
||||
|
||||
iso7816_set_callbacks(NULL);
|
||||
|
||||
|
||||
119
applications/debug/ccid_test/client/ccid_client.py
Executable file
119
applications/debug/ccid_test/client/ccid_client.py
Executable file
@@ -0,0 +1,119 @@
|
||||
#!/usr/bin/env python
|
||||
# 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,
|
||||
)
|
||||
|
||||
upper_bound = 0xF0
|
||||
max_apdu = list(range(0, upper_bound))
|
||||
|
||||
test_apdu(
|
||||
connection,
|
||||
"INS 0x04: Lc=0x%x, data=max_apdu, Le=0x%x. Expect 0x%x bytes data in return"
|
||||
% (upper_bound, upper_bound, upper_bound),
|
||||
[0x01, 0x04, 0x00, 0x00, upper_bound] + max_apdu + [upper_bound],
|
||||
0x90,
|
||||
0x00,
|
||||
max_apdu,
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
2
applications/debug/ccid_test/client/requirements.txt
Normal file
2
applications/debug/ccid_test/client/requirements.txt
Normal file
@@ -0,0 +1,2 @@
|
||||
pyscard
|
||||
# or sudo apt install python3-pyscard
|
||||
@@ -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_
|
||||
|
||||
@@ -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 <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <furi.h>
|
||||
#include <furi_hal.h>
|
||||
|
||||
#include "iso7816_t0_apdu.h"
|
||||
#include "iso7816_atr.h"
|
||||
#include "iso7816_callbacks.h"
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <furi.h>
|
||||
|
||||
#define ISO7816_RESPONSE_BUFFER_SIZE 255
|
||||
#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);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
#ifndef _ISO7816_CALLBACKS_H_
|
||||
#define _ISO7816_CALLBACKS_H_
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#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);
|
||||
@@ -24,5 +19,3 @@ void iso7816_xfr_datablock_callback(
|
||||
uint32_t dataBlockLen,
|
||||
uint8_t* responseDataBlock,
|
||||
uint32_t* responseDataBlockLen);
|
||||
|
||||
#endif //_ISO7816_CALLBACKS_H_
|
||||
8
applications/debug/ccid_test/iso7816_response.c
Normal file
8
applications/debug/ccid_test/iso7816_response.c
Normal file
@@ -0,0 +1,8 @@
|
||||
#include <stdint.h>
|
||||
#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;
|
||||
}
|
||||
12
applications/debug/ccid_test/iso7816_response.h
Normal file
12
applications/debug/ccid_test/iso7816_response.h
Normal file
@@ -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);
|
||||
@@ -2,37 +2,73 @@
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <furi.h>
|
||||
#include <furi_hal.h>
|
||||
#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++;
|
||||
}
|
||||
}
|
||||
@@ -45,4 +81,4 @@ void iso7816_write_response_apdu(
|
||||
responseDataBufferIndex++;
|
||||
|
||||
*readerToPcDataBlockLen = responseDataBufferIndex;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
#ifndef _ISO7816_T0_APDU_H_
|
||||
#define _ISO7816_T0_APDU_H_
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#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);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
10
applications/debug/event_loop_blink_test/application.fam
Normal file
10
applications/debug/event_loop_blink_test/application.fam
Normal file
@@ -0,0 +1,10 @@
|
||||
App(
|
||||
appid="event_loop_blink_test",
|
||||
name="Event Loop Blink Test",
|
||||
apptype=FlipperAppType.DEBUG,
|
||||
entry_point="event_loop_blink_test_app",
|
||||
requires=["input"],
|
||||
stack_size=1 * 1024,
|
||||
order=20,
|
||||
fap_category="Debug",
|
||||
)
|
||||
169
applications/debug/event_loop_blink_test/event_loop_blink_test.c
Normal file
169
applications/debug/event_loop_blink_test/event_loop_blink_test.c
Normal file
@@ -0,0 +1,169 @@
|
||||
#include <furi.h>
|
||||
#include <furi_hal_resources.h>
|
||||
|
||||
#include <gui/gui.h>
|
||||
#include <gui/elements.h>
|
||||
#include <gui/view_port.h>
|
||||
|
||||
#include <input/input.h>
|
||||
|
||||
#define TAG "EventLoopBlinkTest"
|
||||
|
||||
#define TIMER_COUNT (6U)
|
||||
|
||||
typedef struct {
|
||||
FuriEventLoop* event_loop;
|
||||
FuriMessageQueue* input_queue;
|
||||
FuriEventLoopTimer* timers[TIMER_COUNT];
|
||||
} EventLoopBlinkTestApp;
|
||||
|
||||
static const GpioPin* blink_gpio_pins[] = {
|
||||
&gpio_ext_pa7,
|
||||
&gpio_ext_pa6,
|
||||
&gpio_ext_pa4,
|
||||
&gpio_ext_pb3,
|
||||
&gpio_ext_pb2,
|
||||
&gpio_ext_pc3,
|
||||
};
|
||||
|
||||
static_assert(COUNT_OF(blink_gpio_pins) == TIMER_COUNT);
|
||||
|
||||
static const uint32_t timer_intervals[] = {
|
||||
25,
|
||||
50,
|
||||
100,
|
||||
200,
|
||||
400,
|
||||
800,
|
||||
};
|
||||
|
||||
static_assert(COUNT_OF(timer_intervals) == TIMER_COUNT);
|
||||
|
||||
static void blink_gpio_init(void) {
|
||||
for(size_t i = 0; i < TIMER_COUNT; ++i) {
|
||||
furi_hal_gpio_init_simple(blink_gpio_pins[i], GpioModeOutputPushPull);
|
||||
furi_hal_gpio_write(blink_gpio_pins[i], false);
|
||||
}
|
||||
|
||||
furi_hal_gpio_init_simple(&gpio_ext_pc0, GpioModeOutputPushPull);
|
||||
furi_hal_gpio_write(&gpio_ext_pc0, false);
|
||||
}
|
||||
|
||||
static void blink_gpio_deinit(void) {
|
||||
for(size_t i = 0; i < TIMER_COUNT; ++i) {
|
||||
furi_hal_gpio_write(blink_gpio_pins[i], false);
|
||||
furi_hal_gpio_init_simple(blink_gpio_pins[i], GpioModeAnalog);
|
||||
}
|
||||
|
||||
furi_hal_gpio_write(&gpio_ext_pc0, false);
|
||||
furi_hal_gpio_init_simple(&gpio_ext_pc0, GpioModeAnalog);
|
||||
}
|
||||
|
||||
static void view_port_draw_callback(Canvas* canvas, void* context) {
|
||||
UNUSED(context);
|
||||
canvas_clear(canvas);
|
||||
elements_text_box(
|
||||
canvas,
|
||||
0,
|
||||
0,
|
||||
canvas_width(canvas),
|
||||
canvas_height(canvas),
|
||||
AlignCenter,
|
||||
AlignCenter,
|
||||
"\e#Event Loop Timers Test\e#\n"
|
||||
"Press buttons\n"
|
||||
"to enable or disable timers\n"
|
||||
"\e#Exit\e# = long press \e#Back\e#",
|
||||
false);
|
||||
}
|
||||
|
||||
static void view_port_input_callback(InputEvent* input_event, void* context) {
|
||||
EventLoopBlinkTestApp* app = context;
|
||||
furi_message_queue_put(app->input_queue, input_event, 0);
|
||||
}
|
||||
|
||||
static bool input_queue_callback(FuriMessageQueue* queue, void* context) {
|
||||
EventLoopBlinkTestApp* app = context;
|
||||
|
||||
InputEvent event;
|
||||
FuriStatus status = furi_message_queue_get(queue, &event, 0);
|
||||
furi_assert(status == FuriStatusOk);
|
||||
|
||||
if(event.type == InputTypeShort) {
|
||||
const size_t timer_idx = event.key;
|
||||
furi_assert(timer_idx < TIMER_COUNT);
|
||||
|
||||
FuriEventLoopTimer* timer = app->timers[timer_idx];
|
||||
|
||||
if(furi_event_loop_timer_is_running(timer)) {
|
||||
furi_event_loop_timer_stop(timer);
|
||||
} else {
|
||||
furi_event_loop_timer_restart(timer);
|
||||
}
|
||||
|
||||
} else if(event.type == InputTypeLong) {
|
||||
if(event.key == InputKeyBack) {
|
||||
furi_event_loop_stop(app->event_loop);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void blink_timer_callback(void* context) {
|
||||
const GpioPin* gpio = blink_gpio_pins[(size_t)context];
|
||||
furi_hal_gpio_write(gpio, !furi_hal_gpio_read(gpio));
|
||||
}
|
||||
|
||||
static void event_loop_tick_callback(void* context) {
|
||||
UNUSED(context);
|
||||
furi_hal_gpio_write(&gpio_ext_pc0, !furi_hal_gpio_read(&gpio_ext_pc0));
|
||||
}
|
||||
|
||||
int32_t event_loop_blink_test_app(void* arg) {
|
||||
UNUSED(arg);
|
||||
|
||||
blink_gpio_init();
|
||||
|
||||
EventLoopBlinkTestApp app;
|
||||
|
||||
app.event_loop = furi_event_loop_alloc();
|
||||
app.input_queue = furi_message_queue_alloc(3, sizeof(InputEvent));
|
||||
|
||||
for(size_t i = 0; i < TIMER_COUNT; ++i) {
|
||||
app.timers[i] = furi_event_loop_timer_alloc(
|
||||
app.event_loop, blink_timer_callback, FuriEventLoopTimerTypePeriodic, (void*)i);
|
||||
furi_event_loop_timer_start(app.timers[i], timer_intervals[i]);
|
||||
}
|
||||
|
||||
ViewPort* view_port = view_port_alloc();
|
||||
view_port_draw_callback_set(view_port, view_port_draw_callback, &app);
|
||||
view_port_input_callback_set(view_port, view_port_input_callback, &app);
|
||||
|
||||
Gui* gui = furi_record_open(RECORD_GUI);
|
||||
gui_add_view_port(gui, view_port, GuiLayerFullscreen);
|
||||
|
||||
furi_event_loop_tick_set(app.event_loop, 500, event_loop_tick_callback, &app);
|
||||
furi_event_loop_message_queue_subscribe(
|
||||
app.event_loop, app.input_queue, FuriEventLoopEventIn, input_queue_callback, &app);
|
||||
|
||||
furi_event_loop_run(app.event_loop);
|
||||
|
||||
gui_remove_view_port(gui, view_port);
|
||||
view_port_free(view_port);
|
||||
|
||||
furi_record_close(RECORD_GUI);
|
||||
|
||||
furi_event_loop_message_queue_unsubscribe(app.event_loop, app.input_queue);
|
||||
furi_message_queue_free(app.input_queue);
|
||||
|
||||
for(size_t i = 0; i < TIMER_COUNT; ++i) {
|
||||
furi_event_loop_timer_free(app.timers[i]);
|
||||
}
|
||||
|
||||
furi_event_loop_free(app.event_loop);
|
||||
|
||||
blink_gpio_deinit();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -40,11 +40,11 @@
|
||||
|
||||
#define TAG "ExpansionTest"
|
||||
|
||||
#define TEST_DIR_PATH EXT_PATH(TAG)
|
||||
#define TEST_DIR_PATH EXT_PATH(TAG)
|
||||
#define TEST_FILE_NAME "test.txt"
|
||||
#define TEST_FILE_PATH EXT_PATH(TAG "/" TEST_FILE_NAME)
|
||||
|
||||
#define HOST_SERIAL_ID (FuriHalSerialIdLpuart)
|
||||
#define HOST_SERIAL_ID (FuriHalSerialIdLpuart)
|
||||
#define MODULE_SERIAL_ID (FuriHalSerialIdUsart)
|
||||
|
||||
#define RECEIVE_BUFFER_SIZE (sizeof(ExpansionFrame) + sizeof(ExpansionFrameChecksum))
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#include <furi.h>
|
||||
|
||||
#define DEFAULT_PATH "/"
|
||||
#define EXTENSION "*"
|
||||
#define EXTENSION "*"
|
||||
|
||||
bool file_browser_scene_browser_on_event(void* context, SceneManagerEvent event) {
|
||||
UNUSED(context);
|
||||
|
||||
@@ -78,4 +78,4 @@ int32_t lfrfid_debug_app(void* p) {
|
||||
lfrfid_debug_free(app);
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <toolbox/args.h>
|
||||
|
||||
#define TAG "SpeakerDebug"
|
||||
|
||||
#define CLI_COMMAND "speaker_debug"
|
||||
|
||||
typedef enum {
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
#include <furi_hal.h>
|
||||
|
||||
#define SUBGHZ_TEST_VERSION_APP "0.1"
|
||||
#define SUBGHZ_TEST_DEVELOPED "SkorP"
|
||||
#define SUBGHZ_TEST_GITHUB "https://github.com/flipperdevices/flipperzero-firmware"
|
||||
#define SUBGHZ_TEST_DEVELOPED "SkorP"
|
||||
#define SUBGHZ_TEST_GITHUB "https://github.com/flipperdevices/flipperzero-firmware"
|
||||
|
||||
typedef enum {
|
||||
SubGhzTestViewVariableItemList,
|
||||
|
||||
@@ -241,4 +241,4 @@ uint8_t subghz_protocol_blocks_xor_bytes(uint8_t const message[], size_t size) {
|
||||
result ^= message[i];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
(value) &= ~(_one << (bit)); \
|
||||
})
|
||||
#define bit_write(value, bit, bitvalue) (bitvalue ? bit_set(value, bit) : bit_clear(value, bit))
|
||||
#define DURATION_DIFF(x, y) (((x) < (y)) ? ((y) - (x)) : ((x) - (y)))
|
||||
#define DURATION_DIFF(x, y) (((x) < (y)) ? ((y) - (x)) : ((x) - (y)))
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
||||
@@ -9,13 +9,13 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#define SUBGHZ_PT_SHORT 300
|
||||
#define SUBGHZ_PT_LONG (SUBGHZ_PT_SHORT * 3)
|
||||
#define SUBGHZ_PT_GUARD (SUBGHZ_PT_SHORT * 30)
|
||||
#define SUBGHZ_PT_SHORT 300
|
||||
#define SUBGHZ_PT_LONG (SUBGHZ_PT_SHORT * 3)
|
||||
#define SUBGHZ_PT_GUARD (SUBGHZ_PT_SHORT * 30)
|
||||
#define SUBGHZ_PT_COUNT_KEY_433 9
|
||||
#define SUBGHZ_PT_TIMEOUT_433 900
|
||||
#define SUBGHZ_PT_TIMEOUT_433 900
|
||||
#define SUBGHZ_PT_COUNT_KEY_868 9
|
||||
#define SUBGHZ_PT_TIMEOUT_868 14000
|
||||
#define SUBGHZ_PT_TIMEOUT_868 14000
|
||||
|
||||
#define TAG "SubGhzProtocolPrinceton"
|
||||
|
||||
|
||||
@@ -9,9 +9,10 @@
|
||||
#include <notification/notification.h>
|
||||
#include <notification/notification_messages.h>
|
||||
|
||||
#define LINES_ON_SCREEN 6
|
||||
#define COLUMNS_ON_SCREEN 21
|
||||
#define TAG "UartEcho"
|
||||
|
||||
#define LINES_ON_SCREEN 6
|
||||
#define COLUMNS_ON_SCREEN 21
|
||||
#define DEFAULT_BAUD_RATE 230400
|
||||
|
||||
typedef struct UartDumpModel UartDumpModel;
|
||||
@@ -147,7 +148,7 @@ static void uart_echo_push_to_list(UartDumpModel* model, const char data) {
|
||||
bool new_string_needed = false;
|
||||
if(furi_string_size(model->list[model->line]->text) >= COLUMNS_ON_SCREEN) {
|
||||
new_string_needed = true;
|
||||
} else if((data == '\n' || data == '\r')) {
|
||||
} else if(data == '\n' || data == '\r') {
|
||||
// pack line breaks
|
||||
if(model->last_char != '\n' && model->last_char != '\r') {
|
||||
new_string_needed = true;
|
||||
@@ -206,8 +207,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) {
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,71 @@
|
||||
Filetype: Flipper NFC device
|
||||
Version: 4
|
||||
# Device type can be ISO14443-3A, ISO14443-3B, ISO14443-4A, ISO14443-4B, ISO15693-3, FeliCa, NTAG/Ultralight, Mifare Classic, Mifare DESFire, SLIX, ST25TB
|
||||
Device type: NTAG/Ultralight
|
||||
# UID is common for all formats
|
||||
UID: 04 BA FF CA 4D 5D 80
|
||||
# ISO14443-3A specific data
|
||||
ATQA: 00 44
|
||||
SAK: 00
|
||||
# NTAG/Ultralight specific data
|
||||
Data format version: 2
|
||||
NTAG/Ultralight type: Mifare Ultralight C
|
||||
Signature: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||
Mifare version: 00 00 00 00 00 00 00 00
|
||||
Counter 0: 0
|
||||
Tearing 0: 00
|
||||
Counter 1: 0
|
||||
Tearing 1: 00
|
||||
Counter 2: 0
|
||||
Tearing 2: 00
|
||||
Pages total: 48
|
||||
Pages read: 48
|
||||
Page 0: 04 BA FF C9
|
||||
Page 1: CA 4D 5D 80
|
||||
Page 2: 5A 48 00 00
|
||||
Page 3: E1 10 12 00
|
||||
Page 4: 01 03 A0 0C
|
||||
Page 5: 34 03 00 FE
|
||||
Page 6: 00 00 00 00
|
||||
Page 7: 00 00 00 00
|
||||
Page 8: 00 00 00 00
|
||||
Page 9: 00 00 00 00
|
||||
Page 10: 00 00 BE AF
|
||||
Page 11: 00 00 00 00
|
||||
Page 12: 00 00 00 00
|
||||
Page 13: 00 00 00 00
|
||||
Page 14: 00 00 00 00
|
||||
Page 15: 00 00 00 00
|
||||
Page 16: 00 00 00 00
|
||||
Page 17: 00 00 00 00
|
||||
Page 18: 00 00 00 00
|
||||
Page 19: 00 00 00 00
|
||||
Page 20: 00 00 00 00
|
||||
Page 21: 00 00 00 00
|
||||
Page 22: 00 00 00 00
|
||||
Page 23: 00 00 00 00
|
||||
Page 24: 00 00 00 00
|
||||
Page 25: 00 00 00 00
|
||||
Page 26: 00 00 00 00
|
||||
Page 27: 00 00 00 00
|
||||
Page 28: 00 00 00 00
|
||||
Page 29: 00 00 00 00
|
||||
Page 30: 00 00 00 00
|
||||
Page 31: 00 00 00 00
|
||||
Page 32: 00 00 00 00
|
||||
Page 33: 00 00 00 00
|
||||
Page 34: 00 00 00 00
|
||||
Page 35: 00 00 00 00
|
||||
Page 36: 00 00 00 00
|
||||
Page 37: 00 00 00 00
|
||||
Page 38: 00 00 00 00
|
||||
Page 39: 00 00 00 00
|
||||
Page 40: 00 00 00 00
|
||||
Page 41: 00 00 00 00
|
||||
Page 42: 05 00 00 00
|
||||
Page 43: 00 00 00 00
|
||||
Page 44: 00 00 00 00
|
||||
Page 45: 00 00 00 00
|
||||
Page 46: 00 00 00 00
|
||||
Page 47: 00 00 00 00
|
||||
Failed authentication attempts: 0
|
||||
@@ -72,7 +72,7 @@ void test_runner_free(TestRunner* instance) {
|
||||
free(instance);
|
||||
}
|
||||
|
||||
#define TEST_RUNNER_TMP_DIR EXT_PATH(".tmp")
|
||||
#define TEST_RUNNER_TMP_DIR EXT_PATH(".tmp")
|
||||
#define TEST_RUNNER_TMP_UNIT_TESTS_DIR TEST_RUNNER_TMP_DIR "/unit_tests"
|
||||
|
||||
static bool test_runner_run_plugin(TestRunner* instance, const char* path) {
|
||||
|
||||
@@ -9,4 +9,4 @@ TestRunner* test_runner_alloc(Cli* cli, FuriString* args);
|
||||
|
||||
void test_runner_free(TestRunner* isntance);
|
||||
|
||||
void test_runner_run(TestRunner* isntance);
|
||||
void test_runner_run(TestRunner* isntance);
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#include <storage/storage.h>
|
||||
|
||||
#define BT_TEST_KEY_STORAGE_FILE_PATH EXT_PATH("unit_tests/bt_test.keys")
|
||||
#define BT_TEST_NVM_RAM_BUFF_SIZE (507 * 4) // The same as in ble NVM storage
|
||||
#define BT_TEST_NVM_RAM_BUFF_SIZE (507 * 4) // The same as in ble NVM storage
|
||||
|
||||
typedef struct {
|
||||
Storage* storage;
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
#include "../test.h" // IWYU pragma: keep
|
||||
|
||||
#include <toolbox/compress.h>
|
||||
#include <toolbox/md5_calc.h>
|
||||
#include <toolbox/tar/tar_archive.h>
|
||||
#include <toolbox/dir_walk.h>
|
||||
|
||||
#include <furi.h>
|
||||
#include <furi_hal.h>
|
||||
@@ -56,7 +59,7 @@ static void compress_test_reference_comp_decomp() {
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
|
||||
uint8_t* temp_buffer = malloc(1024);
|
||||
Compress* comp = compress_alloc(1024);
|
||||
Compress* comp = compress_alloc(CompressTypeHeatshrink, &compress_config_heatshrink_default);
|
||||
|
||||
size_t encoded_size = 0;
|
||||
mu_assert(
|
||||
@@ -98,7 +101,7 @@ static void compress_test_random_comp_decomp() {
|
||||
// We only fill half of the buffer with random data, so if anything goes wrong, there's no overflow
|
||||
static const size_t src_data_size = src_buffer_size / 2;
|
||||
|
||||
Compress* comp = compress_alloc(src_buffer_size);
|
||||
Compress* comp = compress_alloc(CompressTypeHeatshrink, &compress_config_heatshrink_default);
|
||||
uint8_t* src_buff = malloc(src_buffer_size);
|
||||
uint8_t* encoded_buff = malloc(encoded_buffer_size);
|
||||
uint8_t* decoded_buff = malloc(src_buffer_size);
|
||||
@@ -146,9 +149,200 @@ static void compress_test_random_comp_decomp() {
|
||||
compress_free(comp);
|
||||
}
|
||||
|
||||
static int32_t hs_unpacker_file_read(void* context, uint8_t* buffer, size_t size) {
|
||||
File* file = (File*)context;
|
||||
return storage_file_read(file, buffer, size);
|
||||
}
|
||||
|
||||
static int32_t hs_unpacker_file_write(void* context, uint8_t* buffer, size_t size) {
|
||||
File* file = (File*)context;
|
||||
return storage_file_write(file, buffer, size);
|
||||
}
|
||||
/*
|
||||
Source file was generated with:
|
||||
```python3
|
||||
import random, string
|
||||
random.seed(1337)
|
||||
with open("hsstream.out.bin", "wb") as f:
|
||||
for c in random.choices(string.printable, k=1024):
|
||||
for _ in range(random.randint(1, 10)):
|
||||
f.write(c.encode())
|
||||
```
|
||||
|
||||
It was compressed with heatshrink using the following command:
|
||||
`python3 -m heatshrink2 compress -w 9 -l 4 hsstream.out.bin hsstream.in.bin`
|
||||
*/
|
||||
|
||||
#define HSSTREAM_IN COMPRESS_UNIT_TESTS_PATH("hsstream.in.bin")
|
||||
#define HSSTREAM_OUT COMPRESS_UNIT_TESTS_PATH("hsstream.out.bin")
|
||||
|
||||
static void compress_test_heatshrink_stream() {
|
||||
Storage* api = furi_record_open(RECORD_STORAGE);
|
||||
File* comp_file = storage_file_alloc(api);
|
||||
File* dest_file = storage_file_alloc(api);
|
||||
|
||||
CompressConfigHeatshrink config = {
|
||||
.window_sz2 = 9,
|
||||
.lookahead_sz2 = 4,
|
||||
.input_buffer_sz = 128,
|
||||
};
|
||||
Compress* compress = compress_alloc(CompressTypeHeatshrink, &config);
|
||||
|
||||
do {
|
||||
storage_simply_remove(api, HSSTREAM_OUT);
|
||||
|
||||
mu_assert(
|
||||
storage_file_open(comp_file, HSSTREAM_IN, FSAM_READ, FSOM_OPEN_EXISTING),
|
||||
"Failed to open compressed file");
|
||||
|
||||
mu_assert(
|
||||
storage_file_open(dest_file, HSSTREAM_OUT, FSAM_WRITE, FSOM_OPEN_ALWAYS),
|
||||
"Failed to open decompressed file");
|
||||
|
||||
mu_assert(
|
||||
compress_decode_streamed(
|
||||
compress, hs_unpacker_file_read, comp_file, hs_unpacker_file_write, dest_file),
|
||||
"Decompression failed");
|
||||
|
||||
storage_file_close(dest_file);
|
||||
|
||||
unsigned char md5[16];
|
||||
FS_Error file_error;
|
||||
mu_assert(
|
||||
md5_calc_file(dest_file, HSSTREAM_OUT, md5, &file_error), "Failed to calculate md5");
|
||||
|
||||
const unsigned char expected_md5[16] = {
|
||||
0xa3,
|
||||
0x70,
|
||||
0xe8,
|
||||
0x8b,
|
||||
0xa9,
|
||||
0x42,
|
||||
0x74,
|
||||
0xf4,
|
||||
0xaa,
|
||||
0x12,
|
||||
0x8d,
|
||||
0x41,
|
||||
0xd2,
|
||||
0xb6,
|
||||
0x71,
|
||||
0xc9};
|
||||
mu_assert(memcmp(md5, expected_md5, sizeof(md5)) == 0, "MD5 mismatch after decompression");
|
||||
|
||||
storage_simply_remove(api, HSSTREAM_OUT);
|
||||
} while(false);
|
||||
|
||||
compress_free(compress);
|
||||
storage_file_free(comp_file);
|
||||
storage_file_free(dest_file);
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
}
|
||||
|
||||
#define HS_TAR_PATH COMPRESS_UNIT_TESTS_PATH("test.ths")
|
||||
#define HS_TAR_EXTRACT_PATH COMPRESS_UNIT_TESTS_PATH("tar_out")
|
||||
|
||||
static bool file_counter(const char* name, bool is_dir, void* context) {
|
||||
UNUSED(name);
|
||||
UNUSED(is_dir);
|
||||
int32_t* n_entries = (int32_t*)context;
|
||||
(*n_entries)++;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
Heatshrink tar file contents and MD5 sums:
|
||||
file1.txt: 64295676ceed5cce2d0dcac402e4bda4
|
||||
file2.txt: 188f67f297eedd7bf3d6a4d3c2fc31c4
|
||||
dir/file3.txt: 34d98ad8135ffe502dba374690136d16
|
||||
dir/big_file.txt: ee169c1e1791a4d319dbfaefaa850e98
|
||||
dir/nested_dir/file4.txt: e099fcb2aaa0672375eaedc549247ee6
|
||||
dir/nested_dir/empty_file.txt: d41d8cd98f00b204e9800998ecf8427e
|
||||
|
||||
XOR of all MD5 sums: 92ed5729786d0e1176d047e35f52d376
|
||||
*/
|
||||
|
||||
static void compress_test_heatshrink_tar() {
|
||||
Storage* api = furi_record_open(RECORD_STORAGE);
|
||||
|
||||
TarArchive* archive = tar_archive_alloc(api);
|
||||
FuriString* path = furi_string_alloc();
|
||||
FileInfo fileinfo;
|
||||
File* file = storage_file_alloc(api);
|
||||
|
||||
do {
|
||||
storage_simply_remove_recursive(api, HS_TAR_EXTRACT_PATH);
|
||||
|
||||
mu_assert(storage_simply_mkdir(api, HS_TAR_EXTRACT_PATH), "Failed to create extract dir");
|
||||
|
||||
mu_assert(
|
||||
tar_archive_get_mode_for_path(HS_TAR_PATH) == TarOpenModeReadHeatshrink,
|
||||
"Invalid mode for heatshrink tar");
|
||||
|
||||
mu_assert(
|
||||
tar_archive_open(archive, HS_TAR_PATH, TarOpenModeReadHeatshrink),
|
||||
"Failed to open heatshrink tar");
|
||||
|
||||
int32_t n_entries = 0;
|
||||
tar_archive_set_file_callback(archive, file_counter, &n_entries);
|
||||
|
||||
mu_assert(
|
||||
tar_archive_unpack_to(archive, HS_TAR_EXTRACT_PATH, NULL),
|
||||
"Failed to unpack heatshrink tar");
|
||||
|
||||
mu_assert(n_entries == 9, "Invalid number of entries in heatshrink tar");
|
||||
|
||||
uint8_t md5_total[16] = {0}, md5_file[16];
|
||||
|
||||
DirWalk* dir_walk = dir_walk_alloc(api);
|
||||
mu_assert(dir_walk_open(dir_walk, HS_TAR_EXTRACT_PATH), "Failed to open dirwalk");
|
||||
while(dir_walk_read(dir_walk, path, &fileinfo) == DirWalkOK) {
|
||||
if(file_info_is_dir(&fileinfo)) {
|
||||
continue;
|
||||
}
|
||||
mu_assert(
|
||||
md5_calc_file(file, furi_string_get_cstr(path), md5_file, NULL),
|
||||
"Failed to calc md5");
|
||||
|
||||
for(size_t i = 0; i < 16; i++) {
|
||||
md5_total[i] ^= md5_file[i];
|
||||
}
|
||||
}
|
||||
dir_walk_free(dir_walk);
|
||||
|
||||
static const unsigned char expected_md5[16] = {
|
||||
0x92,
|
||||
0xed,
|
||||
0x57,
|
||||
0x29,
|
||||
0x78,
|
||||
0x6d,
|
||||
0x0e,
|
||||
0x11,
|
||||
0x76,
|
||||
0xd0,
|
||||
0x47,
|
||||
0xe3,
|
||||
0x5f,
|
||||
0x52,
|
||||
0xd3,
|
||||
0x76};
|
||||
mu_assert(memcmp(md5_total, expected_md5, sizeof(md5_total)) == 0, "MD5 mismatch");
|
||||
|
||||
storage_simply_remove_recursive(api, HS_TAR_EXTRACT_PATH);
|
||||
} while(false);
|
||||
|
||||
storage_file_free(file);
|
||||
furi_string_free(path);
|
||||
tar_archive_free(archive);
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
}
|
||||
|
||||
MU_TEST_SUITE(test_compress) {
|
||||
MU_RUN_TEST(compress_test_random_comp_decomp);
|
||||
MU_RUN_TEST(compress_test_reference_comp_decomp);
|
||||
MU_RUN_TEST(compress_test_heatshrink_stream);
|
||||
MU_RUN_TEST(compress_test_heatshrink_tar);
|
||||
}
|
||||
|
||||
int run_minunit_test_compress(void) {
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
|
||||
#include <expansion/expansion_protocol.h>
|
||||
|
||||
#define EXPANSION_TEST_GARBAGE_MAGIC (0xB19AF)
|
||||
#define EXPANSION_TEST_GARBAGE_BUF_SIZE (0x100U)
|
||||
#define EXPANSION_TEST_GARBAGE_MAGIC (0xB19AF)
|
||||
#define EXPANSION_TEST_GARBAGE_BUF_SIZE (0x100U)
|
||||
#define EXPANSION_TEST_GARBAGE_ITERATIONS (100U)
|
||||
|
||||
MU_TEST(test_expansion_encoded_size) {
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#include "../test.h" // IWYU pragma: keep
|
||||
|
||||
#define TEST_DIR_NAME EXT_PATH(".tmp/unit_tests/ff")
|
||||
#define TEST_DIR TEST_DIR_NAME "/"
|
||||
#define TEST_DIR TEST_DIR_NAME "/"
|
||||
|
||||
static const char* test_filetype = "Flipper File test";
|
||||
static const uint32_t test_version = 666;
|
||||
|
||||
@@ -5,11 +5,11 @@
|
||||
#include <lp5562_reg.h>
|
||||
#include "../test.h" // IWYU pragma: keep
|
||||
|
||||
#define DATA_SIZE 4
|
||||
#define EEPROM_ADDRESS 0b10101000
|
||||
#define EEPROM_ADDRESS_HIGH (EEPROM_ADDRESS | 0b10)
|
||||
#define EEPROM_SIZE 512
|
||||
#define EEPROM_PAGE_SIZE 16
|
||||
#define DATA_SIZE 4
|
||||
#define EEPROM_ADDRESS 0b10101000
|
||||
#define EEPROM_ADDRESS_HIGH (EEPROM_ADDRESS | 0b10)
|
||||
#define EEPROM_SIZE 512
|
||||
#define EEPROM_PAGE_SIZE 16
|
||||
#define EEPROM_WRITE_DELAY_MS 6
|
||||
|
||||
static void furi_hal_i2c_int_setup(void) {
|
||||
@@ -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) {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#include <common/infrared_common_i.h>
|
||||
#include "../test.h" // IWYU pragma: keep
|
||||
|
||||
#define IR_TEST_FILES_DIR EXT_PATH("unit_tests/infrared/")
|
||||
#define IR_TEST_FILES_DIR EXT_PATH("unit_tests/infrared/")
|
||||
#define IR_TEST_FILE_PREFIX "test_"
|
||||
#define IR_TEST_FILE_SUFFIX ".irtest"
|
||||
|
||||
|
||||
@@ -6,9 +6,8 @@
|
||||
|
||||
#define LF_RFID_READ_TIMING_MULTIPLIER 8
|
||||
|
||||
#define EM_TEST_DATA \
|
||||
{ 0x58, 0x00, 0x85, 0x64, 0x02 }
|
||||
#define EM_TEST_DATA_SIZE 5
|
||||
#define EM_TEST_DATA {0x58, 0x00, 0x85, 0x64, 0x02}
|
||||
#define EM_TEST_DATA_SIZE 5
|
||||
#define EM_TEST_EMULATION_TIMINGS_COUNT (64 * 2)
|
||||
|
||||
const int8_t em_test_timings[EM_TEST_EMULATION_TIMINGS_COUNT] = {
|
||||
@@ -21,9 +20,8 @@ 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_SIZE 3
|
||||
#define HID10301_TEST_DATA {0x8D, 0x48, 0xA8}
|
||||
#define HID10301_TEST_DATA_SIZE 3
|
||||
#define HID10301_TEST_EMULATION_TIMINGS_COUNT (541 * 2)
|
||||
|
||||
const int8_t hid10301_test_timings[HID10301_TEST_EMULATION_TIMINGS_COUNT] = {
|
||||
@@ -71,9 +69,8 @@ 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_SIZE 4
|
||||
#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)
|
||||
|
||||
const int8_t ioprox_xsf_test_timings[IOPROX_XSF_TEST_EMULATION_TIMINGS_COUNT] = {
|
||||
@@ -116,9 +113,8 @@ 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_SIZE 4
|
||||
#define INDALA26_TEST_DATA {0x3B, 0x73, 0x64, 0xA8}
|
||||
#define INDALA26_TEST_DATA_SIZE 4
|
||||
|
||||
const int8_t indala26_test_timings[INDALA26_EMULATION_TIMINGS_COUNT] = {
|
||||
1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1, 1, -1,
|
||||
@@ -209,9 +205,8 @@ 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_SIZE 11
|
||||
#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)
|
||||
|
||||
const int8_t fdxb_test_timings[FDXB_TEST_EMULATION_TIMINGS_COUNT] = {
|
||||
|
||||
@@ -71,7 +71,7 @@ extern "C" {
|
||||
/* Maximum length of last message */
|
||||
#define MINUNIT_MESSAGE_LEN 1024
|
||||
/* Accuracy with which floats are compared */
|
||||
#define MINUNIT_EPSILON 1E-12
|
||||
#define MINUNIT_EPSILON 1E-12
|
||||
|
||||
#include "minunit_vars_ex.h"
|
||||
|
||||
@@ -84,9 +84,9 @@ void minunit_print_fail(const char* error);
|
||||
void minunit_printf_warning(const char* format, ...);
|
||||
|
||||
/* Definitions */
|
||||
#define MU_TEST(method_name) static void method_name(void)
|
||||
#define MU_TEST(method_name) static void method_name(void)
|
||||
#define MU_TEST_1(method_name, arg_1) static void method_name(arg_1)
|
||||
#define MU_TEST_SUITE(suite_name) static void suite_name(void)
|
||||
#define MU_TEST_SUITE(suite_name) static void suite_name(void)
|
||||
|
||||
#define MU__SAFE_BLOCK(block) \
|
||||
do { \
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
|
||||
#define TAG "NfcTest"
|
||||
|
||||
#define NFC_TEST_NFC_DEV_PATH EXT_PATH("unit_tests/nfc/nfc_device_test.nfc")
|
||||
#define NFC_TEST_NFC_DEV_PATH EXT_PATH("unit_tests/nfc/nfc_device_test.nfc")
|
||||
#define NFC_APP_MF_CLASSIC_DICT_UNIT_TEST_PATH EXT_PATH("unit_tests/mf_dict.nfc")
|
||||
|
||||
#define NFC_TEST_FLAG_WORKER_DONE (1)
|
||||
@@ -286,6 +286,10 @@ MU_TEST(mf_ultralight_21_reader) {
|
||||
mf_ultralight_reader_test(EXT_PATH("unit_tests/nfc/Ultralight_21.nfc"));
|
||||
}
|
||||
|
||||
MU_TEST(mf_ultralight_c_reader) {
|
||||
mf_ultralight_reader_test(EXT_PATH("unit_tests/nfc/Ultralight_C.nfc"));
|
||||
}
|
||||
|
||||
MU_TEST(ntag_215_reader) {
|
||||
mf_ultralight_reader_test(EXT_PATH("unit_tests/nfc/Ntag215.nfc"));
|
||||
}
|
||||
@@ -828,6 +832,7 @@ MU_TEST_SUITE(nfc) {
|
||||
MU_RUN_TEST(ntag_215_reader);
|
||||
MU_RUN_TEST(ntag_216_reader);
|
||||
MU_RUN_TEST(ntag_213_locked_reader);
|
||||
MU_RUN_TEST(mf_ultralight_c_reader);
|
||||
|
||||
MU_RUN_TEST(mf_ultralight_write);
|
||||
|
||||
|
||||
@@ -43,14 +43,15 @@ typedef struct {
|
||||
static RpcSessionContext rpc_session[TEST_RPC_SESSIONS];
|
||||
|
||||
#define TAG "UnitTestsRpc"
|
||||
#define MAX_RECEIVE_OUTPUT_TIMEOUT 3000
|
||||
#define MAX_NAME_LENGTH 255
|
||||
#define MAX_DATA_SIZE 512u // have to be exact as in rpc_storage.c
|
||||
#define TEST_DIR_NAME EXT_PATH(".tmp/unit_tests/rpc")
|
||||
#define TEST_DIR TEST_DIR_NAME "/"
|
||||
#define MD5SUM_SIZE 16
|
||||
|
||||
#define PING_REQUEST 0
|
||||
#define MAX_RECEIVE_OUTPUT_TIMEOUT 3000
|
||||
#define MAX_NAME_LENGTH 255
|
||||
#define MAX_DATA_SIZE 512u // have to be exact as in rpc_storage.c
|
||||
#define TEST_DIR_NAME EXT_PATH(".tmp/unit_tests/rpc")
|
||||
#define TEST_DIR TEST_DIR_NAME "/"
|
||||
#define MD5SUM_SIZE 16
|
||||
|
||||
#define PING_REQUEST 0
|
||||
#define PING_RESPONSE 1
|
||||
#define WRITE_REQUEST 0
|
||||
#define READ_RESPONSE 1
|
||||
@@ -554,7 +555,7 @@ static bool test_rpc_pb_stream_read(pb_istream_t* istream, pb_byte_t* buf, size_
|
||||
time_left = MAX(time_left, 0);
|
||||
bytes_received =
|
||||
furi_stream_buffer_receive(session_context->output_stream, buf, count, time_left);
|
||||
return (count == bytes_received);
|
||||
return count == bytes_received;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -971,7 +972,7 @@ MU_TEST(test_storage_info) {
|
||||
}
|
||||
|
||||
#define TEST_DIR_STAT_NAME TEST_DIR "stat_dir"
|
||||
#define TEST_DIR_STAT TEST_DIR_STAT_NAME "/"
|
||||
#define TEST_DIR_STAT TEST_DIR_STAT_NAME "/"
|
||||
MU_TEST(test_storage_stat) {
|
||||
test_create_dir(TEST_DIR_STAT_NAME);
|
||||
test_create_file(TEST_DIR_STAT "empty.txt", 0);
|
||||
@@ -1212,7 +1213,7 @@ static void test_storage_delete_run(
|
||||
}
|
||||
|
||||
#define TEST_DIR_RMRF_NAME TEST_DIR "rmrf_test"
|
||||
#define TEST_DIR_RMRF TEST_DIR_RMRF_NAME "/"
|
||||
#define TEST_DIR_RMRF TEST_DIR_RMRF_NAME "/"
|
||||
MU_TEST(test_storage_delete_recursive) {
|
||||
test_create_dir(TEST_DIR_RMRF_NAME);
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#define UNIT_TESTS_PATH(path) EXT_PATH("unit_tests/" path)
|
||||
|
||||
#define STORAGE_LOCKED_FILE EXT_PATH("locked_file.test")
|
||||
#define STORAGE_LOCKED_DIR STORAGE_INT_PATH_PREFIX
|
||||
#define STORAGE_LOCKED_DIR STORAGE_INT_PATH_PREFIX
|
||||
|
||||
#define STORAGE_TEST_DIR UNIT_TESTS_PATH("test_dir")
|
||||
|
||||
|
||||
@@ -11,13 +11,14 @@
|
||||
#include <lib/subghz/devices/cc1101_configs.h>
|
||||
|
||||
#define TAG "SubGhzTest"
|
||||
#define KEYSTORE_DIR_NAME EXT_PATH("subghz/assets/keeloq_mfcodes")
|
||||
#define CAME_ATOMO_DIR_NAME EXT_PATH("subghz/assets/came_atomo")
|
||||
#define NICE_FLOR_S_DIR_NAME EXT_PATH("subghz/assets/nice_flor_s")
|
||||
#define ALUTECH_AT_4N_DIR_NAME EXT_PATH("subghz/assets/alutech_at_4n")
|
||||
#define TEST_RANDOM_DIR_NAME EXT_PATH("unit_tests/subghz/test_random_raw.sub")
|
||||
|
||||
#define KEYSTORE_DIR_NAME EXT_PATH("subghz/assets/keeloq_mfcodes")
|
||||
#define CAME_ATOMO_DIR_NAME EXT_PATH("subghz/assets/came_atomo")
|
||||
#define NICE_FLOR_S_DIR_NAME EXT_PATH("subghz/assets/nice_flor_s")
|
||||
#define ALUTECH_AT_4N_DIR_NAME EXT_PATH("subghz/assets/alutech_at_4n")
|
||||
#define TEST_RANDOM_DIR_NAME EXT_PATH("unit_tests/subghz/test_random_raw.sub")
|
||||
#define TEST_RANDOM_COUNT_PARSE 329
|
||||
#define TEST_TIMEOUT 10000
|
||||
#define TEST_TIMEOUT 10000
|
||||
|
||||
static SubGhzEnvironment* environment_handler;
|
||||
static SubGhzReceiver* receiver_handler;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
#include <flipper_application/flipper_application.h>
|
||||
|
||||
#define APPID "UnitTest"
|
||||
#define APPID "UnitTest"
|
||||
#define API_VERSION (0u)
|
||||
|
||||
typedef struct {
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
#include <input/input.h>
|
||||
|
||||
#define MOUSE_MOVE_SHORT 5
|
||||
#define MOUSE_MOVE_LONG 20
|
||||
#define MOUSE_MOVE_LONG 20
|
||||
|
||||
typedef enum {
|
||||
EventTypeInput,
|
||||
|
||||
@@ -17,18 +17,18 @@
|
||||
|
||||
#define TAG "SubGhzDeviceCc1101Ext"
|
||||
|
||||
#define SUBGHZ_DEVICE_CC1101_EXT_TX_GPIO (&gpio_ext_pb2)
|
||||
#define SUBGHZ_DEVICE_CC1101_EXT_E07_AMP_GPIO &gpio_ext_pc3
|
||||
#define SUBGHZ_DEVICE_CC1101_EXT_TX_GPIO (&gpio_ext_pb2)
|
||||
#define SUBGHZ_DEVICE_CC1101_EXT_E07_AMP_GPIO &gpio_ext_pc3
|
||||
#define SUBGHZ_DEVICE_CC1101_EXT_FORCE_DANGEROUS_RANGE false
|
||||
|
||||
#define SUBGHZ_DEVICE_CC1101_CONFIG_VER 1
|
||||
|
||||
/* DMA Channels definition */
|
||||
#define SUBGHZ_DEVICE_CC1101_EXT_DMA (DMA2)
|
||||
#define SUBGHZ_DEVICE_CC1101_EXT_DMA (DMA2)
|
||||
#define SUBGHZ_DEVICE_CC1101_EXT_DMA_CH3_CHANNEL (LL_DMA_CHANNEL_3)
|
||||
#define SUBGHZ_DEVICE_CC1101_EXT_DMA_CH4_CHANNEL (LL_DMA_CHANNEL_4)
|
||||
#define SUBGHZ_DEVICE_CC1101_EXT_DMA_CH5_CHANNEL (LL_DMA_CHANNEL_5)
|
||||
#define SUBGHZ_DEVICE_CC1101_EXT_DMA_CH3_IRQ (FuriHalInterruptIdDma2Ch3)
|
||||
#define SUBGHZ_DEVICE_CC1101_EXT_DMA_CH3_IRQ (FuriHalInterruptIdDma2Ch3)
|
||||
#define SUBGHZ_DEVICE_CC1101_EXT_DMA_CH3_DEF \
|
||||
SUBGHZ_DEVICE_CC1101_EXT_DMA, SUBGHZ_DEVICE_CC1101_EXT_DMA_CH3_CHANNEL
|
||||
#define SUBGHZ_DEVICE_CC1101_EXT_DMA_CH4_DEF \
|
||||
@@ -390,7 +390,7 @@ bool subghz_device_cc1101_ext_is_rx_data_crc_valid(void) {
|
||||
cc1101_read_reg(
|
||||
subghz_device_cc1101_ext->spi_bus_handle, CC1101_STATUS_LQI | CC1101_BURST, data);
|
||||
furi_hal_spi_release(subghz_device_cc1101_ext->spi_bus_handle);
|
||||
if(((data[0] >> 7) & 0x01)) {
|
||||
if((data[0] >> 7) & 0x01) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
@@ -879,9 +879,8 @@ bool subghz_device_cc1101_ext_start_async_tx(SubGhzDeviceCC1101ExtCallback callb
|
||||
}
|
||||
|
||||
bool subghz_device_cc1101_ext_is_async_tx_complete(void) {
|
||||
return (
|
||||
(subghz_device_cc1101_ext->state == SubGhzDeviceCC1101ExtStateAsyncTx) &&
|
||||
(LL_TIM_GetAutoReload(TIM17) == 0));
|
||||
return (subghz_device_cc1101_ext->state == SubGhzDeviceCC1101ExtStateAsyncTx) &&
|
||||
(LL_TIM_GetAutoReload(TIM17) == 0);
|
||||
}
|
||||
|
||||
void subghz_device_cc1101_ext_stop_async_tx(void) {
|
||||
|
||||
@@ -107,4 +107,4 @@ static const FlipperAppPluginDescriptor subghz_device_cc1101_ext_descriptor = {
|
||||
|
||||
const FlipperAppPluginDescriptor* subghz_device_cc1101_ext_ep(void) {
|
||||
return &subghz_device_cc1101_ext_descriptor;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#define TAG "ble_beacon_app"
|
||||
#define TAG "BleBeaconApp"
|
||||
|
||||
static bool ble_beacon_app_custom_event_callback(void* context, uint32_t event) {
|
||||
furi_assert(context);
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#define PLUGIN_APP_ID "example_plugins"
|
||||
#define PLUGIN_APP_ID "example_plugins"
|
||||
#define PLUGIN_API_VERSION 1
|
||||
|
||||
typedef struct {
|
||||
|
||||
@@ -6,4 +6,4 @@
|
||||
* Resolver interface with private application's symbols.
|
||||
* Implementation is contained in app_api_table.c
|
||||
*/
|
||||
extern const ElfApiInterface* const application_api_interface;
|
||||
extern const ElfApiInterface* const application_api_interface;
|
||||
|
||||
@@ -10,4 +10,4 @@ static constexpr auto app_api_table = sort(create_array_t<sym_entry>(
|
||||
API_METHOD(app_api_accumulator_get, uint32_t, ()),
|
||||
API_METHOD(app_api_accumulator_add, void, (uint32_t)),
|
||||
API_METHOD(app_api_accumulator_sub, void, (uint32_t)),
|
||||
API_METHOD(app_api_accumulator_mul, void, (uint32_t))));
|
||||
API_METHOD(app_api_accumulator_mul, void, (uint32_t))));
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#define PLUGIN_APP_ID "example_plugins_advanced"
|
||||
#define PLUGIN_APP_ID "example_plugins_advanced"
|
||||
#define PLUGIN_API_VERSION 1
|
||||
|
||||
typedef struct {
|
||||
|
||||
@@ -25,15 +25,15 @@
|
||||
#include <furi_hal_power.h>
|
||||
|
||||
#define UPDATE_PERIOD_MS 1000UL
|
||||
#define TEXT_STORE_SIZE 64U
|
||||
#define TEXT_STORE_SIZE 64U
|
||||
|
||||
#define DS18B20_CMD_SKIP_ROM 0xccU
|
||||
#define DS18B20_CMD_CONVERT 0x44U
|
||||
#define DS18B20_CMD_SKIP_ROM 0xccU
|
||||
#define DS18B20_CMD_CONVERT 0x44U
|
||||
#define DS18B20_CMD_READ_SCRATCHPAD 0xbeU
|
||||
|
||||
#define DS18B20_CFG_RESOLUTION_POS 5U
|
||||
#define DS18B20_CFG_RESOLUTION_POS 5U
|
||||
#define DS18B20_CFG_RESOLUTION_MASK 0x03U
|
||||
#define DS18B20_DECIMAL_PART_MASK 0x0fU
|
||||
#define DS18B20_DECIMAL_PART_MASK 0x0fU
|
||||
|
||||
#define DS18B20_SIGN_MASK 0xf0U
|
||||
|
||||
|
||||
@@ -43,4 +43,4 @@ struct ArchiveApp {
|
||||
char file_extension[MAX_EXT_LEN + 1];
|
||||
};
|
||||
|
||||
void archive_show_loading_popup(ArchiveApp* context, bool show);
|
||||
void archive_show_loading_popup(ArchiveApp* context, bool show);
|
||||
|
||||
@@ -344,7 +344,7 @@ bool archive_is_home(ArchiveBrowserView* browser) {
|
||||
}
|
||||
|
||||
const char* default_path = archive_get_default_path(archive_get_tab(browser));
|
||||
return (furi_string_cmp_str(browser->path, default_path) == 0);
|
||||
return furi_string_cmp_str(browser->path, default_path) == 0;
|
||||
}
|
||||
|
||||
const char* archive_get_name(ArchiveBrowserView* browser) {
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
#include "../archive_i.h"
|
||||
#include <storage/storage.h>
|
||||
|
||||
#define TAB_LEFT InputKeyLeft // Default tab switch direction
|
||||
#define TAB_DEFAULT ArchiveTabFavorites // Start tab
|
||||
#define TAB_LEFT InputKeyLeft // Default tab switch direction
|
||||
#define TAB_DEFAULT ArchiveTabFavorites // Start tab
|
||||
#define FILE_LIST_BUF_LEN 50
|
||||
|
||||
static const char* tab_default_paths[] = {
|
||||
@@ -67,7 +67,7 @@ static inline const char* archive_get_default_path(ArchiveTabEnum tab) {
|
||||
}
|
||||
|
||||
inline bool archive_is_known_app(ArchiveFileTypeEnum type) {
|
||||
return (type != ArchiveFileTypeFolder && type != ArchiveFileTypeUnknown);
|
||||
return type != ArchiveFileTypeFolder && type != ArchiveFileTypeUnknown;
|
||||
}
|
||||
|
||||
bool archive_is_item_in_array(ArchiveBrowserViewModel* model, uint32_t idx);
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
#include <storage/storage.h>
|
||||
|
||||
#define ARCHIVE_FAV_PATH ANY_PATH("favorites.txt")
|
||||
#define ARCHIVE_FAV_PATH ANY_PATH("favorites.txt")
|
||||
#define ARCHIVE_FAV_TEMP_PATH ANY_PATH("favorites.tmp")
|
||||
|
||||
uint16_t archive_favorites_count(void* context);
|
||||
|
||||
@@ -47,4 +47,4 @@ static void
|
||||
obj->text = furi_string_alloc_set(text);
|
||||
obj->event = event;
|
||||
}
|
||||
#pragma GCC diagnostic pop
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
#define TAG "ArchiveSceneBrowser"
|
||||
|
||||
#define SCENE_STATE_DEFAULT (0)
|
||||
#define SCENE_STATE_DEFAULT (0)
|
||||
#define SCENE_STATE_NEED_REFRESH (1)
|
||||
|
||||
static const char* archive_get_flipper_app_name(ArchiveFileTypeEnum file_type) {
|
||||
|
||||
@@ -3,4 +3,4 @@ ADD_SCENE(archive, rename, Rename)
|
||||
ADD_SCENE(archive, delete, Delete)
|
||||
ADD_SCENE(archive, info, Info)
|
||||
ADD_SCENE(archive, show, Show)
|
||||
ADD_SCENE(archive, new_dir, NewDir)
|
||||
ADD_SCENE(archive, new_dir, NewDir)
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#include "../helpers/archive_browser.h"
|
||||
|
||||
#define SCENE_DELETE_CUSTOM_EVENT (0UL)
|
||||
#define MAX_TEXT_INPUT_LEN 22
|
||||
#define MAX_TEXT_INPUT_LEN 22
|
||||
|
||||
void archive_scene_delete_widget_callback(GuiButtonType result, InputType type, void* context) {
|
||||
furi_assert(context);
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#define TAG "Archive"
|
||||
|
||||
#define SCENE_RENAME_CUSTOM_EVENT (0UL)
|
||||
#define MAX_TEXT_INPUT_LEN 22
|
||||
#define MAX_TEXT_INPUT_LEN 22
|
||||
|
||||
void archive_scene_rename_text_input_callback(void* context) {
|
||||
ArchiveApp* archive = (ArchiveApp*)context;
|
||||
|
||||
@@ -4,9 +4,9 @@
|
||||
#include "archive_browser_view.h"
|
||||
#include "../helpers/archive_browser.h"
|
||||
|
||||
#define TAG "Archive"
|
||||
#define TAG "Archive"
|
||||
#define SCROLL_INTERVAL (333)
|
||||
#define SCROLL_DELAY (2)
|
||||
#define SCROLL_DELAY (2)
|
||||
|
||||
static const char* ArchiveTabNames[] = {
|
||||
[ArchiveTabFavorites] = "Favorites",
|
||||
@@ -753,4 +753,4 @@ void archive_browser_clipboard_reset(ArchiveBrowserView* browser) {
|
||||
ArchiveBrowserViewModel * model,
|
||||
{ model->clipboard_mode = CLIPBOARD_MODE_OFF; },
|
||||
true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,15 +14,15 @@
|
||||
#include "../helpers/archive_favorites.h"
|
||||
#include "gui/modules/file_browser_worker.h"
|
||||
|
||||
#define MAX_LEN_PX 110
|
||||
#define MAX_LEN_PX 110
|
||||
#define MAX_NAME_LEN 255
|
||||
#define MAX_EXT_LEN 6
|
||||
#define MAX_EXT_LEN 6
|
||||
#define FRAME_HEIGHT 12
|
||||
#define MENU_ITEMS 5u
|
||||
#define MOVE_OFFSET 5u
|
||||
#define MENU_ITEMS 5u
|
||||
#define MOVE_OFFSET 5u
|
||||
|
||||
#define CLIPBOARD_MODE_OFF (0U)
|
||||
#define CLIPBOARD_MODE_CUT (1U)
|
||||
#define CLIPBOARD_MODE_OFF (0U)
|
||||
#define CLIPBOARD_MODE_CUT (1U)
|
||||
#define CLIPBOARD_MODE_COPY (2U)
|
||||
|
||||
typedef enum {
|
||||
|
||||
@@ -5,9 +5,9 @@
|
||||
#include <lib/toolbox/path.h>
|
||||
#include <flipper_format/flipper_format.h>
|
||||
|
||||
#define BAD_USB_SETTINGS_PATH BAD_USB_APP_BASE_FOLDER "/.badusb.settings"
|
||||
#define BAD_USB_SETTINGS_FILE_TYPE "Flipper BadUSB Settings File"
|
||||
#define BAD_USB_SETTINGS_VERSION 1
|
||||
#define BAD_USB_SETTINGS_PATH BAD_USB_APP_BASE_FOLDER "/.badusb.settings"
|
||||
#define BAD_USB_SETTINGS_FILE_TYPE "Flipper BadUSB Settings File"
|
||||
#define BAD_USB_SETTINGS_VERSION 1
|
||||
#define BAD_USB_SETTINGS_DEFAULT_LAYOUT BAD_USB_APP_PATH_LAYOUT_FOLDER "/en-US.kl"
|
||||
|
||||
static bool bad_usb_app_custom_event_callback(void* context, uint32_t event) {
|
||||
|
||||
@@ -16,10 +16,10 @@
|
||||
#include "views/bad_usb_view.h"
|
||||
#include <furi_hal_usb.h>
|
||||
|
||||
#define BAD_USB_APP_BASE_FOLDER EXT_PATH("badusb")
|
||||
#define BAD_USB_APP_BASE_FOLDER EXT_PATH("badusb")
|
||||
#define BAD_USB_APP_PATH_LAYOUT_FOLDER BAD_USB_APP_BASE_FOLDER "/assets/layouts"
|
||||
#define BAD_USB_APP_SCRIPT_EXTENSION ".txt"
|
||||
#define BAD_USB_APP_LAYOUT_EXTENSION ".kl"
|
||||
#define BAD_USB_APP_SCRIPT_EXTENSION ".txt"
|
||||
#define BAD_USB_APP_LAYOUT_EXTENSION ".kl"
|
||||
|
||||
typedef enum {
|
||||
BadUsbAppErrorNoFiles,
|
||||
@@ -49,4 +49,4 @@ typedef enum {
|
||||
BadUsbAppViewError,
|
||||
BadUsbAppViewWork,
|
||||
BadUsbAppViewConfig,
|
||||
} BadUsbAppView;
|
||||
} BadUsbAppView;
|
||||
|
||||
@@ -223,4 +223,4 @@ void bad_usb_hid_ble_remove_pairing(void) {
|
||||
|
||||
furi_check(bt_profile_restore_default(bt));
|
||||
furi_record_close(RECORD_BT);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <dolphin/dolphin.h>
|
||||
|
||||
#define TAG "BadUsb"
|
||||
|
||||
#define WORKER_TAG TAG "Worker"
|
||||
|
||||
#define BADUSB_ASCII_TO_KEY(script, x) \
|
||||
@@ -46,7 +47,7 @@ uint32_t ducky_get_command_len(const char* line) {
|
||||
}
|
||||
|
||||
bool ducky_is_line_end(const char chr) {
|
||||
return ((chr == ' ') || (chr == '\0') || (chr == '\r') || (chr == '\n'));
|
||||
return (chr == ' ') || (chr == '\0') || (chr == '\r') || (chr == '\n');
|
||||
}
|
||||
|
||||
uint16_t ducky_get_keycode(BadUsbScript* bad_usb, const char* param, bool accept_chars) {
|
||||
@@ -56,7 +57,7 @@ uint16_t ducky_get_keycode(BadUsbScript* bad_usb, const char* param, bool accept
|
||||
}
|
||||
|
||||
if((accept_chars) && (strlen(param) > 0)) {
|
||||
return (BADUSB_ASCII_TO_KEY(bad_usb, param[0]) & 0xFF);
|
||||
return BADUSB_ASCII_TO_KEY(bad_usb, param[0]) & 0xFF;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -309,7 +310,7 @@ static int32_t ducky_script_execute_next(BadUsbScript* bad_usb, File* script_fil
|
||||
FURI_LOG_E(WORKER_TAG, "Unknown command at line %zu", bad_usb->st.line_cur - 1U);
|
||||
return SCRIPT_STATE_ERROR;
|
||||
} else {
|
||||
return (delay_val + bad_usb->defdelay);
|
||||
return delay_val + bad_usb->defdelay;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -348,7 +349,7 @@ static int32_t ducky_script_execute_next(BadUsbScript* bad_usb, File* script_fil
|
||||
FURI_LOG_E(WORKER_TAG, "Unknown command at line %zu", bad_usb->st.line_cur);
|
||||
return SCRIPT_STATE_ERROR;
|
||||
} else {
|
||||
return (delay_val + bad_usb->defdelay);
|
||||
return delay_val + bad_usb->defdelay;
|
||||
}
|
||||
} else {
|
||||
furi_string_push_back(bad_usb->line, bad_usb->file_buf[i]);
|
||||
|
||||
@@ -216,6 +216,7 @@ static const DuckyCmd ducky_commands[] = {
|
||||
};
|
||||
|
||||
#define TAG "BadUsb"
|
||||
|
||||
#define WORKER_TAG TAG "Worker"
|
||||
|
||||
int32_t ducky_execute_cmd(BadUsbScript* bad_usb, const char* line) {
|
||||
@@ -231,7 +232,7 @@ int32_t ducky_execute_cmd(BadUsbScript* bad_usb, const char* line) {
|
||||
if(ducky_commands[i].callback == NULL) {
|
||||
return 0;
|
||||
} else {
|
||||
return ((ducky_commands[i].callback)(bad_usb, line, ducky_commands[i].param));
|
||||
return (ducky_commands[i].callback)(bad_usb, line, ducky_commands[i].param);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,10 +9,10 @@ extern "C" {
|
||||
#include "ducky_script.h"
|
||||
#include "bad_usb_hid.h"
|
||||
|
||||
#define SCRIPT_STATE_ERROR (-1)
|
||||
#define SCRIPT_STATE_END (-2)
|
||||
#define SCRIPT_STATE_NEXT_LINE (-3)
|
||||
#define SCRIPT_STATE_CMD_UNKNOWN (-4)
|
||||
#define SCRIPT_STATE_ERROR (-1)
|
||||
#define SCRIPT_STATE_END (-2)
|
||||
#define SCRIPT_STATE_NEXT_LINE (-3)
|
||||
#define SCRIPT_STATE_CMD_UNKNOWN (-4)
|
||||
#define SCRIPT_STATE_STRING_START (-5)
|
||||
#define SCRIPT_STATE_WAIT_FOR_BTN (-6)
|
||||
|
||||
|
||||
@@ -7,14 +7,14 @@
|
||||
|
||||
#define CLOCK_ISO_DATE_FORMAT "%.4d-%.2d-%.2d"
|
||||
#define CLOCK_RFC_DATE_FORMAT "%.2d-%.2d-%.4d"
|
||||
#define CLOCK_TIME_FORMAT "%.2d:%.2d:%.2d"
|
||||
#define CLOCK_TIME_FORMAT "%.2d:%.2d:%.2d"
|
||||
|
||||
#define MERIDIAN_FORMAT "%s"
|
||||
#define MERIDIAN_FORMAT "%s"
|
||||
#define MERIDIAN_STRING_AM "AM"
|
||||
#define MERIDIAN_STRING_PM "PM"
|
||||
|
||||
#define TIME_LEN 12
|
||||
#define DATE_LEN 14
|
||||
#define TIME_LEN 12
|
||||
#define DATE_LEN 14
|
||||
#define MERIDIAN_LEN 3
|
||||
|
||||
typedef enum {
|
||||
|
||||
@@ -10,11 +10,11 @@
|
||||
#include <stm32wbxx_ll_lpuart.h>
|
||||
#include <stm32wbxx_ll_usart.h>
|
||||
|
||||
#define USB_CDC_PKT_LEN CDC_DATA_SZ
|
||||
#define USB_CDC_PKT_LEN CDC_DATA_SZ
|
||||
#define USB_UART_RX_BUF_SIZE (USB_CDC_PKT_LEN * 5)
|
||||
|
||||
#define USB_CDC_BIT_DTR (1 << 0)
|
||||
#define USB_CDC_BIT_RTS (1 << 1)
|
||||
#define USB_CDC_BIT_DTR (1 << 0)
|
||||
#define USB_CDC_BIT_RTS (1 << 1)
|
||||
#define USB_USART_DE_RE_PIN &gpio_ext_pa4
|
||||
|
||||
static const GpioPin* flow_pins[][2] = {
|
||||
|
||||
@@ -28,8 +28,8 @@
|
||||
#include "ibutton_custom_event.h"
|
||||
#include "scenes/ibutton_scene.h"
|
||||
|
||||
#define IBUTTON_APP_FOLDER ANY_PATH("ibutton")
|
||||
#define IBUTTON_APP_FILENAME_PREFIX "iBtn"
|
||||
#define IBUTTON_APP_FOLDER ANY_PATH("ibutton")
|
||||
#define IBUTTON_APP_FILENAME_PREFIX "iBtn"
|
||||
#define IBUTTON_APP_FILENAME_EXTENSION ".ibtn"
|
||||
|
||||
#define IBUTTON_KEY_NAME_SIZE 22
|
||||
|
||||
@@ -36,7 +36,27 @@ bool ibutton_scene_add_value_on_event(void* context, SceneManagerEvent event) {
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
consumed = true;
|
||||
if(event.event == iButtonCustomEventByteEditResult) {
|
||||
scene_manager_next_scene(scene_manager, iButtonSceneSaveName);
|
||||
if(scene_manager_has_previous_scene(scene_manager, iButtonSceneAddType)) {
|
||||
ibutton_protocols_apply_edits(ibutton->protocols, ibutton->key);
|
||||
scene_manager_next_scene(scene_manager, iButtonSceneSaveName);
|
||||
} else {
|
||||
furi_string_printf(
|
||||
ibutton->file_path,
|
||||
"%s/%s%s",
|
||||
IBUTTON_APP_FOLDER,
|
||||
ibutton->key_name,
|
||||
IBUTTON_APP_FILENAME_EXTENSION);
|
||||
|
||||
if(ibutton_save_key(ibutton)) {
|
||||
scene_manager_next_scene(ibutton->scene_manager, iButtonSceneSaveSuccess);
|
||||
|
||||
} else {
|
||||
const uint32_t possible_scenes[] = {
|
||||
iButtonSceneReadKeyMenu, iButtonSceneSavedKeyMenu, iButtonSceneAddType};
|
||||
scene_manager_search_and_switch_to_previous_scene_one_of(
|
||||
ibutton->scene_manager, possible_scenes, COUNT_OF(possible_scenes));
|
||||
}
|
||||
}
|
||||
} else if(event.event == iButtonCustomEventByteEditChanged) {
|
||||
ibutton_protocols_apply_edits(ibutton->protocols, ibutton->key);
|
||||
}
|
||||
|
||||
@@ -41,9 +41,17 @@ bool ibutton_scene_save_name_on_event(void* context, SceneManagerEvent event) {
|
||||
iButton* ibutton = context;
|
||||
bool consumed = false;
|
||||
|
||||
const bool is_new_file = furi_string_empty(ibutton->file_path);
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
consumed = true;
|
||||
if(event.event == iButtonCustomEventTextEditResult) {
|
||||
if(!is_new_file) {
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
storage_simply_remove(storage, furi_string_get_cstr(ibutton->file_path));
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
}
|
||||
|
||||
furi_string_printf(
|
||||
ibutton->file_path,
|
||||
"%s/%s%s",
|
||||
|
||||
@@ -6,6 +6,7 @@ enum SubmenuIndex {
|
||||
SubmenuIndexWriteBlank,
|
||||
SubmenuIndexWriteCopy,
|
||||
SubmenuIndexEdit,
|
||||
SubmenuIndexRename,
|
||||
SubmenuIndexDelete,
|
||||
SubmenuIndexInfo,
|
||||
};
|
||||
@@ -34,6 +35,7 @@ void ibutton_scene_saved_key_menu_on_enter(void* context) {
|
||||
}
|
||||
|
||||
submenu_add_item(submenu, "Edit", SubmenuIndexEdit, ibutton_submenu_callback, ibutton);
|
||||
submenu_add_item(submenu, "Rename", SubmenuIndexRename, ibutton_submenu_callback, ibutton);
|
||||
submenu_add_item(submenu, "Delete", SubmenuIndexDelete, ibutton_submenu_callback, ibutton);
|
||||
submenu_add_item(submenu, "Info", SubmenuIndexInfo, ibutton_submenu_callback, ibutton);
|
||||
|
||||
@@ -61,6 +63,8 @@ bool ibutton_scene_saved_key_menu_on_event(void* context, SceneManagerEvent even
|
||||
scene_manager_next_scene(scene_manager, iButtonSceneWrite);
|
||||
} else if(event.event == SubmenuIndexEdit) {
|
||||
scene_manager_next_scene(scene_manager, iButtonSceneAddValue);
|
||||
} else if(event.event == SubmenuIndexRename) {
|
||||
scene_manager_next_scene(scene_manager, iButtonSceneSaveName);
|
||||
} else if(event.event == SubmenuIndexDelete) {
|
||||
scene_manager_next_scene(scene_manager, iButtonSceneDeleteConfirm);
|
||||
} else if(event.event == SubmenuIndexInfo) {
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#define TAG "InfraredApp"
|
||||
|
||||
#define INFRARED_TX_MIN_INTERVAL_MS (50U)
|
||||
#define INFRARED_TASK_STACK_SIZE (2048UL)
|
||||
#define INFRARED_TASK_STACK_SIZE (2048UL)
|
||||
|
||||
static const NotificationSequence*
|
||||
infrared_notification_sequences[InfraredNotificationMessageCount] = {
|
||||
|
||||
@@ -17,9 +17,9 @@ typedef struct InfraredApp InfraredApp;
|
||||
#include <storage/storage.h>
|
||||
#include <furi_hal_infrared.h>
|
||||
|
||||
#define INFRARED_SETTINGS_PATH EXT_PATH("infrared/.infrared.settings")
|
||||
#define INFRARED_SETTINGS_PATH EXT_PATH("infrared/.infrared.settings")
|
||||
#define INFRARED_SETTINGS_VERSION (1)
|
||||
#define INFRARED_SETTINGS_MAGIC (0x1F)
|
||||
#define INFRARED_SETTINGS_MAGIC (0x1F)
|
||||
|
||||
typedef struct {
|
||||
FuriHalInfraredTxPin tx_pin;
|
||||
|
||||
@@ -39,18 +39,18 @@
|
||||
#include "views/infrared_debug_view.h"
|
||||
#include "views/infrared_move_view.h"
|
||||
|
||||
#define INFRARED_FILE_NAME_SIZE 100
|
||||
#define INFRARED_TEXT_STORE_NUM 2
|
||||
#define INFRARED_FILE_NAME_SIZE 100
|
||||
#define INFRARED_TEXT_STORE_NUM 2
|
||||
#define INFRARED_TEXT_STORE_SIZE 128
|
||||
|
||||
#define INFRARED_MAX_BUTTON_NAME_LENGTH 22
|
||||
#define INFRARED_MAX_REMOTE_NAME_LENGTH 22
|
||||
|
||||
#define INFRARED_APP_FOLDER ANY_PATH("infrared")
|
||||
#define INFRARED_APP_FOLDER ANY_PATH("infrared")
|
||||
#define INFRARED_APP_EXTENSION ".ir"
|
||||
|
||||
#define INFRARED_DEFAULT_REMOTE_NAME "Remote"
|
||||
#define INFRARED_LOG_TAG "InfraredApp"
|
||||
#define INFRARED_LOG_TAG "InfraredApp"
|
||||
|
||||
/**
|
||||
* @brief Enumeration of invalid remote button indices.
|
||||
@@ -86,7 +86,7 @@ typedef struct {
|
||||
bool is_transmitting; /**< Whether a signal is currently being transmitted. */
|
||||
bool is_otg_enabled; /**< Whether OTG power (external 5V) is enabled. */
|
||||
InfraredEditTarget edit_target : 8; /**< Selected editing target (a remote or a button). */
|
||||
InfraredEditMode edit_mode : 8; /**< Selected editing operation (rename or delete). */
|
||||
InfraredEditMode edit_mode : 8; /**< Selected editing operation (rename or delete). */
|
||||
int32_t current_button_index; /**< Selected button index (move destination). */
|
||||
int32_t prev_button_index; /**< Previous button index (move source). */
|
||||
uint32_t last_transmit_time; /**< Lat time a signal was transmitted. */
|
||||
|
||||
@@ -10,10 +10,10 @@
|
||||
#include "infrared_signal.h"
|
||||
#include "infrared_brute_force.h"
|
||||
|
||||
#define INFRARED_CLI_BUF_SIZE (10U)
|
||||
#define INFRARED_CLI_FILE_NAME_SIZE (256U)
|
||||
#define INFRARED_FILE_EXTENSION ".ir"
|
||||
#define INFRARED_ASSETS_FOLDER EXT_PATH("infrared/assets")
|
||||
#define INFRARED_CLI_BUF_SIZE (10U)
|
||||
#define INFRARED_CLI_FILE_NAME_SIZE (256U)
|
||||
#define INFRARED_FILE_EXTENSION ".ir"
|
||||
#define INFRARED_ASSETS_FOLDER EXT_PATH("infrared/assets")
|
||||
#define INFRARED_BRUTE_FORCE_DUMMY_INDEX 0
|
||||
|
||||
DICT_DEF2(dict_signals, FuriString*, FURI_STRING_OPLIST, int, M_DEFAULT_OPLIST)
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
#define TAG "InfraredRemote"
|
||||
|
||||
#define INFRARED_FILE_HEADER "IR signals file"
|
||||
#define INFRARED_FILE_HEADER "IR signals file"
|
||||
#define INFRARED_FILE_VERSION (1)
|
||||
|
||||
ARRAY_DEF(StringArray, const char*, M_CSTR_DUP_OPLIST); //-V575
|
||||
|
||||
@@ -13,18 +13,18 @@
|
||||
#define INFRARED_SIGNAL_TYPE_KEY "type"
|
||||
|
||||
// Type key values
|
||||
#define INFRARED_SIGNAL_TYPE_RAW "raw"
|
||||
#define INFRARED_SIGNAL_TYPE_RAW "raw"
|
||||
#define INFRARED_SIGNAL_TYPE_PARSED "parsed"
|
||||
|
||||
// Raw signal keys
|
||||
#define INFRARED_SIGNAL_DATA_KEY "data"
|
||||
#define INFRARED_SIGNAL_FREQUENCY_KEY "frequency"
|
||||
#define INFRARED_SIGNAL_DATA_KEY "data"
|
||||
#define INFRARED_SIGNAL_FREQUENCY_KEY "frequency"
|
||||
#define INFRARED_SIGNAL_DUTY_CYCLE_KEY "duty_cycle"
|
||||
|
||||
// Parsed signal keys
|
||||
#define INFRARED_SIGNAL_PROTOCOL_KEY "protocol"
|
||||
#define INFRARED_SIGNAL_ADDRESS_KEY "address"
|
||||
#define INFRARED_SIGNAL_COMMAND_KEY "command"
|
||||
#define INFRARED_SIGNAL_ADDRESS_KEY "address"
|
||||
#define INFRARED_SIGNAL_COMMAND_KEY "command"
|
||||
|
||||
struct InfraredSignal {
|
||||
bool is_raw;
|
||||
|
||||
@@ -7,9 +7,9 @@
|
||||
|
||||
#include <toolbox/m_cstr_dup.h>
|
||||
|
||||
#define LIST_ITEMS 4U
|
||||
#define LIST_LINE_H 13U
|
||||
#define HEADER_H 12U
|
||||
#define LIST_ITEMS 4U
|
||||
#define LIST_LINE_H 13U
|
||||
#define HEADER_H 12U
|
||||
#define MOVE_X_OFFSET 5U
|
||||
|
||||
struct InfraredMoveView {
|
||||
@@ -98,7 +98,7 @@ static bool infrared_move_view_input_callback(InputEvent* event, void* context)
|
||||
|
||||
bool consumed = false;
|
||||
|
||||
if(((event->type == InputTypeShort || event->type == InputTypeRepeat)) &&
|
||||
if((event->type == InputTypeShort || event->type == InputTypeRepeat) &&
|
||||
((event->key == InputKeyUp) || (event->key == InputKeyDown))) {
|
||||
with_view_model(
|
||||
move_view->view,
|
||||
|
||||
@@ -3,22 +3,22 @@
|
||||
|
||||
//TODO: use .txt file in resources for passwords.
|
||||
const uint32_t default_passwords[] = {
|
||||
0x51243648, 0x000D8787, 0x19920427, 0x50524F58, 0xF9DCEBA0, 0x65857569, 0x05D73B9F, 0x89A69E60,
|
||||
0x314159E0, 0xAA55BBBB, 0xA5B4C3D2, 0x1C0B5848, 0x00434343, 0x444E4752, 0x4E457854, 0x44B44CAE,
|
||||
0x88661858, 0xE9920427, 0x575F4F4B, 0x50520901, 0x20206666, 0x65857569, 0x5469616E, 0x7686962A,
|
||||
0xC0F5009A, 0x07CEE75D, 0xfeedbeef, 0xdeadc0de, 0x00000000, 0x11111111, 0x22222222, 0x33333333,
|
||||
0x44444444, 0x55555555, 0x66666666, 0x77777777, 0x88888888, 0x99999999, 0xAAAAAAAA, 0xBBBBBBBB,
|
||||
0xCCCCCCCC, 0xDDDDDDDD, 0xEEEEEEEE, 0xFFFFFFFF, 0xa0a1a2a3, 0xb0b1b2b3, 0x50415353, 0x00000001,
|
||||
0x00000002, 0x0000000a, 0x0000000b, 0x01020304, 0x02030405, 0x03040506, 0x04050607, 0x05060708,
|
||||
0x06070809, 0x0708090A, 0x08090A0B, 0x090A0B0C, 0x0A0B0C0D, 0x0B0C0D0E, 0x0C0D0E0F, 0x01234567,
|
||||
0x12345678, 0x10000000, 0x20000000, 0x30000000, 0x40000000, 0x50000000, 0x60000000, 0x70000000,
|
||||
0x80000000, 0x90000000, 0xA0000000, 0xB0000000, 0xC0000000, 0xD0000000, 0xE0000000, 0xF0000000,
|
||||
0x10101010, 0x01010101, 0x11223344, 0x22334455, 0x33445566, 0x44556677, 0x55667788, 0x66778899,
|
||||
0x778899AA, 0x8899AABB, 0x99AABBCC, 0xAABBCCDD, 0xBBCCDDEE, 0xCCDDEEFF, 0x0CB7E7FC, 0xFABADA11,
|
||||
0x87654321, 0x12341234, 0x69696969, 0x12121212, 0x12344321, 0x1234ABCD, 0x11112222, 0x13131313,
|
||||
0x10041004, 0x31415926, 0xabcd1234, 0x20002000, 0x19721972, 0xaa55aa55, 0x55aa55aa, 0x4f271149,
|
||||
0x07d7bb0b, 0x9636ef8f, 0xb5f44686, 0x9E3779B9, 0xC6EF3720, 0x7854794A, 0xF1EA5EED, 0x69314718,
|
||||
0x57721566, 0x93C467E3, 0x27182818, 0x50415353};
|
||||
0x00000000, 0x00000001, 0x00000002, 0x0000000A, 0x0000000B, 0x00012323, 0x000D8787, 0x00434343,
|
||||
0x01010101, 0x01020304, 0x01234567, 0x02030405, 0x03040506, 0x04050607, 0x05060708, 0x05D73B9F,
|
||||
0x06070809, 0x0708090A, 0x07CEE75D, 0x07D7BB0B, 0x08090A0B, 0x090A0B0C, 0x0A0B0C0D, 0x0B0C0D0E,
|
||||
0x0C0D0E0F, 0x0CB7E7FC, 0x10000000, 0x10041004, 0x10101010, 0x11111111, 0x11112222, 0x11223344,
|
||||
0x12121212, 0x121AD038, 0x12341234, 0x12344321, 0x12345678, 0x1234ABCD, 0x126C248A, 0x13131313,
|
||||
0x19721972, 0x19920427, 0x1C0B5848, 0x20000000, 0x20002000, 0x20206666, 0x22222222, 0x22334455,
|
||||
0x27182818, 0x30000000, 0x31415926, 0x314159E0, 0x33333333, 0x33445566, 0x40000000, 0x44444444,
|
||||
0x444E4752, 0x44556677, 0x44B44CAE, 0x4E457854, 0x4F271149, 0x50000000, 0x50415353, 0x50520901,
|
||||
0x50524F58, 0x51243648, 0x5469616E, 0x55555555, 0x55667788, 0x55AA55AA, 0x575F4F4B, 0x57721566,
|
||||
0x60000000, 0x65857569, 0x66666666, 0x66778899, 0x69314718, 0x69696969, 0x70000000, 0x7686962A,
|
||||
0x77777777, 0x778899AA, 0x7854794A, 0x80000000, 0x87654321, 0x88661858, 0x88888888, 0x8899AABB,
|
||||
0x89A69E60, 0x90000000, 0x932D9963, 0x93C467E3, 0x9636EF8F, 0x99999999, 0x99AABBCC, 0x9E3779B9,
|
||||
0xA0000000, 0xA0A1A2A3, 0xA5B4C3D2, 0xAA55AA55, 0xAA55BBBB, 0xAAAAAAAA, 0xAABBCCDD, 0xABCD1234,
|
||||
0xB0000000, 0xB0B1B2B3, 0xB5F44686, 0xBBBBBBBB, 0xBBCCDDEE, 0xC0000000, 0xC0F5009A, 0xC6EF3720,
|
||||
0xCCCCCCCC, 0xCCDDEEFF, 0xD0000000, 0xDDDDDDDD, 0xDEADC0DE, 0xE0000000, 0xE4204998, 0xE9920427,
|
||||
0xEEEEEEEE, 0xF0000000, 0xF1EA5EED, 0xF9DCEBA0, 0xFABADA11, 0xFEEDBEEF, 0xFFFFFFFF};
|
||||
|
||||
const uint32_t* lfrfid_get_t5577_default_passwords(uint8_t* len) {
|
||||
*len = sizeof(default_passwords) / sizeof(uint32_t);
|
||||
|
||||
@@ -23,7 +23,7 @@ static void lfrfid_cli_print_usage(void) {
|
||||
"rfid raw_emulate <filename> - emulate raw data (not very useful, but helps debug protocols)\r\n");
|
||||
printf(
|
||||
"rfid raw_analyze <filename> - outputs raw data to the cli and tries to decode it (useful for protocol development)\r\n");
|
||||
};
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
ProtocolId protocol;
|
||||
|
||||
@@ -35,13 +35,13 @@
|
||||
|
||||
#include <lfrfid/scenes/lfrfid_scene.h>
|
||||
|
||||
#define LFRFID_KEY_NAME_SIZE 22
|
||||
#define LFRFID_KEY_NAME_SIZE 22
|
||||
#define LFRFID_TEXT_STORE_SIZE 40
|
||||
|
||||
#define LFRFID_APP_FOLDER ANY_PATH("lfrfid")
|
||||
#define LFRFID_SD_FOLDER EXT_PATH("lfrfid")
|
||||
#define LFRFID_APP_FILENAME_PREFIX "RFID"
|
||||
#define LFRFID_APP_FILENAME_EXTENSION ".rfid"
|
||||
#define LFRFID_APP_FOLDER ANY_PATH("lfrfid")
|
||||
#define LFRFID_SD_FOLDER EXT_PATH("lfrfid")
|
||||
#define LFRFID_APP_FILENAME_PREFIX "RFID"
|
||||
#define LFRFID_APP_FILENAME_EXTENSION ".rfid"
|
||||
#define LFRFID_APP_SHADOW_FILENAME_EXTENSION ".shd"
|
||||
|
||||
#define LFRFID_APP_RAW_ASK_EXTENSION ".ask.raw"
|
||||
@@ -155,4 +155,4 @@ void lfrfid_widget_callback(GuiButtonType result, InputType type, void* context)
|
||||
|
||||
void lfrfid_text_input_callback(void* context);
|
||||
|
||||
const uint32_t* lfrfid_get_t5577_default_passwords(uint8_t* len);
|
||||
const uint32_t* lfrfid_get_t5577_default_passwords(uint8_t* len);
|
||||
|
||||
@@ -31,8 +31,21 @@ bool lfrfid_scene_save_data_on_event(void* context, SceneManagerEvent event) {
|
||||
consumed = true;
|
||||
size_t size = protocol_dict_get_data_size(app->dict, app->protocol_id);
|
||||
protocol_dict_set_data(app->dict, app->protocol_id, app->new_key_data, size);
|
||||
scene_manager_next_scene(scene_manager, LfRfidSceneSaveName);
|
||||
scene_manager_set_scene_state(scene_manager, LfRfidSceneSaveData, 1);
|
||||
|
||||
if(scene_manager_has_previous_scene(scene_manager, LfRfidSceneSaveType)) {
|
||||
scene_manager_next_scene(scene_manager, LfRfidSceneSaveName);
|
||||
} else {
|
||||
if(!furi_string_empty(app->file_name)) {
|
||||
lfrfid_delete_key(app);
|
||||
}
|
||||
|
||||
if(lfrfid_save_key(app)) {
|
||||
scene_manager_next_scene(scene_manager, LfRfidSceneSaveSuccess);
|
||||
} else {
|
||||
scene_manager_search_and_switch_to_previous_scene(
|
||||
scene_manager, LfRfidSceneSavedKeyMenu);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if(event.type == SceneManagerEventTypeBack) {
|
||||
scene_manager_set_scene_state(scene_manager, LfRfidSceneSaveData, 0);
|
||||
|
||||
@@ -6,6 +6,7 @@ typedef enum {
|
||||
SubmenuIndexWrite,
|
||||
SubmenuIndexWriteAndSetPass,
|
||||
SubmenuIndexEdit,
|
||||
SubmenuIndexRename,
|
||||
SubmenuIndexDelete,
|
||||
SubmenuIndexInfo,
|
||||
} SubmenuIndex;
|
||||
@@ -32,6 +33,8 @@ void lfrfid_scene_saved_key_menu_on_enter(void* context) {
|
||||
app);
|
||||
submenu_add_item(
|
||||
submenu, "Edit", SubmenuIndexEdit, lfrfid_scene_saved_key_menu_submenu_callback, app);
|
||||
submenu_add_item(
|
||||
submenu, "Rename", SubmenuIndexRename, lfrfid_scene_saved_key_menu_submenu_callback, app);
|
||||
submenu_add_item(
|
||||
submenu, "Delete", SubmenuIndexDelete, lfrfid_scene_saved_key_menu_submenu_callback, app);
|
||||
submenu_add_item(
|
||||
@@ -63,6 +66,9 @@ bool lfrfid_scene_saved_key_menu_on_event(void* context, SceneManagerEvent event
|
||||
} else if(event.event == SubmenuIndexEdit) {
|
||||
scene_manager_next_scene(app->scene_manager, LfRfidSceneSaveData);
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexRename) {
|
||||
scene_manager_next_scene(app->scene_manager, LfRfidSceneSaveName);
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexDelete) {
|
||||
scene_manager_next_scene(app->scene_manager, LfRfidSceneDeleteConfirm);
|
||||
consumed = true;
|
||||
|
||||
@@ -56,4 +56,4 @@ void gallagher_deobfuscate_and_parse_credential(
|
||||
((uint32_t)cardholder_data_deobfuscated[2] << 3) +
|
||||
(((uint32_t)cardholder_data_deobfuscated[3] >> 5) & 0x07);
|
||||
credential->issue = cardholder_data_deobfuscated[7] & 0x0F;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,4 +30,4 @@ void gallagher_deobfuscate_and_parse_credential(
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user