mirror of
https://github.com/DarkFlippers/unleashed-firmware.git
synced 2025-12-12 20:49:49 +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
|
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
|
--- a/applications/services/notification/notification_app.c
|
||||||
+++ b/applications/services/notification/notification_app.c
|
+++ b/applications/services/notification/notification_app.c
|
||||||
@@ -9,6 +9,7 @@
|
@@ -9,6 +9,7 @@
|
||||||
@@ -10,7 +10,7 @@ index 9baa738..91ad7c1 100644
|
|||||||
|
|
||||||
#define TAG "NotificationSrv"
|
#define TAG "NotificationSrv"
|
||||||
|
|
||||||
@@ -589,6 +590,7 @@ int32_t notification_srv(void* p) {
|
@@ -588,6 +589,7 @@ int32_t notification_srv(void* p) {
|
||||||
break;
|
break;
|
||||||
case SaveSettingsMessage:
|
case SaveSettingsMessage:
|
||||||
notification_save_settings(app);
|
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
|
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
|
--- a/applications/settings/notification_settings/notification_settings_app.c
|
||||||
+++ b/applications/settings/notification_settings/notification_settings_app.c
|
+++ b/applications/settings/notification_settings/notification_settings_app.c
|
||||||
@@ -3,6 +3,7 @@
|
@@ -3,6 +3,7 @@
|
||||||
@@ -99,7 +99,7 @@ index 2a1d988..dda86f3 100644
|
|||||||
static uint32_t notification_app_settings_exit(void* context) {
|
static uint32_t notification_app_settings_exit(void* context) {
|
||||||
UNUSED(context);
|
UNUSED(context);
|
||||||
return VIEW_NONE;
|
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_index(item, value_index);
|
||||||
variable_item_set_current_value_text(item, contrast_text[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);
|
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
|
diff --git a/applications/settings/notification_settings/rgb_backlight.c b/applications/settings/notification_settings/rgb_backlight.c
|
||||||
new file mode 100644
|
new file mode 100644
|
||||||
index 0000000..98f0d3a
|
index 0000000..4edd775
|
||||||
--- /dev/null
|
--- /dev/null
|
||||||
+++ b/applications/settings/notification_settings/rgb_backlight.c
|
+++ b/applications/settings/notification_settings/rgb_backlight.c
|
||||||
@@ -0,0 +1,217 @@
|
@@ -0,0 +1,217 @@
|
||||||
@@ -169,9 +169,9 @@ index 0000000..98f0d3a
|
|||||||
+#include <furi_hal.h>
|
+#include <furi_hal.h>
|
||||||
+#include <storage/storage.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_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))
|
+#define COLOR_COUNT (sizeof(colors) / sizeof(RGBBacklightColor))
|
||||||
+
|
+
|
||||||
@@ -263,7 +263,7 @@ index 0000000..98f0d3a
|
|||||||
+ storage_file_free(file);
|
+ storage_file_free(file);
|
||||||
+ furi_record_close(RECORD_STORAGE);
|
+ furi_record_close(RECORD_STORAGE);
|
||||||
+ rgb_settings.settings_is_loaded = true;
|
+ rgb_settings.settings_is_loaded = true;
|
||||||
+};
|
+}
|
||||||
+
|
+
|
||||||
+void rgb_backlight_save_settings(void) {
|
+void rgb_backlight_save_settings(void) {
|
||||||
+ RGBBacklightSettings settings;
|
+ RGBBacklightSettings settings;
|
||||||
@@ -294,7 +294,7 @@ index 0000000..98f0d3a
|
|||||||
+ storage_file_close(file);
|
+ storage_file_close(file);
|
||||||
+ storage_file_free(file);
|
+ storage_file_free(file);
|
||||||
+ furi_record_close(RECORD_STORAGE);
|
+ furi_record_close(RECORD_STORAGE);
|
||||||
+};
|
+}
|
||||||
+
|
+
|
||||||
+RGBBacklightSettings* rgb_backlight_get_settings(void) {
|
+RGBBacklightSettings* rgb_backlight_get_settings(void) {
|
||||||
+ if(!rgb_settings.settings_is_loaded) {
|
+ 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
|
diff --git a/applications/settings/notification_settings/rgb_backlight.h b/applications/settings/notification_settings/rgb_backlight.h
|
||||||
new file mode 100644
|
new file mode 100644
|
||||||
index 0000000..68dacda
|
index 0000000..f215ed3
|
||||||
--- /dev/null
|
--- /dev/null
|
||||||
+++ b/applications/settings/notification_settings/rgb_backlight.h
|
+++ b/applications/settings/notification_settings/rgb_backlight.h
|
||||||
@@ -0,0 +1,91 @@
|
@@ -0,0 +1,91 @@
|
||||||
@@ -461,10 +461,9 @@ index 0000000..68dacda
|
|||||||
+ * @return Указатель на строку с названием цвета
|
+ * @return Указатель на строку с названием цвета
|
||||||
+ */
|
+ */
|
||||||
+const char* rgb_backlight_get_color_text(uint8_t index);
|
+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
|
diff --git a/lib/drivers/SK6805.c b/lib/drivers/SK6805.c
|
||||||
new file mode 100644
|
new file mode 100644
|
||||||
index 0000000..572e1df
|
index 0000000..b89f82a
|
||||||
--- /dev/null
|
--- /dev/null
|
||||||
+++ b/lib/drivers/SK6805.c
|
+++ b/lib/drivers/SK6805.c
|
||||||
@@ -0,0 +1,101 @@
|
@@ -0,0 +1,101 @@
|
||||||
@@ -491,14 +490,14 @@ index 0000000..572e1df
|
|||||||
+
|
+
|
||||||
+/* Настройки */
|
+/* Настройки */
|
||||||
+#define SK6805_LED_COUNT 3 //Количество светодиодов на плате подсветки
|
+#define SK6805_LED_COUNT 3 //Количество светодиодов на плате подсветки
|
||||||
+#define SK6805_LED_PIN &led_pin //Порт подключения светодиодов
|
+#define SK6805_LED_PIN &led_pin //Порт подключения светодиодов
|
||||||
+
|
+
|
||||||
+#ifdef FURI_DEBUG
|
+#ifdef FURI_DEBUG
|
||||||
+#define DEBUG_PIN &gpio_ext_pa7
|
+#define DEBUG_PIN &gpio_ext_pa7
|
||||||
+#define DEBUG_INIT() \
|
+#define DEBUG_INIT() \
|
||||||
+ furi_hal_gpio_init(DEBUG_PIN, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh)
|
+ furi_hal_gpio_init(DEBUG_PIN, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh)
|
||||||
+#define DEBUG_SET_HIGH() furi_hal_gpio_write(DEBUG_PIN, true)
|
+#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
|
+#else
|
||||||
+#define DEBUG_INIT()
|
+#define DEBUG_INIT()
|
||||||
+#define DEBUG_SET_HIGH()
|
+#define DEBUG_SET_HIGH()
|
||||||
@@ -571,7 +570,7 @@ index 0000000..572e1df
|
|||||||
+}
|
+}
|
||||||
diff --git a/lib/drivers/SK6805.h b/lib/drivers/SK6805.h
|
diff --git a/lib/drivers/SK6805.h b/lib/drivers/SK6805.h
|
||||||
new file mode 100644
|
new file mode 100644
|
||||||
index 0000000..7c58956
|
index 0000000..c97054f
|
||||||
--- /dev/null
|
--- /dev/null
|
||||||
+++ b/lib/drivers/SK6805.h
|
+++ b/lib/drivers/SK6805.h
|
||||||
@@ -0,0 +1,51 @@
|
@@ -0,0 +1,51 @@
|
||||||
@@ -626,9 +625,8 @@ index 0000000..7c58956
|
|||||||
+void SK6805_update(void);
|
+void SK6805_update(void);
|
||||||
+
|
+
|
||||||
+#endif /* SK6805_H_ */
|
+#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
|
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
|
--- a/targets/f7/furi_hal/furi_hal_light.c
|
||||||
+++ b/targets/f7/furi_hal/furi_hal_light.c
|
+++ b/targets/f7/furi_hal/furi_hal_light.c
|
||||||
@@ -3,6 +3,7 @@
|
@@ -3,6 +3,7 @@
|
||||||
@@ -637,7 +635,7 @@ index 83e1603..45798ca 100644
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
+#include <applications/settings/notification_settings/rgb_backlight.h>
|
+#include <applications/settings/notification_settings/rgb_backlight.h>
|
||||||
|
|
||||||
#define LED_CURRENT_RED (50u)
|
#define LED_CURRENT_RED (50u)
|
||||||
#define LED_CURRENT_GREEN (50u)
|
#define LED_CURRENT_GREEN (50u)
|
||||||
@@ -31,22 +32,21 @@ void furi_hal_light_init(void) {
|
@@ -31,22 +32,21 @@ void furi_hal_light_init(void) {
|
||||||
}
|
}
|
||||||
|
|||||||
129
.clang-format
129
.clang-format
@@ -3,22 +3,55 @@ Language: Cpp
|
|||||||
AccessModifierOffset: -4
|
AccessModifierOffset: -4
|
||||||
AlignAfterOpenBracket: AlwaysBreak
|
AlignAfterOpenBracket: AlwaysBreak
|
||||||
AlignArrayOfStructures: None
|
AlignArrayOfStructures: None
|
||||||
AlignConsecutiveMacros: None
|
AlignConsecutiveAssignments:
|
||||||
AlignConsecutiveAssignments: None
|
Enabled: false
|
||||||
AlignConsecutiveBitFields: None
|
AcrossEmptyLines: false
|
||||||
AlignConsecutiveDeclarations: None
|
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
|
AlignEscapedNewlines: Left
|
||||||
AlignOperands: Align
|
AlignOperands: Align
|
||||||
AlignTrailingComments: false
|
AlignTrailingComments:
|
||||||
|
Kind: Never
|
||||||
|
OverEmptyLines: 0
|
||||||
AllowAllArgumentsOnNextLine: true
|
AllowAllArgumentsOnNextLine: true
|
||||||
AllowAllParametersOfDeclarationOnNextLine: false
|
AllowAllParametersOfDeclarationOnNextLine: false
|
||||||
AllowShortEnumsOnASingleLine: true
|
AllowBreakBeforeNoexceptSpecifier: Never
|
||||||
AllowShortBlocksOnASingleLine: Never
|
AllowShortBlocksOnASingleLine: Never
|
||||||
AllowShortCaseLabelsOnASingleLine: false
|
AllowShortCaseLabelsOnASingleLine: false
|
||||||
|
AllowShortCompoundRequirementOnASingleLine: true
|
||||||
|
AllowShortEnumsOnASingleLine: false
|
||||||
AllowShortFunctionsOnASingleLine: None
|
AllowShortFunctionsOnASingleLine: None
|
||||||
AllowShortLambdasOnASingleLine: All
|
|
||||||
AllowShortIfStatementsOnASingleLine: WithoutElse
|
AllowShortIfStatementsOnASingleLine: WithoutElse
|
||||||
AllowShortLoopsOnASingleLine: true
|
AllowShortLambdasOnASingleLine: All
|
||||||
|
AllowShortLoopsOnASingleLine: false
|
||||||
AlwaysBreakAfterDefinitionReturnType: None
|
AlwaysBreakAfterDefinitionReturnType: None
|
||||||
AlwaysBreakAfterReturnType: None
|
AlwaysBreakAfterReturnType: None
|
||||||
AlwaysBreakBeforeMultilineStrings: false
|
AlwaysBreakBeforeMultilineStrings: false
|
||||||
@@ -27,17 +60,18 @@ AttributeMacros:
|
|||||||
- __capability
|
- __capability
|
||||||
BinPackArguments: false
|
BinPackArguments: false
|
||||||
BinPackParameters: false
|
BinPackParameters: false
|
||||||
|
BitFieldColonSpacing: Both
|
||||||
BraceWrapping:
|
BraceWrapping:
|
||||||
AfterCaseLabel: false
|
AfterCaseLabel: false
|
||||||
AfterClass: false
|
AfterClass: false
|
||||||
AfterControlStatement: Never
|
AfterControlStatement: Never
|
||||||
AfterEnum: false
|
AfterEnum: false
|
||||||
|
AfterExternBlock: false
|
||||||
AfterFunction: false
|
AfterFunction: false
|
||||||
AfterNamespace: false
|
AfterNamespace: false
|
||||||
AfterObjCDeclaration: false
|
AfterObjCDeclaration: false
|
||||||
AfterStruct: false
|
AfterStruct: false
|
||||||
AfterUnion: false
|
AfterUnion: false
|
||||||
AfterExternBlock: false
|
|
||||||
BeforeCatch: false
|
BeforeCatch: false
|
||||||
BeforeElse: false
|
BeforeElse: false
|
||||||
BeforeLambdaBody: false
|
BeforeLambdaBody: false
|
||||||
@@ -46,38 +80,35 @@ BraceWrapping:
|
|||||||
SplitEmptyFunction: true
|
SplitEmptyFunction: true
|
||||||
SplitEmptyRecord: true
|
SplitEmptyRecord: true
|
||||||
SplitEmptyNamespace: true
|
SplitEmptyNamespace: true
|
||||||
BreakBeforeBinaryOperators: None
|
BreakAdjacentStringLiterals: true
|
||||||
BreakBeforeConceptDeclarations: true
|
BreakAfterAttributes: Leave
|
||||||
BreakBeforeBraces: Attach
|
|
||||||
BreakBeforeInheritanceComma: false
|
|
||||||
BreakInheritanceList: BeforeColon
|
|
||||||
BreakBeforeTernaryOperators: false
|
|
||||||
BreakConstructorInitializersBeforeComma: false
|
|
||||||
BreakConstructorInitializers: BeforeComma
|
|
||||||
BreakAfterJavaFieldAnnotations: false
|
BreakAfterJavaFieldAnnotations: false
|
||||||
|
BreakArrays: true
|
||||||
|
BreakBeforeBinaryOperators: None
|
||||||
|
BreakBeforeConceptDeclarations: Always
|
||||||
|
BreakBeforeBraces: Attach
|
||||||
|
BreakBeforeInlineASMColon: OnlyMultiline
|
||||||
|
BreakBeforeTernaryOperators: false
|
||||||
|
BreakConstructorInitializers: BeforeComma
|
||||||
|
BreakInheritanceList: BeforeColon
|
||||||
BreakStringLiterals: false
|
BreakStringLiterals: false
|
||||||
ColumnLimit: 99
|
ColumnLimit: 99
|
||||||
CommentPragmas: '^ IWYU pragma:'
|
CommentPragmas: '^ IWYU pragma:'
|
||||||
QualifierAlignment: Leave
|
|
||||||
CompactNamespaces: false
|
CompactNamespaces: false
|
||||||
ConstructorInitializerIndentWidth: 4
|
ConstructorInitializerIndentWidth: 4
|
||||||
ContinuationIndentWidth: 4
|
ContinuationIndentWidth: 4
|
||||||
Cpp11BracedListStyle: true
|
Cpp11BracedListStyle: true
|
||||||
DeriveLineEnding: true
|
|
||||||
DerivePointerAlignment: false
|
DerivePointerAlignment: false
|
||||||
DisableFormat: false
|
DisableFormat: false
|
||||||
EmptyLineAfterAccessModifier: Never
|
EmptyLineAfterAccessModifier: Never
|
||||||
EmptyLineBeforeAccessModifier: LogicalBlock
|
EmptyLineBeforeAccessModifier: LogicalBlock
|
||||||
ExperimentalAutoDetectBinPacking: false
|
ExperimentalAutoDetectBinPacking: false
|
||||||
PackConstructorInitializers: BinPack
|
|
||||||
BasedOnStyle: ''
|
|
||||||
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
|
||||||
AllowAllConstructorInitializersOnNextLine: true
|
|
||||||
FixNamespaceComments: false
|
FixNamespaceComments: false
|
||||||
ForEachMacros:
|
ForEachMacros:
|
||||||
- foreach
|
- foreach
|
||||||
- Q_FOREACH
|
- Q_FOREACH
|
||||||
- BOOST_FOREACH
|
- BOOST_FOREACH
|
||||||
|
- M_EACH
|
||||||
IfMacros:
|
IfMacros:
|
||||||
- KJ_IF_MAYBE
|
- KJ_IF_MAYBE
|
||||||
IncludeBlocks: Preserve
|
IncludeBlocks: Preserve
|
||||||
@@ -97,19 +128,30 @@ IncludeCategories:
|
|||||||
IncludeIsMainRegex: '(Test)?$'
|
IncludeIsMainRegex: '(Test)?$'
|
||||||
IncludeIsMainSourceRegex: ''
|
IncludeIsMainSourceRegex: ''
|
||||||
IndentAccessModifiers: false
|
IndentAccessModifiers: false
|
||||||
IndentCaseLabels: false
|
|
||||||
IndentCaseBlocks: false
|
IndentCaseBlocks: false
|
||||||
|
IndentCaseLabels: false
|
||||||
|
IndentExternBlock: AfterExternBlock
|
||||||
IndentGotoLabels: true
|
IndentGotoLabels: true
|
||||||
IndentPPDirectives: None
|
IndentPPDirectives: None
|
||||||
IndentExternBlock: AfterExternBlock
|
IndentRequiresClause: false
|
||||||
IndentRequires: false
|
|
||||||
IndentWidth: 4
|
IndentWidth: 4
|
||||||
IndentWrappedFunctionNames: true
|
IndentWrappedFunctionNames: true
|
||||||
|
InsertBraces: false
|
||||||
|
InsertNewlineAtEOF: true
|
||||||
InsertTrailingCommas: None
|
InsertTrailingCommas: None
|
||||||
|
IntegerLiteralSeparator:
|
||||||
|
Binary: 0
|
||||||
|
BinaryMinDigits: 0
|
||||||
|
Decimal: 0
|
||||||
|
DecimalMinDigits: 0
|
||||||
|
Hex: 0
|
||||||
|
HexMinDigits: 0
|
||||||
JavaScriptQuotes: Leave
|
JavaScriptQuotes: Leave
|
||||||
JavaScriptWrapImports: true
|
JavaScriptWrapImports: true
|
||||||
KeepEmptyLinesAtTheStartOfBlocks: false
|
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||||
|
KeepEmptyLinesAtEOF: false
|
||||||
LambdaBodyIndentation: Signature
|
LambdaBodyIndentation: Signature
|
||||||
|
LineEnding: DeriveLF
|
||||||
MacroBlockBegin: ''
|
MacroBlockBegin: ''
|
||||||
MacroBlockEnd: ''
|
MacroBlockEnd: ''
|
||||||
MaxEmptyLinesToKeep: 1
|
MaxEmptyLinesToKeep: 1
|
||||||
@@ -119,34 +161,44 @@ ObjCBlockIndentWidth: 4
|
|||||||
ObjCBreakBeforeNestedBlockParam: true
|
ObjCBreakBeforeNestedBlockParam: true
|
||||||
ObjCSpaceAfterProperty: true
|
ObjCSpaceAfterProperty: true
|
||||||
ObjCSpaceBeforeProtocolList: true
|
ObjCSpaceBeforeProtocolList: true
|
||||||
|
PackConstructorInitializers: BinPack
|
||||||
PenaltyBreakAssignment: 10
|
PenaltyBreakAssignment: 10
|
||||||
PenaltyBreakBeforeFirstCallParameter: 30
|
PenaltyBreakBeforeFirstCallParameter: 30
|
||||||
PenaltyBreakComment: 10
|
PenaltyBreakComment: 10
|
||||||
PenaltyBreakFirstLessLess: 0
|
PenaltyBreakFirstLessLess: 0
|
||||||
PenaltyBreakOpenParenthesis: 0
|
PenaltyBreakOpenParenthesis: 0
|
||||||
|
PenaltyBreakScopeResolution: 500
|
||||||
PenaltyBreakString: 10
|
PenaltyBreakString: 10
|
||||||
PenaltyBreakTemplateDeclaration: 10
|
PenaltyBreakTemplateDeclaration: 10
|
||||||
PenaltyExcessCharacter: 100
|
PenaltyExcessCharacter: 100
|
||||||
PenaltyReturnTypeOnItsOwnLine: 60
|
|
||||||
PenaltyIndentedWhitespace: 0
|
PenaltyIndentedWhitespace: 0
|
||||||
|
PenaltyReturnTypeOnItsOwnLine: 60
|
||||||
PointerAlignment: Left
|
PointerAlignment: Left
|
||||||
PPIndentWidth: -1
|
PPIndentWidth: -1
|
||||||
|
QualifierAlignment: Leave
|
||||||
ReferenceAlignment: Pointer
|
ReferenceAlignment: Pointer
|
||||||
ReflowComments: false
|
ReflowComments: false
|
||||||
RemoveBracesLLVM: false
|
RemoveBracesLLVM: false
|
||||||
|
RemoveParentheses: Leave
|
||||||
|
RemoveSemicolon: true
|
||||||
|
RequiresClausePosition: OwnLine
|
||||||
|
RequiresExpressionIndentation: OuterScope
|
||||||
SeparateDefinitionBlocks: Leave
|
SeparateDefinitionBlocks: Leave
|
||||||
ShortNamespaceLines: 1
|
ShortNamespaceLines: 1
|
||||||
|
SkipMacroDefinitionBody: false
|
||||||
SortIncludes: Never
|
SortIncludes: Never
|
||||||
SortJavaStaticImport: Before
|
SortJavaStaticImport: Before
|
||||||
SortUsingDeclarations: false
|
SortUsingDeclarations: Never
|
||||||
SpaceAfterCStyleCast: false
|
SpaceAfterCStyleCast: false
|
||||||
SpaceAfterLogicalNot: false
|
SpaceAfterLogicalNot: false
|
||||||
SpaceAfterTemplateKeyword: true
|
SpaceAfterTemplateKeyword: true
|
||||||
|
SpaceAroundPointerQualifiers: Default
|
||||||
SpaceBeforeAssignmentOperators: true
|
SpaceBeforeAssignmentOperators: true
|
||||||
SpaceBeforeCaseColon: false
|
SpaceBeforeCaseColon: false
|
||||||
SpaceBeforeCpp11BracedList: false
|
SpaceBeforeCpp11BracedList: false
|
||||||
SpaceBeforeCtorInitializerColon: true
|
SpaceBeforeCtorInitializerColon: true
|
||||||
SpaceBeforeInheritanceColon: true
|
SpaceBeforeInheritanceColon: true
|
||||||
|
SpaceBeforeJsonColon: false
|
||||||
SpaceBeforeParens: Never
|
SpaceBeforeParens: Never
|
||||||
SpaceBeforeParensOptions:
|
SpaceBeforeParensOptions:
|
||||||
AfterControlStatements: false
|
AfterControlStatements: false
|
||||||
@@ -155,32 +207,35 @@ SpaceBeforeParensOptions:
|
|||||||
AfterFunctionDeclarationName: false
|
AfterFunctionDeclarationName: false
|
||||||
AfterIfMacros: false
|
AfterIfMacros: false
|
||||||
AfterOverloadedOperator: false
|
AfterOverloadedOperator: false
|
||||||
|
AfterPlacementOperator: true
|
||||||
|
AfterRequiresInClause: false
|
||||||
|
AfterRequiresInExpression: false
|
||||||
BeforeNonEmptyParentheses: false
|
BeforeNonEmptyParentheses: false
|
||||||
SpaceAroundPointerQualifiers: Default
|
|
||||||
SpaceBeforeRangeBasedForLoopColon: true
|
SpaceBeforeRangeBasedForLoopColon: true
|
||||||
|
SpaceBeforeSquareBrackets: false
|
||||||
SpaceInEmptyBlock: false
|
SpaceInEmptyBlock: false
|
||||||
SpaceInEmptyParentheses: false
|
|
||||||
SpacesBeforeTrailingComments: 1
|
SpacesBeforeTrailingComments: 1
|
||||||
SpacesInAngles: Never
|
SpacesInAngles: Never
|
||||||
SpacesInConditionalStatement: false
|
|
||||||
SpacesInContainerLiterals: false
|
SpacesInContainerLiterals: false
|
||||||
SpacesInCStyleCastParentheses: false
|
|
||||||
SpacesInLineCommentPrefix:
|
SpacesInLineCommentPrefix:
|
||||||
Minimum: 1
|
Minimum: 1
|
||||||
Maximum: -1
|
Maximum: -1
|
||||||
SpacesInParentheses: false
|
SpacesInParens: Never
|
||||||
|
SpacesInParensOptions:
|
||||||
|
InCStyleCasts: false
|
||||||
|
InConditionalStatements: false
|
||||||
|
InEmptyParentheses: false
|
||||||
|
Other: false
|
||||||
SpacesInSquareBrackets: false
|
SpacesInSquareBrackets: false
|
||||||
SpaceBeforeSquareBrackets: false
|
Standard: c++20
|
||||||
BitFieldColonSpacing: Both
|
|
||||||
Standard: c++03
|
|
||||||
StatementAttributeLikeMacros:
|
StatementAttributeLikeMacros:
|
||||||
- Q_EMIT
|
- Q_EMIT
|
||||||
StatementMacros:
|
StatementMacros:
|
||||||
- Q_UNUSED
|
- Q_UNUSED
|
||||||
- QT_REQUIRE_VERSION
|
- QT_REQUIRE_VERSION
|
||||||
TabWidth: 4
|
TabWidth: 4
|
||||||
UseCRLF: false
|
|
||||||
UseTab: Never
|
UseTab: Never
|
||||||
|
VerilogBreakBetweenInstancePorts: true
|
||||||
WhitespaceSensitiveMacros:
|
WhitespaceSensitiveMacros:
|
||||||
- STRINGIZE
|
- STRINGIZE
|
||||||
- PP_STRINGIZE
|
- PP_STRINGIZE
|
||||||
|
|||||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -45,9 +45,6 @@ null.d
|
|||||||
.sconsign.dblite
|
.sconsign.dblite
|
||||||
|
|
||||||
|
|
||||||
# Visual Studio Code
|
|
||||||
/.vscode
|
|
||||||
|
|
||||||
# bundle output
|
# bundle output
|
||||||
/dist
|
/dist
|
||||||
/artifacts-default
|
/artifacts-default
|
||||||
|
|||||||
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -23,9 +23,6 @@
|
|||||||
[submodule "lib/mbedtls"]
|
[submodule "lib/mbedtls"]
|
||||||
path = lib/mbedtls
|
path = lib/mbedtls
|
||||||
url = https://github.com/Mbed-TLS/mbedtls.git
|
url = https://github.com/Mbed-TLS/mbedtls.git
|
||||||
[submodule "lib/cxxheaderparser"]
|
|
||||||
path = lib/cxxheaderparser
|
|
||||||
url = https://github.com/robotpy/cxxheaderparser.git
|
|
||||||
[submodule "lib/heatshrink"]
|
[submodule "lib/heatshrink"]
|
||||||
path = lib/heatshrink
|
path = lib/heatshrink
|
||||||
url = https://github.com/flipperdevices/heatshrink.git
|
url = https://github.com/flipperdevices/heatshrink.git
|
||||||
|
|||||||
@@ -3,10 +3,12 @@
|
|||||||
//-V:M_EACH:1048,1044
|
//-V:M_EACH:1048,1044
|
||||||
//-V:ARRAY_DEF:760,747,568,776,729,712,654,1103
|
//-V:ARRAY_DEF:760,747,568,776,729,712,654,1103
|
||||||
//-V:LIST_DEF:760,747,568,712,729,654,776,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:BPTREE_DEF2:779,1086,557,773,512
|
||||||
//-V:DICT_DEF2:779,524,776,760,1044,1001,729,590,568,747,685,1103
|
//-V:DICT_DEF2:779,524,776,760,1044,1001,729,590,568,747,685,1103
|
||||||
//-V:ALGO_DEF:1048,747,1044
|
//-V:ALGO_DEF:1048,747,1044
|
||||||
//-V:TUPLE_DEF2:524,590,1001,760
|
//-V:TUPLE_DEF2:524,590,1001,760
|
||||||
|
//-V:DEQUE_DEF:658,747,760
|
||||||
|
|
||||||
# Non-severe malloc/null pointer deref warnings
|
# Non-severe malloc/null pointer deref warnings
|
||||||
//-V::522:2,3
|
//-V::522:2,3
|
||||||
|
|||||||
22
.sublime-project
vendored
22
.sublime-project
vendored
@@ -6,16 +6,20 @@
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"settings": {
|
"settings": {
|
||||||
"LSP": {
|
"LSP": {
|
||||||
"clangd": {
|
"clangd": {
|
||||||
"initializationOptions": {
|
|
||||||
"clangd.compile-commands-dir": "build/latest",
|
|
||||||
"clangd.header-insertion": "never",
|
|
||||||
"clangd.query-driver": "**",
|
|
||||||
"clangd.clang-tidy": true,
|
|
||||||
},
|
|
||||||
"enabled": true,
|
"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
|
!example/
|
||||||
/launch.json
|
!ReadMe.md
|
||||||
/settings.json
|
|
||||||
/tasks.json
|
|
||||||
|
|||||||
@@ -1,11 +1,7 @@
|
|||||||
{
|
{
|
||||||
"C_Cpp.default.cStandard": "gnu23",
|
|
||||||
"C_Cpp.default.cppStandard": "c++20",
|
|
||||||
"python.formatting.provider": "black",
|
|
||||||
"workbench.tree.indent": 12,
|
"workbench.tree.indent": 12,
|
||||||
"cortex-debug.enableTelemetry": false,
|
"cortex-debug.enableTelemetry": false,
|
||||||
"cortex-debug.variableUseNaturalFormat": true,
|
"cortex-debug.variableUseNaturalFormat": true,
|
||||||
"cortex-debug.showRTOS": true,
|
|
||||||
"cortex-debug.armToolchainPath": "${workspaceFolder}/toolchain/current/bin",
|
"cortex-debug.armToolchainPath": "${workspaceFolder}/toolchain/current/bin",
|
||||||
"cortex-debug.openocdPath": "${workspaceFolder}/toolchain/current/bin/openocd",
|
"cortex-debug.openocdPath": "${workspaceFolder}/toolchain/current/bin/openocd",
|
||||||
"cortex-debug.gdbPath": "${workspaceFolder}/toolchain/current/bin/arm-none-eabi-gdb-py3",
|
"cortex-debug.gdbPath": "${workspaceFolder}/toolchain/current/bin/arm-none-eabi-gdb-py3",
|
||||||
@@ -16,9 +12,9 @@
|
|||||||
"SConstruct": "python",
|
"SConstruct": "python",
|
||||||
"*.fam": "python"
|
"*.fam": "python"
|
||||||
},
|
},
|
||||||
|
// "clangd.path": "${workspaceFolder}/toolchain/current/bin/clangd@FBT_PLATFORM_EXECUTABLE_EXT@",
|
||||||
"clangd.arguments": [
|
"clangd.arguments": [
|
||||||
// We might be able to tighten this a bit more to only include the correct toolchain.
|
"--query-driver=**/arm-none-eabi-*",
|
||||||
"--query-driver=**",
|
|
||||||
"--compile-commands-dir=${workspaceFolder}/build/latest",
|
"--compile-commands-dir=${workspaceFolder}/build/latest",
|
||||||
"--clang-tidy",
|
"--clang-tidy",
|
||||||
"--header-insertion=never"
|
"--header-insertion=never"
|
||||||
105
CHANGELOG.md
105
CHANGELOG.md
@@ -1,57 +1,64 @@
|
|||||||
## Main changes
|
## Main changes
|
||||||
- SubGHz:
|
- SubGHz:
|
||||||
- Add new protocol - legrand 18bit (by @user890104)
|
- **Novoferm** remotes full support
|
||||||
- OFW: Princeton protocol add custom guard time support
|
- Fix Decode scene in RAW files
|
||||||
- Princeton fix guard time bounds and show guard time multiplier in UI
|
- 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:
|
- 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)
|
- OFW: Ultralight C authentication with des key
|
||||||
- Better plugins(parsers) loading - much faster emulation launch from favourites, no more lags in Saved menu
|
- EMV Transactions less nested, hide if unavailable (by @Willy-JL | PR #771)
|
||||||
- OFW: MF Ultralight Original write support
|
- Update Mifare Classic default keys dict with new keys from proxmark3 repo and UberGuidoZ repo
|
||||||
- OFW: Mifare Plus detection support
|
- LF RFID:
|
||||||
- OFW: Felica emulation
|
- Update T5577 password list (by @korden32 | PR #774)
|
||||||
- OFW: Write to ultralight cards is now possible (no UID writing)
|
- Add DEZ 8 display form for EM4100 (by @korden32 | PR #776 & (#777 by @mishamyte))
|
||||||
- OFW: Fixed infinite loop in dictionary attack scene
|
- JS:
|
||||||
* LF RFID: OFW: Added Support for Securakey Protocol
|
- Refactor widget and keyboard modules, fix crash (by @Willy-JL | PR #770)
|
||||||
* JS: `adc` support in `gpio` module (by @jamisonderek)
|
- SubGHz module fixes and improvements (by @Willy-JL)
|
||||||
* JS: `storage` module (without virtual mount API at the moment) (by @Willy-JL)
|
* OFW: Infrared: check for negative timings
|
||||||
* BadUSB: Add Finnish keyboard layout (by @nicou | PR #761)
|
* OFW: Fix iButton/LFRFID Add Manually results being discarded
|
||||||
* Archive: Fix SubGHz Remote files in favourites falling into non working and non removable state
|
* 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)
|
* Apps: **Check out more Apps updates and fixes by following** [this link](https://github.com/xMasterX/all-the-plugins/commits/dev)
|
||||||
## Other changes
|
## Other changes
|
||||||
* SubGHz: Fix add manually princeton
|
* OFW: HID/BLE Keyboard UI refactoring
|
||||||
* SubGHz: Sync signal delete scene with OFW
|
* OFW: CCID: Add CCIDWorker
|
||||||
* SubGHz: Fix incorrect rx key state when opening Read menu
|
* OFW: Disabled ISR runtime stats collection for updater builds
|
||||||
* 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
|
* OFW: VSCode fixes: .gitignore & clangd
|
||||||
* Misc: Remove outdated brew sdk install files
|
* OFW: ufbt: synced .clang-format rules with main
|
||||||
* Misc: Revert USB CDC changes to fix usb serial
|
* OFW: Code formatting update
|
||||||
* Misc: Fix usage of deprecated `icon_get_data`
|
* OFW: scripts: runfap: fixed starting apps with spaces in path
|
||||||
* Loader: Better API Mismatch message (by @Willy-JL)
|
* OFW: toolchain: v38. clangd as default language server
|
||||||
* CLI: Move part of the CLI to microsd to free up space for COMPACT 0 builds (by @Willy-JL)
|
* OFW: NFC: ISO15693 Render Typo Fix
|
||||||
* NFC: Fix typo in parsers
|
* OFW: tar archive: fix double free
|
||||||
* Apps: Fix `input_callback` and `timer_callback` usage of non `void` argument as input
|
* OFW: ufbt: added ARGS to commandline parser
|
||||||
* LF RFID: OFW PR 3728: Securakey - Add Support for RKKTH Plain Text Format (by @zinongli)
|
* OFW: lib: sconscript todo cleanup
|
||||||
* OFW: ReadMe: update outdated bits and pieces
|
* OFW: Intruder animation
|
||||||
* OFW: Debug: backup openocd work area, fix crash after fresh debugger connect and continue
|
* OFW: Desktop: allow to close blocking bad sd animation
|
||||||
* OFW: ELF, Flipper application: do not crash on "out of memory"
|
* OFW: Updater: reset various debug flags on production build flash (was done in same way in UL before)
|
||||||
* OFW: MF Plus - Don't crash on reading weird cards
|
* OFW: Fix PVS Warnings
|
||||||
* OFW: SubGhz: fix Missed the "Deleted" screen when deleting RAW Subghz (by @Skorpionm)
|
* OFW: CCID: Improve request and response data handling
|
||||||
* OFW: JS: Disable logging in mjs +2k free flash (by @hedger)
|
* OFW: Furi: count ISR time. Cli: show ISR time in top.
|
||||||
* OFW: Archive: fix memory leak in favorites add/remove
|
* OFW: toolchain: v37
|
||||||
* OFW: Furi: Fix EventLoop state persisting on same thread after free
|
* OFW: NFC: Cache plugin name not full path, saves some RAM (by @Willy-JL)
|
||||||
* OFW: Cli: top
|
* OFW: copro: bumped to 1.20.0
|
||||||
* OFW: Desktop lockup fix, GUI improvements
|
* OFW: input_srv: Put input state data on the stack of the service
|
||||||
* OFW: Loader: fix crash on "locked via cli loader"
|
* OFW: Coalesce some allocations
|
||||||
* OFW: SubGhz: fix navigation GUI
|
* OFW: updater: slightly smaller image
|
||||||
* OFW: Furi: event loop
|
* OFW: Updater: Fix double dir cleanup
|
||||||
* OFW: Code Cleanup: unused includes, useless checks, unused variables, etc...
|
* OFW: cli: storage: minor subcommand lookup refactor
|
||||||
* OFW: SubGhz: fix gui "No transition to the "Saved" menu when deleting a SubGHz RAW file"
|
* OFW: LFRFID Securakey: Add Support for RKKTH Plain Text Format
|
||||||
* OFW: RPC: Add TarExtract command, some small fixes
|
* OFW: NFC: Add mf_classic_set_sector_trailer_read function
|
||||||
* OFW: Use static synchronisation primitives
|
* OFW: Separate editing and renaming in iButton and LFRFID
|
||||||
* OFW: cleanup of various warnings from clangd
|
* OFW: New js modules documentation added
|
||||||
* OFW: Add initial ISO7816 support
|
* OFW: Update link to mfkey32
|
||||||
* OFW: fbt, vscode: tweaks for cdb generation for clangd
|
* OFW: NFC: Desfire Renderer Minor Debug
|
||||||
* OFW: Updater: fix inability to update with bigger updater.bin
|
* OFW: RPC: Fix input lockup on disconnect
|
||||||
* OFW: Furi: wrap message queue in container, prepare it for epoll. Accessor: disable expansion service on start.
|
* OFW: Thread Signals
|
||||||
<br><br>
|
<br><br>
|
||||||
#### Known NFC post-refactor regressions list:
|
#### Known NFC post-refactor regressions list:
|
||||||
- Mifare Mini clones reading is broken (original mini working fine) (OFW)
|
- 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)
|
- Infrared -> External IR modules support (with autodetect by OFW)
|
||||||
- **NFC/RFID/iButton**
|
- **NFC/RFID/iButton**
|
||||||
* LFRFID and iButton Fuzzer plugins
|
* LFRFID and iButton Fuzzer plugins
|
||||||
|
* Add DEZ 8 display form for EM4100 (by @korden32)
|
||||||
* Extra Mifare Classic keys in system dict
|
* Extra Mifare Classic keys in system dict
|
||||||
* EMV Protocol + Public data parser (by @Leptopt1los and @wosk)
|
* EMV Protocol + Public data parser (by @Leptopt1los and @wosk)
|
||||||
* NFC `Add manually` -> Mifare Classic with custom UID
|
* 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)
|
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)
|
- Nero Radio 57bit (+ 56bit support)
|
||||||
- CAME 12bit/24bit encoder fixes (Fixes are now merged in OFW)
|
- 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)
|
- 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)
|
- 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)
|
- Keeloq: BFT Mitto -> Update! Check out new [instructions](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/SubGHzRemoteProg.md)
|
||||||
- Star Line
|
- Star Line
|
||||||
- Security+ v1 & v2 (encoders was made in OFW)
|
- Security+ v1 & v2
|
||||||
|
|
||||||
Encoders made by @assasinfil and @xMasterX:
|
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)
|
- 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",
|
"blackmagic",
|
||||||
"jflash",
|
"jflash",
|
||||||
"doxygen",
|
"doxygen",
|
||||||
|
"textfile",
|
||||||
],
|
],
|
||||||
ENV=os.environ,
|
ENV=os.environ,
|
||||||
UPDATE_BUNDLE_DIR="dist/${DIST_DIR}/f${TARGET_HW}-update-${DIST_SUFFIX}",
|
UPDATE_BUNDLE_DIR="dist/${DIST_DIR}/f${TARGET_HW}-update-${DIST_SUFFIX}",
|
||||||
VSCODE_LANG_SERVER=ARGUMENTS.get("LANG_SERVER", "cpptools"),
|
|
||||||
)
|
)
|
||||||
|
|
||||||
firmware_env = distenv.AddFwProject(
|
firmware_env = distenv.AddFwProject(
|
||||||
@@ -403,14 +403,23 @@ distenv.PhonyTarget(
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Prepare vscode environment
|
# Prepare vscode environment
|
||||||
VSCODE_LANG_SERVER = cmd_environment["LANG_SERVER"]
|
|
||||||
vscode_dist = distenv.Install(
|
vscode_dist = distenv.Install(
|
||||||
"#.vscode",
|
"#.vscode",
|
||||||
[
|
[
|
||||||
distenv.Glob("#.vscode/example/*.json"),
|
distenv.Glob("#.vscode/example/*.json", exclude="*.tmpl"),
|
||||||
distenv.Glob(f"#.vscode/example/{VSCODE_LANG_SERVER}/*.json"),
|
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.Precious(vscode_dist)
|
||||||
distenv.NoClean(vscode_dist)
|
distenv.NoClean(vscode_dist)
|
||||||
distenv.Alias("vscode_dist", (vscode_dist, firmware_env["FW_CDB"]))
|
distenv.Alias("vscode_dist", (vscode_dist, firmware_env["FW_CDB"]))
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
#include <gui/elements.h>
|
#include <gui/elements.h>
|
||||||
#include <assets_icons.h>
|
#include <assets_icons.h>
|
||||||
|
|
||||||
#define LOW_CHARGE_THRESHOLD 10
|
#define LOW_CHARGE_THRESHOLD 10
|
||||||
#define HIGH_DRAIN_CURRENT_THRESHOLD 100
|
#define HIGH_DRAIN_CURRENT_THRESHOLD 100
|
||||||
|
|
||||||
struct BatteryInfo {
|
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_draw_box(canvas, x - 4, y + 16, 24, 6);
|
||||||
canvas_set_color(canvas, ColorBlack);
|
canvas_set_color(canvas, ColorBlack);
|
||||||
canvas_draw_str_aligned(canvas, x + 8, y + 22, AlignCenter, AlignBottom, val);
|
canvas_draw_str_aligned(canvas, x + 8, y + 22, AlignCenter, AlignBottom, val);
|
||||||
};
|
}
|
||||||
|
|
||||||
static void draw_battery(Canvas* canvas, BatteryInfoModel* data, int x, int y) {
|
static void draw_battery(Canvas* canvas, BatteryInfoModel* data, int x, int y) {
|
||||||
char emote[20] = {};
|
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 + 3, AlignCenter, AlignCenter, emote);
|
||||||
canvas_draw_str_aligned(canvas, 92, y + 15, AlignCenter, AlignCenter, header);
|
canvas_draw_str_aligned(canvas, 92, y + 15, AlignCenter, AlignCenter, header);
|
||||||
canvas_draw_str_aligned(canvas, 92, y + 27, AlignCenter, AlignCenter, value);
|
canvas_draw_str_aligned(canvas, 92, y + 27, AlignCenter, AlignCenter, value);
|
||||||
};
|
}
|
||||||
|
|
||||||
static void battery_info_draw_callback(Canvas* canvas, void* context) {
|
static void battery_info_draw_callback(Canvas* canvas, void* context) {
|
||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ typedef struct {
|
|||||||
} BtTestModel;
|
} BtTestModel;
|
||||||
|
|
||||||
#define BT_TEST_START_MESSAGE "Ok - Start"
|
#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_up(BtTest* bt_test);
|
||||||
static void bt_test_process_down(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) {
|
void bt_test_set_rssi(BtTest* bt_test, float rssi) {
|
||||||
furi_assert(bt_test);
|
furi_assert(bt_test);
|
||||||
with_view_model(
|
with_view_model(bt_test->view, BtTestModel * model, { model->rssi = rssi; }, true);
|
||||||
bt_test->view, BtTestModel * model, { model->rssi = rssi; }, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void bt_test_set_packets_tx(BtTest* bt_test, uint32_t packets_num) {
|
void bt_test_set_packets_tx(BtTest* bt_test, uint32_t packets_num) {
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
#include "iso7816_callbacks.h"
|
#include "iso7816_callbacks.h"
|
||||||
#include "iso7816_t0_apdu.h"
|
#include "iso7816_t0_apdu.h"
|
||||||
#include "iso7816_atr.h"
|
#include "iso7816_atr.h"
|
||||||
|
#include "iso7816_response.h"
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
EventTypeInput,
|
EventTypeInput,
|
||||||
@@ -118,6 +119,80 @@ static const CcidCallbacks ccid_cb = {
|
|||||||
ccid_xfr_datablock_callback,
|
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) {
|
void iso7816_answer_to_reset(Iso7816Atr* atr) {
|
||||||
//minimum valid ATR: https://smartcard-atr.apdu.fr/parse?ATR=3B+00
|
//minimum valid ATR: https://smartcard-atr.apdu.fr/parse?ATR=3B+00
|
||||||
atr->TS = 0x3B;
|
atr->TS = 0x3B;
|
||||||
@@ -125,48 +200,38 @@ void iso7816_answer_to_reset(Iso7816Atr* atr) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void iso7816_process_command(
|
void iso7816_process_command(
|
||||||
const struct ISO7816_Command_APDU* commandAPDU,
|
const ISO7816_Command_APDU* commandAPDU,
|
||||||
struct ISO7816_Response_APDU* responseAPDU,
|
ISO7816_Response_APDU* responseAPDU) {
|
||||||
const uint8_t* commandApduDataBuffer,
|
|
||||||
uint8_t commandApduDataBufferLen,
|
|
||||||
uint8_t* responseApduDataBuffer,
|
|
||||||
uint8_t* responseApduDataBufferLen) {
|
|
||||||
//example 1: sends a command with no body, receives a response with no body
|
//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
|
//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;
|
if(commandAPDU->CLA == 0x01) {
|
||||||
|
switch(commandAPDU->INS) {
|
||||||
responseAPDU->SW1 = 0x90;
|
case 0x01:
|
||||||
responseAPDU->SW2 = 0x00;
|
handle_instruction_01(responseAPDU);
|
||||||
}
|
break;
|
||||||
//example 3: ends a command with a body with two bytes, receives a response with a body with two bytes
|
case 0x02:
|
||||||
//sends APDU 0x01:0x03:0x00:0x00:0x02:CA:FE
|
handle_instruction_02(
|
||||||
//receives (0xCA, 0xFE) SW1=0x90, SW2=0x02
|
commandAPDU->P1, commandAPDU->P2, commandAPDU->Lc, commandAPDU->Le, responseAPDU);
|
||||||
else if(
|
break;
|
||||||
commandAPDU->CLA == 0x01 && commandAPDU->INS == 0x03 && commandApduDataBufferLen == 2 &&
|
case 0x03:
|
||||||
commandAPDU->Lc == 2) {
|
handle_instruction_03(commandAPDU->P1, commandAPDU->P2, commandAPDU->Lc, responseAPDU);
|
||||||
//echo command body to response body
|
break;
|
||||||
responseApduDataBuffer[0] = commandApduDataBuffer[0];
|
case 0x04:
|
||||||
responseApduDataBuffer[1] = commandApduDataBuffer[1];
|
handle_instruction_04(
|
||||||
|
commandAPDU->P1,
|
||||||
*responseApduDataBufferLen = 2;
|
commandAPDU->P2,
|
||||||
|
commandAPDU->Lc,
|
||||||
responseAPDU->SW1 = 0x90;
|
commandAPDU->Le,
|
||||||
responseAPDU->SW2 = 0x00;
|
commandAPDU->Data,
|
||||||
|
responseAPDU);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
iso7816_set_response(responseAPDU, ISO7816_RESPONSE_INSTRUCTION_NOT_SUPPORTED);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
responseAPDU->SW1 = 0x6A;
|
iso7816_set_response(responseAPDU, ISO7816_RESPONSE_CLASS_NOT_SUPPORTED);
|
||||||
responseAPDU->SW2 = 0x00;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -188,8 +253,10 @@ int32_t ccid_test_app(void* p) {
|
|||||||
|
|
||||||
FuriHalUsbInterface* usb_mode_prev = furi_hal_usb_get_config();
|
FuriHalUsbInterface* usb_mode_prev = furi_hal_usb_get_config();
|
||||||
furi_hal_usb_unlock();
|
furi_hal_usb_unlock();
|
||||||
furi_hal_ccid_set_callbacks((CcidCallbacks*)&ccid_cb, NULL);
|
|
||||||
furi_check(furi_hal_usb_set_config(&usb_ccid, &app->ccid_cfg) == true);
|
furi_check(furi_hal_usb_set_config(&usb_ccid, &app->ccid_cfg) == true);
|
||||||
|
furi_hal_usb_ccid_set_callbacks((CcidCallbacks*)&ccid_cb, NULL);
|
||||||
|
furi_hal_usb_ccid_insert_smartcard();
|
||||||
|
|
||||||
iso7816_set_callbacks((Iso7816Callbacks*)&iso87816_cb);
|
iso7816_set_callbacks((Iso7816Callbacks*)&iso87816_cb);
|
||||||
|
|
||||||
@@ -210,8 +277,8 @@ int32_t ccid_test_app(void* p) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//tear down USB
|
//tear down USB
|
||||||
|
furi_hal_usb_ccid_set_callbacks(NULL, NULL);
|
||||||
furi_hal_usb_set_config(usb_mode_prev, NULL);
|
furi_hal_usb_set_config(usb_mode_prev, NULL);
|
||||||
furi_hal_ccid_set_callbacks(NULL, NULL);
|
|
||||||
|
|
||||||
iso7816_set_callbacks(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_
|
#pragma once
|
||||||
#define _ISO7816_ATR_H_
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t TS;
|
uint8_t TS;
|
||||||
uint8_t T0;
|
uint8_t T0;
|
||||||
} Iso7816Atr;
|
} Iso7816Atr;
|
||||||
|
|
||||||
#endif //_ISO7816_ATR_H_
|
|
||||||
|
|||||||
@@ -1,17 +1,21 @@
|
|||||||
// transforms low level calls such as XFRCallback or ICC Power on to a structured one
|
// 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
|
// 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_t0_apdu.h"
|
||||||
#include "iso7816_atr.h"
|
#include "iso7816_atr.h"
|
||||||
#include "iso7816_callbacks.h"
|
#include "iso7816_callbacks.h"
|
||||||
#include <stdint.h>
|
#include "iso7816_response.h"
|
||||||
#include <stddef.h>
|
|
||||||
#include <furi.h>
|
|
||||||
|
|
||||||
#define ISO7816_RESPONSE_BUFFER_SIZE 255
|
|
||||||
|
|
||||||
static Iso7816Callbacks* callbacks = NULL;
|
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) {
|
void iso7816_set_callbacks(Iso7816Callbacks* cb) {
|
||||||
callbacks = cb;
|
callbacks = cb;
|
||||||
}
|
}
|
||||||
@@ -36,41 +40,26 @@ void iso7816_xfr_datablock_callback(
|
|||||||
uint32_t pcToReaderDataBlockLen,
|
uint32_t pcToReaderDataBlockLen,
|
||||||
uint8_t* readerToPcDataBlock,
|
uint8_t* readerToPcDataBlock,
|
||||||
uint32_t* readerToPcDataBlockLen) {
|
uint32_t* readerToPcDataBlockLen) {
|
||||||
struct ISO7816_Response_APDU responseAPDU;
|
ISO7816_Response_APDU* responseAPDU = (ISO7816_Response_APDU*)&responseApduBuffer;
|
||||||
uint8_t responseApduDataBuffer[ISO7816_RESPONSE_BUFFER_SIZE];
|
|
||||||
uint8_t responseApduDataBufferLen = 0;
|
|
||||||
|
|
||||||
if(callbacks != NULL) {
|
if(callbacks != NULL) {
|
||||||
struct ISO7816_Command_APDU commandAPDU;
|
ISO7816_Command_APDU* commandAPDU = (ISO7816_Command_APDU*)&commandApduBuffer;
|
||||||
|
|
||||||
const uint8_t* commandApduDataBuffer = NULL;
|
uint8_t result =
|
||||||
uint8_t commandApduDataBufferLen = 0;
|
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) {
|
furi_assert(responseAPDU->DataLen < CCID_SHORT_APDU_SIZE);
|
||||||
commandApduDataBufferLen = commandAPDU.Lc;
|
} else if(result == ISO7816_READ_COMMAND_APDU_ERROR_WRONG_LE) {
|
||||||
commandApduDataBuffer = &pcToReaderDataBlock[5];
|
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 {
|
} else {
|
||||||
//class not supported
|
iso7816_set_response(responseAPDU, ISO7816_RESPONSE_INTERNAL_EXCEPTION);
|
||||||
responseAPDU.SW1 = 0x6E;
|
|
||||||
responseAPDU.SW2 = 0x00;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
iso7816_write_response_apdu(
|
iso7816_write_response_apdu(responseAPDU, readerToPcDataBlock, readerToPcDataBlockLen);
|
||||||
&responseAPDU,
|
|
||||||
readerToPcDataBlock,
|
|
||||||
readerToPcDataBlockLen,
|
|
||||||
responseApduDataBuffer,
|
|
||||||
responseApduDataBufferLen);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
#ifndef _ISO7816_CALLBACKS_H_
|
#pragma once
|
||||||
#define _ISO7816_CALLBACKS_H_
|
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "iso7816_atr.h"
|
#include "iso7816_atr.h"
|
||||||
@@ -8,12 +7,8 @@
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
void (*iso7816_answer_to_reset)(Iso7816Atr* atr);
|
void (*iso7816_answer_to_reset)(Iso7816Atr* atr);
|
||||||
void (*iso7816_process_command)(
|
void (*iso7816_process_command)(
|
||||||
const struct ISO7816_Command_APDU* command,
|
const ISO7816_Command_APDU* command,
|
||||||
struct ISO7816_Response_APDU* response,
|
ISO7816_Response_APDU* response);
|
||||||
const uint8_t* commandApduDataBuffer,
|
|
||||||
uint8_t commandApduDataBufferLen,
|
|
||||||
uint8_t* responseApduDataBuffer,
|
|
||||||
uint8_t* responseApduDataBufferLen);
|
|
||||||
} Iso7816Callbacks;
|
} Iso7816Callbacks;
|
||||||
|
|
||||||
void iso7816_set_callbacks(Iso7816Callbacks* cb);
|
void iso7816_set_callbacks(Iso7816Callbacks* cb);
|
||||||
@@ -24,5 +19,3 @@ void iso7816_xfr_datablock_callback(
|
|||||||
uint32_t dataBlockLen,
|
uint32_t dataBlockLen,
|
||||||
uint8_t* responseDataBlock,
|
uint8_t* responseDataBlock,
|
||||||
uint32_t* responseDataBlockLen);
|
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 <stdint.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <furi.h>
|
#include <furi.h>
|
||||||
|
#include <furi_hal.h>
|
||||||
#include "iso7816_t0_apdu.h"
|
#include "iso7816_t0_apdu.h"
|
||||||
|
|
||||||
//reads dataBuffer with dataLen size, translate it into a ISO7816_Command_APDU type
|
//reads dataBuffer with dataLen size, translate it into a ISO7816_Command_APDU type
|
||||||
//extra data will be pointed to commandDataBuffer
|
//extra data will be pointed to commandDataBuffer
|
||||||
void iso7816_read_command_apdu(
|
uint8_t iso7816_read_command_apdu(
|
||||||
struct ISO7816_Command_APDU* command,
|
ISO7816_Command_APDU* command,
|
||||||
const uint8_t* dataBuffer,
|
const uint8_t* dataBuffer,
|
||||||
uint32_t dataLen) {
|
uint32_t dataLen) {
|
||||||
UNUSED(dataLen);
|
|
||||||
|
|
||||||
command->CLA = dataBuffer[0];
|
command->CLA = dataBuffer[0];
|
||||||
command->INS = dataBuffer[1];
|
command->INS = dataBuffer[1];
|
||||||
command->P1 = dataBuffer[2];
|
command->P1 = dataBuffer[2];
|
||||||
command->P2 = dataBuffer[3];
|
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(
|
void iso7816_write_response_apdu(
|
||||||
const struct ISO7816_Response_APDU* response,
|
const ISO7816_Response_APDU* response,
|
||||||
uint8_t* readerToPcDataBlock,
|
uint8_t* readerToPcDataBlock,
|
||||||
uint32_t* readerToPcDataBlockLen,
|
uint32_t* readerToPcDataBlockLen) {
|
||||||
uint8_t* responseDataBuffer,
|
|
||||||
uint32_t responseDataLen) {
|
|
||||||
uint32_t responseDataBufferIndex = 0;
|
uint32_t responseDataBufferIndex = 0;
|
||||||
|
|
||||||
//response body
|
//response body
|
||||||
if(responseDataLen > 0) {
|
if(response->DataLen > 0) {
|
||||||
while(responseDataBufferIndex < responseDataLen) {
|
while(responseDataBufferIndex < response->DataLen) {
|
||||||
readerToPcDataBlock[responseDataBufferIndex] =
|
readerToPcDataBlock[responseDataBufferIndex] = response->Data[responseDataBufferIndex];
|
||||||
responseDataBuffer[responseDataBufferIndex];
|
|
||||||
responseDataBufferIndex++;
|
responseDataBufferIndex++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,14 @@
|
|||||||
#ifndef _ISO7816_T0_APDU_H_
|
#pragma once
|
||||||
#define _ISO7816_T0_APDU_H_
|
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "iso7816_atr.h"
|
#include "iso7816_atr.h"
|
||||||
#include "core/common_defines.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
|
//header
|
||||||
uint8_t CLA;
|
uint8_t CLA;
|
||||||
uint8_t INS;
|
uint8_t INS;
|
||||||
@@ -13,24 +16,27 @@ struct ISO7816_Command_APDU {
|
|||||||
uint8_t P2;
|
uint8_t P2;
|
||||||
|
|
||||||
//body
|
//body
|
||||||
uint8_t Lc;
|
uint16_t Lc; //data length
|
||||||
uint8_t Le;
|
uint16_t Le; //maximum response data length expected by client
|
||||||
} FURI_PACKED;
|
|
||||||
|
|
||||||
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 SW1;
|
||||||
uint8_t SW2;
|
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_answer_to_reset(Iso7816Atr* atr);
|
||||||
void iso7816_read_command_apdu(
|
uint8_t iso7816_read_command_apdu(
|
||||||
struct ISO7816_Command_APDU* command,
|
ISO7816_Command_APDU* command,
|
||||||
const uint8_t* dataBuffer,
|
const uint8_t* pcToReaderDataBlock,
|
||||||
uint32_t dataLen);
|
uint32_t pcToReaderDataBlockLen);
|
||||||
void iso7816_write_response_apdu(
|
void iso7816_write_response_apdu(
|
||||||
const struct ISO7816_Response_APDU* response,
|
const ISO7816_Response_APDU* response,
|
||||||
uint8_t* readerToPcDataBlock,
|
uint8_t* readerToPcDataBlock,
|
||||||
uint32_t* readerToPcDataBlockLen,
|
uint32_t* readerToPcDataBlockLen);
|
||||||
uint8_t* responseDataBuffer,
|
|
||||||
uint32_t responseDataLen);
|
|
||||||
#endif //_ISO7816_T0_APDU_H_
|
|
||||||
|
|||||||
@@ -150,8 +150,7 @@ static void view_display_test_exit(void* context) {
|
|||||||
|
|
||||||
static void view_display_test_timer_callback(void* context) {
|
static void view_display_test_timer_callback(void* context) {
|
||||||
ViewDisplayTest* instance = context;
|
ViewDisplayTest* instance = context;
|
||||||
with_view_model(
|
with_view_model(instance->view, ViewDisplayTestModel * model, { model->counter++; }, true);
|
||||||
instance->view, ViewDisplayTestModel * model, { model->counter++; }, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ViewDisplayTest* view_display_test_alloc(void) {
|
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 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_NAME "test.txt"
|
||||||
#define TEST_FILE_PATH EXT_PATH(TAG "/" TEST_FILE_NAME)
|
#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 MODULE_SERIAL_ID (FuriHalSerialIdUsart)
|
||||||
|
|
||||||
#define RECEIVE_BUFFER_SIZE (sizeof(ExpansionFrame) + sizeof(ExpansionFrameChecksum))
|
#define RECEIVE_BUFFER_SIZE (sizeof(ExpansionFrame) + sizeof(ExpansionFrameChecksum))
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
#include <furi.h>
|
#include <furi.h>
|
||||||
|
|
||||||
#define DEFAULT_PATH "/"
|
#define DEFAULT_PATH "/"
|
||||||
#define EXTENSION "*"
|
#define EXTENSION "*"
|
||||||
|
|
||||||
bool file_browser_scene_browser_on_event(void* context, SceneManagerEvent event) {
|
bool file_browser_scene_browser_on_event(void* context, SceneManagerEvent event) {
|
||||||
UNUSED(context);
|
UNUSED(context);
|
||||||
|
|||||||
@@ -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 lfrfid_debug_view_tune_get_arr(LfRfidTuneView* tune_view) {
|
||||||
uint32_t result = false;
|
uint32_t result = false;
|
||||||
with_view_model(
|
with_view_model(tune_view->view, LfRfidTuneViewModel * model, { result = model->ARR; }, false);
|
||||||
tune_view->view, LfRfidTuneViewModel * model, { result = model->ARR; }, false);
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t lfrfid_debug_view_tune_get_ccr(LfRfidTuneView* tune_view) {
|
uint32_t lfrfid_debug_view_tune_get_ccr(LfRfidTuneView* tune_view) {
|
||||||
uint32_t result = false;
|
uint32_t result = false;
|
||||||
with_view_model(
|
with_view_model(tune_view->view, LfRfidTuneViewModel * model, { result = model->CCR; }, false);
|
||||||
tune_view->view, LfRfidTuneViewModel * model, { result = model->CCR; }, false);
|
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
#include <toolbox/args.h>
|
#include <toolbox/args.h>
|
||||||
|
|
||||||
#define TAG "SpeakerDebug"
|
#define TAG "SpeakerDebug"
|
||||||
|
|
||||||
#define CLI_COMMAND "speaker_debug"
|
#define CLI_COMMAND "speaker_debug"
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
|||||||
@@ -4,8 +4,8 @@
|
|||||||
#include <furi_hal.h>
|
#include <furi_hal.h>
|
||||||
|
|
||||||
#define SUBGHZ_TEST_VERSION_APP "0.1"
|
#define SUBGHZ_TEST_VERSION_APP "0.1"
|
||||||
#define SUBGHZ_TEST_DEVELOPED "SkorP"
|
#define SUBGHZ_TEST_DEVELOPED "SkorP"
|
||||||
#define SUBGHZ_TEST_GITHUB "https://github.com/flipperdevices/flipperzero-firmware"
|
#define SUBGHZ_TEST_GITHUB "https://github.com/flipperdevices/flipperzero-firmware"
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
SubGhzTestViewVariableItemList,
|
SubGhzTestViewVariableItemList,
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
(value) &= ~(_one << (bit)); \
|
(value) &= ~(_one << (bit)); \
|
||||||
})
|
})
|
||||||
#define bit_write(value, bit, bitvalue) (bitvalue ? bit_set(value, bit) : bit_clear(value, 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
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|||||||
@@ -9,13 +9,13 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define SUBGHZ_PT_SHORT 300
|
#define SUBGHZ_PT_SHORT 300
|
||||||
#define SUBGHZ_PT_LONG (SUBGHZ_PT_SHORT * 3)
|
#define SUBGHZ_PT_LONG (SUBGHZ_PT_SHORT * 3)
|
||||||
#define SUBGHZ_PT_GUARD (SUBGHZ_PT_SHORT * 30)
|
#define SUBGHZ_PT_GUARD (SUBGHZ_PT_SHORT * 30)
|
||||||
#define SUBGHZ_PT_COUNT_KEY_433 9
|
#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_COUNT_KEY_868 9
|
||||||
#define SUBGHZ_PT_TIMEOUT_868 14000
|
#define SUBGHZ_PT_TIMEOUT_868 14000
|
||||||
|
|
||||||
#define TAG "SubGhzProtocolPrinceton"
|
#define TAG "SubGhzProtocolPrinceton"
|
||||||
|
|
||||||
|
|||||||
@@ -9,9 +9,10 @@
|
|||||||
#include <notification/notification.h>
|
#include <notification/notification.h>
|
||||||
#include <notification/notification_messages.h>
|
#include <notification/notification_messages.h>
|
||||||
|
|
||||||
#define LINES_ON_SCREEN 6
|
|
||||||
#define COLUMNS_ON_SCREEN 21
|
|
||||||
#define TAG "UartEcho"
|
#define TAG "UartEcho"
|
||||||
|
|
||||||
|
#define LINES_ON_SCREEN 6
|
||||||
|
#define COLUMNS_ON_SCREEN 21
|
||||||
#define DEFAULT_BAUD_RATE 230400
|
#define DEFAULT_BAUD_RATE 230400
|
||||||
|
|
||||||
typedef struct UartDumpModel UartDumpModel;
|
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;
|
bool new_string_needed = false;
|
||||||
if(furi_string_size(model->list[model->line]->text) >= COLUMNS_ON_SCREEN) {
|
if(furi_string_size(model->list[model->line]->text) >= COLUMNS_ON_SCREEN) {
|
||||||
new_string_needed = true;
|
new_string_needed = true;
|
||||||
} else if((data == '\n' || data == '\r')) {
|
} else if(data == '\n' || data == '\r') {
|
||||||
// pack line breaks
|
// pack line breaks
|
||||||
if(model->last_char != '\n' && model->last_char != '\r') {
|
if(model->last_char != '\n' && model->last_char != '\r') {
|
||||||
new_string_needed = true;
|
new_string_needed = true;
|
||||||
@@ -206,8 +207,7 @@ static int32_t uart_echo_worker(void* context) {
|
|||||||
} while(length > 0);
|
} while(length > 0);
|
||||||
|
|
||||||
notification_message(app->notification, &sequence_notification);
|
notification_message(app->notification, &sequence_notification);
|
||||||
with_view_model(
|
with_view_model(app->view, UartDumpModel * model, { UNUSED(model); }, true);
|
||||||
app->view, UartDumpModel * model, { UNUSED(model); }, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(events & WorkerEventRxIdle) {
|
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);
|
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"
|
#define TEST_RUNNER_TMP_UNIT_TESTS_DIR TEST_RUNNER_TMP_DIR "/unit_tests"
|
||||||
|
|
||||||
static bool test_runner_run_plugin(TestRunner* instance, const char* path) {
|
static bool test_runner_run_plugin(TestRunner* instance, const char* path) {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
#include <storage/storage.h>
|
#include <storage/storage.h>
|
||||||
|
|
||||||
#define BT_TEST_KEY_STORAGE_FILE_PATH EXT_PATH("unit_tests/bt_test.keys")
|
#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 {
|
typedef struct {
|
||||||
Storage* storage;
|
Storage* storage;
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
#include "../test.h" // IWYU pragma: keep
|
#include "../test.h" // IWYU pragma: keep
|
||||||
|
|
||||||
#include <toolbox/compress.h>
|
#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.h>
|
||||||
#include <furi_hal.h>
|
#include <furi_hal.h>
|
||||||
@@ -56,7 +59,7 @@ static void compress_test_reference_comp_decomp() {
|
|||||||
furi_record_close(RECORD_STORAGE);
|
furi_record_close(RECORD_STORAGE);
|
||||||
|
|
||||||
uint8_t* temp_buffer = malloc(1024);
|
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;
|
size_t encoded_size = 0;
|
||||||
mu_assert(
|
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
|
// 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;
|
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* src_buff = malloc(src_buffer_size);
|
||||||
uint8_t* encoded_buff = malloc(encoded_buffer_size);
|
uint8_t* encoded_buff = malloc(encoded_buffer_size);
|
||||||
uint8_t* decoded_buff = malloc(src_buffer_size);
|
uint8_t* decoded_buff = malloc(src_buffer_size);
|
||||||
@@ -146,9 +149,200 @@ static void compress_test_random_comp_decomp() {
|
|||||||
compress_free(comp);
|
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_TEST_SUITE(test_compress) {
|
||||||
MU_RUN_TEST(compress_test_random_comp_decomp);
|
MU_RUN_TEST(compress_test_random_comp_decomp);
|
||||||
MU_RUN_TEST(compress_test_reference_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) {
|
int run_minunit_test_compress(void) {
|
||||||
|
|||||||
@@ -5,8 +5,8 @@
|
|||||||
|
|
||||||
#include <expansion/expansion_protocol.h>
|
#include <expansion/expansion_protocol.h>
|
||||||
|
|
||||||
#define EXPANSION_TEST_GARBAGE_MAGIC (0xB19AF)
|
#define EXPANSION_TEST_GARBAGE_MAGIC (0xB19AF)
|
||||||
#define EXPANSION_TEST_GARBAGE_BUF_SIZE (0x100U)
|
#define EXPANSION_TEST_GARBAGE_BUF_SIZE (0x100U)
|
||||||
#define EXPANSION_TEST_GARBAGE_ITERATIONS (100U)
|
#define EXPANSION_TEST_GARBAGE_ITERATIONS (100U)
|
||||||
|
|
||||||
MU_TEST(test_expansion_encoded_size) {
|
MU_TEST(test_expansion_encoded_size) {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
#include "../test.h" // IWYU pragma: keep
|
#include "../test.h" // IWYU pragma: keep
|
||||||
|
|
||||||
#define TEST_DIR_NAME EXT_PATH(".tmp/unit_tests/ff")
|
#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 char* test_filetype = "Flipper File test";
|
||||||
static const uint32_t test_version = 666;
|
static const uint32_t test_version = 666;
|
||||||
|
|||||||
@@ -5,11 +5,11 @@
|
|||||||
#include <lp5562_reg.h>
|
#include <lp5562_reg.h>
|
||||||
#include "../test.h" // IWYU pragma: keep
|
#include "../test.h" // IWYU pragma: keep
|
||||||
|
|
||||||
#define DATA_SIZE 4
|
#define DATA_SIZE 4
|
||||||
#define EEPROM_ADDRESS 0b10101000
|
#define EEPROM_ADDRESS 0b10101000
|
||||||
#define EEPROM_ADDRESS_HIGH (EEPROM_ADDRESS | 0b10)
|
#define EEPROM_ADDRESS_HIGH (EEPROM_ADDRESS | 0b10)
|
||||||
#define EEPROM_SIZE 512
|
#define EEPROM_SIZE 512
|
||||||
#define EEPROM_PAGE_SIZE 16
|
#define EEPROM_PAGE_SIZE 16
|
||||||
#define EEPROM_WRITE_DELAY_MS 6
|
#define EEPROM_WRITE_DELAY_MS 6
|
||||||
|
|
||||||
static void furi_hal_i2c_int_setup(void) {
|
static void furi_hal_i2c_int_setup(void) {
|
||||||
@@ -74,7 +74,8 @@ MU_TEST(furi_hal_i2c_int_3b) {
|
|||||||
DATA_SIZE - 1,
|
DATA_SIZE - 1,
|
||||||
LP5562_I2C_TIMEOUT);
|
LP5562_I2C_TIMEOUT);
|
||||||
mu_assert(ret, "4 rx failed");
|
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(
|
ret = furi_hal_i2c_tx(
|
||||||
&furi_hal_i2c_handle_power, LP5562_ADDRESS, data_many, DATA_SIZE, LP5562_I2C_TIMEOUT);
|
&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,
|
DATA_SIZE - 1,
|
||||||
LP5562_I2C_TIMEOUT);
|
LP5562_I2C_TIMEOUT);
|
||||||
mu_assert(ret, "7 rx failed");
|
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) {
|
MU_TEST(furi_hal_i2c_int_1b_fail) {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
#include <common/infrared_common_i.h>
|
#include <common/infrared_common_i.h>
|
||||||
#include "../test.h" // IWYU pragma: keep
|
#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_PREFIX "test_"
|
||||||
#define IR_TEST_FILE_SUFFIX ".irtest"
|
#define IR_TEST_FILE_SUFFIX ".irtest"
|
||||||
|
|
||||||
|
|||||||
@@ -6,9 +6,8 @@
|
|||||||
|
|
||||||
#define LF_RFID_READ_TIMING_MULTIPLIER 8
|
#define LF_RFID_READ_TIMING_MULTIPLIER 8
|
||||||
|
|
||||||
#define EM_TEST_DATA \
|
#define EM_TEST_DATA {0x58, 0x00, 0x85, 0x64, 0x02}
|
||||||
{ 0x58, 0x00, 0x85, 0x64, 0x02 }
|
#define EM_TEST_DATA_SIZE 5
|
||||||
#define EM_TEST_DATA_SIZE 5
|
|
||||||
#define EM_TEST_EMULATION_TIMINGS_COUNT (64 * 2)
|
#define EM_TEST_EMULATION_TIMINGS_COUNT (64 * 2)
|
||||||
|
|
||||||
const int8_t em_test_timings[EM_TEST_EMULATION_TIMINGS_COUNT] = {
|
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,
|
-32, 32, 32, -32, -32, 32, -32, 32, -32, 32, -32, 32, -32, 32,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define HID10301_TEST_DATA \
|
#define HID10301_TEST_DATA {0x8D, 0x48, 0xA8}
|
||||||
{ 0x8D, 0x48, 0xA8 }
|
#define HID10301_TEST_DATA_SIZE 3
|
||||||
#define HID10301_TEST_DATA_SIZE 3
|
|
||||||
#define HID10301_TEST_EMULATION_TIMINGS_COUNT (541 * 2)
|
#define HID10301_TEST_EMULATION_TIMINGS_COUNT (541 * 2)
|
||||||
|
|
||||||
const int8_t hid10301_test_timings[HID10301_TEST_EMULATION_TIMINGS_COUNT] = {
|
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,
|
5, -5, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4, 4, -4,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define IOPROX_XSF_TEST_DATA \
|
#define IOPROX_XSF_TEST_DATA {0x65, 0x01, 0x05, 0x39}
|
||||||
{ 0x65, 0x01, 0x05, 0x39 }
|
#define IOPROX_XSF_TEST_DATA_SIZE 4
|
||||||
#define IOPROX_XSF_TEST_DATA_SIZE 4
|
|
||||||
#define IOPROX_XSF_TEST_EMULATION_TIMINGS_COUNT (468 * 2)
|
#define IOPROX_XSF_TEST_EMULATION_TIMINGS_COUNT (468 * 2)
|
||||||
|
|
||||||
const int8_t ioprox_xsf_test_timings[IOPROX_XSF_TEST_EMULATION_TIMINGS_COUNT] = {
|
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_EMULATION_TIMINGS_COUNT (1024 * 2)
|
||||||
#define INDALA26_TEST_DATA \
|
#define INDALA26_TEST_DATA {0x3B, 0x73, 0x64, 0xA8}
|
||||||
{ 0x3B, 0x73, 0x64, 0xA8 }
|
#define INDALA26_TEST_DATA_SIZE 4
|
||||||
#define INDALA26_TEST_DATA_SIZE 4
|
|
||||||
|
|
||||||
const int8_t indala26_test_timings[INDALA26_EMULATION_TIMINGS_COUNT] = {
|
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,
|
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,
|
-1, 1, -1, 1, -1, 1, -1, 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
#define FDXB_TEST_DATA \
|
#define FDXB_TEST_DATA {0x44, 0x88, 0x23, 0xF2, 0x5A, 0x6F, 0x00, 0x01, 0x00, 0x00, 0x00}
|
||||||
{ 0x44, 0x88, 0x23, 0xF2, 0x5A, 0x6F, 0x00, 0x01, 0x00, 0x00, 0x00 }
|
#define FDXB_TEST_DATA_SIZE 11
|
||||||
#define FDXB_TEST_DATA_SIZE 11
|
|
||||||
#define FDXB_TEST_EMULATION_TIMINGS_COUNT (206)
|
#define FDXB_TEST_EMULATION_TIMINGS_COUNT (206)
|
||||||
|
|
||||||
const int8_t fdxb_test_timings[FDXB_TEST_EMULATION_TIMINGS_COUNT] = {
|
const int8_t fdxb_test_timings[FDXB_TEST_EMULATION_TIMINGS_COUNT] = {
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ extern "C" {
|
|||||||
/* Maximum length of last message */
|
/* Maximum length of last message */
|
||||||
#define MINUNIT_MESSAGE_LEN 1024
|
#define MINUNIT_MESSAGE_LEN 1024
|
||||||
/* Accuracy with which floats are compared */
|
/* Accuracy with which floats are compared */
|
||||||
#define MINUNIT_EPSILON 1E-12
|
#define MINUNIT_EPSILON 1E-12
|
||||||
|
|
||||||
#include "minunit_vars_ex.h"
|
#include "minunit_vars_ex.h"
|
||||||
|
|
||||||
@@ -84,9 +84,9 @@ void minunit_print_fail(const char* error);
|
|||||||
void minunit_printf_warning(const char* format, ...);
|
void minunit_printf_warning(const char* format, ...);
|
||||||
|
|
||||||
/* Definitions */
|
/* 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_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) \
|
#define MU__SAFE_BLOCK(block) \
|
||||||
do { \
|
do { \
|
||||||
|
|||||||
@@ -30,7 +30,7 @@
|
|||||||
|
|
||||||
#define TAG "NfcTest"
|
#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_APP_MF_CLASSIC_DICT_UNIT_TEST_PATH EXT_PATH("unit_tests/mf_dict.nfc")
|
||||||
|
|
||||||
#define NFC_TEST_FLAG_WORKER_DONE (1)
|
#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"));
|
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) {
|
MU_TEST(ntag_215_reader) {
|
||||||
mf_ultralight_reader_test(EXT_PATH("unit_tests/nfc/Ntag215.nfc"));
|
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_215_reader);
|
||||||
MU_RUN_TEST(ntag_216_reader);
|
MU_RUN_TEST(ntag_216_reader);
|
||||||
MU_RUN_TEST(ntag_213_locked_reader);
|
MU_RUN_TEST(ntag_213_locked_reader);
|
||||||
|
MU_RUN_TEST(mf_ultralight_c_reader);
|
||||||
|
|
||||||
MU_RUN_TEST(mf_ultralight_write);
|
MU_RUN_TEST(mf_ultralight_write);
|
||||||
|
|
||||||
|
|||||||
@@ -43,14 +43,15 @@ typedef struct {
|
|||||||
static RpcSessionContext rpc_session[TEST_RPC_SESSIONS];
|
static RpcSessionContext rpc_session[TEST_RPC_SESSIONS];
|
||||||
|
|
||||||
#define TAG "UnitTestsRpc"
|
#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 PING_RESPONSE 1
|
||||||
#define WRITE_REQUEST 0
|
#define WRITE_REQUEST 0
|
||||||
#define READ_RESPONSE 1
|
#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);
|
time_left = MAX(time_left, 0);
|
||||||
bytes_received =
|
bytes_received =
|
||||||
furi_stream_buffer_receive(session_context->output_stream, buf, count, time_left);
|
furi_stream_buffer_receive(session_context->output_stream, buf, count, time_left);
|
||||||
return (count == bytes_received);
|
return count == bytes_received;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -971,7 +972,7 @@ MU_TEST(test_storage_info) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#define TEST_DIR_STAT_NAME TEST_DIR "stat_dir"
|
#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) {
|
MU_TEST(test_storage_stat) {
|
||||||
test_create_dir(TEST_DIR_STAT_NAME);
|
test_create_dir(TEST_DIR_STAT_NAME);
|
||||||
test_create_file(TEST_DIR_STAT "empty.txt", 0);
|
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_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) {
|
MU_TEST(test_storage_delete_recursive) {
|
||||||
test_create_dir(TEST_DIR_RMRF_NAME);
|
test_create_dir(TEST_DIR_RMRF_NAME);
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
#define UNIT_TESTS_PATH(path) EXT_PATH("unit_tests/" path)
|
#define UNIT_TESTS_PATH(path) EXT_PATH("unit_tests/" path)
|
||||||
|
|
||||||
#define STORAGE_LOCKED_FILE EXT_PATH("locked_file.test")
|
#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")
|
#define STORAGE_TEST_DIR UNIT_TESTS_PATH("test_dir")
|
||||||
|
|
||||||
|
|||||||
@@ -11,13 +11,14 @@
|
|||||||
#include <lib/subghz/devices/cc1101_configs.h>
|
#include <lib/subghz/devices/cc1101_configs.h>
|
||||||
|
|
||||||
#define TAG "SubGhzTest"
|
#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 KEYSTORE_DIR_NAME EXT_PATH("subghz/assets/keeloq_mfcodes")
|
||||||
#define NICE_FLOR_S_DIR_NAME EXT_PATH("subghz/assets/nice_flor_s")
|
#define CAME_ATOMO_DIR_NAME EXT_PATH("subghz/assets/came_atomo")
|
||||||
#define ALUTECH_AT_4N_DIR_NAME EXT_PATH("subghz/assets/alutech_at_4n")
|
#define NICE_FLOR_S_DIR_NAME EXT_PATH("subghz/assets/nice_flor_s")
|
||||||
#define TEST_RANDOM_DIR_NAME EXT_PATH("unit_tests/subghz/test_random_raw.sub")
|
#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_RANDOM_COUNT_PARSE 329
|
||||||
#define TEST_TIMEOUT 10000
|
#define TEST_TIMEOUT 10000
|
||||||
|
|
||||||
static SubGhzEnvironment* environment_handler;
|
static SubGhzEnvironment* environment_handler;
|
||||||
static SubGhzReceiver* receiver_handler;
|
static SubGhzReceiver* receiver_handler;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
#include <flipper_application/flipper_application.h>
|
#include <flipper_application/flipper_application.h>
|
||||||
|
|
||||||
#define APPID "UnitTest"
|
#define APPID "UnitTest"
|
||||||
#define API_VERSION (0u)
|
#define API_VERSION (0u)
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
#include <input/input.h>
|
#include <input/input.h>
|
||||||
|
|
||||||
#define MOUSE_MOVE_SHORT 5
|
#define MOUSE_MOVE_SHORT 5
|
||||||
#define MOUSE_MOVE_LONG 20
|
#define MOUSE_MOVE_LONG 20
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
EventTypeInput,
|
EventTypeInput,
|
||||||
|
|||||||
@@ -17,18 +17,18 @@
|
|||||||
|
|
||||||
#define TAG "SubGhzDeviceCc1101Ext"
|
#define TAG "SubGhzDeviceCc1101Ext"
|
||||||
|
|
||||||
#define SUBGHZ_DEVICE_CC1101_EXT_TX_GPIO (&gpio_ext_pb2)
|
#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_E07_AMP_GPIO &gpio_ext_pc3
|
||||||
#define SUBGHZ_DEVICE_CC1101_EXT_FORCE_DANGEROUS_RANGE false
|
#define SUBGHZ_DEVICE_CC1101_EXT_FORCE_DANGEROUS_RANGE false
|
||||||
|
|
||||||
#define SUBGHZ_DEVICE_CC1101_CONFIG_VER 1
|
#define SUBGHZ_DEVICE_CC1101_CONFIG_VER 1
|
||||||
|
|
||||||
/* DMA Channels definition */
|
/* 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_CH3_CHANNEL (LL_DMA_CHANNEL_3)
|
||||||
#define SUBGHZ_DEVICE_CC1101_EXT_DMA_CH4_CHANNEL (LL_DMA_CHANNEL_4)
|
#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_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 \
|
#define SUBGHZ_DEVICE_CC1101_EXT_DMA_CH3_DEF \
|
||||||
SUBGHZ_DEVICE_CC1101_EXT_DMA, SUBGHZ_DEVICE_CC1101_EXT_DMA_CH3_CHANNEL
|
SUBGHZ_DEVICE_CC1101_EXT_DMA, SUBGHZ_DEVICE_CC1101_EXT_DMA_CH3_CHANNEL
|
||||||
#define SUBGHZ_DEVICE_CC1101_EXT_DMA_CH4_DEF \
|
#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(
|
cc1101_read_reg(
|
||||||
subghz_device_cc1101_ext->spi_bus_handle, CC1101_STATUS_LQI | CC1101_BURST, data);
|
subghz_device_cc1101_ext->spi_bus_handle, CC1101_STATUS_LQI | CC1101_BURST, data);
|
||||||
furi_hal_spi_release(subghz_device_cc1101_ext->spi_bus_handle);
|
furi_hal_spi_release(subghz_device_cc1101_ext->spi_bus_handle);
|
||||||
if(((data[0] >> 7) & 0x01)) {
|
if((data[0] >> 7) & 0x01) {
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
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) {
|
bool subghz_device_cc1101_ext_is_async_tx_complete(void) {
|
||||||
return (
|
return (subghz_device_cc1101_ext->state == SubGhzDeviceCC1101ExtStateAsyncTx) &&
|
||||||
(subghz_device_cc1101_ext->state == SubGhzDeviceCC1101ExtStateAsyncTx) &&
|
(LL_TIM_GetAutoReload(TIM17) == 0);
|
||||||
(LL_TIM_GetAutoReload(TIM17) == 0));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void subghz_device_cc1101_ext_stop_async_tx(void) {
|
void subghz_device_cc1101_ext_stop_async_tx(void) {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#define TAG "ble_beacon_app"
|
#define TAG "BleBeaconApp"
|
||||||
|
|
||||||
static bool ble_beacon_app_custom_event_callback(void* context, uint32_t event) {
|
static bool ble_beacon_app_custom_event_callback(void* context, uint32_t event) {
|
||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#define PLUGIN_APP_ID "example_plugins"
|
#define PLUGIN_APP_ID "example_plugins"
|
||||||
#define PLUGIN_API_VERSION 1
|
#define PLUGIN_API_VERSION 1
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#define PLUGIN_APP_ID "example_plugins_advanced"
|
#define PLUGIN_APP_ID "example_plugins_advanced"
|
||||||
#define PLUGIN_API_VERSION 1
|
#define PLUGIN_API_VERSION 1
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
|||||||
@@ -25,15 +25,15 @@
|
|||||||
#include <furi_hal_power.h>
|
#include <furi_hal_power.h>
|
||||||
|
|
||||||
#define UPDATE_PERIOD_MS 1000UL
|
#define UPDATE_PERIOD_MS 1000UL
|
||||||
#define TEXT_STORE_SIZE 64U
|
#define TEXT_STORE_SIZE 64U
|
||||||
|
|
||||||
#define DS18B20_CMD_SKIP_ROM 0xccU
|
#define DS18B20_CMD_SKIP_ROM 0xccU
|
||||||
#define DS18B20_CMD_CONVERT 0x44U
|
#define DS18B20_CMD_CONVERT 0x44U
|
||||||
#define DS18B20_CMD_READ_SCRATCHPAD 0xbeU
|
#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_CFG_RESOLUTION_MASK 0x03U
|
||||||
#define DS18B20_DECIMAL_PART_MASK 0x0fU
|
#define DS18B20_DECIMAL_PART_MASK 0x0fU
|
||||||
|
|
||||||
#define DS18B20_SIGN_MASK 0xf0U
|
#define DS18B20_SIGN_MASK 0xf0U
|
||||||
|
|
||||||
|
|||||||
@@ -344,7 +344,7 @@ bool archive_is_home(ArchiveBrowserView* browser) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const char* default_path = archive_get_default_path(archive_get_tab(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) {
|
const char* archive_get_name(ArchiveBrowserView* browser) {
|
||||||
|
|||||||
@@ -3,8 +3,8 @@
|
|||||||
#include "../archive_i.h"
|
#include "../archive_i.h"
|
||||||
#include <storage/storage.h>
|
#include <storage/storage.h>
|
||||||
|
|
||||||
#define TAB_LEFT InputKeyLeft // Default tab switch direction
|
#define TAB_LEFT InputKeyLeft // Default tab switch direction
|
||||||
#define TAB_DEFAULT ArchiveTabFavorites // Start tab
|
#define TAB_DEFAULT ArchiveTabFavorites // Start tab
|
||||||
#define FILE_LIST_BUF_LEN 50
|
#define FILE_LIST_BUF_LEN 50
|
||||||
|
|
||||||
static const char* tab_default_paths[] = {
|
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) {
|
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);
|
bool archive_is_item_in_array(ArchiveBrowserViewModel* model, uint32_t idx);
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
#include <storage/storage.h>
|
#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")
|
#define ARCHIVE_FAV_TEMP_PATH ANY_PATH("favorites.tmp")
|
||||||
|
|
||||||
uint16_t archive_favorites_count(void* context);
|
uint16_t archive_favorites_count(void* context);
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
#define TAG "ArchiveSceneBrowser"
|
#define TAG "ArchiveSceneBrowser"
|
||||||
|
|
||||||
#define SCENE_STATE_DEFAULT (0)
|
#define SCENE_STATE_DEFAULT (0)
|
||||||
#define SCENE_STATE_NEED_REFRESH (1)
|
#define SCENE_STATE_NEED_REFRESH (1)
|
||||||
|
|
||||||
static const char* archive_get_flipper_app_name(ArchiveFileTypeEnum file_type) {
|
static const char* archive_get_flipper_app_name(ArchiveFileTypeEnum file_type) {
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
#include "../helpers/archive_browser.h"
|
#include "../helpers/archive_browser.h"
|
||||||
|
|
||||||
#define SCENE_DELETE_CUSTOM_EVENT (0UL)
|
#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) {
|
void archive_scene_delete_widget_callback(GuiButtonType result, InputType type, void* context) {
|
||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
#define TAG "Archive"
|
#define TAG "Archive"
|
||||||
|
|
||||||
#define SCENE_RENAME_CUSTOM_EVENT (0UL)
|
#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) {
|
void archive_scene_rename_text_input_callback(void* context) {
|
||||||
ArchiveApp* archive = (ArchiveApp*)context;
|
ArchiveApp* archive = (ArchiveApp*)context;
|
||||||
|
|||||||
@@ -4,9 +4,9 @@
|
|||||||
#include "archive_browser_view.h"
|
#include "archive_browser_view.h"
|
||||||
#include "../helpers/archive_browser.h"
|
#include "../helpers/archive_browser.h"
|
||||||
|
|
||||||
#define TAG "Archive"
|
#define TAG "Archive"
|
||||||
#define SCROLL_INTERVAL (333)
|
#define SCROLL_INTERVAL (333)
|
||||||
#define SCROLL_DELAY (2)
|
#define SCROLL_DELAY (2)
|
||||||
|
|
||||||
static const char* ArchiveTabNames[] = {
|
static const char* ArchiveTabNames[] = {
|
||||||
[ArchiveTabFavorites] = "Favorites",
|
[ArchiveTabFavorites] = "Favorites",
|
||||||
|
|||||||
@@ -14,15 +14,15 @@
|
|||||||
#include "../helpers/archive_favorites.h"
|
#include "../helpers/archive_favorites.h"
|
||||||
#include "gui/modules/file_browser_worker.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_NAME_LEN 255
|
||||||
#define MAX_EXT_LEN 6
|
#define MAX_EXT_LEN 6
|
||||||
#define FRAME_HEIGHT 12
|
#define FRAME_HEIGHT 12
|
||||||
#define MENU_ITEMS 5u
|
#define MENU_ITEMS 5u
|
||||||
#define MOVE_OFFSET 5u
|
#define MOVE_OFFSET 5u
|
||||||
|
|
||||||
#define CLIPBOARD_MODE_OFF (0U)
|
#define CLIPBOARD_MODE_OFF (0U)
|
||||||
#define CLIPBOARD_MODE_CUT (1U)
|
#define CLIPBOARD_MODE_CUT (1U)
|
||||||
#define CLIPBOARD_MODE_COPY (2U)
|
#define CLIPBOARD_MODE_COPY (2U)
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
|||||||
@@ -5,9 +5,9 @@
|
|||||||
#include <lib/toolbox/path.h>
|
#include <lib/toolbox/path.h>
|
||||||
#include <flipper_format/flipper_format.h>
|
#include <flipper_format/flipper_format.h>
|
||||||
|
|
||||||
#define BAD_USB_SETTINGS_PATH BAD_USB_APP_BASE_FOLDER "/.badusb.settings"
|
#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_FILE_TYPE "Flipper BadUSB Settings File"
|
||||||
#define BAD_USB_SETTINGS_VERSION 1
|
#define BAD_USB_SETTINGS_VERSION 1
|
||||||
#define BAD_USB_SETTINGS_DEFAULT_LAYOUT BAD_USB_APP_PATH_LAYOUT_FOLDER "/en-US.kl"
|
#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) {
|
static bool bad_usb_app_custom_event_callback(void* context, uint32_t event) {
|
||||||
|
|||||||
@@ -16,10 +16,10 @@
|
|||||||
#include "views/bad_usb_view.h"
|
#include "views/bad_usb_view.h"
|
||||||
#include <furi_hal_usb.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_PATH_LAYOUT_FOLDER BAD_USB_APP_BASE_FOLDER "/assets/layouts"
|
||||||
#define BAD_USB_APP_SCRIPT_EXTENSION ".txt"
|
#define BAD_USB_APP_SCRIPT_EXTENSION ".txt"
|
||||||
#define BAD_USB_APP_LAYOUT_EXTENSION ".kl"
|
#define BAD_USB_APP_LAYOUT_EXTENSION ".kl"
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
BadUsbAppErrorNoFiles,
|
BadUsbAppErrorNoFiles,
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
#include <dolphin/dolphin.h>
|
#include <dolphin/dolphin.h>
|
||||||
|
|
||||||
#define TAG "BadUsb"
|
#define TAG "BadUsb"
|
||||||
|
|
||||||
#define WORKER_TAG TAG "Worker"
|
#define WORKER_TAG TAG "Worker"
|
||||||
|
|
||||||
#define BADUSB_ASCII_TO_KEY(script, x) \
|
#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) {
|
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) {
|
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)) {
|
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;
|
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);
|
FURI_LOG_E(WORKER_TAG, "Unknown command at line %zu", bad_usb->st.line_cur - 1U);
|
||||||
return SCRIPT_STATE_ERROR;
|
return SCRIPT_STATE_ERROR;
|
||||||
} else {
|
} 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);
|
FURI_LOG_E(WORKER_TAG, "Unknown command at line %zu", bad_usb->st.line_cur);
|
||||||
return SCRIPT_STATE_ERROR;
|
return SCRIPT_STATE_ERROR;
|
||||||
} else {
|
} else {
|
||||||
return (delay_val + bad_usb->defdelay);
|
return delay_val + bad_usb->defdelay;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
furi_string_push_back(bad_usb->line, bad_usb->file_buf[i]);
|
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 TAG "BadUsb"
|
||||||
|
|
||||||
#define WORKER_TAG TAG "Worker"
|
#define WORKER_TAG TAG "Worker"
|
||||||
|
|
||||||
int32_t ducky_execute_cmd(BadUsbScript* bad_usb, const char* line) {
|
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) {
|
if(ducky_commands[i].callback == NULL) {
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} 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 "ducky_script.h"
|
||||||
#include "bad_usb_hid.h"
|
#include "bad_usb_hid.h"
|
||||||
|
|
||||||
#define SCRIPT_STATE_ERROR (-1)
|
#define SCRIPT_STATE_ERROR (-1)
|
||||||
#define SCRIPT_STATE_END (-2)
|
#define SCRIPT_STATE_END (-2)
|
||||||
#define SCRIPT_STATE_NEXT_LINE (-3)
|
#define SCRIPT_STATE_NEXT_LINE (-3)
|
||||||
#define SCRIPT_STATE_CMD_UNKNOWN (-4)
|
#define SCRIPT_STATE_CMD_UNKNOWN (-4)
|
||||||
#define SCRIPT_STATE_STRING_START (-5)
|
#define SCRIPT_STATE_STRING_START (-5)
|
||||||
#define SCRIPT_STATE_WAIT_FOR_BTN (-6)
|
#define SCRIPT_STATE_WAIT_FOR_BTN (-6)
|
||||||
|
|
||||||
|
|||||||
@@ -7,14 +7,14 @@
|
|||||||
|
|
||||||
#define CLOCK_ISO_DATE_FORMAT "%.4d-%.2d-%.2d"
|
#define CLOCK_ISO_DATE_FORMAT "%.4d-%.2d-%.2d"
|
||||||
#define CLOCK_RFC_DATE_FORMAT "%.2d-%.2d-%.4d"
|
#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_AM "AM"
|
||||||
#define MERIDIAN_STRING_PM "PM"
|
#define MERIDIAN_STRING_PM "PM"
|
||||||
|
|
||||||
#define TIME_LEN 12
|
#define TIME_LEN 12
|
||||||
#define DATE_LEN 14
|
#define DATE_LEN 14
|
||||||
#define MERIDIAN_LEN 3
|
#define MERIDIAN_LEN 3
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
|||||||
@@ -10,11 +10,11 @@
|
|||||||
#include <stm32wbxx_ll_lpuart.h>
|
#include <stm32wbxx_ll_lpuart.h>
|
||||||
#include <stm32wbxx_ll_usart.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_UART_RX_BUF_SIZE (USB_CDC_PKT_LEN * 5)
|
||||||
|
|
||||||
#define USB_CDC_BIT_DTR (1 << 0)
|
#define USB_CDC_BIT_DTR (1 << 0)
|
||||||
#define USB_CDC_BIT_RTS (1 << 1)
|
#define USB_CDC_BIT_RTS (1 << 1)
|
||||||
#define USB_USART_DE_RE_PIN &gpio_ext_pa4
|
#define USB_USART_DE_RE_PIN &gpio_ext_pa4
|
||||||
|
|
||||||
static const GpioPin* flow_pins[][2] = {
|
static const GpioPin* flow_pins[][2] = {
|
||||||
|
|||||||
@@ -28,8 +28,8 @@
|
|||||||
#include "ibutton_custom_event.h"
|
#include "ibutton_custom_event.h"
|
||||||
#include "scenes/ibutton_scene.h"
|
#include "scenes/ibutton_scene.h"
|
||||||
|
|
||||||
#define IBUTTON_APP_FOLDER ANY_PATH("ibutton")
|
#define IBUTTON_APP_FOLDER ANY_PATH("ibutton")
|
||||||
#define IBUTTON_APP_FILENAME_PREFIX "iBtn"
|
#define IBUTTON_APP_FILENAME_PREFIX "iBtn"
|
||||||
#define IBUTTON_APP_FILENAME_EXTENSION ".ibtn"
|
#define IBUTTON_APP_FILENAME_EXTENSION ".ibtn"
|
||||||
|
|
||||||
#define IBUTTON_KEY_NAME_SIZE 22
|
#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) {
|
if(event.type == SceneManagerEventTypeCustom) {
|
||||||
consumed = true;
|
consumed = true;
|
||||||
if(event.event == iButtonCustomEventByteEditResult) {
|
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) {
|
} else if(event.event == iButtonCustomEventByteEditChanged) {
|
||||||
ibutton_protocols_apply_edits(ibutton->protocols, ibutton->key);
|
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;
|
iButton* ibutton = context;
|
||||||
bool consumed = false;
|
bool consumed = false;
|
||||||
|
|
||||||
|
const bool is_new_file = furi_string_empty(ibutton->file_path);
|
||||||
|
|
||||||
if(event.type == SceneManagerEventTypeCustom) {
|
if(event.type == SceneManagerEventTypeCustom) {
|
||||||
consumed = true;
|
consumed = true;
|
||||||
if(event.event == iButtonCustomEventTextEditResult) {
|
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(
|
furi_string_printf(
|
||||||
ibutton->file_path,
|
ibutton->file_path,
|
||||||
"%s/%s%s",
|
"%s/%s%s",
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ enum SubmenuIndex {
|
|||||||
SubmenuIndexWriteBlank,
|
SubmenuIndexWriteBlank,
|
||||||
SubmenuIndexWriteCopy,
|
SubmenuIndexWriteCopy,
|
||||||
SubmenuIndexEdit,
|
SubmenuIndexEdit,
|
||||||
|
SubmenuIndexRename,
|
||||||
SubmenuIndexDelete,
|
SubmenuIndexDelete,
|
||||||
SubmenuIndexInfo,
|
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, "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, "Delete", SubmenuIndexDelete, ibutton_submenu_callback, ibutton);
|
||||||
submenu_add_item(submenu, "Info", SubmenuIndexInfo, 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);
|
scene_manager_next_scene(scene_manager, iButtonSceneWrite);
|
||||||
} else if(event.event == SubmenuIndexEdit) {
|
} else if(event.event == SubmenuIndexEdit) {
|
||||||
scene_manager_next_scene(scene_manager, iButtonSceneAddValue);
|
scene_manager_next_scene(scene_manager, iButtonSceneAddValue);
|
||||||
|
} else if(event.event == SubmenuIndexRename) {
|
||||||
|
scene_manager_next_scene(scene_manager, iButtonSceneSaveName);
|
||||||
} else if(event.event == SubmenuIndexDelete) {
|
} else if(event.event == SubmenuIndexDelete) {
|
||||||
scene_manager_next_scene(scene_manager, iButtonSceneDeleteConfirm);
|
scene_manager_next_scene(scene_manager, iButtonSceneDeleteConfirm);
|
||||||
} else if(event.event == SubmenuIndexInfo) {
|
} else if(event.event == SubmenuIndexInfo) {
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
#define TAG "InfraredApp"
|
#define TAG "InfraredApp"
|
||||||
|
|
||||||
#define INFRARED_TX_MIN_INTERVAL_MS (50U)
|
#define INFRARED_TX_MIN_INTERVAL_MS (50U)
|
||||||
#define INFRARED_TASK_STACK_SIZE (2048UL)
|
#define INFRARED_TASK_STACK_SIZE (2048UL)
|
||||||
|
|
||||||
static const NotificationSequence*
|
static const NotificationSequence*
|
||||||
infrared_notification_sequences[InfraredNotificationMessageCount] = {
|
infrared_notification_sequences[InfraredNotificationMessageCount] = {
|
||||||
|
|||||||
@@ -17,9 +17,9 @@ typedef struct InfraredApp InfraredApp;
|
|||||||
#include <storage/storage.h>
|
#include <storage/storage.h>
|
||||||
#include <furi_hal_infrared.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_VERSION (1)
|
||||||
#define INFRARED_SETTINGS_MAGIC (0x1F)
|
#define INFRARED_SETTINGS_MAGIC (0x1F)
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
FuriHalInfraredTxPin tx_pin;
|
FuriHalInfraredTxPin tx_pin;
|
||||||
|
|||||||
@@ -39,18 +39,18 @@
|
|||||||
#include "views/infrared_debug_view.h"
|
#include "views/infrared_debug_view.h"
|
||||||
#include "views/infrared_move_view.h"
|
#include "views/infrared_move_view.h"
|
||||||
|
|
||||||
#define INFRARED_FILE_NAME_SIZE 100
|
#define INFRARED_FILE_NAME_SIZE 100
|
||||||
#define INFRARED_TEXT_STORE_NUM 2
|
#define INFRARED_TEXT_STORE_NUM 2
|
||||||
#define INFRARED_TEXT_STORE_SIZE 128
|
#define INFRARED_TEXT_STORE_SIZE 128
|
||||||
|
|
||||||
#define INFRARED_MAX_BUTTON_NAME_LENGTH 22
|
#define INFRARED_MAX_BUTTON_NAME_LENGTH 22
|
||||||
#define INFRARED_MAX_REMOTE_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_APP_EXTENSION ".ir"
|
||||||
|
|
||||||
#define INFRARED_DEFAULT_REMOTE_NAME "Remote"
|
#define INFRARED_DEFAULT_REMOTE_NAME "Remote"
|
||||||
#define INFRARED_LOG_TAG "InfraredApp"
|
#define INFRARED_LOG_TAG "InfraredApp"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Enumeration of invalid remote button indices.
|
* @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_transmitting; /**< Whether a signal is currently being transmitted. */
|
||||||
bool is_otg_enabled; /**< Whether OTG power (external 5V) is enabled. */
|
bool is_otg_enabled; /**< Whether OTG power (external 5V) is enabled. */
|
||||||
InfraredEditTarget edit_target : 8; /**< Selected editing target (a remote or a button). */
|
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 current_button_index; /**< Selected button index (move destination). */
|
||||||
int32_t prev_button_index; /**< Previous button index (move source). */
|
int32_t prev_button_index; /**< Previous button index (move source). */
|
||||||
uint32_t last_transmit_time; /**< Lat time a signal was transmitted. */
|
uint32_t last_transmit_time; /**< Lat time a signal was transmitted. */
|
||||||
|
|||||||
@@ -10,10 +10,10 @@
|
|||||||
#include "infrared_signal.h"
|
#include "infrared_signal.h"
|
||||||
#include "infrared_brute_force.h"
|
#include "infrared_brute_force.h"
|
||||||
|
|
||||||
#define INFRARED_CLI_BUF_SIZE (10U)
|
#define INFRARED_CLI_BUF_SIZE (10U)
|
||||||
#define INFRARED_CLI_FILE_NAME_SIZE (256U)
|
#define INFRARED_CLI_FILE_NAME_SIZE (256U)
|
||||||
#define INFRARED_FILE_EXTENSION ".ir"
|
#define INFRARED_FILE_EXTENSION ".ir"
|
||||||
#define INFRARED_ASSETS_FOLDER EXT_PATH("infrared/assets")
|
#define INFRARED_ASSETS_FOLDER EXT_PATH("infrared/assets")
|
||||||
#define INFRARED_BRUTE_FORCE_DUMMY_INDEX 0
|
#define INFRARED_BRUTE_FORCE_DUMMY_INDEX 0
|
||||||
|
|
||||||
DICT_DEF2(dict_signals, FuriString*, FURI_STRING_OPLIST, int, M_DEFAULT_OPLIST)
|
DICT_DEF2(dict_signals, FuriString*, FURI_STRING_OPLIST, int, M_DEFAULT_OPLIST)
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
#define TAG "InfraredRemote"
|
#define TAG "InfraredRemote"
|
||||||
|
|
||||||
#define INFRARED_FILE_HEADER "IR signals file"
|
#define INFRARED_FILE_HEADER "IR signals file"
|
||||||
#define INFRARED_FILE_VERSION (1)
|
#define INFRARED_FILE_VERSION (1)
|
||||||
|
|
||||||
ARRAY_DEF(StringArray, const char*, M_CSTR_DUP_OPLIST); //-V575
|
ARRAY_DEF(StringArray, const char*, M_CSTR_DUP_OPLIST); //-V575
|
||||||
|
|||||||
@@ -13,18 +13,18 @@
|
|||||||
#define INFRARED_SIGNAL_TYPE_KEY "type"
|
#define INFRARED_SIGNAL_TYPE_KEY "type"
|
||||||
|
|
||||||
// Type key values
|
// Type key values
|
||||||
#define INFRARED_SIGNAL_TYPE_RAW "raw"
|
#define INFRARED_SIGNAL_TYPE_RAW "raw"
|
||||||
#define INFRARED_SIGNAL_TYPE_PARSED "parsed"
|
#define INFRARED_SIGNAL_TYPE_PARSED "parsed"
|
||||||
|
|
||||||
// Raw signal keys
|
// Raw signal keys
|
||||||
#define INFRARED_SIGNAL_DATA_KEY "data"
|
#define INFRARED_SIGNAL_DATA_KEY "data"
|
||||||
#define INFRARED_SIGNAL_FREQUENCY_KEY "frequency"
|
#define INFRARED_SIGNAL_FREQUENCY_KEY "frequency"
|
||||||
#define INFRARED_SIGNAL_DUTY_CYCLE_KEY "duty_cycle"
|
#define INFRARED_SIGNAL_DUTY_CYCLE_KEY "duty_cycle"
|
||||||
|
|
||||||
// Parsed signal keys
|
// Parsed signal keys
|
||||||
#define INFRARED_SIGNAL_PROTOCOL_KEY "protocol"
|
#define INFRARED_SIGNAL_PROTOCOL_KEY "protocol"
|
||||||
#define INFRARED_SIGNAL_ADDRESS_KEY "address"
|
#define INFRARED_SIGNAL_ADDRESS_KEY "address"
|
||||||
#define INFRARED_SIGNAL_COMMAND_KEY "command"
|
#define INFRARED_SIGNAL_COMMAND_KEY "command"
|
||||||
|
|
||||||
struct InfraredSignal {
|
struct InfraredSignal {
|
||||||
bool is_raw;
|
bool is_raw;
|
||||||
|
|||||||
@@ -7,9 +7,9 @@
|
|||||||
|
|
||||||
#include <toolbox/m_cstr_dup.h>
|
#include <toolbox/m_cstr_dup.h>
|
||||||
|
|
||||||
#define LIST_ITEMS 4U
|
#define LIST_ITEMS 4U
|
||||||
#define LIST_LINE_H 13U
|
#define LIST_LINE_H 13U
|
||||||
#define HEADER_H 12U
|
#define HEADER_H 12U
|
||||||
#define MOVE_X_OFFSET 5U
|
#define MOVE_X_OFFSET 5U
|
||||||
|
|
||||||
struct InfraredMoveView {
|
struct InfraredMoveView {
|
||||||
@@ -98,7 +98,7 @@ static bool infrared_move_view_input_callback(InputEvent* event, void* context)
|
|||||||
|
|
||||||
bool consumed = false;
|
bool consumed = false;
|
||||||
|
|
||||||
if(((event->type == InputTypeShort || event->type == InputTypeRepeat)) &&
|
if((event->type == InputTypeShort || event->type == InputTypeRepeat) &&
|
||||||
((event->key == InputKeyUp) || (event->key == InputKeyDown))) {
|
((event->key == InputKeyUp) || (event->key == InputKeyDown))) {
|
||||||
with_view_model(
|
with_view_model(
|
||||||
move_view->view,
|
move_view->view,
|
||||||
|
|||||||
@@ -3,22 +3,22 @@
|
|||||||
|
|
||||||
//TODO: use .txt file in resources for passwords.
|
//TODO: use .txt file in resources for passwords.
|
||||||
const uint32_t default_passwords[] = {
|
const uint32_t default_passwords[] = {
|
||||||
0x51243648, 0x000D8787, 0x19920427, 0x50524F58, 0xF9DCEBA0, 0x65857569, 0x05D73B9F, 0x89A69E60,
|
0x00000000, 0x00000001, 0x00000002, 0x0000000A, 0x0000000B, 0x00012323, 0x000D8787, 0x00434343,
|
||||||
0x314159E0, 0xAA55BBBB, 0xA5B4C3D2, 0x1C0B5848, 0x00434343, 0x444E4752, 0x4E457854, 0x44B44CAE,
|
0x01010101, 0x01020304, 0x01234567, 0x02030405, 0x03040506, 0x04050607, 0x05060708, 0x05D73B9F,
|
||||||
0x88661858, 0xE9920427, 0x575F4F4B, 0x50520901, 0x20206666, 0x65857569, 0x5469616E, 0x7686962A,
|
0x06070809, 0x0708090A, 0x07CEE75D, 0x07D7BB0B, 0x08090A0B, 0x090A0B0C, 0x0A0B0C0D, 0x0B0C0D0E,
|
||||||
0xC0F5009A, 0x07CEE75D, 0xfeedbeef, 0xdeadc0de, 0x00000000, 0x11111111, 0x22222222, 0x33333333,
|
0x0C0D0E0F, 0x0CB7E7FC, 0x10000000, 0x10041004, 0x10101010, 0x11111111, 0x11112222, 0x11223344,
|
||||||
0x44444444, 0x55555555, 0x66666666, 0x77777777, 0x88888888, 0x99999999, 0xAAAAAAAA, 0xBBBBBBBB,
|
0x12121212, 0x121AD038, 0x12341234, 0x12344321, 0x12345678, 0x1234ABCD, 0x126C248A, 0x13131313,
|
||||||
0xCCCCCCCC, 0xDDDDDDDD, 0xEEEEEEEE, 0xFFFFFFFF, 0xa0a1a2a3, 0xb0b1b2b3, 0x50415353, 0x00000001,
|
0x19721972, 0x19920427, 0x1C0B5848, 0x20000000, 0x20002000, 0x20206666, 0x22222222, 0x22334455,
|
||||||
0x00000002, 0x0000000a, 0x0000000b, 0x01020304, 0x02030405, 0x03040506, 0x04050607, 0x05060708,
|
0x27182818, 0x30000000, 0x31415926, 0x314159E0, 0x33333333, 0x33445566, 0x40000000, 0x44444444,
|
||||||
0x06070809, 0x0708090A, 0x08090A0B, 0x090A0B0C, 0x0A0B0C0D, 0x0B0C0D0E, 0x0C0D0E0F, 0x01234567,
|
0x444E4752, 0x44556677, 0x44B44CAE, 0x4E457854, 0x4F271149, 0x50000000, 0x50415353, 0x50520901,
|
||||||
0x12345678, 0x10000000, 0x20000000, 0x30000000, 0x40000000, 0x50000000, 0x60000000, 0x70000000,
|
0x50524F58, 0x51243648, 0x5469616E, 0x55555555, 0x55667788, 0x55AA55AA, 0x575F4F4B, 0x57721566,
|
||||||
0x80000000, 0x90000000, 0xA0000000, 0xB0000000, 0xC0000000, 0xD0000000, 0xE0000000, 0xF0000000,
|
0x60000000, 0x65857569, 0x66666666, 0x66778899, 0x69314718, 0x69696969, 0x70000000, 0x7686962A,
|
||||||
0x10101010, 0x01010101, 0x11223344, 0x22334455, 0x33445566, 0x44556677, 0x55667788, 0x66778899,
|
0x77777777, 0x778899AA, 0x7854794A, 0x80000000, 0x87654321, 0x88661858, 0x88888888, 0x8899AABB,
|
||||||
0x778899AA, 0x8899AABB, 0x99AABBCC, 0xAABBCCDD, 0xBBCCDDEE, 0xCCDDEEFF, 0x0CB7E7FC, 0xFABADA11,
|
0x89A69E60, 0x90000000, 0x932D9963, 0x93C467E3, 0x9636EF8F, 0x99999999, 0x99AABBCC, 0x9E3779B9,
|
||||||
0x87654321, 0x12341234, 0x69696969, 0x12121212, 0x12344321, 0x1234ABCD, 0x11112222, 0x13131313,
|
0xA0000000, 0xA0A1A2A3, 0xA5B4C3D2, 0xAA55AA55, 0xAA55BBBB, 0xAAAAAAAA, 0xAABBCCDD, 0xABCD1234,
|
||||||
0x10041004, 0x31415926, 0xabcd1234, 0x20002000, 0x19721972, 0xaa55aa55, 0x55aa55aa, 0x4f271149,
|
0xB0000000, 0xB0B1B2B3, 0xB5F44686, 0xBBBBBBBB, 0xBBCCDDEE, 0xC0000000, 0xC0F5009A, 0xC6EF3720,
|
||||||
0x07d7bb0b, 0x9636ef8f, 0xb5f44686, 0x9E3779B9, 0xC6EF3720, 0x7854794A, 0xF1EA5EED, 0x69314718,
|
0xCCCCCCCC, 0xCCDDEEFF, 0xD0000000, 0xDDDDDDDD, 0xDEADC0DE, 0xE0000000, 0xE4204998, 0xE9920427,
|
||||||
0x57721566, 0x93C467E3, 0x27182818, 0x50415353};
|
0xEEEEEEEE, 0xF0000000, 0xF1EA5EED, 0xF9DCEBA0, 0xFABADA11, 0xFEEDBEEF, 0xFFFFFFFF};
|
||||||
|
|
||||||
const uint32_t* lfrfid_get_t5577_default_passwords(uint8_t* len) {
|
const uint32_t* lfrfid_get_t5577_default_passwords(uint8_t* len) {
|
||||||
*len = sizeof(default_passwords) / sizeof(uint32_t);
|
*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");
|
"rfid raw_emulate <filename> - emulate raw data (not very useful, but helps debug protocols)\r\n");
|
||||||
printf(
|
printf(
|
||||||
"rfid raw_analyze <filename> - outputs raw data to the cli and tries to decode it (useful for protocol development)\r\n");
|
"rfid raw_analyze <filename> - outputs raw data to the cli and tries to decode it (useful for protocol development)\r\n");
|
||||||
};
|
}
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
ProtocolId protocol;
|
ProtocolId protocol;
|
||||||
|
|||||||
@@ -35,13 +35,13 @@
|
|||||||
|
|
||||||
#include <lfrfid/scenes/lfrfid_scene.h>
|
#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_TEXT_STORE_SIZE 40
|
||||||
|
|
||||||
#define LFRFID_APP_FOLDER ANY_PATH("lfrfid")
|
#define LFRFID_APP_FOLDER ANY_PATH("lfrfid")
|
||||||
#define LFRFID_SD_FOLDER EXT_PATH("lfrfid")
|
#define LFRFID_SD_FOLDER EXT_PATH("lfrfid")
|
||||||
#define LFRFID_APP_FILENAME_PREFIX "RFID"
|
#define LFRFID_APP_FILENAME_PREFIX "RFID"
|
||||||
#define LFRFID_APP_FILENAME_EXTENSION ".rfid"
|
#define LFRFID_APP_FILENAME_EXTENSION ".rfid"
|
||||||
#define LFRFID_APP_SHADOW_FILENAME_EXTENSION ".shd"
|
#define LFRFID_APP_SHADOW_FILENAME_EXTENSION ".shd"
|
||||||
|
|
||||||
#define LFRFID_APP_RAW_ASK_EXTENSION ".ask.raw"
|
#define LFRFID_APP_RAW_ASK_EXTENSION ".ask.raw"
|
||||||
|
|||||||
@@ -31,8 +31,21 @@ bool lfrfid_scene_save_data_on_event(void* context, SceneManagerEvent event) {
|
|||||||
consumed = true;
|
consumed = true;
|
||||||
size_t size = protocol_dict_get_data_size(app->dict, app->protocol_id);
|
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);
|
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) {
|
} else if(event.type == SceneManagerEventTypeBack) {
|
||||||
scene_manager_set_scene_state(scene_manager, LfRfidSceneSaveData, 0);
|
scene_manager_set_scene_state(scene_manager, LfRfidSceneSaveData, 0);
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ typedef enum {
|
|||||||
SubmenuIndexWrite,
|
SubmenuIndexWrite,
|
||||||
SubmenuIndexWriteAndSetPass,
|
SubmenuIndexWriteAndSetPass,
|
||||||
SubmenuIndexEdit,
|
SubmenuIndexEdit,
|
||||||
|
SubmenuIndexRename,
|
||||||
SubmenuIndexDelete,
|
SubmenuIndexDelete,
|
||||||
SubmenuIndexInfo,
|
SubmenuIndexInfo,
|
||||||
} SubmenuIndex;
|
} SubmenuIndex;
|
||||||
@@ -32,6 +33,8 @@ void lfrfid_scene_saved_key_menu_on_enter(void* context) {
|
|||||||
app);
|
app);
|
||||||
submenu_add_item(
|
submenu_add_item(
|
||||||
submenu, "Edit", SubmenuIndexEdit, lfrfid_scene_saved_key_menu_submenu_callback, app);
|
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_add_item(
|
||||||
submenu, "Delete", SubmenuIndexDelete, lfrfid_scene_saved_key_menu_submenu_callback, app);
|
submenu, "Delete", SubmenuIndexDelete, lfrfid_scene_saved_key_menu_submenu_callback, app);
|
||||||
submenu_add_item(
|
submenu_add_item(
|
||||||
@@ -63,6 +66,9 @@ bool lfrfid_scene_saved_key_menu_on_event(void* context, SceneManagerEvent event
|
|||||||
} else if(event.event == SubmenuIndexEdit) {
|
} else if(event.event == SubmenuIndexEdit) {
|
||||||
scene_manager_next_scene(app->scene_manager, LfRfidSceneSaveData);
|
scene_manager_next_scene(app->scene_manager, LfRfidSceneSaveData);
|
||||||
consumed = true;
|
consumed = true;
|
||||||
|
} else if(event.event == SubmenuIndexRename) {
|
||||||
|
scene_manager_next_scene(app->scene_manager, LfRfidSceneSaveName);
|
||||||
|
consumed = true;
|
||||||
} else if(event.event == SubmenuIndexDelete) {
|
} else if(event.event == SubmenuIndexDelete) {
|
||||||
scene_manager_next_scene(app->scene_manager, LfRfidSceneDeleteConfirm);
|
scene_manager_next_scene(app->scene_manager, LfRfidSceneDeleteConfirm);
|
||||||
consumed = true;
|
consumed = true;
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
#include <furi/furi.h>
|
#include <furi/furi.h>
|
||||||
#include <storage/storage.h>
|
#include <storage/storage.h>
|
||||||
|
|
||||||
#define NFC_APP_KEYS_EXTENSION ".keys"
|
#define NFC_APP_KEYS_EXTENSION ".keys"
|
||||||
#define NFC_APP_KEY_CACHE_FOLDER "/ext/nfc/.cache"
|
#define NFC_APP_KEY_CACHE_FOLDER "/ext/nfc/.cache"
|
||||||
|
|
||||||
static const char* mf_classic_key_cache_file_header = "Flipper NFC keys";
|
static const char* mf_classic_key_cache_file_header = "Flipper NFC keys";
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ void mf_ultralight_auth_reset(MfUltralightAuth* instance) {
|
|||||||
|
|
||||||
instance->type = MfUltralightAuthTypeNone;
|
instance->type = MfUltralightAuthTypeNone;
|
||||||
memset(&instance->password, 0, sizeof(MfUltralightAuthPassword));
|
memset(&instance->password, 0, sizeof(MfUltralightAuthPassword));
|
||||||
|
memset(&instance->tdes_key, 0, sizeof(MfUltralightC3DesAuthKey));
|
||||||
memset(&instance->pack, 0, sizeof(MfUltralightAuthPack));
|
memset(&instance->pack, 0, sizeof(MfUltralightAuthPack));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ typedef enum {
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
MfUltralightAuthType type;
|
MfUltralightAuthType type;
|
||||||
MfUltralightAuthPassword password;
|
MfUltralightAuthPassword password;
|
||||||
|
MfUltralightC3DesAuthKey tdes_key;
|
||||||
MfUltralightAuthPack pack;
|
MfUltralightAuthPack pack;
|
||||||
} MfUltralightAuth;
|
} MfUltralightAuth;
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
#include <nfc/protocols/mf_classic/mf_classic.h>
|
#include <nfc/protocols/mf_classic/mf_classic.h>
|
||||||
#include <furi/furi.h>
|
#include <furi/furi.h>
|
||||||
|
|
||||||
#define NFC_APP_FOLDER ANY_PATH("nfc")
|
#define NFC_APP_FOLDER ANY_PATH("nfc")
|
||||||
#define NFC_APP_MF_CLASSIC_DICT_USER_PATH (NFC_APP_FOLDER "/assets/mf_classic_dict_user.nfc")
|
#define NFC_APP_MF_CLASSIC_DICT_USER_PATH (NFC_APP_FOLDER "/assets/mf_classic_dict_user.nfc")
|
||||||
|
|
||||||
struct MfUserDict {
|
struct MfUserDict {
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
|
|
||||||
#define TAG "NfcSupportedCards"
|
#define TAG "NfcSupportedCards"
|
||||||
|
|
||||||
#define NFC_SUPPORTED_CARDS_PLUGINS_PATH APP_DATA_PATH("plugins")
|
#define NFC_SUPPORTED_CARDS_PLUGINS_PATH APP_DATA_PATH("plugins")
|
||||||
#define NFC_SUPPORTED_CARDS_PLUGIN_SUFFIX "_parser.fal"
|
#define NFC_SUPPORTED_CARDS_PLUGIN_SUFFIX "_parser.fal"
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@@ -24,7 +24,7 @@ typedef enum {
|
|||||||
} NfcSupportedCardsPluginFeature;
|
} NfcSupportedCardsPluginFeature;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
FuriString* path;
|
FuriString* name;
|
||||||
NfcProtocol protocol;
|
NfcProtocol protocol;
|
||||||
NfcSupportedCardsPluginFeature feature;
|
NfcSupportedCardsPluginFeature feature;
|
||||||
} NfcSupportedCardsPluginCache;
|
} NfcSupportedCardsPluginCache;
|
||||||
@@ -41,7 +41,6 @@ typedef enum {
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
Storage* storage;
|
Storage* storage;
|
||||||
File* directory;
|
File* directory;
|
||||||
FuriString* file_path;
|
|
||||||
char file_name[256];
|
char file_name[256];
|
||||||
FlipperApplication* app;
|
FlipperApplication* app;
|
||||||
} NfcSupportedCardsLoadContext;
|
} NfcSupportedCardsLoadContext;
|
||||||
@@ -73,7 +72,7 @@ void nfc_supported_cards_free(NfcSupportedCards* instance) {
|
|||||||
!NfcSupportedCardsPluginCache_end_p(iter);
|
!NfcSupportedCardsPluginCache_end_p(iter);
|
||||||
NfcSupportedCardsPluginCache_next(iter)) {
|
NfcSupportedCardsPluginCache_next(iter)) {
|
||||||
NfcSupportedCardsPluginCache* plugin_cache = NfcSupportedCardsPluginCache_ref(iter);
|
NfcSupportedCardsPluginCache* plugin_cache = NfcSupportedCardsPluginCache_ref(iter);
|
||||||
furi_string_free(plugin_cache->path);
|
furi_string_free(plugin_cache->name);
|
||||||
}
|
}
|
||||||
NfcSupportedCardsPluginCache_clear(instance->plugins_cache_arr);
|
NfcSupportedCardsPluginCache_clear(instance->plugins_cache_arr);
|
||||||
|
|
||||||
@@ -86,7 +85,6 @@ static NfcSupportedCardsLoadContext* nfc_supported_cards_load_context_alloc(void
|
|||||||
|
|
||||||
instance->storage = furi_record_open(RECORD_STORAGE);
|
instance->storage = furi_record_open(RECORD_STORAGE);
|
||||||
instance->directory = storage_file_alloc(instance->storage);
|
instance->directory = storage_file_alloc(instance->storage);
|
||||||
instance->file_path = furi_string_alloc();
|
|
||||||
|
|
||||||
if(!storage_dir_open(instance->directory, NFC_SUPPORTED_CARDS_PLUGINS_PATH)) {
|
if(!storage_dir_open(instance->directory, NFC_SUPPORTED_CARDS_PLUGINS_PATH)) {
|
||||||
FURI_LOG_D(TAG, "Failed to open directory: %s", NFC_SUPPORTED_CARDS_PLUGINS_PATH);
|
FURI_LOG_D(TAG, "Failed to open directory: %s", NFC_SUPPORTED_CARDS_PLUGINS_PATH);
|
||||||
@@ -100,8 +98,6 @@ static void nfc_supported_cards_load_context_free(NfcSupportedCardsLoadContext*
|
|||||||
flipper_application_free(instance->app);
|
flipper_application_free(instance->app);
|
||||||
}
|
}
|
||||||
|
|
||||||
furi_string_free(instance->file_path);
|
|
||||||
|
|
||||||
storage_dir_close(instance->directory);
|
storage_dir_close(instance->directory);
|
||||||
storage_file_free(instance->directory);
|
storage_file_free(instance->directory);
|
||||||
|
|
||||||
@@ -111,16 +107,19 @@ static void nfc_supported_cards_load_context_free(NfcSupportedCardsLoadContext*
|
|||||||
|
|
||||||
static const NfcSupportedCardsPlugin* nfc_supported_cards_get_plugin(
|
static const NfcSupportedCardsPlugin* nfc_supported_cards_get_plugin(
|
||||||
NfcSupportedCardsLoadContext* instance,
|
NfcSupportedCardsLoadContext* instance,
|
||||||
const FuriString* path,
|
const char* name,
|
||||||
const ElfApiInterface* api_interface) {
|
const ElfApiInterface* api_interface) {
|
||||||
furi_assert(instance);
|
furi_assert(instance);
|
||||||
furi_assert(path);
|
furi_assert(name);
|
||||||
|
|
||||||
const NfcSupportedCardsPlugin* plugin = NULL;
|
const NfcSupportedCardsPlugin* plugin = NULL;
|
||||||
|
FuriString* plugin_path = furi_string_alloc_printf(
|
||||||
|
"%s/%s%s", NFC_SUPPORTED_CARDS_PLUGINS_PATH, name, NFC_SUPPORTED_CARDS_PLUGIN_SUFFIX);
|
||||||
do {
|
do {
|
||||||
if(instance->app) flipper_application_free(instance->app);
|
if(instance->app) flipper_application_free(instance->app);
|
||||||
instance->app = flipper_application_alloc(instance->storage, api_interface);
|
instance->app = flipper_application_alloc(instance->storage, api_interface);
|
||||||
if(flipper_application_preload(instance->app, furi_string_get_cstr(path)) !=
|
|
||||||
|
if(flipper_application_preload(instance->app, furi_string_get_cstr(plugin_path)) !=
|
||||||
FlipperApplicationPreloadStatusSuccess)
|
FlipperApplicationPreloadStatusSuccess)
|
||||||
break;
|
break;
|
||||||
if(!flipper_application_is_plugin(instance->app)) break;
|
if(!flipper_application_is_plugin(instance->app)) break;
|
||||||
@@ -136,6 +135,7 @@ static const NfcSupportedCardsPlugin* nfc_supported_cards_get_plugin(
|
|||||||
|
|
||||||
plugin = descriptor->entry_point;
|
plugin = descriptor->entry_point;
|
||||||
} while(false);
|
} while(false);
|
||||||
|
furi_string_free(plugin_path);
|
||||||
|
|
||||||
return plugin;
|
return plugin;
|
||||||
}
|
}
|
||||||
@@ -151,13 +151,21 @@ static const NfcSupportedCardsPlugin* nfc_supported_cards_get_next_plugin(
|
|||||||
instance->directory, NULL, instance->file_name, sizeof(instance->file_name)))
|
instance->directory, NULL, instance->file_name, sizeof(instance->file_name)))
|
||||||
break;
|
break;
|
||||||
|
|
||||||
furi_string_set(instance->file_path, instance->file_name);
|
const size_t suffix_len = strlen(NFC_SUPPORTED_CARDS_PLUGIN_SUFFIX);
|
||||||
if(!furi_string_end_with_str(instance->file_path, NFC_SUPPORTED_CARDS_PLUGIN_SUFFIX))
|
const size_t file_name_len = strlen(instance->file_name);
|
||||||
continue;
|
if(file_name_len <= suffix_len) break;
|
||||||
|
|
||||||
path_concat(NFC_SUPPORTED_CARDS_PLUGINS_PATH, instance->file_name, instance->file_path);
|
size_t suffix_start_pos = file_name_len - suffix_len;
|
||||||
|
if(memcmp(
|
||||||
|
&instance->file_name[suffix_start_pos],
|
||||||
|
NFC_SUPPORTED_CARDS_PLUGIN_SUFFIX,
|
||||||
|
suffix_len) != 0) //-V1051
|
||||||
|
break;
|
||||||
|
|
||||||
plugin = nfc_supported_cards_get_plugin(instance, instance->file_path, api_interface);
|
// Trim suffix from file_name to save memory. The suffix will be concatenated on plugin load.
|
||||||
|
instance->file_name[suffix_start_pos] = '\0';
|
||||||
|
|
||||||
|
plugin = nfc_supported_cards_get_plugin(instance, instance->file_name, api_interface);
|
||||||
} while(plugin == NULL); //-V654
|
} while(plugin == NULL); //-V654
|
||||||
|
|
||||||
return plugin;
|
return plugin;
|
||||||
@@ -181,7 +189,7 @@ void nfc_supported_cards_load_cache(NfcSupportedCards* instance) {
|
|||||||
if(plugin == NULL) break; //-V547
|
if(plugin == NULL) break; //-V547
|
||||||
|
|
||||||
NfcSupportedCardsPluginCache plugin_cache = {}; //-V779
|
NfcSupportedCardsPluginCache plugin_cache = {}; //-V779
|
||||||
plugin_cache.path = furi_string_alloc_set(instance->load_context->file_path);
|
plugin_cache.name = furi_string_alloc_set(instance->load_context->file_name);
|
||||||
plugin_cache.protocol = plugin->protocol;
|
plugin_cache.protocol = plugin->protocol;
|
||||||
if(plugin->verify) {
|
if(plugin->verify) {
|
||||||
plugin_cache.feature |= NfcSupportedCardsPluginFeatureHasVerify;
|
plugin_cache.feature |= NfcSupportedCardsPluginFeatureHasVerify;
|
||||||
@@ -233,7 +241,7 @@ bool nfc_supported_cards_read(NfcSupportedCards* instance, NfcDevice* device, Nf
|
|||||||
const ElfApiInterface* api_interface =
|
const ElfApiInterface* api_interface =
|
||||||
composite_api_resolver_get(instance->api_resolver);
|
composite_api_resolver_get(instance->api_resolver);
|
||||||
const NfcSupportedCardsPlugin* plugin = nfc_supported_cards_get_plugin(
|
const NfcSupportedCardsPlugin* plugin = nfc_supported_cards_get_plugin(
|
||||||
instance->load_context, plugin_cache->path, api_interface);
|
instance->load_context, furi_string_get_cstr(plugin_cache->name), api_interface);
|
||||||
if(plugin == NULL) continue;
|
if(plugin == NULL) continue;
|
||||||
|
|
||||||
if(plugin->verify) {
|
if(plugin->verify) {
|
||||||
@@ -281,7 +289,7 @@ bool nfc_supported_cards_parse(
|
|||||||
const ElfApiInterface* api_interface =
|
const ElfApiInterface* api_interface =
|
||||||
composite_api_resolver_get(instance->api_resolver);
|
composite_api_resolver_get(instance->api_resolver);
|
||||||
const NfcSupportedCardsPlugin* plugin = nfc_supported_cards_get_plugin(
|
const NfcSupportedCardsPlugin* plugin = nfc_supported_cards_get_plugin(
|
||||||
instance->load_context, plugin_cache->path, api_interface);
|
instance->load_context, furi_string_get_cstr(plugin_cache->name), api_interface);
|
||||||
if(plugin == NULL) continue;
|
if(plugin == NULL) continue;
|
||||||
|
|
||||||
if(plugin->parse) {
|
if(plugin->parse) {
|
||||||
|
|||||||
@@ -9,6 +9,10 @@
|
|||||||
#include "../nfc_protocol_support_gui_common.h"
|
#include "../nfc_protocol_support_gui_common.h"
|
||||||
#include "../iso14443_4a/iso14443_4a_i.h"
|
#include "../iso14443_4a/iso14443_4a_i.h"
|
||||||
|
|
||||||
|
enum {
|
||||||
|
SubmenuIndexTransactions = SubmenuIndexCommonMax,
|
||||||
|
};
|
||||||
|
|
||||||
static void nfc_scene_info_on_enter_emv(NfcApp* instance) {
|
static void nfc_scene_info_on_enter_emv(NfcApp* instance) {
|
||||||
const NfcDevice* device = instance->nfc_device;
|
const NfcDevice* device = instance->nfc_device;
|
||||||
const EmvData* data = nfc_device_get_data(device, NfcProtocolEmv);
|
const EmvData* data = nfc_device_get_data(device, NfcProtocolEmv);
|
||||||
@@ -24,11 +28,6 @@ static void nfc_scene_info_on_enter_emv(NfcApp* instance) {
|
|||||||
furi_string_free(temp_str);
|
furi_string_free(temp_str);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void nfc_scene_more_info_on_enter_emv(NfcApp* instance) {
|
|
||||||
// Jump to advanced scene right away
|
|
||||||
scene_manager_next_scene(instance->scene_manager, NfcSceneEmvMoreInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
static NfcCommand nfc_scene_read_poller_callback_emv(NfcGenericEvent event, void* context) {
|
static NfcCommand nfc_scene_read_poller_callback_emv(NfcGenericEvent event, void* context) {
|
||||||
furi_assert(event.protocol == NfcProtocolEmv);
|
furi_assert(event.protocol == NfcProtocolEmv);
|
||||||
|
|
||||||
@@ -49,6 +48,20 @@ static void nfc_scene_read_on_enter_emv(NfcApp* instance) {
|
|||||||
nfc_poller_start(instance->poller, nfc_scene_read_poller_callback_emv, instance);
|
nfc_poller_start(instance->poller, nfc_scene_read_poller_callback_emv, instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void nfc_scene_read_menu_on_enter_emv(NfcApp* instance) {
|
||||||
|
Submenu* submenu = instance->submenu;
|
||||||
|
const EmvData* data = nfc_device_get_data(instance->nfc_device, NfcProtocolEmv);
|
||||||
|
|
||||||
|
if(data->emv_application.active_tr > 0) {
|
||||||
|
submenu_add_item(
|
||||||
|
submenu,
|
||||||
|
"Transactions",
|
||||||
|
SubmenuIndexTransactions,
|
||||||
|
nfc_protocol_support_common_submenu_callback,
|
||||||
|
instance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void nfc_scene_read_success_on_enter_emv(NfcApp* instance) {
|
static void nfc_scene_read_success_on_enter_emv(NfcApp* instance) {
|
||||||
const NfcDevice* device = instance->nfc_device;
|
const NfcDevice* device = instance->nfc_device;
|
||||||
const EmvData* data = nfc_device_get_data(device, NfcProtocolEmv);
|
const EmvData* data = nfc_device_get_data(device, NfcProtocolEmv);
|
||||||
@@ -64,8 +77,21 @@ static void nfc_scene_read_success_on_enter_emv(NfcApp* instance) {
|
|||||||
furi_string_free(temp_str);
|
furi_string_free(temp_str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool nfc_scene_read_menu_on_event_emv(NfcApp* instance, SceneManagerEvent event) {
|
||||||
|
bool consumed = false;
|
||||||
|
|
||||||
|
if(event.type == SceneManagerEventTypeCustom) {
|
||||||
|
if(event.event == SubmenuIndexTransactions) {
|
||||||
|
scene_manager_next_scene(instance->scene_manager, NfcSceneEmvTransactions);
|
||||||
|
consumed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return consumed;
|
||||||
|
}
|
||||||
|
|
||||||
const NfcProtocolSupportBase nfc_protocol_support_emv = {
|
const NfcProtocolSupportBase nfc_protocol_support_emv = {
|
||||||
.features = NfcProtocolFeatureMoreInfo,
|
.features = NfcProtocolFeatureNone,
|
||||||
|
|
||||||
.scene_info =
|
.scene_info =
|
||||||
{
|
{
|
||||||
@@ -74,7 +100,7 @@ const NfcProtocolSupportBase nfc_protocol_support_emv = {
|
|||||||
},
|
},
|
||||||
.scene_more_info =
|
.scene_more_info =
|
||||||
{
|
{
|
||||||
.on_enter = nfc_scene_more_info_on_enter_emv,
|
.on_enter = nfc_protocol_support_common_on_enter_empty,
|
||||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
.on_event = nfc_protocol_support_common_on_event_empty,
|
||||||
},
|
},
|
||||||
.scene_read =
|
.scene_read =
|
||||||
@@ -84,8 +110,8 @@ const NfcProtocolSupportBase nfc_protocol_support_emv = {
|
|||||||
},
|
},
|
||||||
.scene_read_menu =
|
.scene_read_menu =
|
||||||
{
|
{
|
||||||
.on_enter = nfc_protocol_support_common_on_enter_empty,
|
.on_enter = nfc_scene_read_menu_on_enter_emv,
|
||||||
.on_event = nfc_protocol_support_common_on_event_empty,
|
.on_event = nfc_scene_read_menu_on_event_emv,
|
||||||
},
|
},
|
||||||
.scene_read_success =
|
.scene_read_success =
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -68,7 +68,8 @@ void nfc_render_emv_application(const EmvApplication* apl, FuriString* str) {
|
|||||||
const uint8_t len = apl->aid_len;
|
const uint8_t len = apl->aid_len;
|
||||||
|
|
||||||
furi_string_cat_printf(str, "AID: ");
|
furi_string_cat_printf(str, "AID: ");
|
||||||
for(uint8_t i = 0; i < len; i++) furi_string_cat_printf(str, "%02X", apl->aid[i]);
|
for(uint8_t i = 0; i < len; i++)
|
||||||
|
furi_string_cat_printf(str, "%02X", apl->aid[i]);
|
||||||
furi_string_cat_printf(str, "\n");
|
furi_string_cat_printf(str, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ static void nfc_scene_read_success_on_enter_felica(NfcApp* instance) {
|
|||||||
|
|
||||||
FuriString* temp_str = furi_string_alloc();
|
FuriString* temp_str = furi_string_alloc();
|
||||||
|
|
||||||
if(!scene_manager_has_previous_scene(instance->scene_manager, NfcSceneFelicaUnlockWarn)) {
|
if(!scene_manager_has_previous_scene(instance->scene_manager, NfcSceneDesAuthUnlockWarn)) {
|
||||||
furi_string_cat_printf(
|
furi_string_cat_printf(
|
||||||
temp_str, "\e#%s\n", nfc_device_get_name(device, NfcDeviceNameTypeFull));
|
temp_str, "\e#%s\n", nfc_device_get_name(device, NfcDeviceNameTypeFull));
|
||||||
nfc_render_felica_info(data, NfcProtocolFormatTypeShort, temp_str);
|
nfc_render_felica_info(data, NfcProtocolFormatTypeShort, temp_str);
|
||||||
@@ -163,7 +163,7 @@ static void nfc_scene_read_menu_on_enter_felica(NfcApp* instance) {
|
|||||||
static bool nfc_scene_read_menu_on_event_felica(NfcApp* instance, SceneManagerEvent event) {
|
static bool nfc_scene_read_menu_on_event_felica(NfcApp* instance, SceneManagerEvent event) {
|
||||||
if(event.type == SceneManagerEventTypeCustom) {
|
if(event.type == SceneManagerEventTypeCustom) {
|
||||||
if(event.event == SubmenuIndexUnlock) {
|
if(event.event == SubmenuIndexUnlock) {
|
||||||
scene_manager_next_scene(instance->scene_manager, NfcSceneFelicaKeyInput);
|
scene_manager_next_scene(instance->scene_manager, NfcSceneDesAuthKeyInput);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,7 +71,7 @@ void nfc_render_iso15693_3_system_info(const Iso15693_3Data* data, FuriString* s
|
|||||||
void nfc_render_iso15693_3_extra(const Iso15693_3Data* data, FuriString* str) {
|
void nfc_render_iso15693_3_extra(const Iso15693_3Data* data, FuriString* str) {
|
||||||
furi_string_cat(str, "\n::::::::::::::::[General info]:::::::::::::::::\n");
|
furi_string_cat(str, "\n::::::::::::::::[General info]:::::::::::::::::\n");
|
||||||
if(data->system_info.flags & ISO15693_3_SYSINFO_FLAG_DSFID) {
|
if(data->system_info.flags & ISO15693_3_SYSINFO_FLAG_DSFID) {
|
||||||
furi_string_cat_printf(str, "DSFID: %02X\n", data->system_info.ic_ref);
|
furi_string_cat_printf(str, "DSFID: %02X\n", data->system_info.dsfid);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(data->system_info.flags & ISO15693_3_SYSINFO_FLAG_AFI) {
|
if(data->system_info.flags & ISO15693_3_SYSINFO_FLAG_AFI) {
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ void nfc_render_mf_desfire_version(const MfDesfireVersion* data, FuriString* str
|
|||||||
furi_string_cat_printf(
|
furi_string_cat_printf(
|
||||||
str,
|
str,
|
||||||
"batch %02x:%02x:%02x:%02x:%02x\n"
|
"batch %02x:%02x:%02x:%02x:%02x\n"
|
||||||
"week %d year %d\n",
|
"week %02x year 20%02x\n",
|
||||||
data->batch[0],
|
data->batch[0],
|
||||||
data->batch[1],
|
data->batch[1],
|
||||||
data->batch[2],
|
data->batch[2],
|
||||||
|
|||||||
@@ -150,6 +150,7 @@ static NfcCommand
|
|||||||
}
|
}
|
||||||
if(!mf_ultralight_event->data->auth_context.skip_auth) {
|
if(!mf_ultralight_event->data->auth_context.skip_auth) {
|
||||||
mf_ultralight_event->data->auth_context.password = instance->mf_ul_auth->password;
|
mf_ultralight_event->data->auth_context.password = instance->mf_ul_auth->password;
|
||||||
|
mf_ultralight_event->data->auth_context.tdes_key = instance->mf_ul_auth->tdes_key;
|
||||||
}
|
}
|
||||||
} else if(mf_ultralight_event->type == MfUltralightPollerEventTypeAuthSuccess) {
|
} else if(mf_ultralight_event->type == MfUltralightPollerEventTypeAuthSuccess) {
|
||||||
instance->mf_ul_auth->pack = mf_ultralight_event->data->auth_context.pack;
|
instance->mf_ul_auth->pack = mf_ultralight_event->data->auth_context.pack;
|
||||||
@@ -243,7 +244,13 @@ static bool nfc_scene_read_and_saved_menu_on_event_mf_ultralight(
|
|||||||
|
|
||||||
if(event.type == SceneManagerEventTypeCustom) {
|
if(event.type == SceneManagerEventTypeCustom) {
|
||||||
if(event.event == SubmenuIndexUnlock) {
|
if(event.event == SubmenuIndexUnlock) {
|
||||||
scene_manager_next_scene(instance->scene_manager, NfcSceneMfUltralightUnlockMenu);
|
const MfUltralightData* data =
|
||||||
|
nfc_device_get_data(instance->nfc_device, NfcProtocolMfUltralight);
|
||||||
|
|
||||||
|
uint32_t next_scene = (data->type == MfUltralightTypeMfulC) ?
|
||||||
|
NfcSceneDesAuthKeyInput :
|
||||||
|
NfcSceneMfUltralightUnlockMenu;
|
||||||
|
scene_manager_next_scene(instance->scene_manager, next_scene);
|
||||||
consumed = true;
|
consumed = true;
|
||||||
} else if(event.event == SubmenuIndexWrite) {
|
} else if(event.event == SubmenuIndexWrite) {
|
||||||
scene_manager_next_scene(instance->scene_manager, NfcSceneMfUltralightWrite);
|
scene_manager_next_scene(instance->scene_manager, NfcSceneMfUltralightWrite);
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ void nfc_unlock_helper_setup_from_state(NfcApp* instance) {
|
|||||||
bool unlocking =
|
bool unlocking =
|
||||||
scene_manager_has_previous_scene(
|
scene_manager_has_previous_scene(
|
||||||
instance->scene_manager, NfcSceneMfUltralightUnlockWarn) ||
|
instance->scene_manager, NfcSceneMfUltralightUnlockWarn) ||
|
||||||
scene_manager_has_previous_scene(instance->scene_manager, NfcSceneFelicaUnlockWarn);
|
scene_manager_has_previous_scene(instance->scene_manager, NfcSceneDesAuthUnlockWarn);
|
||||||
|
|
||||||
uint32_t state = unlocking ? NfcSceneReadMenuStateCardSearch : NfcSceneReadMenuStateCardFound;
|
uint32_t state = unlocking ? NfcSceneReadMenuStateCardSearch : NfcSceneReadMenuStateCardFound;
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user