mirror of
https://github.com/D4C1-Labs/Flipper-ARF.git
synced 2026-07-02 01:21:40 +00:00
Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 426607f916 | |||
| 5badcb6143 | |||
| 7ebd996eed |
@@ -1,246 +0,0 @@
|
||||
---
|
||||
Language: Cpp
|
||||
AccessModifierOffset: -4
|
||||
AlignAfterOpenBracket: AlwaysBreak
|
||||
AlignArrayOfStructures: None
|
||||
AlignConsecutiveAssignments:
|
||||
Enabled: false
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCompound: false
|
||||
AlignFunctionPointers: false
|
||||
PadOperators: true
|
||||
AlignConsecutiveBitFields:
|
||||
Enabled: true
|
||||
AcrossEmptyLines: true
|
||||
AcrossComments: true
|
||||
AlignCompound: false
|
||||
AlignFunctionPointers: false
|
||||
PadOperators: true
|
||||
AlignConsecutiveDeclarations:
|
||||
Enabled: false
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCompound: false
|
||||
AlignFunctionPointers: false
|
||||
PadOperators: true
|
||||
AlignConsecutiveMacros:
|
||||
Enabled: true
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: true
|
||||
AlignCompound: true
|
||||
AlignFunctionPointers: false
|
||||
PadOperators: true
|
||||
AlignConsecutiveShortCaseStatements:
|
||||
Enabled: false
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCaseColons: false
|
||||
AlignEscapedNewlines: Left
|
||||
AlignOperands: Align
|
||||
AlignTrailingComments:
|
||||
Kind: Never
|
||||
OverEmptyLines: 0
|
||||
AllowAllArgumentsOnNextLine: true
|
||||
AllowAllParametersOfDeclarationOnNextLine: false
|
||||
AllowBreakBeforeNoexceptSpecifier: Never
|
||||
AllowShortBlocksOnASingleLine: Never
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortCompoundRequirementOnASingleLine: true
|
||||
AllowShortEnumsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: None
|
||||
AllowShortIfStatementsOnASingleLine: WithoutElse
|
||||
AllowShortLambdasOnASingleLine: All
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AlwaysBreakAfterDefinitionReturnType: None
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakBeforeMultilineStrings: false
|
||||
AlwaysBreakTemplateDeclarations: Yes
|
||||
AttributeMacros:
|
||||
- __capability
|
||||
BinPackArguments: false
|
||||
BinPackParameters: false
|
||||
BitFieldColonSpacing: Both
|
||||
BraceWrapping:
|
||||
AfterCaseLabel: false
|
||||
AfterClass: false
|
||||
AfterControlStatement: Never
|
||||
AfterEnum: false
|
||||
AfterExternBlock: false
|
||||
AfterFunction: false
|
||||
AfterNamespace: false
|
||||
AfterObjCDeclaration: false
|
||||
AfterStruct: false
|
||||
AfterUnion: false
|
||||
BeforeCatch: false
|
||||
BeforeElse: false
|
||||
BeforeLambdaBody: false
|
||||
BeforeWhile: false
|
||||
IndentBraces: false
|
||||
SplitEmptyFunction: true
|
||||
SplitEmptyRecord: true
|
||||
SplitEmptyNamespace: true
|
||||
BreakAdjacentStringLiterals: true
|
||||
BreakAfterAttributes: Leave
|
||||
BreakAfterJavaFieldAnnotations: false
|
||||
BreakArrays: true
|
||||
BreakBeforeBinaryOperators: None
|
||||
BreakBeforeConceptDeclarations: Always
|
||||
BreakBeforeBraces: Attach
|
||||
BreakBeforeInlineASMColon: OnlyMultiline
|
||||
BreakBeforeTernaryOperators: false
|
||||
BreakConstructorInitializers: BeforeComma
|
||||
BreakInheritanceList: BeforeColon
|
||||
BreakStringLiterals: false
|
||||
ColumnLimit: 99
|
||||
CommentPragmas: '^ IWYU pragma:'
|
||||
CompactNamespaces: false
|
||||
ConstructorInitializerIndentWidth: 4
|
||||
ContinuationIndentWidth: 4
|
||||
Cpp11BracedListStyle: true
|
||||
DerivePointerAlignment: false
|
||||
DisableFormat: false
|
||||
EmptyLineAfterAccessModifier: Never
|
||||
EmptyLineBeforeAccessModifier: LogicalBlock
|
||||
ExperimentalAutoDetectBinPacking: false
|
||||
FixNamespaceComments: false
|
||||
ForEachMacros:
|
||||
- foreach
|
||||
- Q_FOREACH
|
||||
- BOOST_FOREACH
|
||||
- M_EACH
|
||||
IfMacros:
|
||||
- KJ_IF_MAYBE
|
||||
IncludeBlocks: Preserve
|
||||
IncludeCategories:
|
||||
- Regex: '.*'
|
||||
Priority: 1
|
||||
SortPriority: 0
|
||||
CaseSensitive: false
|
||||
- Regex: '^(<|"(gtest|gmock|isl|json)/)'
|
||||
Priority: 3
|
||||
SortPriority: 0
|
||||
CaseSensitive: false
|
||||
- Regex: '.*'
|
||||
Priority: 1
|
||||
SortPriority: 0
|
||||
CaseSensitive: false
|
||||
IncludeIsMainRegex: '(Test)?$'
|
||||
IncludeIsMainSourceRegex: ''
|
||||
IndentAccessModifiers: false
|
||||
IndentCaseBlocks: false
|
||||
IndentCaseLabels: false
|
||||
IndentExternBlock: AfterExternBlock
|
||||
IndentGotoLabels: true
|
||||
IndentPPDirectives: None
|
||||
IndentRequiresClause: false
|
||||
IndentWidth: 4
|
||||
IndentWrappedFunctionNames: true
|
||||
InsertBraces: false
|
||||
InsertNewlineAtEOF: true
|
||||
InsertTrailingCommas: None
|
||||
IntegerLiteralSeparator:
|
||||
Binary: 0
|
||||
BinaryMinDigits: 0
|
||||
Decimal: 0
|
||||
DecimalMinDigits: 0
|
||||
Hex: 0
|
||||
HexMinDigits: 0
|
||||
JavaScriptQuotes: Leave
|
||||
JavaScriptWrapImports: true
|
||||
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||
KeepEmptyLinesAtEOF: false
|
||||
LambdaBodyIndentation: Signature
|
||||
LineEnding: DeriveLF
|
||||
MacroBlockBegin: ''
|
||||
MacroBlockEnd: ''
|
||||
MaxEmptyLinesToKeep: 1
|
||||
NamespaceIndentation: None
|
||||
ObjCBinPackProtocolList: Auto
|
||||
ObjCBlockIndentWidth: 4
|
||||
ObjCBreakBeforeNestedBlockParam: true
|
||||
ObjCSpaceAfterProperty: true
|
||||
ObjCSpaceBeforeProtocolList: true
|
||||
PackConstructorInitializers: BinPack
|
||||
PenaltyBreakAssignment: 10
|
||||
PenaltyBreakBeforeFirstCallParameter: 30
|
||||
PenaltyBreakComment: 10
|
||||
PenaltyBreakFirstLessLess: 0
|
||||
PenaltyBreakOpenParenthesis: 0
|
||||
PenaltyBreakScopeResolution: 500
|
||||
PenaltyBreakString: 10
|
||||
PenaltyBreakTemplateDeclaration: 10
|
||||
PenaltyExcessCharacter: 100
|
||||
PenaltyIndentedWhitespace: 0
|
||||
PenaltyReturnTypeOnItsOwnLine: 60
|
||||
PointerAlignment: Left
|
||||
PPIndentWidth: -1
|
||||
QualifierAlignment: Leave
|
||||
ReferenceAlignment: Pointer
|
||||
ReflowComments: false
|
||||
RemoveBracesLLVM: false
|
||||
RemoveParentheses: Leave
|
||||
RemoveSemicolon: true
|
||||
RequiresClausePosition: OwnLine
|
||||
RequiresExpressionIndentation: OuterScope
|
||||
SeparateDefinitionBlocks: Leave
|
||||
ShortNamespaceLines: 1
|
||||
SkipMacroDefinitionBody: false
|
||||
SortIncludes: Never
|
||||
SortJavaStaticImport: Before
|
||||
SortUsingDeclarations: Never
|
||||
SpaceAfterCStyleCast: false
|
||||
SpaceAfterLogicalNot: false
|
||||
SpaceAfterTemplateKeyword: true
|
||||
SpaceAroundPointerQualifiers: Default
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeCaseColon: false
|
||||
SpaceBeforeCpp11BracedList: false
|
||||
SpaceBeforeCtorInitializerColon: true
|
||||
SpaceBeforeInheritanceColon: true
|
||||
SpaceBeforeJsonColon: false
|
||||
SpaceBeforeParens: Never
|
||||
SpaceBeforeParensOptions:
|
||||
AfterControlStatements: false
|
||||
AfterForeachMacros: false
|
||||
AfterFunctionDefinitionName: false
|
||||
AfterFunctionDeclarationName: false
|
||||
AfterIfMacros: false
|
||||
AfterOverloadedOperator: false
|
||||
AfterPlacementOperator: true
|
||||
AfterRequiresInClause: false
|
||||
AfterRequiresInExpression: false
|
||||
BeforeNonEmptyParentheses: false
|
||||
SpaceBeforeRangeBasedForLoopColon: true
|
||||
SpaceBeforeSquareBrackets: false
|
||||
SpaceInEmptyBlock: false
|
||||
SpacesBeforeTrailingComments: 1
|
||||
SpacesInAngles: Never
|
||||
SpacesInContainerLiterals: false
|
||||
SpacesInLineCommentPrefix:
|
||||
Minimum: 1
|
||||
Maximum: -1
|
||||
SpacesInParens: Never
|
||||
SpacesInParensOptions:
|
||||
InCStyleCasts: false
|
||||
InConditionalStatements: false
|
||||
InEmptyParentheses: false
|
||||
Other: false
|
||||
SpacesInSquareBrackets: false
|
||||
Standard: c++20
|
||||
StatementAttributeLikeMacros:
|
||||
- Q_EMIT
|
||||
StatementMacros:
|
||||
- Q_UNUSED
|
||||
- QT_REQUIRE_VERSION
|
||||
TabWidth: 4
|
||||
UseTab: Never
|
||||
VerilogBreakBetweenInstancePorts: true
|
||||
WhitespaceSensitiveMacros:
|
||||
- STRINGIZE
|
||||
- PP_STRINGIZE
|
||||
- BOOST_PP_STRINGIZE
|
||||
- NS_SWIFT_NAME
|
||||
- CF_SWIFT_NAME
|
||||
...
|
||||
|
||||
@@ -1,674 +0,0 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The GNU General Public License is a free, copyleft license for
|
||||
software and other kinds of works.
|
||||
|
||||
The licenses for most software and other practical works are designed
|
||||
to take away your freedom to share and change the works. By contrast,
|
||||
the GNU General Public License is intended to guarantee your freedom to
|
||||
share and change all versions of a program--to make sure it remains free
|
||||
software for all its users. We, the Free Software Foundation, use the
|
||||
GNU General Public License for most of our software; it applies also to
|
||||
any other work released this way by its authors. You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
them if you wish), that you receive source code or can get it if you
|
||||
want it, that you can change the software or use pieces of it in new
|
||||
free programs, and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to prevent others from denying you
|
||||
these rights or asking you to surrender the rights. Therefore, you have
|
||||
certain responsibilities if you distribute copies of the software, or if
|
||||
you modify it: responsibilities to respect the freedom of others.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must pass on to the recipients the same
|
||||
freedoms that you received. You must make sure that they, too, receive
|
||||
or can get the source code. And you must show them these terms so they
|
||||
know their rights.
|
||||
|
||||
Developers that use the GNU GPL protect your rights with two steps:
|
||||
(1) assert copyright on the software, and (2) offer you this License
|
||||
giving you legal permission to copy, distribute and/or modify it.
|
||||
|
||||
For the developers' and authors' protection, the GPL clearly explains
|
||||
that there is no warranty for this free software. For both users' and
|
||||
authors' sake, the GPL requires that modified versions be marked as
|
||||
changed, so that their problems will not be attributed erroneously to
|
||||
authors of previous versions.
|
||||
|
||||
Some devices are designed to deny users access to install or run
|
||||
modified versions of the software inside them, although the manufacturer
|
||||
can do so. This is fundamentally incompatible with the aim of
|
||||
protecting users' freedom to change the software. The systematic
|
||||
pattern of such abuse occurs in the area of products for individuals to
|
||||
use, which is precisely where it is most unacceptable. Therefore, we
|
||||
have designed this version of the GPL to prohibit the practice for those
|
||||
products. If such problems arise substantially in other domains, we
|
||||
stand ready to extend this provision to those domains in future versions
|
||||
of the GPL, as needed to protect the freedom of users.
|
||||
|
||||
Finally, every program is threatened constantly by software patents.
|
||||
States should not allow patents to restrict development and use of
|
||||
software on general-purpose computers, but in those that do, we wish to
|
||||
avoid the special danger that patents applied to a free program could
|
||||
make it effectively proprietary. To prevent this, the GPL assures that
|
||||
patents cannot be used to render the program non-free.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
TERMS AND CONDITIONS
|
||||
|
||||
0. Definitions.
|
||||
|
||||
"This License" refers to version 3 of the GNU General Public License.
|
||||
|
||||
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||
works, such as semiconductor masks.
|
||||
|
||||
"The Program" refers to any copyrightable work licensed under this
|
||||
License. Each licensee is addressed as "you". "Licensees" and
|
||||
"recipients" may be individuals or organizations.
|
||||
|
||||
To "modify" a work means to copy from or adapt all or part of the work
|
||||
in a fashion requiring copyright permission, other than the making of an
|
||||
exact copy. The resulting work is called a "modified version" of the
|
||||
earlier work or a work "based on" the earlier work.
|
||||
|
||||
A "covered work" means either the unmodified Program or a work based
|
||||
on the Program.
|
||||
|
||||
To "propagate" a work means to do anything with it that, without
|
||||
permission, would make you directly or secondarily liable for
|
||||
infringement under applicable copyright law, except executing it on a
|
||||
computer or modifying a private copy. Propagation includes copying,
|
||||
distribution (with or without modification), making available to the
|
||||
public, and in some countries other activities as well.
|
||||
|
||||
To "convey" a work means any kind of propagation that enables other
|
||||
parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
work under this License, and how to view a copy of this License. If
|
||||
the interface presents a list of user commands or options, such as a
|
||||
menu, a prominent item in the list meets this criterion.
|
||||
|
||||
1. Source Code.
|
||||
|
||||
The "source code" for a work means the preferred form of the work
|
||||
for making modifications to it. "Object code" means any non-source
|
||||
form of a work.
|
||||
|
||||
A "Standard Interface" means an interface that either is an official
|
||||
standard defined by a recognized standards body, or, in the case of
|
||||
interfaces specified for a particular programming language, one that
|
||||
is widely used among developers working in that language.
|
||||
|
||||
The "System Libraries" of an executable work include anything, other
|
||||
than the work as a whole, that (a) is included in the normal form of
|
||||
packaging a Major Component, but which is not part of that Major
|
||||
Component, and (b) serves only to enable use of the work with that
|
||||
Major Component, or to implement a Standard Interface for which an
|
||||
implementation is available to the public in source code form. A
|
||||
"Major Component", in this context, means a major essential component
|
||||
(kernel, window system, and so on) of the specific operating system
|
||||
(if any) on which the executable work runs, or a compiler used to
|
||||
produce the work, or an object code interpreter used to run it.
|
||||
|
||||
The "Corresponding Source" for a work in object code form means all
|
||||
the source code needed to generate, install, and (for an executable
|
||||
work) run the object code and to modify the work, including scripts to
|
||||
control those activities. However, it does not include the work's
|
||||
System Libraries, or general-purpose tools or generally available free
|
||||
programs which are used unmodified in performing those activities but
|
||||
which are not part of the work. For example, Corresponding Source
|
||||
includes interface definition files associated with source files for
|
||||
the work, and the source code for shared libraries and dynamically
|
||||
linked subprograms that the work is specifically designed to require,
|
||||
such as by intimate data communication or control flow between those
|
||||
subprograms and other parts of the work.
|
||||
|
||||
The Corresponding Source need not include anything that users
|
||||
can regenerate automatically from other parts of the Corresponding
|
||||
Source.
|
||||
|
||||
The Corresponding Source for a work in source code form is that
|
||||
same work.
|
||||
|
||||
2. Basic Permissions.
|
||||
|
||||
All rights granted under this License are granted for the term of
|
||||
copyright on the Program, and are irrevocable provided the stated
|
||||
conditions are met. This License explicitly affirms your unlimited
|
||||
permission to run the unmodified Program. The output from running a
|
||||
covered work is covered by this License only if the output, given its
|
||||
content, constitutes a covered work. This License acknowledges your
|
||||
rights of fair use or other equivalent, as provided by copyright law.
|
||||
|
||||
You may make, run and propagate covered works that you do not
|
||||
convey, without conditions so long as your license otherwise remains
|
||||
in force. You may convey covered works to others for the sole purpose
|
||||
of having them make modifications exclusively for you, or provide you
|
||||
with facilities for running those works, provided that you comply with
|
||||
the terms of this License in conveying all material for which you do
|
||||
not control copyright. Those thus making or running the covered works
|
||||
for you must do so exclusively on your behalf, under your direction
|
||||
and control, on terms that prohibit them from making any copies of
|
||||
your copyrighted material outside their relationship with you.
|
||||
|
||||
Conveying under any other circumstances is permitted solely under
|
||||
the conditions stated below. Sublicensing is not allowed; section 10
|
||||
makes it unnecessary.
|
||||
|
||||
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||
|
||||
No covered work shall be deemed part of an effective technological
|
||||
measure under any applicable law fulfilling obligations under article
|
||||
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||
similar laws prohibiting or restricting circumvention of such
|
||||
measures.
|
||||
|
||||
When you convey a covered work, you waive any legal power to forbid
|
||||
circumvention of technological measures to the extent such circumvention
|
||||
is effected by exercising rights under this License with respect to
|
||||
the covered work, and you disclaim any intention to limit operation or
|
||||
modification of the work as a means of enforcing, against the work's
|
||||
users, your or third parties' legal rights to forbid circumvention of
|
||||
technological measures.
|
||||
|
||||
4. Conveying Verbatim Copies.
|
||||
|
||||
You may convey verbatim copies of the Program's source code as you
|
||||
receive it, in any medium, provided that you conspicuously and
|
||||
appropriately publish on each copy an appropriate copyright notice;
|
||||
keep intact all notices stating that this License and any
|
||||
non-permissive terms added in accord with section 7 apply to the code;
|
||||
keep intact all notices of the absence of any warranty; and give all
|
||||
recipients a copy of this License along with the Program.
|
||||
|
||||
You may charge any price or no price for each copy that you convey,
|
||||
and you may offer support or warranty protection for a fee.
|
||||
|
||||
5. Conveying Modified Source Versions.
|
||||
|
||||
You may convey a work based on the Program, or the modifications to
|
||||
produce it from the Program, in the form of source code under the
|
||||
terms of section 4, provided that you also meet all of these conditions:
|
||||
|
||||
a) The work must carry prominent notices stating that you modified
|
||||
it, and giving a relevant date.
|
||||
|
||||
b) The work must carry prominent notices stating that it is
|
||||
released under this License and any conditions added under section
|
||||
7. This requirement modifies the requirement in section 4 to
|
||||
"keep intact all notices".
|
||||
|
||||
c) You must license the entire work, as a whole, under this
|
||||
License to anyone who comes into possession of a copy. This
|
||||
License will therefore apply, along with any applicable section 7
|
||||
additional terms, to the whole of the work, and all its parts,
|
||||
regardless of how they are packaged. This License gives no
|
||||
permission to license the work in any other way, but it does not
|
||||
invalidate such permission if you have separately received it.
|
||||
|
||||
d) If the work has interactive user interfaces, each must display
|
||||
Appropriate Legal Notices; however, if the Program has interactive
|
||||
interfaces that do not display Appropriate Legal Notices, your
|
||||
work need not make them do so.
|
||||
|
||||
A compilation of a covered work with other separate and independent
|
||||
works, which are not by their nature extensions of the covered work,
|
||||
and which are not combined with it such as to form a larger program,
|
||||
in or on a volume of a storage or distribution medium, is called an
|
||||
"aggregate" if the compilation and its resulting copyright are not
|
||||
used to limit the access or legal rights of the compilation's users
|
||||
beyond what the individual works permit. Inclusion of a covered work
|
||||
in an aggregate does not cause this License to apply to the other
|
||||
parts of the aggregate.
|
||||
|
||||
6. Conveying Non-Source Forms.
|
||||
|
||||
You may convey a covered work in object code form under the terms
|
||||
of sections 4 and 5, provided that you also convey the
|
||||
machine-readable Corresponding Source under the terms of this License,
|
||||
in one of these ways:
|
||||
|
||||
a) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by the
|
||||
Corresponding Source fixed on a durable physical medium
|
||||
customarily used for software interchange.
|
||||
|
||||
b) Convey the object code in, or embodied in, a physical product
|
||||
(including a physical distribution medium), accompanied by a
|
||||
written offer, valid for at least three years and valid for as
|
||||
long as you offer spare parts or customer support for that product
|
||||
model, to give anyone who possesses the object code either (1) a
|
||||
copy of the Corresponding Source for all the software in the
|
||||
product that is covered by this License, on a durable physical
|
||||
medium customarily used for software interchange, for a price no
|
||||
more than your reasonable cost of physically performing this
|
||||
conveying of source, or (2) access to copy the
|
||||
Corresponding Source from a network server at no charge.
|
||||
|
||||
c) Convey individual copies of the object code with a copy of the
|
||||
written offer to provide the Corresponding Source. This
|
||||
alternative is allowed only occasionally and noncommercially, and
|
||||
only if you received the object code with such an offer, in accord
|
||||
with subsection 6b.
|
||||
|
||||
d) Convey the object code by offering access from a designated
|
||||
place (gratis or for a charge), and offer equivalent access to the
|
||||
Corresponding Source in the same way through the same place at no
|
||||
further charge. You need not require recipients to copy the
|
||||
Corresponding Source along with the object code. If the place to
|
||||
copy the object code is a network server, the Corresponding Source
|
||||
may be on a different server (operated by you or a third party)
|
||||
that supports equivalent copying facilities, provided you maintain
|
||||
clear directions next to the object code saying where to find the
|
||||
Corresponding Source. Regardless of what server hosts the
|
||||
Corresponding Source, you remain obligated to ensure that it is
|
||||
available for as long as needed to satisfy these requirements.
|
||||
|
||||
e) Convey the object code using peer-to-peer transmission, provided
|
||||
you inform other peers where the object code and Corresponding
|
||||
Source of the work are being offered to the general public at no
|
||||
charge under subsection 6d.
|
||||
|
||||
A separable portion of the object code, whose source code is excluded
|
||||
from the Corresponding Source as a System Library, need not be
|
||||
included in conveying the object code work.
|
||||
|
||||
A "User Product" is either (1) a "consumer product", which means any
|
||||
tangible personal property which is normally used for personal, family,
|
||||
or household purposes, or (2) anything designed or sold for incorporation
|
||||
into a dwelling. In determining whether a product is a consumer product,
|
||||
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||
product received by a particular user, "normally used" refers to a
|
||||
typical or common use of that class of product, regardless of the status
|
||||
of the particular user or of the way in which the particular user
|
||||
actually uses, or expects or is expected to use, the product. A product
|
||||
is a consumer product regardless of whether the product has substantial
|
||||
commercial, industrial or non-consumer uses, unless such uses represent
|
||||
the only significant mode of use of the product.
|
||||
|
||||
"Installation Information" for a User Product means any methods,
|
||||
procedures, authorization keys, or other information required to install
|
||||
and execute modified versions of a covered work in that User Product from
|
||||
a modified version of its Corresponding Source. The information must
|
||||
suffice to ensure that the continued functioning of the modified object
|
||||
code is in no case prevented or interfered with solely because
|
||||
modification has been made.
|
||||
|
||||
If you convey an object code work under this section in, or with, or
|
||||
specifically for use in, a User Product, and the conveying occurs as
|
||||
part of a transaction in which the right of possession and use of the
|
||||
User Product is transferred to the recipient in perpetuity or for a
|
||||
fixed term (regardless of how the transaction is characterized), the
|
||||
Corresponding Source conveyed under this section must be accompanied
|
||||
by the Installation Information. But this requirement does not apply
|
||||
if neither you nor any third party retains the ability to install
|
||||
modified object code on the User Product (for example, the work has
|
||||
been installed in ROM).
|
||||
|
||||
The requirement to provide Installation Information does not include a
|
||||
requirement to continue to provide support service, warranty, or updates
|
||||
for a work that has been modified or installed by the recipient, or for
|
||||
the User Product in which it has been modified or installed. Access to a
|
||||
network may be denied when the modification itself materially and
|
||||
adversely affects the operation of the network or violates the rules and
|
||||
protocols for communication across the network.
|
||||
|
||||
Corresponding Source conveyed, and Installation Information provided,
|
||||
in accord with this section must be in a format that is publicly
|
||||
documented (and with an implementation available to the public in
|
||||
source code form), and must require no special password or key for
|
||||
unpacking, reading or copying.
|
||||
|
||||
7. Additional Terms.
|
||||
|
||||
"Additional permissions" are terms that supplement the terms of this
|
||||
License by making exceptions from one or more of its conditions.
|
||||
Additional permissions that are applicable to the entire Program shall
|
||||
be treated as though they were included in this License, to the extent
|
||||
that they are valid under applicable law. If additional permissions
|
||||
apply only to part of the Program, that part may be used separately
|
||||
under those permissions, but the entire Program remains governed by
|
||||
this License without regard to the additional permissions.
|
||||
|
||||
When you convey a copy of a covered work, you may at your option
|
||||
remove any additional permissions from that copy, or from any part of
|
||||
it. (Additional permissions may be written to require their own
|
||||
removal in certain cases when you modify the work.) You may place
|
||||
additional permissions on material, added by you to a covered work,
|
||||
for which you have or can give appropriate copyright permission.
|
||||
|
||||
Notwithstanding any other provision of this License, for material you
|
||||
add to a covered work, you may (if authorized by the copyright holders of
|
||||
that material) supplement the terms of this License with terms:
|
||||
|
||||
a) Disclaiming warranty or limiting liability differently from the
|
||||
terms of sections 15 and 16 of this License; or
|
||||
|
||||
b) Requiring preservation of specified reasonable legal notices or
|
||||
author attributions in that material or in the Appropriate Legal
|
||||
Notices displayed by works containing it; or
|
||||
|
||||
c) Prohibiting misrepresentation of the origin of that material, or
|
||||
requiring that modified versions of such material be marked in
|
||||
reasonable ways as different from the original version; or
|
||||
|
||||
d) Limiting the use for publicity purposes of names of licensors or
|
||||
authors of the material; or
|
||||
|
||||
e) Declining to grant rights under trademark law for use of some
|
||||
trade names, trademarks, or service marks; or
|
||||
|
||||
f) Requiring indemnification of licensors and authors of that
|
||||
material by anyone who conveys the material (or modified versions of
|
||||
it) with contractual assumptions of liability to the recipient, for
|
||||
any liability that these contractual assumptions directly impose on
|
||||
those licensors and authors.
|
||||
|
||||
All other non-permissive additional terms are considered "further
|
||||
restrictions" within the meaning of section 10. If the Program as you
|
||||
received it, or any part of it, contains a notice stating that it is
|
||||
governed by this License along with a term that is a further
|
||||
restriction, you may remove that term. If a license document contains
|
||||
a further restriction but permits relicensing or conveying under this
|
||||
License, you may add to a covered work material governed by the terms
|
||||
of that license document, provided that the further restriction does
|
||||
not survive such relicensing or conveying.
|
||||
|
||||
If you add terms to a covered work in accord with this section, you
|
||||
must place, in the relevant source files, a statement of the
|
||||
additional terms that apply to those files, or a notice indicating
|
||||
where to find the applicable terms.
|
||||
|
||||
Additional terms, permissive or non-permissive, may be stated in the
|
||||
form of a separately written license, or stated as exceptions;
|
||||
the above requirements apply either way.
|
||||
|
||||
8. Termination.
|
||||
|
||||
You may not propagate or modify a covered work except as expressly
|
||||
provided under this License. Any attempt otherwise to propagate or
|
||||
modify it is void, and will automatically terminate your rights under
|
||||
this License (including any patent licenses granted under the third
|
||||
paragraph of section 11).
|
||||
|
||||
However, if you cease all violation of this License, then your
|
||||
license from a particular copyright holder is reinstated (a)
|
||||
provisionally, unless and until the copyright holder explicitly and
|
||||
finally terminates your license, and (b) permanently, if the copyright
|
||||
holder fails to notify you of the violation by some reasonable means
|
||||
prior to 60 days after the cessation.
|
||||
|
||||
Moreover, your license from a particular copyright holder is
|
||||
reinstated permanently if the copyright holder notifies you of the
|
||||
violation by some reasonable means, this is the first time you have
|
||||
received notice of violation of this License (for any work) from that
|
||||
copyright holder, and you cure the violation prior to 30 days after
|
||||
your receipt of the notice.
|
||||
|
||||
Termination of your rights under this section does not terminate the
|
||||
licenses of parties who have received copies or rights from you under
|
||||
this License. If your rights have been terminated and not permanently
|
||||
reinstated, you do not qualify to receive new licenses for the same
|
||||
material under section 10.
|
||||
|
||||
9. Acceptance Not Required for Having Copies.
|
||||
|
||||
You are not required to accept this License in order to receive or
|
||||
run a copy of the Program. Ancillary propagation of a covered work
|
||||
occurring solely as a consequence of using peer-to-peer transmission
|
||||
to receive a copy likewise does not require acceptance. However,
|
||||
nothing other than this License grants you permission to propagate or
|
||||
modify any covered work. These actions infringe copyright if you do
|
||||
not accept this License. Therefore, by modifying or propagating a
|
||||
covered work, you indicate your acceptance of this License to do so.
|
||||
|
||||
10. Automatic Licensing of Downstream Recipients.
|
||||
|
||||
Each time you convey a covered work, the recipient automatically
|
||||
receives a license from the original licensors, to run, modify and
|
||||
propagate that work, subject to this License. You are not responsible
|
||||
for enforcing compliance by third parties with this License.
|
||||
|
||||
An "entity transaction" is a transaction transferring control of an
|
||||
organization, or substantially all assets of one, or subdividing an
|
||||
organization, or merging organizations. If propagation of a covered
|
||||
work results from an entity transaction, each party to that
|
||||
transaction who receives a copy of the work also receives whatever
|
||||
licenses to the work the party's predecessor in interest had or could
|
||||
give under the previous paragraph, plus a right to possession of the
|
||||
Corresponding Source of the work from the predecessor in interest, if
|
||||
the predecessor has it or can get it with reasonable efforts.
|
||||
|
||||
You may not impose any further restrictions on the exercise of the
|
||||
rights granted or affirmed under this License. For example, you may
|
||||
not impose a license fee, royalty, or other charge for exercise of
|
||||
rights granted under this License, and you may not initiate litigation
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||
any patent claim is infringed by making, using, selling, offering for
|
||||
sale, or importing the Program or any portion of it.
|
||||
|
||||
11. Patents.
|
||||
|
||||
A "contributor" is a copyright holder who authorizes use under this
|
||||
License of the Program or a work on which the Program is based. The
|
||||
work thus licensed is called the contributor's "contributor version".
|
||||
|
||||
A contributor's "essential patent claims" are all patent claims
|
||||
owned or controlled by the contributor, whether already acquired or
|
||||
hereafter acquired, that would be infringed by some manner, permitted
|
||||
by this License, of making, using, or selling its contributor version,
|
||||
but do not include claims that would be infringed only as a
|
||||
consequence of further modification of the contributor version. For
|
||||
purposes of this definition, "control" includes the right to grant
|
||||
patent sublicenses in a manner consistent with the requirements of
|
||||
this License.
|
||||
|
||||
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||
patent license under the contributor's essential patent claims, to
|
||||
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||
propagate the contents of its contributor version.
|
||||
|
||||
In the following three paragraphs, a "patent license" is any express
|
||||
agreement or commitment, however denominated, not to enforce a patent
|
||||
(such as an express permission to practice a patent or covenant not to
|
||||
sue for patent infringement). To "grant" such a patent license to a
|
||||
party means to make such an agreement or commitment not to enforce a
|
||||
patent against the party.
|
||||
|
||||
If you convey a covered work, knowingly relying on a patent license,
|
||||
and the Corresponding Source of the work is not available for anyone
|
||||
to copy, free of charge and under the terms of this License, through a
|
||||
publicly available network server or other readily accessible means,
|
||||
then you must either (1) cause the Corresponding Source to be so
|
||||
available, or (2) arrange to deprive yourself of the benefit of the
|
||||
patent license for this particular work, or (3) arrange, in a manner
|
||||
consistent with the requirements of this License, to extend the patent
|
||||
license to downstream recipients. "Knowingly relying" means you have
|
||||
actual knowledge that, but for the patent license, your conveying the
|
||||
covered work in a country, or your recipient's use of the covered work
|
||||
in a country, would infringe one or more identifiable patents in that
|
||||
country that you have reason to believe are valid.
|
||||
|
||||
If, pursuant to or in connection with a single transaction or
|
||||
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||
covered work, and grant a patent license to some of the parties
|
||||
receiving the covered work authorizing them to use, propagate, modify
|
||||
or convey a specific copy of the covered work, then the patent license
|
||||
you grant is automatically extended to all recipients of the covered
|
||||
work and works based on it.
|
||||
|
||||
A patent license is "discriminatory" if it does not include within
|
||||
the scope of its coverage, prohibits the exercise of, or is
|
||||
conditioned on the non-exercise of one or more of the rights that are
|
||||
specifically granted under this License. You may not convey a covered
|
||||
work if you are a party to an arrangement with a third party that is
|
||||
in the business of distributing software, under which you make payment
|
||||
to the third party based on the extent of your activity of conveying
|
||||
the work, and under which the third party grants, to any of the
|
||||
parties who would receive the covered work from you, a discriminatory
|
||||
patent license (a) in connection with copies of the covered work
|
||||
conveyed by you (or copies made from those copies), or (b) primarily
|
||||
for and in connection with specific products or compilations that
|
||||
contain the covered work, unless you entered into that arrangement,
|
||||
or that patent license was granted, prior to 28 March 2007.
|
||||
|
||||
Nothing in this License shall be construed as excluding or limiting
|
||||
any implied license or other defenses to infringement that may
|
||||
otherwise be available to you under applicable patent law.
|
||||
|
||||
12. No Surrender of Others' Freedom.
|
||||
|
||||
If conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot convey a
|
||||
covered work so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you may
|
||||
not convey it at all. For example, if you agree to terms that obligate you
|
||||
to collect a royalty for further conveying from those to whom you convey
|
||||
the Program, the only way you could satisfy both those terms and this
|
||||
License would be to refrain entirely from conveying the Program.
|
||||
|
||||
13. Use with the GNU Affero General Public License.
|
||||
|
||||
Notwithstanding any other provision of this License, you have
|
||||
permission to link or combine any covered work with a work licensed
|
||||
under version 3 of the GNU Affero General Public License into a single
|
||||
combined work, and to convey the resulting work. The terms of this
|
||||
License will continue to apply to the part which is the covered work,
|
||||
but the special requirements of the GNU Affero General Public License,
|
||||
section 13, concerning interaction through a network will apply to the
|
||||
combination as such.
|
||||
|
||||
14. Revised Versions of this License.
|
||||
|
||||
The Free Software Foundation may publish revised and/or new versions of
|
||||
the GNU General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the
|
||||
Program specifies that a certain numbered version of the GNU General
|
||||
Public License "or any later version" applies to it, you have the
|
||||
option of following the terms and conditions either of that numbered
|
||||
version or of any later version published by the Free Software
|
||||
Foundation. If the Program does not specify a version number of the
|
||||
GNU General Public License, you may choose any version ever published
|
||||
by the Free Software Foundation.
|
||||
|
||||
If the Program specifies that a proxy can decide which future
|
||||
versions of the GNU General Public License can be used, that proxy's
|
||||
public statement of acceptance of a version permanently authorizes you
|
||||
to choose that version for the Program.
|
||||
|
||||
Later license versions may give you additional or different
|
||||
permissions. However, no additional obligations are imposed on any
|
||||
author or copyright holder as a result of your choosing to follow a
|
||||
later version.
|
||||
|
||||
15. Disclaimer of Warranty.
|
||||
|
||||
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. Limitation of Liability.
|
||||
|
||||
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||
SUCH DAMAGES.
|
||||
|
||||
17. Interpretation of Sections 15 and 16.
|
||||
|
||||
If the disclaimer of warranty and limitation of liability provided
|
||||
above cannot be given local legal effect according to their terms,
|
||||
reviewing courts shall apply local law that most closely approximates
|
||||
an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
state the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program does terminal interaction, make it output a short
|
||||
notice like this when it starts in an interactive mode:
|
||||
|
||||
<program> Copyright (C) <year> <name of author>
|
||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, your program's commands
|
||||
might be different; for a GUI interface, you would use an "about box".
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU GPL, see
|
||||
<https://www.gnu.org/licenses/>.
|
||||
|
||||
The GNU General Public License does not permit incorporating your program
|
||||
into proprietary programs. If your program is a subroutine library, you
|
||||
may consider it more useful to permit linking proprietary applications with
|
||||
the library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License. But first, please read
|
||||
<https://www.gnu.org/licenses/why-not-lgpl.html>.
|
||||
@@ -1,130 +0,0 @@
|
||||
# **ProtoPirate**
|
||||
|
||||
### _for Flipper Zero_
|
||||
|
||||
## **⚠️ Warning: Important Security & Project Update**
|
||||
Read message by following link below:
|
||||
|
||||
https://protopirate.net/ProtoPirate
|
||||
|
||||
Main repo is located at: https://protopirate.net/ProtoPirate/ProtoPirate
|
||||
|
||||
All others are read only mirrors!
|
||||
|
||||
|
||||
ProtoPirate is an experimental rolling-code analysis toolkit developed by members of **The Pirates' Plunder**.
|
||||
|
||||
The app currently supports decoding for multiple automotive key-fob families (Kia, Ford, Subaru, Suzuki, VW, and more), with the goal of being a drop-in Flipper app (.fap) that is free, open source, and can be used on any Flipper Zero firmware.
|
||||
|
||||
App is intended for educational and security purposes only, and has no signal transmission enabled by default. This prevents users from accidentally desyncing their keyfobs, making it safe for non-specialists.
|
||||
|
||||
## **Supported Protocols**
|
||||
|
||||
Protocols are split into **AM** and **FM** registries. The active registry is chosen from the receiver selected preset.
|
||||
|
||||
### **AM protocols**
|
||||
|
||||
|
||||
| Protocol | Decoder | Encoder | Signal Encoding | Modulation | Encryption | CRC | Frequency |
|
||||
| ------------------------ | ------- | ------- | --------------- | ---------- | ------------------------------ | ------------ | --------------- |
|
||||
| Chrysler V0 | ✅ | ✅ | PWM | AM650 | Rolling Code | Checksum | 315.00 / 433.92 |
|
||||
| Fiat V0 | ✅ | ✅ | Manchester | AM650 | Rolling Code (static emu only) | ❌ | 315.00 / 433.92 |
|
||||
| Fiat V1 | ✅ | ❌ | Manchester | AM650 | Rolling Code | CRC8 | 315.00 / 433.92 |
|
||||
| Ford V0 | ✅ | ✅ | Manchester | AM650 | Rolling Code | ✅ + Checksum | 315.00 / 433.92 |
|
||||
| Honda V1 | ✅ | ✅ | Manchester | AM650 | Rolling Code | CRC4 | 315.00 / 433.92 |
|
||||
| Kia V1 | ✅ | ✅ | Manchester | AM650 | Rolling Code | CRC4 | 315.00 / 433.92 |
|
||||
| Porsche Touareg | ✅ | ❌ | PWM | AM650 | Rolling Code | ❌ | 315.00 / 433.92 |
|
||||
| PSA (Peugeot/Citroen) | ✅ | ✅ | Manchester | AM650 | XTEA/XOR | CRC8 | 315.00 / 433.92 |
|
||||
| StarLine | ✅ | ✅ | PWM | AM650 | KeeLoq | ❌ | 315.00 / 433.92 |
|
||||
| Subaru | ✅ | ✅ | PPM | AM650 | Rolling Code | ❌ | 315.00 / 433.92 |
|
||||
| VAG (VW/Audi/Seat/Skoda) | ✅ | ✅ | Manchester | AM650 | AUT64/XTEA | ❌ | 434.42 |
|
||||
|
||||
|
||||
### **FM protocols**
|
||||
|
||||
|
||||
| Protocol | Decoder | Encoder | Signal Encoding | Modulation | Encryption | CRC | Frequency |
|
||||
| ----------------------------- | ------- | ------- | --------------- | ---------- | ---------------------------- | ---------- | --------------- |
|
||||
| Ford V1 | ✅ | ✅ | Manchester | F4 | Rolling Code | CRC16 | 315.00 / 433.92 |
|
||||
| Ford V2 | ✅ | ✅ | Manchester | F4 | Rolling Code (simple replay) | ❌ | 434.25 |
|
||||
| Ford V3 | ✅ | ❌ | Manchester | F4 | Rolling Code | ❌ | 434.25 |
|
||||
| Honda Static | ✅ | ✅ | PWM | Honda1 | Static Code | Checksum | 315.00 / 433.92 |
|
||||
| Kia V0 / Suzuki V0 / Honda V0 | ✅ | ✅ | PWM | FM476 | Rolling Code | CRC8 | 315.00 / 433.92 |
|
||||
| Kia V2 | ✅ | ✅ | Manchester | FM476 | Rolling Code | CRC4 | 315.00 / 433.92 |
|
||||
| Kia V3 / V4 | ✅ | ✅ | PWM | FM476 | KeeLoq | CRC4 (BF) | 315.00 / 433.92 |
|
||||
| Kia V5 | ✅ | ✅ | PWM | FM476 | Rolling Code | ✅ | 315.00 / 433.92 |
|
||||
| Kia V6 | ✅ | ✅ | Manchester | FM476 | AES128 | CRC8 | 315.00 / 433.92 |
|
||||
| Kia V7 | ✅ | ✅ | Manchester | FM476 | Rolling Code | CRC8 | 315.00 / 433.92 |
|
||||
| Land Rover V0 | ✅ | ✅ | PWM | F4 | Rolling Code | Check+Tail | 315.00 / 433.92 |
|
||||
| Mazda V0 | ✅ | ✅ | Manchester | FM (F2?) | Rolling Code | Checksum | 315.00 / 433.92 |
|
||||
| Mitsubishi V0 | ✅ | ❌ | PWM | FM476 | Rolling Code | ❌ | 315.00 / 433.92 |
|
||||
| PSA (Peugeot/Citroen) | ✅ | ✅ | Manchester | FM (F3?) | XTEA/XOR | CRC8 | 315.00 / 433.92 |
|
||||
| Scher-Khan | ✅ | ❌ | PWM | FM | Magic Code | ❌ | 315.00 / 433.92 |
|
||||
|
||||
|
||||
*More Coming Soon*
|
||||
|
||||
## **Features**
|
||||
|
||||
### 📡 Protocol Receiver
|
||||
|
||||
Real-time signal capture and decoding with animated radar display. Supports frequency hopping.
|
||||
|
||||
### 📂 Sub Decode
|
||||
|
||||
Load and analyze existing `.sub` files from your SD card. Browse `/ext/subghz/` to decode previously captured signals.
|
||||
|
||||
### ⏱️ Timing Tuner
|
||||
|
||||
Tool for protocol developers to compare real fob signal timing against protocol definitions.
|
||||
|
||||
- **Protocol Definition**: Expected short/long pulse durations and tolerance
|
||||
- **Received Signal**: Measured timing from real fob (avg, min, max, sample count)
|
||||
- **Analysis**: Difference from expected, jitter measurements
|
||||
- **Conclusion**: Whether timing matches or needs adjustment with specific recommendations
|
||||
|
||||
## **Credits**
|
||||
|
||||
The following contributors are recognized for helping us keep open sourced projects and the freeware community alive.
|
||||
|
||||
### **App Development**
|
||||
|
||||
- RocketGod
|
||||
- MMX
|
||||
- Leeroy
|
||||
- gullradriel
|
||||
- Skorp - Thanks, I sneaked a lot from Weather App!
|
||||
- Vadim's Radio Driver
|
||||
|
||||
### **Protocol Magic**
|
||||
|
||||
- L0rdDiakon
|
||||
- YougZ
|
||||
- RocketGod
|
||||
- MMX
|
||||
- DoobTheGoober
|
||||
- Skorp
|
||||
- Slackware
|
||||
- Trikk
|
||||
- Wootini
|
||||
- Li0ard
|
||||
- Leeroy
|
||||
- Ash
|
||||
|
||||
### **Reverse Engineering Support**
|
||||
|
||||
- DoobTheGoober
|
||||
- MMX
|
||||
- NeedNotApply
|
||||
- RocketGod
|
||||
- Slackware
|
||||
- Trikk
|
||||
- Li0ard
|
||||
|
||||
## **Community & Support**
|
||||
|
||||
Join **The Pirates' Plunder** on Discord for development updates, testing, protocol research, community support, and a bunch of badasses doing fun shit:
|
||||
|
||||
➡️ **[https://discord.gg/thepirates](https://discord.gg/thepirates)**
|
||||
|
||||
<img alt="rocketgod_logo_transparent" src="https://github.com/user-attachments/assets/ad15b106-152c-4a60-a9e2-4d40dfa8f3c6" />
|
||||
@@ -3,42 +3,42 @@ App(
|
||||
name="Garage Door Remote",
|
||||
apptype=FlipperAppType.EXTERNAL,
|
||||
targets=["f7"],
|
||||
entry_point="protopirate_app",
|
||||
entry_point="gdr_app",
|
||||
requires=["gui"],
|
||||
stack_size=4 * 1024,
|
||||
stack_size=8 * 1024,
|
||||
fap_description="Capture and emulate garage and gate remote signals from Sub-GHz",
|
||||
fap_version="2.6",
|
||||
fap_icon="images/protopirate_10px.png",
|
||||
fap_icon="images/gdr_10x10.png",
|
||||
fap_category="Sub-GHz",
|
||||
fap_icon_assets="images",
|
||||
fap_file_assets="keystore",
|
||||
sources=[
|
||||
"protopirate_app.c",
|
||||
"protopirate_app_i.c",
|
||||
"protopirate_history.c",
|
||||
"helpers/protopirate_psa_bf_host.c",
|
||||
"helpers/protopirate_settings.c",
|
||||
"helpers/protopirate_storage.c",
|
||||
"gdr_app.c",
|
||||
"gdr_app_i.c",
|
||||
"gdr_history.c",
|
||||
"helpers/gdr_psa_bf_host.c",
|
||||
"helpers/gdr_settings.c",
|
||||
"helpers/gdr_storage.c",
|
||||
"helpers/radio_device_loader.c",
|
||||
"helpers/raw_file_reader.c",
|
||||
"scenes/protopirate_scene.c",
|
||||
"scenes/protopirate_scene_about.c",
|
||||
"scenes/protopirate_scene_dual_receiver.c",
|
||||
"scenes/protopirate_scene_dual_receiver_config.c",
|
||||
"scenes/protopirate_scene_emulate.c",
|
||||
"scenes/protopirate_scene_need_saving.c",
|
||||
"scenes/protopirate_scene_receiver.c",
|
||||
"scenes/protopirate_scene_receiver_config.c",
|
||||
"scenes/protopirate_scene_receiver_info.c",
|
||||
"scenes/protopirate_scene_saved.c",
|
||||
"scenes/protopirate_scene_saved_info.c",
|
||||
"scenes/protopirate_scene_shield_receiver.c",
|
||||
"scenes/protopirate_scene_shield_receiver_config.c",
|
||||
"scenes/protopirate_scene_start.c",
|
||||
"scenes/protopirate_scene_sub_decode.c",
|
||||
"scenes/protopirate_scene_timing_tuner.c",
|
||||
"views/protopirate_dual_receiver.c",
|
||||
"views/protopirate_receiver.c",
|
||||
"scenes/gdr_scene.c",
|
||||
"scenes/gdr_scene_about.c",
|
||||
"scenes/gdr_scene_dual_receiver.c",
|
||||
"scenes/gdr_scene_dual_receiver_config.c",
|
||||
"scenes/gdr_scene_emulate.c",
|
||||
"scenes/gdr_scene_need_saving.c",
|
||||
"scenes/gdr_scene_receiver.c",
|
||||
"scenes/gdr_scene_receiver_config.c",
|
||||
"scenes/gdr_scene_receiver_info.c",
|
||||
"scenes/gdr_scene_saved.c",
|
||||
"scenes/gdr_scene_saved_info.c",
|
||||
"scenes/gdr_scene_shield_receiver.c",
|
||||
"scenes/gdr_scene_shield_receiver_config.c",
|
||||
"scenes/gdr_scene_start.c",
|
||||
"scenes/gdr_scene_sub_decode.c",
|
||||
"scenes/gdr_scene_timing_tuner.c",
|
||||
"views/gdr_dual_receiver.c",
|
||||
"views/gdr_receiver.c",
|
||||
"protocols/protocol_items.c",
|
||||
"protocols/protocols_common.c",
|
||||
"protocols/keys.c",
|
||||
@@ -46,12 +46,12 @@ App(
|
||||
)
|
||||
|
||||
App(
|
||||
appid="protopirate_am_plugin",
|
||||
appid="gdr_am_plugin",
|
||||
apptype=FlipperAppType.PLUGIN,
|
||||
entry_point="protopirate_am_plugin_ep",
|
||||
entry_point="gdr_am_plugin_ep",
|
||||
requires=["garage_door_remote"],
|
||||
sources=[
|
||||
"protocols/plugins/protopirate_am_plugin.c",
|
||||
"protocols/plugins/gdr_am_plugin.c",
|
||||
"protocols/protocols_common.c",
|
||||
"protocols/keys.c",
|
||||
"protocols/alutech_at_4n.c",
|
||||
@@ -79,12 +79,12 @@ App(
|
||||
)
|
||||
|
||||
App(
|
||||
appid="protopirate_fm_plugin",
|
||||
appid="gdr_fm_plugin",
|
||||
apptype=FlipperAppType.PLUGIN,
|
||||
entry_point="protopirate_fm_plugin_ep",
|
||||
entry_point="gdr_fm_plugin_ep",
|
||||
requires=["garage_door_remote"],
|
||||
sources=[
|
||||
"protocols/plugins/protopirate_fm_plugin.c",
|
||||
"protocols/plugins/gdr_fm_plugin.c",
|
||||
"protocols/protocols_common.c",
|
||||
"protocols/keys.c",
|
||||
"protocols/ansonic.c",
|
||||
@@ -93,38 +93,12 @@ App(
|
||||
)
|
||||
|
||||
App(
|
||||
appid="protopirate_emulate_plugin",
|
||||
appid="gdr_emulate_plugin",
|
||||
apptype=FlipperAppType.PLUGIN,
|
||||
entry_point="protopirate_emulate_plugin_ep",
|
||||
entry_point="gdr_emulate_plugin_ep",
|
||||
requires=["garage_door_remote"],
|
||||
sources=[
|
||||
"scenes/plugins/protopirate_emulate_plugin.c",
|
||||
],
|
||||
fal_embedded=True,
|
||||
)
|
||||
|
||||
|
||||
App(
|
||||
appid="protopirate_fm_plugin",
|
||||
apptype=FlipperAppType.PLUGIN,
|
||||
entry_point="protopirate_fm_plugin_ep",
|
||||
requires=["garage_door_remote"],
|
||||
sources=[
|
||||
"protocols/plugins/protopirate_fm_plugin.c",
|
||||
"protocols/protocols_common.c",
|
||||
"protocols/keys.c",
|
||||
"protocols/ansonic.c",
|
||||
],
|
||||
fal_embedded=True,
|
||||
)
|
||||
|
||||
App(
|
||||
appid="protopirate_emulate_plugin",
|
||||
apptype=FlipperAppType.PLUGIN,
|
||||
entry_point="protopirate_emulate_plugin_ep",
|
||||
requires=["garage_door_remote"],
|
||||
sources=[
|
||||
"scenes/plugins/protopirate_emulate_plugin.c",
|
||||
"scenes/plugins/gdr_emulate_plugin.c",
|
||||
],
|
||||
fal_embedded=True,
|
||||
)
|
||||
|
||||
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+130
-130
@@ -1,20 +1,20 @@
|
||||
// protopirate_app.c
|
||||
#include "protopirate_app_i.h"
|
||||
// gdr_app.c
|
||||
#include "gdr_app_i.h"
|
||||
|
||||
#include <furi.h>
|
||||
#include <furi_hal.h>
|
||||
#include "protocols/protocol_items.h"
|
||||
#include "protocols/protocols_common.h"
|
||||
#include "helpers/protopirate_settings.h"
|
||||
#include "helpers/protopirate_storage.h"
|
||||
#include "helpers/protopirate_psa_bf_host.h"
|
||||
#include "helpers/gdr_settings.h"
|
||||
#include "helpers/gdr_storage.h"
|
||||
#include "helpers/gdr_psa_bf_host.h"
|
||||
#include "protocols/keys.h"
|
||||
#include <string.h>
|
||||
|
||||
#define TAG "ProtoPirateApp"
|
||||
#define TAG "GDRApp"
|
||||
|
||||
#if defined(ENABLE_DUAL_RX_SCENE) || defined(ENABLE_SHIELD_RX_SCENE)
|
||||
static bool protopirate_setting_has_frequency(SubGhzSetting* setting, uint32_t frequency) {
|
||||
static bool gdr_setting_has_frequency(SubGhzSetting* setting, uint32_t frequency) {
|
||||
size_t count = subghz_setting_get_frequency_count(setting);
|
||||
for(size_t i = 0; i < count; i++) {
|
||||
if(subghz_setting_get_frequency(setting, i) == frequency) {
|
||||
@@ -26,27 +26,27 @@ static bool protopirate_setting_has_frequency(SubGhzSetting* setting, uint32_t f
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_DUAL_RX_SCENE
|
||||
static ProtoPirateProtocolRegistryFilter protopirate_setting_preset_filter(
|
||||
static GDRProtocolRegistryFilter gdr_setting_preset_filter(
|
||||
SubGhzSetting* setting,
|
||||
uint8_t index) {
|
||||
return protopirate_get_protocol_registry_filter_for_preset(
|
||||
return gdr_get_protocol_registry_filter_for_preset(
|
||||
subghz_setting_get_preset_data(setting, index),
|
||||
subghz_setting_get_preset_data_size(setting, index));
|
||||
}
|
||||
|
||||
static uint8_t protopirate_find_preset_by_name_or_filter(
|
||||
static uint8_t gdr_find_preset_by_name_or_filter(
|
||||
SubGhzSetting* setting,
|
||||
const char* preferred_name,
|
||||
ProtoPirateProtocolRegistryFilter filter) {
|
||||
GDRProtocolRegistryFilter filter) {
|
||||
size_t count = subghz_setting_get_preset_count(setting);
|
||||
for(size_t i = 0; i < count; i++) {
|
||||
if(strcmp(subghz_setting_get_preset_name(setting, i), preferred_name) == 0 &&
|
||||
protopirate_setting_preset_filter(setting, (uint8_t)i) == filter) {
|
||||
gdr_setting_preset_filter(setting, (uint8_t)i) == filter) {
|
||||
return (uint8_t)i;
|
||||
}
|
||||
}
|
||||
for(size_t i = 0; i < count; i++) {
|
||||
if(protopirate_setting_preset_filter(setting, (uint8_t)i) == filter) {
|
||||
if(gdr_setting_preset_filter(setting, (uint8_t)i) == filter) {
|
||||
return (uint8_t)i;
|
||||
}
|
||||
}
|
||||
@@ -54,7 +54,7 @@ static uint8_t protopirate_find_preset_by_name_or_filter(
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
protopirate_find_preset_by_name(SubGhzSetting* setting, const char* preset_name) {
|
||||
gdr_find_preset_by_name(SubGhzSetting* setting, const char* preset_name) {
|
||||
if(!preset_name || preset_name[0] == '\0') {
|
||||
return UINT8_MAX;
|
||||
}
|
||||
@@ -69,25 +69,25 @@ static uint8_t
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool protopirate_app_custom_event_callback(void* context, uint32_t event) {
|
||||
static bool gdr_app_custom_event_callback(void* context, uint32_t event) {
|
||||
furi_check(context);
|
||||
ProtoPirateApp* app = context;
|
||||
GDRApp* app = context;
|
||||
return scene_manager_handle_custom_event(app->scene_manager, event);
|
||||
}
|
||||
|
||||
static bool protopirate_app_back_event_callback(void* context) {
|
||||
static bool gdr_app_back_event_callback(void* context) {
|
||||
furi_check(context);
|
||||
ProtoPirateApp* app = context;
|
||||
GDRApp* app = context;
|
||||
return scene_manager_handle_back_event(app->scene_manager);
|
||||
}
|
||||
|
||||
static void protopirate_app_tick_event_callback(void* context) {
|
||||
static void gdr_app_tick_event_callback(void* context) {
|
||||
furi_check(context);
|
||||
ProtoPirateApp* app = context;
|
||||
GDRApp* app = context;
|
||||
scene_manager_handle_tick_event(app->scene_manager);
|
||||
}
|
||||
|
||||
bool protopirate_ensure_variable_item_list(ProtoPirateApp* app) {
|
||||
bool gdr_ensure_variable_item_list(GDRApp* app) {
|
||||
furi_check(app);
|
||||
if(app->variable_item_list) {
|
||||
return true;
|
||||
@@ -100,12 +100,12 @@ bool protopirate_ensure_variable_item_list(ProtoPirateApp* app) {
|
||||
|
||||
view_dispatcher_add_view(
|
||||
app->view_dispatcher,
|
||||
ProtoPirateViewVariableItemList,
|
||||
GDRViewVariableItemList,
|
||||
variable_item_list_get_view(app->variable_item_list));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool protopirate_ensure_widget(ProtoPirateApp* app) {
|
||||
bool gdr_ensure_widget(GDRApp* app) {
|
||||
furi_check(app);
|
||||
if(app->widget) {
|
||||
return true;
|
||||
@@ -117,11 +117,11 @@ bool protopirate_ensure_widget(ProtoPirateApp* app) {
|
||||
}
|
||||
|
||||
view_dispatcher_add_view(
|
||||
app->view_dispatcher, ProtoPirateViewWidget, widget_get_view(app->widget));
|
||||
app->view_dispatcher, GDRViewWidget, widget_get_view(app->widget));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool protopirate_ensure_text_input(ProtoPirateApp* app) {
|
||||
bool gdr_ensure_text_input(GDRApp* app) {
|
||||
furi_check(app);
|
||||
if(app->text_input) {
|
||||
return true;
|
||||
@@ -133,11 +133,11 @@ bool protopirate_ensure_text_input(ProtoPirateApp* app) {
|
||||
}
|
||||
|
||||
view_dispatcher_add_view(
|
||||
app->view_dispatcher, ProtoPirateViewTextInput, text_input_get_view(app->text_input));
|
||||
app->view_dispatcher, GDRViewTextInput, text_input_get_view(app->text_input));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool protopirate_ensure_view_about(ProtoPirateApp* app) {
|
||||
bool gdr_ensure_view_about(GDRApp* app) {
|
||||
furi_check(app);
|
||||
if(app->view_about) {
|
||||
return true;
|
||||
@@ -148,49 +148,49 @@ bool protopirate_ensure_view_about(ProtoPirateApp* app) {
|
||||
return false;
|
||||
}
|
||||
|
||||
view_dispatcher_add_view(app->view_dispatcher, ProtoPirateViewAbout, app->view_about);
|
||||
view_dispatcher_add_view(app->view_dispatcher, GDRViewAbout, app->view_about);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool protopirate_ensure_receiver_view(ProtoPirateApp* app) {
|
||||
bool gdr_ensure_receiver_view(GDRApp* app) {
|
||||
furi_check(app);
|
||||
if(app->protopirate_receiver) {
|
||||
if(app->gdr_receiver) {
|
||||
return true;
|
||||
}
|
||||
|
||||
app->protopirate_receiver = protopirate_view_receiver_alloc(app->auto_save);
|
||||
if(!app->protopirate_receiver) {
|
||||
app->gdr_receiver = gdr_view_receiver_alloc(app->auto_save);
|
||||
if(!app->gdr_receiver) {
|
||||
return false;
|
||||
}
|
||||
|
||||
view_dispatcher_add_view(
|
||||
app->view_dispatcher,
|
||||
ProtoPirateViewReceiver,
|
||||
protopirate_view_receiver_get_view(app->protopirate_receiver));
|
||||
GDRViewReceiver,
|
||||
gdr_view_receiver_get_view(app->gdr_receiver));
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_DUAL_RX_SCENE
|
||||
bool protopirate_ensure_dual_receiver_view(ProtoPirateApp* app) {
|
||||
bool gdr_ensure_dual_receiver_view(GDRApp* app) {
|
||||
furi_check(app);
|
||||
if(app->dual_receiver) {
|
||||
return true;
|
||||
}
|
||||
|
||||
app->dual_receiver = protopirate_view_dual_receiver_alloc();
|
||||
app->dual_receiver = gdr_view_dual_receiver_alloc();
|
||||
if(!app->dual_receiver) {
|
||||
return false;
|
||||
}
|
||||
|
||||
view_dispatcher_add_view(
|
||||
app->view_dispatcher,
|
||||
ProtoPirateViewDualReceiver,
|
||||
protopirate_view_dual_receiver_get_view(app->dual_receiver));
|
||||
GDRViewDualReceiver,
|
||||
gdr_view_dual_receiver_get_view(app->dual_receiver));
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void protopirate_radio_init_cleanup(ProtoPirateApp* app, bool devices_initialized) {
|
||||
static void gdr_radio_init_cleanup(GDRApp* app, bool devices_initialized) {
|
||||
furi_check(app);
|
||||
furi_check(app->txrx);
|
||||
|
||||
@@ -228,21 +228,21 @@ static void protopirate_radio_init_cleanup(ProtoPirateApp* app, bool devices_ini
|
||||
|
||||
app->txrx->protocol_registry = NULL;
|
||||
app->txrx->protocol_plugin = NULL;
|
||||
app->txrx->protocol_registry_filter = ProtoPirateProtocolRegistryFilterAM;
|
||||
app->txrx->txrx_state = ProtoPirateTxRxStateIDLE;
|
||||
app->txrx->protocol_registry_filter = GDRProtocolRegistryFilterAM;
|
||||
app->txrx->txrx_state = GDRTxRxStateIDLE;
|
||||
app->radio_initialized = false;
|
||||
}
|
||||
|
||||
ProtoPirateApp* protopirate_app_alloc() {
|
||||
protopirate_storage_purge_temp_history_at_startup();
|
||||
ProtoPirateApp* app = malloc(sizeof(ProtoPirateApp));
|
||||
GDRApp* gdr_app_alloc() {
|
||||
gdr_storage_purge_temp_history_at_startup();
|
||||
GDRApp* app = malloc(sizeof(GDRApp));
|
||||
if(!app) {
|
||||
FURI_LOG_E(TAG, "Failed to allocate ProtoPirateApp app !");
|
||||
FURI_LOG_E(TAG, "Failed to allocate GDRApp app !");
|
||||
return NULL;
|
||||
}
|
||||
memset(app, 0, sizeof(ProtoPirateApp));
|
||||
memset(app, 0, sizeof(GDRApp));
|
||||
|
||||
FURI_LOG_I(TAG, "Allocating ProtoPirate Decoder App");
|
||||
FURI_LOG_I(TAG, "Allocating GDR Decoder App");
|
||||
|
||||
// GUI
|
||||
app->gui = furi_record_open(RECORD_GUI);
|
||||
@@ -252,15 +252,15 @@ ProtoPirateApp* protopirate_app_alloc() {
|
||||
#if defined(FW_ORIGIN_RM)
|
||||
view_dispatcher_enable_queue(app->view_dispatcher);
|
||||
#endif
|
||||
app->scene_manager = scene_manager_alloc(&protopirate_scene_handlers, app);
|
||||
app->scene_manager = scene_manager_alloc(&gdr_scene_handlers, app);
|
||||
|
||||
view_dispatcher_set_event_callback_context(app->view_dispatcher, app);
|
||||
view_dispatcher_set_custom_event_callback(
|
||||
app->view_dispatcher, protopirate_app_custom_event_callback);
|
||||
app->view_dispatcher, gdr_app_custom_event_callback);
|
||||
view_dispatcher_set_navigation_event_callback(
|
||||
app->view_dispatcher, protopirate_app_back_event_callback);
|
||||
app->view_dispatcher, gdr_app_back_event_callback);
|
||||
view_dispatcher_set_tick_event_callback(
|
||||
app->view_dispatcher, protopirate_app_tick_event_callback, 100);
|
||||
app->view_dispatcher, gdr_app_tick_event_callback, 100);
|
||||
|
||||
view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen);
|
||||
|
||||
@@ -273,7 +273,7 @@ ProtoPirateApp* protopirate_app_alloc() {
|
||||
// SubMenu
|
||||
app->submenu = submenu_alloc();
|
||||
view_dispatcher_add_view(
|
||||
app->view_dispatcher, ProtoPirateViewSubmenu, submenu_get_view(app->submenu));
|
||||
app->view_dispatcher, GDRViewSubmenu, submenu_get_view(app->submenu));
|
||||
|
||||
app->save_protocol = NULL;
|
||||
app->save_from_saved_info = false;
|
||||
@@ -283,11 +283,11 @@ ProtoPirateApp* protopirate_app_alloc() {
|
||||
|
||||
// File Browser path
|
||||
app->file_path = furi_string_alloc();
|
||||
furi_string_set(app->file_path, PROTOPIRATE_APP_FOLDER);
|
||||
furi_string_set(app->file_path, GDR_APP_FOLDER);
|
||||
|
||||
// Load saved settings
|
||||
ProtoPirateSettings settings;
|
||||
protopirate_settings_load(&settings);
|
||||
GDRSettings settings;
|
||||
gdr_settings_load(&settings);
|
||||
|
||||
// Apply auto-save setting
|
||||
app->auto_save = settings.auto_save;
|
||||
@@ -327,18 +327,18 @@ ProtoPirateApp* protopirate_app_alloc() {
|
||||
}
|
||||
|
||||
// Initialize TxRx structure with minimal setup
|
||||
app->lock = ProtoPirateLockOff;
|
||||
app->txrx = malloc(sizeof(ProtoPirateTxRx));
|
||||
app->lock = GDRLockOff;
|
||||
app->txrx = malloc(sizeof(GDRTxRx));
|
||||
furi_check(app->txrx);
|
||||
memset(app->txrx, 0, sizeof(ProtoPirateTxRx));
|
||||
memset(app->txrx, 0, sizeof(GDRTxRx));
|
||||
|
||||
app->txrx->preset = malloc(sizeof(SubGhzRadioPreset));
|
||||
furi_check(app->txrx->preset);
|
||||
app->txrx->preset->name = furi_string_alloc();
|
||||
furi_check(app->txrx->preset->name);
|
||||
app->txrx->txrx_state = ProtoPirateTxRxStateIDLE;
|
||||
app->txrx->rx_key_state = ProtoPirateRxKeyStateIDLE;
|
||||
app->txrx->protocol_registry_filter = ProtoPirateProtocolRegistryFilterAM;
|
||||
app->txrx->txrx_state = GDRTxRxStateIDLE;
|
||||
app->txrx->rx_key_state = GDRRxKeyStateIDLE;
|
||||
app->txrx->protocol_registry_filter = GDRProtocolRegistryFilterAM;
|
||||
|
||||
// Get preset name and data
|
||||
const char* preset_name = subghz_setting_get_preset_name(app->setting, preset_index);
|
||||
@@ -353,22 +353,22 @@ ProtoPirateApp* protopirate_app_alloc() {
|
||||
settings.auto_save,
|
||||
settings.hopping_enabled);
|
||||
|
||||
protopirate_preset_init(app, preset_name, frequency, preset_data, preset_data_size);
|
||||
gdr_preset_init(app, preset_name, frequency, preset_data, preset_data_size);
|
||||
|
||||
#ifdef ENABLE_DUAL_RX_SCENE
|
||||
|
||||
uint32_t default_frequency = subghz_setting_get_default_frequency(app->setting);
|
||||
app->dual_freq_a = protopirate_setting_has_frequency(app->setting, settings.dual_freq_a) ?
|
||||
app->dual_freq_a = gdr_setting_has_frequency(app->setting, settings.dual_freq_a) ?
|
||||
settings.dual_freq_a :
|
||||
default_frequency;
|
||||
app->dual_freq_b = protopirate_setting_has_frequency(app->setting, settings.dual_freq_b) ?
|
||||
app->dual_freq_b = gdr_setting_has_frequency(app->setting, settings.dual_freq_b) ?
|
||||
settings.dual_freq_b :
|
||||
default_frequency;
|
||||
uint8_t preset_count = (uint8_t)subghz_setting_get_preset_count(app->setting);
|
||||
uint8_t named_preset_a =
|
||||
protopirate_find_preset_by_name(app->setting, settings.dual_preset_name_a);
|
||||
gdr_find_preset_by_name(app->setting, settings.dual_preset_name_a);
|
||||
uint8_t named_preset_b =
|
||||
protopirate_find_preset_by_name(app->setting, settings.dual_preset_name_b);
|
||||
gdr_find_preset_by_name(app->setting, settings.dual_preset_name_b);
|
||||
app->dual_preset_a =
|
||||
named_preset_a != UINT8_MAX ? named_preset_a : settings.dual_preset_a;
|
||||
app->dual_preset_b =
|
||||
@@ -377,15 +377,15 @@ ProtoPirateApp* protopirate_app_alloc() {
|
||||
app->dual_preset_a = UINT8_MAX;
|
||||
app->dual_preset_b = UINT8_MAX;
|
||||
} else if(app->dual_preset_a >= preset_count) {
|
||||
app->dual_preset_a = protopirate_find_preset_by_name_or_filter(
|
||||
app->setting, "AM650", ProtoPirateProtocolRegistryFilterAM);
|
||||
app->dual_preset_a = gdr_find_preset_by_name_or_filter(
|
||||
app->setting, "AM650", GDRProtocolRegistryFilterAM);
|
||||
if(app->dual_preset_a == UINT8_MAX) {
|
||||
app->dual_preset_a = 0;
|
||||
}
|
||||
}
|
||||
if(app->dual_preset_b >= preset_count) {
|
||||
app->dual_preset_b = protopirate_find_preset_by_name_or_filter(
|
||||
app->setting, "FM476", ProtoPirateProtocolRegistryFilterFM);
|
||||
app->dual_preset_b = gdr_find_preset_by_name_or_filter(
|
||||
app->setting, "FM476", GDRProtocolRegistryFilterFM);
|
||||
if(app->dual_preset_b == UINT8_MAX) {
|
||||
app->dual_preset_b = 0;
|
||||
}
|
||||
@@ -395,7 +395,7 @@ ProtoPirateApp* protopirate_app_alloc() {
|
||||
#ifdef ENABLE_SHIELD_RX_SCENE
|
||||
{
|
||||
uint32_t default_frequency = subghz_setting_get_default_frequency(app->setting);
|
||||
app->shield_freq = protopirate_setting_has_frequency(app->setting, settings.shield_freq) ?
|
||||
app->shield_freq = gdr_setting_has_frequency(app->setting, settings.shield_freq) ?
|
||||
settings.shield_freq :
|
||||
default_frequency;
|
||||
app->shield_preset_index = settings.shield_preset_index;
|
||||
@@ -414,8 +414,8 @@ ProtoPirateApp* protopirate_app_alloc() {
|
||||
#endif
|
||||
|
||||
// Apply hopping state from settings
|
||||
app->txrx->hopper_state = settings.hopping_enabled ? ProtoPirateHopperStateRunning :
|
||||
ProtoPirateHopperStateOFF;
|
||||
app->txrx->hopper_state = settings.hopping_enabled ? GDRHopperStateRunning :
|
||||
GDRHopperStateOFF;
|
||||
app->txrx->hopper_idx_frequency = 0;
|
||||
app->txrx->hopper_timeout = 0;
|
||||
app->txrx->idx_menu_chosen = 0;
|
||||
@@ -425,11 +425,11 @@ ProtoPirateApp* protopirate_app_alloc() {
|
||||
return app;
|
||||
}
|
||||
|
||||
bool protopirate_radio_init(ProtoPirateApp* app) {
|
||||
bool gdr_radio_init(GDRApp* app) {
|
||||
furi_check(app);
|
||||
furi_check(app->txrx);
|
||||
|
||||
FURI_LOG_I(TAG, "=== protopirate_radio_init called ===");
|
||||
FURI_LOG_I(TAG, "=== gdr_radio_init called ===");
|
||||
FURI_LOG_D(TAG, "State: radio_initialized=%d", app->radio_initialized);
|
||||
|
||||
if(app->radio_initialized) {
|
||||
@@ -445,7 +445,7 @@ bool protopirate_radio_init(ProtoPirateApp* app) {
|
||||
"Radio marked initialized but resources missing (env=%p device=%p), repairing",
|
||||
app->txrx->environment,
|
||||
app->txrx->radio_device);
|
||||
protopirate_radio_deinit(app);
|
||||
gdr_radio_deinit(app);
|
||||
}
|
||||
|
||||
// Fresh radio init - nothing was initialized before
|
||||
@@ -455,24 +455,24 @@ bool protopirate_radio_init(ProtoPirateApp* app) {
|
||||
app->txrx->environment = subghz_environment_alloc();
|
||||
if(!app->txrx->environment) {
|
||||
FURI_LOG_E(TAG, "Failed to allocate environment!");
|
||||
protopirate_radio_init_cleanup(app, false);
|
||||
gdr_radio_init_cleanup(app, false);
|
||||
return false;
|
||||
}
|
||||
|
||||
app->txrx->protocol_registry = NULL;
|
||||
|
||||
if(!protopirate_refresh_protocol_registry(app, false)) {
|
||||
if(!gdr_refresh_protocol_registry(app, false)) {
|
||||
FURI_LOG_E(TAG, "Failed to configure protocol registry");
|
||||
protopirate_radio_init_cleanup(app, false);
|
||||
gdr_radio_init_cleanup(app, false);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Load keystores
|
||||
subghz_environment_load_keystore(app->txrx->environment, PROTOPIRATE_KEYSTORE_DIR_NAME);
|
||||
subghz_environment_load_keystore(app->txrx->environment, GDR_KEYSTORE_DIR_NAME);
|
||||
|
||||
// Load ProtoPirate specific keys
|
||||
protopirate_keys_load(app->txrx->environment);
|
||||
FURI_LOG_I(TAG, "Loaded ProtoPirate secure keys");
|
||||
// Load GDR specific keys
|
||||
gdr_keys_load(app->txrx->environment);
|
||||
FURI_LOG_I(TAG, "Loaded GDR secure keys");
|
||||
|
||||
// Initialize SubGhz devices
|
||||
subghz_devices_init();
|
||||
@@ -489,7 +489,7 @@ bool protopirate_radio_init(ProtoPirateApp* app) {
|
||||
|
||||
if(!app->txrx->radio_device) {
|
||||
FURI_LOG_E(TAG, "Failed to initialize any radio device!");
|
||||
protopirate_radio_init_cleanup(app, true);
|
||||
gdr_radio_init_cleanup(app, true);
|
||||
return false;
|
||||
}
|
||||
#ifndef REMOVE_LOGS
|
||||
@@ -512,8 +512,8 @@ bool protopirate_radio_init(ProtoPirateApp* app) {
|
||||
}
|
||||
|
||||
// Deinitialize radio subsystem
|
||||
void protopirate_radio_deinit(ProtoPirateApp* app) {
|
||||
FURI_LOG_I(TAG, "=== protopirate_radio_deinit called ===");
|
||||
void gdr_radio_deinit(GDRApp* app) {
|
||||
FURI_LOG_I(TAG, "=== gdr_radio_deinit called ===");
|
||||
FURI_LOG_D(TAG, "State: radio_initialized=%d", app->radio_initialized);
|
||||
FURI_LOG_D(
|
||||
TAG,
|
||||
@@ -535,7 +535,7 @@ void protopirate_radio_deinit(ProtoPirateApp* app) {
|
||||
bool devices_initialized = app->radio_initialized || (app->txrx->radio_device != NULL);
|
||||
|
||||
// Make sure we're not receiving
|
||||
if(app->txrx->worker && app->txrx->txrx_state == ProtoPirateTxRxStateRx) {
|
||||
if(app->txrx->worker && app->txrx->txrx_state == GDRTxRxStateRx) {
|
||||
FURI_LOG_D(TAG, "Stopping active RX, state=%d", app->txrx->txrx_state);
|
||||
subghz_worker_stop(app->txrx->worker);
|
||||
if(app->txrx->radio_device) {
|
||||
@@ -590,9 +590,9 @@ void protopirate_radio_deinit(ProtoPirateApp* app) {
|
||||
if(app->txrx->history) {
|
||||
FURI_LOG_D(TAG, "Freeing history %p", app->txrx->history);
|
||||
if(app->selected_capture.history == app->txrx->history) {
|
||||
protopirate_selected_capture_clear(app);
|
||||
gdr_selected_capture_clear(app);
|
||||
}
|
||||
protopirate_history_free(app->txrx->history);
|
||||
gdr_history_free(app->txrx->history);
|
||||
app->txrx->history = NULL;
|
||||
} else {
|
||||
FURI_LOG_D(TAG, "History was NULL, skipping free");
|
||||
@@ -606,25 +606,25 @@ void protopirate_radio_deinit(ProtoPirateApp* app) {
|
||||
FURI_LOG_D(TAG, "Worker was NULL, skipping free");
|
||||
}
|
||||
|
||||
app->txrx->txrx_state = ProtoPirateTxRxStateIDLE;
|
||||
app->txrx->txrx_state = GDRTxRxStateIDLE;
|
||||
app->radio_initialized = false;
|
||||
|
||||
FURI_LOG_D(TAG, "Final state: radio_initialized=%d", app->radio_initialized);
|
||||
}
|
||||
|
||||
void protopirate_app_free(ProtoPirateApp* app) {
|
||||
void gdr_app_free(GDRApp* app) {
|
||||
furi_check(app);
|
||||
|
||||
FURI_LOG_I(TAG, "=== protopirate_app_free called ===");
|
||||
FURI_LOG_I(TAG, "=== gdr_app_free called ===");
|
||||
FURI_LOG_D(TAG, "State: radio_initialized=%d", app->radio_initialized);
|
||||
|
||||
// Save settings before exiting
|
||||
ProtoPirateSettings settings;
|
||||
protopirate_settings_load(&settings);
|
||||
GDRSettings settings;
|
||||
gdr_settings_load(&settings);
|
||||
settings.frequency = app->txrx->preset->frequency;
|
||||
settings.auto_save = app->auto_save;
|
||||
settings.tx_power = app->tx_power;
|
||||
settings.hopping_enabled = (app->txrx->hopper_state != ProtoPirateHopperStateOFF);
|
||||
settings.hopping_enabled = (app->txrx->hopper_state != GDRHopperStateOFF);
|
||||
settings.emulate_feature_enabled = app->emulate_feature_enabled;
|
||||
#ifdef ENABLE_DUAL_RX_SCENE
|
||||
settings.dual_freq_a = app->dual_freq_a;
|
||||
@@ -675,11 +675,11 @@ void protopirate_app_free(ProtoPirateApp* app) {
|
||||
settings.hopping_enabled,
|
||||
settings.emulate_feature_enabled);
|
||||
|
||||
protopirate_settings_save(&settings);
|
||||
gdr_settings_save(&settings);
|
||||
|
||||
// Deinitialize whichever is active - NULL checks inside handle all cases
|
||||
FURI_LOG_D(TAG, "Calling radio_deinit");
|
||||
protopirate_radio_deinit(app);
|
||||
gdr_radio_deinit(app);
|
||||
|
||||
if(app->loaded_file_path) {
|
||||
FURI_LOG_D(TAG, "Freeing loaded_file_path");
|
||||
@@ -690,21 +690,21 @@ void protopirate_app_free(ProtoPirateApp* app) {
|
||||
// Submenu
|
||||
if(app->submenu) {
|
||||
FURI_LOG_D(TAG, "Removing submenu view");
|
||||
view_dispatcher_remove_view(app->view_dispatcher, ProtoPirateViewSubmenu);
|
||||
view_dispatcher_remove_view(app->view_dispatcher, GDRViewSubmenu);
|
||||
submenu_free(app->submenu);
|
||||
}
|
||||
|
||||
// Variable Item List
|
||||
if(app->variable_item_list) {
|
||||
FURI_LOG_D(TAG, "Removing variable_item_list view");
|
||||
view_dispatcher_remove_view(app->view_dispatcher, ProtoPirateViewVariableItemList);
|
||||
view_dispatcher_remove_view(app->view_dispatcher, GDRViewVariableItemList);
|
||||
variable_item_list_free(app->variable_item_list);
|
||||
}
|
||||
|
||||
// About View
|
||||
if(app->view_about) {
|
||||
FURI_LOG_D(TAG, "Removing about view");
|
||||
view_dispatcher_remove_view(app->view_dispatcher, ProtoPirateViewAbout);
|
||||
view_dispatcher_remove_view(app->view_dispatcher, GDRViewAbout);
|
||||
view_free(app->view_about);
|
||||
}
|
||||
|
||||
@@ -717,14 +717,14 @@ void protopirate_app_free(ProtoPirateApp* app) {
|
||||
// Widget
|
||||
if(app->widget) {
|
||||
FURI_LOG_D(TAG, "Removing widget view");
|
||||
view_dispatcher_remove_view(app->view_dispatcher, ProtoPirateViewWidget);
|
||||
view_dispatcher_remove_view(app->view_dispatcher, GDRViewWidget);
|
||||
widget_free(app->widget);
|
||||
}
|
||||
|
||||
// Text Input
|
||||
if(app->text_input) {
|
||||
FURI_LOG_D(TAG, "Removing text_input view");
|
||||
view_dispatcher_remove_view(app->view_dispatcher, ProtoPirateViewTextInput);
|
||||
view_dispatcher_remove_view(app->view_dispatcher, GDRViewTextInput);
|
||||
text_input_free(app->text_input);
|
||||
}
|
||||
if(app->save_protocol) {
|
||||
@@ -733,21 +733,21 @@ void protopirate_app_free(ProtoPirateApp* app) {
|
||||
}
|
||||
|
||||
// Receiver
|
||||
if(app->protopirate_receiver) {
|
||||
if(app->gdr_receiver) {
|
||||
FURI_LOG_D(TAG, "Removing receiver view");
|
||||
view_dispatcher_remove_view(app->view_dispatcher, ProtoPirateViewReceiver);
|
||||
protopirate_view_receiver_free(app->protopirate_receiver);
|
||||
view_dispatcher_remove_view(app->view_dispatcher, GDRViewReceiver);
|
||||
gdr_view_receiver_free(app->gdr_receiver);
|
||||
}
|
||||
|
||||
#ifdef ENABLE_DUAL_RX_SCENE
|
||||
|
||||
bool dual_devices_initialized = app->dual_chain_a || app->dual_chain_b;
|
||||
if(app->dual_chain_a) {
|
||||
protopirate_rx_chain_free(app->dual_chain_a);
|
||||
gdr_rx_chain_free(app->dual_chain_a);
|
||||
app->dual_chain_a = NULL;
|
||||
}
|
||||
if(app->dual_chain_b) {
|
||||
protopirate_rx_chain_free(app->dual_chain_b);
|
||||
gdr_rx_chain_free(app->dual_chain_b);
|
||||
app->dual_chain_b = NULL;
|
||||
}
|
||||
if(dual_devices_initialized) {
|
||||
@@ -755,15 +755,15 @@ void protopirate_app_free(ProtoPirateApp* app) {
|
||||
}
|
||||
if(app->dual_receiver) {
|
||||
FURI_LOG_D(TAG, "Removing dual receiver view");
|
||||
view_dispatcher_remove_view(app->view_dispatcher, ProtoPirateViewDualReceiver);
|
||||
protopirate_view_dual_receiver_free(app->dual_receiver);
|
||||
view_dispatcher_remove_view(app->view_dispatcher, GDRViewDualReceiver);
|
||||
gdr_view_dual_receiver_free(app->dual_receiver);
|
||||
app->dual_receiver = NULL;
|
||||
}
|
||||
if(app->dual_history) {
|
||||
if(app->selected_capture.history == app->dual_history) {
|
||||
protopirate_selected_capture_clear(app);
|
||||
gdr_selected_capture_clear(app);
|
||||
}
|
||||
protopirate_history_free(app->dual_history);
|
||||
gdr_history_free(app->dual_history);
|
||||
app->dual_history = NULL;
|
||||
}
|
||||
if(app->dual_history_mutex) {
|
||||
@@ -775,11 +775,11 @@ void protopirate_app_free(ProtoPirateApp* app) {
|
||||
#ifdef ENABLE_SHIELD_RX_SCENE
|
||||
bool shield_devices_initialized = app->shield_rx_chain || app->shield_tx_chain;
|
||||
if(app->shield_rx_chain) {
|
||||
protopirate_rx_chain_free(app->shield_rx_chain);
|
||||
gdr_rx_chain_free(app->shield_rx_chain);
|
||||
app->shield_rx_chain = NULL;
|
||||
}
|
||||
if(app->shield_tx_chain) {
|
||||
protopirate_tx_chain_free(app->shield_tx_chain);
|
||||
gdr_tx_chain_free(app->shield_tx_chain);
|
||||
app->shield_tx_chain = NULL;
|
||||
}
|
||||
if(shield_devices_initialized) {
|
||||
@@ -787,9 +787,9 @@ void protopirate_app_free(ProtoPirateApp* app) {
|
||||
}
|
||||
if(app->shield_history) {
|
||||
if(app->selected_capture.history == app->shield_history) {
|
||||
protopirate_selected_capture_clear(app);
|
||||
gdr_selected_capture_clear(app);
|
||||
}
|
||||
protopirate_history_free(app->shield_history);
|
||||
gdr_history_free(app->shield_history);
|
||||
app->shield_history = NULL;
|
||||
}
|
||||
if(app->shield_history_mutex) {
|
||||
@@ -798,7 +798,7 @@ void protopirate_app_free(ProtoPirateApp* app) {
|
||||
}
|
||||
#endif
|
||||
|
||||
protopirate_psa_bf_context_release(app);
|
||||
gdr_psa_bf_context_release(app);
|
||||
|
||||
// Setting
|
||||
FURI_LOG_D(TAG, "Freeing subghz_setting");
|
||||
@@ -812,7 +812,7 @@ void protopirate_app_free(ProtoPirateApp* app) {
|
||||
free(app->txrx);
|
||||
|
||||
#ifdef ENABLE_EMULATE_FEATURE
|
||||
protopirate_emulate_context_release(app);
|
||||
gdr_emulate_context_release(app);
|
||||
#endif
|
||||
|
||||
pp_shared_upload_release();
|
||||
@@ -840,38 +840,38 @@ void protopirate_app_free(ProtoPirateApp* app) {
|
||||
free(app);
|
||||
}
|
||||
|
||||
int32_t protopirate_app(char* p) {
|
||||
int32_t gdr_app(char* p) {
|
||||
furi_hal_power_suppress_charge_enter();
|
||||
|
||||
ProtoPirateApp* protopirate_app = protopirate_app_alloc();
|
||||
if(!protopirate_app) {
|
||||
// logging is already done in protopirate_app_alloc()
|
||||
GDRApp* gdr_app = gdr_app_alloc();
|
||||
if(!gdr_app) {
|
||||
// logging is already done in gdr_app_alloc()
|
||||
furi_hal_power_suppress_charge_exit();
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Handle Command line PSF that may have been passed to us
|
||||
bool load_saved = (p && strlen(p));
|
||||
if(load_saved) protopirate_app->loaded_file_path = furi_string_alloc_set(p);
|
||||
if(load_saved) gdr_app->loaded_file_path = furi_string_alloc_set(p);
|
||||
scene_manager_next_scene(
|
||||
protopirate_app->scene_manager,
|
||||
(load_saved) ? ProtoPirateSceneSavedInfo : ProtoPirateSceneStart);
|
||||
gdr_app->scene_manager,
|
||||
(load_saved) ? GDRSceneSavedInfo : GDRSceneStart);
|
||||
|
||||
//We now jump straight to emulate scene from Browser. If the user wanted the key to look at, just click back.
|
||||
if(load_saved) {
|
||||
if(protopirate_app->emulate_feature_enabled) {
|
||||
if(gdr_app->emulate_feature_enabled) {
|
||||
view_dispatcher_send_custom_event(
|
||||
protopirate_app->view_dispatcher, ProtoPirateCustomEventSavedInfoEmulate);
|
||||
notification_message(protopirate_app->notifications, &sequence_success);
|
||||
gdr_app->view_dispatcher, GDRCustomEventSavedInfoEmulate);
|
||||
notification_message(gdr_app->notifications, &sequence_success);
|
||||
} else {
|
||||
view_dispatcher_send_custom_event(
|
||||
protopirate_app->view_dispatcher, ProtoPirateCustomEventReceiverInfoSave);
|
||||
gdr_app->view_dispatcher, GDRCustomEventReceiverInfoSave);
|
||||
}
|
||||
}
|
||||
|
||||
view_dispatcher_run(protopirate_app->view_dispatcher);
|
||||
view_dispatcher_run(gdr_app->view_dispatcher);
|
||||
|
||||
protopirate_app_free(protopirate_app);
|
||||
gdr_app_free(gdr_app);
|
||||
|
||||
furi_hal_power_suppress_charge_exit();
|
||||
|
||||
+114
-114
@@ -1,17 +1,17 @@
|
||||
// protopirate_app_i.c
|
||||
#include "protopirate_app_i.h"
|
||||
// gdr_app_i.c
|
||||
#include "gdr_app_i.h"
|
||||
#include "protocols/protocol_items.h"
|
||||
#include <loader/firmware_api/firmware_api.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define TAG "ProtoPirateTxRx"
|
||||
#define TAG "GDRTxRx"
|
||||
|
||||
void protopirate_selected_capture_set(
|
||||
ProtoPirateApp* app,
|
||||
ProtoPirateHistory* history,
|
||||
void gdr_selected_capture_set(
|
||||
GDRApp* app,
|
||||
GDRHistory* history,
|
||||
FuriMutex* mutex,
|
||||
uint16_t index,
|
||||
ProtoPirateCaptureOwner owner) {
|
||||
GDRCaptureOwner owner) {
|
||||
furi_check(app);
|
||||
app->selected_capture.history = history;
|
||||
app->selected_capture.mutex = mutex;
|
||||
@@ -19,75 +19,75 @@ void protopirate_selected_capture_set(
|
||||
app->selected_capture.owner = owner;
|
||||
}
|
||||
|
||||
void protopirate_selected_capture_clear(ProtoPirateApp* app) {
|
||||
void gdr_selected_capture_clear(GDRApp* app) {
|
||||
furi_check(app);
|
||||
memset(&app->selected_capture, 0, sizeof(app->selected_capture));
|
||||
}
|
||||
|
||||
bool protopirate_selected_capture_is_valid(ProtoPirateApp* app) {
|
||||
bool gdr_selected_capture_is_valid(GDRApp* app) {
|
||||
furi_check(app);
|
||||
ProtoPirateSelectedCapture* selected = &app->selected_capture;
|
||||
if(!selected->history || selected->owner == ProtoPirateCaptureOwnerNone) {
|
||||
GDRSelectedCapture* selected = &app->selected_capture;
|
||||
if(!selected->history || selected->owner == GDRCaptureOwnerNone) {
|
||||
return false;
|
||||
}
|
||||
if(selected->mutex) {
|
||||
furi_mutex_acquire(selected->mutex, FuriWaitForever);
|
||||
}
|
||||
bool valid = selected->index < protopirate_history_get_item(selected->history);
|
||||
bool valid = selected->index < gdr_history_get_item(selected->history);
|
||||
if(selected->mutex) {
|
||||
furi_mutex_release(selected->mutex);
|
||||
}
|
||||
return valid;
|
||||
}
|
||||
|
||||
ProtoPirateHistory* protopirate_selected_capture_get_history(ProtoPirateApp* app) {
|
||||
return protopirate_selected_capture_is_valid(app) ? app->selected_capture.history : NULL;
|
||||
GDRHistory* gdr_selected_capture_get_history(GDRApp* app) {
|
||||
return gdr_selected_capture_is_valid(app) ? app->selected_capture.history : NULL;
|
||||
}
|
||||
|
||||
uint16_t protopirate_selected_capture_get_index(ProtoPirateApp* app) {
|
||||
uint16_t gdr_selected_capture_get_index(GDRApp* app) {
|
||||
furi_check(app);
|
||||
return app->selected_capture.index;
|
||||
}
|
||||
|
||||
ProtoPirateHistorySource protopirate_selected_capture_get_source(ProtoPirateApp* app) {
|
||||
ProtoPirateHistory* history = protopirate_selected_capture_get_history(app);
|
||||
GDRHistorySource gdr_selected_capture_get_source(GDRApp* app) {
|
||||
GDRHistory* history = gdr_selected_capture_get_history(app);
|
||||
if(!history) {
|
||||
return ProtoPirateHistorySourceUnknown;
|
||||
return GDRHistorySourceUnknown;
|
||||
}
|
||||
return protopirate_history_get_source(history, app->selected_capture.index);
|
||||
return gdr_history_get_source(history, app->selected_capture.index);
|
||||
}
|
||||
|
||||
FlipperFormat* protopirate_selected_capture_get_raw_data(ProtoPirateApp* app) {
|
||||
ProtoPirateHistory* history = protopirate_selected_capture_get_history(app);
|
||||
FlipperFormat* gdr_selected_capture_get_raw_data(GDRApp* app) {
|
||||
GDRHistory* history = gdr_selected_capture_get_history(app);
|
||||
if(!history) {
|
||||
return NULL;
|
||||
}
|
||||
return protopirate_history_get_raw_data(history, app->selected_capture.index);
|
||||
return gdr_history_get_raw_data(history, app->selected_capture.index);
|
||||
}
|
||||
|
||||
bool protopirate_selected_capture_get_path(ProtoPirateApp* app, FuriString* out_path) {
|
||||
bool gdr_selected_capture_get_path(GDRApp* app, FuriString* out_path) {
|
||||
furi_check(out_path);
|
||||
ProtoPirateHistory* history = protopirate_selected_capture_get_history(app);
|
||||
GDRHistory* history = gdr_selected_capture_get_history(app);
|
||||
if(!history) {
|
||||
return false;
|
||||
}
|
||||
return protopirate_history_get_capture_path(history, app->selected_capture.index, out_path);
|
||||
return gdr_history_get_capture_path(history, app->selected_capture.index, out_path);
|
||||
}
|
||||
|
||||
void protopirate_selected_capture_release_scratch(ProtoPirateApp* app) {
|
||||
void gdr_selected_capture_release_scratch(GDRApp* app) {
|
||||
furi_check(app);
|
||||
if(app->selected_capture.history) {
|
||||
protopirate_history_release_scratch(app->selected_capture.history);
|
||||
gdr_history_release_scratch(app->selected_capture.history);
|
||||
}
|
||||
}
|
||||
|
||||
static const char* protopirate_get_registry_plugin_path(ProtoPirateProtocolRegistryFilter filter) {
|
||||
return (filter == ProtoPirateProtocolRegistryFilterFM) ?
|
||||
APP_ASSETS_PATH("plugins/protopirate_fm_plugin.fal") :
|
||||
APP_ASSETS_PATH("plugins/protopirate_am_plugin.fal");
|
||||
static const char* gdr_get_registry_plugin_path(GDRProtocolRegistryFilter filter) {
|
||||
return (filter == GDRProtocolRegistryFilterFM) ?
|
||||
APP_ASSETS_PATH("plugins/gdr_fm_plugin.fal") :
|
||||
APP_ASSETS_PATH("plugins/gdr_am_plugin.fal");
|
||||
}
|
||||
|
||||
static void protopirate_unload_protocol_plugin(ProtoPirateTxRx* txrx) {
|
||||
static void gdr_unload_protocol_plugin(GDRTxRx* txrx) {
|
||||
furi_check(txrx);
|
||||
|
||||
txrx->protocol_plugin = NULL;
|
||||
@@ -104,12 +104,12 @@ static void protopirate_unload_protocol_plugin(ProtoPirateTxRx* txrx) {
|
||||
}
|
||||
}
|
||||
|
||||
static void protopirate_teardown_receiver_stack_for_registry_switch(ProtoPirateApp* app) {
|
||||
static void gdr_teardown_receiver_stack_for_registry_switch(GDRApp* app) {
|
||||
furi_check(app);
|
||||
furi_check(app->txrx);
|
||||
|
||||
if(app->txrx->txrx_state == ProtoPirateTxRxStateRx) {
|
||||
protopirate_rx_end(app);
|
||||
if(app->txrx->txrx_state == GDRTxRxStateRx) {
|
||||
gdr_rx_end(app);
|
||||
}
|
||||
|
||||
if(app->txrx->receiver) {
|
||||
@@ -126,15 +126,15 @@ static void protopirate_teardown_receiver_stack_for_registry_switch(ProtoPirateA
|
||||
app->txrx->worker = NULL;
|
||||
}
|
||||
|
||||
if(app->txrx->radio_device && app->txrx->txrx_state != ProtoPirateTxRxStateTx) {
|
||||
if(app->txrx->radio_device && app->txrx->txrx_state != GDRTxRxStateTx) {
|
||||
subghz_devices_idle(app->txrx->radio_device);
|
||||
app->txrx->txrx_state = ProtoPirateTxRxStateIDLE;
|
||||
app->txrx->txrx_state = GDRTxRxStateIDLE;
|
||||
}
|
||||
}
|
||||
|
||||
static bool protopirate_ensure_protocol_registry_plugin(
|
||||
ProtoPirateApp* app,
|
||||
ProtoPirateProtocolRegistryFilter filter,
|
||||
static bool gdr_ensure_protocol_registry_plugin(
|
||||
GDRApp* app,
|
||||
GDRProtocolRegistryFilter filter,
|
||||
const SubGhzProtocolRegistry** registry) {
|
||||
furi_check(app);
|
||||
furi_check(app->txrx);
|
||||
@@ -155,7 +155,7 @@ static bool protopirate_ensure_protocol_registry_plugin(
|
||||
|
||||
if(app->txrx->protocol_plugin || app->txrx->protocol_plugin_manager ||
|
||||
app->txrx->plugin_resolver) {
|
||||
protopirate_unload_protocol_plugin(app->txrx);
|
||||
gdr_unload_protocol_plugin(app->txrx);
|
||||
}
|
||||
|
||||
CompositeApiResolver* resolver = composite_api_resolver_alloc();
|
||||
@@ -166,8 +166,8 @@ static bool protopirate_ensure_protocol_registry_plugin(
|
||||
composite_api_resolver_add(resolver, firmware_api_interface);
|
||||
|
||||
PluginManager* manager = plugin_manager_alloc(
|
||||
PROTOPIRATE_PROTOCOL_PLUGIN_APP_ID,
|
||||
PROTOPIRATE_PROTOCOL_PLUGIN_API_VERSION,
|
||||
GDR_PROTOCOL_PLUGIN_APP_ID,
|
||||
GDR_PROTOCOL_PLUGIN_API_VERSION,
|
||||
composite_api_resolver_get(resolver));
|
||||
if(!manager) {
|
||||
FURI_LOG_E(TAG, "Failed to allocate protocol plugin manager");
|
||||
@@ -175,7 +175,7 @@ static bool protopirate_ensure_protocol_registry_plugin(
|
||||
return false;
|
||||
}
|
||||
|
||||
const char* plugin_path = protopirate_get_registry_plugin_path(filter);
|
||||
const char* plugin_path = gdr_get_registry_plugin_path(filter);
|
||||
PluginManagerError error = plugin_manager_load_single(manager, plugin_path);
|
||||
if(error != PluginManagerErrorNone) {
|
||||
FURI_LOG_E(TAG, "Failed to load protocol plugin %s: %d", plugin_path, (int)error);
|
||||
@@ -184,7 +184,7 @@ static bool protopirate_ensure_protocol_registry_plugin(
|
||||
return false;
|
||||
}
|
||||
|
||||
const ProtoPirateProtocolPlugin* plugin = plugin_manager_get_ep(manager, 0U);
|
||||
const GDRProtocolPlugin* plugin = plugin_manager_get_ep(manager, 0U);
|
||||
if(!plugin || !plugin->registry) {
|
||||
FURI_LOG_E(TAG, "Protocol plugin entry point is invalid");
|
||||
plugin_manager_free(manager);
|
||||
@@ -208,7 +208,7 @@ static bool protopirate_ensure_protocol_registry_plugin(
|
||||
return true;
|
||||
}
|
||||
|
||||
bool protopirate_refresh_protocol_registry(ProtoPirateApp* app, bool ensure_receiver_ready) {
|
||||
bool gdr_refresh_protocol_registry(GDRApp* app, bool ensure_receiver_ready) {
|
||||
furi_check(app);
|
||||
furi_check(app->txrx);
|
||||
|
||||
@@ -216,23 +216,23 @@ bool protopirate_refresh_protocol_registry(ProtoPirateApp* app, bool ensure_rece
|
||||
return true;
|
||||
}
|
||||
|
||||
ProtoPirateProtocolRegistryFilter filter = protopirate_get_protocol_registry_filter_for_preset(
|
||||
GDRProtocolRegistryFilter filter = gdr_get_protocol_registry_filter_for_preset(
|
||||
app->txrx->preset->data, app->txrx->preset->data_size);
|
||||
bool filter_changed = !app->txrx->protocol_plugin ||
|
||||
(app->txrx->protocol_registry_filter != filter);
|
||||
|
||||
if(filter_changed) {
|
||||
protopirate_teardown_receiver_stack_for_registry_switch(app);
|
||||
gdr_teardown_receiver_stack_for_registry_switch(app);
|
||||
} else if(ensure_receiver_ready && !app->txrx->receiver) {
|
||||
protopirate_teardown_receiver_stack_for_registry_switch(app);
|
||||
gdr_teardown_receiver_stack_for_registry_switch(app);
|
||||
}
|
||||
|
||||
const SubGhzProtocolRegistry* registry = NULL;
|
||||
if(!protopirate_ensure_protocol_registry_plugin(app, filter, ®istry) || !registry) {
|
||||
if(!gdr_ensure_protocol_registry_plugin(app, filter, ®istry) || !registry) {
|
||||
FURI_LOG_E(
|
||||
TAG,
|
||||
"Failed to resolve %s protocol registry plugin",
|
||||
protopirate_get_protocol_registry_filter_name(filter));
|
||||
gdr_get_protocol_registry_filter_name(filter));
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -241,7 +241,7 @@ bool protopirate_refresh_protocol_registry(ProtoPirateApp* app, bool ensure_rece
|
||||
FURI_LOG_I(
|
||||
TAG,
|
||||
"Using %s protocol registry (%zu protocols)",
|
||||
protopirate_get_protocol_registry_filter_name(filter),
|
||||
gdr_get_protocol_registry_filter_name(filter),
|
||||
registry->size);
|
||||
subghz_environment_set_protocol_registry(app->txrx->environment, registry);
|
||||
app->txrx->protocol_registry = registry;
|
||||
@@ -260,7 +260,7 @@ bool protopirate_refresh_protocol_registry(ProtoPirateApp* app, bool ensure_rece
|
||||
FURI_LOG_E(
|
||||
TAG,
|
||||
"Failed to allocate receiver for %s registry",
|
||||
protopirate_get_protocol_registry_filter_name(filter));
|
||||
gdr_get_protocol_registry_filter_name(filter));
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -268,8 +268,8 @@ bool protopirate_refresh_protocol_registry(ProtoPirateApp* app, bool ensure_rece
|
||||
return true;
|
||||
}
|
||||
|
||||
bool protopirate_apply_protocol_registry_for_preset_data(
|
||||
ProtoPirateApp* app,
|
||||
bool gdr_apply_protocol_registry_for_preset_data(
|
||||
GDRApp* app,
|
||||
const uint8_t* preset_data,
|
||||
size_t preset_data_size) {
|
||||
furi_check(app);
|
||||
@@ -279,22 +279,22 @@ bool protopirate_apply_protocol_registry_for_preset_data(
|
||||
return false;
|
||||
}
|
||||
|
||||
ProtoPirateProtocolRegistryFilter filter =
|
||||
protopirate_get_protocol_registry_filter_for_preset(preset_data, preset_data_size);
|
||||
GDRProtocolRegistryFilter filter =
|
||||
gdr_get_protocol_registry_filter_for_preset(preset_data, preset_data_size);
|
||||
|
||||
bool filter_changed = !app->txrx->protocol_plugin ||
|
||||
(app->txrx->protocol_registry_filter != filter);
|
||||
|
||||
if(filter_changed) {
|
||||
protopirate_teardown_receiver_stack_for_registry_switch(app);
|
||||
gdr_teardown_receiver_stack_for_registry_switch(app);
|
||||
}
|
||||
|
||||
const SubGhzProtocolRegistry* registry = NULL;
|
||||
if(!protopirate_ensure_protocol_registry_plugin(app, filter, ®istry) || !registry) {
|
||||
if(!gdr_ensure_protocol_registry_plugin(app, filter, ®istry) || !registry) {
|
||||
FURI_LOG_E(
|
||||
TAG,
|
||||
"Failed to resolve %s registry plugin for preset apply",
|
||||
protopirate_get_protocol_registry_filter_name(filter));
|
||||
gdr_get_protocol_registry_filter_name(filter));
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -305,29 +305,29 @@ bool protopirate_apply_protocol_registry_for_preset_data(
|
||||
FURI_LOG_I(
|
||||
TAG,
|
||||
"Switching active protocol registry to %s (%zu protocols)",
|
||||
protopirate_get_protocol_registry_filter_name(filter),
|
||||
gdr_get_protocol_registry_filter_name(filter),
|
||||
registry->size);
|
||||
subghz_environment_set_protocol_registry(app->txrx->environment, registry);
|
||||
app->txrx->protocol_registry = registry;
|
||||
return true;
|
||||
}
|
||||
|
||||
void protopirate_preset_init(
|
||||
void gdr_preset_init(
|
||||
void* context,
|
||||
const char* preset_name,
|
||||
uint32_t frequency,
|
||||
uint8_t* preset_data,
|
||||
size_t preset_data_size) {
|
||||
furi_check(context);
|
||||
ProtoPirateApp* app = context;
|
||||
GDRApp* app = context;
|
||||
furi_string_set(app->txrx->preset->name, preset_name);
|
||||
app->txrx->preset->frequency = frequency;
|
||||
app->txrx->preset->data = preset_data;
|
||||
app->txrx->preset->data_size = preset_data_size;
|
||||
}
|
||||
|
||||
void protopirate_get_frequency_modulation_str(
|
||||
ProtoPirateApp* app,
|
||||
void gdr_get_frequency_modulation_str(
|
||||
GDRApp* app,
|
||||
char* frequency,
|
||||
size_t frequency_size,
|
||||
char* modulation,
|
||||
@@ -346,15 +346,15 @@ void protopirate_get_frequency_modulation_str(
|
||||
}
|
||||
}
|
||||
|
||||
void protopirate_get_frequency_modulation(
|
||||
ProtoPirateApp* app,
|
||||
void gdr_get_frequency_modulation(
|
||||
GDRApp* app,
|
||||
FuriString* frequency,
|
||||
FuriString* modulation) {
|
||||
furi_check(app);
|
||||
|
||||
char frequency_buf[16] = {0};
|
||||
char modulation_buf[8] = {0};
|
||||
protopirate_get_frequency_modulation_str(
|
||||
gdr_get_frequency_modulation_str(
|
||||
app, frequency_buf, sizeof(frequency_buf), modulation_buf, sizeof(modulation_buf));
|
||||
|
||||
if(frequency != NULL) {
|
||||
@@ -365,20 +365,20 @@ void protopirate_get_frequency_modulation(
|
||||
}
|
||||
}
|
||||
|
||||
void protopirate_begin(ProtoPirateApp* app, uint8_t* preset_data) {
|
||||
void gdr_begin(GDRApp* app, uint8_t* preset_data) {
|
||||
furi_check(app);
|
||||
if(!app->txrx->radio_device) {
|
||||
FURI_LOG_W(TAG, "begin requested without radio device");
|
||||
app->txrx->txrx_state = ProtoPirateTxRxStateIDLE;
|
||||
app->txrx->txrx_state = GDRTxRxStateIDLE;
|
||||
return;
|
||||
}
|
||||
subghz_devices_reset(app->txrx->radio_device);
|
||||
subghz_devices_idle(app->txrx->radio_device);
|
||||
subghz_devices_load_preset(app->txrx->radio_device, FuriHalSubGhzPresetCustom, preset_data);
|
||||
app->txrx->txrx_state = ProtoPirateTxRxStateIDLE;
|
||||
app->txrx->txrx_state = GDRTxRxStateIDLE;
|
||||
}
|
||||
|
||||
uint32_t protopirate_rx(ProtoPirateApp* app, uint32_t frequency) {
|
||||
uint32_t gdr_rx(GDRApp* app, uint32_t frequency) {
|
||||
furi_check(app);
|
||||
furi_check(app->txrx);
|
||||
if(!app->radio_initialized || !app->txrx->radio_device || !app->txrx->worker) {
|
||||
@@ -388,15 +388,15 @@ uint32_t protopirate_rx(ProtoPirateApp* app, uint32_t frequency) {
|
||||
app->radio_initialized,
|
||||
app->txrx->radio_device,
|
||||
app->txrx->worker);
|
||||
app->txrx->txrx_state = ProtoPirateTxRxStateIDLE;
|
||||
app->txrx->txrx_state = GDRTxRxStateIDLE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(!subghz_devices_is_frequency_valid(app->txrx->radio_device, frequency)) {
|
||||
furi_crash("ProtoPirate: Incorrect RX frequency.");
|
||||
furi_crash("GDR: Incorrect RX frequency.");
|
||||
}
|
||||
if(app->txrx->txrx_state == ProtoPirateTxRxStateRx ||
|
||||
app->txrx->txrx_state == ProtoPirateTxRxStateSleep) {
|
||||
if(app->txrx->txrx_state == GDRTxRxStateRx ||
|
||||
app->txrx->txrx_state == GDRTxRxStateSleep) {
|
||||
FURI_LOG_W(TAG, "RX start ignored in state %d", app->txrx->txrx_state);
|
||||
return app->txrx->preset ? app->txrx->preset->frequency : 0;
|
||||
}
|
||||
@@ -410,24 +410,24 @@ uint32_t protopirate_rx(ProtoPirateApp* app, uint32_t frequency) {
|
||||
app->txrx->radio_device, subghz_worker_rx_callback, app->txrx->worker);
|
||||
|
||||
subghz_worker_start(app->txrx->worker);
|
||||
app->txrx->txrx_state = ProtoPirateTxRxStateRx;
|
||||
app->txrx->txrx_state = GDRTxRxStateRx;
|
||||
return value;
|
||||
}
|
||||
|
||||
void protopirate_idle(ProtoPirateApp* app) {
|
||||
void gdr_idle(GDRApp* app) {
|
||||
furi_check(app);
|
||||
furi_check(app->txrx->txrx_state != ProtoPirateTxRxStateSleep);
|
||||
furi_check(app->txrx->txrx_state != GDRTxRxStateSleep);
|
||||
if(app->txrx->radio_device) {
|
||||
subghz_devices_idle(app->txrx->radio_device);
|
||||
} else {
|
||||
FURI_LOG_W(TAG, "idle requested without radio device");
|
||||
}
|
||||
app->txrx->txrx_state = ProtoPirateTxRxStateIDLE;
|
||||
app->txrx->txrx_state = GDRTxRxStateIDLE;
|
||||
}
|
||||
|
||||
void protopirate_rx_end(ProtoPirateApp* app) {
|
||||
void gdr_rx_end(GDRApp* app) {
|
||||
furi_check(app);
|
||||
if(!app->txrx || app->txrx->txrx_state != ProtoPirateTxRxStateRx) {
|
||||
if(!app->txrx || app->txrx->txrx_state != GDRTxRxStateRx) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -440,33 +440,33 @@ void protopirate_rx_end(ProtoPirateApp* app) {
|
||||
subghz_devices_idle(app->txrx->radio_device);
|
||||
}
|
||||
|
||||
app->txrx->txrx_state = ProtoPirateTxRxStateIDLE;
|
||||
app->txrx->txrx_state = GDRTxRxStateIDLE;
|
||||
}
|
||||
|
||||
void protopirate_sleep(ProtoPirateApp* app) {
|
||||
void gdr_sleep(GDRApp* app) {
|
||||
furi_check(app);
|
||||
subghz_devices_sleep(app->txrx->radio_device);
|
||||
app->txrx->txrx_state = ProtoPirateTxRxStateSleep;
|
||||
app->txrx->txrx_state = GDRTxRxStateSleep;
|
||||
}
|
||||
|
||||
void protopirate_release_shared_radio_state(ProtoPirateApp* app) {
|
||||
void gdr_release_shared_radio_state(GDRApp* app) {
|
||||
furi_check(app);
|
||||
furi_check(app->txrx);
|
||||
|
||||
if(app->protopirate_receiver) {
|
||||
protopirate_view_receiver_reset_menu(app->protopirate_receiver);
|
||||
if(app->gdr_receiver) {
|
||||
gdr_view_receiver_reset_menu(app->gdr_receiver);
|
||||
}
|
||||
|
||||
protopirate_radio_deinit(app);
|
||||
gdr_radio_deinit(app);
|
||||
}
|
||||
|
||||
void protopirate_rx_stack_suspend_for_tx(ProtoPirateApp* app) {
|
||||
void gdr_rx_stack_suspend_for_tx(GDRApp* app) {
|
||||
if(!app || !app->radio_initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(app->txrx->txrx_state == ProtoPirateTxRxStateRx) {
|
||||
protopirate_rx_end(app);
|
||||
if(app->txrx->txrx_state == GDRTxRxStateRx) {
|
||||
gdr_rx_end(app);
|
||||
}
|
||||
|
||||
if(app->txrx->worker && subghz_worker_is_running(app->txrx->worker)) {
|
||||
@@ -477,30 +477,30 @@ void protopirate_rx_stack_suspend_for_tx(ProtoPirateApp* app) {
|
||||
subghz_receiver_set_rx_callback(app->txrx->receiver, NULL, NULL);
|
||||
}
|
||||
|
||||
if(app->txrx->radio_device && app->txrx->txrx_state != ProtoPirateTxRxStateTx) {
|
||||
if(app->txrx->radio_device && app->txrx->txrx_state != GDRTxRxStateTx) {
|
||||
subghz_devices_idle(app->txrx->radio_device);
|
||||
app->txrx->txrx_state = ProtoPirateTxRxStateIDLE;
|
||||
app->txrx->txrx_state = GDRTxRxStateIDLE;
|
||||
}
|
||||
}
|
||||
|
||||
void protopirate_rx_stack_resume_after_tx(ProtoPirateApp* app) {
|
||||
void gdr_rx_stack_resume_after_tx(GDRApp* app) {
|
||||
if(!app || !app->radio_initialized || !app->txrx->environment) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(!protopirate_refresh_protocol_registry(app, true)) {
|
||||
if(!gdr_refresh_protocol_registry(app, true)) {
|
||||
FURI_LOG_E(TAG, "rx_stack_resume: failed to restore RX stack");
|
||||
}
|
||||
}
|
||||
|
||||
void protopirate_hopper_update(ProtoPirateApp* app) {
|
||||
void gdr_hopper_update(GDRApp* app) {
|
||||
furi_check(app);
|
||||
|
||||
switch(app->txrx->hopper_state) {
|
||||
case ProtoPirateHopperStateOFF:
|
||||
case ProtoPirateHopperStatePause:
|
||||
case GDRHopperStateOFF:
|
||||
case GDRHopperStatePause:
|
||||
return;
|
||||
case ProtoPirateHopperStateRSSITimeOut:
|
||||
case GDRHopperStateRSSITimeOut:
|
||||
if(app->txrx->hopper_timeout != 0) {
|
||||
app->txrx->hopper_timeout--;
|
||||
return;
|
||||
@@ -510,21 +510,21 @@ void protopirate_hopper_update(ProtoPirateApp* app) {
|
||||
break;
|
||||
}
|
||||
float rssi = -127.0f;
|
||||
if(app->txrx->hopper_state != ProtoPirateHopperStateRSSITimeOut) {
|
||||
if(app->txrx->hopper_state != GDRHopperStateRSSITimeOut) {
|
||||
rssi = subghz_devices_get_rssi(app->txrx->radio_device);
|
||||
|
||||
if(rssi > -90.0f) {
|
||||
app->txrx->hopper_timeout = 10;
|
||||
app->txrx->hopper_state = ProtoPirateHopperStateRSSITimeOut;
|
||||
app->txrx->hopper_state = GDRHopperStateRSSITimeOut;
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
app->txrx->hopper_state = ProtoPirateHopperStateRunning;
|
||||
app->txrx->hopper_state = GDRHopperStateRunning;
|
||||
}
|
||||
|
||||
const size_t hopper_count = subghz_setting_get_hopper_frequency_count(app->setting);
|
||||
if(hopper_count == 0) {
|
||||
app->txrx->hopper_state = ProtoPirateHopperStateOFF;
|
||||
app->txrx->hopper_state = GDRHopperStateOFF;
|
||||
app->txrx->hopper_idx_frequency = 0;
|
||||
return;
|
||||
}
|
||||
@@ -534,36 +534,36 @@ void protopirate_hopper_update(ProtoPirateApp* app) {
|
||||
app->txrx->hopper_idx_frequency = 0;
|
||||
}
|
||||
|
||||
if(app->txrx->txrx_state == ProtoPirateTxRxStateRx) {
|
||||
protopirate_rx_end(app);
|
||||
if(app->txrx->txrx_state == GDRTxRxStateRx) {
|
||||
gdr_rx_end(app);
|
||||
}
|
||||
if(app->txrx->txrx_state == ProtoPirateTxRxStateIDLE && app->txrx->receiver) {
|
||||
if(app->txrx->txrx_state == GDRTxRxStateIDLE && app->txrx->receiver) {
|
||||
subghz_receiver_reset(app->txrx->receiver);
|
||||
app->txrx->preset->frequency =
|
||||
subghz_setting_get_hopper_frequency(app->setting, app->txrx->hopper_idx_frequency);
|
||||
protopirate_rx(app, app->txrx->preset->frequency);
|
||||
gdr_rx(app, app->txrx->preset->frequency);
|
||||
}
|
||||
}
|
||||
|
||||
void protopirate_tx(ProtoPirateApp* app, uint32_t frequency) {
|
||||
void gdr_tx(GDRApp* app, uint32_t frequency) {
|
||||
furi_check(app);
|
||||
if(!subghz_devices_is_frequency_valid(app->txrx->radio_device, frequency)) {
|
||||
return;
|
||||
}
|
||||
|
||||
furi_check(app->txrx->txrx_state == ProtoPirateTxRxStateIDLE);
|
||||
furi_check(app->txrx->txrx_state == GDRTxRxStateIDLE);
|
||||
|
||||
subghz_devices_idle(app->txrx->radio_device);
|
||||
subghz_devices_set_frequency(app->txrx->radio_device, frequency);
|
||||
subghz_devices_set_tx(app->txrx->radio_device);
|
||||
|
||||
app->txrx->txrx_state = ProtoPirateTxRxStateTx;
|
||||
app->txrx->txrx_state = GDRTxRxStateTx;
|
||||
}
|
||||
|
||||
void protopirate_tx_stop(ProtoPirateApp* app) {
|
||||
void gdr_tx_stop(GDRApp* app) {
|
||||
furi_check(app);
|
||||
furi_check(app->txrx->txrx_state == ProtoPirateTxRxStateTx);
|
||||
furi_check(app->txrx->txrx_state == GDRTxRxStateTx);
|
||||
|
||||
subghz_devices_idle(app->txrx->radio_device);
|
||||
app->txrx->txrx_state = ProtoPirateTxRxStateIDLE;
|
||||
app->txrx->txrx_state = GDRTxRxStateIDLE;
|
||||
}
|
||||
@@ -0,0 +1,237 @@
|
||||
// gdr_app_i.h
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
#include "helpers/gdr_types.h"
|
||||
#include "helpers/gdr_settings.h"
|
||||
#include "scenes/gdr_scene.h"
|
||||
#include "views/gdr_receiver.h"
|
||||
#include "gdr_history.h"
|
||||
#include "helpers/radio_device_loader.h"
|
||||
#ifdef ENABLE_DUAL_RX_SCENE
|
||||
#include "helpers/gdr_rx_chain.h"
|
||||
#include "views/gdr_dual_receiver.h"
|
||||
#endif
|
||||
#ifdef ENABLE_SHIELD_RX_SCENE
|
||||
#include "helpers/gdr_rx_chain.h"
|
||||
#include "helpers/gdr_tx_chain.h"
|
||||
#endif
|
||||
|
||||
#include <gui/gui.h>
|
||||
#include <gui/view_dispatcher.h>
|
||||
#include <gui/scene_manager.h>
|
||||
#include <gui/modules/submenu.h>
|
||||
#include <gui/modules/variable_item_list.h>
|
||||
#include <gui/modules/widget.h>
|
||||
#include <gui/modules/text_input.h>
|
||||
#include <notification/notification_messages.h>
|
||||
#include <lib/subghz/subghz_setting.h>
|
||||
#include <lib/subghz/subghz_worker.h>
|
||||
#include <lib/subghz/receiver.h>
|
||||
#include <lib/subghz/transmitter.h>
|
||||
#include <lib/subghz/devices/devices.h>
|
||||
#include <lib/subghz/subghz_file_encoder_worker.h>
|
||||
#include <lib/flipper_application/plugins/plugin_manager.h>
|
||||
#include <lib/flipper_application/plugins/composite_resolver.h>
|
||||
#include <dialogs/dialogs.h>
|
||||
#include "defines.h"
|
||||
#include "protocols/protocols_common.h"
|
||||
#include "protocols/protocol_items.h"
|
||||
#include "protocols/gdr_protocol_plugins.h"
|
||||
#ifdef ENABLE_EMULATE_FEATURE
|
||||
#include "scenes/plugins/gdr_emulate_plugin.h"
|
||||
#endif
|
||||
#include "scenes/plugins/gdr_psa_bf_plugin.h"
|
||||
|
||||
#define GDR_KEYSTORE_DIR_NAME APP_ASSETS_PATH("encrypted")
|
||||
|
||||
typedef struct GDRApp GDRApp;
|
||||
|
||||
typedef enum {
|
||||
GDRCaptureOwnerNone = 0,
|
||||
GDRCaptureOwnerReceiver,
|
||||
GDRCaptureOwnerDualReceiver,
|
||||
#ifdef ENABLE_SHIELD_RX_SCENE
|
||||
GDRCaptureOwnerShieldReceiver,
|
||||
#endif
|
||||
GDRCaptureOwnerSubDecode,
|
||||
} GDRCaptureOwner;
|
||||
|
||||
typedef struct {
|
||||
GDRHistory* history;
|
||||
FuriMutex* mutex;
|
||||
uint16_t index;
|
||||
GDRCaptureOwner owner;
|
||||
} GDRSelectedCapture;
|
||||
|
||||
typedef struct {
|
||||
SubGhzWorker* worker;
|
||||
SubGhzEnvironment* environment;
|
||||
SubGhzReceiver* receiver;
|
||||
SubGhzRadioPreset* preset;
|
||||
const SubGhzProtocolRegistry* protocol_registry;
|
||||
CompositeApiResolver* plugin_resolver;
|
||||
PluginManager* protocol_plugin_manager;
|
||||
const GDRProtocolPlugin* protocol_plugin;
|
||||
GDRProtocolRegistryFilter protocol_registry_filter;
|
||||
GDRHistory* history;
|
||||
const SubGhzDevice* radio_device;
|
||||
GDRTxRxState txrx_state;
|
||||
GDRHopperState hopper_state;
|
||||
GDRRxKeyState rx_key_state;
|
||||
uint8_t hopper_idx_frequency;
|
||||
uint8_t hopper_timeout;
|
||||
uint16_t idx_menu_chosen;
|
||||
} GDRTxRx;
|
||||
|
||||
struct GDRApp {
|
||||
Gui* gui;
|
||||
ViewDispatcher* view_dispatcher;
|
||||
SceneManager* scene_manager;
|
||||
NotificationApp* notifications;
|
||||
DialogsApp* dialogs;
|
||||
VariableItemList* variable_item_list;
|
||||
Submenu* submenu;
|
||||
Widget* widget;
|
||||
TextInput* text_input;
|
||||
View* view_about;
|
||||
FuriString* file_path;
|
||||
GDRReceiver* gdr_receiver;
|
||||
GDRTxRx* txrx;
|
||||
SubGhzSetting* setting;
|
||||
GDRLock lock;
|
||||
FuriString* loaded_file_path;
|
||||
bool auto_save;
|
||||
bool radio_initialized;
|
||||
GDRSettings settings;
|
||||
uint32_t start_tx_time;
|
||||
uint8_t tx_power;
|
||||
char save_filename[64];
|
||||
FuriString* save_protocol;
|
||||
uint16_t save_history_idx;
|
||||
bool save_from_saved_info;
|
||||
bool emulate_disabled_for_loaded;
|
||||
bool emulate_feature_enabled;
|
||||
GDRSelectedCapture selected_capture;
|
||||
GDRCaptureOwner unsaved_history_owner;
|
||||
#ifdef ENABLE_EMULATE_FEATURE
|
||||
#define EMULATE_NAV_NONE 0U
|
||||
#define EMULATE_NAV_POP 1U
|
||||
#define EMULATE_NAV_STOP_APP 2U
|
||||
CompositeApiResolver* emulate_plugin_resolver;
|
||||
PluginManager* emulate_plugin_manager;
|
||||
const GDREmulatePlugin* emulate_plugin;
|
||||
uint8_t emulate_nav_pending;
|
||||
#endif
|
||||
CompositeApiResolver* psa_bf_plugin_resolver;
|
||||
PluginManager* psa_bf_plugin_manager;
|
||||
const GDRPsaBfPlugin* psa_bf_plugin;
|
||||
#ifdef ENABLE_DUAL_RX_SCENE
|
||||
GDRDualReceiver* dual_receiver;
|
||||
GDRRxChain* dual_chain_a;
|
||||
GDRRxChain* dual_chain_b;
|
||||
GDRHistory* dual_history;
|
||||
FuriMutex* dual_history_mutex;
|
||||
uint32_t dual_freq_a;
|
||||
uint32_t dual_freq_b;
|
||||
uint8_t dual_preset_a;
|
||||
uint8_t dual_preset_b;
|
||||
#endif
|
||||
#ifdef ENABLE_SHIELD_RX_SCENE
|
||||
GDRRxChain* shield_rx_chain;
|
||||
GDRTxChain* shield_tx_chain;
|
||||
GDRHistory* shield_history;
|
||||
FuriMutex* shield_history_mutex;
|
||||
uint32_t shield_freq;
|
||||
uint8_t shield_preset_index;
|
||||
uint8_t shield_tx_offset_index;
|
||||
uint8_t shield_tx_power;
|
||||
bool shield_auto_save_failed;
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef ENABLE_EMULATE_FEATURE
|
||||
void gdr_emulate_context_release(GDRApp* app);
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
GDRSetTypeFord_v0,
|
||||
GDRSetTypeMAX,
|
||||
} GDRSetType;
|
||||
|
||||
void gdr_preset_init(
|
||||
void* context,
|
||||
const char* preset_name,
|
||||
uint32_t frequency,
|
||||
uint8_t* preset_data,
|
||||
size_t preset_data_size);
|
||||
|
||||
void gdr_get_frequency_modulation(
|
||||
GDRApp* app,
|
||||
FuriString* frequency,
|
||||
FuriString* modulation);
|
||||
void gdr_get_frequency_modulation_str(
|
||||
GDRApp* app,
|
||||
char* frequency,
|
||||
size_t frequency_size,
|
||||
char* modulation,
|
||||
size_t modulation_size);
|
||||
|
||||
void gdr_begin(GDRApp* app, uint8_t* preset_data);
|
||||
uint32_t gdr_rx(GDRApp* app, uint32_t frequency);
|
||||
void gdr_idle(GDRApp* app);
|
||||
void gdr_rx_end(GDRApp* app);
|
||||
void gdr_sleep(GDRApp* app);
|
||||
void gdr_hopper_update(GDRApp* app);
|
||||
void gdr_tx(GDRApp* app, uint32_t frequency);
|
||||
void gdr_tx_stop(GDRApp* app);
|
||||
bool gdr_radio_init(GDRApp* app);
|
||||
void gdr_radio_deinit(GDRApp* app);
|
||||
bool gdr_refresh_protocol_registry(GDRApp* app, bool ensure_receiver_ready);
|
||||
bool gdr_apply_protocol_registry_for_preset_data(
|
||||
GDRApp* app,
|
||||
const uint8_t* preset_data,
|
||||
size_t preset_data_size);
|
||||
bool gdr_ensure_variable_item_list(GDRApp* app);
|
||||
bool gdr_ensure_widget(GDRApp* app);
|
||||
bool gdr_ensure_text_input(GDRApp* app);
|
||||
bool gdr_ensure_view_about(GDRApp* app);
|
||||
bool gdr_ensure_receiver_view(GDRApp* app);
|
||||
#ifdef ENABLE_DUAL_RX_SCENE
|
||||
bool gdr_ensure_dual_receiver_view(GDRApp* app);
|
||||
#endif
|
||||
void gdr_release_shared_radio_state(GDRApp* app);
|
||||
|
||||
void gdr_rx_stack_suspend_for_tx(GDRApp* app);
|
||||
|
||||
void gdr_rx_stack_resume_after_tx(GDRApp* app);
|
||||
|
||||
void gdr_selected_capture_set(
|
||||
GDRApp* app,
|
||||
GDRHistory* history,
|
||||
FuriMutex* mutex,
|
||||
uint16_t index,
|
||||
GDRCaptureOwner owner);
|
||||
void gdr_selected_capture_clear(GDRApp* app);
|
||||
bool gdr_selected_capture_is_valid(GDRApp* app);
|
||||
GDRHistory* gdr_selected_capture_get_history(GDRApp* app);
|
||||
uint16_t gdr_selected_capture_get_index(GDRApp* app);
|
||||
GDRHistorySource gdr_selected_capture_get_source(GDRApp* app);
|
||||
FlipperFormat* gdr_selected_capture_get_raw_data(GDRApp* app);
|
||||
bool gdr_selected_capture_get_path(GDRApp* app, FuriString* out_path);
|
||||
void gdr_selected_capture_release_scratch(GDRApp* app);
|
||||
|
||||
void gdr_app_free(GDRApp* app);
|
||||
|
||||
static const NotificationSequence sequence_tx = {
|
||||
&message_note_c5,
|
||||
&message_vibro_on,
|
||||
&message_red_255,
|
||||
&message_blue_255,
|
||||
&message_blink_start_10,
|
||||
&message_delay_25,
|
||||
&message_vibro_off,
|
||||
&message_delay_25,
|
||||
&message_sound_off,
|
||||
NULL,
|
||||
};
|
||||
+111
-111
@@ -1,6 +1,6 @@
|
||||
// protopirate_history.c
|
||||
#include "protopirate_history.h"
|
||||
#include "helpers/protopirate_storage.h"
|
||||
// gdr_history.c
|
||||
#include "gdr_history.h"
|
||||
#include "helpers/gdr_storage.h"
|
||||
#include <lib/subghz/receiver.h>
|
||||
#include <storage/storage.h>
|
||||
#include <string.h>
|
||||
@@ -8,28 +8,28 @@
|
||||
#include <furi.h>
|
||||
#include "defines.h"
|
||||
|
||||
#define TAG "ProtoPirateHistory"
|
||||
#define TAG "GDRHistory"
|
||||
#define HISTORY_SCRATCH_TEXT_RESERVE 256U
|
||||
#define HISTORY_SCRATCH_PATH_RESERVE 128U
|
||||
#define HISTORY_ARENA_RESERVE 1024U
|
||||
|
||||
static uint32_t protopirate_history_next_capture_seq = 0;
|
||||
static uint32_t gdr_history_next_capture_seq = 0;
|
||||
|
||||
typedef struct {
|
||||
uint32_t seq_id;
|
||||
uint16_t text_offset;
|
||||
uint16_t text_len;
|
||||
uint8_t type;
|
||||
ProtoPirateHistorySource source;
|
||||
} ProtoPirateHistoryItem;
|
||||
GDRHistorySource source;
|
||||
} GDRHistoryItem;
|
||||
|
||||
ARRAY_DEF(ProtoPirateHistoryItemArray, ProtoPirateHistoryItem, M_POD_OPLIST)
|
||||
ARRAY_DEF(GDRHistoryItemArray, GDRHistoryItem, M_POD_OPLIST)
|
||||
|
||||
struct ProtoPirateHistory {
|
||||
ProtoPirateHistoryItemArray_t data;
|
||||
struct GDRHistory {
|
||||
GDRHistoryItemArray_t data;
|
||||
uint16_t last_index;
|
||||
uint32_t last_update_timestamp[ProtoPirateHistorySourceCount];
|
||||
uint8_t code_last_hash_data[ProtoPirateHistorySourceCount];
|
||||
uint32_t last_update_timestamp[GDRHistorySourceCount];
|
||||
uint8_t code_last_hash_data[GDRHistorySourceCount];
|
||||
Storage* storage;
|
||||
FlipperFormat* loaded_ff;
|
||||
int16_t loaded_idx;
|
||||
@@ -39,26 +39,26 @@ struct ProtoPirateHistory {
|
||||
FuriString* text_arena;
|
||||
};
|
||||
|
||||
static uint32_t protopirate_history_allocate_capture_seq(void) {
|
||||
static uint32_t gdr_history_allocate_capture_seq(void) {
|
||||
uint32_t tick_seed = (uint32_t)(furi_get_tick() & 0x0FFFFFFF);
|
||||
if(tick_seed == 0) {
|
||||
tick_seed = 1;
|
||||
}
|
||||
|
||||
FURI_CRITICAL_ENTER();
|
||||
if(protopirate_history_next_capture_seq == 0 ||
|
||||
protopirate_history_next_capture_seq < tick_seed) {
|
||||
protopirate_history_next_capture_seq = tick_seed;
|
||||
if(gdr_history_next_capture_seq == 0 ||
|
||||
gdr_history_next_capture_seq < tick_seed) {
|
||||
gdr_history_next_capture_seq = tick_seed;
|
||||
}
|
||||
uint32_t seq = protopirate_history_next_capture_seq++;
|
||||
if(protopirate_history_next_capture_seq == 0) {
|
||||
protopirate_history_next_capture_seq = 1;
|
||||
uint32_t seq = gdr_history_next_capture_seq++;
|
||||
if(gdr_history_next_capture_seq == 0) {
|
||||
gdr_history_next_capture_seq = 1;
|
||||
}
|
||||
FURI_CRITICAL_EXIT();
|
||||
return seq;
|
||||
}
|
||||
|
||||
void protopirate_history_release_scratch(ProtoPirateHistory* instance) {
|
||||
void gdr_history_release_scratch(GDRHistory* instance) {
|
||||
furi_check(instance);
|
||||
if(instance->loaded_ff) {
|
||||
flipper_format_free(instance->loaded_ff);
|
||||
@@ -68,27 +68,27 @@ void protopirate_history_release_scratch(ProtoPirateHistory* instance) {
|
||||
}
|
||||
|
||||
static void
|
||||
protopirate_history_build_path(ProtoPirateHistory* instance, uint32_t seq_id, FuriString* out) {
|
||||
gdr_history_build_path(GDRHistory* instance, uint32_t seq_id, FuriString* out) {
|
||||
UNUSED(instance);
|
||||
protopirate_storage_build_history_path(seq_id, out);
|
||||
gdr_storage_build_history_path(seq_id, out);
|
||||
}
|
||||
|
||||
static void
|
||||
protopirate_history_delete_capture_file(ProtoPirateHistory* instance, uint32_t seq_id) {
|
||||
protopirate_history_build_path(instance, seq_id, instance->scratch_path);
|
||||
protopirate_storage_delete_file(furi_string_get_cstr(instance->scratch_path));
|
||||
gdr_history_delete_capture_file(GDRHistory* instance, uint32_t seq_id) {
|
||||
gdr_history_build_path(instance, seq_id, instance->scratch_path);
|
||||
gdr_storage_delete_file(furi_string_get_cstr(instance->scratch_path));
|
||||
}
|
||||
|
||||
static void protopirate_history_delete_all_capture_files(ProtoPirateHistory* instance) {
|
||||
size_t item_count = ProtoPirateHistoryItemArray_size(instance->data);
|
||||
static void gdr_history_delete_all_capture_files(GDRHistory* instance) {
|
||||
size_t item_count = GDRHistoryItemArray_size(instance->data);
|
||||
for(size_t i = 0; i < item_count; i++) {
|
||||
ProtoPirateHistoryItem* item = ProtoPirateHistoryItemArray_get(instance->data, i);
|
||||
protopirate_history_delete_capture_file(instance, item->seq_id);
|
||||
GDRHistoryItem* item = GDRHistoryItemArray_get(instance->data, i);
|
||||
gdr_history_delete_capture_file(instance, item->seq_id);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
protopirate_history_arena_remove(ProtoPirateHistory* instance, uint16_t offset, uint16_t len) {
|
||||
gdr_history_arena_remove(GDRHistory* instance, uint16_t offset, uint16_t len) {
|
||||
if(len == 0) return;
|
||||
|
||||
size_t arena_size = furi_string_size(instance->text_arena);
|
||||
@@ -103,19 +103,19 @@ static void
|
||||
furi_string_cat_str(rebuilt, arena + offset + len);
|
||||
furi_string_move(instance->text_arena, rebuilt);
|
||||
|
||||
size_t n = ProtoPirateHistoryItemArray_size(instance->data);
|
||||
size_t n = GDRHistoryItemArray_size(instance->data);
|
||||
for(size_t i = 0; i < n; i++) {
|
||||
ProtoPirateHistoryItem* it = ProtoPirateHistoryItemArray_get(instance->data, i);
|
||||
GDRHistoryItem* it = GDRHistoryItemArray_get(instance->data, i);
|
||||
if(it->text_offset > offset) {
|
||||
it->text_offset -= len;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ProtoPirateHistory* protopirate_history_alloc(void) {
|
||||
ProtoPirateHistory* instance = malloc(sizeof(ProtoPirateHistory));
|
||||
GDRHistory* gdr_history_alloc(void) {
|
||||
GDRHistory* instance = malloc(sizeof(GDRHistory));
|
||||
furi_check(instance);
|
||||
ProtoPirateHistoryItemArray_init(instance->data);
|
||||
GDRHistoryItemArray_init(instance->data);
|
||||
instance->last_index = 0;
|
||||
memset(instance->last_update_timestamp, 0, sizeof(instance->last_update_timestamp));
|
||||
memset(instance->code_last_hash_data, 0, sizeof(instance->code_last_hash_data));
|
||||
@@ -138,11 +138,11 @@ ProtoPirateHistory* protopirate_history_alloc(void) {
|
||||
return instance;
|
||||
}
|
||||
|
||||
void protopirate_history_free(ProtoPirateHistory* instance) {
|
||||
void gdr_history_free(GDRHistory* instance) {
|
||||
furi_check(instance);
|
||||
protopirate_history_release_scratch(instance);
|
||||
protopirate_history_delete_all_capture_files(instance);
|
||||
ProtoPirateHistoryItemArray_clear(instance->data);
|
||||
gdr_history_release_scratch(instance);
|
||||
gdr_history_delete_all_capture_files(instance);
|
||||
GDRHistoryItemArray_clear(instance->data);
|
||||
|
||||
if(instance->scratch_text) {
|
||||
furi_string_free(instance->scratch_text);
|
||||
@@ -164,29 +164,29 @@ void protopirate_history_free(ProtoPirateHistory* instance) {
|
||||
free(instance);
|
||||
}
|
||||
|
||||
void protopirate_history_reset(ProtoPirateHistory* instance) {
|
||||
void gdr_history_reset(GDRHistory* instance) {
|
||||
furi_check(instance);
|
||||
protopirate_history_release_scratch(instance);
|
||||
protopirate_history_delete_all_capture_files(instance);
|
||||
ProtoPirateHistoryItemArray_reset(instance->data);
|
||||
gdr_history_release_scratch(instance);
|
||||
gdr_history_delete_all_capture_files(instance);
|
||||
GDRHistoryItemArray_reset(instance->data);
|
||||
furi_string_reset(instance->text_arena);
|
||||
instance->last_index = 0;
|
||||
memset(instance->last_update_timestamp, 0, sizeof(instance->last_update_timestamp));
|
||||
memset(instance->code_last_hash_data, 0, sizeof(instance->code_last_hash_data));
|
||||
}
|
||||
|
||||
uint16_t protopirate_history_get_item(ProtoPirateHistory* instance) {
|
||||
uint16_t gdr_history_get_item(GDRHistory* instance) {
|
||||
furi_check(instance);
|
||||
return ProtoPirateHistoryItemArray_size(instance->data);
|
||||
return GDRHistoryItemArray_size(instance->data);
|
||||
}
|
||||
|
||||
uint16_t protopirate_history_get_last_index(ProtoPirateHistory* instance) {
|
||||
uint16_t gdr_history_get_last_index(GDRHistory* instance) {
|
||||
furi_check(instance);
|
||||
return instance->last_index;
|
||||
}
|
||||
|
||||
void protopirate_history_format_status_text(
|
||||
ProtoPirateHistory* instance,
|
||||
void gdr_history_format_status_text(
|
||||
GDRHistory* instance,
|
||||
char* output,
|
||||
size_t output_size) {
|
||||
furi_check(instance);
|
||||
@@ -196,87 +196,87 @@ void protopirate_history_format_status_text(
|
||||
return;
|
||||
}
|
||||
|
||||
uint16_t n = protopirate_history_get_item(instance);
|
||||
if(n >= PROTOPIRATE_HISTORY_MAX) {
|
||||
uint16_t n = gdr_history_get_item(instance);
|
||||
if(n >= GDR_HISTORY_MAX) {
|
||||
snprintf(output, output_size, "FULL");
|
||||
} else {
|
||||
snprintf(output, output_size, "%u/%u", n, PROTOPIRATE_HISTORY_MAX);
|
||||
snprintf(output, output_size, "%u/%u", n, GDR_HISTORY_MAX);
|
||||
}
|
||||
}
|
||||
|
||||
void protopirate_history_get_status_text(ProtoPirateHistory* instance, FuriString* output) {
|
||||
void gdr_history_get_status_text(GDRHistory* instance, FuriString* output) {
|
||||
furi_check(instance);
|
||||
furi_check(output);
|
||||
|
||||
char status_text[16];
|
||||
protopirate_history_format_status_text(instance, status_text, sizeof(status_text));
|
||||
gdr_history_format_status_text(instance, status_text, sizeof(status_text));
|
||||
furi_string_set_str(output, status_text);
|
||||
}
|
||||
|
||||
bool protopirate_history_get_capture_path(
|
||||
ProtoPirateHistory* instance,
|
||||
bool gdr_history_get_capture_path(
|
||||
GDRHistory* instance,
|
||||
uint16_t idx,
|
||||
FuriString* out_path) {
|
||||
furi_check(instance);
|
||||
furi_check(out_path);
|
||||
|
||||
if(idx >= ProtoPirateHistoryItemArray_size(instance->data)) {
|
||||
if(idx >= GDRHistoryItemArray_size(instance->data)) {
|
||||
return false;
|
||||
}
|
||||
ProtoPirateHistoryItem* item = ProtoPirateHistoryItemArray_get(instance->data, idx);
|
||||
protopirate_history_build_path(instance, item->seq_id, out_path);
|
||||
GDRHistoryItem* item = GDRHistoryItemArray_get(instance->data, idx);
|
||||
gdr_history_build_path(instance, item->seq_id, out_path);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool protopirate_history_capture_path_equals(
|
||||
ProtoPirateHistory* instance,
|
||||
bool gdr_history_capture_path_equals(
|
||||
GDRHistory* instance,
|
||||
uint16_t idx,
|
||||
const char* path) {
|
||||
furi_check(instance);
|
||||
|
||||
if(!path || idx >= ProtoPirateHistoryItemArray_size(instance->data)) {
|
||||
if(!path || idx >= GDRHistoryItemArray_size(instance->data)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ProtoPirateHistoryItem* item = ProtoPirateHistoryItemArray_get(instance->data, idx);
|
||||
protopirate_history_build_path(instance, item->seq_id, instance->scratch_path);
|
||||
GDRHistoryItem* item = GDRHistoryItemArray_get(instance->data, idx);
|
||||
gdr_history_build_path(instance, item->seq_id, instance->scratch_path);
|
||||
return strcmp(furi_string_get_cstr(instance->scratch_path), path) == 0;
|
||||
}
|
||||
|
||||
ProtoPirateHistorySource protopirate_history_get_source(
|
||||
ProtoPirateHistory* instance,
|
||||
GDRHistorySource gdr_history_get_source(
|
||||
GDRHistory* instance,
|
||||
uint16_t idx) {
|
||||
furi_check(instance);
|
||||
if(idx >= ProtoPirateHistoryItemArray_size(instance->data)) {
|
||||
return ProtoPirateHistorySourceUnknown;
|
||||
if(idx >= GDRHistoryItemArray_size(instance->data)) {
|
||||
return GDRHistorySourceUnknown;
|
||||
}
|
||||
return ProtoPirateHistoryItemArray_get(instance->data, idx)->source;
|
||||
return GDRHistoryItemArray_get(instance->data, idx)->source;
|
||||
}
|
||||
|
||||
const char* protopirate_history_source_name(ProtoPirateHistorySource source) {
|
||||
const char* gdr_history_source_name(GDRHistorySource source) {
|
||||
switch(source) {
|
||||
case ProtoPirateHistorySourceExternal:
|
||||
case GDRHistorySourceExternal:
|
||||
return "External";
|
||||
case ProtoPirateHistorySourceInternal:
|
||||
case GDRHistorySourceInternal:
|
||||
return "Internal";
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
bool protopirate_history_add_to_history(
|
||||
ProtoPirateHistory* instance,
|
||||
bool gdr_history_add_to_history(
|
||||
GDRHistory* instance,
|
||||
void* context,
|
||||
SubGhzRadioPreset* preset,
|
||||
ProtoPirateHistorySource source) {
|
||||
GDRHistorySource source) {
|
||||
furi_check(instance);
|
||||
furi_check(context);
|
||||
|
||||
if(source >= ProtoPirateHistorySourceCount) {
|
||||
source = ProtoPirateHistorySourceUnknown;
|
||||
if(source >= GDRHistorySourceCount) {
|
||||
source = GDRHistorySourceUnknown;
|
||||
}
|
||||
|
||||
if(ProtoPirateHistoryItemArray_size(instance->data) >= PROTOPIRATE_HISTORY_MAX) {
|
||||
if(GDRHistoryItemArray_size(instance->data) >= GDR_HISTORY_MAX) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -289,7 +289,7 @@ bool protopirate_history_add_to_history(
|
||||
return false;
|
||||
}
|
||||
|
||||
protopirate_history_release_scratch(instance);
|
||||
gdr_history_release_scratch(instance);
|
||||
|
||||
furi_string_reset(instance->scratch_text);
|
||||
furi_string_reset(instance->scratch_path);
|
||||
@@ -307,13 +307,13 @@ bool protopirate_history_add_to_history(
|
||||
return false;
|
||||
}
|
||||
|
||||
if(source != ProtoPirateHistorySourceUnknown) {
|
||||
if(source != GDRHistorySourceUnknown) {
|
||||
flipper_format_insert_or_update_string_cstr(
|
||||
temp_ff, "RadioDevice", protopirate_history_source_name(source));
|
||||
temp_ff, "RadioDevice", gdr_history_source_name(source));
|
||||
}
|
||||
|
||||
uint32_t seq = protopirate_history_allocate_capture_seq();
|
||||
bool saved = protopirate_storage_save_history_capture(temp_ff, seq, instance->scratch_path);
|
||||
uint32_t seq = gdr_history_allocate_capture_seq();
|
||||
bool saved = gdr_storage_save_history_capture(temp_ff, seq, instance->scratch_path);
|
||||
flipper_format_free(temp_ff);
|
||||
|
||||
if(!saved) {
|
||||
@@ -332,7 +332,7 @@ bool protopirate_history_add_to_history(
|
||||
furi_check(offset <= UINT16_MAX);
|
||||
furi_string_cat_str(instance->text_arena, text_cstr);
|
||||
|
||||
ProtoPirateHistoryItem* item = ProtoPirateHistoryItemArray_push_raw(instance->data);
|
||||
GDRHistoryItem* item = GDRHistoryItemArray_push_raw(instance->data);
|
||||
item->seq_id = seq;
|
||||
item->text_offset = (uint16_t)offset;
|
||||
item->text_len = (uint16_t)text_len;
|
||||
@@ -345,57 +345,57 @@ bool protopirate_history_add_to_history(
|
||||
TAG,
|
||||
"Added item %u to history (size: %zu) seq=%lu",
|
||||
instance->last_index,
|
||||
ProtoPirateHistoryItemArray_size(instance->data),
|
||||
GDRHistoryItemArray_size(instance->data),
|
||||
(unsigned long)seq);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void protopirate_history_delete_item(ProtoPirateHistory* instance, uint16_t idx) {
|
||||
void gdr_history_delete_item(GDRHistory* instance, uint16_t idx) {
|
||||
furi_check(instance);
|
||||
|
||||
size_t item_count = ProtoPirateHistoryItemArray_size(instance->data);
|
||||
size_t item_count = GDRHistoryItemArray_size(instance->data);
|
||||
if(idx >= item_count) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(instance->loaded_ff) {
|
||||
if(instance->loaded_idx == (int16_t)idx) {
|
||||
protopirate_history_release_scratch(instance);
|
||||
gdr_history_release_scratch(instance);
|
||||
} else if(instance->loaded_idx > (int16_t)idx) {
|
||||
instance->loaded_idx--;
|
||||
}
|
||||
}
|
||||
|
||||
ProtoPirateHistoryItem* item = ProtoPirateHistoryItemArray_get(instance->data, idx);
|
||||
GDRHistoryItem* item = GDRHistoryItemArray_get(instance->data, idx);
|
||||
uint32_t seq_id = item->seq_id;
|
||||
uint16_t text_offset = item->text_offset;
|
||||
uint16_t text_len = item->text_len;
|
||||
|
||||
protopirate_history_delete_capture_file(instance, seq_id);
|
||||
ProtoPirateHistoryItemArray_pop_at(NULL, instance->data, idx);
|
||||
protopirate_history_arena_remove(instance, text_offset, text_len);
|
||||
gdr_history_delete_capture_file(instance, seq_id);
|
||||
GDRHistoryItemArray_pop_at(NULL, instance->data, idx);
|
||||
gdr_history_arena_remove(instance, text_offset, text_len);
|
||||
|
||||
FURI_LOG_I(
|
||||
TAG,
|
||||
"Deleted history item %u (size: %zu)",
|
||||
idx,
|
||||
ProtoPirateHistoryItemArray_size(instance->data));
|
||||
GDRHistoryItemArray_size(instance->data));
|
||||
}
|
||||
|
||||
void protopirate_history_get_text_item_menu(
|
||||
ProtoPirateHistory* instance,
|
||||
void gdr_history_get_text_item_menu(
|
||||
GDRHistory* instance,
|
||||
FuriString* output,
|
||||
uint16_t idx) {
|
||||
furi_check(instance);
|
||||
furi_check(output);
|
||||
|
||||
if(idx >= ProtoPirateHistoryItemArray_size(instance->data)) {
|
||||
if(idx >= GDRHistoryItemArray_size(instance->data)) {
|
||||
furi_string_set(output, "---");
|
||||
return;
|
||||
}
|
||||
|
||||
ProtoPirateHistoryItem* item = ProtoPirateHistoryItemArray_get(instance->data, idx);
|
||||
GDRHistoryItem* item = GDRHistoryItemArray_get(instance->data, idx);
|
||||
const char* arena = furi_string_get_cstr(instance->text_arena);
|
||||
const char* str = arena + item->text_offset;
|
||||
size_t remaining = item->text_len;
|
||||
@@ -407,16 +407,16 @@ void protopirate_history_get_text_item_menu(
|
||||
|
||||
uint16_t display_idx = idx + 1;
|
||||
const char* source_tag = "";
|
||||
if(item->source == ProtoPirateHistorySourceExternal) {
|
||||
if(item->source == GDRHistorySourceExternal) {
|
||||
source_tag = "[E] ";
|
||||
} else if(item->source == ProtoPirateHistorySourceInternal) {
|
||||
} else if(item->source == GDRHistorySourceInternal) {
|
||||
source_tag = "[I] ";
|
||||
}
|
||||
furi_string_printf(output, "%u. %s%.*s", display_idx, source_tag, (int)len, str);
|
||||
}
|
||||
|
||||
void protopirate_history_get_text_item_detail(
|
||||
ProtoPirateHistory* instance,
|
||||
void gdr_history_get_text_item_detail(
|
||||
GDRHistory* instance,
|
||||
uint16_t idx,
|
||||
FuriString* output,
|
||||
SubGhzEnvironment* environment) {
|
||||
@@ -424,20 +424,20 @@ void protopirate_history_get_text_item_detail(
|
||||
furi_check(output);
|
||||
UNUSED(environment);
|
||||
|
||||
if(idx >= ProtoPirateHistoryItemArray_size(instance->data)) {
|
||||
if(idx >= GDRHistoryItemArray_size(instance->data)) {
|
||||
furi_string_set(output, "---");
|
||||
return;
|
||||
}
|
||||
|
||||
ProtoPirateHistoryItem* item = ProtoPirateHistoryItemArray_get(instance->data, idx);
|
||||
GDRHistoryItem* item = GDRHistoryItemArray_get(instance->data, idx);
|
||||
const char* arena = furi_string_get_cstr(instance->text_arena);
|
||||
furi_string_set_strn(output, arena + item->text_offset, item->text_len);
|
||||
}
|
||||
|
||||
FlipperFormat* protopirate_history_get_raw_data(ProtoPirateHistory* instance, uint16_t idx) {
|
||||
FlipperFormat* gdr_history_get_raw_data(GDRHistory* instance, uint16_t idx) {
|
||||
furi_check(instance);
|
||||
|
||||
if(idx >= ProtoPirateHistoryItemArray_size(instance->data)) {
|
||||
if(idx >= GDRHistoryItemArray_size(instance->data)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -445,10 +445,10 @@ FlipperFormat* protopirate_history_get_raw_data(ProtoPirateHistory* instance, ui
|
||||
return instance->loaded_ff;
|
||||
}
|
||||
|
||||
protopirate_history_release_scratch(instance);
|
||||
gdr_history_release_scratch(instance);
|
||||
|
||||
ProtoPirateHistoryItem* item = ProtoPirateHistoryItemArray_get(instance->data, idx);
|
||||
protopirate_history_build_path(instance, item->seq_id, instance->scratch_path);
|
||||
GDRHistoryItem* item = GDRHistoryItemArray_get(instance->data, idx);
|
||||
gdr_history_build_path(instance, item->seq_id, instance->scratch_path);
|
||||
|
||||
instance->loaded_ff = flipper_format_file_alloc(instance->storage);
|
||||
furi_check(instance->loaded_ff);
|
||||
@@ -464,19 +464,19 @@ FlipperFormat* protopirate_history_get_raw_data(ProtoPirateHistory* instance, ui
|
||||
return instance->loaded_ff;
|
||||
}
|
||||
|
||||
void protopirate_history_set_item_str(ProtoPirateHistory* instance, uint16_t idx, const char* str) {
|
||||
void gdr_history_set_item_str(GDRHistory* instance, uint16_t idx, const char* str) {
|
||||
furi_check(instance);
|
||||
furi_check(str);
|
||||
|
||||
if(idx >= ProtoPirateHistoryItemArray_size(instance->data)) {
|
||||
if(idx >= GDRHistoryItemArray_size(instance->data)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ProtoPirateHistoryItem* item = ProtoPirateHistoryItemArray_get(instance->data, idx);
|
||||
GDRHistoryItem* item = GDRHistoryItemArray_get(instance->data, idx);
|
||||
uint16_t old_offset = item->text_offset;
|
||||
uint16_t old_len = item->text_len;
|
||||
|
||||
protopirate_history_arena_remove(instance, old_offset, old_len);
|
||||
gdr_history_arena_remove(instance, old_offset, old_len);
|
||||
|
||||
size_t new_offset = furi_string_size(instance->text_arena);
|
||||
size_t new_len = strlen(str);
|
||||
@@ -0,0 +1,63 @@
|
||||
// gdr_history.h
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
#include <lib/subghz/receiver.h>
|
||||
#include <lib/subghz/protocols/base.h>
|
||||
|
||||
#define GDR_HISTORY_MAX 10
|
||||
|
||||
typedef struct SubGhzEnvironment SubGhzEnvironment;
|
||||
typedef struct GDRHistory GDRHistory;
|
||||
|
||||
typedef enum {
|
||||
GDRHistorySourceUnknown = 0,
|
||||
GDRHistorySourceExternal,
|
||||
GDRHistorySourceInternal,
|
||||
GDRHistorySourceCount,
|
||||
} GDRHistorySource;
|
||||
|
||||
GDRHistory* gdr_history_alloc(void);
|
||||
void gdr_history_free(GDRHistory* instance);
|
||||
void gdr_history_reset(GDRHistory* instance);
|
||||
uint16_t gdr_history_get_item(GDRHistory* instance);
|
||||
uint16_t gdr_history_get_last_index(GDRHistory* instance);
|
||||
GDRHistorySource gdr_history_get_source(
|
||||
GDRHistory* instance,
|
||||
uint16_t idx);
|
||||
const char* gdr_history_source_name(GDRHistorySource source);
|
||||
void gdr_history_format_status_text(
|
||||
GDRHistory* instance,
|
||||
char* output,
|
||||
size_t output_size);
|
||||
void gdr_history_get_status_text(GDRHistory* instance, FuriString* output);
|
||||
|
||||
bool gdr_history_get_capture_path(
|
||||
GDRHistory* instance,
|
||||
uint16_t idx,
|
||||
FuriString* out_path);
|
||||
bool gdr_history_capture_path_equals(
|
||||
GDRHistory* instance,
|
||||
uint16_t idx,
|
||||
const char* path);
|
||||
|
||||
bool gdr_history_add_to_history(
|
||||
GDRHistory* instance,
|
||||
void* context,
|
||||
SubGhzRadioPreset* preset,
|
||||
GDRHistorySource source);
|
||||
void gdr_history_delete_item(GDRHistory* instance, uint16_t idx);
|
||||
void gdr_history_get_text_item_menu(
|
||||
GDRHistory* instance,
|
||||
FuriString* output,
|
||||
uint16_t idx);
|
||||
void gdr_history_get_text_item_detail(
|
||||
GDRHistory* instance,
|
||||
uint16_t idx,
|
||||
FuriString* output,
|
||||
SubGhzEnvironment* environment);
|
||||
FlipperFormat* gdr_history_get_raw_data(GDRHistory* instance, uint16_t idx);
|
||||
|
||||
void gdr_history_release_scratch(GDRHistory* instance);
|
||||
|
||||
void gdr_history_set_item_str(GDRHistory* instance, uint16_t idx, const char* str);
|
||||
+1
-1
@@ -9,5 +9,5 @@ extern const Icon I_PP_scanning_123x52;
|
||||
extern const Icon I_PP_scanning_ext_123x52;
|
||||
extern const Icon I_Pin_back_arrow_10x8;
|
||||
extern const Icon I_WarningDolphin_45x42;
|
||||
extern const Icon I_protopirate_10px;
|
||||
extern const Icon I_gdr_10px;
|
||||
extern const Icon I_subghz_10px;
|
||||
@@ -0,0 +1,14 @@
|
||||
#include "gdr_psa_bf_host.h"
|
||||
|
||||
bool gdr_psa_bf_plugin_ensure_loaded(GDRApp* app) {
|
||||
(void)app;
|
||||
return false;
|
||||
}
|
||||
|
||||
void gdr_psa_bf_plugin_unload_if_idle(GDRApp* app) {
|
||||
(void)app;
|
||||
}
|
||||
|
||||
void gdr_psa_bf_context_release(GDRApp* app) {
|
||||
(void)app;
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef struct GDRApp GDRApp;
|
||||
|
||||
bool gdr_psa_bf_plugin_ensure_loaded(GDRApp* app);
|
||||
void gdr_psa_bf_plugin_unload_if_idle(GDRApp* app);
|
||||
void gdr_psa_bf_context_release(GDRApp* app);
|
||||
|
||||
void gdr_receiver_info_rebuild_normal_widget(void* app);
|
||||
|
||||
#ifdef ENABLE_SUB_DECODE_SCENE
|
||||
void gdr_subdecode_psa_bf_complete_refresh(void* app);
|
||||
#endif
|
||||
+126
-126
@@ -1,5 +1,5 @@
|
||||
// helpers/protopirate_rx_chain.c
|
||||
#include "protopirate_rx_chain.h"
|
||||
// helpers/gdr_rx_chain.c
|
||||
#include "gdr_rx_chain.h"
|
||||
|
||||
#if defined(ENABLE_DUAL_RX_SCENE) || defined(ENABLE_SHIELD_RX_SCENE)
|
||||
|
||||
@@ -7,33 +7,33 @@
|
||||
#include <loader/firmware_api/firmware_api.h>
|
||||
#include "../protocols/keys.h"
|
||||
|
||||
#define TAG "ProtoPirateRxChain"
|
||||
#define TAG "GDRRxChain"
|
||||
|
||||
#define PROTOPIRATE_CHAIN_KEYSTORE_DIR APP_ASSETS_PATH("encrypted")
|
||||
#define GDR_CHAIN_KEYSTORE_DIR APP_ASSETS_PATH("encrypted")
|
||||
|
||||
#define PROTOPIRATE_CC1101_REG_FIFOTHR 0x03U
|
||||
#define PROTOPIRATE_CC1101_REG_FSCTRL1 0x07U
|
||||
#define PROTOPIRATE_CC1101_REG_MDMCFG4 0x10U
|
||||
#define PROTOPIRATE_CC1101_REG_MDMCFG3 0x11U
|
||||
#define PROTOPIRATE_CC1101_REG_MDMCFG2 0x12U
|
||||
#define PROTOPIRATE_CC1101_REG_DEVIATN 0x15U
|
||||
#define PROTOPIRATE_CC1101_REG_AGCCTRL2 0x1BU
|
||||
#define PROTOPIRATE_CC1101_REG_AGCCTRL1 0x1CU
|
||||
#define PROTOPIRATE_CC1101_REG_AGCCTRL0 0x1DU
|
||||
#define PROTOPIRATE_CC1101_REG_FREND1 0x21U
|
||||
#define PROTOPIRATE_CC1101_REG_TEST2 0x2CU
|
||||
#define PROTOPIRATE_CC1101_REG_TEST1 0x2DU
|
||||
#define GDR_CC1101_REG_FIFOTHR 0x03U
|
||||
#define GDR_CC1101_REG_FSCTRL1 0x07U
|
||||
#define GDR_CC1101_REG_MDMCFG4 0x10U
|
||||
#define GDR_CC1101_REG_MDMCFG3 0x11U
|
||||
#define GDR_CC1101_REG_MDMCFG2 0x12U
|
||||
#define GDR_CC1101_REG_DEVIATN 0x15U
|
||||
#define GDR_CC1101_REG_AGCCTRL2 0x1BU
|
||||
#define GDR_CC1101_REG_AGCCTRL1 0x1CU
|
||||
#define GDR_CC1101_REG_AGCCTRL0 0x1DU
|
||||
#define GDR_CC1101_REG_FREND1 0x21U
|
||||
#define GDR_CC1101_REG_TEST2 0x2CU
|
||||
#define GDR_CC1101_REG_TEST1 0x2DU
|
||||
|
||||
#define PROTOPIRATE_CC1101_CHANBW_135_KHZ_MASK 0xA0U
|
||||
#define PROTOPIRATE_CC1101_XTAL_HZ 26000000UL
|
||||
#define PROTOPIRATE_FM_BANDWIDTH_GUARD_HZ 50000UL
|
||||
#define GDR_CC1101_CHANBW_135_KHZ_MASK 0xA0U
|
||||
#define GDR_CC1101_XTAL_HZ 26000000UL
|
||||
#define GDR_FM_BANDWIDTH_GUARD_HZ 50000UL
|
||||
|
||||
#define PROTOPIRATE_CC1101_MOD_FORMAT_MASK 0x70U
|
||||
#define PROTOPIRATE_CC1101_MOD_FORMAT_2FSK 0x00U
|
||||
#define PROTOPIRATE_CC1101_MOD_FORMAT_GFSK 0x10U
|
||||
#define PROTOPIRATE_CC1101_MOD_FORMAT_OOK 0x30U
|
||||
#define GDR_CC1101_MOD_FORMAT_MASK 0x70U
|
||||
#define GDR_CC1101_MOD_FORMAT_2FSK 0x00U
|
||||
#define GDR_CC1101_MOD_FORMAT_GFSK 0x10U
|
||||
#define GDR_CC1101_MOD_FORMAT_OOK 0x30U
|
||||
|
||||
static bool protopirate_rx_chain_preset_get_register(
|
||||
static bool gdr_rx_chain_preset_get_register(
|
||||
const uint8_t* data,
|
||||
size_t size,
|
||||
uint8_t reg,
|
||||
@@ -53,7 +53,7 @@ static bool protopirate_rx_chain_preset_get_register(
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool protopirate_rx_chain_preset_set_register(
|
||||
static bool gdr_rx_chain_preset_set_register(
|
||||
uint8_t* data,
|
||||
size_t size,
|
||||
uint8_t reg,
|
||||
@@ -73,7 +73,7 @@ static bool protopirate_rx_chain_preset_set_register(
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool protopirate_rx_chain_preset_find_terminator(
|
||||
static bool gdr_rx_chain_preset_find_terminator(
|
||||
const uint8_t* data,
|
||||
size_t size,
|
||||
size_t* offset) {
|
||||
@@ -89,29 +89,29 @@ static bool protopirate_rx_chain_preset_find_terminator(
|
||||
return false;
|
||||
}
|
||||
|
||||
static uint32_t protopirate_rx_chain_channel_bandwidth_hz(uint8_t mdmcfg4) {
|
||||
static uint32_t gdr_rx_chain_channel_bandwidth_hz(uint8_t mdmcfg4) {
|
||||
uint8_t exponent = (mdmcfg4 >> 6U) & 0x03U;
|
||||
uint8_t mantissa = (mdmcfg4 >> 4U) & 0x03U;
|
||||
uint32_t denominator = 8UL * (4UL + mantissa) * (1UL << exponent);
|
||||
return PROTOPIRATE_CC1101_XTAL_HZ / denominator;
|
||||
return GDR_CC1101_XTAL_HZ / denominator;
|
||||
}
|
||||
|
||||
static uint32_t protopirate_rx_chain_data_rate_hz(uint8_t mdmcfg4, uint8_t mdmcfg3) {
|
||||
static uint32_t gdr_rx_chain_data_rate_hz(uint8_t mdmcfg4, uint8_t mdmcfg3) {
|
||||
uint8_t exponent = mdmcfg4 & 0x0FU;
|
||||
uint64_t numerator =
|
||||
(uint64_t)(256UL + mdmcfg3) * (1ULL << exponent) * PROTOPIRATE_CC1101_XTAL_HZ;
|
||||
(uint64_t)(256UL + mdmcfg3) * (1ULL << exponent) * GDR_CC1101_XTAL_HZ;
|
||||
return (uint32_t)((numerator + (1ULL << 27U)) >> 28U);
|
||||
}
|
||||
|
||||
static uint32_t protopirate_rx_chain_deviation_hz(uint8_t deviatn) {
|
||||
static uint32_t gdr_rx_chain_deviation_hz(uint8_t deviatn) {
|
||||
uint8_t exponent = (deviatn >> 4U) & 0x07U;
|
||||
uint8_t mantissa = deviatn & 0x07U;
|
||||
uint64_t numerator =
|
||||
(uint64_t)PROTOPIRATE_CC1101_XTAL_HZ * (8UL + mantissa) * (1ULL << exponent);
|
||||
(uint64_t)GDR_CC1101_XTAL_HZ * (8UL + mantissa) * (1ULL << exponent);
|
||||
return (uint32_t)((numerator + (1ULL << 16U)) >> 17U);
|
||||
}
|
||||
|
||||
static uint8_t protopirate_rx_chain_select_bandwidth_bits(
|
||||
static uint8_t gdr_rx_chain_select_bandwidth_bits(
|
||||
uint32_t minimum_hz,
|
||||
uint32_t* selected_hz) {
|
||||
static const uint8_t bandwidth_bits[] = {
|
||||
@@ -136,7 +136,7 @@ static uint8_t protopirate_rx_chain_select_bandwidth_bits(
|
||||
const size_t bandwidth_count = sizeof(bandwidth_bits) / sizeof(bandwidth_bits[0]);
|
||||
for(size_t i = 0; i < bandwidth_count; i++) {
|
||||
uint32_t bandwidth =
|
||||
protopirate_rx_chain_channel_bandwidth_hz((uint8_t)(bandwidth_bits[i] << 4U));
|
||||
gdr_rx_chain_channel_bandwidth_hz((uint8_t)(bandwidth_bits[i] << 4U));
|
||||
if(bandwidth >= minimum_hz) {
|
||||
if(selected_hz) {
|
||||
*selected_hz = bandwidth;
|
||||
@@ -146,30 +146,30 @@ static uint8_t protopirate_rx_chain_select_bandwidth_bits(
|
||||
}
|
||||
|
||||
if(selected_hz) {
|
||||
*selected_hz = protopirate_rx_chain_channel_bandwidth_hz(0x00U);
|
||||
*selected_hz = gdr_rx_chain_channel_bandwidth_hz(0x00U);
|
||||
}
|
||||
return 0x00U;
|
||||
}
|
||||
|
||||
static const char* protopirate_rx_chain_plugin_path(ProtoPirateProtocolRegistryFilter filter) {
|
||||
return (filter == ProtoPirateProtocolRegistryFilterFM) ?
|
||||
APP_ASSETS_PATH("plugins/protopirate_fm_plugin.fal") :
|
||||
APP_ASSETS_PATH("plugins/protopirate_am_plugin.fal");
|
||||
static const char* gdr_rx_chain_plugin_path(GDRProtocolRegistryFilter filter) {
|
||||
return (filter == GDRProtocolRegistryFilterFM) ?
|
||||
APP_ASSETS_PATH("plugins/gdr_fm_plugin.fal") :
|
||||
APP_ASSETS_PATH("plugins/gdr_am_plugin.fal");
|
||||
}
|
||||
|
||||
ProtoPirateRxChain* protopirate_rx_chain_alloc(char label) {
|
||||
ProtoPirateRxChain* chain = malloc(sizeof(ProtoPirateRxChain));
|
||||
GDRRxChain* gdr_rx_chain_alloc(char label) {
|
||||
GDRRxChain* chain = malloc(sizeof(GDRRxChain));
|
||||
furi_check(chain);
|
||||
memset(chain, 0, sizeof(ProtoPirateRxChain));
|
||||
memset(chain, 0, sizeof(GDRRxChain));
|
||||
chain->label = label;
|
||||
chain->preset.name = furi_string_alloc();
|
||||
furi_check(chain->preset.name);
|
||||
chain->state = ProtoPirateTxRxStateIDLE;
|
||||
chain->filter = ProtoPirateProtocolRegistryFilterAM;
|
||||
chain->state = GDRTxRxStateIDLE;
|
||||
chain->filter = GDRProtocolRegistryFilterAM;
|
||||
return chain;
|
||||
}
|
||||
|
||||
static void protopirate_rx_chain_unload_plugin(ProtoPirateRxChain* chain) {
|
||||
static void gdr_rx_chain_unload_plugin(GDRRxChain* chain) {
|
||||
chain->plugin = NULL;
|
||||
chain->registry = NULL;
|
||||
if(chain->plugin_manager) {
|
||||
@@ -182,13 +182,13 @@ static void protopirate_rx_chain_unload_plugin(ProtoPirateRxChain* chain) {
|
||||
}
|
||||
}
|
||||
|
||||
void protopirate_rx_chain_free(ProtoPirateRxChain* chain) {
|
||||
void gdr_rx_chain_free(GDRRxChain* chain) {
|
||||
if(!chain) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Make sure RX is stopped before tearing anything down.
|
||||
protopirate_rx_chain_stop(chain);
|
||||
gdr_rx_chain_stop(chain);
|
||||
|
||||
if(chain->receiver) {
|
||||
subghz_receiver_set_rx_callback(chain->receiver, NULL, NULL);
|
||||
@@ -210,7 +210,7 @@ void protopirate_rx_chain_free(ProtoPirateRxChain* chain) {
|
||||
chain->device = NULL;
|
||||
}
|
||||
|
||||
protopirate_rx_chain_unload_plugin(chain);
|
||||
gdr_rx_chain_unload_plugin(chain);
|
||||
|
||||
if(chain->environment) {
|
||||
subghz_environment_free(chain->environment);
|
||||
@@ -230,8 +230,8 @@ void protopirate_rx_chain_free(ProtoPirateRxChain* chain) {
|
||||
free(chain);
|
||||
}
|
||||
|
||||
bool protopirate_rx_chain_acquire_device(
|
||||
ProtoPirateRxChain* chain,
|
||||
bool gdr_rx_chain_acquire_device(
|
||||
GDRRxChain* chain,
|
||||
SubGhzRadioDeviceType type) {
|
||||
furi_check(chain);
|
||||
|
||||
@@ -258,8 +258,8 @@ bool protopirate_rx_chain_acquire_device(
|
||||
return true;
|
||||
}
|
||||
|
||||
bool protopirate_rx_chain_set_preset(
|
||||
ProtoPirateRxChain* chain,
|
||||
bool gdr_rx_chain_set_preset(
|
||||
GDRRxChain* chain,
|
||||
SubGhzSetting* setting,
|
||||
const char* preset_name,
|
||||
uint32_t frequency) {
|
||||
@@ -270,7 +270,7 @@ bool protopirate_rx_chain_set_preset(
|
||||
size_t preset_count = subghz_setting_get_preset_count(setting);
|
||||
for(size_t i = 0; i < preset_count; i++) {
|
||||
if(strcmp(subghz_setting_get_preset_name(setting, i), preset_name) == 0) {
|
||||
return protopirate_rx_chain_set_preset_data(
|
||||
return gdr_rx_chain_set_preset_data(
|
||||
chain,
|
||||
preset_name,
|
||||
subghz_setting_get_preset_data(setting, i),
|
||||
@@ -283,8 +283,8 @@ bool protopirate_rx_chain_set_preset(
|
||||
return false;
|
||||
}
|
||||
|
||||
bool protopirate_rx_chain_set_preset_data(
|
||||
ProtoPirateRxChain* chain,
|
||||
bool gdr_rx_chain_set_preset_data(
|
||||
GDRRxChain* chain,
|
||||
const char* preset_name,
|
||||
uint8_t* preset_data,
|
||||
size_t preset_data_size,
|
||||
@@ -310,57 +310,57 @@ bool protopirate_rx_chain_set_preset_data(
|
||||
chain->base_preset_data_size = preset_data_size;
|
||||
chain->frequency = frequency;
|
||||
chain->filter =
|
||||
protopirate_get_protocol_registry_filter_for_preset(preset_data, preset_data_size);
|
||||
gdr_get_protocol_registry_filter_for_preset(preset_data, preset_data_size);
|
||||
uint8_t mdmcfg4 = 0U;
|
||||
chain->rx_bandwidth_hz = protopirate_rx_chain_preset_get_register(
|
||||
chain->rx_bandwidth_hz = gdr_rx_chain_preset_get_register(
|
||||
preset_data,
|
||||
preset_data_size,
|
||||
PROTOPIRATE_CC1101_REG_MDMCFG4,
|
||||
GDR_CC1101_REG_MDMCFG4,
|
||||
&mdmcfg4) ?
|
||||
protopirate_rx_chain_channel_bandwidth_hz(mdmcfg4) :
|
||||
gdr_rx_chain_channel_bandwidth_hz(mdmcfg4) :
|
||||
0U;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool protopirate_rx_chain_apply_ook_shield_profile(ProtoPirateRxChain* chain) {
|
||||
static bool gdr_rx_chain_apply_ook_shield_profile(GDRRxChain* chain) {
|
||||
if(!chain->base_preset_data || chain->preset.data_size < 2U) {
|
||||
FURI_LOG_E(TAG, "[%c] cannot narrow RX BW without preset data", chain->label);
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t mdmcfg4 = 0U;
|
||||
if(!protopirate_rx_chain_preset_get_register(
|
||||
if(!gdr_rx_chain_preset_get_register(
|
||||
chain->base_preset_data,
|
||||
chain->base_preset_data_size,
|
||||
PROTOPIRATE_CC1101_REG_MDMCFG4,
|
||||
GDR_CC1101_REG_MDMCFG4,
|
||||
&mdmcfg4)) {
|
||||
FURI_LOG_W(TAG, "[%c] OOK preset missing MDMCFG4; retaining original", chain->label);
|
||||
return true;
|
||||
}
|
||||
|
||||
const uint8_t narrowed_mdmcfg4 =
|
||||
(uint8_t)((mdmcfg4 & 0x0FU) | PROTOPIRATE_CC1101_CHANBW_135_KHZ_MASK);
|
||||
(uint8_t)((mdmcfg4 & 0x0FU) | GDR_CC1101_CHANBW_135_KHZ_MASK);
|
||||
|
||||
const struct {
|
||||
uint8_t reg;
|
||||
uint8_t value;
|
||||
} narrow_registers[] = {
|
||||
{PROTOPIRATE_CC1101_REG_FIFOTHR, 0x47U},
|
||||
{PROTOPIRATE_CC1101_REG_FSCTRL1, 0x06U},
|
||||
{PROTOPIRATE_CC1101_REG_MDMCFG4, narrowed_mdmcfg4},
|
||||
{PROTOPIRATE_CC1101_REG_AGCCTRL2, 0x04U},
|
||||
{PROTOPIRATE_CC1101_REG_AGCCTRL1, 0x00U},
|
||||
{PROTOPIRATE_CC1101_REG_AGCCTRL0, 0x92U},
|
||||
{PROTOPIRATE_CC1101_REG_FREND1, 0x56U},
|
||||
{PROTOPIRATE_CC1101_REG_TEST2, 0x81U},
|
||||
{PROTOPIRATE_CC1101_REG_TEST1, 0x35U},
|
||||
{GDR_CC1101_REG_FIFOTHR, 0x47U},
|
||||
{GDR_CC1101_REG_FSCTRL1, 0x06U},
|
||||
{GDR_CC1101_REG_MDMCFG4, narrowed_mdmcfg4},
|
||||
{GDR_CC1101_REG_AGCCTRL2, 0x04U},
|
||||
{GDR_CC1101_REG_AGCCTRL1, 0x00U},
|
||||
{GDR_CC1101_REG_AGCCTRL0, 0x92U},
|
||||
{GDR_CC1101_REG_FREND1, 0x56U},
|
||||
{GDR_CC1101_REG_TEST2, 0x81U},
|
||||
{GDR_CC1101_REG_TEST1, 0x35U},
|
||||
};
|
||||
|
||||
const size_t register_count = sizeof(narrow_registers) / sizeof(narrow_registers[0]);
|
||||
size_t missing_count = 0U;
|
||||
for(size_t i = 0; i < register_count; i++) {
|
||||
uint8_t value = 0U;
|
||||
if(!protopirate_rx_chain_preset_get_register(
|
||||
if(!gdr_rx_chain_preset_get_register(
|
||||
chain->base_preset_data,
|
||||
chain->base_preset_data_size,
|
||||
narrow_registers[i].reg,
|
||||
@@ -370,7 +370,7 @@ static bool protopirate_rx_chain_apply_ook_shield_profile(ProtoPirateRxChain* ch
|
||||
}
|
||||
|
||||
size_t terminator_offset = 0U;
|
||||
if(!protopirate_rx_chain_preset_find_terminator(
|
||||
if(!gdr_rx_chain_preset_find_terminator(
|
||||
chain->base_preset_data, chain->base_preset_data_size, &terminator_offset)) {
|
||||
FURI_LOG_W(TAG, "[%c] OOK preset has no terminator; retaining original", chain->label);
|
||||
return true;
|
||||
@@ -387,7 +387,7 @@ static bool protopirate_rx_chain_apply_ook_shield_profile(ProtoPirateRxChain* ch
|
||||
size_t write_offset = terminator_offset;
|
||||
for(size_t i = 0; i < register_count; i++) {
|
||||
uint8_t value = 0U;
|
||||
if(!protopirate_rx_chain_preset_get_register(
|
||||
if(!gdr_rx_chain_preset_get_register(
|
||||
chain->base_preset_data,
|
||||
chain->base_preset_data_size,
|
||||
narrow_registers[i].reg,
|
||||
@@ -402,7 +402,7 @@ static bool protopirate_rx_chain_apply_ook_shield_profile(ProtoPirateRxChain* ch
|
||||
chain->base_preset_data_size - terminator_offset);
|
||||
|
||||
for(size_t i = 0; i < register_count; i++) {
|
||||
if(!protopirate_rx_chain_preset_set_register(
|
||||
if(!gdr_rx_chain_preset_set_register(
|
||||
copy, expanded_size, narrow_registers[i].reg, narrow_registers[i].value)) {
|
||||
FURI_LOG_E(TAG, "[%c] failed to patch narrow RX preset", chain->label);
|
||||
free(copy);
|
||||
@@ -414,55 +414,55 @@ static bool protopirate_rx_chain_apply_ook_shield_profile(ProtoPirateRxChain* ch
|
||||
chain->preset.data = copy;
|
||||
chain->preset.data_size = expanded_size;
|
||||
chain->rx_bandwidth_hz =
|
||||
protopirate_rx_chain_channel_bandwidth_hz(PROTOPIRATE_CC1101_CHANBW_135_KHZ_MASK);
|
||||
gdr_rx_chain_channel_bandwidth_hz(GDR_CC1101_CHANBW_135_KHZ_MASK);
|
||||
FURI_LOG_I(TAG, "[%c] applied TI 135 kHz OOK sensitivity profile", chain->label);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool protopirate_rx_chain_apply_fm_shield_profile(ProtoPirateRxChain* chain) {
|
||||
static bool gdr_rx_chain_apply_fm_shield_profile(GDRRxChain* chain) {
|
||||
uint8_t mdmcfg2 = 0U;
|
||||
uint8_t mdmcfg3 = 0U;
|
||||
uint8_t mdmcfg4 = 0U;
|
||||
uint8_t deviatn = 0U;
|
||||
if(!protopirate_rx_chain_preset_get_register(
|
||||
if(!gdr_rx_chain_preset_get_register(
|
||||
chain->base_preset_data,
|
||||
chain->base_preset_data_size,
|
||||
PROTOPIRATE_CC1101_REG_MDMCFG2,
|
||||
GDR_CC1101_REG_MDMCFG2,
|
||||
&mdmcfg2) ||
|
||||
!protopirate_rx_chain_preset_get_register(
|
||||
!gdr_rx_chain_preset_get_register(
|
||||
chain->base_preset_data,
|
||||
chain->base_preset_data_size,
|
||||
PROTOPIRATE_CC1101_REG_MDMCFG3,
|
||||
GDR_CC1101_REG_MDMCFG3,
|
||||
&mdmcfg3) ||
|
||||
!protopirate_rx_chain_preset_get_register(
|
||||
!gdr_rx_chain_preset_get_register(
|
||||
chain->base_preset_data,
|
||||
chain->base_preset_data_size,
|
||||
PROTOPIRATE_CC1101_REG_MDMCFG4,
|
||||
GDR_CC1101_REG_MDMCFG4,
|
||||
&mdmcfg4) ||
|
||||
!protopirate_rx_chain_preset_get_register(
|
||||
!gdr_rx_chain_preset_get_register(
|
||||
chain->base_preset_data,
|
||||
chain->base_preset_data_size,
|
||||
PROTOPIRATE_CC1101_REG_DEVIATN,
|
||||
GDR_CC1101_REG_DEVIATN,
|
||||
&deviatn)) {
|
||||
FURI_LOG_W(TAG, "[%c] incomplete FM preset; retaining original bandwidth", chain->label);
|
||||
return true;
|
||||
}
|
||||
|
||||
uint8_t modulation = mdmcfg2 & PROTOPIRATE_CC1101_MOD_FORMAT_MASK;
|
||||
if(modulation != PROTOPIRATE_CC1101_MOD_FORMAT_2FSK &&
|
||||
modulation != PROTOPIRATE_CC1101_MOD_FORMAT_GFSK) {
|
||||
uint8_t modulation = mdmcfg2 & GDR_CC1101_MOD_FORMAT_MASK;
|
||||
if(modulation != GDR_CC1101_MOD_FORMAT_2FSK &&
|
||||
modulation != GDR_CC1101_MOD_FORMAT_GFSK) {
|
||||
FURI_LOG_W(TAG, "[%c] unsupported FM format; retaining original bandwidth", chain->label);
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t data_rate = protopirate_rx_chain_data_rate_hz(mdmcfg4, mdmcfg3);
|
||||
uint32_t deviation = protopirate_rx_chain_deviation_hz(deviatn);
|
||||
uint32_t data_rate = gdr_rx_chain_data_rate_hz(mdmcfg4, mdmcfg3);
|
||||
uint32_t deviation = gdr_rx_chain_deviation_hz(deviatn);
|
||||
uint32_t minimum_bandwidth =
|
||||
data_rate + (2UL * deviation) + PROTOPIRATE_FM_BANDWIDTH_GUARD_HZ;
|
||||
data_rate + (2UL * deviation) + GDR_FM_BANDWIDTH_GUARD_HZ;
|
||||
uint32_t selected_bandwidth = 0U;
|
||||
uint8_t bandwidth_bits =
|
||||
protopirate_rx_chain_select_bandwidth_bits(minimum_bandwidth, &selected_bandwidth);
|
||||
uint32_t original_bandwidth = protopirate_rx_chain_channel_bandwidth_hz(mdmcfg4);
|
||||
gdr_rx_chain_select_bandwidth_bits(minimum_bandwidth, &selected_bandwidth);
|
||||
uint32_t original_bandwidth = gdr_rx_chain_channel_bandwidth_hz(mdmcfg4);
|
||||
|
||||
if(selected_bandwidth >= original_bandwidth) {
|
||||
chain->rx_bandwidth_hz = original_bandwidth;
|
||||
@@ -482,10 +482,10 @@ static bool protopirate_rx_chain_apply_fm_shield_profile(ProtoPirateRxChain* cha
|
||||
memcpy(copy, chain->base_preset_data, chain->base_preset_data_size);
|
||||
|
||||
uint8_t profiled_mdmcfg4 = (uint8_t)((mdmcfg4 & 0x0FU) | (bandwidth_bits << 4U));
|
||||
if(!protopirate_rx_chain_preset_set_register(
|
||||
if(!gdr_rx_chain_preset_set_register(
|
||||
copy,
|
||||
chain->base_preset_data_size,
|
||||
PROTOPIRATE_CC1101_REG_MDMCFG4,
|
||||
GDR_CC1101_REG_MDMCFG4,
|
||||
profiled_mdmcfg4)) {
|
||||
free(copy);
|
||||
return true;
|
||||
@@ -493,15 +493,15 @@ static bool protopirate_rx_chain_apply_fm_shield_profile(ProtoPirateRxChain* cha
|
||||
|
||||
if(selected_bandwidth <= 101562UL) {
|
||||
uint8_t agcctrl2 = 0U;
|
||||
if(protopirate_rx_chain_preset_get_register(
|
||||
if(gdr_rx_chain_preset_get_register(
|
||||
copy,
|
||||
chain->base_preset_data_size,
|
||||
PROTOPIRATE_CC1101_REG_AGCCTRL2,
|
||||
GDR_CC1101_REG_AGCCTRL2,
|
||||
&agcctrl2)) {
|
||||
protopirate_rx_chain_preset_set_register(
|
||||
gdr_rx_chain_preset_set_register(
|
||||
copy,
|
||||
chain->base_preset_data_size,
|
||||
PROTOPIRATE_CC1101_REG_AGCCTRL2,
|
||||
GDR_CC1101_REG_AGCCTRL2,
|
||||
(uint8_t)((agcctrl2 & 0xF8U) | 0x03U));
|
||||
}
|
||||
}
|
||||
@@ -520,7 +520,7 @@ static bool protopirate_rx_chain_apply_fm_shield_profile(ProtoPirateRxChain* cha
|
||||
return true;
|
||||
}
|
||||
|
||||
bool protopirate_rx_chain_apply_shield_profile(ProtoPirateRxChain* chain) {
|
||||
bool gdr_rx_chain_apply_shield_profile(GDRRxChain* chain) {
|
||||
furi_check(chain);
|
||||
|
||||
if(chain->owned_preset_data) {
|
||||
@@ -531,28 +531,28 @@ bool protopirate_rx_chain_apply_shield_profile(ProtoPirateRxChain* chain) {
|
||||
chain->preset.data_size = chain->base_preset_data_size;
|
||||
|
||||
uint8_t mdmcfg2 = 0U;
|
||||
if(!protopirate_rx_chain_preset_get_register(
|
||||
if(!gdr_rx_chain_preset_get_register(
|
||||
chain->base_preset_data,
|
||||
chain->base_preset_data_size,
|
||||
PROTOPIRATE_CC1101_REG_MDMCFG2,
|
||||
GDR_CC1101_REG_MDMCFG2,
|
||||
&mdmcfg2)) {
|
||||
FURI_LOG_W(TAG, "[%c] preset modulation unknown; retaining original", chain->label);
|
||||
return true;
|
||||
}
|
||||
|
||||
switch(mdmcfg2 & PROTOPIRATE_CC1101_MOD_FORMAT_MASK) {
|
||||
case PROTOPIRATE_CC1101_MOD_FORMAT_OOK:
|
||||
return protopirate_rx_chain_apply_ook_shield_profile(chain);
|
||||
case PROTOPIRATE_CC1101_MOD_FORMAT_2FSK:
|
||||
case PROTOPIRATE_CC1101_MOD_FORMAT_GFSK:
|
||||
return protopirate_rx_chain_apply_fm_shield_profile(chain);
|
||||
switch(mdmcfg2 & GDR_CC1101_MOD_FORMAT_MASK) {
|
||||
case GDR_CC1101_MOD_FORMAT_OOK:
|
||||
return gdr_rx_chain_apply_ook_shield_profile(chain);
|
||||
case GDR_CC1101_MOD_FORMAT_2FSK:
|
||||
case GDR_CC1101_MOD_FORMAT_GFSK:
|
||||
return gdr_rx_chain_apply_fm_shield_profile(chain);
|
||||
default:
|
||||
FURI_LOG_W(TAG, "[%c] no Shield profile for modulation; retaining original", chain->label);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool protopirate_rx_chain_init_receiver(ProtoPirateRxChain* chain) {
|
||||
bool gdr_rx_chain_init_receiver(GDRRxChain* chain) {
|
||||
furi_check(chain);
|
||||
|
||||
if(!chain->environment) {
|
||||
@@ -572,8 +572,8 @@ bool protopirate_rx_chain_init_receiver(ProtoPirateRxChain* chain) {
|
||||
composite_api_resolver_add(resolver, firmware_api_interface);
|
||||
|
||||
PluginManager* manager = plugin_manager_alloc(
|
||||
PROTOPIRATE_PROTOCOL_PLUGIN_APP_ID,
|
||||
PROTOPIRATE_PROTOCOL_PLUGIN_API_VERSION,
|
||||
GDR_PROTOCOL_PLUGIN_APP_ID,
|
||||
GDR_PROTOCOL_PLUGIN_API_VERSION,
|
||||
composite_api_resolver_get(resolver));
|
||||
if(!manager) {
|
||||
FURI_LOG_E(TAG, "[%c] Failed to allocate plugin manager", chain->label);
|
||||
@@ -581,7 +581,7 @@ bool protopirate_rx_chain_init_receiver(ProtoPirateRxChain* chain) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const char* plugin_path = protopirate_rx_chain_plugin_path(chain->filter);
|
||||
const char* plugin_path = gdr_rx_chain_plugin_path(chain->filter);
|
||||
PluginManagerError error = plugin_manager_load_single(manager, plugin_path);
|
||||
if(error != PluginManagerErrorNone) {
|
||||
FURI_LOG_E(TAG, "[%c] Failed to load plugin %s: %d", chain->label, plugin_path, (int)error);
|
||||
@@ -590,7 +590,7 @@ bool protopirate_rx_chain_init_receiver(ProtoPirateRxChain* chain) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const ProtoPirateProtocolPlugin* plugin = plugin_manager_get_ep(manager, 0U);
|
||||
const GDRProtocolPlugin* plugin = plugin_manager_get_ep(manager, 0U);
|
||||
if(!plugin || !plugin->registry || plugin->filter != chain->filter) {
|
||||
FURI_LOG_E(TAG, "[%c] Invalid plugin entry point", chain->label);
|
||||
plugin_manager_free(manager);
|
||||
@@ -606,8 +606,8 @@ bool protopirate_rx_chain_init_receiver(ProtoPirateRxChain* chain) {
|
||||
|
||||
subghz_environment_set_protocol_registry(chain->environment, chain->registry);
|
||||
|
||||
subghz_environment_load_keystore(chain->environment, PROTOPIRATE_CHAIN_KEYSTORE_DIR);
|
||||
protopirate_keys_load(chain->environment);
|
||||
subghz_environment_load_keystore(chain->environment, GDR_CHAIN_KEYSTORE_DIR);
|
||||
gdr_keys_load(chain->environment);
|
||||
|
||||
if(!chain->receiver) {
|
||||
chain->receiver = subghz_receiver_alloc_init(chain->environment);
|
||||
@@ -634,8 +634,8 @@ bool protopirate_rx_chain_init_receiver(ProtoPirateRxChain* chain) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void protopirate_rx_chain_set_decode_callback(
|
||||
ProtoPirateRxChain* chain,
|
||||
void gdr_rx_chain_set_decode_callback(
|
||||
GDRRxChain* chain,
|
||||
SubGhzReceiverCallback callback,
|
||||
void* context) {
|
||||
furi_check(chain);
|
||||
@@ -643,13 +643,13 @@ void protopirate_rx_chain_set_decode_callback(
|
||||
subghz_receiver_set_rx_callback(chain->receiver, callback, context);
|
||||
}
|
||||
|
||||
bool protopirate_rx_chain_start(ProtoPirateRxChain* chain) {
|
||||
bool gdr_rx_chain_start(GDRRxChain* chain) {
|
||||
furi_check(chain);
|
||||
if(!chain->device || !chain->worker || !chain->receiver) {
|
||||
FURI_LOG_E(TAG, "[%c] start rejected (incomplete stack)", chain->label);
|
||||
return false;
|
||||
}
|
||||
if(chain->state == ProtoPirateTxRxStateRx) {
|
||||
if(chain->state == GDRTxRxStateRx) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -669,16 +669,16 @@ bool protopirate_rx_chain_start(ProtoPirateRxChain* chain) {
|
||||
|
||||
subghz_devices_start_async_rx(chain->device, subghz_worker_rx_callback, chain->worker);
|
||||
subghz_worker_start(chain->worker);
|
||||
chain->state = ProtoPirateTxRxStateRx;
|
||||
chain->state = GDRTxRxStateRx;
|
||||
FURI_LOG_I(TAG, "[%c] RX started on %lu Hz", chain->label, chain->frequency);
|
||||
return true;
|
||||
}
|
||||
|
||||
void protopirate_rx_chain_stop(ProtoPirateRxChain* chain) {
|
||||
void gdr_rx_chain_stop(GDRRxChain* chain) {
|
||||
if(!chain) {
|
||||
return;
|
||||
}
|
||||
if(chain->state != ProtoPirateTxRxStateRx) {
|
||||
if(chain->state != GDRTxRxStateRx) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -689,12 +689,12 @@ void protopirate_rx_chain_stop(ProtoPirateRxChain* chain) {
|
||||
subghz_devices_stop_async_rx(chain->device);
|
||||
subghz_devices_idle(chain->device);
|
||||
}
|
||||
chain->state = ProtoPirateTxRxStateIDLE;
|
||||
chain->state = GDRTxRxStateIDLE;
|
||||
}
|
||||
|
||||
float protopirate_rx_chain_get_rssi(ProtoPirateRxChain* chain) {
|
||||
float gdr_rx_chain_get_rssi(GDRRxChain* chain) {
|
||||
furi_check(chain);
|
||||
if(!chain->device || chain->state != ProtoPirateTxRxStateRx) {
|
||||
if(!chain->device || chain->state != GDRTxRxStateRx) {
|
||||
return -127.0f;
|
||||
}
|
||||
return subghz_devices_get_rssi(chain->device);
|
||||
+22
-22
@@ -1,7 +1,7 @@
|
||||
// helpers/protopirate_rx_chain.h
|
||||
// helpers/gdr_rx_chain.h
|
||||
#pragma once
|
||||
|
||||
#include "protopirate_types.h"
|
||||
#include "gdr_types.h"
|
||||
|
||||
#if defined(ENABLE_DUAL_RX_SCENE) || defined(ENABLE_SHIELD_RX_SCENE)
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
#include "radio_device_loader.h"
|
||||
#include "../protocols/protocol_items.h"
|
||||
#include "../protocols/protopirate_protocol_plugins.h"
|
||||
#include "../protocols/gdr_protocol_plugins.h"
|
||||
|
||||
typedef struct {
|
||||
char label; // 'A' or 'B' (display tag)
|
||||
@@ -28,9 +28,9 @@ typedef struct {
|
||||
|
||||
CompositeApiResolver* resolver;
|
||||
PluginManager* plugin_manager;
|
||||
const ProtoPirateProtocolPlugin* plugin;
|
||||
const GDRProtocolPlugin* plugin;
|
||||
const SubGhzProtocolRegistry* registry;
|
||||
ProtoPirateProtocolRegistryFilter filter;
|
||||
GDRProtocolRegistryFilter filter;
|
||||
|
||||
SubGhzRadioPreset preset; // .name is an owned FuriString
|
||||
uint8_t* base_preset_data;
|
||||
@@ -40,43 +40,43 @@ typedef struct {
|
||||
uint32_t frequency;
|
||||
uint32_t rx_bandwidth_hz;
|
||||
|
||||
ProtoPirateTxRxState state;
|
||||
} ProtoPirateRxChain;
|
||||
GDRTxRxState state;
|
||||
} GDRRxChain;
|
||||
|
||||
ProtoPirateRxChain* protopirate_rx_chain_alloc(char label);
|
||||
GDRRxChain* gdr_rx_chain_alloc(char label);
|
||||
|
||||
void protopirate_rx_chain_free(ProtoPirateRxChain* chain);
|
||||
void gdr_rx_chain_free(GDRRxChain* chain);
|
||||
|
||||
bool protopirate_rx_chain_acquire_device(
|
||||
ProtoPirateRxChain* chain,
|
||||
bool gdr_rx_chain_acquire_device(
|
||||
GDRRxChain* chain,
|
||||
SubGhzRadioDeviceType type);
|
||||
|
||||
bool protopirate_rx_chain_set_preset(
|
||||
ProtoPirateRxChain* chain,
|
||||
bool gdr_rx_chain_set_preset(
|
||||
GDRRxChain* chain,
|
||||
SubGhzSetting* setting,
|
||||
const char* preset_name,
|
||||
uint32_t frequency);
|
||||
|
||||
bool protopirate_rx_chain_set_preset_data(
|
||||
ProtoPirateRxChain* chain,
|
||||
bool gdr_rx_chain_set_preset_data(
|
||||
GDRRxChain* chain,
|
||||
const char* preset_name,
|
||||
uint8_t* preset_data,
|
||||
size_t preset_data_size,
|
||||
uint32_t frequency);
|
||||
|
||||
bool protopirate_rx_chain_apply_shield_profile(ProtoPirateRxChain* chain);
|
||||
bool gdr_rx_chain_apply_shield_profile(GDRRxChain* chain);
|
||||
|
||||
bool protopirate_rx_chain_init_receiver(ProtoPirateRxChain* chain);
|
||||
bool gdr_rx_chain_init_receiver(GDRRxChain* chain);
|
||||
|
||||
void protopirate_rx_chain_set_decode_callback(
|
||||
ProtoPirateRxChain* chain,
|
||||
void gdr_rx_chain_set_decode_callback(
|
||||
GDRRxChain* chain,
|
||||
SubGhzReceiverCallback callback,
|
||||
void* context);
|
||||
|
||||
bool protopirate_rx_chain_start(ProtoPirateRxChain* chain);
|
||||
bool gdr_rx_chain_start(GDRRxChain* chain);
|
||||
|
||||
void protopirate_rx_chain_stop(ProtoPirateRxChain* chain);
|
||||
void gdr_rx_chain_stop(GDRRxChain* chain);
|
||||
|
||||
float protopirate_rx_chain_get_rssi(ProtoPirateRxChain* chain);
|
||||
float gdr_rx_chain_get_rssi(GDRRxChain* chain);
|
||||
|
||||
#endif // ENABLE_DUAL_RX_SCENE || ENABLE_SHIELD_RX_SCENE
|
||||
+11
-11
@@ -1,5 +1,5 @@
|
||||
// helpers/protopirate_settings.c
|
||||
#include "protopirate_settings.h"
|
||||
// helpers/gdr_settings.c
|
||||
#include "gdr_settings.h"
|
||||
#include <storage/storage.h>
|
||||
#include <flipper_format/flipper_format.h>
|
||||
#include <furi.h>
|
||||
@@ -7,12 +7,12 @@
|
||||
#include "../defines.h"
|
||||
#include "../protocols/protocols_common.h"
|
||||
|
||||
#define TAG "ProtoPirateSettings"
|
||||
#define TAG "GDRSettings"
|
||||
|
||||
#define SETTINGS_FILE_HEADER "ProtoPirate Settings"
|
||||
#define SETTINGS_FILE_HEADER "GDR Settings"
|
||||
#define SETTINGS_FILE_VERSION 1
|
||||
|
||||
void protopirate_settings_set_defaults(ProtoPirateSettings* settings) {
|
||||
void gdr_settings_set_defaults(GDRSettings* settings) {
|
||||
settings->frequency = 433920000;
|
||||
settings->preset_index = 0;
|
||||
settings->tx_power = 0;
|
||||
@@ -31,15 +31,15 @@ void protopirate_settings_set_defaults(ProtoPirateSettings* settings) {
|
||||
settings->shield_tx_power = 0;
|
||||
}
|
||||
|
||||
void protopirate_settings_load(ProtoPirateSettings* settings) {
|
||||
void gdr_settings_load(GDRSettings* settings) {
|
||||
// Set defaults first
|
||||
protopirate_settings_set_defaults(settings);
|
||||
gdr_settings_set_defaults(settings);
|
||||
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
FlipperFormat* ff = flipper_format_file_alloc(storage);
|
||||
|
||||
do {
|
||||
if(!flipper_format_file_open_existing(ff, PROTOPIRATE_SETTINGS_FILE)) {
|
||||
if(!flipper_format_file_open_existing(ff, GDR_SETTINGS_FILE)) {
|
||||
FURI_LOG_I(TAG, "Settings file not found, using defaults");
|
||||
break;
|
||||
}
|
||||
@@ -177,16 +177,16 @@ void protopirate_settings_load(ProtoPirateSettings* settings) {
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
}
|
||||
|
||||
void protopirate_settings_save(ProtoPirateSettings* settings) {
|
||||
void gdr_settings_save(GDRSettings* settings) {
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
|
||||
// Ensure directory exists
|
||||
storage_simply_mkdir(storage, PROTOPIRATE_SETTINGS_DIR);
|
||||
storage_simply_mkdir(storage, GDR_SETTINGS_DIR);
|
||||
|
||||
FlipperFormat* ff = flipper_format_file_alloc(storage);
|
||||
|
||||
do {
|
||||
if(!flipper_format_file_open_always(ff, PROTOPIRATE_SETTINGS_FILE)) {
|
||||
if(!flipper_format_file_open_always(ff, GDR_SETTINGS_FILE)) {
|
||||
FURI_LOG_E(TAG, "Failed to open settings file for writing");
|
||||
break;
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
// helpers/gdr_settings.h
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#define GDR_SETTINGS_FILE APP_DATA_PATH("settings.txt")
|
||||
#define GDR_SETTINGS_DIR APP_DATA_PATH()
|
||||
#define GDR_PRESET_NAME_MAX 64U
|
||||
|
||||
typedef struct {
|
||||
uint32_t frequency;
|
||||
uint8_t preset_index;
|
||||
uint8_t tx_power;
|
||||
bool auto_save;
|
||||
bool hopping_enabled;
|
||||
bool emulate_feature_enabled;
|
||||
uint32_t dual_freq_a;
|
||||
uint32_t dual_freq_b;
|
||||
uint8_t dual_preset_a;
|
||||
uint8_t dual_preset_b;
|
||||
char dual_preset_name_a[GDR_PRESET_NAME_MAX];
|
||||
char dual_preset_name_b[GDR_PRESET_NAME_MAX];
|
||||
uint32_t shield_freq;
|
||||
uint8_t shield_preset_index;
|
||||
uint8_t shield_tx_offset_index;
|
||||
uint8_t shield_tx_power;
|
||||
} GDRSettings;
|
||||
|
||||
void gdr_settings_load(GDRSettings* settings);
|
||||
void gdr_settings_save(GDRSettings* settings);
|
||||
void gdr_settings_set_defaults(GDRSettings* settings);
|
||||
+101
-101
@@ -1,70 +1,70 @@
|
||||
// helpers/protopirate_storage.c
|
||||
#include "protopirate_storage.h"
|
||||
// helpers/gdr_storage.c
|
||||
#include "gdr_storage.h"
|
||||
#include "../defines.h"
|
||||
#include "../protocols/protocols_common.h"
|
||||
|
||||
#define TAG "ProtoPirateStorage"
|
||||
#define TAG "GDRStorage"
|
||||
|
||||
bool protopirate_storage_init(void) {
|
||||
bool gdr_storage_init(void) {
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
bool result = storage_simply_mkdir(storage, PROTOPIRATE_APP_FOLDER);
|
||||
bool result = storage_simply_mkdir(storage, GDR_APP_FOLDER);
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
return result;
|
||||
}
|
||||
|
||||
void protopirate_storage_wipe_history_cache(void) {
|
||||
void gdr_storage_wipe_history_cache(void) {
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
if(storage_dir_exists(storage, PROTOPIRATE_HISTORY_FOLDER)) {
|
||||
storage_simply_remove_recursive(storage, PROTOPIRATE_HISTORY_FOLDER);
|
||||
if(storage_dir_exists(storage, GDR_HISTORY_FOLDER)) {
|
||||
storage_simply_remove_recursive(storage, GDR_HISTORY_FOLDER);
|
||||
FURI_LOG_I(TAG, "Wiped history cache");
|
||||
}
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
}
|
||||
|
||||
void protopirate_storage_purge_temp_history_at_startup(void) {
|
||||
void gdr_storage_purge_temp_history_at_startup(void) {
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
if(storage_dir_exists(storage, PROTOPIRATE_HISTORY_FOLDER)) {
|
||||
storage_simply_remove_recursive(storage, PROTOPIRATE_HISTORY_FOLDER);
|
||||
if(storage_dir_exists(storage, GDR_HISTORY_FOLDER)) {
|
||||
storage_simply_remove_recursive(storage, GDR_HISTORY_FOLDER);
|
||||
}
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
}
|
||||
|
||||
bool protopirate_storage_ensure_history_folder(void) {
|
||||
if(!protopirate_storage_init()) {
|
||||
bool gdr_storage_ensure_history_folder(void) {
|
||||
if(!gdr_storage_init()) {
|
||||
return false;
|
||||
}
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
storage_simply_mkdir(storage, PROTOPIRATE_CACHE_FOLDER);
|
||||
bool ok = storage_simply_mkdir(storage, PROTOPIRATE_HISTORY_FOLDER);
|
||||
storage_simply_mkdir(storage, GDR_CACHE_FOLDER);
|
||||
bool ok = storage_simply_mkdir(storage, GDR_HISTORY_FOLDER);
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
return ok;
|
||||
}
|
||||
|
||||
void protopirate_storage_build_history_path(uint32_t seq, FuriString* out) {
|
||||
void gdr_storage_build_history_path(uint32_t seq, FuriString* out) {
|
||||
furi_check(out);
|
||||
furi_string_printf(
|
||||
out,
|
||||
"%s/hist_%08lu%s",
|
||||
PROTOPIRATE_HISTORY_FOLDER,
|
||||
GDR_HISTORY_FOLDER,
|
||||
(unsigned long)seq,
|
||||
PROTOPIRATE_APP_EXTENSION);
|
||||
GDR_APP_EXTENSION);
|
||||
}
|
||||
|
||||
bool protopirate_storage_save_history_capture(
|
||||
bool gdr_storage_save_history_capture(
|
||||
FlipperFormat* flipper_format,
|
||||
uint32_t seq,
|
||||
FuriString* out_path) {
|
||||
furi_check(flipper_format);
|
||||
furi_check(out_path);
|
||||
|
||||
if(!protopirate_storage_ensure_history_folder()) {
|
||||
if(!gdr_storage_ensure_history_folder()) {
|
||||
FURI_LOG_E(TAG, "History folder missing");
|
||||
return false;
|
||||
}
|
||||
|
||||
protopirate_storage_build_history_path(seq, out_path);
|
||||
gdr_storage_build_history_path(seq, out_path);
|
||||
|
||||
return protopirate_storage_save_capture_to_path(
|
||||
return gdr_storage_save_capture_to_path(
|
||||
flipper_format, furi_string_get_cstr(out_path));
|
||||
}
|
||||
|
||||
@@ -90,7 +90,7 @@ static void sanitize_filename(const char* input, char* output, size_t output_siz
|
||||
output[j] = '\0';
|
||||
}
|
||||
|
||||
bool protopirate_storage_get_next_filename(const char* protocol_name, FuriString* out_filename) {
|
||||
bool gdr_storage_get_next_filename(const char* protocol_name, FuriString* out_filename) {
|
||||
if(!protocol_name || !out_filename) return false;
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
FuriString* temp_path = furi_string_alloc();
|
||||
@@ -104,10 +104,10 @@ bool protopirate_storage_get_next_filename(const char* protocol_name, FuriString
|
||||
furi_string_printf(
|
||||
temp_path,
|
||||
"%s/%s_%03lu%s",
|
||||
PROTOPIRATE_APP_FOLDER,
|
||||
GDR_APP_FOLDER,
|
||||
safe_name,
|
||||
(unsigned long)index,
|
||||
PROTOPIRATE_APP_EXTENSION);
|
||||
GDR_APP_EXTENSION);
|
||||
|
||||
if(!storage_file_exists(storage, furi_string_get_cstr(temp_path))) {
|
||||
furi_string_set(out_filename, temp_path);
|
||||
@@ -122,7 +122,7 @@ bool protopirate_storage_get_next_filename(const char* protocol_name, FuriString
|
||||
return found;
|
||||
}
|
||||
|
||||
static const char* const protopirate_storage_base_u32_fields[] = {
|
||||
static const char* const gdr_storage_base_u32_fields[] = {
|
||||
"TE",
|
||||
FF_SERIAL,
|
||||
FF_BTN,
|
||||
@@ -137,7 +137,7 @@ static const char* const protopirate_storage_base_u32_fields[] = {
|
||||
FF_TYPE,
|
||||
};
|
||||
|
||||
static const char* const protopirate_storage_tail_u32_fields[] = {
|
||||
static const char* const gdr_storage_tail_u32_fields[] = {
|
||||
"DataHi",
|
||||
"DataLo",
|
||||
"RawCnt",
|
||||
@@ -147,7 +147,7 @@ static const char* const protopirate_storage_tail_u32_fields[] = {
|
||||
"Checksum",
|
||||
};
|
||||
|
||||
static bool protopirate_storage_fail(const char* action, const char* key) {
|
||||
static bool gdr_storage_fail(const char* action, const char* key) {
|
||||
UNUSED(action);
|
||||
UNUSED(key);
|
||||
FURI_LOG_E(TAG, "%s failed: %s", action, key);
|
||||
@@ -155,13 +155,13 @@ static bool protopirate_storage_fail(const char* action, const char* key) {
|
||||
}
|
||||
|
||||
static bool
|
||||
protopirate_storage_get_count(FlipperFormat* flipper_format, const char* key, uint32_t* count) {
|
||||
gdr_storage_get_count(FlipperFormat* flipper_format, const char* key, uint32_t* count) {
|
||||
*count = 0;
|
||||
flipper_format_rewind(flipper_format);
|
||||
return flipper_format_get_value_count(flipper_format, key, count) && (*count > 0);
|
||||
}
|
||||
|
||||
static bool protopirate_storage_copy_string_optional(
|
||||
static bool gdr_storage_copy_string_optional(
|
||||
FlipperFormat* save_file,
|
||||
FlipperFormat* flipper_format,
|
||||
const char* key,
|
||||
@@ -171,30 +171,30 @@ static bool protopirate_storage_copy_string_optional(
|
||||
return true;
|
||||
}
|
||||
if(!flipper_format_write_string(save_file, key, value)) {
|
||||
return protopirate_storage_fail("Write", key);
|
||||
return gdr_storage_fail("Write", key);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool protopirate_storage_copy_string_if_present(
|
||||
static bool gdr_storage_copy_string_if_present(
|
||||
FlipperFormat* save_file,
|
||||
FlipperFormat* flipper_format,
|
||||
const char* key,
|
||||
FuriString* value) {
|
||||
uint32_t count = 0;
|
||||
if(!protopirate_storage_get_count(flipper_format, key, &count)) {
|
||||
if(!gdr_storage_get_count(flipper_format, key, &count)) {
|
||||
return true;
|
||||
}
|
||||
if(!flipper_format_read_string(flipper_format, key, value)) {
|
||||
return protopirate_storage_fail("Read", key);
|
||||
return gdr_storage_fail("Read", key);
|
||||
}
|
||||
if(!flipper_format_write_string(save_file, key, value)) {
|
||||
return protopirate_storage_fail("Write", key);
|
||||
return gdr_storage_fail("Write", key);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool protopirate_storage_copy_u32_optional(
|
||||
static bool gdr_storage_copy_u32_optional(
|
||||
FlipperFormat* save_file,
|
||||
FlipperFormat* flipper_format,
|
||||
const char* key) {
|
||||
@@ -204,25 +204,25 @@ static bool protopirate_storage_copy_u32_optional(
|
||||
return true;
|
||||
}
|
||||
if(!flipper_format_write_uint32(save_file, key, &value, 1)) {
|
||||
return protopirate_storage_fail("Write", key);
|
||||
return gdr_storage_fail("Write", key);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool protopirate_storage_copy_u32_fields(
|
||||
static bool gdr_storage_copy_u32_fields(
|
||||
FlipperFormat* save_file,
|
||||
FlipperFormat* flipper_format,
|
||||
const char* const* fields,
|
||||
size_t field_count) {
|
||||
for(size_t i = 0; i < field_count; i++) {
|
||||
if(!protopirate_storage_copy_u32_optional(save_file, flipper_format, fields[i])) {
|
||||
if(!gdr_storage_copy_u32_optional(save_file, flipper_format, fields[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool protopirate_storage_copy_hex_fixed(
|
||||
static bool gdr_storage_copy_hex_fixed(
|
||||
FlipperFormat* save_file,
|
||||
FlipperFormat* flipper_format,
|
||||
const char* key,
|
||||
@@ -242,12 +242,12 @@ static bool protopirate_storage_copy_hex_fixed(
|
||||
*copied = true;
|
||||
}
|
||||
if(!flipper_format_write_hex(save_file, key, data, len)) {
|
||||
return protopirate_storage_fail("Write", key);
|
||||
return gdr_storage_fail("Write", key);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool protopirate_storage_copy_u32_array(
|
||||
static bool gdr_storage_copy_u32_array(
|
||||
FlipperFormat* save_file,
|
||||
FlipperFormat* flipper_format,
|
||||
const char* key,
|
||||
@@ -267,9 +267,9 @@ static bool protopirate_storage_copy_u32_array(
|
||||
bool status = false;
|
||||
flipper_format_rewind(flipper_format);
|
||||
if(!flipper_format_read_uint32(flipper_format, key, data, count)) {
|
||||
protopirate_storage_fail("Read", key);
|
||||
gdr_storage_fail("Read", key);
|
||||
} else if(!flipper_format_write_uint32(save_file, key, data, count)) {
|
||||
protopirate_storage_fail("Write", key);
|
||||
gdr_storage_fail("Write", key);
|
||||
} else {
|
||||
status = true;
|
||||
}
|
||||
@@ -278,25 +278,25 @@ static bool protopirate_storage_copy_u32_array(
|
||||
return status;
|
||||
}
|
||||
|
||||
static bool protopirate_storage_copy_u32_array_if_present(
|
||||
static bool gdr_storage_copy_u32_array_if_present(
|
||||
FlipperFormat* save_file,
|
||||
FlipperFormat* flipper_format,
|
||||
const char* key,
|
||||
uint32_t max_count) {
|
||||
uint32_t count = 0;
|
||||
if(!protopirate_storage_get_count(flipper_format, key, &count)) {
|
||||
if(!gdr_storage_get_count(flipper_format, key, &count)) {
|
||||
return true;
|
||||
}
|
||||
return protopirate_storage_copy_u32_array(save_file, flipper_format, key, count, max_count);
|
||||
return gdr_storage_copy_u32_array(save_file, flipper_format, key, count, max_count);
|
||||
}
|
||||
|
||||
static bool protopirate_storage_copy_hex_array_if_present(
|
||||
static bool gdr_storage_copy_hex_array_if_present(
|
||||
FlipperFormat* save_file,
|
||||
FlipperFormat* flipper_format,
|
||||
const char* key,
|
||||
uint32_t max_count) {
|
||||
uint32_t count = 0;
|
||||
if(!protopirate_storage_get_count(flipper_format, key, &count)) {
|
||||
if(!gdr_storage_get_count(flipper_format, key, &count)) {
|
||||
return true;
|
||||
}
|
||||
if(count >= max_count) {
|
||||
@@ -313,9 +313,9 @@ static bool protopirate_storage_copy_hex_array_if_present(
|
||||
bool status = false;
|
||||
flipper_format_rewind(flipper_format);
|
||||
if(!flipper_format_read_hex(flipper_format, key, data, count)) {
|
||||
protopirate_storage_fail("Read", key);
|
||||
gdr_storage_fail("Read", key);
|
||||
} else if(!flipper_format_write_hex(save_file, key, data, count)) {
|
||||
protopirate_storage_fail("Write", key);
|
||||
gdr_storage_fail("Write", key);
|
||||
} else {
|
||||
status = true;
|
||||
}
|
||||
@@ -324,7 +324,7 @@ static bool protopirate_storage_copy_hex_array_if_present(
|
||||
return status;
|
||||
}
|
||||
|
||||
static bool protopirate_storage_copy_key(
|
||||
static bool gdr_storage_copy_key(
|
||||
FlipperFormat* save_file,
|
||||
FlipperFormat* flipper_format,
|
||||
FuriString* value) {
|
||||
@@ -333,46 +333,46 @@ static bool protopirate_storage_copy_key(
|
||||
flipper_format_rewind(flipper_format);
|
||||
if(flipper_format_read_string(flipper_format, FF_KEY, value)) {
|
||||
if(!flipper_format_write_string(save_file, FF_KEY, value)) {
|
||||
return protopirate_storage_fail("Write", FF_KEY);
|
||||
return gdr_storage_fail("Write", FF_KEY);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if(protopirate_storage_get_count(flipper_format, FF_KEY, &count)) {
|
||||
return protopirate_storage_copy_u32_array(save_file, flipper_format, FF_KEY, count, 1024);
|
||||
if(gdr_storage_get_count(flipper_format, FF_KEY, &count)) {
|
||||
return gdr_storage_copy_u32_array(save_file, flipper_format, FF_KEY, count, 1024);
|
||||
}
|
||||
|
||||
return protopirate_storage_copy_hex_fixed(save_file, flipper_format, FF_KEY, 8, NULL);
|
||||
return gdr_storage_copy_hex_fixed(save_file, flipper_format, FF_KEY, 8, NULL);
|
||||
}
|
||||
|
||||
static bool protopirate_storage_copy_hex_or_u32(
|
||||
static bool gdr_storage_copy_hex_or_u32(
|
||||
FlipperFormat* save_file,
|
||||
FlipperFormat* flipper_format,
|
||||
const char* key,
|
||||
size_t hex_len) {
|
||||
bool copied = false;
|
||||
if(!protopirate_storage_copy_hex_fixed(save_file, flipper_format, key, hex_len, &copied)) {
|
||||
if(!gdr_storage_copy_hex_fixed(save_file, flipper_format, key, hex_len, &copied)) {
|
||||
return false;
|
||||
}
|
||||
return copied || protopirate_storage_copy_u32_optional(save_file, flipper_format, key);
|
||||
return copied || gdr_storage_copy_u32_optional(save_file, flipper_format, key);
|
||||
}
|
||||
|
||||
static bool protopirate_storage_copy_key_2(
|
||||
static bool gdr_storage_copy_key_2(
|
||||
FlipperFormat* save_file,
|
||||
FlipperFormat* flipper_format,
|
||||
FuriString* value) {
|
||||
bool copied = false;
|
||||
if(!protopirate_storage_copy_hex_fixed(save_file, flipper_format, "Key_2", 8, &copied)) {
|
||||
if(!gdr_storage_copy_hex_fixed(save_file, flipper_format, "Key_2", 8, &copied)) {
|
||||
return false;
|
||||
}
|
||||
if(copied) {
|
||||
return true;
|
||||
}
|
||||
return protopirate_storage_copy_string_optional(save_file, flipper_format, "Key_2", value) &&
|
||||
protopirate_storage_copy_u32_optional(save_file, flipper_format, "Key_2");
|
||||
return gdr_storage_copy_string_optional(save_file, flipper_format, "Key_2", value) &&
|
||||
gdr_storage_copy_u32_optional(save_file, flipper_format, "Key_2");
|
||||
}
|
||||
|
||||
static bool protopirate_storage_write_capture_data(
|
||||
static bool gdr_storage_write_capture_data(
|
||||
FlipperFormat* save_file,
|
||||
FlipperFormat* flipper_format) {
|
||||
furi_check(save_file);
|
||||
@@ -386,51 +386,51 @@ static bool protopirate_storage_write_capture_data(
|
||||
|
||||
bool status = false;
|
||||
do {
|
||||
if(!protopirate_storage_copy_string_optional(
|
||||
if(!gdr_storage_copy_string_optional(
|
||||
save_file, flipper_format, FF_PROTOCOL, string_value))
|
||||
break;
|
||||
if(!protopirate_storage_copy_u32_optional(save_file, flipper_format, FF_BIT)) break;
|
||||
if(!protopirate_storage_copy_key(save_file, flipper_format, string_value)) break;
|
||||
if(!protopirate_storage_copy_u32_optional(save_file, flipper_format, FF_FREQUENCY)) break;
|
||||
if(!protopirate_storage_copy_string_optional(
|
||||
if(!gdr_storage_copy_u32_optional(save_file, flipper_format, FF_BIT)) break;
|
||||
if(!gdr_storage_copy_key(save_file, flipper_format, string_value)) break;
|
||||
if(!gdr_storage_copy_u32_optional(save_file, flipper_format, FF_FREQUENCY)) break;
|
||||
if(!gdr_storage_copy_string_optional(
|
||||
save_file, flipper_format, FF_PRESET, string_value))
|
||||
break;
|
||||
if(!protopirate_storage_copy_string_optional(
|
||||
if(!gdr_storage_copy_string_optional(
|
||||
save_file, flipper_format, "RadioDevice", string_value))
|
||||
break;
|
||||
if(!protopirate_storage_copy_string_if_present(
|
||||
if(!gdr_storage_copy_string_if_present(
|
||||
save_file, flipper_format, "Custom_preset_module", string_value))
|
||||
break;
|
||||
if(!protopirate_storage_copy_hex_array_if_present(
|
||||
if(!gdr_storage_copy_hex_array_if_present(
|
||||
save_file, flipper_format, "Custom_preset_data", 1024))
|
||||
break;
|
||||
if(!protopirate_storage_copy_u32_fields(
|
||||
if(!gdr_storage_copy_u32_fields(
|
||||
save_file,
|
||||
flipper_format,
|
||||
protopirate_storage_base_u32_fields,
|
||||
COUNT_OF(protopirate_storage_base_u32_fields)))
|
||||
gdr_storage_base_u32_fields,
|
||||
COUNT_OF(gdr_storage_base_u32_fields)))
|
||||
break;
|
||||
if(!protopirate_storage_copy_hex_fixed(save_file, flipper_format, "Key2", 8, NULL)) break;
|
||||
if(!protopirate_storage_copy_u32_optional(save_file, flipper_format, "KeyIdx")) break;
|
||||
if(!protopirate_storage_copy_u32_optional(save_file, flipper_format, "Seed")) break;
|
||||
if(!protopirate_storage_copy_hex_or_u32(save_file, flipper_format, "ValidationField", 2))
|
||||
if(!gdr_storage_copy_hex_fixed(save_file, flipper_format, "Key2", 8, NULL)) break;
|
||||
if(!gdr_storage_copy_u32_optional(save_file, flipper_format, "KeyIdx")) break;
|
||||
if(!gdr_storage_copy_u32_optional(save_file, flipper_format, "Seed")) break;
|
||||
if(!gdr_storage_copy_hex_or_u32(save_file, flipper_format, "ValidationField", 2))
|
||||
break;
|
||||
if(!protopirate_storage_copy_key_2(save_file, flipper_format, string_value)) break;
|
||||
if(!protopirate_storage_copy_hex_or_u32(save_file, flipper_format, "Key_3", 4)) break;
|
||||
if(!protopirate_storage_copy_u32_optional(save_file, flipper_format, "Key_4")) break;
|
||||
if(!protopirate_storage_copy_u32_optional(save_file, flipper_format, "Fx")) break;
|
||||
if(!protopirate_storage_copy_hex_fixed(save_file, flipper_format, "Key1", 8, NULL)) break;
|
||||
if(!protopirate_storage_copy_u32_optional(save_file, flipper_format, "Check")) break;
|
||||
if(!protopirate_storage_copy_u32_array_if_present(
|
||||
if(!gdr_storage_copy_key_2(save_file, flipper_format, string_value)) break;
|
||||
if(!gdr_storage_copy_hex_or_u32(save_file, flipper_format, "Key_3", 4)) break;
|
||||
if(!gdr_storage_copy_u32_optional(save_file, flipper_format, "Key_4")) break;
|
||||
if(!gdr_storage_copy_u32_optional(save_file, flipper_format, "Fx")) break;
|
||||
if(!gdr_storage_copy_hex_fixed(save_file, flipper_format, "Key1", 8, NULL)) break;
|
||||
if(!gdr_storage_copy_u32_optional(save_file, flipper_format, "Check")) break;
|
||||
if(!gdr_storage_copy_u32_array_if_present(
|
||||
save_file, flipper_format, "RAW_Data", 4096))
|
||||
break;
|
||||
if(!protopirate_storage_copy_u32_fields(
|
||||
if(!gdr_storage_copy_u32_fields(
|
||||
save_file,
|
||||
flipper_format,
|
||||
protopirate_storage_tail_u32_fields,
|
||||
COUNT_OF(protopirate_storage_tail_u32_fields)))
|
||||
gdr_storage_tail_u32_fields,
|
||||
COUNT_OF(gdr_storage_tail_u32_fields)))
|
||||
break;
|
||||
if(!protopirate_storage_copy_string_optional(
|
||||
if(!gdr_storage_copy_string_optional(
|
||||
save_file, flipper_format, FF_MANUFACTURE, string_value))
|
||||
break;
|
||||
status = true;
|
||||
@@ -441,11 +441,11 @@ static bool protopirate_storage_write_capture_data(
|
||||
return status;
|
||||
}
|
||||
|
||||
bool protopirate_storage_save_capture_to_path(FlipperFormat* flipper_format, const char* full_path) {
|
||||
bool gdr_storage_save_capture_to_path(FlipperFormat* flipper_format, const char* full_path) {
|
||||
furi_check(flipper_format);
|
||||
furi_check(full_path);
|
||||
|
||||
if(!protopirate_storage_init()) {
|
||||
if(!gdr_storage_init()) {
|
||||
FURI_LOG_E(TAG, "Failed to create app folder");
|
||||
return false;
|
||||
}
|
||||
@@ -470,7 +470,7 @@ bool protopirate_storage_save_capture_to_path(FlipperFormat* flipper_format, con
|
||||
break;
|
||||
}
|
||||
|
||||
if(!protopirate_storage_write_capture_data(save_file, flipper_format)) {
|
||||
if(!gdr_storage_write_capture_data(save_file, flipper_format)) {
|
||||
FURI_LOG_E(TAG, "Failed to write capture data");
|
||||
break;
|
||||
}
|
||||
@@ -485,16 +485,16 @@ bool protopirate_storage_save_capture_to_path(FlipperFormat* flipper_format, con
|
||||
return result;
|
||||
}
|
||||
|
||||
void protopirate_storage_delete_temp(void) {
|
||||
void gdr_storage_delete_temp(void) {
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
if(storage_file_exists(storage, PROTOPIRATE_TEMP_FILE)) {
|
||||
storage_simply_remove(storage, PROTOPIRATE_TEMP_FILE);
|
||||
if(storage_file_exists(storage, GDR_TEMP_FILE)) {
|
||||
storage_simply_remove(storage, GDR_TEMP_FILE);
|
||||
FURI_LOG_I(TAG, "Deleted temp file");
|
||||
}
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
}
|
||||
|
||||
bool protopirate_storage_save_capture(
|
||||
bool gdr_storage_save_capture(
|
||||
FlipperFormat* flipper_format,
|
||||
const char* protocol_name,
|
||||
FuriString* out_path) {
|
||||
@@ -502,14 +502,14 @@ bool protopirate_storage_save_capture(
|
||||
furi_check(protocol_name);
|
||||
furi_check(out_path);
|
||||
|
||||
if(!protopirate_storage_init()) {
|
||||
if(!gdr_storage_init()) {
|
||||
FURI_LOG_E(TAG, "Failed to create app folder");
|
||||
return false;
|
||||
}
|
||||
|
||||
FuriString* file_path = furi_string_alloc();
|
||||
|
||||
if(!protopirate_storage_get_next_filename(protocol_name, file_path)) {
|
||||
if(!gdr_storage_get_next_filename(protocol_name, file_path)) {
|
||||
FURI_LOG_E(TAG, "Failed to get next filename");
|
||||
furi_string_free(file_path);
|
||||
return false;
|
||||
@@ -530,7 +530,7 @@ bool protopirate_storage_save_capture(
|
||||
break;
|
||||
}
|
||||
|
||||
if(!protopirate_storage_write_capture_data(save_file, flipper_format)) {
|
||||
if(!gdr_storage_write_capture_data(save_file, flipper_format)) {
|
||||
FURI_LOG_E(TAG, "Failed to write capture data");
|
||||
break;
|
||||
}
|
||||
@@ -548,7 +548,7 @@ bool protopirate_storage_save_capture(
|
||||
return result;
|
||||
}
|
||||
|
||||
bool protopirate_storage_delete_file(const char* file_path) {
|
||||
bool gdr_storage_delete_file(const char* file_path) {
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
bool result = storage_simply_remove(storage, file_path);
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
@@ -0,0 +1,59 @@
|
||||
// helpers/gdr_storage.h
|
||||
#pragma once
|
||||
|
||||
#include <furi.h>
|
||||
#include <storage/storage.h>
|
||||
#include <flipper_format/flipper_format.h>
|
||||
|
||||
#define GDR_APP_FOLDER APP_DATA_PATH("saved")
|
||||
#define GDR_APP_EXTENSION ".psf"
|
||||
#define GDR_APP_FILE_VERSION 1
|
||||
#define GDR_TEMP_FILE APP_DATA_PATH("saved/.temp.psf")
|
||||
#define GDR_CACHE_FOLDER APP_DATA_PATH("cache")
|
||||
#define GDR_HISTORY_FOLDER APP_DATA_PATH("cache/history")
|
||||
|
||||
// Initialize storage (create folder if needed)
|
||||
bool gdr_storage_init(void);
|
||||
|
||||
// Save a capture to a new file (auto-generated name)
|
||||
bool gdr_storage_save_capture(
|
||||
FlipperFormat* flipper_format,
|
||||
const char* protocol_name,
|
||||
FuriString* out_path);
|
||||
|
||||
// Save a capture to a specific file path (user-chosen name)
|
||||
bool gdr_storage_save_capture_to_path(FlipperFormat* flipper_format, const char* full_path);
|
||||
|
||||
// Save to temp file for emulation
|
||||
bool gdr_storage_save_temp(FlipperFormat* flipper_format);
|
||||
|
||||
// Delete temp file
|
||||
void gdr_storage_delete_temp(void);
|
||||
|
||||
// Get next available filename for a protocol
|
||||
bool gdr_storage_get_next_filename(const char* protocol_name, FuriString* out_filename);
|
||||
|
||||
// Delete a file
|
||||
bool gdr_storage_delete_file(const char* file_path);
|
||||
|
||||
// Load a file (caller must close with gdr_storage_close_file)
|
||||
FlipperFormat* gdr_storage_load_file(const char* file_path);
|
||||
|
||||
// Close a loaded file (by gdr_storage_load_file only)
|
||||
void gdr_storage_close_file(FlipperFormat* flipper_format);
|
||||
|
||||
// Check if file exists
|
||||
bool gdr_storage_file_exists(const char* file_path);
|
||||
|
||||
bool gdr_storage_ensure_history_folder(void);
|
||||
|
||||
void gdr_storage_purge_temp_history_at_startup(void);
|
||||
|
||||
void gdr_storage_wipe_history_cache(void);
|
||||
|
||||
bool gdr_storage_save_history_capture(
|
||||
FlipperFormat* flipper_format,
|
||||
uint32_t seq,
|
||||
FuriString* out_path);
|
||||
|
||||
void gdr_storage_build_history_path(uint32_t seq, FuriString* out);
|
||||
+37
-37
@@ -1,19 +1,19 @@
|
||||
// helpers/protopirate_tx_chain.c
|
||||
#include "protopirate_tx_chain.h"
|
||||
// helpers/gdr_tx_chain.c
|
||||
#include "gdr_tx_chain.h"
|
||||
|
||||
#ifdef ENABLE_SHIELD_RX_SCENE
|
||||
|
||||
#include <furi.h>
|
||||
#include <string.h>
|
||||
|
||||
#define TAG "ProtoPirateTxChain"
|
||||
#define TAG "GDRTxChain"
|
||||
|
||||
#define PROTOPIRATE_TX_CARRIER_PRESET "AM650"
|
||||
#define PROTOPIRATE_TX_POWER_COUNT 9U
|
||||
#define PROTOPIRATE_TX_PRESET_VALUES_AM 8U
|
||||
#define PROTOPIRATE_TX_PRESET_VALUES_COUNT 17U
|
||||
#define GDR_TX_CARRIER_PRESET "AM650"
|
||||
#define GDR_TX_POWER_COUNT 9U
|
||||
#define GDR_TX_PRESET_VALUES_AM 8U
|
||||
#define GDR_TX_PRESET_VALUES_COUNT 17U
|
||||
|
||||
static const uint8_t protopirate_tx_power_value[PROTOPIRATE_TX_PRESET_VALUES_COUNT] = {
|
||||
static const uint8_t gdr_tx_power_value[GDR_TX_PRESET_VALUES_COUNT] = {
|
||||
0,
|
||||
0xC0,
|
||||
0xC8,
|
||||
@@ -34,7 +34,7 @@ static const uint8_t protopirate_tx_power_value[PROTOPIRATE_TX_PRESET_VALUES_COU
|
||||
};
|
||||
|
||||
static size_t
|
||||
protopirate_tx_chain_get_pa_table_offset(const uint8_t* preset_data, size_t preset_size) {
|
||||
gdr_tx_chain_get_pa_table_offset(const uint8_t* preset_data, size_t preset_size) {
|
||||
size_t offset = 0;
|
||||
while((offset + 1U) < preset_size) {
|
||||
if(preset_data[offset] == 0U) {
|
||||
@@ -45,15 +45,15 @@ static size_t
|
||||
return 0U;
|
||||
}
|
||||
|
||||
static void protopirate_tx_chain_apply_tx_power(
|
||||
static void gdr_tx_chain_apply_tx_power(
|
||||
uint8_t* preset_data,
|
||||
size_t preset_size,
|
||||
uint8_t tx_power) {
|
||||
if(!tx_power || tx_power >= PROTOPIRATE_TX_POWER_COUNT) {
|
||||
if(!tx_power || tx_power >= GDR_TX_POWER_COUNT) {
|
||||
return;
|
||||
}
|
||||
|
||||
const size_t pa_offset = protopirate_tx_chain_get_pa_table_offset(preset_data, preset_size);
|
||||
const size_t pa_offset = gdr_tx_chain_get_pa_table_offset(preset_data, preset_size);
|
||||
if(!pa_offset) {
|
||||
return;
|
||||
}
|
||||
@@ -65,15 +65,15 @@ static void protopirate_tx_chain_apply_tx_power(
|
||||
return;
|
||||
}
|
||||
if(fm_byte) {
|
||||
preset_data[pa_offset] = protopirate_tx_power_value[tx_power];
|
||||
preset_data[pa_offset] = gdr_tx_power_value[tx_power];
|
||||
} else if(am_byte) {
|
||||
preset_data[pa_offset + 1U] =
|
||||
protopirate_tx_power_value[PROTOPIRATE_TX_PRESET_VALUES_AM + tx_power];
|
||||
gdr_tx_power_value[GDR_TX_PRESET_VALUES_AM + tx_power];
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t*
|
||||
protopirate_tx_chain_copy_preset(const uint8_t* src, size_t src_size, size_t* out_size) {
|
||||
gdr_tx_chain_copy_preset(const uint8_t* src, size_t src_size, size_t* out_size) {
|
||||
if(!src || !src_size || !out_size) {
|
||||
return NULL;
|
||||
}
|
||||
@@ -88,22 +88,22 @@ static uint8_t*
|
||||
return copy;
|
||||
}
|
||||
|
||||
ProtoPirateTxChain* protopirate_tx_chain_alloc(void) {
|
||||
ProtoPirateTxChain* chain = malloc(sizeof(ProtoPirateTxChain));
|
||||
GDRTxChain* gdr_tx_chain_alloc(void) {
|
||||
GDRTxChain* chain = malloc(sizeof(GDRTxChain));
|
||||
furi_check(chain);
|
||||
memset(chain, 0, sizeof(ProtoPirateTxChain));
|
||||
memset(chain, 0, sizeof(GDRTxChain));
|
||||
chain->preset_name = furi_string_alloc();
|
||||
furi_check(chain->preset_name);
|
||||
chain->state = ProtoPirateTxRxStateIDLE;
|
||||
chain->state = GDRTxRxStateIDLE;
|
||||
return chain;
|
||||
}
|
||||
|
||||
void protopirate_tx_chain_free(ProtoPirateTxChain* chain) {
|
||||
void gdr_tx_chain_free(GDRTxChain* chain) {
|
||||
if(!chain) {
|
||||
return;
|
||||
}
|
||||
|
||||
protopirate_tx_chain_stop(chain);
|
||||
gdr_tx_chain_stop(chain);
|
||||
|
||||
if(chain->device) {
|
||||
subghz_devices_idle(chain->device);
|
||||
@@ -125,7 +125,7 @@ void protopirate_tx_chain_free(ProtoPirateTxChain* chain) {
|
||||
free(chain);
|
||||
}
|
||||
|
||||
bool protopirate_tx_chain_acquire_device(ProtoPirateTxChain* chain) {
|
||||
bool gdr_tx_chain_acquire_device(GDRTxChain* chain) {
|
||||
furi_check(chain);
|
||||
|
||||
chain->device = radio_device_loader_set(NULL, SubGhzRadioDeviceTypeInternal);
|
||||
@@ -154,8 +154,8 @@ bool protopirate_tx_chain_acquire_device(ProtoPirateTxChain* chain) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool protopirate_tx_chain_configure(
|
||||
ProtoPirateTxChain* chain,
|
||||
bool gdr_tx_chain_configure(
|
||||
GDRTxChain* chain,
|
||||
SubGhzSetting* setting,
|
||||
uint32_t rx_frequency,
|
||||
int32_t offset_hz,
|
||||
@@ -164,23 +164,23 @@ bool protopirate_tx_chain_configure(
|
||||
furi_check(setting);
|
||||
|
||||
const uint8_t* source_preset =
|
||||
subghz_setting_get_preset_data_by_name(setting, PROTOPIRATE_TX_CARRIER_PRESET);
|
||||
subghz_setting_get_preset_data_by_name(setting, GDR_TX_CARRIER_PRESET);
|
||||
if(!source_preset) {
|
||||
FURI_LOG_E(TAG, "Carrier preset %s is unavailable", PROTOPIRATE_TX_CARRIER_PRESET);
|
||||
FURI_LOG_E(TAG, "Carrier preset %s is unavailable", GDR_TX_CARRIER_PRESET);
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t preset_count = subghz_setting_get_preset_count(setting);
|
||||
size_t source_size = 0;
|
||||
for(size_t i = 0; i < preset_count; i++) {
|
||||
if(strcmp(subghz_setting_get_preset_name(setting, i), PROTOPIRATE_TX_CARRIER_PRESET) ==
|
||||
if(strcmp(subghz_setting_get_preset_name(setting, i), GDR_TX_CARRIER_PRESET) ==
|
||||
0) {
|
||||
source_size = subghz_setting_get_preset_data_size(setting, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!source_size) {
|
||||
FURI_LOG_E(TAG, "Carrier preset %s has zero size", PROTOPIRATE_TX_CARRIER_PRESET);
|
||||
FURI_LOG_E(TAG, "Carrier preset %s has zero size", GDR_TX_CARRIER_PRESET);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -191,14 +191,14 @@ bool protopirate_tx_chain_configure(
|
||||
}
|
||||
|
||||
chain->preset_data =
|
||||
protopirate_tx_chain_copy_preset(source_preset, source_size, &chain->preset_data_size);
|
||||
gdr_tx_chain_copy_preset(source_preset, source_size, &chain->preset_data_size);
|
||||
if(!chain->preset_data) {
|
||||
FURI_LOG_E(TAG, "Failed to copy preset data");
|
||||
return false;
|
||||
}
|
||||
|
||||
protopirate_tx_chain_apply_tx_power(chain->preset_data, chain->preset_data_size, tx_power);
|
||||
furi_string_set(chain->preset_name, PROTOPIRATE_TX_CARRIER_PRESET);
|
||||
gdr_tx_chain_apply_tx_power(chain->preset_data, chain->preset_data_size, tx_power);
|
||||
furi_string_set(chain->preset_name, GDR_TX_CARRIER_PRESET);
|
||||
|
||||
const int64_t tx_frequency_signed = (int64_t)rx_frequency + offset_hz;
|
||||
if(tx_frequency_signed <= 0 || tx_frequency_signed > UINT32_MAX) {
|
||||
@@ -224,13 +224,13 @@ bool protopirate_tx_chain_configure(
|
||||
return true;
|
||||
}
|
||||
|
||||
bool protopirate_tx_chain_start_carrier(ProtoPirateTxChain* chain) {
|
||||
bool gdr_tx_chain_start_carrier(GDRTxChain* chain) {
|
||||
furi_check(chain);
|
||||
if(!chain->device || !chain->data_gpio || !chain->preset_data) {
|
||||
FURI_LOG_E(TAG, "start rejected (incomplete stack)");
|
||||
return false;
|
||||
}
|
||||
if(chain->state == ProtoPirateTxRxStateTx) {
|
||||
if(chain->state == GDRTxRxStateTx) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -247,16 +247,16 @@ bool protopirate_tx_chain_start_carrier(ProtoPirateTxChain* chain) {
|
||||
subghz_devices_idle(chain->device);
|
||||
return false;
|
||||
}
|
||||
chain->state = ProtoPirateTxRxStateTx;
|
||||
chain->state = GDRTxRxStateTx;
|
||||
FURI_LOG_I(TAG, "Carrier TX started on %lu Hz", chain->frequency);
|
||||
return true;
|
||||
}
|
||||
|
||||
void protopirate_tx_chain_stop(ProtoPirateTxChain* chain) {
|
||||
void gdr_tx_chain_stop(GDRTxChain* chain) {
|
||||
if(!chain) {
|
||||
return;
|
||||
}
|
||||
if(chain->state != ProtoPirateTxRxStateTx) {
|
||||
if(chain->state != GDRTxRxStateTx) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -267,7 +267,7 @@ void protopirate_tx_chain_stop(ProtoPirateTxChain* chain) {
|
||||
furi_hal_gpio_write(chain->data_gpio, false);
|
||||
furi_hal_gpio_init(chain->data_gpio, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||
}
|
||||
chain->state = ProtoPirateTxRxStateIDLE;
|
||||
chain->state = GDRTxRxStateIDLE;
|
||||
}
|
||||
|
||||
#endif // ENABLE_SHIELD_RX_SCENE
|
||||
@@ -0,0 +1,38 @@
|
||||
// helpers/gdr_tx_chain.h
|
||||
#pragma once
|
||||
|
||||
#include "gdr_types.h"
|
||||
|
||||
#ifdef ENABLE_SHIELD_RX_SCENE
|
||||
|
||||
#include <lib/subghz/subghz_setting.h>
|
||||
#include <lib/subghz/devices/devices.h>
|
||||
|
||||
#include "radio_device_loader.h"
|
||||
|
||||
typedef struct {
|
||||
const SubGhzDevice* device;
|
||||
const GpioPin* data_gpio;
|
||||
uint8_t* preset_data;
|
||||
size_t preset_data_size;
|
||||
FuriString* preset_name;
|
||||
uint32_t frequency;
|
||||
GDRTxRxState state;
|
||||
} GDRTxChain;
|
||||
|
||||
GDRTxChain* gdr_tx_chain_alloc(void);
|
||||
void gdr_tx_chain_free(GDRTxChain* chain);
|
||||
|
||||
bool gdr_tx_chain_acquire_device(GDRTxChain* chain);
|
||||
|
||||
bool gdr_tx_chain_configure(
|
||||
GDRTxChain* chain,
|
||||
SubGhzSetting* setting,
|
||||
uint32_t rx_frequency,
|
||||
int32_t offset_hz,
|
||||
uint8_t tx_power);
|
||||
|
||||
bool gdr_tx_chain_start_carrier(GDRTxChain* chain);
|
||||
void gdr_tx_chain_stop(GDRTxChain* chain);
|
||||
|
||||
#endif // ENABLE_SHIELD_RX_SCENE
|
||||
@@ -0,0 +1,95 @@
|
||||
// helpers/gdr_types.h
|
||||
#pragma once
|
||||
|
||||
#include <furi.h>
|
||||
#include <furi_hal.h>
|
||||
#include "../defines.h"
|
||||
|
||||
typedef enum {
|
||||
GDRViewVariableItemList,
|
||||
GDRViewSubmenu,
|
||||
GDRViewWidget,
|
||||
GDRViewReceiver,
|
||||
GDRViewAbout,
|
||||
GDRViewFileBrowser,
|
||||
GDRViewTextInput,
|
||||
#ifdef ENABLE_DUAL_RX_SCENE
|
||||
GDRViewDualReceiver,
|
||||
#endif
|
||||
} GDRView;
|
||||
|
||||
typedef enum {
|
||||
// Custom events for views
|
||||
GDRCustomEventViewReceiverOK,
|
||||
GDRCustomEventViewReceiverConfig,
|
||||
GDRCustomEventViewReceiverBack,
|
||||
GDRCustomEventViewReceiverDeleteItem,
|
||||
GDRCustomEventViewReceiverUnlock,
|
||||
// Custom events for scenes
|
||||
GDRCustomEventSceneReceiverUpdate,
|
||||
GDRCustomEventReceiverDeferredRxStart,
|
||||
GDRCustomEventSceneSettingLock,
|
||||
// File management
|
||||
GDRCustomEventReceiverInfoSave,
|
||||
GDRCustomEventReceiverInfoSaveConfirm,
|
||||
GDRCustomEventReceiverInfoEmulate,
|
||||
GDRCustomEventReceiverInfoBruteforceStart,
|
||||
GDRCustomEventReceiverInfoBruteforceCancel,
|
||||
GDRCustomEventSavedInfoDelete,
|
||||
// Emulator
|
||||
GDRCustomEventSavedInfoEmulate,
|
||||
GDRCustomEventEmulateTransmit,
|
||||
GDRCustomEventEmulateStop,
|
||||
GDRCustomEventEmulateExit,
|
||||
// Sub decode
|
||||
GDRCustomEventSubDecodeUpdate,
|
||||
GDRCustomEventSubDecodeSave,
|
||||
GDRCustomEventSubDecodeBruteforceStart,
|
||||
GDRCustomEventPsaBruteforceComplete,
|
||||
// File Browser
|
||||
GDRCustomEventSavedFileSelected,
|
||||
// Need saving confirmation
|
||||
GDRCustomEventSceneStay,
|
||||
GDRCustomEventSceneExit,
|
||||
// About scene
|
||||
GDRCustomEventAboutToggleEmulate,
|
||||
#ifdef ENABLE_DUAL_RX_SCENE
|
||||
// Dual RX scene
|
||||
GDRCustomEventDualReceiverDeferredRxStart,
|
||||
GDRCustomEventDualReceiverUpdate,
|
||||
GDRCustomEventViewDualReceiverOK,
|
||||
GDRCustomEventViewDualReceiverBack,
|
||||
GDRCustomEventViewDualReceiverDeleteItem,
|
||||
GDRCustomEventViewDualReceiverConfig,
|
||||
#endif
|
||||
#ifdef ENABLE_SHIELD_RX_SCENE
|
||||
GDRCustomEventShieldReceiverDeferredStart,
|
||||
GDRCustomEventShieldReceiverUpdate,
|
||||
#endif
|
||||
} GDRCustomEvent;
|
||||
|
||||
typedef enum {
|
||||
GDRLockOff,
|
||||
GDRLockOn,
|
||||
} GDRLock;
|
||||
|
||||
typedef enum {
|
||||
GDRTxRxStateIDLE,
|
||||
GDRTxRxStateRx,
|
||||
GDRTxRxStateTx,
|
||||
GDRTxRxStateSleep,
|
||||
} GDRTxRxState;
|
||||
|
||||
typedef enum {
|
||||
GDRHopperStateOFF,
|
||||
GDRHopperStateRunning,
|
||||
GDRHopperStatePause,
|
||||
GDRHopperStateRSSITimeOut,
|
||||
} GDRHopperState;
|
||||
|
||||
typedef enum {
|
||||
GDRRxKeyStateIDLE,
|
||||
GDRRxKeyStateBack,
|
||||
GDRRxKeyStateStart,
|
||||
GDRRxKeyStateAddKey,
|
||||
} GDRRxKeyState;
|
||||
@@ -1,14 +0,0 @@
|
||||
#include "protopirate_psa_bf_host.h"
|
||||
|
||||
bool protopirate_psa_bf_plugin_ensure_loaded(ProtoPirateApp* app) {
|
||||
(void)app;
|
||||
return false;
|
||||
}
|
||||
|
||||
void protopirate_psa_bf_plugin_unload_if_idle(ProtoPirateApp* app) {
|
||||
(void)app;
|
||||
}
|
||||
|
||||
void protopirate_psa_bf_context_release(ProtoPirateApp* app) {
|
||||
(void)app;
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef struct ProtoPirateApp ProtoPirateApp;
|
||||
|
||||
bool protopirate_psa_bf_plugin_ensure_loaded(ProtoPirateApp* app);
|
||||
void protopirate_psa_bf_plugin_unload_if_idle(ProtoPirateApp* app);
|
||||
void protopirate_psa_bf_context_release(ProtoPirateApp* app);
|
||||
|
||||
void protopirate_receiver_info_rebuild_normal_widget(void* app);
|
||||
|
||||
#ifdef ENABLE_SUB_DECODE_SCENE
|
||||
void protopirate_subdecode_psa_bf_complete_refresh(void* app);
|
||||
#endif
|
||||
@@ -1,32 +0,0 @@
|
||||
// helpers/protopirate_settings.h
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#define PROTOPIRATE_SETTINGS_FILE APP_DATA_PATH("settings.txt")
|
||||
#define PROTOPIRATE_SETTINGS_DIR APP_DATA_PATH()
|
||||
#define PROTOPIRATE_PRESET_NAME_MAX 64U
|
||||
|
||||
typedef struct {
|
||||
uint32_t frequency;
|
||||
uint8_t preset_index;
|
||||
uint8_t tx_power;
|
||||
bool auto_save;
|
||||
bool hopping_enabled;
|
||||
bool emulate_feature_enabled;
|
||||
uint32_t dual_freq_a;
|
||||
uint32_t dual_freq_b;
|
||||
uint8_t dual_preset_a;
|
||||
uint8_t dual_preset_b;
|
||||
char dual_preset_name_a[PROTOPIRATE_PRESET_NAME_MAX];
|
||||
char dual_preset_name_b[PROTOPIRATE_PRESET_NAME_MAX];
|
||||
uint32_t shield_freq;
|
||||
uint8_t shield_preset_index;
|
||||
uint8_t shield_tx_offset_index;
|
||||
uint8_t shield_tx_power;
|
||||
} ProtoPirateSettings;
|
||||
|
||||
void protopirate_settings_load(ProtoPirateSettings* settings);
|
||||
void protopirate_settings_save(ProtoPirateSettings* settings);
|
||||
void protopirate_settings_set_defaults(ProtoPirateSettings* settings);
|
||||
@@ -1,59 +0,0 @@
|
||||
// helpers/protopirate_storage.h
|
||||
#pragma once
|
||||
|
||||
#include <furi.h>
|
||||
#include <storage/storage.h>
|
||||
#include <flipper_format/flipper_format.h>
|
||||
|
||||
#define PROTOPIRATE_APP_FOLDER APP_DATA_PATH("saved")
|
||||
#define PROTOPIRATE_APP_EXTENSION ".psf"
|
||||
#define PROTOPIRATE_APP_FILE_VERSION 1
|
||||
#define PROTOPIRATE_TEMP_FILE APP_DATA_PATH("saved/.temp.psf")
|
||||
#define PROTOPIRATE_CACHE_FOLDER APP_DATA_PATH("cache")
|
||||
#define PROTOPIRATE_HISTORY_FOLDER APP_DATA_PATH("cache/history")
|
||||
|
||||
// Initialize storage (create folder if needed)
|
||||
bool protopirate_storage_init(void);
|
||||
|
||||
// Save a capture to a new file (auto-generated name)
|
||||
bool protopirate_storage_save_capture(
|
||||
FlipperFormat* flipper_format,
|
||||
const char* protocol_name,
|
||||
FuriString* out_path);
|
||||
|
||||
// Save a capture to a specific file path (user-chosen name)
|
||||
bool protopirate_storage_save_capture_to_path(FlipperFormat* flipper_format, const char* full_path);
|
||||
|
||||
// Save to temp file for emulation
|
||||
bool protopirate_storage_save_temp(FlipperFormat* flipper_format);
|
||||
|
||||
// Delete temp file
|
||||
void protopirate_storage_delete_temp(void);
|
||||
|
||||
// Get next available filename for a protocol
|
||||
bool protopirate_storage_get_next_filename(const char* protocol_name, FuriString* out_filename);
|
||||
|
||||
// Delete a file
|
||||
bool protopirate_storage_delete_file(const char* file_path);
|
||||
|
||||
// Load a file (caller must close with protopirate_storage_close_file)
|
||||
FlipperFormat* protopirate_storage_load_file(const char* file_path);
|
||||
|
||||
// Close a loaded file (by protopirate_storage_load_file only)
|
||||
void protopirate_storage_close_file(FlipperFormat* flipper_format);
|
||||
|
||||
// Check if file exists
|
||||
bool protopirate_storage_file_exists(const char* file_path);
|
||||
|
||||
bool protopirate_storage_ensure_history_folder(void);
|
||||
|
||||
void protopirate_storage_purge_temp_history_at_startup(void);
|
||||
|
||||
void protopirate_storage_wipe_history_cache(void);
|
||||
|
||||
bool protopirate_storage_save_history_capture(
|
||||
FlipperFormat* flipper_format,
|
||||
uint32_t seq,
|
||||
FuriString* out_path);
|
||||
|
||||
void protopirate_storage_build_history_path(uint32_t seq, FuriString* out);
|
||||
@@ -1,38 +0,0 @@
|
||||
// helpers/protopirate_tx_chain.h
|
||||
#pragma once
|
||||
|
||||
#include "protopirate_types.h"
|
||||
|
||||
#ifdef ENABLE_SHIELD_RX_SCENE
|
||||
|
||||
#include <lib/subghz/subghz_setting.h>
|
||||
#include <lib/subghz/devices/devices.h>
|
||||
|
||||
#include "radio_device_loader.h"
|
||||
|
||||
typedef struct {
|
||||
const SubGhzDevice* device;
|
||||
const GpioPin* data_gpio;
|
||||
uint8_t* preset_data;
|
||||
size_t preset_data_size;
|
||||
FuriString* preset_name;
|
||||
uint32_t frequency;
|
||||
ProtoPirateTxRxState state;
|
||||
} ProtoPirateTxChain;
|
||||
|
||||
ProtoPirateTxChain* protopirate_tx_chain_alloc(void);
|
||||
void protopirate_tx_chain_free(ProtoPirateTxChain* chain);
|
||||
|
||||
bool protopirate_tx_chain_acquire_device(ProtoPirateTxChain* chain);
|
||||
|
||||
bool protopirate_tx_chain_configure(
|
||||
ProtoPirateTxChain* chain,
|
||||
SubGhzSetting* setting,
|
||||
uint32_t rx_frequency,
|
||||
int32_t offset_hz,
|
||||
uint8_t tx_power);
|
||||
|
||||
bool protopirate_tx_chain_start_carrier(ProtoPirateTxChain* chain);
|
||||
void protopirate_tx_chain_stop(ProtoPirateTxChain* chain);
|
||||
|
||||
#endif // ENABLE_SHIELD_RX_SCENE
|
||||
@@ -1,95 +0,0 @@
|
||||
// helpers/protopirate_types.h
|
||||
#pragma once
|
||||
|
||||
#include <furi.h>
|
||||
#include <furi_hal.h>
|
||||
#include "../defines.h"
|
||||
|
||||
typedef enum {
|
||||
ProtoPirateViewVariableItemList,
|
||||
ProtoPirateViewSubmenu,
|
||||
ProtoPirateViewWidget,
|
||||
ProtoPirateViewReceiver,
|
||||
ProtoPirateViewAbout,
|
||||
ProtoPirateViewFileBrowser,
|
||||
ProtoPirateViewTextInput,
|
||||
#ifdef ENABLE_DUAL_RX_SCENE
|
||||
ProtoPirateViewDualReceiver,
|
||||
#endif
|
||||
} ProtoPirateView;
|
||||
|
||||
typedef enum {
|
||||
// Custom events for views
|
||||
ProtoPirateCustomEventViewReceiverOK,
|
||||
ProtoPirateCustomEventViewReceiverConfig,
|
||||
ProtoPirateCustomEventViewReceiverBack,
|
||||
ProtoPirateCustomEventViewReceiverDeleteItem,
|
||||
ProtoPirateCustomEventViewReceiverUnlock,
|
||||
// Custom events for scenes
|
||||
ProtoPirateCustomEventSceneReceiverUpdate,
|
||||
ProtoPirateCustomEventReceiverDeferredRxStart,
|
||||
ProtoPirateCustomEventSceneSettingLock,
|
||||
// File management
|
||||
ProtoPirateCustomEventReceiverInfoSave,
|
||||
ProtoPirateCustomEventReceiverInfoSaveConfirm,
|
||||
ProtoPirateCustomEventReceiverInfoEmulate,
|
||||
ProtoPirateCustomEventReceiverInfoBruteforceStart,
|
||||
ProtoPirateCustomEventReceiverInfoBruteforceCancel,
|
||||
ProtoPirateCustomEventSavedInfoDelete,
|
||||
// Emulator
|
||||
ProtoPirateCustomEventSavedInfoEmulate,
|
||||
ProtoPirateCustomEventEmulateTransmit,
|
||||
ProtoPirateCustomEventEmulateStop,
|
||||
ProtoPirateCustomEventEmulateExit,
|
||||
// Sub decode
|
||||
ProtoPirateCustomEventSubDecodeUpdate,
|
||||
ProtoPirateCustomEventSubDecodeSave,
|
||||
ProtoPirateCustomEventSubDecodeBruteforceStart,
|
||||
ProtoPirateCustomEventPsaBruteforceComplete,
|
||||
// File Browser
|
||||
ProtoPirateCustomEventSavedFileSelected,
|
||||
// Need saving confirmation
|
||||
ProtoPirateCustomEventSceneStay,
|
||||
ProtoPirateCustomEventSceneExit,
|
||||
// About scene
|
||||
ProtoPirateCustomEventAboutToggleEmulate,
|
||||
#ifdef ENABLE_DUAL_RX_SCENE
|
||||
// Dual RX scene
|
||||
ProtoPirateCustomEventDualReceiverDeferredRxStart,
|
||||
ProtoPirateCustomEventDualReceiverUpdate,
|
||||
ProtoPirateCustomEventViewDualReceiverOK,
|
||||
ProtoPirateCustomEventViewDualReceiverBack,
|
||||
ProtoPirateCustomEventViewDualReceiverDeleteItem,
|
||||
ProtoPirateCustomEventViewDualReceiverConfig,
|
||||
#endif
|
||||
#ifdef ENABLE_SHIELD_RX_SCENE
|
||||
ProtoPirateCustomEventShieldReceiverDeferredStart,
|
||||
ProtoPirateCustomEventShieldReceiverUpdate,
|
||||
#endif
|
||||
} ProtoPirateCustomEvent;
|
||||
|
||||
typedef enum {
|
||||
ProtoPirateLockOff,
|
||||
ProtoPirateLockOn,
|
||||
} ProtoPirateLock;
|
||||
|
||||
typedef enum {
|
||||
ProtoPirateTxRxStateIDLE,
|
||||
ProtoPirateTxRxStateRx,
|
||||
ProtoPirateTxRxStateTx,
|
||||
ProtoPirateTxRxStateSleep,
|
||||
} ProtoPirateTxRxState;
|
||||
|
||||
typedef enum {
|
||||
ProtoPirateHopperStateOFF,
|
||||
ProtoPirateHopperStateRunning,
|
||||
ProtoPirateHopperStatePause,
|
||||
ProtoPirateHopperStateRSSITimeOut,
|
||||
} ProtoPirateHopperState;
|
||||
|
||||
typedef enum {
|
||||
ProtoPirateRxKeyStateIDLE,
|
||||
ProtoPirateRxKeyStateBack,
|
||||
ProtoPirateRxKeyStateStart,
|
||||
ProtoPirateRxKeyStateAddKey,
|
||||
} ProtoPirateRxKeyState;
|
||||
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "../protopirate_app_i.h"
|
||||
#include "../gdr_app_i.h"
|
||||
#ifdef ENABLE_SUB_DECODE_SCENE
|
||||
#include <furi.h>
|
||||
#include <storage/storage.h>
|
||||
|
||||
|
Before Width: | Height: | Size: 171 B After Width: | Height: | Size: 171 B |
Binary file not shown.
|
After Width: | Height: | Size: 171 B |
@@ -402,7 +402,7 @@ static bool subghz_protocol_encoder_alutech_at_4n_get_upload(
|
||||
|
||||
// Save original button for later use
|
||||
if(subghz_custom_btn_get_original() == 0) {
|
||||
subghz_custom_btn_set_original(btn);
|
||||
// subghz_custom_btn_set_original(btn);
|
||||
}
|
||||
|
||||
btn = subghz_protocol_alutech_at_4n_get_btn_code();
|
||||
@@ -727,9 +727,9 @@ static void subghz_protocol_alutech_at_4n_remote_controller(
|
||||
|
||||
// Save original button for later use
|
||||
if(subghz_custom_btn_get_original() == 0) {
|
||||
subghz_custom_btn_set_original(instance->btn);
|
||||
// subghz_custom_btn_set_original(instance->btn);
|
||||
}
|
||||
subghz_custom_btn_set_max(4);
|
||||
// subghz_custom_btn_set_max(4);
|
||||
}
|
||||
|
||||
uint8_t subghz_protocol_decoder_alutech_at_4n_get_hash_data(void* context) {
|
||||
|
||||
@@ -206,10 +206,10 @@ static uint64_t
|
||||
generic->seed = ((uint16_t)encrypted_data[14] << 8) | encrypted_data[15];
|
||||
|
||||
// Save original button for later use
|
||||
if(subghz_custom_btn_get_original() == 0) {
|
||||
subghz_custom_btn_set_original(generic->btn);
|
||||
}
|
||||
subghz_custom_btn_set_max(2);
|
||||
// if(subghz_custom_btn_get_original() == 0) {
|
||||
// subghz_custom_btn_set_original(generic->btn);
|
||||
// }
|
||||
// subghz_custom_btn_set_max(2);
|
||||
|
||||
return middle_bytes;
|
||||
}
|
||||
|
||||
@@ -244,9 +244,9 @@ static void subghz_protocol_encoder_came_atomo_get_upload(
|
||||
}
|
||||
|
||||
// Save original button for later use
|
||||
if(subghz_custom_btn_get_original() == 0) {
|
||||
subghz_custom_btn_set_original(btn);
|
||||
}
|
||||
// if(subghz_custom_btn_get_original() == 0) {
|
||||
// // // subghz_custom_btn_set_original(btn);
|
||||
// }
|
||||
|
||||
btn = subghz_protocol_came_atomo_get_btn_code();
|
||||
|
||||
@@ -669,9 +669,9 @@ static void subghz_protocol_came_atomo_remote_controller(SubGhzBlockGeneric* ins
|
||||
|
||||
// Save original button for later use
|
||||
if(subghz_custom_btn_get_original() == 0) {
|
||||
subghz_custom_btn_set_original(instance->btn);
|
||||
// subghz_custom_btn_set_original(instance->btn);
|
||||
}
|
||||
subghz_custom_btn_set_max(3);
|
||||
// subghz_custom_btn_set_max(3);
|
||||
}
|
||||
|
||||
void atomo_encrypt(uint8_t* buff) {
|
||||
|
||||
@@ -131,7 +131,7 @@ static bool subghz_protocol_faac_slh_gen_data(SubGhzProtocolEncoderFaacSLH* inst
|
||||
} else {
|
||||
// TODO: Stupid bypass for custom button, remake later
|
||||
if(subghz_custom_btn_get_original() == 0) {
|
||||
subghz_custom_btn_set_original(0xF);
|
||||
// subghz_custom_btn_set_original(0xF);
|
||||
}
|
||||
|
||||
uint8_t custom_btn_id = subghz_custom_btn_get();
|
||||
@@ -565,10 +565,10 @@ static void subghz_protocol_faac_slh_check_remote_controller(
|
||||
|
||||
// TODO: Stupid bypass for custom button, remake later
|
||||
if(subghz_custom_btn_get_original() == 0) {
|
||||
subghz_custom_btn_set_original(0xF);
|
||||
// subghz_custom_btn_set_original(0xF);
|
||||
}
|
||||
|
||||
subghz_custom_btn_set_max(1);
|
||||
// subghz_custom_btn_set_max(1);
|
||||
|
||||
uint8_t data_tmp = 0;
|
||||
uint8_t data_prg[8];
|
||||
|
||||
@@ -230,10 +230,10 @@ static void subghz_protocol_gangqi_remote_controller(SubGhzBlockGeneric* instanc
|
||||
instance->serial = (instance->data & 0xFFFFF0000) >> 16;
|
||||
|
||||
// Save original button for later use
|
||||
if(subghz_custom_btn_get_original() == 0) {
|
||||
subghz_custom_btn_set_original(instance->btn);
|
||||
}
|
||||
subghz_custom_btn_set_max(3);
|
||||
// if(subghz_custom_btn_get_original() == 0) {
|
||||
// subghz_custom_btn_set_original(instance->btn);
|
||||
// }
|
||||
// subghz_custom_btn_set_max(3);
|
||||
|
||||
// GangQi Decoder
|
||||
// 09.2024 - @xMasterX (MMX) (last update - bytesum calculation at 02.2025)
|
||||
|
||||
+4
-4
@@ -4,11 +4,11 @@
|
||||
#include <lib/subghz/types.h>
|
||||
#include "protocol_items.h"
|
||||
|
||||
#define PROTOPIRATE_PROTOCOL_PLUGIN_APP_ID "protopirate_protocol_plugins"
|
||||
#define PROTOPIRATE_PROTOCOL_PLUGIN_API_VERSION 1U
|
||||
#define GDR_PROTOCOL_PLUGIN_APP_ID "gdr_protocol_plugins"
|
||||
#define GDR_PROTOCOL_PLUGIN_API_VERSION 1U
|
||||
|
||||
typedef struct {
|
||||
const char* plugin_name;
|
||||
ProtoPirateProtocolRegistryFilter filter;
|
||||
GDRProtocolRegistryFilter filter;
|
||||
const SubGhzProtocolRegistry* registry;
|
||||
} ProtoPirateProtocolPlugin;
|
||||
} GDRProtocolPlugin;
|
||||
@@ -223,9 +223,7 @@ static void subghz_protocol_hay21_remote_controller(SubGhzBlockGeneric* instance
|
||||
|
||||
// Save original button for later use
|
||||
if(subghz_custom_btn_get_original() == 0) {
|
||||
subghz_custom_btn_set_original(instance->btn);
|
||||
}
|
||||
subghz_custom_btn_set_max(2);
|
||||
|
||||
|
||||
// Hay21 Decoder
|
||||
// 09.2024 - @xMasterX (MMX)
|
||||
|
||||
@@ -225,9 +225,9 @@ static void subghz_protocol_hollarm_remote_controller(SubGhzBlockGeneric* instan
|
||||
|
||||
// Save original button for later use
|
||||
if(subghz_custom_btn_get_original() == 0) {
|
||||
subghz_custom_btn_set_original(instance->btn);
|
||||
// subghz_custom_btn_set_original(instance->btn);
|
||||
}
|
||||
subghz_custom_btn_set_max(3);
|
||||
// subghz_custom_btn_set_max(3);
|
||||
|
||||
// Hollarm Decoder
|
||||
// 09.2024 - @xMasterX (MMX)
|
||||
|
||||
@@ -147,7 +147,7 @@ static bool
|
||||
subghz_protocol_jarolift_gen_data(SubGhzProtocolEncoderJarolift* instance, uint8_t btn) {
|
||||
// Save original button for later use
|
||||
if(subghz_custom_btn_get_original() == 0) {
|
||||
subghz_custom_btn_set_original(btn);
|
||||
// subghz_custom_btn_set_original(btn);
|
||||
}
|
||||
|
||||
btn = subghz_protocol_jarolift_get_btn_code();
|
||||
@@ -605,9 +605,9 @@ static void subghz_protocol_jarolift_remote_controller(
|
||||
instance->cnt = decrypt & 0xFFFF;
|
||||
// Save original button for later use
|
||||
if(subghz_custom_btn_get_original() == 0) {
|
||||
subghz_custom_btn_set_original(instance->btn);
|
||||
// subghz_custom_btn_set_original(instance->btn);
|
||||
}
|
||||
subghz_custom_btn_set_max(3);
|
||||
// subghz_custom_btn_set_max(3);
|
||||
} else {
|
||||
instance->btn = 0;
|
||||
instance->serial = 0;
|
||||
|
||||
@@ -10,7 +10,7 @@ uint64_t kia_v6_a_key = 0;
|
||||
uint64_t kia_v6_b_key = 0;
|
||||
uint64_t kia_v5_key = 0;
|
||||
|
||||
void protopirate_keys_load(SubGhzEnvironment* environment) {
|
||||
void gdr_keys_load(SubGhzEnvironment* environment) {
|
||||
SubGhzKeystore* keystore = subghz_environment_get_keystore(environment);
|
||||
// Load keys from secure keystore
|
||||
for
|
||||
|
||||
@@ -18,4 +18,4 @@ uint64_t get_kia_v6_keystore_b();
|
||||
|
||||
uint64_t get_kia_v5_key();
|
||||
|
||||
void protopirate_keys_load(SubGhzEnvironment* environment);
|
||||
void gdr_keys_load(SubGhzEnvironment* environment);
|
||||
|
||||
@@ -149,7 +149,7 @@ static bool subghz_protocol_kinggates_stylo_4k_gen_data(
|
||||
uint8_t btn) {
|
||||
// Save original button for later use
|
||||
if(subghz_custom_btn_get_original() == 0) {
|
||||
subghz_custom_btn_set_original(btn);
|
||||
// subghz_custom_btn_set_original(btn);
|
||||
}
|
||||
|
||||
btn = subghz_protocol_kinggates_stylo_4k_get_btn_code();
|
||||
@@ -576,9 +576,9 @@ static void subghz_protocol_kinggates_stylo_4k_remote_controller(
|
||||
instance->cnt = decrypt & 0xFFFF;
|
||||
// Save original button for later use
|
||||
if(subghz_custom_btn_get_original() == 0) {
|
||||
subghz_custom_btn_set_original(instance->btn);
|
||||
// subghz_custom_btn_set_original(instance->btn);
|
||||
}
|
||||
subghz_custom_btn_set_max(3);
|
||||
// subghz_custom_btn_set_max(3);
|
||||
} else {
|
||||
instance->btn = 0;
|
||||
instance->serial = 0;
|
||||
|
||||
@@ -145,7 +145,7 @@ static void subghz_protocol_encoder_nice_flor_s_get_upload(
|
||||
|
||||
// Save original button for later use
|
||||
if(subghz_custom_btn_get_original() == 0) {
|
||||
subghz_custom_btn_set_original(btn);
|
||||
// subghz_custom_btn_set_original(btn);
|
||||
}
|
||||
|
||||
btn = subghz_protocol_nice_flor_s_get_btn_code();
|
||||
@@ -759,10 +759,10 @@ static void subghz_protocol_nice_flor_s_remote_controller(
|
||||
}
|
||||
|
||||
// Save original button for later use
|
||||
if(subghz_custom_btn_get_original() == 0) {
|
||||
subghz_custom_btn_set_original(instance->btn);
|
||||
}
|
||||
subghz_custom_btn_set_max(4);
|
||||
// if(subghz_custom_btn_get_original() == 0) {
|
||||
// // subghz_custom_btn_set_original(instance->btn);
|
||||
// }
|
||||
// // subghz_custom_btn_set_max(4);
|
||||
}
|
||||
|
||||
uint8_t subghz_protocol_decoder_nice_flor_s_get_hash_data(void* context) {
|
||||
|
||||
@@ -250,9 +250,9 @@ static bool
|
||||
uint8_t btn = instance->generic.btn;
|
||||
|
||||
// Save original button for later use
|
||||
if(subghz_custom_btn_get_original() == 0) {
|
||||
subghz_custom_btn_set_original(btn);
|
||||
}
|
||||
// if(subghz_custom_btn_get_original() == 0) {
|
||||
// // // subghz_custom_btn_set_original(btn);
|
||||
// }
|
||||
|
||||
// Get custom button code
|
||||
// This will override the btn variable if a custom button is set
|
||||
@@ -611,9 +611,9 @@ static void subghz_protocol_phoenix_v2_check_remote_controller(SubGhzBlockGeneri
|
||||
|
||||
// Save original button for later use
|
||||
if(subghz_custom_btn_get_original() == 0) {
|
||||
subghz_custom_btn_set_original(instance->btn);
|
||||
// subghz_custom_btn_set_original(instance->btn);
|
||||
}
|
||||
subghz_custom_btn_set_max(4);
|
||||
// subghz_custom_btn_set_max(4);
|
||||
}
|
||||
|
||||
uint8_t subghz_protocol_decoder_phoenix_v2_get_hash_data(void* context) {
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
#include "../gdr_protocol_plugins.h"
|
||||
|
||||
#include "../alutech_at_4n.h"
|
||||
#include "../beninca_arc.h"
|
||||
#include "../came.h"
|
||||
#include "../came_atomo.h"
|
||||
#include "../came_twee.h"
|
||||
#include "../chamberlain_code.h"
|
||||
#include "../clemsa.h"
|
||||
#include "../dooya.h"
|
||||
#include "../faac_slh.h"
|
||||
#include "../gate_tx.h"
|
||||
#include "../hormann.h"
|
||||
#include "../keeloq.h"
|
||||
#include "../linear.h"
|
||||
#include "../linear_delta3.h"
|
||||
#include "../megacode.h"
|
||||
#include "../nice_flo.h"
|
||||
#include "../nice_flor_s.h"
|
||||
#include "../princeton.h"
|
||||
#include "../somfy_keytis.h"
|
||||
#include "../somfy_telis.h"
|
||||
|
||||
#define GDR_AM_PROTOCOL(symbol)
|
||||
#include "gdr_am_protocols_list.inc"
|
||||
#undef GDR_AM_PROTOCOL
|
||||
|
||||
static const SubGhzProtocol* const gdr_protocol_registry_am_items[] = {
|
||||
#define GDR_AM_PROTOCOL(symbol) &symbol,
|
||||
#include "gdr_am_protocols_list.inc"
|
||||
#undef GDR_AM_PROTOCOL
|
||||
};
|
||||
|
||||
static const SubGhzProtocolRegistry gdr_protocol_registry_am = {
|
||||
.items = gdr_protocol_registry_am_items,
|
||||
.size = sizeof(gdr_protocol_registry_am_items) /
|
||||
sizeof(gdr_protocol_registry_am_items[0]),
|
||||
};
|
||||
|
||||
static const GDRProtocolPlugin gdr_am_plugin = {
|
||||
.plugin_name = "Garage Door Remote AM Registry",
|
||||
.filter = GDRProtocolRegistryFilterAM,
|
||||
.registry = &gdr_protocol_registry_am,
|
||||
};
|
||||
|
||||
static const FlipperAppPluginDescriptor gdr_am_plugin_descriptor = {
|
||||
.appid = GDR_PROTOCOL_PLUGIN_APP_ID,
|
||||
.ep_api_version = GDR_PROTOCOL_PLUGIN_API_VERSION,
|
||||
.entry_point = &gdr_am_plugin,
|
||||
};
|
||||
|
||||
const FlipperAppPluginDescriptor* gdr_am_plugin_ep(void) {
|
||||
return &gdr_am_plugin_descriptor;
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
GDR_AM_PROTOCOL(subghz_protocol_alutech_at_4n)
|
||||
GDR_AM_PROTOCOL(subghz_protocol_beninca_arc)
|
||||
GDR_AM_PROTOCOL(subghz_protocol_came)
|
||||
GDR_AM_PROTOCOL(subghz_protocol_came_atomo)
|
||||
GDR_AM_PROTOCOL(subghz_protocol_came_twee)
|
||||
GDR_AM_PROTOCOL(subghz_protocol_chamb_code)
|
||||
GDR_AM_PROTOCOL(subghz_protocol_clemsa)
|
||||
GDR_AM_PROTOCOL(subghz_protocol_dooya)
|
||||
GDR_AM_PROTOCOL(subghz_protocol_faac_slh)
|
||||
GDR_AM_PROTOCOL(subghz_protocol_gate_tx)
|
||||
GDR_AM_PROTOCOL(subghz_protocol_hormann)
|
||||
GDR_AM_PROTOCOL(subghz_protocol_keeloq)
|
||||
GDR_AM_PROTOCOL(subghz_protocol_linear)
|
||||
GDR_AM_PROTOCOL(subghz_protocol_linear_delta3)
|
||||
GDR_AM_PROTOCOL(subghz_protocol_megacode)
|
||||
GDR_AM_PROTOCOL(subghz_protocol_nice_flo)
|
||||
GDR_AM_PROTOCOL(subghz_protocol_nice_flor_s)
|
||||
GDR_AM_PROTOCOL(subghz_protocol_princeton)
|
||||
GDR_AM_PROTOCOL(subghz_protocol_somfy_keytis)
|
||||
GDR_AM_PROTOCOL(subghz_protocol_somfy_telis)
|
||||
@@ -0,0 +1,28 @@
|
||||
#include "../gdr_protocol_plugins.h"
|
||||
#include "../ansonic.h"
|
||||
|
||||
static const SubGhzProtocol* const gdr_protocol_registry_fm_items[] = {
|
||||
&subghz_protocol_ansonic,
|
||||
};
|
||||
|
||||
static const SubGhzProtocolRegistry gdr_protocol_registry_fm = {
|
||||
.items = gdr_protocol_registry_fm_items,
|
||||
.size = sizeof(gdr_protocol_registry_fm_items) /
|
||||
sizeof(gdr_protocol_registry_fm_items[0]),
|
||||
};
|
||||
|
||||
static const GDRProtocolPlugin gdr_fm_plugin = {
|
||||
.plugin_name = "Garage Door Remote FM Registry",
|
||||
.filter = GDRProtocolRegistryFilterFM,
|
||||
.registry = &gdr_protocol_registry_fm,
|
||||
};
|
||||
|
||||
static const FlipperAppPluginDescriptor gdr_fm_plugin_descriptor = {
|
||||
.appid = GDR_PROTOCOL_PLUGIN_APP_ID,
|
||||
.ep_api_version = GDR_PROTOCOL_PLUGIN_API_VERSION,
|
||||
.entry_point = &gdr_fm_plugin,
|
||||
};
|
||||
|
||||
const FlipperAppPluginDescriptor* gdr_fm_plugin_ep(void) {
|
||||
return &gdr_fm_plugin_descriptor;
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
#include "../protopirate_protocol_plugins.h"
|
||||
|
||||
#include "../alutech_at_4n.h"
|
||||
#include "../beninca_arc.h"
|
||||
#include "../came.h"
|
||||
#include "../came_atomo.h"
|
||||
#include "../came_twee.h"
|
||||
#include "../chamberlain_code.h"
|
||||
#include "../clemsa.h"
|
||||
#include "../dooya.h"
|
||||
#include "../faac_slh.h"
|
||||
#include "../gate_tx.h"
|
||||
#include "../hormann.h"
|
||||
#include "../keeloq.h"
|
||||
#include "../linear.h"
|
||||
#include "../linear_delta3.h"
|
||||
#include "../megacode.h"
|
||||
#include "../nice_flo.h"
|
||||
#include "../nice_flor_s.h"
|
||||
#include "../princeton.h"
|
||||
#include "../somfy_keytis.h"
|
||||
#include "../somfy_telis.h"
|
||||
|
||||
#define PROTOPIRATE_AM_PROTOCOL(symbol)
|
||||
#include "protopirate_am_protocols_list.inc"
|
||||
#undef PROTOPIRATE_AM_PROTOCOL
|
||||
|
||||
static const SubGhzProtocol* const protopirate_protocol_registry_am_items[] = {
|
||||
#define PROTOPIRATE_AM_PROTOCOL(symbol) &symbol,
|
||||
#include "protopirate_am_protocols_list.inc"
|
||||
#undef PROTOPIRATE_AM_PROTOCOL
|
||||
};
|
||||
|
||||
static const SubGhzProtocolRegistry protopirate_protocol_registry_am = {
|
||||
.items = protopirate_protocol_registry_am_items,
|
||||
.size = sizeof(protopirate_protocol_registry_am_items) /
|
||||
sizeof(protopirate_protocol_registry_am_items[0]),
|
||||
};
|
||||
|
||||
static const ProtoPirateProtocolPlugin protopirate_am_plugin = {
|
||||
.plugin_name = "Garage Door Remote AM Registry",
|
||||
.filter = ProtoPirateProtocolRegistryFilterAM,
|
||||
.registry = &protopirate_protocol_registry_am,
|
||||
};
|
||||
|
||||
static const FlipperAppPluginDescriptor protopirate_am_plugin_descriptor = {
|
||||
.appid = PROTOPIRATE_PROTOCOL_PLUGIN_APP_ID,
|
||||
.ep_api_version = PROTOPIRATE_PROTOCOL_PLUGIN_API_VERSION,
|
||||
.entry_point = &protopirate_am_plugin,
|
||||
};
|
||||
|
||||
const FlipperAppPluginDescriptor* protopirate_am_plugin_ep(void) {
|
||||
return &protopirate_am_plugin_descriptor;
|
||||
}
|
||||
-20
@@ -1,20 +0,0 @@
|
||||
PROTOPIRATE_AM_PROTOCOL(subghz_protocol_alutech_at_4n)
|
||||
PROTOPIRATE_AM_PROTOCOL(subghz_protocol_beninca_arc)
|
||||
PROTOPIRATE_AM_PROTOCOL(subghz_protocol_came)
|
||||
PROTOPIRATE_AM_PROTOCOL(subghz_protocol_came_atomo)
|
||||
PROTOPIRATE_AM_PROTOCOL(subghz_protocol_came_twee)
|
||||
PROTOPIRATE_AM_PROTOCOL(subghz_protocol_chamb_code)
|
||||
PROTOPIRATE_AM_PROTOCOL(subghz_protocol_clemsa)
|
||||
PROTOPIRATE_AM_PROTOCOL(subghz_protocol_dooya)
|
||||
PROTOPIRATE_AM_PROTOCOL(subghz_protocol_faac_slh)
|
||||
PROTOPIRATE_AM_PROTOCOL(subghz_protocol_gate_tx)
|
||||
PROTOPIRATE_AM_PROTOCOL(subghz_protocol_hormann)
|
||||
PROTOPIRATE_AM_PROTOCOL(subghz_protocol_keeloq)
|
||||
PROTOPIRATE_AM_PROTOCOL(subghz_protocol_linear)
|
||||
PROTOPIRATE_AM_PROTOCOL(subghz_protocol_linear_delta3)
|
||||
PROTOPIRATE_AM_PROTOCOL(subghz_protocol_megacode)
|
||||
PROTOPIRATE_AM_PROTOCOL(subghz_protocol_nice_flo)
|
||||
PROTOPIRATE_AM_PROTOCOL(subghz_protocol_nice_flor_s)
|
||||
PROTOPIRATE_AM_PROTOCOL(subghz_protocol_princeton)
|
||||
PROTOPIRATE_AM_PROTOCOL(subghz_protocol_somfy_keytis)
|
||||
PROTOPIRATE_AM_PROTOCOL(subghz_protocol_somfy_telis)
|
||||
@@ -1,28 +0,0 @@
|
||||
#include "../protopirate_protocol_plugins.h"
|
||||
#include "../ansonic.h"
|
||||
|
||||
static const SubGhzProtocol* const protopirate_protocol_registry_fm_items[] = {
|
||||
&subghz_protocol_ansonic,
|
||||
};
|
||||
|
||||
static const SubGhzProtocolRegistry protopirate_protocol_registry_fm = {
|
||||
.items = protopirate_protocol_registry_fm_items,
|
||||
.size = sizeof(protopirate_protocol_registry_fm_items) /
|
||||
sizeof(protopirate_protocol_registry_fm_items[0]),
|
||||
};
|
||||
|
||||
static const ProtoPirateProtocolPlugin protopirate_fm_plugin = {
|
||||
.plugin_name = "Garage Door Remote FM Registry",
|
||||
.filter = ProtoPirateProtocolRegistryFilterFM,
|
||||
.registry = &protopirate_protocol_registry_fm,
|
||||
};
|
||||
|
||||
static const FlipperAppPluginDescriptor protopirate_fm_plugin_descriptor = {
|
||||
.appid = PROTOPIRATE_PROTOCOL_PLUGIN_APP_ID,
|
||||
.ep_api_version = PROTOPIRATE_PROTOCOL_PLUGIN_API_VERSION,
|
||||
.entry_point = &protopirate_fm_plugin,
|
||||
};
|
||||
|
||||
const FlipperAppPluginDescriptor* protopirate_fm_plugin_ep(void) {
|
||||
return &protopirate_fm_plugin_descriptor;
|
||||
}
|
||||
@@ -330,9 +330,9 @@ static void subghz_protocol_princeton_check_remote_controller(SubGhzBlockGeneric
|
||||
|
||||
// Save original button for later use
|
||||
if(subghz_custom_btn_get_original() == 0) {
|
||||
subghz_custom_btn_set_original(instance->btn);
|
||||
// subghz_custom_btn_set_original(instance->btn);
|
||||
}
|
||||
subghz_custom_btn_set_max(4);
|
||||
// subghz_custom_btn_set_max(4);
|
||||
}
|
||||
|
||||
SubGhzProtocolStatus
|
||||
|
||||
@@ -4,17 +4,17 @@
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#define TAG "ProtoPirateRegistry"
|
||||
#define TAG "GDRRegistry"
|
||||
|
||||
#define PROTOPIRATE_CC1101_REG_MDMCFG2 0x12U
|
||||
#define PROTOPIRATE_CC1101_MOD_FORMAT_MASK 0x70U
|
||||
#define PROTOPIRATE_CC1101_MOD_FORMAT_2FSK 0x00U
|
||||
#define PROTOPIRATE_CC1101_MOD_FORMAT_GFSK 0x10U
|
||||
#define PROTOPIRATE_CC1101_MOD_FORMAT_ASK_OOK 0x30U
|
||||
#define PROTOPIRATE_CC1101_MOD_FORMAT_4FSK 0x40U
|
||||
#define PROTOPIRATE_CC1101_MOD_FORMAT_MSK 0x70U
|
||||
#define GDR_CC1101_REG_MDMCFG2 0x12U
|
||||
#define GDR_CC1101_MOD_FORMAT_MASK 0x70U
|
||||
#define GDR_CC1101_MOD_FORMAT_2FSK 0x00U
|
||||
#define GDR_CC1101_MOD_FORMAT_GFSK 0x10U
|
||||
#define GDR_CC1101_MOD_FORMAT_ASK_OOK 0x30U
|
||||
#define GDR_CC1101_MOD_FORMAT_4FSK 0x40U
|
||||
#define GDR_CC1101_MOD_FORMAT_MSK 0x70U
|
||||
|
||||
static bool protopirate_preset_try_get_register(
|
||||
static bool gdr_preset_try_get_register(
|
||||
const uint8_t* preset_data,
|
||||
size_t preset_data_size,
|
||||
uint8_t reg,
|
||||
@@ -40,41 +40,41 @@ static bool protopirate_preset_try_get_register(
|
||||
return false;
|
||||
}
|
||||
|
||||
ProtoPirateProtocolRegistryFilter protopirate_get_protocol_registry_filter_for_preset(
|
||||
GDRProtocolRegistryFilter gdr_get_protocol_registry_filter_for_preset(
|
||||
const uint8_t* preset_data,
|
||||
size_t preset_data_size) {
|
||||
uint8_t mdmcfg2 = 0U;
|
||||
|
||||
if(!protopirate_preset_try_get_register(
|
||||
preset_data, preset_data_size, PROTOPIRATE_CC1101_REG_MDMCFG2, &mdmcfg2)) {
|
||||
if(!gdr_preset_try_get_register(
|
||||
preset_data, preset_data_size, GDR_CC1101_REG_MDMCFG2, &mdmcfg2)) {
|
||||
FURI_LOG_W(TAG, "Preset missing MDMCFG2, defaulting to AM registry");
|
||||
return ProtoPirateProtocolRegistryFilterAM;
|
||||
return GDRProtocolRegistryFilterAM;
|
||||
}
|
||||
|
||||
// MDMCFG2[6:4] stores the CC1101 modulation format.
|
||||
// ASK/OOK maps to our AM decoder set; the FSK-family formats map to FM.
|
||||
switch(mdmcfg2 & PROTOPIRATE_CC1101_MOD_FORMAT_MASK) {
|
||||
case PROTOPIRATE_CC1101_MOD_FORMAT_ASK_OOK:
|
||||
return ProtoPirateProtocolRegistryFilterAM;
|
||||
case PROTOPIRATE_CC1101_MOD_FORMAT_2FSK:
|
||||
case PROTOPIRATE_CC1101_MOD_FORMAT_GFSK:
|
||||
case PROTOPIRATE_CC1101_MOD_FORMAT_4FSK:
|
||||
case PROTOPIRATE_CC1101_MOD_FORMAT_MSK:
|
||||
return ProtoPirateProtocolRegistryFilterFM;
|
||||
switch(mdmcfg2 & GDR_CC1101_MOD_FORMAT_MASK) {
|
||||
case GDR_CC1101_MOD_FORMAT_ASK_OOK:
|
||||
return GDRProtocolRegistryFilterAM;
|
||||
case GDR_CC1101_MOD_FORMAT_2FSK:
|
||||
case GDR_CC1101_MOD_FORMAT_GFSK:
|
||||
case GDR_CC1101_MOD_FORMAT_4FSK:
|
||||
case GDR_CC1101_MOD_FORMAT_MSK:
|
||||
return GDRProtocolRegistryFilterFM;
|
||||
default:
|
||||
FURI_LOG_W(TAG, "Unknown MDMCFG2 0x%02X, defaulting to AM registry", mdmcfg2);
|
||||
return ProtoPirateProtocolRegistryFilterAM;
|
||||
return GDRProtocolRegistryFilterAM;
|
||||
}
|
||||
}
|
||||
|
||||
const char*
|
||||
protopirate_get_protocol_registry_filter_name(ProtoPirateProtocolRegistryFilter filter) {
|
||||
return (filter == ProtoPirateProtocolRegistryFilterFM) ? "FM" : "AM";
|
||||
gdr_get_protocol_registry_filter_name(GDRProtocolRegistryFilter filter) {
|
||||
return (filter == GDRProtocolRegistryFilterFM) ? "FM" : "AM";
|
||||
}
|
||||
|
||||
#ifdef ENABLE_TIMING_TUNER_SCENE
|
||||
// Protocol timing definitions - mirrors the SubGhzBlockConst in each protocol
|
||||
static const ProtoPirateProtocolTiming protocol_timings[] = {
|
||||
static const GDRProtocolTiming protocol_timings[] = {
|
||||
// Star Line: PWM 250/500µs
|
||||
{
|
||||
.name = "Star Line",
|
||||
@@ -96,7 +96,7 @@ static const ProtoPirateProtocolTiming protocol_timings[] = {
|
||||
|
||||
static const size_t protocol_timings_count = COUNT_OF(protocol_timings);
|
||||
|
||||
const ProtoPirateProtocolTiming* protopirate_get_protocol_timing(const char* protocol_name) {
|
||||
const GDRProtocolTiming* gdr_get_protocol_timing(const char* protocol_name) {
|
||||
if(!protocol_name) return NULL;
|
||||
|
||||
for(size_t i = 0; i < protocol_timings_count; i++) {
|
||||
@@ -124,12 +124,12 @@ const ProtoPirateProtocolTiming* protopirate_get_protocol_timing(const char* pro
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const ProtoPirateProtocolTiming* protopirate_get_protocol_timing_by_index(size_t index) {
|
||||
const GDRProtocolTiming* gdr_get_protocol_timing_by_index(size_t index) {
|
||||
if(index >= protocol_timings_count) return NULL;
|
||||
return &protocol_timings[index];
|
||||
}
|
||||
|
||||
size_t protopirate_get_protocol_timing_count(void) {
|
||||
size_t gdr_get_protocol_timing_count(void) {
|
||||
return protocol_timings_count;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -6,16 +6,16 @@
|
||||
#include "keeloq.h"
|
||||
|
||||
typedef enum {
|
||||
ProtoPirateProtocolRegistryFilterAM = 0,
|
||||
ProtoPirateProtocolRegistryFilterFM,
|
||||
} ProtoPirateProtocolRegistryFilter;
|
||||
GDRProtocolRegistryFilterAM = 0,
|
||||
GDRProtocolRegistryFilterFM,
|
||||
} GDRProtocolRegistryFilter;
|
||||
|
||||
ProtoPirateProtocolRegistryFilter protopirate_get_protocol_registry_filter_for_preset(
|
||||
GDRProtocolRegistryFilter gdr_get_protocol_registry_filter_for_preset(
|
||||
const uint8_t* preset_data,
|
||||
size_t preset_data_size);
|
||||
|
||||
const char*
|
||||
protopirate_get_protocol_registry_filter_name(ProtoPirateProtocolRegistryFilter filter);
|
||||
gdr_get_protocol_registry_filter_name(GDRProtocolRegistryFilter filter);
|
||||
|
||||
#ifdef ENABLE_TIMING_TUNER_SCENE
|
||||
// Timing information for protocol analysis
|
||||
@@ -25,14 +25,14 @@ typedef struct {
|
||||
uint32_t te_long;
|
||||
uint32_t te_delta;
|
||||
uint32_t min_count_bit;
|
||||
} ProtoPirateProtocolTiming;
|
||||
} GDRProtocolTiming;
|
||||
|
||||
// Get timing info for a protocol by name (returns NULL if not found)
|
||||
const ProtoPirateProtocolTiming* protopirate_get_protocol_timing(const char* protocol_name);
|
||||
const GDRProtocolTiming* gdr_get_protocol_timing(const char* protocol_name);
|
||||
|
||||
// Get timing info by index (for iteration)
|
||||
const ProtoPirateProtocolTiming* protopirate_get_protocol_timing_by_index(size_t index);
|
||||
const GDRProtocolTiming* gdr_get_protocol_timing_by_index(size_t index);
|
||||
|
||||
// Get number of protocols with timing info
|
||||
size_t protopirate_get_protocol_timing_count(void);
|
||||
size_t gdr_get_protocol_timing_count(void);
|
||||
#endif
|
||||
|
||||
@@ -249,7 +249,7 @@ size_t
|
||||
|
||||
void pp_encoder_free(void* context) {
|
||||
furi_check(context);
|
||||
ProtoPirateEncoderHeader* hdr = context;
|
||||
GDREncoderHeader* hdr = context;
|
||||
hdr->encoder.upload = NULL;
|
||||
hdr->encoder.size_upload = 0;
|
||||
free(hdr);
|
||||
@@ -257,14 +257,14 @@ void pp_encoder_free(void* context) {
|
||||
|
||||
void pp_encoder_stop(void* context) {
|
||||
furi_check(context);
|
||||
ProtoPirateEncoderHeader* hdr = context;
|
||||
GDREncoderHeader* hdr = context;
|
||||
hdr->encoder.is_running = false;
|
||||
hdr->encoder.front = 0;
|
||||
}
|
||||
|
||||
LevelDuration pp_encoder_yield(void* context) {
|
||||
furi_check(context);
|
||||
ProtoPirateEncoderHeader* hdr = context;
|
||||
GDREncoderHeader* hdr = context;
|
||||
if(hdr->encoder.repeat == 0 || !hdr->encoder.is_running || hdr->encoder.size_upload == 0) {
|
||||
hdr->encoder.is_running = false;
|
||||
return level_duration_reset();
|
||||
@@ -298,7 +298,7 @@ void pp_shared_upload_release(void) {
|
||||
|
||||
void pp_encoder_buffer_ensure(void* context, size_t capacity) {
|
||||
furi_check(context);
|
||||
ProtoPirateEncoderHeader* hdr = context;
|
||||
GDREncoderHeader* hdr = context;
|
||||
furi_check(capacity <= PP_SHARED_UPLOAD_CAPACITY);
|
||||
hdr->encoder.upload = pp_shared_upload_buffer();
|
||||
hdr->encoder.size_upload = capacity;
|
||||
@@ -306,7 +306,7 @@ void pp_encoder_buffer_ensure(void* context, size_t capacity) {
|
||||
|
||||
uint8_t pp_decoder_hash_blocks(void* context) {
|
||||
furi_check(context);
|
||||
ProtoPirateDecoderHeader* hdr = context;
|
||||
GDRDecoderHeader* hdr = context;
|
||||
return subghz_protocol_blocks_get_hash_data(
|
||||
&hdr->decoder, (hdr->decoder.decode_count_bit / 8U) + 1U);
|
||||
}
|
||||
|
||||
@@ -112,7 +112,7 @@ typedef struct {
|
||||
SubGhzProtocolDecoderBase base;
|
||||
SubGhzBlockDecoder decoder;
|
||||
SubGhzBlockGeneric generic;
|
||||
} ProtoPirateDecoderHeader;
|
||||
} GDRDecoderHeader;
|
||||
|
||||
uint8_t pp_decoder_hash_blocks(void* context);
|
||||
|
||||
@@ -121,7 +121,7 @@ void pp_decoder_free_default(void* context);
|
||||
typedef struct {
|
||||
SubGhzProtocolEncoderBase base;
|
||||
SubGhzProtocolBlockEncoder encoder;
|
||||
} ProtoPirateEncoderHeader;
|
||||
} GDREncoderHeader;
|
||||
|
||||
void pp_encoder_free(void* context);
|
||||
void pp_encoder_stop(void* context);
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <lib/flipper_application/flipper_application.h>
|
||||
#include <lib/subghz/types.h>
|
||||
#include "protocol_items.h"
|
||||
|
||||
#define PROTOPIRATE_PROTOCOL_PLUGIN_APP_ID "protopirate_protocol_plugins"
|
||||
#define PROTOPIRATE_PROTOCOL_PLUGIN_API_VERSION 1U
|
||||
|
||||
typedef struct {
|
||||
const char* plugin_name;
|
||||
ProtoPirateProtocolRegistryFilter filter;
|
||||
const SubGhzProtocolRegistry* registry;
|
||||
} ProtoPirateProtocolPlugin;
|
||||
@@ -170,9 +170,7 @@ static void subghz_protocol_encoder_roger_get_upload(SubGhzProtocolEncoderRoger*
|
||||
uint8_t btn = instance->generic.btn;
|
||||
|
||||
// Save original button for later use
|
||||
if(subghz_custom_btn_get_original() == 0) {
|
||||
subghz_custom_btn_set_original(btn);
|
||||
}
|
||||
// // // subghz_custom_btn_set_original(btn);
|
||||
|
||||
// Get custom button code
|
||||
// This will override the btn variable if a custom button is set
|
||||
@@ -251,9 +249,9 @@ static void subghz_protocol_roger_check_remote_controller(SubGhzBlockGeneric* in
|
||||
|
||||
// Save original button for later use
|
||||
if(subghz_custom_btn_get_original() == 0) {
|
||||
subghz_custom_btn_set_original(instance->btn);
|
||||
// subghz_custom_btn_set_original(instance->btn);
|
||||
}
|
||||
subghz_custom_btn_set_max(3);
|
||||
// subghz_custom_btn_set_max(3);
|
||||
}
|
||||
|
||||
SubGhzProtocolStatus
|
||||
|
||||
@@ -342,10 +342,10 @@ static void
|
||||
}
|
||||
|
||||
// Save original button for later use
|
||||
if(subghz_custom_btn_get_original() == 0) {
|
||||
subghz_custom_btn_set_original(instance->btn);
|
||||
}
|
||||
subghz_custom_btn_set_max(4);
|
||||
// if(subghz_custom_btn_get_original() == 0) {
|
||||
// subghz_custom_btn_set_original(instance->btn);
|
||||
// }
|
||||
// subghz_custom_btn_set_max(4);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -390,7 +390,7 @@ static uint8_t subghz_protocol_secplus_v2_get_btn_code(void);
|
||||
static void subghz_protocol_secplus_v2_encode(SubGhzProtocolEncoderSecPlus_v2* instance) {
|
||||
// Save original button for later use
|
||||
if(subghz_custom_btn_get_original() == 0) {
|
||||
subghz_custom_btn_set_original(instance->generic.btn);
|
||||
// subghz_custom_btn_set_original(instance->generic.btn);
|
||||
}
|
||||
|
||||
instance->generic.btn = subghz_protocol_secplus_v2_get_btn_code();
|
||||
|
||||
@@ -119,7 +119,7 @@ static bool subghz_protocol_somfy_telis_gen_data(
|
||||
|
||||
// Save original button for later use
|
||||
if(subghz_custom_btn_get_original() == 0) {
|
||||
subghz_custom_btn_set_original(btn);
|
||||
// subghz_custom_btn_set_original(btn);
|
||||
}
|
||||
|
||||
btn = subghz_protocol_somfy_telis_get_btn_code();
|
||||
@@ -627,9 +627,9 @@ static void subghz_protocol_somfy_telis_check_remote_controller(SubGhzBlockGener
|
||||
|
||||
// Save original button for later use
|
||||
if(subghz_custom_btn_get_original() == 0) {
|
||||
subghz_custom_btn_set_original(instance->btn);
|
||||
// subghz_custom_btn_set_original(instance->btn);
|
||||
}
|
||||
subghz_custom_btn_set_max(3);
|
||||
// subghz_custom_btn_set_max(3);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,237 +0,0 @@
|
||||
// protopirate_app_i.h
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
#include "helpers/protopirate_types.h"
|
||||
#include "helpers/protopirate_settings.h"
|
||||
#include "scenes/protopirate_scene.h"
|
||||
#include "views/protopirate_receiver.h"
|
||||
#include "protopirate_history.h"
|
||||
#include "helpers/radio_device_loader.h"
|
||||
#ifdef ENABLE_DUAL_RX_SCENE
|
||||
#include "helpers/protopirate_rx_chain.h"
|
||||
#include "views/protopirate_dual_receiver.h"
|
||||
#endif
|
||||
#ifdef ENABLE_SHIELD_RX_SCENE
|
||||
#include "helpers/protopirate_rx_chain.h"
|
||||
#include "helpers/protopirate_tx_chain.h"
|
||||
#endif
|
||||
|
||||
#include <gui/gui.h>
|
||||
#include <gui/view_dispatcher.h>
|
||||
#include <gui/scene_manager.h>
|
||||
#include <gui/modules/submenu.h>
|
||||
#include <gui/modules/variable_item_list.h>
|
||||
#include <gui/modules/widget.h>
|
||||
#include <gui/modules/text_input.h>
|
||||
#include <notification/notification_messages.h>
|
||||
#include <lib/subghz/subghz_setting.h>
|
||||
#include <lib/subghz/subghz_worker.h>
|
||||
#include <lib/subghz/receiver.h>
|
||||
#include <lib/subghz/transmitter.h>
|
||||
#include <lib/subghz/devices/devices.h>
|
||||
#include <lib/subghz/subghz_file_encoder_worker.h>
|
||||
#include <lib/flipper_application/plugins/plugin_manager.h>
|
||||
#include <lib/flipper_application/plugins/composite_resolver.h>
|
||||
#include <dialogs/dialogs.h>
|
||||
#include "defines.h"
|
||||
#include "protocols/protocols_common.h"
|
||||
#include "protocols/protocol_items.h"
|
||||
#include "protocols/protopirate_protocol_plugins.h"
|
||||
#ifdef ENABLE_EMULATE_FEATURE
|
||||
#include "scenes/plugins/protopirate_emulate_plugin.h"
|
||||
#endif
|
||||
#include "scenes/plugins/protopirate_psa_bf_plugin.h"
|
||||
|
||||
#define PROTOPIRATE_KEYSTORE_DIR_NAME APP_ASSETS_PATH("encrypted")
|
||||
|
||||
typedef struct ProtoPirateApp ProtoPirateApp;
|
||||
|
||||
typedef enum {
|
||||
ProtoPirateCaptureOwnerNone = 0,
|
||||
ProtoPirateCaptureOwnerReceiver,
|
||||
ProtoPirateCaptureOwnerDualReceiver,
|
||||
#ifdef ENABLE_SHIELD_RX_SCENE
|
||||
ProtoPirateCaptureOwnerShieldReceiver,
|
||||
#endif
|
||||
ProtoPirateCaptureOwnerSubDecode,
|
||||
} ProtoPirateCaptureOwner;
|
||||
|
||||
typedef struct {
|
||||
ProtoPirateHistory* history;
|
||||
FuriMutex* mutex;
|
||||
uint16_t index;
|
||||
ProtoPirateCaptureOwner owner;
|
||||
} ProtoPirateSelectedCapture;
|
||||
|
||||
typedef struct {
|
||||
SubGhzWorker* worker;
|
||||
SubGhzEnvironment* environment;
|
||||
SubGhzReceiver* receiver;
|
||||
SubGhzRadioPreset* preset;
|
||||
const SubGhzProtocolRegistry* protocol_registry;
|
||||
CompositeApiResolver* plugin_resolver;
|
||||
PluginManager* protocol_plugin_manager;
|
||||
const ProtoPirateProtocolPlugin* protocol_plugin;
|
||||
ProtoPirateProtocolRegistryFilter protocol_registry_filter;
|
||||
ProtoPirateHistory* history;
|
||||
const SubGhzDevice* radio_device;
|
||||
ProtoPirateTxRxState txrx_state;
|
||||
ProtoPirateHopperState hopper_state;
|
||||
ProtoPirateRxKeyState rx_key_state;
|
||||
uint8_t hopper_idx_frequency;
|
||||
uint8_t hopper_timeout;
|
||||
uint16_t idx_menu_chosen;
|
||||
} ProtoPirateTxRx;
|
||||
|
||||
struct ProtoPirateApp {
|
||||
Gui* gui;
|
||||
ViewDispatcher* view_dispatcher;
|
||||
SceneManager* scene_manager;
|
||||
NotificationApp* notifications;
|
||||
DialogsApp* dialogs;
|
||||
VariableItemList* variable_item_list;
|
||||
Submenu* submenu;
|
||||
Widget* widget;
|
||||
TextInput* text_input;
|
||||
View* view_about;
|
||||
FuriString* file_path;
|
||||
ProtoPirateReceiver* protopirate_receiver;
|
||||
ProtoPirateTxRx* txrx;
|
||||
SubGhzSetting* setting;
|
||||
ProtoPirateLock lock;
|
||||
FuriString* loaded_file_path;
|
||||
bool auto_save;
|
||||
bool radio_initialized;
|
||||
ProtoPirateSettings settings;
|
||||
uint32_t start_tx_time;
|
||||
uint8_t tx_power;
|
||||
char save_filename[64];
|
||||
FuriString* save_protocol;
|
||||
uint16_t save_history_idx;
|
||||
bool save_from_saved_info;
|
||||
bool emulate_disabled_for_loaded;
|
||||
bool emulate_feature_enabled;
|
||||
ProtoPirateSelectedCapture selected_capture;
|
||||
ProtoPirateCaptureOwner unsaved_history_owner;
|
||||
#ifdef ENABLE_EMULATE_FEATURE
|
||||
#define EMULATE_NAV_NONE 0U
|
||||
#define EMULATE_NAV_POP 1U
|
||||
#define EMULATE_NAV_STOP_APP 2U
|
||||
CompositeApiResolver* emulate_plugin_resolver;
|
||||
PluginManager* emulate_plugin_manager;
|
||||
const ProtoPirateEmulatePlugin* emulate_plugin;
|
||||
uint8_t emulate_nav_pending;
|
||||
#endif
|
||||
CompositeApiResolver* psa_bf_plugin_resolver;
|
||||
PluginManager* psa_bf_plugin_manager;
|
||||
const ProtoPiratePsaBfPlugin* psa_bf_plugin;
|
||||
#ifdef ENABLE_DUAL_RX_SCENE
|
||||
ProtoPirateDualReceiver* dual_receiver;
|
||||
ProtoPirateRxChain* dual_chain_a;
|
||||
ProtoPirateRxChain* dual_chain_b;
|
||||
ProtoPirateHistory* dual_history;
|
||||
FuriMutex* dual_history_mutex;
|
||||
uint32_t dual_freq_a;
|
||||
uint32_t dual_freq_b;
|
||||
uint8_t dual_preset_a;
|
||||
uint8_t dual_preset_b;
|
||||
#endif
|
||||
#ifdef ENABLE_SHIELD_RX_SCENE
|
||||
ProtoPirateRxChain* shield_rx_chain;
|
||||
ProtoPirateTxChain* shield_tx_chain;
|
||||
ProtoPirateHistory* shield_history;
|
||||
FuriMutex* shield_history_mutex;
|
||||
uint32_t shield_freq;
|
||||
uint8_t shield_preset_index;
|
||||
uint8_t shield_tx_offset_index;
|
||||
uint8_t shield_tx_power;
|
||||
bool shield_auto_save_failed;
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef ENABLE_EMULATE_FEATURE
|
||||
void protopirate_emulate_context_release(ProtoPirateApp* app);
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
ProtoPirateSetTypeFord_v0,
|
||||
ProtoPirateSetTypeMAX,
|
||||
} ProtoPirateSetType;
|
||||
|
||||
void protopirate_preset_init(
|
||||
void* context,
|
||||
const char* preset_name,
|
||||
uint32_t frequency,
|
||||
uint8_t* preset_data,
|
||||
size_t preset_data_size);
|
||||
|
||||
void protopirate_get_frequency_modulation(
|
||||
ProtoPirateApp* app,
|
||||
FuriString* frequency,
|
||||
FuriString* modulation);
|
||||
void protopirate_get_frequency_modulation_str(
|
||||
ProtoPirateApp* app,
|
||||
char* frequency,
|
||||
size_t frequency_size,
|
||||
char* modulation,
|
||||
size_t modulation_size);
|
||||
|
||||
void protopirate_begin(ProtoPirateApp* app, uint8_t* preset_data);
|
||||
uint32_t protopirate_rx(ProtoPirateApp* app, uint32_t frequency);
|
||||
void protopirate_idle(ProtoPirateApp* app);
|
||||
void protopirate_rx_end(ProtoPirateApp* app);
|
||||
void protopirate_sleep(ProtoPirateApp* app);
|
||||
void protopirate_hopper_update(ProtoPirateApp* app);
|
||||
void protopirate_tx(ProtoPirateApp* app, uint32_t frequency);
|
||||
void protopirate_tx_stop(ProtoPirateApp* app);
|
||||
bool protopirate_radio_init(ProtoPirateApp* app);
|
||||
void protopirate_radio_deinit(ProtoPirateApp* app);
|
||||
bool protopirate_refresh_protocol_registry(ProtoPirateApp* app, bool ensure_receiver_ready);
|
||||
bool protopirate_apply_protocol_registry_for_preset_data(
|
||||
ProtoPirateApp* app,
|
||||
const uint8_t* preset_data,
|
||||
size_t preset_data_size);
|
||||
bool protopirate_ensure_variable_item_list(ProtoPirateApp* app);
|
||||
bool protopirate_ensure_widget(ProtoPirateApp* app);
|
||||
bool protopirate_ensure_text_input(ProtoPirateApp* app);
|
||||
bool protopirate_ensure_view_about(ProtoPirateApp* app);
|
||||
bool protopirate_ensure_receiver_view(ProtoPirateApp* app);
|
||||
#ifdef ENABLE_DUAL_RX_SCENE
|
||||
bool protopirate_ensure_dual_receiver_view(ProtoPirateApp* app);
|
||||
#endif
|
||||
void protopirate_release_shared_radio_state(ProtoPirateApp* app);
|
||||
|
||||
void protopirate_rx_stack_suspend_for_tx(ProtoPirateApp* app);
|
||||
|
||||
void protopirate_rx_stack_resume_after_tx(ProtoPirateApp* app);
|
||||
|
||||
void protopirate_selected_capture_set(
|
||||
ProtoPirateApp* app,
|
||||
ProtoPirateHistory* history,
|
||||
FuriMutex* mutex,
|
||||
uint16_t index,
|
||||
ProtoPirateCaptureOwner owner);
|
||||
void protopirate_selected_capture_clear(ProtoPirateApp* app);
|
||||
bool protopirate_selected_capture_is_valid(ProtoPirateApp* app);
|
||||
ProtoPirateHistory* protopirate_selected_capture_get_history(ProtoPirateApp* app);
|
||||
uint16_t protopirate_selected_capture_get_index(ProtoPirateApp* app);
|
||||
ProtoPirateHistorySource protopirate_selected_capture_get_source(ProtoPirateApp* app);
|
||||
FlipperFormat* protopirate_selected_capture_get_raw_data(ProtoPirateApp* app);
|
||||
bool protopirate_selected_capture_get_path(ProtoPirateApp* app, FuriString* out_path);
|
||||
void protopirate_selected_capture_release_scratch(ProtoPirateApp* app);
|
||||
|
||||
void protopirate_app_free(ProtoPirateApp* app);
|
||||
|
||||
static const NotificationSequence sequence_tx = {
|
||||
&message_note_c5,
|
||||
&message_vibro_on,
|
||||
&message_red_255,
|
||||
&message_blue_255,
|
||||
&message_blink_start_10,
|
||||
&message_delay_25,
|
||||
&message_vibro_off,
|
||||
&message_delay_25,
|
||||
&message_sound_off,
|
||||
NULL,
|
||||
};
|
||||
@@ -1,63 +0,0 @@
|
||||
// protopirate_history.h
|
||||
#pragma once
|
||||
|
||||
#include <stddef.h>
|
||||
#include <lib/subghz/receiver.h>
|
||||
#include <lib/subghz/protocols/base.h>
|
||||
|
||||
#define PROTOPIRATE_HISTORY_MAX 10
|
||||
|
||||
typedef struct SubGhzEnvironment SubGhzEnvironment;
|
||||
typedef struct ProtoPirateHistory ProtoPirateHistory;
|
||||
|
||||
typedef enum {
|
||||
ProtoPirateHistorySourceUnknown = 0,
|
||||
ProtoPirateHistorySourceExternal,
|
||||
ProtoPirateHistorySourceInternal,
|
||||
ProtoPirateHistorySourceCount,
|
||||
} ProtoPirateHistorySource;
|
||||
|
||||
ProtoPirateHistory* protopirate_history_alloc(void);
|
||||
void protopirate_history_free(ProtoPirateHistory* instance);
|
||||
void protopirate_history_reset(ProtoPirateHistory* instance);
|
||||
uint16_t protopirate_history_get_item(ProtoPirateHistory* instance);
|
||||
uint16_t protopirate_history_get_last_index(ProtoPirateHistory* instance);
|
||||
ProtoPirateHistorySource protopirate_history_get_source(
|
||||
ProtoPirateHistory* instance,
|
||||
uint16_t idx);
|
||||
const char* protopirate_history_source_name(ProtoPirateHistorySource source);
|
||||
void protopirate_history_format_status_text(
|
||||
ProtoPirateHistory* instance,
|
||||
char* output,
|
||||
size_t output_size);
|
||||
void protopirate_history_get_status_text(ProtoPirateHistory* instance, FuriString* output);
|
||||
|
||||
bool protopirate_history_get_capture_path(
|
||||
ProtoPirateHistory* instance,
|
||||
uint16_t idx,
|
||||
FuriString* out_path);
|
||||
bool protopirate_history_capture_path_equals(
|
||||
ProtoPirateHistory* instance,
|
||||
uint16_t idx,
|
||||
const char* path);
|
||||
|
||||
bool protopirate_history_add_to_history(
|
||||
ProtoPirateHistory* instance,
|
||||
void* context,
|
||||
SubGhzRadioPreset* preset,
|
||||
ProtoPirateHistorySource source);
|
||||
void protopirate_history_delete_item(ProtoPirateHistory* instance, uint16_t idx);
|
||||
void protopirate_history_get_text_item_menu(
|
||||
ProtoPirateHistory* instance,
|
||||
FuriString* output,
|
||||
uint16_t idx);
|
||||
void protopirate_history_get_text_item_detail(
|
||||
ProtoPirateHistory* instance,
|
||||
uint16_t idx,
|
||||
FuriString* output,
|
||||
SubGhzEnvironment* environment);
|
||||
FlipperFormat* protopirate_history_get_raw_data(ProtoPirateHistory* instance, uint16_t idx);
|
||||
|
||||
void protopirate_history_release_scratch(ProtoPirateHistory* instance);
|
||||
|
||||
void protopirate_history_set_item_str(ProtoPirateHistory* instance, uint16_t idx, const char* str);
|
||||
@@ -0,0 +1,31 @@
|
||||
// scenes/gdr_scene.c
|
||||
#include "gdr_scene.h"
|
||||
|
||||
// Generate scene on_enter handlers array
|
||||
#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_enter,
|
||||
void (*const gdr_scene_on_enter_handlers[])(void*) = {
|
||||
#include "gdr_scene_config.h"
|
||||
};
|
||||
#undef ADD_SCENE
|
||||
|
||||
// Generate scene on_event handlers array
|
||||
#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_event,
|
||||
bool (*const gdr_scene_on_event_handlers[])(void* context, SceneManagerEvent event) = {
|
||||
#include "gdr_scene_config.h"
|
||||
};
|
||||
#undef ADD_SCENE
|
||||
|
||||
// Generate scene on_exit handlers array
|
||||
#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_exit,
|
||||
void (*const gdr_scene_on_exit_handlers[])(void* context) = {
|
||||
#include "gdr_scene_config.h"
|
||||
};
|
||||
#undef ADD_SCENE
|
||||
|
||||
// Initialize scene handlers configuration structure
|
||||
const SceneManagerHandlers gdr_scene_handlers = {
|
||||
.on_enter_handlers = gdr_scene_on_enter_handlers,
|
||||
.on_event_handlers = gdr_scene_on_event_handlers,
|
||||
.on_exit_handlers = gdr_scene_on_exit_handlers,
|
||||
.scene_num = GDRSceneNum,
|
||||
};
|
||||
+10
-10
@@ -1,31 +1,31 @@
|
||||
// scenes/protopirate_scene.h
|
||||
// scenes/gdr_scene.h
|
||||
#pragma once
|
||||
|
||||
#include <gui/scene_manager.h>
|
||||
#include "../protopirate_app_i.h"
|
||||
#include "../gdr_app_i.h"
|
||||
|
||||
// Generate scene id and total number
|
||||
#define ADD_SCENE(prefix, name, id) ProtoPirateScene##id,
|
||||
#define ADD_SCENE(prefix, name, id) GDRScene##id,
|
||||
typedef enum {
|
||||
#include "protopirate_scene_config.h"
|
||||
ProtoPirateSceneNum,
|
||||
} ProtoPirateScene;
|
||||
#include "gdr_scene_config.h"
|
||||
GDRSceneNum,
|
||||
} GDRScene;
|
||||
#undef ADD_SCENE
|
||||
|
||||
extern const SceneManagerHandlers protopirate_scene_handlers;
|
||||
extern const SceneManagerHandlers gdr_scene_handlers;
|
||||
|
||||
// Generate scene on_enter handlers declaration
|
||||
#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_enter(void*);
|
||||
#include "protopirate_scene_config.h"
|
||||
#include "gdr_scene_config.h"
|
||||
#undef ADD_SCENE
|
||||
|
||||
// Generate scene on_event handlers declaration
|
||||
#define ADD_SCENE(prefix, name, id) \
|
||||
bool prefix##_scene_##name##_on_event(void* context, SceneManagerEvent event);
|
||||
#include "protopirate_scene_config.h"
|
||||
#include "gdr_scene_config.h"
|
||||
#undef ADD_SCENE
|
||||
|
||||
// Generate scene on_exit handlers declaration
|
||||
#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_exit(void* context);
|
||||
#include "protopirate_scene_config.h"
|
||||
#include "gdr_scene_config.h"
|
||||
#undef ADD_SCENE
|
||||
+20
-20
@@ -1,7 +1,7 @@
|
||||
// scenes/protopirate_scene_about.c
|
||||
#include "../protopirate_app_i.h"
|
||||
#include "../helpers/protopirate_settings.h"
|
||||
#include "proto_pirate_icons.h"
|
||||
// scenes/gdr_scene_about.c
|
||||
#include "../gdr_app_i.h"
|
||||
#include "../helpers/gdr_settings.h"
|
||||
#include "gdr_icons.h"
|
||||
#include <gui/elements.h>
|
||||
#include <input/input.h>
|
||||
#include <dialogs/dialogs.h>
|
||||
@@ -128,7 +128,7 @@ static void about_draw_callback(Canvas* canvas, void* context) {
|
||||
// Redraw header over mask
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
canvas_draw_str(canvas, x_off, 10, "ProtoPirate v" FAP_VERSION);
|
||||
canvas_draw_str(canvas, x_off, 10, "GDR v" FAP_VERSION);
|
||||
|
||||
canvas_set_font(canvas, FontKeyboard);
|
||||
if(g_state.frame % 8 < 4) {
|
||||
@@ -159,7 +159,7 @@ static void about_draw_callback(Canvas* canvas, void* context) {
|
||||
|
||||
static bool about_input_callback(InputEvent* event, void* context) {
|
||||
furi_check(context);
|
||||
ProtoPirateApp* app = context;
|
||||
GDRApp* app = context;
|
||||
|
||||
if(event->type != InputTypePress) {
|
||||
return false;
|
||||
@@ -175,7 +175,7 @@ static bool about_input_callback(InputEvent* event, void* context) {
|
||||
if(g_state.combo_progress >= EMULATE_TOGGLE_COMBO_LEN) {
|
||||
g_state.combo_progress = 0;
|
||||
view_dispatcher_send_custom_event(
|
||||
app->view_dispatcher, ProtoPirateCustomEventAboutToggleEmulate);
|
||||
app->view_dispatcher, GDRCustomEventAboutToggleEmulate);
|
||||
}
|
||||
} else if(event->key == EMULATE_TOGGLE_COMBO[0]) {
|
||||
|
||||
@@ -187,7 +187,7 @@ static bool about_input_callback(InputEvent* event, void* context) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static void about_show_emulate_toggle_popup(ProtoPirateApp* app) {
|
||||
static void about_show_emulate_toggle_popup(GDRApp* app) {
|
||||
const bool now_enabled = app->emulate_feature_enabled;
|
||||
|
||||
DialogMessage* message = dialog_message_alloc();
|
||||
@@ -211,11 +211,11 @@ static void about_show_emulate_toggle_popup(ProtoPirateApp* app) {
|
||||
dialog_message_free(message);
|
||||
}
|
||||
|
||||
void protopirate_scene_about_on_enter(void* context) {
|
||||
void gdr_scene_about_on_enter(void* context) {
|
||||
furi_check(context);
|
||||
ProtoPirateApp* app = context;
|
||||
GDRApp* app = context;
|
||||
|
||||
if(!protopirate_ensure_view_about(app)) {
|
||||
if(!gdr_ensure_view_about(app)) {
|
||||
notification_message(app->notifications, &sequence_error);
|
||||
scene_manager_previous_scene(app->scene_manager);
|
||||
return;
|
||||
@@ -230,11 +230,11 @@ void protopirate_scene_about_on_enter(void* context) {
|
||||
view_set_input_callback(app->view_about, about_input_callback);
|
||||
view_set_context(app->view_about, app);
|
||||
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, ProtoPirateViewAbout);
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, GDRViewAbout);
|
||||
}
|
||||
|
||||
bool protopirate_scene_about_on_event(void* context, SceneManagerEvent event) {
|
||||
ProtoPirateApp* app = context;
|
||||
bool gdr_scene_about_on_event(void* context, SceneManagerEvent event) {
|
||||
GDRApp* app = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeTick) {
|
||||
@@ -252,13 +252,13 @@ bool protopirate_scene_about_on_event(void* context, SceneManagerEvent event) {
|
||||
view_commit_model(app->view_about, true);
|
||||
consumed = true;
|
||||
} else if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == ProtoPirateCustomEventAboutToggleEmulate) {
|
||||
if(event.event == GDRCustomEventAboutToggleEmulate) {
|
||||
app->emulate_feature_enabled = !app->emulate_feature_enabled;
|
||||
|
||||
ProtoPirateSettings settings;
|
||||
protopirate_settings_load(&settings);
|
||||
GDRSettings settings;
|
||||
gdr_settings_load(&settings);
|
||||
settings.emulate_feature_enabled = app->emulate_feature_enabled;
|
||||
protopirate_settings_save(&settings);
|
||||
gdr_settings_save(&settings);
|
||||
|
||||
notification_message(
|
||||
app->notifications,
|
||||
@@ -272,9 +272,9 @@ bool protopirate_scene_about_on_event(void* context, SceneManagerEvent event) {
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void protopirate_scene_about_on_exit(void* context) {
|
||||
void gdr_scene_about_on_exit(void* context) {
|
||||
furi_check(context);
|
||||
ProtoPirateApp* app = context;
|
||||
GDRApp* app = context;
|
||||
|
||||
view_set_draw_callback(app->view_about, NULL);
|
||||
view_set_input_callback(app->view_about, NULL);
|
||||
@@ -0,0 +1,29 @@
|
||||
// scenes/gdr_scene_config.h
|
||||
|
||||
#include "../defines.h"
|
||||
|
||||
ADD_SCENE(gdr, start, Start)
|
||||
#ifdef ENABLE_SUB_DECODE_SCENE
|
||||
ADD_SCENE(gdr, sub_decode, SubDecode)
|
||||
#endif
|
||||
ADD_SCENE(gdr, about, About)
|
||||
#ifdef ENABLE_DUAL_RX_SCENE
|
||||
ADD_SCENE(gdr, dual_receiver, DualReceiver)
|
||||
ADD_SCENE(gdr, dual_receiver_config, DualReceiverConfig)
|
||||
#endif
|
||||
#ifdef ENABLE_SHIELD_RX_SCENE
|
||||
ADD_SCENE(gdr, shield_receiver, ShieldReceiver)
|
||||
ADD_SCENE(gdr, shield_receiver_config, ShieldReceiverConfig)
|
||||
#endif
|
||||
ADD_SCENE(gdr, receiver, Receiver)
|
||||
ADD_SCENE(gdr, receiver_config, ReceiverConfig)
|
||||
ADD_SCENE(gdr, receiver_info, ReceiverInfo)
|
||||
ADD_SCENE(gdr, need_saving, NeedSaving)
|
||||
ADD_SCENE(gdr, saved, Saved)
|
||||
ADD_SCENE(gdr, saved_info, SavedInfo)
|
||||
#ifdef ENABLE_EMULATE_FEATURE
|
||||
ADD_SCENE(gdr, emulate, Emulate)
|
||||
#endif
|
||||
#ifdef ENABLE_TIMING_TUNER_SCENE
|
||||
ADD_SCENE(gdr, timing_tuner, TimingTuner)
|
||||
#endif
|
||||
+113
-113
@@ -1,29 +1,29 @@
|
||||
// scenes/protopirate_scene_dual_receiver.c
|
||||
#include "../protopirate_app_i.h"
|
||||
// scenes/gdr_scene_dual_receiver.c
|
||||
#include "../gdr_app_i.h"
|
||||
|
||||
#ifdef ENABLE_DUAL_RX_SCENE
|
||||
|
||||
#include "../helpers/protopirate_storage.h"
|
||||
#include "../helpers/gdr_storage.h"
|
||||
#include <notification/notification_messages.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define TAG "ProtoPirateSceneDualRx"
|
||||
#define TAG "GDRSceneDualRx"
|
||||
|
||||
#define DUAL_SCENE_STATE_NONE 0u
|
||||
#define DUAL_SCENE_STATE_TO_SUBSCENE 1u
|
||||
|
||||
typedef struct {
|
||||
ProtoPirateApp* app;
|
||||
ProtoPirateRxChain* chain;
|
||||
GDRApp* app;
|
||||
GDRRxChain* chain;
|
||||
} DualDecodeBinding;
|
||||
|
||||
static DualDecodeBinding s_bind_a;
|
||||
static DualDecodeBinding s_bind_b;
|
||||
static bool s_dual_devices_inited = false;
|
||||
|
||||
void protopirate_scene_dual_receiver_view_callback(ProtoPirateCustomEvent event, void* context);
|
||||
void gdr_scene_dual_receiver_view_callback(GDRCustomEvent event, void* context);
|
||||
|
||||
static void protopirate_scene_dual_receiver_fmt_freq(uint32_t freq, char* out, size_t out_size) {
|
||||
static void gdr_scene_dual_receiver_fmt_freq(uint32_t freq, char* out, size_t out_size) {
|
||||
snprintf(
|
||||
out,
|
||||
out_size,
|
||||
@@ -32,7 +32,7 @@ static void protopirate_scene_dual_receiver_fmt_freq(uint32_t freq, char* out, s
|
||||
(unsigned long)((freq / 10000UL) % 100UL));
|
||||
}
|
||||
|
||||
static void protopirate_scene_dual_receiver_decode_cb(
|
||||
static void gdr_scene_dual_receiver_decode_cb(
|
||||
SubGhzReceiver* receiver,
|
||||
SubGhzProtocolDecoderBase* decoder_base,
|
||||
void* context) {
|
||||
@@ -40,28 +40,28 @@ static void protopirate_scene_dual_receiver_decode_cb(
|
||||
furi_check(decoder_base);
|
||||
furi_check(context);
|
||||
DualDecodeBinding* bind = context;
|
||||
ProtoPirateApp* app = bind->app;
|
||||
GDRApp* app = bind->app;
|
||||
|
||||
if(!app->dual_history || !app->dual_history_mutex) {
|
||||
return;
|
||||
}
|
||||
|
||||
furi_mutex_acquire(app->dual_history_mutex, FuriWaitForever);
|
||||
ProtoPirateHistorySource source = bind->chain->is_external ?
|
||||
ProtoPirateHistorySourceExternal :
|
||||
ProtoPirateHistorySourceInternal;
|
||||
bool added = protopirate_history_add_to_history(
|
||||
GDRHistorySource source = bind->chain->is_external ?
|
||||
GDRHistorySourceExternal :
|
||||
GDRHistorySourceInternal;
|
||||
bool added = gdr_history_add_to_history(
|
||||
app->dual_history, decoder_base, &bind->chain->preset, source);
|
||||
furi_mutex_release(app->dual_history_mutex);
|
||||
|
||||
if(added) {
|
||||
notification_message(app->notifications, &sequence_semi_success);
|
||||
view_dispatcher_send_custom_event(
|
||||
app->view_dispatcher, ProtoPirateCustomEventDualReceiverUpdate);
|
||||
app->view_dispatcher, GDRCustomEventDualReceiverUpdate);
|
||||
}
|
||||
}
|
||||
|
||||
static void protopirate_scene_dual_receiver_update_status(ProtoPirateApp* app) {
|
||||
static void gdr_scene_dual_receiver_update_status(GDRApp* app) {
|
||||
furi_check(app);
|
||||
if(!app->dual_receiver) {
|
||||
return;
|
||||
@@ -69,9 +69,9 @@ static void protopirate_scene_dual_receiver_update_status(ProtoPirateApp* app) {
|
||||
|
||||
char freq_str[16];
|
||||
if(app->dual_chain_a) {
|
||||
protopirate_scene_dual_receiver_fmt_freq(
|
||||
gdr_scene_dual_receiver_fmt_freq(
|
||||
app->dual_chain_a->frequency, freq_str, sizeof(freq_str));
|
||||
protopirate_view_dual_receiver_set_chain_status(
|
||||
gdr_view_dual_receiver_set_chain_status(
|
||||
app->dual_receiver,
|
||||
0,
|
||||
"A",
|
||||
@@ -80,9 +80,9 @@ static void protopirate_scene_dual_receiver_update_status(ProtoPirateApp* app) {
|
||||
app->dual_chain_a->is_external);
|
||||
}
|
||||
if(app->dual_chain_b) {
|
||||
protopirate_scene_dual_receiver_fmt_freq(
|
||||
gdr_scene_dual_receiver_fmt_freq(
|
||||
app->dual_chain_b->frequency, freq_str, sizeof(freq_str));
|
||||
protopirate_view_dual_receiver_set_chain_status(
|
||||
gdr_view_dual_receiver_set_chain_status(
|
||||
app->dual_receiver,
|
||||
1,
|
||||
"B",
|
||||
@@ -93,22 +93,22 @@ static void protopirate_scene_dual_receiver_update_status(ProtoPirateApp* app) {
|
||||
|
||||
char hist_str[16] = {0};
|
||||
if(app->dual_history) {
|
||||
protopirate_history_format_status_text(app->dual_history, hist_str, sizeof(hist_str));
|
||||
gdr_history_format_status_text(app->dual_history, hist_str, sizeof(hist_str));
|
||||
} else {
|
||||
snprintf(hist_str, sizeof(hist_str), "0/%u", PROTOPIRATE_HISTORY_MAX);
|
||||
snprintf(hist_str, sizeof(hist_str), "0/%u", GDR_HISTORY_MAX);
|
||||
}
|
||||
protopirate_view_dual_receiver_set_history_stat(app->dual_receiver, hist_str);
|
||||
gdr_view_dual_receiver_set_history_stat(app->dual_receiver, hist_str);
|
||||
}
|
||||
|
||||
static void protopirate_scene_dual_receiver_teardown(ProtoPirateApp* app) {
|
||||
static void gdr_scene_dual_receiver_teardown(GDRApp* app) {
|
||||
furi_check(app);
|
||||
|
||||
if(app->dual_chain_a) {
|
||||
protopirate_rx_chain_free(app->dual_chain_a);
|
||||
gdr_rx_chain_free(app->dual_chain_a);
|
||||
app->dual_chain_a = NULL;
|
||||
}
|
||||
if(app->dual_chain_b) {
|
||||
protopirate_rx_chain_free(app->dual_chain_b);
|
||||
gdr_rx_chain_free(app->dual_chain_b);
|
||||
app->dual_chain_b = NULL;
|
||||
}
|
||||
|
||||
@@ -121,13 +121,13 @@ static void protopirate_scene_dual_receiver_teardown(ProtoPirateApp* app) {
|
||||
}
|
||||
}
|
||||
|
||||
static bool protopirate_scene_dual_receiver_build(ProtoPirateApp* app) {
|
||||
static bool gdr_scene_dual_receiver_build(GDRApp* app) {
|
||||
furi_check(app);
|
||||
|
||||
protopirate_radio_deinit(app);
|
||||
gdr_radio_deinit(app);
|
||||
|
||||
if(!app->dual_history) {
|
||||
app->dual_history = protopirate_history_alloc();
|
||||
app->dual_history = gdr_history_alloc();
|
||||
if(!app->dual_history) {
|
||||
FURI_LOG_E(TAG, "Failed to allocate dual history");
|
||||
return false;
|
||||
@@ -144,54 +144,54 @@ static bool protopirate_scene_dual_receiver_build(ProtoPirateApp* app) {
|
||||
subghz_devices_init();
|
||||
s_dual_devices_inited = true;
|
||||
|
||||
app->dual_chain_a = protopirate_rx_chain_alloc('A');
|
||||
app->dual_chain_b = protopirate_rx_chain_alloc('B');
|
||||
app->dual_chain_a = gdr_rx_chain_alloc('A');
|
||||
app->dual_chain_b = gdr_rx_chain_alloc('B');
|
||||
if(!app->dual_chain_a || !app->dual_chain_b) {
|
||||
FURI_LOG_E(TAG, "Failed to allocate chains");
|
||||
protopirate_scene_dual_receiver_teardown(app);
|
||||
gdr_scene_dual_receiver_teardown(app);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!protopirate_rx_chain_acquire_device(
|
||||
if(!gdr_rx_chain_acquire_device(
|
||||
app->dual_chain_a, SubGhzRadioDeviceTypeExternalCC1101)) {
|
||||
FURI_LOG_E(TAG, "External CC1101 unavailable - dual RX requires it");
|
||||
protopirate_scene_dual_receiver_teardown(app);
|
||||
gdr_scene_dual_receiver_teardown(app);
|
||||
return false;
|
||||
}
|
||||
if(!protopirate_rx_chain_acquire_device(app->dual_chain_b, SubGhzRadioDeviceTypeInternal)) {
|
||||
if(!gdr_rx_chain_acquire_device(app->dual_chain_b, SubGhzRadioDeviceTypeInternal)) {
|
||||
FURI_LOG_E(TAG, "Internal CC1101 unavailable");
|
||||
protopirate_scene_dual_receiver_teardown(app);
|
||||
gdr_scene_dual_receiver_teardown(app);
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t preset_count = subghz_setting_get_preset_count(app->setting);
|
||||
if(app->dual_preset_a >= preset_count || app->dual_preset_b >= preset_count) {
|
||||
FURI_LOG_E(TAG, "Dual RX requires valid presets");
|
||||
protopirate_scene_dual_receiver_teardown(app);
|
||||
gdr_scene_dual_receiver_teardown(app);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!protopirate_rx_chain_set_preset_data(
|
||||
if(!gdr_rx_chain_set_preset_data(
|
||||
app->dual_chain_a,
|
||||
subghz_setting_get_preset_name(app->setting, app->dual_preset_a),
|
||||
subghz_setting_get_preset_data(app->setting, app->dual_preset_a),
|
||||
subghz_setting_get_preset_data_size(app->setting, app->dual_preset_a),
|
||||
app->dual_freq_a) ||
|
||||
!protopirate_rx_chain_set_preset_data(
|
||||
!gdr_rx_chain_set_preset_data(
|
||||
app->dual_chain_b,
|
||||
subghz_setting_get_preset_name(app->setting, app->dual_preset_b),
|
||||
subghz_setting_get_preset_data(app->setting, app->dual_preset_b),
|
||||
subghz_setting_get_preset_data_size(app->setting, app->dual_preset_b),
|
||||
app->dual_freq_b)) {
|
||||
FURI_LOG_E(TAG, "Failed to set chain presets");
|
||||
protopirate_scene_dual_receiver_teardown(app);
|
||||
gdr_scene_dual_receiver_teardown(app);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!protopirate_rx_chain_init_receiver(app->dual_chain_a) ||
|
||||
!protopirate_rx_chain_init_receiver(app->dual_chain_b)) {
|
||||
if(!gdr_rx_chain_init_receiver(app->dual_chain_a) ||
|
||||
!gdr_rx_chain_init_receiver(app->dual_chain_b)) {
|
||||
FURI_LOG_E(TAG, "Failed to init chain receivers");
|
||||
protopirate_scene_dual_receiver_teardown(app);
|
||||
gdr_scene_dual_receiver_teardown(app);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -200,145 +200,145 @@ static bool protopirate_scene_dual_receiver_build(ProtoPirateApp* app) {
|
||||
s_bind_b.app = app;
|
||||
s_bind_b.chain = app->dual_chain_b;
|
||||
|
||||
protopirate_rx_chain_set_decode_callback(
|
||||
app->dual_chain_a, protopirate_scene_dual_receiver_decode_cb, &s_bind_a);
|
||||
protopirate_rx_chain_set_decode_callback(
|
||||
app->dual_chain_b, protopirate_scene_dual_receiver_decode_cb, &s_bind_b);
|
||||
gdr_rx_chain_set_decode_callback(
|
||||
app->dual_chain_a, gdr_scene_dual_receiver_decode_cb, &s_bind_a);
|
||||
gdr_rx_chain_set_decode_callback(
|
||||
app->dual_chain_b, gdr_scene_dual_receiver_decode_cb, &s_bind_b);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void protopirate_scene_dual_receiver_on_enter(void* context) {
|
||||
void gdr_scene_dual_receiver_on_enter(void* context) {
|
||||
furi_check(context);
|
||||
ProtoPirateApp* app = context;
|
||||
GDRApp* app = context;
|
||||
|
||||
if(!protopirate_ensure_dual_receiver_view(app)) {
|
||||
if(!gdr_ensure_dual_receiver_view(app)) {
|
||||
notification_message(app->notifications, &sequence_error);
|
||||
scene_manager_search_and_switch_to_previous_scene(app->scene_manager, ProtoPirateSceneStart);
|
||||
scene_manager_search_and_switch_to_previous_scene(app->scene_manager, GDRSceneStart);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!protopirate_scene_dual_receiver_build(app)) {
|
||||
if(!gdr_scene_dual_receiver_build(app)) {
|
||||
notification_message(app->notifications, &sequence_error);
|
||||
scene_manager_search_and_switch_to_previous_scene(app->scene_manager, ProtoPirateSceneStart);
|
||||
scene_manager_search_and_switch_to_previous_scene(app->scene_manager, GDRSceneStart);
|
||||
return;
|
||||
}
|
||||
|
||||
protopirate_view_dual_receiver_set_callback(
|
||||
app->dual_receiver, protopirate_scene_dual_receiver_view_callback, app);
|
||||
protopirate_view_dual_receiver_set_history_mutex(app->dual_receiver, app->dual_history_mutex);
|
||||
protopirate_view_dual_receiver_set_history(app->dual_receiver, app->dual_history);
|
||||
protopirate_view_dual_receiver_sync_menu_from_history(app->dual_receiver, app->dual_history);
|
||||
if(app->selected_capture.owner == ProtoPirateCaptureOwnerDualReceiver &&
|
||||
gdr_view_dual_receiver_set_callback(
|
||||
app->dual_receiver, gdr_scene_dual_receiver_view_callback, app);
|
||||
gdr_view_dual_receiver_set_history_mutex(app->dual_receiver, app->dual_history_mutex);
|
||||
gdr_view_dual_receiver_set_history(app->dual_receiver, app->dual_history);
|
||||
gdr_view_dual_receiver_sync_menu_from_history(app->dual_receiver, app->dual_history);
|
||||
if(app->selected_capture.owner == GDRCaptureOwnerDualReceiver &&
|
||||
app->selected_capture.history == app->dual_history &&
|
||||
protopirate_selected_capture_is_valid(app)) {
|
||||
protopirate_view_dual_receiver_set_idx_menu(
|
||||
gdr_selected_capture_is_valid(app)) {
|
||||
gdr_view_dual_receiver_set_idx_menu(
|
||||
app->dual_receiver, app->selected_capture.index);
|
||||
}
|
||||
protopirate_scene_dual_receiver_update_status(app);
|
||||
gdr_scene_dual_receiver_update_status(app);
|
||||
|
||||
scene_manager_set_scene_state(
|
||||
app->scene_manager, ProtoPirateSceneDualReceiver, DUAL_SCENE_STATE_NONE);
|
||||
app->scene_manager, GDRSceneDualReceiver, DUAL_SCENE_STATE_NONE);
|
||||
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, ProtoPirateViewDualReceiver);
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, GDRViewDualReceiver);
|
||||
view_dispatcher_send_custom_event(
|
||||
app->view_dispatcher, ProtoPirateCustomEventDualReceiverDeferredRxStart);
|
||||
app->view_dispatcher, GDRCustomEventDualReceiverDeferredRxStart);
|
||||
}
|
||||
|
||||
bool protopirate_scene_dual_receiver_on_event(void* context, SceneManagerEvent event) {
|
||||
bool gdr_scene_dual_receiver_on_event(void* context, SceneManagerEvent event) {
|
||||
furi_check(context);
|
||||
ProtoPirateApp* app = context;
|
||||
GDRApp* app = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
switch(event.event) {
|
||||
case ProtoPirateCustomEventDualReceiverDeferredRxStart:
|
||||
if(!protopirate_rx_chain_start(app->dual_chain_a) ||
|
||||
!protopirate_rx_chain_start(app->dual_chain_b)) {
|
||||
case GDRCustomEventDualReceiverDeferredRxStart:
|
||||
if(!gdr_rx_chain_start(app->dual_chain_a) ||
|
||||
!gdr_rx_chain_start(app->dual_chain_b)) {
|
||||
FURI_LOG_E(TAG, "Failed to start one or both chains");
|
||||
protopirate_scene_dual_receiver_teardown(app);
|
||||
gdr_scene_dual_receiver_teardown(app);
|
||||
notification_message(app->notifications, &sequence_error);
|
||||
scene_manager_set_scene_state(
|
||||
app->scene_manager, ProtoPirateSceneDualReceiver, DUAL_SCENE_STATE_NONE);
|
||||
app->scene_manager, GDRSceneDualReceiver, DUAL_SCENE_STATE_NONE);
|
||||
scene_manager_search_and_switch_to_previous_scene(
|
||||
app->scene_manager, ProtoPirateSceneStart);
|
||||
app->scene_manager, GDRSceneStart);
|
||||
consumed = true;
|
||||
break;
|
||||
}
|
||||
protopirate_scene_dual_receiver_update_status(app);
|
||||
gdr_scene_dual_receiver_update_status(app);
|
||||
consumed = true;
|
||||
break;
|
||||
|
||||
case ProtoPirateCustomEventDualReceiverUpdate:
|
||||
protopirate_view_dual_receiver_sync_menu_from_history(
|
||||
case GDRCustomEventDualReceiverUpdate:
|
||||
gdr_view_dual_receiver_sync_menu_from_history(
|
||||
app->dual_receiver, app->dual_history);
|
||||
protopirate_scene_dual_receiver_update_status(app);
|
||||
gdr_scene_dual_receiver_update_status(app);
|
||||
consumed = true;
|
||||
break;
|
||||
|
||||
case ProtoPirateCustomEventViewDualReceiverConfig:
|
||||
case GDRCustomEventViewDualReceiverConfig:
|
||||
scene_manager_set_scene_state(
|
||||
app->scene_manager, ProtoPirateSceneDualReceiver, DUAL_SCENE_STATE_TO_SUBSCENE);
|
||||
scene_manager_next_scene(app->scene_manager, ProtoPirateSceneDualReceiverConfig);
|
||||
app->scene_manager, GDRSceneDualReceiver, DUAL_SCENE_STATE_TO_SUBSCENE);
|
||||
scene_manager_next_scene(app->scene_manager, GDRSceneDualReceiverConfig);
|
||||
consumed = true;
|
||||
break;
|
||||
|
||||
case ProtoPirateCustomEventViewDualReceiverDeleteItem: {
|
||||
uint16_t idx = protopirate_view_dual_receiver_get_idx_menu(app->dual_receiver);
|
||||
case GDRCustomEventViewDualReceiverDeleteItem: {
|
||||
uint16_t idx = gdr_view_dual_receiver_get_idx_menu(app->dual_receiver);
|
||||
furi_mutex_acquire(app->dual_history_mutex, FuriWaitForever);
|
||||
bool valid = idx < protopirate_history_get_item(app->dual_history);
|
||||
bool valid = idx < gdr_history_get_item(app->dual_history);
|
||||
if(valid) {
|
||||
protopirate_history_delete_item(app->dual_history, idx);
|
||||
gdr_history_delete_item(app->dual_history, idx);
|
||||
}
|
||||
furi_mutex_release(app->dual_history_mutex);
|
||||
if(valid) {
|
||||
protopirate_view_dual_receiver_delete_item(app->dual_receiver, idx);
|
||||
protopirate_scene_dual_receiver_update_status(app);
|
||||
gdr_view_dual_receiver_delete_item(app->dual_receiver, idx);
|
||||
gdr_scene_dual_receiver_update_status(app);
|
||||
}
|
||||
consumed = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case ProtoPirateCustomEventViewDualReceiverOK:
|
||||
case GDRCustomEventViewDualReceiverOK:
|
||||
{
|
||||
uint16_t idx =
|
||||
protopirate_view_dual_receiver_get_idx_menu(app->dual_receiver);
|
||||
gdr_view_dual_receiver_get_idx_menu(app->dual_receiver);
|
||||
furi_mutex_acquire(app->dual_history_mutex, FuriWaitForever);
|
||||
bool valid = idx < protopirate_history_get_item(app->dual_history);
|
||||
bool valid = idx < gdr_history_get_item(app->dual_history);
|
||||
furi_mutex_release(app->dual_history_mutex);
|
||||
if(valid) {
|
||||
protopirate_selected_capture_set(
|
||||
gdr_selected_capture_set(
|
||||
app,
|
||||
app->dual_history,
|
||||
app->dual_history_mutex,
|
||||
idx,
|
||||
ProtoPirateCaptureOwnerDualReceiver);
|
||||
GDRCaptureOwnerDualReceiver);
|
||||
scene_manager_set_scene_state(
|
||||
app->scene_manager,
|
||||
ProtoPirateSceneDualReceiver,
|
||||
GDRSceneDualReceiver,
|
||||
DUAL_SCENE_STATE_TO_SUBSCENE);
|
||||
scene_manager_next_scene(
|
||||
app->scene_manager, ProtoPirateSceneReceiverInfo);
|
||||
app->scene_manager, GDRSceneReceiverInfo);
|
||||
}
|
||||
}
|
||||
consumed = true;
|
||||
break;
|
||||
|
||||
case ProtoPirateCustomEventViewDualReceiverBack:
|
||||
case GDRCustomEventViewDualReceiverBack:
|
||||
furi_mutex_acquire(app->dual_history_mutex, FuriWaitForever);
|
||||
bool has_history = protopirate_history_get_item(app->dual_history) > 0;
|
||||
bool has_history = gdr_history_get_item(app->dual_history) > 0;
|
||||
furi_mutex_release(app->dual_history_mutex);
|
||||
if(has_history) {
|
||||
app->unsaved_history_owner = ProtoPirateCaptureOwnerDualReceiver;
|
||||
app->unsaved_history_owner = GDRCaptureOwnerDualReceiver;
|
||||
scene_manager_set_scene_state(
|
||||
app->scene_manager,
|
||||
ProtoPirateSceneDualReceiver,
|
||||
GDRSceneDualReceiver,
|
||||
DUAL_SCENE_STATE_TO_SUBSCENE);
|
||||
scene_manager_next_scene(app->scene_manager, ProtoPirateSceneNeedSaving);
|
||||
scene_manager_next_scene(app->scene_manager, GDRSceneNeedSaving);
|
||||
} else {
|
||||
app->unsaved_history_owner = ProtoPirateCaptureOwnerNone;
|
||||
app->unsaved_history_owner = GDRCaptureOwnerNone;
|
||||
scene_manager_search_and_switch_to_previous_scene(
|
||||
app->scene_manager, ProtoPirateSceneStart);
|
||||
app->scene_manager, GDRSceneStart);
|
||||
}
|
||||
consumed = true;
|
||||
break;
|
||||
@@ -348,12 +348,12 @@ bool protopirate_scene_dual_receiver_on_event(void* context, SceneManagerEvent e
|
||||
}
|
||||
} else if(event.type == SceneManagerEventTypeTick) {
|
||||
if(app->dual_chain_a) {
|
||||
protopirate_view_dual_receiver_set_rssi(
|
||||
app->dual_receiver, 0, protopirate_rx_chain_get_rssi(app->dual_chain_a));
|
||||
gdr_view_dual_receiver_set_rssi(
|
||||
app->dual_receiver, 0, gdr_rx_chain_get_rssi(app->dual_chain_a));
|
||||
}
|
||||
if(app->dual_chain_b) {
|
||||
protopirate_view_dual_receiver_set_rssi(
|
||||
app->dual_receiver, 1, protopirate_rx_chain_get_rssi(app->dual_chain_b));
|
||||
gdr_view_dual_receiver_set_rssi(
|
||||
app->dual_receiver, 1, gdr_rx_chain_get_rssi(app->dual_chain_b));
|
||||
}
|
||||
consumed = true;
|
||||
}
|
||||
@@ -361,31 +361,31 @@ bool protopirate_scene_dual_receiver_on_event(void* context, SceneManagerEvent e
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void protopirate_scene_dual_receiver_on_exit(void* context) {
|
||||
void gdr_scene_dual_receiver_on_exit(void* context) {
|
||||
furi_check(context);
|
||||
ProtoPirateApp* app = context;
|
||||
GDRApp* app = context;
|
||||
|
||||
const bool leaving_for_subscene =
|
||||
(scene_manager_get_scene_state(app->scene_manager, ProtoPirateSceneDualReceiver) ==
|
||||
(scene_manager_get_scene_state(app->scene_manager, GDRSceneDualReceiver) ==
|
||||
DUAL_SCENE_STATE_TO_SUBSCENE);
|
||||
|
||||
protopirate_scene_dual_receiver_teardown(app);
|
||||
gdr_scene_dual_receiver_teardown(app);
|
||||
|
||||
if(leaving_for_subscene) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(app->dual_receiver) {
|
||||
protopirate_view_dual_receiver_reset_menu(app->dual_receiver);
|
||||
gdr_view_dual_receiver_reset_menu(app->dual_receiver);
|
||||
}
|
||||
if(app->selected_capture.owner == ProtoPirateCaptureOwnerDualReceiver) {
|
||||
protopirate_selected_capture_clear(app);
|
||||
if(app->selected_capture.owner == GDRCaptureOwnerDualReceiver) {
|
||||
gdr_selected_capture_clear(app);
|
||||
}
|
||||
}
|
||||
|
||||
void protopirate_scene_dual_receiver_view_callback(ProtoPirateCustomEvent event, void* context) {
|
||||
void gdr_scene_dual_receiver_view_callback(GDRCustomEvent event, void* context) {
|
||||
furi_check(context);
|
||||
ProtoPirateApp* app = context;
|
||||
GDRApp* app = context;
|
||||
view_dispatcher_send_custom_event(app->view_dispatcher, event);
|
||||
}
|
||||
|
||||
+48
-48
@@ -1,20 +1,20 @@
|
||||
// scenes/protopirate_scene_dual_receiver_config.c
|
||||
#include "../protopirate_app_i.h"
|
||||
// scenes/gdr_scene_dual_receiver_config.c
|
||||
#include "../gdr_app_i.h"
|
||||
|
||||
#ifdef ENABLE_DUAL_RX_SCENE
|
||||
|
||||
#define TAG "ProtoPirateSceneDualCfg"
|
||||
#define TAG "GDRSceneDualCfg"
|
||||
|
||||
typedef enum {
|
||||
ProtoPirateDualConfigExtFrequency,
|
||||
ProtoPirateDualConfigExtPreset,
|
||||
ProtoPirateDualConfigIntFrequency,
|
||||
ProtoPirateDualConfigIntPreset,
|
||||
ProtoPirateDualConfigSwapRoles,
|
||||
} ProtoPirateDualConfigItem;
|
||||
GDRDualConfigExtFrequency,
|
||||
GDRDualConfigExtPreset,
|
||||
GDRDualConfigIntFrequency,
|
||||
GDRDualConfigIntPreset,
|
||||
GDRDualConfigSwapRoles,
|
||||
} GDRDualConfigItem;
|
||||
|
||||
static void protopirate_dual_config_set_preset_item(
|
||||
ProtoPirateApp* app,
|
||||
static void gdr_dual_config_set_preset_item(
|
||||
GDRApp* app,
|
||||
VariableItem* item,
|
||||
uint8_t index) {
|
||||
variable_item_set_current_value_index(item, index);
|
||||
@@ -22,7 +22,7 @@ static void protopirate_dual_config_set_preset_item(
|
||||
item, subghz_setting_get_preset_name(app->setting, index));
|
||||
}
|
||||
|
||||
static uint8_t protopirate_dual_config_freq_index(ProtoPirateApp* app, uint32_t frequency) {
|
||||
static uint8_t gdr_dual_config_freq_index(GDRApp* app, uint32_t frequency) {
|
||||
uint8_t count = (uint8_t)subghz_setting_get_frequency_count(app->setting);
|
||||
for(uint8_t i = 0; i < count; i++) {
|
||||
if(subghz_setting_get_frequency(app->setting, i) == frequency) {
|
||||
@@ -32,7 +32,7 @@ static uint8_t protopirate_dual_config_freq_index(ProtoPirateApp* app, uint32_t
|
||||
return subghz_setting_get_frequency_default_index(app->setting);
|
||||
}
|
||||
|
||||
static void protopirate_dual_config_set_freq_text(VariableItem* item, uint32_t frequency) {
|
||||
static void gdr_dual_config_set_freq_text(VariableItem* item, uint32_t frequency) {
|
||||
char text_buf[10] = {0};
|
||||
snprintf(
|
||||
text_buf,
|
||||
@@ -43,61 +43,61 @@ static void protopirate_dual_config_set_freq_text(VariableItem* item, uint32_t f
|
||||
variable_item_set_current_value_text(item, text_buf);
|
||||
}
|
||||
|
||||
static void protopirate_dual_config_set_freq_a(VariableItem* item) {
|
||||
ProtoPirateApp* app = variable_item_get_context(item);
|
||||
static void gdr_dual_config_set_freq_a(VariableItem* item) {
|
||||
GDRApp* app = variable_item_get_context(item);
|
||||
uint8_t index = variable_item_get_current_value_index(item);
|
||||
app->dual_freq_a = subghz_setting_get_frequency(app->setting, index);
|
||||
protopirate_dual_config_set_freq_text(item, app->dual_freq_a);
|
||||
gdr_dual_config_set_freq_text(item, app->dual_freq_a);
|
||||
}
|
||||
|
||||
static void protopirate_dual_config_set_freq_b(VariableItem* item) {
|
||||
ProtoPirateApp* app = variable_item_get_context(item);
|
||||
static void gdr_dual_config_set_freq_b(VariableItem* item) {
|
||||
GDRApp* app = variable_item_get_context(item);
|
||||
uint8_t index = variable_item_get_current_value_index(item);
|
||||
app->dual_freq_b = subghz_setting_get_frequency(app->setting, index);
|
||||
protopirate_dual_config_set_freq_text(item, app->dual_freq_b);
|
||||
gdr_dual_config_set_freq_text(item, app->dual_freq_b);
|
||||
}
|
||||
|
||||
static void protopirate_dual_config_set_preset_a(VariableItem* item) {
|
||||
ProtoPirateApp* app = variable_item_get_context(item);
|
||||
static void gdr_dual_config_set_preset_a(VariableItem* item) {
|
||||
GDRApp* app = variable_item_get_context(item);
|
||||
uint8_t index = variable_item_get_current_value_index(item);
|
||||
app->dual_preset_a = index;
|
||||
protopirate_dual_config_set_preset_item(app, item, index);
|
||||
gdr_dual_config_set_preset_item(app, item, index);
|
||||
}
|
||||
|
||||
static void protopirate_dual_config_set_preset_b(VariableItem* item) {
|
||||
ProtoPirateApp* app = variable_item_get_context(item);
|
||||
static void gdr_dual_config_set_preset_b(VariableItem* item) {
|
||||
GDRApp* app = variable_item_get_context(item);
|
||||
uint8_t index = variable_item_get_current_value_index(item);
|
||||
app->dual_preset_b = index;
|
||||
protopirate_dual_config_set_preset_item(app, item, index);
|
||||
gdr_dual_config_set_preset_item(app, item, index);
|
||||
}
|
||||
|
||||
static void protopirate_dual_config_enter_callback(void* context, uint32_t index) {
|
||||
ProtoPirateApp* app = context;
|
||||
if(index != ProtoPirateDualConfigSwapRoles) {
|
||||
static void gdr_dual_config_enter_callback(void* context, uint32_t index) {
|
||||
GDRApp* app = context;
|
||||
if(index != GDRDualConfigSwapRoles) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t preset_a = app->dual_preset_a;
|
||||
app->dual_preset_a = app->dual_preset_b;
|
||||
app->dual_preset_b = preset_a;
|
||||
protopirate_dual_config_set_preset_item(
|
||||
gdr_dual_config_set_preset_item(
|
||||
app,
|
||||
variable_item_list_get(app->variable_item_list, ProtoPirateDualConfigExtPreset),
|
||||
variable_item_list_get(app->variable_item_list, GDRDualConfigExtPreset),
|
||||
app->dual_preset_a);
|
||||
protopirate_dual_config_set_preset_item(
|
||||
gdr_dual_config_set_preset_item(
|
||||
app,
|
||||
variable_item_list_get(app->variable_item_list, ProtoPirateDualConfigIntPreset),
|
||||
variable_item_list_get(app->variable_item_list, GDRDualConfigIntPreset),
|
||||
app->dual_preset_b);
|
||||
notification_message(app->notifications, &sequence_success);
|
||||
}
|
||||
|
||||
void protopirate_scene_dual_receiver_config_on_enter(void* context) {
|
||||
void gdr_scene_dual_receiver_config_on_enter(void* context) {
|
||||
furi_check(context);
|
||||
ProtoPirateApp* app = context;
|
||||
GDRApp* app = context;
|
||||
VariableItem* item;
|
||||
uint8_t value_index;
|
||||
|
||||
if(!protopirate_ensure_variable_item_list(app)) {
|
||||
if(!gdr_ensure_variable_item_list(app)) {
|
||||
notification_message(app->notifications, &sequence_error);
|
||||
scene_manager_previous_scene(app->scene_manager);
|
||||
return;
|
||||
@@ -108,17 +108,17 @@ void protopirate_scene_dual_receiver_config_on_enter(void* context) {
|
||||
|
||||
// Chain A (external)
|
||||
item = variable_item_list_add(
|
||||
app->variable_item_list, "Ext Freq:", freq_count, protopirate_dual_config_set_freq_a, app);
|
||||
value_index = protopirate_dual_config_freq_index(app, app->dual_freq_a);
|
||||
app->variable_item_list, "Ext Freq:", freq_count, gdr_dual_config_set_freq_a, app);
|
||||
value_index = gdr_dual_config_freq_index(app, app->dual_freq_a);
|
||||
variable_item_set_current_value_index(item, value_index);
|
||||
protopirate_dual_config_set_freq_text(
|
||||
gdr_dual_config_set_freq_text(
|
||||
item, subghz_setting_get_frequency(app->setting, value_index));
|
||||
|
||||
item = variable_item_list_add(
|
||||
app->variable_item_list,
|
||||
"Ext Preset:",
|
||||
preset_count,
|
||||
protopirate_dual_config_set_preset_a,
|
||||
gdr_dual_config_set_preset_a,
|
||||
app);
|
||||
variable_item_set_current_value_index(item, app->dual_preset_a);
|
||||
variable_item_set_current_value_text(
|
||||
@@ -126,17 +126,17 @@ void protopirate_scene_dual_receiver_config_on_enter(void* context) {
|
||||
|
||||
// Chain B (internal)
|
||||
item = variable_item_list_add(
|
||||
app->variable_item_list, "Int Freq:", freq_count, protopirate_dual_config_set_freq_b, app);
|
||||
value_index = protopirate_dual_config_freq_index(app, app->dual_freq_b);
|
||||
app->variable_item_list, "Int Freq:", freq_count, gdr_dual_config_set_freq_b, app);
|
||||
value_index = gdr_dual_config_freq_index(app, app->dual_freq_b);
|
||||
variable_item_set_current_value_index(item, value_index);
|
||||
protopirate_dual_config_set_freq_text(
|
||||
gdr_dual_config_set_freq_text(
|
||||
item, subghz_setting_get_frequency(app->setting, value_index));
|
||||
|
||||
item = variable_item_list_add(
|
||||
app->variable_item_list,
|
||||
"Int Preset:",
|
||||
preset_count,
|
||||
protopirate_dual_config_set_preset_b,
|
||||
gdr_dual_config_set_preset_b,
|
||||
app);
|
||||
variable_item_set_current_value_index(item, app->dual_preset_b);
|
||||
variable_item_set_current_value_text(
|
||||
@@ -146,20 +146,20 @@ void protopirate_scene_dual_receiver_config_on_enter(void* context) {
|
||||
app->variable_item_list, "Swap roles", 1, NULL, NULL);
|
||||
variable_item_set_current_value_text(item, "Press OK");
|
||||
variable_item_list_set_enter_callback(
|
||||
app->variable_item_list, protopirate_dual_config_enter_callback, app);
|
||||
app->variable_item_list, gdr_dual_config_enter_callback, app);
|
||||
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, ProtoPirateViewVariableItemList);
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, GDRViewVariableItemList);
|
||||
}
|
||||
|
||||
bool protopirate_scene_dual_receiver_config_on_event(void* context, SceneManagerEvent event) {
|
||||
bool gdr_scene_dual_receiver_config_on_event(void* context, SceneManagerEvent event) {
|
||||
UNUSED(context);
|
||||
UNUSED(event);
|
||||
return false;
|
||||
}
|
||||
|
||||
void protopirate_scene_dual_receiver_config_on_exit(void* context) {
|
||||
void gdr_scene_dual_receiver_config_on_exit(void* context) {
|
||||
furi_check(context);
|
||||
ProtoPirateApp* app = context;
|
||||
GDRApp* app = context;
|
||||
variable_item_list_set_selected_item(app->variable_item_list, 0);
|
||||
variable_item_list_reset(app->variable_item_list);
|
||||
}
|
||||
+33
-33
@@ -1,55 +1,55 @@
|
||||
// scenes/protopirate_scene_emulate.c
|
||||
#include "../protopirate_app_i.h"
|
||||
// scenes/gdr_scene_emulate.c
|
||||
#include "../gdr_app_i.h"
|
||||
|
||||
#ifdef ENABLE_EMULATE_FEATURE
|
||||
|
||||
#include "plugins/protopirate_emulate_plugin.h"
|
||||
#include "../helpers/protopirate_storage.h"
|
||||
#include "../protopirate_history.h"
|
||||
#include "plugins/gdr_emulate_plugin.h"
|
||||
#include "../helpers/gdr_storage.h"
|
||||
#include "../gdr_history.h"
|
||||
|
||||
#include <loader/firmware_api/firmware_api.h>
|
||||
#include <lib/flipper_application/plugins/plugin_manager.h>
|
||||
#include <lib/flipper_application/plugins/composite_resolver.h>
|
||||
|
||||
#define TAG "ProtoPirateSceneEmulate"
|
||||
#define TAG "GDRSceneEmulate"
|
||||
|
||||
#define EMULATE_PLUGIN_PATH APP_ASSETS_PATH("plugins/protopirate_emulate_plugin.fal")
|
||||
#define EMULATE_PLUGIN_PATH APP_ASSETS_PATH("plugins/gdr_emulate_plugin.fal")
|
||||
|
||||
|
||||
static bool host_radio_init(void* app) {
|
||||
return protopirate_radio_init((ProtoPirateApp*)app);
|
||||
return gdr_radio_init((GDRApp*)app);
|
||||
}
|
||||
|
||||
static bool host_apply_protocol_registry_for_preset_data(
|
||||
void* app,
|
||||
const uint8_t* preset_data,
|
||||
size_t preset_data_size) {
|
||||
return protopirate_apply_protocol_registry_for_preset_data(
|
||||
(ProtoPirateApp*)app, preset_data, preset_data_size);
|
||||
return gdr_apply_protocol_registry_for_preset_data(
|
||||
(GDRApp*)app, preset_data, preset_data_size);
|
||||
}
|
||||
|
||||
static void host_rx_stack_suspend_for_tx(void* app) {
|
||||
protopirate_rx_stack_suspend_for_tx((ProtoPirateApp*)app);
|
||||
gdr_rx_stack_suspend_for_tx((GDRApp*)app);
|
||||
}
|
||||
|
||||
static bool host_ensure_view_about(void* app) {
|
||||
return protopirate_ensure_view_about((ProtoPirateApp*)app);
|
||||
return gdr_ensure_view_about((GDRApp*)app);
|
||||
}
|
||||
|
||||
static void host_idle(void* app) {
|
||||
protopirate_idle((ProtoPirateApp*)app);
|
||||
gdr_idle((GDRApp*)app);
|
||||
}
|
||||
|
||||
static void host_history_release_scratch(void* app) {
|
||||
ProtoPirateApp* a = (ProtoPirateApp*)app;
|
||||
if(a) protopirate_selected_capture_release_scratch(a);
|
||||
GDRApp* a = (GDRApp*)app;
|
||||
if(a) gdr_selected_capture_release_scratch(a);
|
||||
}
|
||||
|
||||
static void host_storage_delete_temp(void) {
|
||||
protopirate_storage_delete_temp();
|
||||
gdr_storage_delete_temp();
|
||||
}
|
||||
|
||||
static void protopirate_emulate_apply_pending_nav(ProtoPirateApp* app) {
|
||||
static void gdr_emulate_apply_pending_nav(GDRApp* app) {
|
||||
furi_check(app);
|
||||
|
||||
const uint8_t nav = app->emulate_nav_pending;
|
||||
@@ -67,7 +67,7 @@ static void protopirate_emulate_apply_pending_nav(ProtoPirateApp* app) {
|
||||
}
|
||||
}
|
||||
|
||||
static const ProtoPirateEmulateHostApi protopirate_emulate_host_api = {
|
||||
static const GDREmulateHostApi gdr_emulate_host_api = {
|
||||
.radio_init = host_radio_init,
|
||||
.apply_protocol_registry_for_preset_data = host_apply_protocol_registry_for_preset_data,
|
||||
.rx_stack_suspend_for_tx = host_rx_stack_suspend_for_tx,
|
||||
@@ -80,7 +80,7 @@ static const ProtoPirateEmulateHostApi protopirate_emulate_host_api = {
|
||||
// -----------------------------------------------------------------------------
|
||||
// Plugin load / unload
|
||||
// -----------------------------------------------------------------------------
|
||||
static void emulate_plugin_unload(ProtoPirateApp* app) {
|
||||
static void emulate_plugin_unload(GDRApp* app) {
|
||||
furi_check(app);
|
||||
|
||||
app->emulate_plugin = NULL;
|
||||
@@ -96,7 +96,7 @@ static void emulate_plugin_unload(ProtoPirateApp* app) {
|
||||
}
|
||||
}
|
||||
|
||||
static bool emulate_plugin_load(ProtoPirateApp* app) {
|
||||
static bool emulate_plugin_load(GDRApp* app) {
|
||||
furi_check(app);
|
||||
|
||||
if(app->emulate_plugin) return true;
|
||||
@@ -113,8 +113,8 @@ static bool emulate_plugin_load(ProtoPirateApp* app) {
|
||||
composite_api_resolver_add(resolver, firmware_api_interface);
|
||||
|
||||
PluginManager* manager = plugin_manager_alloc(
|
||||
PROTOPIRATE_EMULATE_PLUGIN_APP_ID,
|
||||
PROTOPIRATE_EMULATE_PLUGIN_API_VERSION,
|
||||
GDR_EMULATE_PLUGIN_APP_ID,
|
||||
GDR_EMULATE_PLUGIN_API_VERSION,
|
||||
composite_api_resolver_get(resolver));
|
||||
if(!manager) {
|
||||
FURI_LOG_E(TAG, "Failed to allocate emulate plugin manager");
|
||||
@@ -130,7 +130,7 @@ static bool emulate_plugin_load(ProtoPirateApp* app) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const ProtoPirateEmulatePlugin* plugin = plugin_manager_get_ep(manager, 0U);
|
||||
const GDREmulatePlugin* plugin = plugin_manager_get_ep(manager, 0U);
|
||||
if(!plugin || !plugin->on_enter || !plugin->on_event || !plugin->on_exit ||
|
||||
!plugin->set_host_api) {
|
||||
FURI_LOG_E(TAG, "Emulate plugin entry point is invalid");
|
||||
@@ -143,11 +143,11 @@ static bool emulate_plugin_load(ProtoPirateApp* app) {
|
||||
app->emulate_plugin_manager = manager;
|
||||
app->emulate_plugin = plugin;
|
||||
|
||||
plugin->set_host_api(&protopirate_emulate_host_api);
|
||||
plugin->set_host_api(&gdr_emulate_host_api);
|
||||
return true;
|
||||
}
|
||||
|
||||
void protopirate_emulate_context_release(ProtoPirateApp* app) {
|
||||
void gdr_emulate_context_release(GDRApp* app) {
|
||||
if(!app) return;
|
||||
if(app->emulate_plugin && app->emulate_plugin->context_release) {
|
||||
app->emulate_plugin->context_release(app);
|
||||
@@ -155,8 +155,8 @@ void protopirate_emulate_context_release(ProtoPirateApp* app) {
|
||||
emulate_plugin_unload(app);
|
||||
}
|
||||
|
||||
void protopirate_scene_emulate_on_enter(void* context) {
|
||||
ProtoPirateApp* app = context;
|
||||
void gdr_scene_emulate_on_enter(void* context) {
|
||||
GDRApp* app = context;
|
||||
|
||||
app->emulate_nav_pending = EMULATE_NAV_NONE;
|
||||
|
||||
@@ -167,23 +167,23 @@ void protopirate_scene_emulate_on_enter(void* context) {
|
||||
}
|
||||
|
||||
app->emulate_plugin->on_enter(app);
|
||||
protopirate_emulate_apply_pending_nav(app);
|
||||
gdr_emulate_apply_pending_nav(app);
|
||||
}
|
||||
|
||||
bool protopirate_scene_emulate_on_event(void* context, SceneManagerEvent event) {
|
||||
ProtoPirateApp* app = context;
|
||||
bool gdr_scene_emulate_on_event(void* context, SceneManagerEvent event) {
|
||||
GDRApp* app = context;
|
||||
|
||||
if(!app->emulate_plugin || !app->emulate_plugin->on_event) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const bool consumed = app->emulate_plugin->on_event(app, event);
|
||||
protopirate_emulate_apply_pending_nav(app);
|
||||
gdr_emulate_apply_pending_nav(app);
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void protopirate_scene_emulate_on_exit(void* context) {
|
||||
ProtoPirateApp* app = context;
|
||||
void gdr_scene_emulate_on_exit(void* context) {
|
||||
GDRApp* app = context;
|
||||
|
||||
if(app->emulate_plugin && app->emulate_plugin->on_exit) {
|
||||
app->emulate_plugin->on_exit(app);
|
||||
+34
-34
@@ -1,26 +1,26 @@
|
||||
// scenes/protopirate_scene_need_saving.c
|
||||
#include "../protopirate_app_i.h"
|
||||
#include "proto_pirate_icons.h"
|
||||
// scenes/gdr_scene_need_saving.c
|
||||
#include "../gdr_app_i.h"
|
||||
#include "gdr_icons.h"
|
||||
|
||||
#define TAG "ProtoPirateNeedSaving"
|
||||
#define TAG "GDRNeedSaving"
|
||||
|
||||
static void
|
||||
protopirate_scene_need_saving_callback(GuiButtonType result, InputType type, void* context) {
|
||||
gdr_scene_need_saving_callback(GuiButtonType result, InputType type, void* context) {
|
||||
furi_assert(context);
|
||||
ProtoPirateApp* app = context;
|
||||
GDRApp* app = context;
|
||||
|
||||
if((result == GuiButtonTypeRight) && (type == InputTypeShort)) {
|
||||
view_dispatcher_send_custom_event(app->view_dispatcher, ProtoPirateCustomEventSceneStay);
|
||||
view_dispatcher_send_custom_event(app->view_dispatcher, GDRCustomEventSceneStay);
|
||||
} else if((result == GuiButtonTypeLeft) && (type == InputTypeShort)) {
|
||||
view_dispatcher_send_custom_event(app->view_dispatcher, ProtoPirateCustomEventSceneExit);
|
||||
view_dispatcher_send_custom_event(app->view_dispatcher, GDRCustomEventSceneExit);
|
||||
}
|
||||
}
|
||||
|
||||
void protopirate_scene_need_saving_on_enter(void* context) {
|
||||
void gdr_scene_need_saving_on_enter(void* context) {
|
||||
furi_check(context);
|
||||
ProtoPirateApp* app = context;
|
||||
GDRApp* app = context;
|
||||
|
||||
if(!protopirate_ensure_widget(app)) {
|
||||
if(!gdr_ensure_widget(app)) {
|
||||
notification_message(app->notifications, &sequence_error);
|
||||
scene_manager_previous_scene(app->scene_manager);
|
||||
return;
|
||||
@@ -39,74 +39,74 @@ void protopirate_scene_need_saving_on_enter(void* context) {
|
||||
"All unsaved data\nwill be lost!");
|
||||
|
||||
widget_add_button_element(
|
||||
app->widget, GuiButtonTypeRight, "Stay", protopirate_scene_need_saving_callback, app);
|
||||
app->widget, GuiButtonTypeRight, "Stay", gdr_scene_need_saving_callback, app);
|
||||
widget_add_button_element(
|
||||
app->widget, GuiButtonTypeLeft, "Exit", protopirate_scene_need_saving_callback, app);
|
||||
app->widget, GuiButtonTypeLeft, "Exit", gdr_scene_need_saving_callback, app);
|
||||
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, ProtoPirateViewWidget);
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, GDRViewWidget);
|
||||
}
|
||||
|
||||
bool protopirate_scene_need_saving_on_event(void* context, SceneManagerEvent event) {
|
||||
bool gdr_scene_need_saving_on_event(void* context, SceneManagerEvent event) {
|
||||
furi_check(context);
|
||||
ProtoPirateApp* app = context;
|
||||
GDRApp* app = context;
|
||||
|
||||
if(event.type == SceneManagerEventTypeBack) {
|
||||
// Hardware back button = same as "Stay"
|
||||
scene_manager_previous_scene(app->scene_manager);
|
||||
return true;
|
||||
} else if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == ProtoPirateCustomEventSceneStay) {
|
||||
if(event.event == GDRCustomEventSceneStay) {
|
||||
scene_manager_previous_scene(app->scene_manager);
|
||||
return true;
|
||||
} else if(event.event == ProtoPirateCustomEventSceneExit) {
|
||||
} else if(event.event == GDRCustomEventSceneExit) {
|
||||
bool history_owner_handled = false;
|
||||
#ifdef ENABLE_DUAL_RX_SCENE
|
||||
if(app->unsaved_history_owner == ProtoPirateCaptureOwnerDualReceiver) {
|
||||
if(app->unsaved_history_owner == GDRCaptureOwnerDualReceiver) {
|
||||
if(app->dual_history && app->dual_history_mutex) {
|
||||
furi_mutex_acquire(app->dual_history_mutex, FuriWaitForever);
|
||||
protopirate_history_reset(app->dual_history);
|
||||
gdr_history_reset(app->dual_history);
|
||||
furi_mutex_release(app->dual_history_mutex);
|
||||
}
|
||||
if(app->dual_receiver) {
|
||||
protopirate_view_dual_receiver_reset_menu(app->dual_receiver);
|
||||
gdr_view_dual_receiver_reset_menu(app->dual_receiver);
|
||||
}
|
||||
if(app->selected_capture.owner == ProtoPirateCaptureOwnerDualReceiver) {
|
||||
protopirate_selected_capture_clear(app);
|
||||
if(app->selected_capture.owner == GDRCaptureOwnerDualReceiver) {
|
||||
gdr_selected_capture_clear(app);
|
||||
}
|
||||
history_owner_handled = true;
|
||||
}
|
||||
#endif
|
||||
#ifdef ENABLE_SHIELD_RX_SCENE
|
||||
if(app->unsaved_history_owner == ProtoPirateCaptureOwnerShieldReceiver) {
|
||||
if(app->unsaved_history_owner == GDRCaptureOwnerShieldReceiver) {
|
||||
if(app->shield_history && app->shield_history_mutex) {
|
||||
furi_mutex_acquire(app->shield_history_mutex, FuriWaitForever);
|
||||
protopirate_history_reset(app->shield_history);
|
||||
gdr_history_reset(app->shield_history);
|
||||
app->shield_auto_save_failed = false;
|
||||
furi_mutex_release(app->shield_history_mutex);
|
||||
}
|
||||
if(app->protopirate_receiver) {
|
||||
protopirate_view_receiver_reset_menu(app->protopirate_receiver);
|
||||
if(app->gdr_receiver) {
|
||||
gdr_view_receiver_reset_menu(app->gdr_receiver);
|
||||
}
|
||||
if(app->selected_capture.owner == ProtoPirateCaptureOwnerShieldReceiver) {
|
||||
protopirate_selected_capture_clear(app);
|
||||
if(app->selected_capture.owner == GDRCaptureOwnerShieldReceiver) {
|
||||
gdr_selected_capture_clear(app);
|
||||
}
|
||||
history_owner_handled = true;
|
||||
}
|
||||
#endif
|
||||
if(!history_owner_handled) {
|
||||
protopirate_release_shared_radio_state(app);
|
||||
gdr_release_shared_radio_state(app);
|
||||
}
|
||||
scene_manager_search_and_switch_to_previous_scene(
|
||||
app->scene_manager, ProtoPirateSceneStart);
|
||||
app->scene_manager, GDRSceneStart);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void protopirate_scene_need_saving_on_exit(void* context) {
|
||||
void gdr_scene_need_saving_on_exit(void* context) {
|
||||
furi_check(context);
|
||||
ProtoPirateApp* app = context;
|
||||
GDRApp* app = context;
|
||||
widget_reset(app->widget);
|
||||
app->unsaved_history_owner = ProtoPirateCaptureOwnerNone;
|
||||
app->unsaved_history_owner = GDRCaptureOwnerNone;
|
||||
}
|
||||
+113
-113
@@ -1,26 +1,26 @@
|
||||
// scenes/protopirate_scene_receiver.c
|
||||
#include "../protopirate_app_i.h"
|
||||
#include "../helpers/protopirate_storage.h"
|
||||
#include "views/protopirate_receiver.h"
|
||||
// scenes/gdr_scene_receiver.c
|
||||
#include "../gdr_app_i.h"
|
||||
#include "../helpers/gdr_storage.h"
|
||||
#include "views/gdr_receiver.h"
|
||||
#include <notification/notification_messages.h>
|
||||
#include <stdio.h>
|
||||
#include "proto_pirate_icons.h"
|
||||
#include "gdr_icons.h"
|
||||
|
||||
#define TAG "ProtoPirateSceneRx"
|
||||
#define TAG "GDRSceneRx"
|
||||
|
||||
// Forward declaration
|
||||
void protopirate_scene_receiver_view_callback(ProtoPirateCustomEvent event, void* context);
|
||||
static void protopirate_scene_receiver_start_rx_stack(ProtoPirateApp* app);
|
||||
void gdr_scene_receiver_view_callback(GDRCustomEvent event, void* context);
|
||||
static void gdr_scene_receiver_start_rx_stack(GDRApp* app);
|
||||
|
||||
static void protopirate_scene_receiver_update_statusbar(void* context) {
|
||||
static void gdr_scene_receiver_update_statusbar(void* context) {
|
||||
furi_check(context);
|
||||
ProtoPirateApp* app = context;
|
||||
GDRApp* app = context;
|
||||
|
||||
char frequency_str[16] = {0};
|
||||
char modulation_str[8] = {0};
|
||||
char history_stat_str[16] = {0};
|
||||
|
||||
protopirate_get_frequency_modulation_str(
|
||||
gdr_get_frequency_modulation_str(
|
||||
app, frequency_str, sizeof(frequency_str), modulation_str, sizeof(modulation_str));
|
||||
|
||||
bool is_external = false;
|
||||
@@ -29,34 +29,34 @@ static void protopirate_scene_receiver_update_statusbar(void* context) {
|
||||
}
|
||||
|
||||
if(app->txrx->history) {
|
||||
protopirate_history_format_status_text(
|
||||
gdr_history_format_status_text(
|
||||
app->txrx->history, history_stat_str, sizeof(history_stat_str));
|
||||
} else {
|
||||
snprintf(history_stat_str, sizeof(history_stat_str), "0/%u", PROTOPIRATE_HISTORY_MAX);
|
||||
snprintf(history_stat_str, sizeof(history_stat_str), "0/%u", GDR_HISTORY_MAX);
|
||||
}
|
||||
|
||||
protopirate_view_receiver_add_data_statusbar(
|
||||
app->protopirate_receiver, frequency_str, modulation_str, history_stat_str, is_external);
|
||||
gdr_view_receiver_add_data_statusbar(
|
||||
app->gdr_receiver, frequency_str, modulation_str, history_stat_str, is_external);
|
||||
}
|
||||
|
||||
static void protopirate_scene_receiver_callback(
|
||||
static void gdr_scene_receiver_callback(
|
||||
SubGhzReceiver* receiver,
|
||||
SubGhzProtocolDecoderBase* decoder_base,
|
||||
void* context) {
|
||||
UNUSED(receiver);
|
||||
furi_check(decoder_base);
|
||||
furi_check(context);
|
||||
ProtoPirateApp* app = context;
|
||||
GDRApp* app = context;
|
||||
|
||||
FURI_LOG_I(TAG, "=== SIGNAL DECODED (%s) ===", decoder_base->protocol->name);
|
||||
|
||||
uint16_t count_before = protopirate_history_get_item(app->txrx->history);
|
||||
uint16_t count_before = gdr_history_get_item(app->txrx->history);
|
||||
bool added =
|
||||
protopirate_history_add_to_history(
|
||||
gdr_history_add_to_history(
|
||||
app->txrx->history,
|
||||
decoder_base,
|
||||
app->txrx->preset,
|
||||
ProtoPirateHistorySourceUnknown);
|
||||
GDRHistorySourceUnknown);
|
||||
|
||||
if(added) {
|
||||
notification_message(app->notifications, &sequence_semi_success);
|
||||
@@ -64,21 +64,21 @@ static void protopirate_scene_receiver_callback(
|
||||
FURI_LOG_I(
|
||||
TAG,
|
||||
"Added to history, total items: %u",
|
||||
protopirate_history_get_item(app->txrx->history));
|
||||
gdr_history_get_item(app->txrx->history));
|
||||
|
||||
uint16_t count_after = protopirate_history_get_item(app->txrx->history);
|
||||
uint16_t count_after = gdr_history_get_item(app->txrx->history);
|
||||
|
||||
if(count_after > count_before) {
|
||||
protopirate_view_receiver_append_menu_row_from_history(
|
||||
app->protopirate_receiver, app->txrx->history, count_after - 1);
|
||||
gdr_view_receiver_append_menu_row_from_history(
|
||||
app->gdr_receiver, app->txrx->history, count_after - 1);
|
||||
}
|
||||
|
||||
uint16_t last_index = protopirate_history_get_item(app->txrx->history) - 1;
|
||||
protopirate_view_receiver_set_idx_menu(app->protopirate_receiver, last_index);
|
||||
uint16_t last_index = gdr_history_get_item(app->txrx->history) - 1;
|
||||
gdr_view_receiver_set_idx_menu(app->gdr_receiver, last_index);
|
||||
|
||||
if(app->auto_save) {
|
||||
FlipperFormat* ff = protopirate_history_get_raw_data(
|
||||
app->txrx->history, protopirate_history_get_item(app->txrx->history) - 1);
|
||||
FlipperFormat* ff = gdr_history_get_raw_data(
|
||||
app->txrx->history, gdr_history_get_item(app->txrx->history) - 1);
|
||||
|
||||
if(ff) {
|
||||
FuriString* protocol = furi_string_alloc();
|
||||
@@ -102,7 +102,7 @@ static void protopirate_scene_receiver_callback(
|
||||
return;
|
||||
}
|
||||
|
||||
if(protopirate_storage_save_capture(
|
||||
if(gdr_storage_save_capture(
|
||||
ff, furi_string_get_cstr(protocol), saved_path)) {
|
||||
FURI_LOG_I(TAG, "Auto-saved: %s", furi_string_get_cstr(saved_path));
|
||||
notification_message(app->notifications, &sequence_double_vibro);
|
||||
@@ -116,24 +116,24 @@ static void protopirate_scene_receiver_callback(
|
||||
}
|
||||
|
||||
view_dispatcher_send_custom_event(
|
||||
app->view_dispatcher, ProtoPirateCustomEventSceneReceiverUpdate);
|
||||
app->view_dispatcher, GDRCustomEventSceneReceiverUpdate);
|
||||
} else {
|
||||
FURI_LOG_D(TAG, "Capture not admitted (full or duplicate)");
|
||||
}
|
||||
|
||||
if(app->txrx->hopper_state == ProtoPirateHopperStateRunning) {
|
||||
app->txrx->hopper_state = ProtoPirateHopperStatePause;
|
||||
if(app->txrx->hopper_state == GDRHopperStateRunning) {
|
||||
app->txrx->hopper_state = GDRHopperStatePause;
|
||||
app->txrx->hopper_timeout = 10;
|
||||
}
|
||||
}
|
||||
|
||||
static void protopirate_scene_receiver_start_rx_stack(ProtoPirateApp* app) {
|
||||
static void gdr_scene_receiver_start_rx_stack(GDRApp* app) {
|
||||
furi_check(app);
|
||||
if(!app->radio_initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
protopirate_rx_stack_resume_after_tx(app);
|
||||
gdr_rx_stack_resume_after_tx(app);
|
||||
if(!app->txrx->receiver) {
|
||||
FURI_LOG_E(TAG, "SubGhz receiver unavailable — staying on receiver in degraded mode");
|
||||
notification_message(app->notifications, &sequence_error);
|
||||
@@ -156,10 +156,10 @@ static void protopirate_scene_receiver_start_rx_stack(ProtoPirateApp* app) {
|
||||
subghz_receiver_reset(app->txrx->receiver);
|
||||
|
||||
subghz_worker_set_context(app->txrx->worker, app->txrx->receiver);
|
||||
subghz_receiver_set_rx_callback(app->txrx->receiver, protopirate_scene_receiver_callback, app);
|
||||
subghz_receiver_set_rx_callback(app->txrx->receiver, gdr_scene_receiver_callback, app);
|
||||
|
||||
if(app->txrx->hopper_state != ProtoPirateHopperStateOFF) {
|
||||
app->txrx->hopper_state = ProtoPirateHopperStateRunning;
|
||||
if(app->txrx->hopper_state != GDRHopperStateOFF) {
|
||||
app->txrx->hopper_state = GDRHopperStateRunning;
|
||||
}
|
||||
|
||||
const char* preset_name = furi_string_get_cstr(app->txrx->preset->name);
|
||||
@@ -170,35 +170,35 @@ static void protopirate_scene_receiver_start_rx_stack(ProtoPirateApp* app) {
|
||||
preset_data = subghz_setting_get_preset_data_by_name(app->setting, "AM650");
|
||||
}
|
||||
|
||||
protopirate_begin(app, preset_data);
|
||||
gdr_begin(app, preset_data);
|
||||
|
||||
uint32_t frequency = app->txrx->preset->frequency;
|
||||
if(app->txrx->hopper_state == ProtoPirateHopperStateRunning) {
|
||||
if(app->txrx->hopper_state == GDRHopperStateRunning) {
|
||||
frequency = subghz_setting_get_hopper_frequency(app->setting, 0);
|
||||
app->txrx->hopper_idx_frequency = 0;
|
||||
}
|
||||
|
||||
FURI_LOG_I(TAG, "Starting RX on %lu Hz", frequency);
|
||||
protopirate_rx(app, frequency);
|
||||
gdr_rx(app, frequency);
|
||||
|
||||
FURI_LOG_I(TAG, "RX started, state: %d", app->txrx->txrx_state);
|
||||
}
|
||||
|
||||
void protopirate_scene_receiver_on_enter(void* context) {
|
||||
void gdr_scene_receiver_on_enter(void* context) {
|
||||
furi_check(context);
|
||||
ProtoPirateApp* app = context;
|
||||
GDRApp* app = context;
|
||||
|
||||
if(!protopirate_ensure_receiver_view(app)) {
|
||||
if(!gdr_ensure_receiver_view(app)) {
|
||||
notification_message(app->notifications, &sequence_error);
|
||||
scene_manager_previous_scene(app->scene_manager);
|
||||
return;
|
||||
}
|
||||
|
||||
if(app->txrx->history) {
|
||||
protopirate_history_release_scratch(app->txrx->history);
|
||||
gdr_history_release_scratch(app->txrx->history);
|
||||
}
|
||||
|
||||
if(!app->radio_initialized && !protopirate_radio_init(app)) {
|
||||
if(!app->radio_initialized && !gdr_radio_init(app)) {
|
||||
FURI_LOG_E(TAG, "Failed to initialize radio for receiver scene");
|
||||
notification_message(app->notifications, &sequence_error);
|
||||
scene_manager_previous_scene(app->scene_manager);
|
||||
@@ -206,25 +206,25 @@ void protopirate_scene_receiver_on_enter(void* context) {
|
||||
}
|
||||
|
||||
if(!app->txrx->history) {
|
||||
app->txrx->history = protopirate_history_alloc();
|
||||
app->txrx->history = gdr_history_alloc();
|
||||
if(!app->txrx->history) {
|
||||
FURI_LOG_E(TAG, "Failed to allocate history!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
protopirate_view_receiver_set_history_mutex(app->protopirate_receiver, NULL);
|
||||
protopirate_view_receiver_sync_menu_from_history(
|
||||
app->protopirate_receiver, app->txrx->history);
|
||||
gdr_view_receiver_set_history_mutex(app->gdr_receiver, NULL);
|
||||
gdr_view_receiver_sync_menu_from_history(
|
||||
app->gdr_receiver, app->txrx->history);
|
||||
|
||||
protopirate_view_receiver_set_callback(
|
||||
app->protopirate_receiver, protopirate_scene_receiver_view_callback, app);
|
||||
gdr_view_receiver_set_callback(
|
||||
app->gdr_receiver, gdr_scene_receiver_view_callback, app);
|
||||
|
||||
protopirate_view_receiver_set_lock(app->protopirate_receiver, app->lock);
|
||||
protopirate_view_receiver_set_autosave(app->protopirate_receiver, app->auto_save);
|
||||
protopirate_view_receiver_set_sub_decode_mode(app->protopirate_receiver, false);
|
||||
gdr_view_receiver_set_lock(app->gdr_receiver, app->lock);
|
||||
gdr_view_receiver_set_autosave(app->gdr_receiver, app->auto_save);
|
||||
gdr_view_receiver_set_sub_decode_mode(app->gdr_receiver, false);
|
||||
|
||||
protopirate_scene_receiver_update_statusbar(app);
|
||||
gdr_scene_receiver_update_statusbar(app);
|
||||
|
||||
#ifndef REMOVE_LOGS
|
||||
bool is_external =
|
||||
@@ -239,121 +239,121 @@ void protopirate_scene_receiver_on_enter(void* context) {
|
||||
FURI_LOG_I(TAG, "Auto-save: %s", app->auto_save ? "ON" : "OFF");
|
||||
#endif
|
||||
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, ProtoPirateViewReceiver);
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, GDRViewReceiver);
|
||||
view_dispatcher_send_custom_event(
|
||||
app->view_dispatcher, ProtoPirateCustomEventReceiverDeferredRxStart);
|
||||
app->view_dispatcher, GDRCustomEventReceiverDeferredRxStart);
|
||||
}
|
||||
|
||||
static void protopirate_scene_receiver_handle_back(ProtoPirateApp* app) {
|
||||
if(app->txrx->history && protopirate_history_get_item(app->txrx->history) > 0 &&
|
||||
static void gdr_scene_receiver_handle_back(GDRApp* app) {
|
||||
if(app->txrx->history && gdr_history_get_item(app->txrx->history) > 0 &&
|
||||
!app->auto_save) {
|
||||
app->unsaved_history_owner = ProtoPirateCaptureOwnerReceiver;
|
||||
scene_manager_set_scene_state(app->scene_manager, ProtoPirateSceneReceiver, 1);
|
||||
scene_manager_next_scene(app->scene_manager, ProtoPirateSceneNeedSaving);
|
||||
app->unsaved_history_owner = GDRCaptureOwnerReceiver;
|
||||
scene_manager_set_scene_state(app->scene_manager, GDRSceneReceiver, 1);
|
||||
scene_manager_next_scene(app->scene_manager, GDRSceneNeedSaving);
|
||||
} else {
|
||||
app->unsaved_history_owner = ProtoPirateCaptureOwnerNone;
|
||||
app->unsaved_history_owner = GDRCaptureOwnerNone;
|
||||
scene_manager_search_and_switch_to_previous_scene(
|
||||
app->scene_manager, ProtoPirateSceneStart);
|
||||
app->scene_manager, GDRSceneStart);
|
||||
}
|
||||
}
|
||||
|
||||
bool protopirate_scene_receiver_on_event(void* context, SceneManagerEvent event) {
|
||||
bool gdr_scene_receiver_on_event(void* context, SceneManagerEvent event) {
|
||||
furi_check(context);
|
||||
ProtoPirateApp* app = context;
|
||||
GDRApp* app = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
switch(event.event) {
|
||||
case ProtoPirateCustomEventReceiverDeferredRxStart:
|
||||
case GDRCustomEventReceiverDeferredRxStart:
|
||||
#ifndef REMOVE_LOGS
|
||||
FURI_LOG_I(TAG, "Deferred RX start (post-emulate path)");
|
||||
#endif
|
||||
protopirate_scene_receiver_start_rx_stack(app);
|
||||
protopirate_scene_receiver_update_statusbar(app);
|
||||
gdr_scene_receiver_start_rx_stack(app);
|
||||
gdr_scene_receiver_update_statusbar(app);
|
||||
consumed = true;
|
||||
break;
|
||||
|
||||
case ProtoPirateCustomEventSceneReceiverUpdate:
|
||||
protopirate_scene_receiver_update_statusbar(app);
|
||||
case GDRCustomEventSceneReceiverUpdate:
|
||||
gdr_scene_receiver_update_statusbar(app);
|
||||
consumed = true;
|
||||
break;
|
||||
|
||||
case ProtoPirateCustomEventViewReceiverOK: {
|
||||
uint16_t idx = protopirate_view_receiver_get_idx_menu(app->protopirate_receiver);
|
||||
case GDRCustomEventViewReceiverOK: {
|
||||
uint16_t idx = gdr_view_receiver_get_idx_menu(app->gdr_receiver);
|
||||
FURI_LOG_I(TAG, "Selected item %d", idx);
|
||||
if(idx < protopirate_history_get_item(app->txrx->history)) {
|
||||
if(idx < gdr_history_get_item(app->txrx->history)) {
|
||||
app->txrx->idx_menu_chosen = idx;
|
||||
protopirate_selected_capture_set(
|
||||
gdr_selected_capture_set(
|
||||
app,
|
||||
app->txrx->history,
|
||||
NULL,
|
||||
idx,
|
||||
ProtoPirateCaptureOwnerReceiver);
|
||||
scene_manager_set_scene_state(app->scene_manager, ProtoPirateSceneReceiver, 1);
|
||||
scene_manager_next_scene(app->scene_manager, ProtoPirateSceneReceiverInfo);
|
||||
GDRCaptureOwnerReceiver);
|
||||
scene_manager_set_scene_state(app->scene_manager, GDRSceneReceiver, 1);
|
||||
scene_manager_next_scene(app->scene_manager, GDRSceneReceiverInfo);
|
||||
}
|
||||
}
|
||||
consumed = true;
|
||||
break;
|
||||
|
||||
case ProtoPirateCustomEventViewReceiverDeleteItem: {
|
||||
uint16_t idx = protopirate_view_receiver_get_idx_menu(app->protopirate_receiver);
|
||||
if(idx < protopirate_history_get_item(app->txrx->history)) {
|
||||
case GDRCustomEventViewReceiverDeleteItem: {
|
||||
uint16_t idx = gdr_view_receiver_get_idx_menu(app->gdr_receiver);
|
||||
if(idx < gdr_history_get_item(app->txrx->history)) {
|
||||
if(app->loaded_file_path &&
|
||||
protopirate_history_capture_path_equals(
|
||||
gdr_history_capture_path_equals(
|
||||
app->txrx->history, idx, furi_string_get_cstr(app->loaded_file_path))) {
|
||||
furi_string_free(app->loaded_file_path);
|
||||
app->loaded_file_path = NULL;
|
||||
}
|
||||
protopirate_history_delete_item(app->txrx->history, idx);
|
||||
protopirate_view_receiver_delete_item(app->protopirate_receiver, idx);
|
||||
gdr_history_delete_item(app->txrx->history, idx);
|
||||
gdr_view_receiver_delete_item(app->gdr_receiver, idx);
|
||||
|
||||
uint16_t count_after =
|
||||
app->txrx->history ? protopirate_history_get_item(app->txrx->history) : 0;
|
||||
app->txrx->history ? gdr_history_get_item(app->txrx->history) : 0;
|
||||
if(count_after == 0) {
|
||||
protopirate_view_receiver_sync_menu_from_history(
|
||||
app->protopirate_receiver, app->txrx->history);
|
||||
protopirate_view_receiver_set_idx_menu(app->protopirate_receiver, 0);
|
||||
gdr_view_receiver_sync_menu_from_history(
|
||||
app->gdr_receiver, app->txrx->history);
|
||||
gdr_view_receiver_set_idx_menu(app->gdr_receiver, 0);
|
||||
}
|
||||
protopirate_scene_receiver_update_statusbar(app);
|
||||
gdr_scene_receiver_update_statusbar(app);
|
||||
app->txrx->idx_menu_chosen =
|
||||
protopirate_view_receiver_get_idx_menu(app->protopirate_receiver);
|
||||
gdr_view_receiver_get_idx_menu(app->gdr_receiver);
|
||||
}
|
||||
consumed = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case ProtoPirateCustomEventViewReceiverConfig:
|
||||
scene_manager_set_scene_state(app->scene_manager, ProtoPirateSceneReceiver, 1);
|
||||
scene_manager_next_scene(app->scene_manager, ProtoPirateSceneReceiverConfig);
|
||||
case GDRCustomEventViewReceiverConfig:
|
||||
scene_manager_set_scene_state(app->scene_manager, GDRSceneReceiver, 1);
|
||||
scene_manager_next_scene(app->scene_manager, GDRSceneReceiverConfig);
|
||||
consumed = true;
|
||||
break;
|
||||
|
||||
case ProtoPirateCustomEventViewReceiverBack:
|
||||
protopirate_scene_receiver_handle_back(app);
|
||||
case GDRCustomEventViewReceiverBack:
|
||||
gdr_scene_receiver_handle_back(app);
|
||||
consumed = true;
|
||||
break;
|
||||
|
||||
case ProtoPirateCustomEventViewReceiverUnlock:
|
||||
app->lock = ProtoPirateLockOff;
|
||||
protopirate_view_receiver_set_lock(app->protopirate_receiver, app->lock);
|
||||
case GDRCustomEventViewReceiverUnlock:
|
||||
app->lock = GDRLockOff;
|
||||
gdr_view_receiver_set_lock(app->gdr_receiver, app->lock);
|
||||
consumed = true;
|
||||
break;
|
||||
}
|
||||
} else if(event.type == SceneManagerEventTypeTick) {
|
||||
if(app->txrx->hopper_state != ProtoPirateHopperStateOFF) {
|
||||
protopirate_hopper_update(app);
|
||||
if(app->txrx->hopper_state != GDRHopperStateOFF) {
|
||||
gdr_hopper_update(app);
|
||||
static uint8_t hopper_statusbar_tick = 0;
|
||||
if(++hopper_statusbar_tick >= 8) {
|
||||
hopper_statusbar_tick = 0;
|
||||
protopirate_scene_receiver_update_statusbar(app);
|
||||
gdr_scene_receiver_update_statusbar(app);
|
||||
}
|
||||
}
|
||||
|
||||
if(app->radio_initialized && app->txrx->txrx_state == ProtoPirateTxRxStateRx &&
|
||||
if(app->radio_initialized && app->txrx->txrx_state == GDRTxRxStateRx &&
|
||||
app->txrx->radio_device) {
|
||||
float rssi = subghz_devices_get_rssi(app->txrx->radio_device);
|
||||
protopirate_view_receiver_set_rssi(app->protopirate_receiver, rssi);
|
||||
gdr_view_receiver_set_rssi(app->gdr_receiver, rssi);
|
||||
|
||||
static uint8_t rssi_log_counter = 0;
|
||||
if(++rssi_log_counter >= 50) {
|
||||
@@ -375,30 +375,30 @@ bool protopirate_scene_receiver_on_event(void* context, SceneManagerEvent event)
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void protopirate_scene_receiver_on_exit(void* context) {
|
||||
void gdr_scene_receiver_on_exit(void* context) {
|
||||
furi_check(context);
|
||||
ProtoPirateApp* app = context;
|
||||
GDRApp* app = context;
|
||||
|
||||
FURI_LOG_I(TAG, "=== EXITING RECEIVER SCENE ===");
|
||||
|
||||
const bool leaving_for_subscene =
|
||||
(scene_manager_get_scene_state(app->scene_manager, ProtoPirateSceneReceiver) == 1);
|
||||
(scene_manager_get_scene_state(app->scene_manager, GDRSceneReceiver) == 1);
|
||||
|
||||
if(app->radio_initialized && app->txrx->txrx_state == ProtoPirateTxRxStateRx) {
|
||||
protopirate_rx_end(app);
|
||||
if(app->radio_initialized && app->txrx->txrx_state == GDRTxRxStateRx) {
|
||||
gdr_rx_end(app);
|
||||
}
|
||||
|
||||
if(leaving_for_subscene) {
|
||||
scene_manager_set_scene_state(app->scene_manager, ProtoPirateSceneReceiver, 0);
|
||||
scene_manager_set_scene_state(app->scene_manager, GDRSceneReceiver, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
protopirate_view_receiver_reset_menu(app->protopirate_receiver);
|
||||
protopirate_radio_deinit(app);
|
||||
gdr_view_receiver_reset_menu(app->gdr_receiver);
|
||||
gdr_radio_deinit(app);
|
||||
}
|
||||
|
||||
void protopirate_scene_receiver_view_callback(ProtoPirateCustomEvent event, void* context) {
|
||||
void gdr_scene_receiver_view_callback(GDRCustomEvent event, void* context) {
|
||||
furi_check(context);
|
||||
ProtoPirateApp* app = context;
|
||||
GDRApp* app = context;
|
||||
view_dispatcher_send_custom_event(app->view_dispatcher, event);
|
||||
}
|
||||
+60
-60
@@ -1,15 +1,15 @@
|
||||
// scenes/protopirate_scene_receiver_config.c
|
||||
#include "../protopirate_app_i.h"
|
||||
// scenes/gdr_scene_receiver_config.c
|
||||
#include "../gdr_app_i.h"
|
||||
|
||||
enum ProtoPirateSettingIndex {
|
||||
ProtoPirateSettingIndexFrequency,
|
||||
ProtoPirateSettingIndexHopping,
|
||||
ProtoPirateSettingIndexModulation,
|
||||
enum GDRSettingIndex {
|
||||
GDRSettingIndexFrequency,
|
||||
GDRSettingIndexHopping,
|
||||
GDRSettingIndexModulation,
|
||||
#ifdef ENABLE_EMULATE_FEATURE
|
||||
ProtoPirateSettingIndexTXPower,
|
||||
GDRSettingIndexTXPower,
|
||||
#endif
|
||||
ProtoPirateSettingIndexAutoSave,
|
||||
ProtoPirateSettingIndexLock,
|
||||
GDRSettingIndexAutoSave,
|
||||
GDRSettingIndexLock,
|
||||
};
|
||||
|
||||
#define HOPPING_COUNT 2
|
||||
@@ -19,8 +19,8 @@ const char* const hopping_text[HOPPING_COUNT] = {
|
||||
};
|
||||
|
||||
const uint32_t hopping_value[HOPPING_COUNT] = {
|
||||
ProtoPirateHopperStateOFF,
|
||||
ProtoPirateHopperStateRunning,
|
||||
GDRHopperStateOFF,
|
||||
GDRHopperStateRunning,
|
||||
};
|
||||
|
||||
#define AUTO_SAVE_COUNT 2
|
||||
@@ -44,9 +44,9 @@ const char* const tx_power_text[TX_POWER_COUNT] = {
|
||||
};
|
||||
#endif
|
||||
|
||||
uint8_t protopirate_scene_receiver_config_next_frequency(const uint32_t value, void* context) {
|
||||
uint8_t gdr_scene_receiver_config_next_frequency(const uint32_t value, void* context) {
|
||||
furi_check(context);
|
||||
ProtoPirateApp* app = context;
|
||||
GDRApp* app = context;
|
||||
uint8_t index = 0;
|
||||
for(uint8_t i = 0; i < subghz_setting_get_frequency_count(app->setting); i++) {
|
||||
if(value == subghz_setting_get_frequency(app->setting, i)) {
|
||||
@@ -59,9 +59,9 @@ uint8_t protopirate_scene_receiver_config_next_frequency(const uint32_t value, v
|
||||
return index;
|
||||
}
|
||||
|
||||
uint8_t protopirate_scene_receiver_config_next_preset(const char* preset_name, void* context) {
|
||||
uint8_t gdr_scene_receiver_config_next_preset(const char* preset_name, void* context) {
|
||||
furi_check(context);
|
||||
ProtoPirateApp* app = context;
|
||||
GDRApp* app = context;
|
||||
uint8_t index = 0;
|
||||
for(uint8_t i = 0; i < subghz_setting_get_preset_count(app->setting); i++) {
|
||||
if(!strcmp(subghz_setting_get_preset_name(app->setting, i), preset_name)) {
|
||||
@@ -72,31 +72,31 @@ uint8_t protopirate_scene_receiver_config_next_preset(const char* preset_name, v
|
||||
return index;
|
||||
}
|
||||
|
||||
uint8_t protopirate_scene_receiver_config_hopper_value_index(
|
||||
uint8_t gdr_scene_receiver_config_hopper_value_index(
|
||||
const uint32_t value,
|
||||
const uint32_t values[],
|
||||
uint8_t values_count,
|
||||
void* context) {
|
||||
furi_check(context);
|
||||
UNUSED(values_count);
|
||||
ProtoPirateApp* app = context;
|
||||
GDRApp* app = context;
|
||||
|
||||
if(value == values[0]) {
|
||||
return 0;
|
||||
} else {
|
||||
variable_item_set_current_value_text(
|
||||
(VariableItem*)scene_manager_get_scene_state(
|
||||
app->scene_manager, ProtoPirateSceneReceiverConfig),
|
||||
app->scene_manager, GDRSceneReceiverConfig),
|
||||
" -----");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
static void protopirate_scene_receiver_config_set_frequency(VariableItem* item) {
|
||||
ProtoPirateApp* app = variable_item_get_context(item);
|
||||
static void gdr_scene_receiver_config_set_frequency(VariableItem* item) {
|
||||
GDRApp* app = variable_item_get_context(item);
|
||||
uint8_t index = variable_item_get_current_value_index(item);
|
||||
|
||||
if(app->txrx->hopper_state == ProtoPirateHopperStateOFF) {
|
||||
if(app->txrx->hopper_state == GDRHopperStateOFF) {
|
||||
char text_buf[10] = {0};
|
||||
snprintf(
|
||||
text_buf,
|
||||
@@ -112,29 +112,29 @@ static void protopirate_scene_receiver_config_set_frequency(VariableItem* item)
|
||||
}
|
||||
}
|
||||
|
||||
static void protopirate_scene_receiver_config_set_preset(VariableItem* item) {
|
||||
ProtoPirateApp* app = variable_item_get_context(item);
|
||||
static void gdr_scene_receiver_config_set_preset(VariableItem* item) {
|
||||
GDRApp* app = variable_item_get_context(item);
|
||||
uint8_t index = variable_item_get_current_value_index(item);
|
||||
variable_item_set_current_value_text(
|
||||
item, subghz_setting_get_preset_name(app->setting, index));
|
||||
protopirate_preset_init(
|
||||
gdr_preset_init(
|
||||
app,
|
||||
subghz_setting_get_preset_name(app->setting, index),
|
||||
app->txrx->preset->frequency,
|
||||
subghz_setting_get_preset_data(app->setting, index),
|
||||
subghz_setting_get_preset_data_size(app->setting, index));
|
||||
|
||||
if(!protopirate_refresh_protocol_registry(app, false)) {
|
||||
if(!gdr_refresh_protocol_registry(app, false)) {
|
||||
notification_message(app->notifications, &sequence_error);
|
||||
}
|
||||
}
|
||||
|
||||
static void protopirate_scene_receiver_config_set_hopping_running(VariableItem* item) {
|
||||
ProtoPirateApp* app = variable_item_get_context(item);
|
||||
static void gdr_scene_receiver_config_set_hopping_running(VariableItem* item) {
|
||||
GDRApp* app = variable_item_get_context(item);
|
||||
uint8_t index = variable_item_get_current_value_index(item);
|
||||
|
||||
variable_item_set_current_value_text(item, hopping_text[index]);
|
||||
if(hopping_value[index] == ProtoPirateHopperStateOFF) {
|
||||
if(hopping_value[index] == GDRHopperStateOFF) {
|
||||
char text_buf[10] = {0};
|
||||
snprintf(
|
||||
text_buf,
|
||||
@@ -144,29 +144,29 @@ static void protopirate_scene_receiver_config_set_hopping_running(VariableItem*
|
||||
(subghz_setting_get_default_frequency(app->setting) % 1000000) / 10000);
|
||||
variable_item_set_current_value_text(
|
||||
(VariableItem*)scene_manager_get_scene_state(
|
||||
app->scene_manager, ProtoPirateSceneReceiverConfig),
|
||||
app->scene_manager, GDRSceneReceiverConfig),
|
||||
text_buf);
|
||||
app->txrx->preset->frequency = subghz_setting_get_default_frequency(app->setting);
|
||||
variable_item_set_current_value_index(
|
||||
(VariableItem*)scene_manager_get_scene_state(
|
||||
app->scene_manager, ProtoPirateSceneReceiverConfig),
|
||||
app->scene_manager, GDRSceneReceiverConfig),
|
||||
subghz_setting_get_frequency_default_index(app->setting));
|
||||
} else {
|
||||
variable_item_set_current_value_text(
|
||||
(VariableItem*)scene_manager_get_scene_state(
|
||||
app->scene_manager, ProtoPirateSceneReceiverConfig),
|
||||
app->scene_manager, GDRSceneReceiverConfig),
|
||||
" -----");
|
||||
variable_item_set_current_value_index(
|
||||
(VariableItem*)scene_manager_get_scene_state(
|
||||
app->scene_manager, ProtoPirateSceneReceiverConfig),
|
||||
app->scene_manager, GDRSceneReceiverConfig),
|
||||
subghz_setting_get_frequency_default_index(app->setting));
|
||||
}
|
||||
|
||||
app->txrx->hopper_state = hopping_value[index];
|
||||
}
|
||||
|
||||
static void protopirate_scene_receiver_config_set_auto_save(VariableItem* item) {
|
||||
ProtoPirateApp* app = variable_item_get_context(item);
|
||||
static void gdr_scene_receiver_config_set_auto_save(VariableItem* item) {
|
||||
GDRApp* app = variable_item_get_context(item);
|
||||
uint8_t index = variable_item_get_current_value_index(item);
|
||||
|
||||
app->auto_save = (index == 1);
|
||||
@@ -174,8 +174,8 @@ static void protopirate_scene_receiver_config_set_auto_save(VariableItem* item)
|
||||
}
|
||||
|
||||
#ifdef ENABLE_EMULATE_FEATURE
|
||||
static void protopirate_scene_receiver_config_set_tx_power(VariableItem* item) {
|
||||
ProtoPirateApp* app = variable_item_get_context(item);
|
||||
static void gdr_scene_receiver_config_set_tx_power(VariableItem* item) {
|
||||
GDRApp* app = variable_item_get_context(item);
|
||||
uint8_t index = variable_item_get_current_value_index(item);
|
||||
|
||||
app->tx_power = index;
|
||||
@@ -184,21 +184,21 @@ static void protopirate_scene_receiver_config_set_tx_power(VariableItem* item) {
|
||||
#endif
|
||||
|
||||
static void
|
||||
protopirate_scene_receiver_config_var_list_enter_callback(void* context, uint32_t index) {
|
||||
gdr_scene_receiver_config_var_list_enter_callback(void* context, uint32_t index) {
|
||||
furi_check(context);
|
||||
ProtoPirateApp* app = context;
|
||||
if(index == ProtoPirateSettingIndexLock) {
|
||||
GDRApp* app = context;
|
||||
if(index == GDRSettingIndexLock) {
|
||||
view_dispatcher_send_custom_event(
|
||||
app->view_dispatcher, ProtoPirateCustomEventSceneSettingLock);
|
||||
app->view_dispatcher, GDRCustomEventSceneSettingLock);
|
||||
}
|
||||
}
|
||||
|
||||
void protopirate_scene_receiver_config_on_enter(void* context) {
|
||||
ProtoPirateApp* app = context;
|
||||
void gdr_scene_receiver_config_on_enter(void* context) {
|
||||
GDRApp* app = context;
|
||||
VariableItem* item;
|
||||
uint8_t value_index;
|
||||
|
||||
if(!protopirate_ensure_variable_item_list(app)) {
|
||||
if(!gdr_ensure_variable_item_list(app)) {
|
||||
notification_message(app->notifications, &sequence_error);
|
||||
scene_manager_previous_scene(app->scene_manager);
|
||||
return;
|
||||
@@ -208,12 +208,12 @@ void protopirate_scene_receiver_config_on_enter(void* context) {
|
||||
app->variable_item_list,
|
||||
"Frequency:",
|
||||
subghz_setting_get_frequency_count(app->setting),
|
||||
protopirate_scene_receiver_config_set_frequency,
|
||||
gdr_scene_receiver_config_set_frequency,
|
||||
app);
|
||||
value_index =
|
||||
protopirate_scene_receiver_config_next_frequency(app->txrx->preset->frequency, app);
|
||||
gdr_scene_receiver_config_next_frequency(app->txrx->preset->frequency, app);
|
||||
scene_manager_set_scene_state(
|
||||
app->scene_manager, ProtoPirateSceneReceiverConfig, (uint32_t)item);
|
||||
app->scene_manager, GDRSceneReceiverConfig, (uint32_t)item);
|
||||
variable_item_set_current_value_index(item, value_index);
|
||||
char text_buf[10] = {0};
|
||||
snprintf(
|
||||
@@ -228,9 +228,9 @@ void protopirate_scene_receiver_config_on_enter(void* context) {
|
||||
app->variable_item_list,
|
||||
"Hopping:",
|
||||
HOPPING_COUNT,
|
||||
protopirate_scene_receiver_config_set_hopping_running,
|
||||
gdr_scene_receiver_config_set_hopping_running,
|
||||
app);
|
||||
value_index = protopirate_scene_receiver_config_hopper_value_index(
|
||||
value_index = gdr_scene_receiver_config_hopper_value_index(
|
||||
app->txrx->hopper_state, hopping_value, HOPPING_COUNT, app);
|
||||
variable_item_set_current_value_index(item, value_index);
|
||||
variable_item_set_current_value_text(item, hopping_text[value_index]);
|
||||
@@ -239,9 +239,9 @@ void protopirate_scene_receiver_config_on_enter(void* context) {
|
||||
app->variable_item_list,
|
||||
"Modulation:",
|
||||
subghz_setting_get_preset_count(app->setting),
|
||||
protopirate_scene_receiver_config_set_preset,
|
||||
gdr_scene_receiver_config_set_preset,
|
||||
app);
|
||||
value_index = protopirate_scene_receiver_config_next_preset(
|
||||
value_index = gdr_scene_receiver_config_next_preset(
|
||||
furi_string_get_cstr(app->txrx->preset->name), app);
|
||||
variable_item_set_current_value_index(item, value_index);
|
||||
variable_item_set_current_value_text(
|
||||
@@ -253,7 +253,7 @@ void protopirate_scene_receiver_config_on_enter(void* context) {
|
||||
app->variable_item_list,
|
||||
"TX Power:",
|
||||
TX_POWER_COUNT,
|
||||
protopirate_scene_receiver_config_set_tx_power,
|
||||
gdr_scene_receiver_config_set_tx_power,
|
||||
app);
|
||||
variable_item_set_current_value_index(item, app->tx_power);
|
||||
variable_item_set_current_value_text(item, tx_power_text[app->tx_power]);
|
||||
@@ -263,25 +263,25 @@ void protopirate_scene_receiver_config_on_enter(void* context) {
|
||||
app->variable_item_list,
|
||||
"Auto-Save:",
|
||||
AUTO_SAVE_COUNT,
|
||||
protopirate_scene_receiver_config_set_auto_save,
|
||||
gdr_scene_receiver_config_set_auto_save,
|
||||
app);
|
||||
variable_item_set_current_value_index(item, app->auto_save ? 1 : 0);
|
||||
variable_item_set_current_value_text(item, auto_save_text[app->auto_save ? 1 : 0]);
|
||||
|
||||
variable_item_list_add(app->variable_item_list, "Lock Keyboard", 1, NULL, NULL);
|
||||
variable_item_list_set_enter_callback(
|
||||
app->variable_item_list, protopirate_scene_receiver_config_var_list_enter_callback, app);
|
||||
app->variable_item_list, gdr_scene_receiver_config_var_list_enter_callback, app);
|
||||
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, ProtoPirateViewVariableItemList);
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, GDRViewVariableItemList);
|
||||
}
|
||||
|
||||
bool protopirate_scene_receiver_config_on_event(void* context, SceneManagerEvent event) {
|
||||
ProtoPirateApp* app = context;
|
||||
bool gdr_scene_receiver_config_on_event(void* context, SceneManagerEvent event) {
|
||||
GDRApp* app = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == ProtoPirateCustomEventSceneSettingLock) {
|
||||
app->lock = ProtoPirateLockOn;
|
||||
if(event.event == GDRCustomEventSceneSettingLock) {
|
||||
app->lock = GDRLockOn;
|
||||
scene_manager_previous_scene(app->scene_manager);
|
||||
consumed = true;
|
||||
}
|
||||
@@ -289,8 +289,8 @@ bool protopirate_scene_receiver_config_on_event(void* context, SceneManagerEvent
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void protopirate_scene_receiver_config_on_exit(void* context) {
|
||||
ProtoPirateApp* app = context;
|
||||
void gdr_scene_receiver_config_on_exit(void* context) {
|
||||
GDRApp* app = context;
|
||||
variable_item_list_set_selected_item(app->variable_item_list, 0);
|
||||
variable_item_list_reset(app->variable_item_list);
|
||||
}
|
||||
+76
-76
@@ -1,27 +1,27 @@
|
||||
// scenes/protopirate_scene_receiver_info.c
|
||||
#include "../protopirate_app_i.h"
|
||||
#include "../helpers/protopirate_storage.h"
|
||||
#include "../helpers/protopirate_psa_bf_host.h"
|
||||
#include "proto_pirate_icons.h"
|
||||
// scenes/gdr_scene_receiver_info.c
|
||||
#include "../gdr_app_i.h"
|
||||
#include "../helpers/gdr_storage.h"
|
||||
#include "../helpers/gdr_psa_bf_host.h"
|
||||
#include "gdr_icons.h"
|
||||
|
||||
#define TAG "ProtoPirateReceiverInfo"
|
||||
#define TAG "GDRReceiverInfo"
|
||||
|
||||
static void protopirate_scene_receiver_info_widget_callback(
|
||||
static void gdr_scene_receiver_info_widget_callback(
|
||||
GuiButtonType result,
|
||||
InputType type,
|
||||
void* context);
|
||||
|
||||
static void protopirate_scene_receiver_info_text_input_callback(void* context) {
|
||||
ProtoPirateApp* app = context;
|
||||
static void gdr_scene_receiver_info_text_input_callback(void* context) {
|
||||
GDRApp* app = context;
|
||||
view_dispatcher_send_custom_event(
|
||||
app->view_dispatcher, ProtoPirateCustomEventReceiverInfoSaveConfirm);
|
||||
app->view_dispatcher, GDRCustomEventReceiverInfoSaveConfirm);
|
||||
}
|
||||
|
||||
static void protopirate_receiver_info_build_normal_widget(ProtoPirateApp* app) {
|
||||
static void gdr_receiver_info_build_normal_widget(GDRApp* app) {
|
||||
widget_reset(app->widget);
|
||||
|
||||
ProtoPirateHistory* history = protopirate_selected_capture_get_history(app);
|
||||
uint16_t selected_index = protopirate_selected_capture_get_index(app);
|
||||
GDRHistory* history = gdr_selected_capture_get_history(app);
|
||||
uint16_t selected_index = gdr_selected_capture_get_index(app);
|
||||
if(!history) {
|
||||
widget_add_string_element(
|
||||
app->widget, 64, 32, AlignCenter, AlignCenter, FontPrimary, "Capture unavailable");
|
||||
@@ -29,16 +29,16 @@ static void protopirate_receiver_info_build_normal_widget(ProtoPirateApp* app) {
|
||||
}
|
||||
|
||||
FuriString* text = furi_string_alloc();
|
||||
protopirate_history_get_text_item_menu(history, text, selected_index);
|
||||
gdr_history_get_text_item_menu(history, text, selected_index);
|
||||
widget_add_string_element(
|
||||
app->widget, 64, 0, AlignCenter, AlignTop, FontPrimary, furi_string_get_cstr(text));
|
||||
|
||||
furi_string_reset(text);
|
||||
protopirate_history_get_text_item_detail(
|
||||
gdr_history_get_text_item_detail(
|
||||
history, selected_index, text, app->txrx->environment);
|
||||
|
||||
bool is_psa = false;
|
||||
FlipperFormat* ff = protopirate_selected_capture_get_raw_data(app);
|
||||
FlipperFormat* ff = gdr_selected_capture_get_raw_data(app);
|
||||
if(ff) {
|
||||
FuriString* protocol = furi_string_alloc();
|
||||
flipper_format_rewind(ff);
|
||||
@@ -60,10 +60,10 @@ static void protopirate_receiver_info_build_normal_widget(ProtoPirateApp* app) {
|
||||
}
|
||||
|
||||
FuriString* display_text = furi_string_alloc();
|
||||
ProtoPirateHistorySource source = protopirate_selected_capture_get_source(app);
|
||||
if(source != ProtoPirateHistorySourceUnknown) {
|
||||
GDRHistorySource source = gdr_selected_capture_get_source(app);
|
||||
if(source != GDRHistorySourceUnknown) {
|
||||
furi_string_cat_printf(
|
||||
display_text, "Receiver: %s\r\n", protopirate_history_source_name(source));
|
||||
display_text, "Receiver: %s\r\n", gdr_history_source_name(source));
|
||||
}
|
||||
furi_string_cat_str(display_text, text_str);
|
||||
text_str = furi_string_get_cstr(display_text);
|
||||
@@ -119,16 +119,16 @@ static void protopirate_receiver_info_build_normal_widget(ProtoPirateApp* app) {
|
||||
}
|
||||
|
||||
bool psa_needs_bf = false;
|
||||
if(is_psa && protopirate_psa_bf_plugin_ensure_loaded(app) && app->psa_bf_plugin) {
|
||||
if(is_psa && gdr_psa_bf_plugin_ensure_loaded(app) && app->psa_bf_plugin) {
|
||||
psa_needs_bf = app->psa_bf_plugin->widget_left_should_bruteforce(
|
||||
app, ProtoPiratePsaBfContextReceiverInfo);
|
||||
app, GDRPsaBfContextReceiverInfo);
|
||||
}
|
||||
if(psa_needs_bf) {
|
||||
widget_add_button_element(
|
||||
app->widget,
|
||||
GuiButtonTypeLeft,
|
||||
"Brute force",
|
||||
protopirate_scene_receiver_info_widget_callback,
|
||||
gdr_scene_receiver_info_widget_callback,
|
||||
app);
|
||||
} else
|
||||
#ifdef ENABLE_EMULATE_FEATURE
|
||||
@@ -137,7 +137,7 @@ static void protopirate_receiver_info_build_normal_widget(ProtoPirateApp* app) {
|
||||
app->widget,
|
||||
GuiButtonTypeLeft,
|
||||
"Emulate",
|
||||
protopirate_scene_receiver_info_widget_callback,
|
||||
gdr_scene_receiver_info_widget_callback,
|
||||
app);
|
||||
}
|
||||
#endif
|
||||
@@ -146,51 +146,51 @@ static void protopirate_receiver_info_build_normal_widget(ProtoPirateApp* app) {
|
||||
app->widget,
|
||||
GuiButtonTypeRight,
|
||||
"Save",
|
||||
protopirate_scene_receiver_info_widget_callback,
|
||||
gdr_scene_receiver_info_widget_callback,
|
||||
app);
|
||||
|
||||
furi_string_free(display_text);
|
||||
furi_string_free(text);
|
||||
}
|
||||
|
||||
void protopirate_receiver_info_rebuild_normal_widget(void* app) {
|
||||
protopirate_receiver_info_build_normal_widget((ProtoPirateApp*)app);
|
||||
void gdr_receiver_info_rebuild_normal_widget(void* app) {
|
||||
gdr_receiver_info_build_normal_widget((GDRApp*)app);
|
||||
}
|
||||
|
||||
static void protopirate_scene_receiver_info_widget_callback(
|
||||
static void gdr_scene_receiver_info_widget_callback(
|
||||
GuiButtonType result,
|
||||
InputType type,
|
||||
void* context) {
|
||||
ProtoPirateApp* app = context;
|
||||
GDRApp* app = context;
|
||||
if(type == InputTypeShort || type == InputTypeLong) {
|
||||
if(result == GuiButtonTypeRight) {
|
||||
view_dispatcher_send_custom_event(
|
||||
app->view_dispatcher, ProtoPirateCustomEventReceiverInfoSave);
|
||||
app->view_dispatcher, GDRCustomEventReceiverInfoSave);
|
||||
} else if(result == GuiButtonTypeLeft) {
|
||||
if(protopirate_psa_bf_plugin_ensure_loaded(app) && app->psa_bf_plugin &&
|
||||
if(gdr_psa_bf_plugin_ensure_loaded(app) && app->psa_bf_plugin &&
|
||||
app->psa_bf_plugin->widget_left_should_bruteforce(
|
||||
app, ProtoPiratePsaBfContextReceiverInfo)) {
|
||||
app, GDRPsaBfContextReceiverInfo)) {
|
||||
view_dispatcher_send_custom_event(
|
||||
app->view_dispatcher, ProtoPirateCustomEventReceiverInfoBruteforceStart);
|
||||
app->view_dispatcher, GDRCustomEventReceiverInfoBruteforceStart);
|
||||
} else
|
||||
#ifdef ENABLE_EMULATE_FEATURE
|
||||
if(app->emulate_feature_enabled && !app->emulate_disabled_for_loaded) {
|
||||
view_dispatcher_send_custom_event(
|
||||
app->view_dispatcher, ProtoPirateCustomEventReceiverInfoEmulate);
|
||||
app->view_dispatcher, GDRCustomEventReceiverInfoEmulate);
|
||||
}
|
||||
#endif
|
||||
} else if(result == GuiButtonTypeCenter) {
|
||||
view_dispatcher_send_custom_event(
|
||||
app->view_dispatcher, ProtoPirateCustomEventReceiverInfoBruteforceCancel);
|
||||
app->view_dispatcher, GDRCustomEventReceiverInfoBruteforceCancel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void protopirate_scene_receiver_info_on_enter(void* context) {
|
||||
void gdr_scene_receiver_info_on_enter(void* context) {
|
||||
furi_check(context);
|
||||
ProtoPirateApp* app = context;
|
||||
GDRApp* app = context;
|
||||
|
||||
if(!protopirate_ensure_widget(app) || !protopirate_ensure_text_input(app)) {
|
||||
if(!gdr_ensure_widget(app) || !gdr_ensure_text_input(app)) {
|
||||
notification_message(app->notifications, &sequence_error);
|
||||
scene_manager_previous_scene(app->scene_manager);
|
||||
return;
|
||||
@@ -198,51 +198,51 @@ void protopirate_scene_receiver_info_on_enter(void* context) {
|
||||
|
||||
app->emulate_disabled_for_loaded = false;
|
||||
|
||||
if(!protopirate_selected_capture_is_valid(app) && app->txrx && app->txrx->history &&
|
||||
app->txrx->idx_menu_chosen < protopirate_history_get_item(app->txrx->history)) {
|
||||
protopirate_selected_capture_set(
|
||||
if(!gdr_selected_capture_is_valid(app) && app->txrx && app->txrx->history &&
|
||||
app->txrx->idx_menu_chosen < gdr_history_get_item(app->txrx->history)) {
|
||||
gdr_selected_capture_set(
|
||||
app,
|
||||
app->txrx->history,
|
||||
NULL,
|
||||
app->txrx->idx_menu_chosen,
|
||||
ProtoPirateCaptureOwnerReceiver);
|
||||
GDRCaptureOwnerReceiver);
|
||||
}
|
||||
|
||||
if(protopirate_psa_bf_plugin_ensure_loaded(app) && app->psa_bf_plugin) {
|
||||
if(gdr_psa_bf_plugin_ensure_loaded(app) && app->psa_bf_plugin) {
|
||||
if(app->psa_bf_plugin->is_running(app)) {
|
||||
app->psa_bf_plugin->on_scene_enter(app, ProtoPiratePsaBfContextReceiverInfo);
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, ProtoPirateViewWidget);
|
||||
app->psa_bf_plugin->on_scene_enter(app, GDRPsaBfContextReceiverInfo);
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, GDRViewWidget);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
protopirate_receiver_info_build_normal_widget(app);
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, ProtoPirateViewWidget);
|
||||
gdr_receiver_info_build_normal_widget(app);
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, GDRViewWidget);
|
||||
}
|
||||
|
||||
bool protopirate_scene_receiver_info_on_event(void* context, SceneManagerEvent event) {
|
||||
ProtoPirateApp* app = context;
|
||||
bool gdr_scene_receiver_info_on_event(void* context, SceneManagerEvent event) {
|
||||
GDRApp* app = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(protopirate_psa_bf_plugin_ensure_loaded(app) && app->psa_bf_plugin) {
|
||||
if(gdr_psa_bf_plugin_ensure_loaded(app) && app->psa_bf_plugin) {
|
||||
if(app->psa_bf_plugin->is_running(app) ||
|
||||
event.event == ProtoPirateCustomEventPsaBruteforceComplete ||
|
||||
event.event == ProtoPirateCustomEventReceiverInfoBruteforceStart ||
|
||||
event.event == ProtoPirateCustomEventReceiverInfoBruteforceCancel) {
|
||||
event.event == GDRCustomEventPsaBruteforceComplete ||
|
||||
event.event == GDRCustomEventReceiverInfoBruteforceStart ||
|
||||
event.event == GDRCustomEventReceiverInfoBruteforceCancel) {
|
||||
consumed = app->psa_bf_plugin->on_scene_event(
|
||||
app, ProtoPiratePsaBfContextReceiverInfo, event);
|
||||
app, GDRPsaBfContextReceiverInfo, event);
|
||||
if(consumed) return true;
|
||||
}
|
||||
if(event.type == SceneManagerEventTypeBack &&
|
||||
app->psa_bf_plugin->on_scene_event(
|
||||
app, ProtoPiratePsaBfContextReceiverInfo, event)) {
|
||||
app, GDRPsaBfContextReceiverInfo, event)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == ProtoPirateCustomEventReceiverInfoSave) {
|
||||
FlipperFormat* ff = protopirate_selected_capture_get_raw_data(app);
|
||||
if(event.event == GDRCustomEventReceiverInfoSave) {
|
||||
FlipperFormat* ff = gdr_selected_capture_get_raw_data(app);
|
||||
if(ff) {
|
||||
FuriString* protocol = furi_string_alloc();
|
||||
flipper_format_rewind(ff);
|
||||
@@ -254,7 +254,7 @@ bool protopirate_scene_receiver_info_on_event(void* context, SceneManagerEvent e
|
||||
furi_string_replace_all(protocol, " ", "_");
|
||||
|
||||
FuriString* auto_path = furi_string_alloc();
|
||||
if(protopirate_storage_get_next_filename(
|
||||
if(gdr_storage_get_next_filename(
|
||||
furi_string_get_cstr(protocol), auto_path)) {
|
||||
const char* full = furi_string_get_cstr(auto_path);
|
||||
const char* slash = strrchr(full, '/');
|
||||
@@ -275,36 +275,36 @@ bool protopirate_scene_receiver_info_on_event(void* context, SceneManagerEvent e
|
||||
|
||||
if(app->save_protocol) furi_string_free(app->save_protocol);
|
||||
app->save_protocol = protocol;
|
||||
app->save_history_idx = protopirate_selected_capture_get_index(app);
|
||||
app->save_history_idx = gdr_selected_capture_get_index(app);
|
||||
app->save_from_saved_info = false;
|
||||
|
||||
text_input_reset(app->text_input);
|
||||
text_input_set_header_text(app->text_input, "Save filename:");
|
||||
text_input_set_result_callback(
|
||||
app->text_input,
|
||||
protopirate_scene_receiver_info_text_input_callback,
|
||||
gdr_scene_receiver_info_text_input_callback,
|
||||
app,
|
||||
app->save_filename,
|
||||
sizeof(app->save_filename),
|
||||
false);
|
||||
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, ProtoPirateViewTextInput);
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, GDRViewTextInput);
|
||||
}
|
||||
consumed = true;
|
||||
}
|
||||
|
||||
if(event.event == ProtoPirateCustomEventReceiverInfoSaveConfirm) {
|
||||
ProtoPirateHistory* history = protopirate_selected_capture_get_history(app);
|
||||
if(event.event == GDRCustomEventReceiverInfoSaveConfirm) {
|
||||
GDRHistory* history = gdr_selected_capture_get_history(app);
|
||||
FlipperFormat* ff =
|
||||
history ? protopirate_history_get_raw_data(history, app->save_history_idx) : NULL;
|
||||
history ? gdr_history_get_raw_data(history, app->save_history_idx) : NULL;
|
||||
if(ff) {
|
||||
FuriString* save_path = furi_string_alloc_printf(
|
||||
"%s/%s%s",
|
||||
PROTOPIRATE_APP_FOLDER,
|
||||
GDR_APP_FOLDER,
|
||||
app->save_filename,
|
||||
PROTOPIRATE_APP_EXTENSION);
|
||||
GDR_APP_EXTENSION);
|
||||
|
||||
if(protopirate_storage_save_capture_to_path(ff, furi_string_get_cstr(save_path))) {
|
||||
if(gdr_storage_save_capture_to_path(ff, furi_string_get_cstr(save_path))) {
|
||||
notification_message(app->notifications, &sequence_success);
|
||||
FURI_LOG_I(TAG, "Saved to: %s", furi_string_get_cstr(save_path));
|
||||
} else {
|
||||
@@ -319,16 +319,16 @@ bool protopirate_scene_receiver_info_on_event(void* context, SceneManagerEvent e
|
||||
app->save_protocol = NULL;
|
||||
}
|
||||
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, ProtoPirateViewWidget);
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, GDRViewWidget);
|
||||
consumed = true;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_EMULATE_FEATURE
|
||||
if(event.event == ProtoPirateCustomEventReceiverInfoEmulate &&
|
||||
if(event.event == GDRCustomEventReceiverInfoEmulate &&
|
||||
app->emulate_feature_enabled && !app->emulate_disabled_for_loaded) {
|
||||
FuriString* hist_path = furi_string_alloc();
|
||||
if(protopirate_selected_capture_get_path(app, hist_path)) {
|
||||
protopirate_selected_capture_release_scratch(app);
|
||||
if(gdr_selected_capture_get_path(app, hist_path)) {
|
||||
gdr_selected_capture_release_scratch(app);
|
||||
if(app->loaded_file_path) furi_string_free(app->loaded_file_path);
|
||||
app->loaded_file_path = furi_string_alloc_set(hist_path);
|
||||
furi_string_free(hist_path);
|
||||
@@ -336,13 +336,13 @@ bool protopirate_scene_receiver_info_on_event(void* context, SceneManagerEvent e
|
||||
TAG,
|
||||
"Emulate from history file: %s",
|
||||
furi_string_get_cstr(app->loaded_file_path));
|
||||
scene_manager_next_scene(app->scene_manager, ProtoPirateSceneEmulate);
|
||||
scene_manager_next_scene(app->scene_manager, GDRSceneEmulate);
|
||||
} else {
|
||||
furi_string_free(hist_path);
|
||||
FURI_LOG_E(
|
||||
TAG,
|
||||
"No capture path for index %d",
|
||||
protopirate_selected_capture_get_index(app));
|
||||
gdr_selected_capture_get_index(app));
|
||||
notification_message(app->notifications, &sequence_error);
|
||||
}
|
||||
consumed = true;
|
||||
@@ -353,10 +353,10 @@ bool protopirate_scene_receiver_info_on_event(void* context, SceneManagerEvent e
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void protopirate_scene_receiver_info_on_exit(void* context) {
|
||||
void gdr_scene_receiver_info_on_exit(void* context) {
|
||||
furi_check(context);
|
||||
ProtoPirateApp* app = context;
|
||||
GDRApp* app = context;
|
||||
widget_reset(app->widget);
|
||||
protopirate_selected_capture_release_scratch(app);
|
||||
protopirate_psa_bf_plugin_unload_if_idle(app);
|
||||
gdr_selected_capture_release_scratch(app);
|
||||
gdr_psa_bf_plugin_unload_if_idle(app);
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
// scenes/gdr_scene_saved.c
|
||||
#include "../gdr_app_i.h"
|
||||
|
||||
#define TAG "GDRSceneSaved"
|
||||
|
||||
void gdr_scene_saved_on_enter(void* context) {
|
||||
GDRApp* app = context;
|
||||
scene_manager_previous_scene(app->scene_manager);
|
||||
}
|
||||
|
||||
bool gdr_scene_saved_on_event(void* context, SceneManagerEvent event) {
|
||||
UNUSED(context);
|
||||
UNUSED(event);
|
||||
return false;
|
||||
}
|
||||
|
||||
void gdr_scene_saved_on_exit(void* context) {
|
||||
UNUSED(context);
|
||||
}
|
||||
+24
-24
@@ -1,34 +1,34 @@
|
||||
// scenes/protopirate_scene_saved_info.c
|
||||
#include "../protopirate_app_i.h"
|
||||
#include "../helpers/protopirate_storage.h"
|
||||
// scenes/gdr_scene_saved_info.c
|
||||
#include "../gdr_app_i.h"
|
||||
#include "../helpers/gdr_storage.h"
|
||||
#include "../protocols/protocols_common.h"
|
||||
#include "proto_pirate_icons.h"
|
||||
#include "gdr_icons.h"
|
||||
|
||||
#define TAG "ProtoPirateSceneSavedInfo"
|
||||
#define TAG "GDRSceneSavedInfo"
|
||||
|
||||
static void protopirate_scene_saved_info_widget_callback(
|
||||
static void gdr_scene_saved_info_widget_callback(
|
||||
GuiButtonType result,
|
||||
InputType type,
|
||||
void* context) {
|
||||
ProtoPirateApp* app = context;
|
||||
GDRApp* app = context;
|
||||
|
||||
if((result == GuiButtonTypeLeft) && (type == InputTypeShort)) {
|
||||
#ifdef ENABLE_EMULATE_FEATURE
|
||||
if(app->emulate_feature_enabled && !app->emulate_disabled_for_loaded) {
|
||||
view_dispatcher_send_custom_event(
|
||||
app->view_dispatcher, ProtoPirateCustomEventSavedInfoEmulate);
|
||||
app->view_dispatcher, GDRCustomEventSavedInfoEmulate);
|
||||
}
|
||||
#endif
|
||||
} else if(result == GuiButtonTypeRight && (type == InputTypeShort)) {
|
||||
//Send delete event and get user confirmation to delete.
|
||||
view_dispatcher_send_custom_event(
|
||||
app->view_dispatcher, ProtoPirateCustomEventSavedInfoDelete);
|
||||
app->view_dispatcher, GDRCustomEventSavedInfoDelete);
|
||||
}
|
||||
}
|
||||
|
||||
void protopirate_scene_saved_info_on_enter(void* context) {
|
||||
void gdr_scene_saved_info_on_enter(void* context) {
|
||||
furi_check(context);
|
||||
ProtoPirateApp* app = context;
|
||||
GDRApp* app = context;
|
||||
Storage* storage = NULL;
|
||||
FlipperFormat* ff = NULL;
|
||||
FuriString* info_str = NULL;
|
||||
@@ -37,9 +37,9 @@ void protopirate_scene_saved_info_on_enter(void* context) {
|
||||
|
||||
FURI_LOG_I(TAG, "=== ENTER START ===");
|
||||
|
||||
protopirate_release_shared_radio_state(app);
|
||||
gdr_release_shared_radio_state(app);
|
||||
|
||||
if(!protopirate_ensure_widget(app)) {
|
||||
if(!gdr_ensure_widget(app)) {
|
||||
notification_message(app->notifications, &sequence_error);
|
||||
scene_manager_previous_scene(app->scene_manager);
|
||||
return;
|
||||
@@ -222,7 +222,7 @@ cleanup:
|
||||
app->widget,
|
||||
GuiButtonTypeLeft,
|
||||
"Emulate",
|
||||
protopirate_scene_saved_info_widget_callback,
|
||||
gdr_scene_saved_info_widget_callback,
|
||||
app);
|
||||
}
|
||||
#endif
|
||||
@@ -230,7 +230,7 @@ cleanup:
|
||||
app->widget,
|
||||
GuiButtonTypeRight,
|
||||
"Delete",
|
||||
protopirate_scene_saved_info_widget_callback,
|
||||
gdr_scene_saved_info_widget_callback,
|
||||
app);
|
||||
}
|
||||
|
||||
@@ -242,16 +242,16 @@ cleanup:
|
||||
|
||||
switch_view:
|
||||
FURI_LOG_I(TAG, "Switching to widget");
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, ProtoPirateViewWidget);
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, GDRViewWidget);
|
||||
FURI_LOG_I(TAG, "=== ENTER DONE ===");
|
||||
}
|
||||
|
||||
bool protopirate_scene_saved_info_on_event(void* context, SceneManagerEvent event) {
|
||||
ProtoPirateApp* app = context;
|
||||
bool gdr_scene_saved_info_on_event(void* context, SceneManagerEvent event) {
|
||||
GDRApp* app = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == ProtoPirateCustomEventSavedInfoDelete) {
|
||||
if(event.event == GDRCustomEventSavedInfoDelete) {
|
||||
FURI_LOG_I(TAG, "Delete requested");
|
||||
if(app->loaded_file_path && !furi_string_empty(app->loaded_file_path)) {
|
||||
DialogMessage* message = dialog_message_alloc();
|
||||
@@ -272,17 +272,17 @@ bool protopirate_scene_saved_info_on_event(void* context, SceneManagerEvent even
|
||||
//Delete if the user said yes.
|
||||
if(dialog_result == DialogMessageButtonLeft) {
|
||||
notification_message(app->notifications, &sequence_semi_success);
|
||||
protopirate_storage_delete_file(furi_string_get_cstr(app->loaded_file_path));
|
||||
gdr_storage_delete_file(furi_string_get_cstr(app->loaded_file_path));
|
||||
scene_manager_previous_scene(app->scene_manager);
|
||||
}
|
||||
}
|
||||
consumed = true;
|
||||
}
|
||||
#ifdef ENABLE_EMULATE_FEATURE
|
||||
if(event.event == ProtoPirateCustomEventSavedInfoEmulate &&
|
||||
if(event.event == GDRCustomEventSavedInfoEmulate &&
|
||||
app->emulate_feature_enabled && !app->emulate_disabled_for_loaded) {
|
||||
FURI_LOG_I(TAG, "Emulate requested");
|
||||
scene_manager_next_scene(app->scene_manager, ProtoPirateSceneEmulate);
|
||||
scene_manager_next_scene(app->scene_manager, GDRSceneEmulate);
|
||||
consumed = true;
|
||||
}
|
||||
#endif
|
||||
@@ -291,8 +291,8 @@ bool protopirate_scene_saved_info_on_event(void* context, SceneManagerEvent even
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void protopirate_scene_saved_info_on_exit(void* context) {
|
||||
ProtoPirateApp* app = context;
|
||||
void gdr_scene_saved_info_on_exit(void* context) {
|
||||
GDRApp* app = context;
|
||||
FURI_LOG_I(TAG, "Exiting SavedInfo scene");
|
||||
widget_reset(app->widget);
|
||||
}
|
||||
+128
-128
@@ -1,14 +1,14 @@
|
||||
// scenes/protopirate_scene_shield_receiver.c
|
||||
#include "../protopirate_app_i.h"
|
||||
// scenes/gdr_scene_shield_receiver.c
|
||||
#include "../gdr_app_i.h"
|
||||
|
||||
#ifdef ENABLE_SHIELD_RX_SCENE
|
||||
|
||||
#include "../helpers/protopirate_storage.h"
|
||||
#include "views/protopirate_receiver.h"
|
||||
#include "../helpers/gdr_storage.h"
|
||||
#include "views/gdr_receiver.h"
|
||||
#include <notification/notification_messages.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define TAG "ProtoPirateSceneShieldRx"
|
||||
#define TAG "GDRSceneShieldRx"
|
||||
|
||||
#define SHIELD_SCENE_STATE_NONE 0u
|
||||
#define SHIELD_SCENE_STATE_TO_SUBSCENE 1u
|
||||
@@ -31,15 +31,15 @@ static const int32_t shield_tx_offset_hz[SHIELD_TX_OFFSET_COUNT] = {
|
||||
|
||||
static bool s_shield_devices_inited = false;
|
||||
|
||||
void protopirate_scene_shield_receiver_view_callback(ProtoPirateCustomEvent event, void* context);
|
||||
void gdr_scene_shield_receiver_view_callback(GDRCustomEvent event, void* context);
|
||||
|
||||
static bool protopirate_scene_shield_receiver_auto_save_locked(ProtoPirateApp* app) {
|
||||
uint16_t item_count = protopirate_history_get_item(app->shield_history);
|
||||
static bool gdr_scene_shield_receiver_auto_save_locked(GDRApp* app) {
|
||||
uint16_t item_count = gdr_history_get_item(app->shield_history);
|
||||
if(item_count == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
FlipperFormat* ff = protopirate_history_get_raw_data(app->shield_history, item_count - 1U);
|
||||
FlipperFormat* ff = gdr_history_get_raw_data(app->shield_history, item_count - 1U);
|
||||
if(!ff) {
|
||||
return false;
|
||||
}
|
||||
@@ -63,13 +63,13 @@ static bool protopirate_scene_shield_receiver_auto_save_locked(ProtoPirateApp* a
|
||||
furi_string_replace_all(protocol, "/", "_");
|
||||
furi_string_replace_all(protocol, " ", "_");
|
||||
|
||||
bool saved = protopirate_storage_save_capture(ff, furi_string_get_cstr(protocol), saved_path);
|
||||
bool saved = gdr_storage_save_capture(ff, furi_string_get_cstr(protocol), saved_path);
|
||||
furi_string_free(protocol);
|
||||
furi_string_free(saved_path);
|
||||
return saved;
|
||||
}
|
||||
|
||||
static int32_t protopirate_scene_shield_receiver_tx_offset_hz(const ProtoPirateApp* app) {
|
||||
static int32_t gdr_scene_shield_receiver_tx_offset_hz(const GDRApp* app) {
|
||||
furi_check(app);
|
||||
uint8_t index = app->shield_tx_offset_index;
|
||||
if(index >= SHIELD_TX_OFFSET_COUNT) {
|
||||
@@ -78,33 +78,33 @@ static int32_t protopirate_scene_shield_receiver_tx_offset_hz(const ProtoPirateA
|
||||
return shield_tx_offset_hz[index];
|
||||
}
|
||||
|
||||
static int32_t protopirate_scene_shield_receiver_resolve_tx_offset(ProtoPirateApp* app) {
|
||||
static int32_t gdr_scene_shield_receiver_resolve_tx_offset(GDRApp* app) {
|
||||
|
||||
return protopirate_scene_shield_receiver_tx_offset_hz(app);
|
||||
return gdr_scene_shield_receiver_tx_offset_hz(app);
|
||||
}
|
||||
|
||||
static void protopirate_scene_shield_receiver_decode_cb(
|
||||
static void gdr_scene_shield_receiver_decode_cb(
|
||||
SubGhzReceiver* receiver,
|
||||
SubGhzProtocolDecoderBase* decoder_base,
|
||||
void* context) {
|
||||
UNUSED(receiver);
|
||||
furi_check(decoder_base);
|
||||
furi_check(context);
|
||||
ProtoPirateApp* app = context;
|
||||
GDRApp* app = context;
|
||||
|
||||
if(!app->shield_history || !app->shield_history_mutex || !app->shield_rx_chain) {
|
||||
return;
|
||||
}
|
||||
|
||||
furi_mutex_acquire(app->shield_history_mutex, FuriWaitForever);
|
||||
bool added = protopirate_history_add_to_history(
|
||||
bool added = gdr_history_add_to_history(
|
||||
app->shield_history,
|
||||
decoder_base,
|
||||
&app->shield_rx_chain->preset,
|
||||
ProtoPirateHistorySourceExternal);
|
||||
GDRHistorySourceExternal);
|
||||
bool auto_save = app->auto_save;
|
||||
bool auto_saved = added && auto_save &&
|
||||
protopirate_scene_shield_receiver_auto_save_locked(app);
|
||||
gdr_scene_shield_receiver_auto_save_locked(app);
|
||||
if(added && auto_save && !auto_saved) {
|
||||
app->shield_auto_save_failed = true;
|
||||
}
|
||||
@@ -118,11 +118,11 @@ static void protopirate_scene_shield_receiver_decode_cb(
|
||||
notification_message(app->notifications, &sequence_error);
|
||||
}
|
||||
view_dispatcher_send_custom_event(
|
||||
app->view_dispatcher, ProtoPirateCustomEventShieldReceiverUpdate);
|
||||
app->view_dispatcher, GDRCustomEventShieldReceiverUpdate);
|
||||
}
|
||||
}
|
||||
|
||||
static void protopirate_scene_shield_receiver_update_statusbar(ProtoPirateApp* app) {
|
||||
static void gdr_scene_shield_receiver_update_statusbar(GDRApp* app) {
|
||||
furi_check(app);
|
||||
|
||||
char frequency_str[16] = {0};
|
||||
@@ -142,31 +142,31 @@ static void protopirate_scene_shield_receiver_update_statusbar(ProtoPirateApp* a
|
||||
"%s %luk/%+ldk",
|
||||
furi_string_get_cstr(app->shield_rx_chain->preset.name),
|
||||
(unsigned long)((app->shield_rx_chain->rx_bandwidth_hz + 500UL) / 1000UL),
|
||||
(long)(protopirate_scene_shield_receiver_tx_offset_hz(app) / 1000L));
|
||||
(long)(gdr_scene_shield_receiver_tx_offset_hz(app) / 1000L));
|
||||
}
|
||||
|
||||
if(app->shield_history) {
|
||||
furi_mutex_acquire(app->shield_history_mutex, FuriWaitForever);
|
||||
protopirate_history_format_status_text(
|
||||
gdr_history_format_status_text(
|
||||
app->shield_history, history_stat_str, sizeof(history_stat_str));
|
||||
furi_mutex_release(app->shield_history_mutex);
|
||||
} else {
|
||||
snprintf(history_stat_str, sizeof(history_stat_str), "0/%u", PROTOPIRATE_HISTORY_MAX);
|
||||
snprintf(history_stat_str, sizeof(history_stat_str), "0/%u", GDR_HISTORY_MAX);
|
||||
}
|
||||
|
||||
protopirate_view_receiver_add_data_statusbar(
|
||||
app->protopirate_receiver, frequency_str, modulation_str, history_stat_str, true);
|
||||
gdr_view_receiver_add_data_statusbar(
|
||||
app->gdr_receiver, frequency_str, modulation_str, history_stat_str, true);
|
||||
}
|
||||
|
||||
static void protopirate_scene_shield_receiver_teardown(ProtoPirateApp* app) {
|
||||
static void gdr_scene_shield_receiver_teardown(GDRApp* app) {
|
||||
furi_check(app);
|
||||
|
||||
if(app->shield_rx_chain) {
|
||||
protopirate_rx_chain_free(app->shield_rx_chain);
|
||||
gdr_rx_chain_free(app->shield_rx_chain);
|
||||
app->shield_rx_chain = NULL;
|
||||
}
|
||||
if(app->shield_tx_chain) {
|
||||
protopirate_tx_chain_free(app->shield_tx_chain);
|
||||
gdr_tx_chain_free(app->shield_tx_chain);
|
||||
app->shield_tx_chain = NULL;
|
||||
}
|
||||
|
||||
@@ -176,13 +176,13 @@ static void protopirate_scene_shield_receiver_teardown(ProtoPirateApp* app) {
|
||||
}
|
||||
}
|
||||
|
||||
static bool protopirate_scene_shield_receiver_build(ProtoPirateApp* app) {
|
||||
static bool gdr_scene_shield_receiver_build(GDRApp* app) {
|
||||
furi_check(app);
|
||||
|
||||
protopirate_radio_deinit(app);
|
||||
gdr_radio_deinit(app);
|
||||
|
||||
if(!app->shield_history) {
|
||||
app->shield_history = protopirate_history_alloc();
|
||||
app->shield_history = gdr_history_alloc();
|
||||
if(!app->shield_history) {
|
||||
FURI_LOG_E(TAG, "Failed to allocate shield history");
|
||||
return false;
|
||||
@@ -196,7 +196,7 @@ static bool protopirate_scene_shield_receiver_build(ProtoPirateApp* app) {
|
||||
}
|
||||
}
|
||||
furi_mutex_acquire(app->shield_history_mutex, FuriWaitForever);
|
||||
if(protopirate_history_get_item(app->shield_history) == 0) {
|
||||
if(gdr_history_get_item(app->shield_history) == 0) {
|
||||
app->shield_auto_save_failed = false;
|
||||
}
|
||||
furi_mutex_release(app->shield_history_mutex);
|
||||
@@ -204,226 +204,226 @@ static bool protopirate_scene_shield_receiver_build(ProtoPirateApp* app) {
|
||||
subghz_devices_init();
|
||||
s_shield_devices_inited = true;
|
||||
|
||||
app->shield_rx_chain = protopirate_rx_chain_alloc('E');
|
||||
app->shield_tx_chain = protopirate_tx_chain_alloc();
|
||||
app->shield_rx_chain = gdr_rx_chain_alloc('E');
|
||||
app->shield_tx_chain = gdr_tx_chain_alloc();
|
||||
if(!app->shield_rx_chain || !app->shield_tx_chain) {
|
||||
FURI_LOG_E(TAG, "Failed to allocate shield chains");
|
||||
protopirate_scene_shield_receiver_teardown(app);
|
||||
gdr_scene_shield_receiver_teardown(app);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!protopirate_rx_chain_acquire_device(
|
||||
if(!gdr_rx_chain_acquire_device(
|
||||
app->shield_rx_chain, SubGhzRadioDeviceTypeExternalCC1101)) {
|
||||
FURI_LOG_E(TAG, "External CC1101 unavailable - Shield RX requires it");
|
||||
protopirate_scene_shield_receiver_teardown(app);
|
||||
gdr_scene_shield_receiver_teardown(app);
|
||||
return false;
|
||||
}
|
||||
if(!protopirate_tx_chain_acquire_device(app->shield_tx_chain)) {
|
||||
if(!gdr_tx_chain_acquire_device(app->shield_tx_chain)) {
|
||||
FURI_LOG_E(TAG, "Internal CC1101 unavailable");
|
||||
protopirate_scene_shield_receiver_teardown(app);
|
||||
gdr_scene_shield_receiver_teardown(app);
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t preset_count = subghz_setting_get_preset_count(app->setting);
|
||||
if(app->shield_preset_index >= preset_count) {
|
||||
FURI_LOG_E(TAG, "Invalid shield preset index");
|
||||
protopirate_scene_shield_receiver_teardown(app);
|
||||
gdr_scene_shield_receiver_teardown(app);
|
||||
return false;
|
||||
}
|
||||
|
||||
const char* preset_name = subghz_setting_get_preset_name(app->setting, app->shield_preset_index);
|
||||
if(!protopirate_rx_chain_set_preset(
|
||||
if(!gdr_rx_chain_set_preset(
|
||||
app->shield_rx_chain, app->setting, preset_name, app->shield_freq) ||
|
||||
!protopirate_rx_chain_apply_shield_profile(app->shield_rx_chain)) {
|
||||
!gdr_rx_chain_apply_shield_profile(app->shield_rx_chain)) {
|
||||
FURI_LOG_E(TAG, "Failed to configure Shield RX profile");
|
||||
protopirate_scene_shield_receiver_teardown(app);
|
||||
gdr_scene_shield_receiver_teardown(app);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!protopirate_tx_chain_configure(
|
||||
if(!gdr_tx_chain_configure(
|
||||
app->shield_tx_chain,
|
||||
app->setting,
|
||||
app->shield_freq,
|
||||
protopirate_scene_shield_receiver_resolve_tx_offset(app),
|
||||
gdr_scene_shield_receiver_resolve_tx_offset(app),
|
||||
app->shield_tx_power)) {
|
||||
FURI_LOG_E(TAG, "Failed to configure Shield TX");
|
||||
protopirate_scene_shield_receiver_teardown(app);
|
||||
gdr_scene_shield_receiver_teardown(app);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!protopirate_rx_chain_init_receiver(app->shield_rx_chain)) {
|
||||
if(!gdr_rx_chain_init_receiver(app->shield_rx_chain)) {
|
||||
FURI_LOG_E(TAG, "Failed to init external RX chain");
|
||||
protopirate_scene_shield_receiver_teardown(app);
|
||||
gdr_scene_shield_receiver_teardown(app);
|
||||
return false;
|
||||
}
|
||||
|
||||
protopirate_rx_chain_set_decode_callback(
|
||||
app->shield_rx_chain, protopirate_scene_shield_receiver_decode_cb, app);
|
||||
gdr_rx_chain_set_decode_callback(
|
||||
app->shield_rx_chain, gdr_scene_shield_receiver_decode_cb, app);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void protopirate_scene_shield_receiver_on_enter(void* context) {
|
||||
void gdr_scene_shield_receiver_on_enter(void* context) {
|
||||
furi_check(context);
|
||||
ProtoPirateApp* app = context;
|
||||
GDRApp* app = context;
|
||||
|
||||
if(!protopirate_ensure_receiver_view(app)) {
|
||||
if(!gdr_ensure_receiver_view(app)) {
|
||||
notification_message(app->notifications, &sequence_error);
|
||||
scene_manager_search_and_switch_to_previous_scene(
|
||||
app->scene_manager, ProtoPirateSceneStart);
|
||||
app->scene_manager, GDRSceneStart);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!protopirate_scene_shield_receiver_build(app)) {
|
||||
if(!gdr_scene_shield_receiver_build(app)) {
|
||||
notification_message(app->notifications, &sequence_error);
|
||||
scene_manager_search_and_switch_to_previous_scene(
|
||||
app->scene_manager, ProtoPirateSceneStart);
|
||||
app->scene_manager, GDRSceneStart);
|
||||
return;
|
||||
}
|
||||
|
||||
protopirate_view_receiver_set_history_mutex(
|
||||
app->protopirate_receiver, app->shield_history_mutex);
|
||||
protopirate_view_receiver_sync_menu_from_history(
|
||||
app->protopirate_receiver, app->shield_history);
|
||||
protopirate_view_receiver_set_callback(
|
||||
app->protopirate_receiver, protopirate_scene_shield_receiver_view_callback, app);
|
||||
protopirate_view_receiver_set_lock(app->protopirate_receiver, app->lock);
|
||||
protopirate_view_receiver_set_autosave(app->protopirate_receiver, app->auto_save);
|
||||
protopirate_view_receiver_set_sub_decode_mode(app->protopirate_receiver, false);
|
||||
gdr_view_receiver_set_history_mutex(
|
||||
app->gdr_receiver, app->shield_history_mutex);
|
||||
gdr_view_receiver_sync_menu_from_history(
|
||||
app->gdr_receiver, app->shield_history);
|
||||
gdr_view_receiver_set_callback(
|
||||
app->gdr_receiver, gdr_scene_shield_receiver_view_callback, app);
|
||||
gdr_view_receiver_set_lock(app->gdr_receiver, app->lock);
|
||||
gdr_view_receiver_set_autosave(app->gdr_receiver, app->auto_save);
|
||||
gdr_view_receiver_set_sub_decode_mode(app->gdr_receiver, false);
|
||||
|
||||
if(app->selected_capture.owner == ProtoPirateCaptureOwnerShieldReceiver &&
|
||||
if(app->selected_capture.owner == GDRCaptureOwnerShieldReceiver &&
|
||||
app->selected_capture.history == app->shield_history &&
|
||||
protopirate_selected_capture_is_valid(app)) {
|
||||
protopirate_view_receiver_set_idx_menu(
|
||||
app->protopirate_receiver, app->selected_capture.index);
|
||||
gdr_selected_capture_is_valid(app)) {
|
||||
gdr_view_receiver_set_idx_menu(
|
||||
app->gdr_receiver, app->selected_capture.index);
|
||||
}
|
||||
|
||||
protopirate_scene_shield_receiver_update_statusbar(app);
|
||||
gdr_scene_shield_receiver_update_statusbar(app);
|
||||
scene_manager_set_scene_state(
|
||||
app->scene_manager, ProtoPirateSceneShieldReceiver, SHIELD_SCENE_STATE_NONE);
|
||||
app->scene_manager, GDRSceneShieldReceiver, SHIELD_SCENE_STATE_NONE);
|
||||
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, ProtoPirateViewReceiver);
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, GDRViewReceiver);
|
||||
view_dispatcher_send_custom_event(
|
||||
app->view_dispatcher, ProtoPirateCustomEventShieldReceiverDeferredStart);
|
||||
app->view_dispatcher, GDRCustomEventShieldReceiverDeferredStart);
|
||||
}
|
||||
|
||||
static void protopirate_scene_shield_receiver_handle_back(ProtoPirateApp* app) {
|
||||
static void gdr_scene_shield_receiver_handle_back(GDRApp* app) {
|
||||
bool has_history = false;
|
||||
bool auto_save_failed = false;
|
||||
if(app->shield_history && app->shield_history_mutex) {
|
||||
furi_mutex_acquire(app->shield_history_mutex, FuriWaitForever);
|
||||
has_history = protopirate_history_get_item(app->shield_history) > 0;
|
||||
has_history = gdr_history_get_item(app->shield_history) > 0;
|
||||
auto_save_failed = app->shield_auto_save_failed;
|
||||
furi_mutex_release(app->shield_history_mutex);
|
||||
}
|
||||
|
||||
if(has_history && (!app->auto_save || auto_save_failed)) {
|
||||
app->unsaved_history_owner = ProtoPirateCaptureOwnerShieldReceiver;
|
||||
app->unsaved_history_owner = GDRCaptureOwnerShieldReceiver;
|
||||
scene_manager_set_scene_state(
|
||||
app->scene_manager, ProtoPirateSceneShieldReceiver, SHIELD_SCENE_STATE_TO_SUBSCENE);
|
||||
scene_manager_next_scene(app->scene_manager, ProtoPirateSceneNeedSaving);
|
||||
app->scene_manager, GDRSceneShieldReceiver, SHIELD_SCENE_STATE_TO_SUBSCENE);
|
||||
scene_manager_next_scene(app->scene_manager, GDRSceneNeedSaving);
|
||||
} else {
|
||||
app->unsaved_history_owner = ProtoPirateCaptureOwnerNone;
|
||||
app->unsaved_history_owner = GDRCaptureOwnerNone;
|
||||
scene_manager_search_and_switch_to_previous_scene(
|
||||
app->scene_manager, ProtoPirateSceneStart);
|
||||
app->scene_manager, GDRSceneStart);
|
||||
}
|
||||
}
|
||||
|
||||
bool protopirate_scene_shield_receiver_on_event(void* context, SceneManagerEvent event) {
|
||||
bool gdr_scene_shield_receiver_on_event(void* context, SceneManagerEvent event) {
|
||||
furi_check(context);
|
||||
ProtoPirateApp* app = context;
|
||||
GDRApp* app = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
switch(event.event) {
|
||||
case ProtoPirateCustomEventShieldReceiverDeferredStart:
|
||||
if(!protopirate_rx_chain_start(app->shield_rx_chain) ||
|
||||
!protopirate_tx_chain_start_carrier(app->shield_tx_chain)) {
|
||||
case GDRCustomEventShieldReceiverDeferredStart:
|
||||
if(!gdr_rx_chain_start(app->shield_rx_chain) ||
|
||||
!gdr_tx_chain_start_carrier(app->shield_tx_chain)) {
|
||||
FURI_LOG_E(TAG, "Failed to start shield TX/RX");
|
||||
protopirate_scene_shield_receiver_teardown(app);
|
||||
gdr_scene_shield_receiver_teardown(app);
|
||||
notification_message(app->notifications, &sequence_error);
|
||||
scene_manager_search_and_switch_to_previous_scene(
|
||||
app->scene_manager, ProtoPirateSceneStart);
|
||||
app->scene_manager, GDRSceneStart);
|
||||
} else {
|
||||
notification_message(app->notifications, &sequence_tx);
|
||||
protopirate_scene_shield_receiver_update_statusbar(app);
|
||||
gdr_scene_shield_receiver_update_statusbar(app);
|
||||
}
|
||||
consumed = true;
|
||||
break;
|
||||
|
||||
case ProtoPirateCustomEventShieldReceiverUpdate:
|
||||
protopirate_view_receiver_sync_menu_from_history(
|
||||
app->protopirate_receiver, app->shield_history);
|
||||
protopirate_scene_shield_receiver_update_statusbar(app);
|
||||
case GDRCustomEventShieldReceiverUpdate:
|
||||
gdr_view_receiver_sync_menu_from_history(
|
||||
app->gdr_receiver, app->shield_history);
|
||||
gdr_scene_shield_receiver_update_statusbar(app);
|
||||
consumed = true;
|
||||
break;
|
||||
|
||||
case ProtoPirateCustomEventViewReceiverOK: {
|
||||
uint16_t idx = protopirate_view_receiver_get_idx_menu(app->protopirate_receiver);
|
||||
case GDRCustomEventViewReceiverOK: {
|
||||
uint16_t idx = gdr_view_receiver_get_idx_menu(app->gdr_receiver);
|
||||
furi_mutex_acquire(app->shield_history_mutex, FuriWaitForever);
|
||||
bool valid = idx < protopirate_history_get_item(app->shield_history);
|
||||
bool valid = idx < gdr_history_get_item(app->shield_history);
|
||||
furi_mutex_release(app->shield_history_mutex);
|
||||
if(valid) {
|
||||
protopirate_selected_capture_set(
|
||||
gdr_selected_capture_set(
|
||||
app,
|
||||
app->shield_history,
|
||||
app->shield_history_mutex,
|
||||
idx,
|
||||
ProtoPirateCaptureOwnerShieldReceiver);
|
||||
GDRCaptureOwnerShieldReceiver);
|
||||
scene_manager_set_scene_state(
|
||||
app->scene_manager,
|
||||
ProtoPirateSceneShieldReceiver,
|
||||
GDRSceneShieldReceiver,
|
||||
SHIELD_SCENE_STATE_TO_SUBSCENE);
|
||||
scene_manager_next_scene(app->scene_manager, ProtoPirateSceneReceiverInfo);
|
||||
scene_manager_next_scene(app->scene_manager, GDRSceneReceiverInfo);
|
||||
}
|
||||
consumed = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case ProtoPirateCustomEventViewReceiverDeleteItem: {
|
||||
uint16_t idx = protopirate_view_receiver_get_idx_menu(app->protopirate_receiver);
|
||||
case GDRCustomEventViewReceiverDeleteItem: {
|
||||
uint16_t idx = gdr_view_receiver_get_idx_menu(app->gdr_receiver);
|
||||
furi_mutex_acquire(app->shield_history_mutex, FuriWaitForever);
|
||||
bool valid = idx < protopirate_history_get_item(app->shield_history);
|
||||
bool valid = idx < gdr_history_get_item(app->shield_history);
|
||||
if(valid) {
|
||||
protopirate_history_delete_item(app->shield_history, idx);
|
||||
gdr_history_delete_item(app->shield_history, idx);
|
||||
}
|
||||
uint16_t count_after = protopirate_history_get_item(app->shield_history);
|
||||
uint16_t count_after = gdr_history_get_item(app->shield_history);
|
||||
if(count_after == 0) {
|
||||
app->shield_auto_save_failed = false;
|
||||
}
|
||||
furi_mutex_release(app->shield_history_mutex);
|
||||
|
||||
if(valid) {
|
||||
protopirate_view_receiver_delete_item(app->protopirate_receiver, idx);
|
||||
gdr_view_receiver_delete_item(app->gdr_receiver, idx);
|
||||
|
||||
if(count_after == 0) {
|
||||
protopirate_view_receiver_sync_menu_from_history(
|
||||
app->protopirate_receiver, app->shield_history);
|
||||
protopirate_view_receiver_set_idx_menu(app->protopirate_receiver, 0);
|
||||
gdr_view_receiver_sync_menu_from_history(
|
||||
app->gdr_receiver, app->shield_history);
|
||||
gdr_view_receiver_set_idx_menu(app->gdr_receiver, 0);
|
||||
}
|
||||
protopirate_scene_shield_receiver_update_statusbar(app);
|
||||
gdr_scene_shield_receiver_update_statusbar(app);
|
||||
}
|
||||
consumed = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case ProtoPirateCustomEventViewReceiverConfig:
|
||||
case GDRCustomEventViewReceiverConfig:
|
||||
scene_manager_set_scene_state(
|
||||
app->scene_manager,
|
||||
ProtoPirateSceneShieldReceiver,
|
||||
GDRSceneShieldReceiver,
|
||||
SHIELD_SCENE_STATE_TO_SUBSCENE);
|
||||
scene_manager_next_scene(app->scene_manager, ProtoPirateSceneShieldReceiverConfig);
|
||||
scene_manager_next_scene(app->scene_manager, GDRSceneShieldReceiverConfig);
|
||||
consumed = true;
|
||||
break;
|
||||
|
||||
case ProtoPirateCustomEventViewReceiverBack:
|
||||
protopirate_scene_shield_receiver_handle_back(app);
|
||||
case GDRCustomEventViewReceiverBack:
|
||||
gdr_scene_shield_receiver_handle_back(app);
|
||||
consumed = true;
|
||||
break;
|
||||
|
||||
case ProtoPirateCustomEventViewReceiverUnlock:
|
||||
app->lock = ProtoPirateLockOff;
|
||||
protopirate_view_receiver_set_lock(app->protopirate_receiver, app->lock);
|
||||
case GDRCustomEventViewReceiverUnlock:
|
||||
app->lock = GDRLockOff;
|
||||
gdr_view_receiver_set_lock(app->gdr_receiver, app->lock);
|
||||
consumed = true;
|
||||
break;
|
||||
|
||||
@@ -432,8 +432,8 @@ bool protopirate_scene_shield_receiver_on_event(void* context, SceneManagerEvent
|
||||
}
|
||||
} else if(event.type == SceneManagerEventTypeTick) {
|
||||
if(app->shield_rx_chain) {
|
||||
protopirate_view_receiver_set_rssi(
|
||||
app->protopirate_receiver, protopirate_rx_chain_get_rssi(app->shield_rx_chain));
|
||||
gdr_view_receiver_set_rssi(
|
||||
app->gdr_receiver, gdr_rx_chain_get_rssi(app->shield_rx_chain));
|
||||
notification_message(app->notifications, &sequence_blink_cyan_10);
|
||||
}
|
||||
consumed = true;
|
||||
@@ -442,29 +442,29 @@ bool protopirate_scene_shield_receiver_on_event(void* context, SceneManagerEvent
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void protopirate_scene_shield_receiver_on_exit(void* context) {
|
||||
void gdr_scene_shield_receiver_on_exit(void* context) {
|
||||
furi_check(context);
|
||||
ProtoPirateApp* app = context;
|
||||
GDRApp* app = context;
|
||||
|
||||
const bool leaving_for_subscene =
|
||||
(scene_manager_get_scene_state(app->scene_manager, ProtoPirateSceneShieldReceiver) ==
|
||||
(scene_manager_get_scene_state(app->scene_manager, GDRSceneShieldReceiver) ==
|
||||
SHIELD_SCENE_STATE_TO_SUBSCENE);
|
||||
|
||||
protopirate_scene_shield_receiver_teardown(app);
|
||||
gdr_scene_shield_receiver_teardown(app);
|
||||
|
||||
if(leaving_for_subscene) {
|
||||
return;
|
||||
}
|
||||
|
||||
protopirate_view_receiver_reset_menu(app->protopirate_receiver);
|
||||
if(app->selected_capture.owner == ProtoPirateCaptureOwnerShieldReceiver) {
|
||||
protopirate_selected_capture_clear(app);
|
||||
gdr_view_receiver_reset_menu(app->gdr_receiver);
|
||||
if(app->selected_capture.owner == GDRCaptureOwnerShieldReceiver) {
|
||||
gdr_selected_capture_clear(app);
|
||||
}
|
||||
}
|
||||
|
||||
void protopirate_scene_shield_receiver_view_callback(ProtoPirateCustomEvent event, void* context) {
|
||||
void gdr_scene_shield_receiver_view_callback(GDRCustomEvent event, void* context) {
|
||||
furi_check(context);
|
||||
ProtoPirateApp* app = context;
|
||||
GDRApp* app = context;
|
||||
view_dispatcher_send_custom_event(app->view_dispatcher, event);
|
||||
}
|
||||
|
||||
+32
-32
@@ -1,9 +1,9 @@
|
||||
// scenes/protopirate_scene_shield_receiver_config.c
|
||||
#include "../protopirate_app_i.h"
|
||||
// scenes/gdr_scene_shield_receiver_config.c
|
||||
#include "../gdr_app_i.h"
|
||||
|
||||
#ifdef ENABLE_SHIELD_RX_SCENE
|
||||
|
||||
#define TAG "ProtoPirateSceneShieldCfg"
|
||||
#define TAG "GDRSceneShieldCfg"
|
||||
|
||||
#define SHIELD_TX_OFFSET_COUNT 12U
|
||||
static const char* const shield_tx_offset_text[SHIELD_TX_OFFSET_COUNT] = {
|
||||
@@ -22,13 +22,13 @@ static const char* const shield_tx_offset_text[SHIELD_TX_OFFSET_COUNT] = {
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
ProtoPirateShieldConfigFrequency,
|
||||
ProtoPirateShieldConfigPreset,
|
||||
ProtoPirateShieldConfigTxOffset,
|
||||
ProtoPirateShieldConfigTxPower,
|
||||
} ProtoPirateShieldConfigItem;
|
||||
GDRShieldConfigFrequency,
|
||||
GDRShieldConfigPreset,
|
||||
GDRShieldConfigTxOffset,
|
||||
GDRShieldConfigTxPower,
|
||||
} GDRShieldConfigItem;
|
||||
|
||||
static uint8_t protopirate_shield_config_freq_index(ProtoPirateApp* app, uint32_t frequency) {
|
||||
static uint8_t gdr_shield_config_freq_index(GDRApp* app, uint32_t frequency) {
|
||||
uint8_t count = (uint8_t)subghz_setting_get_frequency_count(app->setting);
|
||||
for(uint8_t i = 0; i < count; i++) {
|
||||
if(subghz_setting_get_frequency(app->setting, i) == frequency) {
|
||||
@@ -38,7 +38,7 @@ static uint8_t protopirate_shield_config_freq_index(ProtoPirateApp* app, uint32_
|
||||
return subghz_setting_get_frequency_default_index(app->setting);
|
||||
}
|
||||
|
||||
static void protopirate_shield_config_set_freq_text(VariableItem* item, uint32_t frequency) {
|
||||
static void gdr_shield_config_set_freq_text(VariableItem* item, uint32_t frequency) {
|
||||
char text_buf[10] = {0};
|
||||
snprintf(
|
||||
text_buf,
|
||||
@@ -49,23 +49,23 @@ static void protopirate_shield_config_set_freq_text(VariableItem* item, uint32_t
|
||||
variable_item_set_current_value_text(item, text_buf);
|
||||
}
|
||||
|
||||
static void protopirate_shield_config_set_frequency(VariableItem* item) {
|
||||
ProtoPirateApp* app = variable_item_get_context(item);
|
||||
static void gdr_shield_config_set_frequency(VariableItem* item) {
|
||||
GDRApp* app = variable_item_get_context(item);
|
||||
uint8_t index = variable_item_get_current_value_index(item);
|
||||
app->shield_freq = subghz_setting_get_frequency(app->setting, index);
|
||||
protopirate_shield_config_set_freq_text(item, app->shield_freq);
|
||||
gdr_shield_config_set_freq_text(item, app->shield_freq);
|
||||
}
|
||||
|
||||
static void protopirate_shield_config_set_preset(VariableItem* item) {
|
||||
ProtoPirateApp* app = variable_item_get_context(item);
|
||||
static void gdr_shield_config_set_preset(VariableItem* item) {
|
||||
GDRApp* app = variable_item_get_context(item);
|
||||
uint8_t index = variable_item_get_current_value_index(item);
|
||||
app->shield_preset_index = index;
|
||||
variable_item_set_current_value_text(
|
||||
item, subghz_setting_get_preset_name(app->setting, index));
|
||||
}
|
||||
|
||||
static void protopirate_shield_config_set_tx_offset(VariableItem* item) {
|
||||
ProtoPirateApp* app = variable_item_get_context(item);
|
||||
static void gdr_shield_config_set_tx_offset(VariableItem* item) {
|
||||
GDRApp* app = variable_item_get_context(item);
|
||||
uint8_t index = variable_item_get_current_value_index(item);
|
||||
if(index >= SHIELD_TX_OFFSET_COUNT) {
|
||||
index = 3;
|
||||
@@ -87,19 +87,19 @@ static const char* const shield_tx_power_text[SHIELD_TX_POWER_COUNT] = {
|
||||
"-30dBm",
|
||||
};
|
||||
|
||||
static void protopirate_shield_config_set_tx_power(VariableItem* item) {
|
||||
ProtoPirateApp* app = variable_item_get_context(item);
|
||||
static void gdr_shield_config_set_tx_power(VariableItem* item) {
|
||||
GDRApp* app = variable_item_get_context(item);
|
||||
uint8_t index = variable_item_get_current_value_index(item);
|
||||
app->shield_tx_power = index;
|
||||
variable_item_set_current_value_text(item, shield_tx_power_text[index]);
|
||||
}
|
||||
|
||||
void protopirate_scene_shield_receiver_config_on_enter(void* context) {
|
||||
void gdr_scene_shield_receiver_config_on_enter(void* context) {
|
||||
furi_check(context);
|
||||
ProtoPirateApp* app = context;
|
||||
GDRApp* app = context;
|
||||
VariableItem* item;
|
||||
|
||||
if(!protopirate_ensure_variable_item_list(app)) {
|
||||
if(!gdr_ensure_variable_item_list(app)) {
|
||||
notification_message(app->notifications, &sequence_error);
|
||||
scene_manager_previous_scene(app->scene_manager);
|
||||
return;
|
||||
@@ -111,17 +111,17 @@ void protopirate_scene_shield_receiver_config_on_enter(void* context) {
|
||||
app->variable_item_list,
|
||||
"RX Frequency",
|
||||
subghz_setting_get_frequency_count(app->setting),
|
||||
protopirate_shield_config_set_frequency,
|
||||
gdr_shield_config_set_frequency,
|
||||
app);
|
||||
variable_item_set_current_value_index(
|
||||
item, protopirate_shield_config_freq_index(app, app->shield_freq));
|
||||
protopirate_shield_config_set_freq_text(item, app->shield_freq);
|
||||
item, gdr_shield_config_freq_index(app, app->shield_freq));
|
||||
gdr_shield_config_set_freq_text(item, app->shield_freq);
|
||||
|
||||
item = variable_item_list_add(
|
||||
app->variable_item_list,
|
||||
"RX Modulation",
|
||||
subghz_setting_get_preset_count(app->setting),
|
||||
protopirate_shield_config_set_preset,
|
||||
gdr_shield_config_set_preset,
|
||||
app);
|
||||
if(app->shield_preset_index >= subghz_setting_get_preset_count(app->setting)) {
|
||||
app->shield_preset_index = 0;
|
||||
@@ -134,7 +134,7 @@ void protopirate_scene_shield_receiver_config_on_enter(void* context) {
|
||||
app->variable_item_list,
|
||||
"Jam TX Offset",
|
||||
SHIELD_TX_OFFSET_COUNT,
|
||||
protopirate_shield_config_set_tx_offset,
|
||||
gdr_shield_config_set_tx_offset,
|
||||
app);
|
||||
if(app->shield_tx_offset_index >= SHIELD_TX_OFFSET_COUNT) {
|
||||
app->shield_tx_offset_index = 3;
|
||||
@@ -146,7 +146,7 @@ void protopirate_scene_shield_receiver_config_on_enter(void* context) {
|
||||
app->variable_item_list,
|
||||
"Shield TX Power",
|
||||
SHIELD_TX_POWER_COUNT,
|
||||
protopirate_shield_config_set_tx_power,
|
||||
gdr_shield_config_set_tx_power,
|
||||
app);
|
||||
if(app->shield_tx_power >= SHIELD_TX_POWER_COUNT) {
|
||||
app->shield_tx_power = 0U;
|
||||
@@ -154,18 +154,18 @@ void protopirate_scene_shield_receiver_config_on_enter(void* context) {
|
||||
variable_item_set_current_value_index(item, app->shield_tx_power);
|
||||
variable_item_set_current_value_text(item, shield_tx_power_text[app->shield_tx_power]);
|
||||
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, ProtoPirateViewVariableItemList);
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, GDRViewVariableItemList);
|
||||
}
|
||||
|
||||
bool protopirate_scene_shield_receiver_config_on_event(void* context, SceneManagerEvent event) {
|
||||
bool gdr_scene_shield_receiver_config_on_event(void* context, SceneManagerEvent event) {
|
||||
UNUSED(context);
|
||||
UNUSED(event);
|
||||
return false;
|
||||
}
|
||||
|
||||
void protopirate_scene_shield_receiver_config_on_exit(void* context) {
|
||||
void gdr_scene_shield_receiver_config_on_exit(void* context) {
|
||||
furi_check(context);
|
||||
ProtoPirateApp* app = context;
|
||||
GDRApp* app = context;
|
||||
variable_item_list_reset(app->variable_item_list);
|
||||
}
|
||||
|
||||
+66
-66
@@ -1,48 +1,48 @@
|
||||
// scenes/protopirate_scene_start.c
|
||||
#include "../protopirate_app_i.h"
|
||||
#include "../helpers/protopirate_storage.h"
|
||||
// scenes/gdr_scene_start.c
|
||||
#include "../gdr_app_i.h"
|
||||
#include "../helpers/gdr_storage.h"
|
||||
|
||||
#include "proto_pirate_icons.h"
|
||||
#include "gdr_icons.h"
|
||||
|
||||
#define TAG "ProtoPirateSceneStart"
|
||||
#define TAG "GDRSceneStart"
|
||||
|
||||
typedef enum {
|
||||
SubmenuIndexProtoPirateReceiver,
|
||||
SubmenuIndexGDRReceiver,
|
||||
#ifdef ENABLE_DUAL_RX_SCENE
|
||||
SubmenuIndexProtoPirateDualReceiver,
|
||||
SubmenuIndexGDRDualReceiver,
|
||||
#endif
|
||||
#ifdef ENABLE_SHIELD_RX_SCENE
|
||||
SubmenuIndexProtoPirateShieldReceiver,
|
||||
SubmenuIndexGDRShieldReceiver,
|
||||
#endif
|
||||
SubmenuIndexProtoPirateSaved,
|
||||
SubmenuIndexProtoPirateReceiverConfig,
|
||||
SubmenuIndexGDRSaved,
|
||||
SubmenuIndexGDRReceiverConfig,
|
||||
#ifdef ENABLE_SUB_DECODE_SCENE
|
||||
SubmenuIndexProtoPirateSubDecode,
|
||||
SubmenuIndexGDRSubDecode,
|
||||
#endif
|
||||
#ifdef ENABLE_TIMING_TUNER_SCENE
|
||||
SubmenuIndexProtoPirateTimingTuner,
|
||||
SubmenuIndexGDRTimingTuner,
|
||||
#endif
|
||||
SubmenuIndexProtoPirateAbout,
|
||||
SubmenuIndexGDRAbout,
|
||||
} SubmenuIndex;
|
||||
|
||||
// Forward declaration
|
||||
static void protopirate_scene_start_open_saved_captures(ProtoPirateApp* app);
|
||||
static void gdr_scene_start_open_saved_captures(GDRApp* app);
|
||||
|
||||
static void protopirate_scene_start_submenu_callback(void* context, uint32_t index) {
|
||||
static void gdr_scene_start_submenu_callback(void* context, uint32_t index) {
|
||||
furi_check(context);
|
||||
ProtoPirateApp* app = context;
|
||||
GDRApp* app = context;
|
||||
|
||||
// Handle "Saved Captures" directly here, not via custom event
|
||||
if(index == SubmenuIndexProtoPirateSaved) {
|
||||
protopirate_scene_start_open_saved_captures(app);
|
||||
if(index == SubmenuIndexGDRSaved) {
|
||||
gdr_scene_start_open_saved_captures(app);
|
||||
} else {
|
||||
view_dispatcher_send_custom_event(app->view_dispatcher, index);
|
||||
}
|
||||
}
|
||||
|
||||
static void protopirate_scene_start_open_saved_captures(ProtoPirateApp* app) {
|
||||
static void gdr_scene_start_open_saved_captures(GDRApp* app) {
|
||||
FURI_LOG_I(TAG, "[1] Opening saved captures browser");
|
||||
FURI_LOG_I(TAG, "[1a] PROTOPIRATE_APP_FOLDER = %s", PROTOPIRATE_APP_FOLDER);
|
||||
FURI_LOG_I(TAG, "[1a] GDR_APP_FOLDER = %s", GDR_APP_FOLDER);
|
||||
|
||||
// Check and create folder
|
||||
FURI_LOG_D(TAG, "[2] Opening storage");
|
||||
@@ -55,13 +55,13 @@ static void protopirate_scene_start_open_saved_captures(ProtoPirateApp* app) {
|
||||
|
||||
FURI_LOG_D(TAG, "[3] Checking folder exists");
|
||||
|
||||
if(!storage_dir_exists(storage, PROTOPIRATE_APP_FOLDER)) {
|
||||
if(!storage_dir_exists(storage, GDR_APP_FOLDER)) {
|
||||
FURI_LOG_I(TAG, "[4] Creating folder");
|
||||
storage_simply_mkdir(storage, PROTOPIRATE_APP_FOLDER);
|
||||
storage_simply_mkdir(storage, GDR_APP_FOLDER);
|
||||
}
|
||||
|
||||
#ifndef REMOVE_LOGS
|
||||
bool folder_ok = storage_dir_exists(storage, PROTOPIRATE_APP_FOLDER);
|
||||
bool folder_ok = storage_dir_exists(storage, GDR_APP_FOLDER);
|
||||
FURI_LOG_D(TAG, "[5] Folder exists: %s", folder_ok ? "yes" : "no");
|
||||
#endif
|
||||
|
||||
@@ -77,7 +77,7 @@ static void protopirate_scene_start_open_saved_captures(ProtoPirateApp* app) {
|
||||
|
||||
// Set starting path
|
||||
FURI_LOG_D(TAG, "[8] Setting file_path");
|
||||
furi_string_set(app->file_path, PROTOPIRATE_APP_FOLDER);
|
||||
furi_string_set(app->file_path, GDR_APP_FOLDER);
|
||||
FURI_LOG_D(TAG, "[9] file_path set to: %s", furi_string_get_cstr(app->file_path));
|
||||
|
||||
// Configure file browser
|
||||
@@ -88,7 +88,7 @@ static void protopirate_scene_start_open_saved_captures(ProtoPirateApp* app) {
|
||||
dialog_file_browser_set_basic_options(&browser_options, ".psf", &I_subghz_10px);
|
||||
|
||||
FURI_LOG_D(TAG, "[12] Setting browser_options fields");
|
||||
browser_options.base_path = PROTOPIRATE_APP_FOLDER;
|
||||
browser_options.base_path = GDR_APP_FOLDER;
|
||||
browser_options.skip_assets = true;
|
||||
browser_options.hide_dot_files = true;
|
||||
|
||||
@@ -126,7 +126,7 @@ static void protopirate_scene_start_open_saved_captures(ProtoPirateApp* app) {
|
||||
app->loaded_file_path = furi_string_alloc_set(app->file_path);
|
||||
|
||||
FURI_LOG_D(TAG, "[19] Navigating to SavedInfo scene");
|
||||
scene_manager_next_scene(app->scene_manager, ProtoPirateSceneSavedInfo);
|
||||
scene_manager_next_scene(app->scene_manager, GDRSceneSavedInfo);
|
||||
} else {
|
||||
FURI_LOG_I(TAG, "[16] File browser cancelled or empty");
|
||||
}
|
||||
@@ -134,25 +134,25 @@ static void protopirate_scene_start_open_saved_captures(ProtoPirateApp* app) {
|
||||
FURI_LOG_I(TAG, "[20] open_saved_captures complete");
|
||||
}
|
||||
|
||||
void protopirate_scene_start_on_enter(void* context) {
|
||||
void gdr_scene_start_on_enter(void* context) {
|
||||
furi_check(context);
|
||||
ProtoPirateApp* app = context;
|
||||
GDRApp* app = context;
|
||||
|
||||
protopirate_release_shared_radio_state(app);
|
||||
gdr_release_shared_radio_state(app);
|
||||
|
||||
submenu_add_item(
|
||||
app->submenu,
|
||||
"Receive",
|
||||
SubmenuIndexProtoPirateReceiver,
|
||||
protopirate_scene_start_submenu_callback,
|
||||
SubmenuIndexGDRReceiver,
|
||||
gdr_scene_start_submenu_callback,
|
||||
app);
|
||||
|
||||
#ifdef ENABLE_DUAL_RX_SCENE
|
||||
submenu_add_item(
|
||||
app->submenu,
|
||||
"Dual RX",
|
||||
SubmenuIndexProtoPirateDualReceiver,
|
||||
protopirate_scene_start_submenu_callback,
|
||||
SubmenuIndexGDRDualReceiver,
|
||||
gdr_scene_start_submenu_callback,
|
||||
app);
|
||||
#endif
|
||||
|
||||
@@ -160,103 +160,103 @@ void protopirate_scene_start_on_enter(void* context) {
|
||||
submenu_add_item(
|
||||
app->submenu,
|
||||
"RollJam!",
|
||||
SubmenuIndexProtoPirateShieldReceiver,
|
||||
protopirate_scene_start_submenu_callback,
|
||||
SubmenuIndexGDRShieldReceiver,
|
||||
gdr_scene_start_submenu_callback,
|
||||
app);
|
||||
#endif
|
||||
|
||||
submenu_add_item(
|
||||
app->submenu,
|
||||
"Saved Captures",
|
||||
SubmenuIndexProtoPirateSaved,
|
||||
protopirate_scene_start_submenu_callback,
|
||||
SubmenuIndexGDRSaved,
|
||||
gdr_scene_start_submenu_callback,
|
||||
app);
|
||||
|
||||
submenu_add_item(
|
||||
app->submenu,
|
||||
"Configuration",
|
||||
SubmenuIndexProtoPirateReceiverConfig,
|
||||
protopirate_scene_start_submenu_callback,
|
||||
SubmenuIndexGDRReceiverConfig,
|
||||
gdr_scene_start_submenu_callback,
|
||||
app);
|
||||
#ifdef ENABLE_SUB_DECODE_SCENE
|
||||
submenu_add_item(
|
||||
app->submenu,
|
||||
"Sub Decode",
|
||||
SubmenuIndexProtoPirateSubDecode,
|
||||
protopirate_scene_start_submenu_callback,
|
||||
SubmenuIndexGDRSubDecode,
|
||||
gdr_scene_start_submenu_callback,
|
||||
app);
|
||||
#endif
|
||||
#ifdef ENABLE_TIMING_TUNER_SCENE
|
||||
submenu_add_item(
|
||||
app->submenu,
|
||||
"Timing Tuner",
|
||||
SubmenuIndexProtoPirateTimingTuner,
|
||||
protopirate_scene_start_submenu_callback,
|
||||
SubmenuIndexGDRTimingTuner,
|
||||
gdr_scene_start_submenu_callback,
|
||||
app);
|
||||
#endif
|
||||
|
||||
submenu_add_item(
|
||||
app->submenu,
|
||||
"About",
|
||||
SubmenuIndexProtoPirateAbout,
|
||||
protopirate_scene_start_submenu_callback,
|
||||
SubmenuIndexGDRAbout,
|
||||
gdr_scene_start_submenu_callback,
|
||||
app);
|
||||
|
||||
submenu_set_selected_item(
|
||||
app->submenu, scene_manager_get_scene_state(app->scene_manager, ProtoPirateSceneStart));
|
||||
app->submenu, scene_manager_get_scene_state(app->scene_manager, GDRSceneStart));
|
||||
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, ProtoPirateViewSubmenu);
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, GDRViewSubmenu);
|
||||
}
|
||||
|
||||
bool protopirate_scene_start_on_event(void* context, SceneManagerEvent event) {
|
||||
bool gdr_scene_start_on_event(void* context, SceneManagerEvent event) {
|
||||
furi_check(context);
|
||||
ProtoPirateApp* app = context;
|
||||
GDRApp* app = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == SubmenuIndexProtoPirateAbout) {
|
||||
scene_manager_next_scene(app->scene_manager, ProtoPirateSceneAbout);
|
||||
if(event.event == SubmenuIndexGDRAbout) {
|
||||
scene_manager_next_scene(app->scene_manager, GDRSceneAbout);
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexProtoPirateReceiver) {
|
||||
scene_manager_next_scene(app->scene_manager, ProtoPirateSceneReceiver);
|
||||
} else if(event.event == SubmenuIndexGDRReceiver) {
|
||||
scene_manager_next_scene(app->scene_manager, GDRSceneReceiver);
|
||||
consumed = true;
|
||||
}
|
||||
#ifdef ENABLE_DUAL_RX_SCENE
|
||||
else if(event.event == SubmenuIndexProtoPirateDualReceiver) {
|
||||
scene_manager_next_scene(app->scene_manager, ProtoPirateSceneDualReceiver);
|
||||
else if(event.event == SubmenuIndexGDRDualReceiver) {
|
||||
scene_manager_next_scene(app->scene_manager, GDRSceneDualReceiver);
|
||||
consumed = true;
|
||||
}
|
||||
#endif
|
||||
#ifdef ENABLE_SHIELD_RX_SCENE
|
||||
else if(event.event == SubmenuIndexProtoPirateShieldReceiver) {
|
||||
scene_manager_next_scene(app->scene_manager, ProtoPirateSceneShieldReceiver);
|
||||
else if(event.event == SubmenuIndexGDRShieldReceiver) {
|
||||
scene_manager_next_scene(app->scene_manager, GDRSceneShieldReceiver);
|
||||
consumed = true;
|
||||
}
|
||||
#endif
|
||||
else if(event.event == SubmenuIndexProtoPirateReceiverConfig) {
|
||||
scene_manager_next_scene(app->scene_manager, ProtoPirateSceneReceiverConfig);
|
||||
else if(event.event == SubmenuIndexGDRReceiverConfig) {
|
||||
scene_manager_next_scene(app->scene_manager, GDRSceneReceiverConfig);
|
||||
consumed = true;
|
||||
}
|
||||
#ifdef ENABLE_SUB_DECODE_SCENE
|
||||
else if(event.event == SubmenuIndexProtoPirateSubDecode) {
|
||||
scene_manager_next_scene(app->scene_manager, ProtoPirateSceneSubDecode);
|
||||
else if(event.event == SubmenuIndexGDRSubDecode) {
|
||||
scene_manager_next_scene(app->scene_manager, GDRSceneSubDecode);
|
||||
consumed = true;
|
||||
}
|
||||
#endif
|
||||
#ifdef ENABLE_TIMING_TUNER_SCENE
|
||||
else if(event.event == SubmenuIndexProtoPirateTimingTuner) {
|
||||
scene_manager_next_scene(app->scene_manager, ProtoPirateSceneTimingTuner);
|
||||
else if(event.event == SubmenuIndexGDRTimingTuner) {
|
||||
scene_manager_next_scene(app->scene_manager, GDRSceneTimingTuner);
|
||||
consumed = true;
|
||||
}
|
||||
#endif
|
||||
scene_manager_set_scene_state(app->scene_manager, ProtoPirateSceneStart, event.event);
|
||||
scene_manager_set_scene_state(app->scene_manager, GDRSceneStart, event.event);
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void protopirate_scene_start_on_exit(void* context) {
|
||||
void gdr_scene_start_on_exit(void* context) {
|
||||
furi_check(context);
|
||||
ProtoPirateApp* app = context;
|
||||
GDRApp* app = context;
|
||||
submenu_reset(app->submenu);
|
||||
}
|
||||
+120
-120
@@ -1,11 +1,11 @@
|
||||
// scenes/protopirate_scene_sub_decode.c
|
||||
#include "../protopirate_app_i.h"
|
||||
// scenes/gdr_scene_sub_decode.c
|
||||
#include "../gdr_app_i.h"
|
||||
#ifdef ENABLE_SUB_DECODE_SCENE
|
||||
#include "../helpers/protopirate_storage.h"
|
||||
#include "../helpers/gdr_storage.h"
|
||||
#include "../helpers/radio_device_loader.h"
|
||||
#include "../helpers/raw_file_reader.h"
|
||||
#include "../protopirate_history.h"
|
||||
#include "../helpers/protopirate_psa_bf_host.h"
|
||||
#include "../gdr_history.h"
|
||||
#include "../helpers/gdr_psa_bf_host.h"
|
||||
#include "core/core_defines.h"
|
||||
#include "core/record.h"
|
||||
#include "storage/storage.h"
|
||||
@@ -13,9 +13,9 @@
|
||||
#include <math.h>
|
||||
#include <lib/subghz/types.h>
|
||||
|
||||
#include "proto_pirate_icons.h"
|
||||
#include "gdr_icons.h"
|
||||
|
||||
#define TAG "ProtoPirateSubDecode"
|
||||
#define TAG "GDRSubDecode"
|
||||
|
||||
#define SUBGHZ_APP_FOLDER EXT_PATH("subghz")
|
||||
#define SAMPLES_TO_READ_PER_TICK 128
|
||||
@@ -60,7 +60,7 @@ typedef struct {
|
||||
|
||||
uint8_t worker_startup_delay;
|
||||
|
||||
ProtoPirateHistory* history;
|
||||
GDRHistory* history;
|
||||
uint16_t match_count;
|
||||
uint16_t selected_history_index;
|
||||
bool showing_signal_info;
|
||||
@@ -70,49 +70,49 @@ typedef struct {
|
||||
|
||||
static SubDecodeContext* g_decode_ctx = NULL;
|
||||
|
||||
static void protopirate_scene_sub_decode_update_receiver_statusbar(
|
||||
ProtoPirateApp* app,
|
||||
ProtoPirateHistory* history) {
|
||||
static void gdr_scene_sub_decode_update_receiver_statusbar(
|
||||
GDRApp* app,
|
||||
GDRHistory* history) {
|
||||
char frequency_str[16] = {0};
|
||||
char modulation_str[8] = {0};
|
||||
char history_stat_str[16] = {0};
|
||||
|
||||
protopirate_get_frequency_modulation_str(
|
||||
gdr_get_frequency_modulation_str(
|
||||
app, frequency_str, sizeof(frequency_str), modulation_str, sizeof(modulation_str));
|
||||
protopirate_history_format_status_text(history, history_stat_str, sizeof(history_stat_str));
|
||||
gdr_history_format_status_text(history, history_stat_str, sizeof(history_stat_str));
|
||||
|
||||
bool is_external =
|
||||
app->txrx->radio_device ? radio_device_loader_is_external(app->txrx->radio_device) : false;
|
||||
protopirate_view_receiver_add_data_statusbar(
|
||||
app->protopirate_receiver, frequency_str, modulation_str, history_stat_str, is_external);
|
||||
gdr_view_receiver_add_data_statusbar(
|
||||
app->gdr_receiver, frequency_str, modulation_str, history_stat_str, is_external);
|
||||
}
|
||||
|
||||
void protopirate_subdecode_psa_bf_complete_refresh(void* app) {
|
||||
ProtoPirateApp* a = (ProtoPirateApp*)app;
|
||||
void gdr_subdecode_psa_bf_complete_refresh(void* app) {
|
||||
GDRApp* a = (GDRApp*)app;
|
||||
SubDecodeContext* ctx = g_decode_ctx;
|
||||
if(!a || !ctx) return;
|
||||
ctx->state = DecodeStateShowSignalInfo;
|
||||
view_dispatcher_send_custom_event(
|
||||
a->view_dispatcher, ProtoPirateCustomEventSubDecodeUpdate);
|
||||
a->view_dispatcher, GDRCustomEventSubDecodeUpdate);
|
||||
}
|
||||
|
||||
// Forward declaration
|
||||
static void protopirate_scene_sub_decode_widget_callback(
|
||||
static void gdr_scene_sub_decode_widget_callback(
|
||||
GuiButtonType result,
|
||||
InputType type,
|
||||
void* context);
|
||||
|
||||
// Receiver view callback for history navigation
|
||||
static void
|
||||
protopirate_scene_sub_decode_receiver_callback(ProtoPirateCustomEvent event, void* context);
|
||||
gdr_scene_sub_decode_receiver_callback(GDRCustomEvent event, void* context);
|
||||
|
||||
// Callback when receiver successfully decodes a signal
|
||||
static void protopirate_sub_decode_receiver_callback(
|
||||
static void gdr_sub_decode_receiver_callback(
|
||||
SubGhzReceiver* receiver,
|
||||
SubGhzProtocolDecoderBase* decoder_base,
|
||||
void* context) {
|
||||
furi_check(context);
|
||||
ProtoPirateApp* app = context;
|
||||
GDRApp* app = context;
|
||||
SubDecodeContext* ctx = g_decode_ctx;
|
||||
|
||||
if(!ctx || ctx->state != DecodeStateDecodingRaw) {
|
||||
@@ -121,23 +121,23 @@ static void protopirate_sub_decode_receiver_callback(
|
||||
|
||||
FURI_LOG_I(TAG, "=== SIGNAL DECODED FROM FILE ===");
|
||||
|
||||
if(protopirate_history_add_to_history(
|
||||
if(gdr_history_add_to_history(
|
||||
ctx->history,
|
||||
decoder_base,
|
||||
app->txrx->preset,
|
||||
ProtoPirateHistorySourceUnknown)) {
|
||||
GDRHistorySourceUnknown)) {
|
||||
ctx->match_count++;
|
||||
FURI_LOG_I(TAG, "Added signal %u to history", ctx->match_count);
|
||||
|
||||
view_dispatcher_send_custom_event(
|
||||
app->view_dispatcher, ProtoPirateCustomEventSubDecodeUpdate);
|
||||
app->view_dispatcher, GDRCustomEventSubDecodeUpdate);
|
||||
}
|
||||
|
||||
subghz_receiver_reset(receiver);
|
||||
}
|
||||
|
||||
// Draw the decoding animation
|
||||
static void protopirate_decode_draw_callback(Canvas* canvas, void* context) {
|
||||
static void gdr_decode_draw_callback(Canvas* canvas, void* context) {
|
||||
UNUSED(context);
|
||||
SubDecodeContext* ctx = g_decode_ctx;
|
||||
if(!ctx) return;
|
||||
@@ -379,7 +379,7 @@ static void protopirate_decode_draw_callback(Canvas* canvas, void* context) {
|
||||
canvas_draw_str(canvas, 123, 62, spinner);
|
||||
}
|
||||
|
||||
static bool protopirate_decode_input_callback(InputEvent* event, void* context) {
|
||||
static bool gdr_decode_input_callback(InputEvent* event, void* context) {
|
||||
UNUSED(context);
|
||||
|
||||
if(event->type == InputTypeShort && event->key == InputKeyBack) {
|
||||
@@ -414,48 +414,48 @@ static void close_file_handles(SubDecodeContext* ctx) {
|
||||
|
||||
// Receiver view callback for history navigation
|
||||
static void
|
||||
protopirate_scene_sub_decode_receiver_callback(ProtoPirateCustomEvent event, void* context) {
|
||||
ProtoPirateApp* app = context;
|
||||
gdr_scene_sub_decode_receiver_callback(GDRCustomEvent event, void* context) {
|
||||
GDRApp* app = context;
|
||||
view_dispatcher_send_custom_event(app->view_dispatcher, event);
|
||||
}
|
||||
|
||||
// Widget callback for buttons (used in signal info view)
|
||||
static void protopirate_scene_sub_decode_widget_callback(
|
||||
static void gdr_scene_sub_decode_widget_callback(
|
||||
GuiButtonType result,
|
||||
InputType type,
|
||||
void* context) {
|
||||
ProtoPirateApp* app = context;
|
||||
GDRApp* app = context;
|
||||
|
||||
if(type == InputTypeShort || type == InputTypeLong) {
|
||||
if(result == GuiButtonTypeRight) {
|
||||
// Save button in signal info view
|
||||
view_dispatcher_send_custom_event(
|
||||
app->view_dispatcher, ProtoPirateCustomEventSubDecodeSave);
|
||||
app->view_dispatcher, GDRCustomEventSubDecodeSave);
|
||||
} else if(result == GuiButtonTypeLeft) {
|
||||
view_dispatcher_send_custom_event(
|
||||
app->view_dispatcher, ProtoPirateCustomEventSubDecodeBruteforceStart);
|
||||
app->view_dispatcher, GDRCustomEventSubDecodeBruteforceStart);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void protopirate_scene_sub_decode_on_enter(void* context) {
|
||||
ProtoPirateApp* app = context;
|
||||
void gdr_scene_sub_decode_on_enter(void* context) {
|
||||
GDRApp* app = context;
|
||||
|
||||
if(!protopirate_ensure_receiver_view(app) || !protopirate_ensure_widget(app) ||
|
||||
!protopirate_ensure_view_about(app)) {
|
||||
if(!gdr_ensure_receiver_view(app) || !gdr_ensure_widget(app) ||
|
||||
!gdr_ensure_view_about(app)) {
|
||||
notification_message(app->notifications, &sequence_error);
|
||||
scene_manager_previous_scene(app->scene_manager);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!app->radio_initialized && !protopirate_radio_init(app)) {
|
||||
if(!app->radio_initialized && !gdr_radio_init(app)) {
|
||||
FURI_LOG_E(TAG, "Failed to initialize radio for sub decode scene");
|
||||
notification_message(app->notifications, &sequence_error);
|
||||
scene_manager_previous_scene(app->scene_manager);
|
||||
return;
|
||||
}
|
||||
|
||||
protopirate_rx_stack_resume_after_tx(app);
|
||||
gdr_rx_stack_resume_after_tx(app);
|
||||
if(!app->txrx->receiver) {
|
||||
FURI_LOG_E(TAG, "Failed to allocate receiver for sub decode scene");
|
||||
notification_message(app->notifications, &sequence_error);
|
||||
@@ -477,7 +477,7 @@ void protopirate_scene_sub_decode_on_enter(void* context) {
|
||||
|
||||
// Allocate history
|
||||
if(!app->txrx->history) {
|
||||
app->txrx->history = protopirate_history_alloc();
|
||||
app->txrx->history = gdr_history_alloc();
|
||||
if(!app->txrx->history) {
|
||||
FURI_LOG_E(TAG, "Failed to allocate history!");
|
||||
free(g_decode_ctx);
|
||||
@@ -496,12 +496,12 @@ void protopirate_scene_sub_decode_on_enter(void* context) {
|
||||
g_decode_ctx->save_data = NULL;
|
||||
g_decode_ctx->worker_startup_delay = 0;
|
||||
g_decode_ctx->history = app->txrx->history;
|
||||
//protopirate_history_reset(g_decode_ctx->history);
|
||||
//gdr_history_reset(g_decode_ctx->history);
|
||||
g_decode_ctx->match_count = 0;
|
||||
g_decode_ctx->selected_history_index = 0;
|
||||
g_decode_ctx->raw_reader = NULL;
|
||||
|
||||
protopirate_view_receiver_set_sub_decode_mode(app->protopirate_receiver, true);
|
||||
gdr_view_receiver_set_sub_decode_mode(app->gdr_receiver, true);
|
||||
|
||||
FURI_LOG_I(TAG, "After context setup - Free heap: %zu", memmgr_get_free_heap());
|
||||
|
||||
@@ -518,11 +518,11 @@ void protopirate_scene_sub_decode_on_enter(void* context) {
|
||||
FURI_LOG_I(TAG, "Selected file: %s", furi_string_get_cstr(g_decode_ctx->file_path));
|
||||
g_decode_ctx->state = DecodeStateOpenFile;
|
||||
|
||||
view_set_draw_callback(app->view_about, protopirate_decode_draw_callback);
|
||||
view_set_input_callback(app->view_about, protopirate_decode_input_callback);
|
||||
view_set_draw_callback(app->view_about, gdr_decode_draw_callback);
|
||||
view_set_input_callback(app->view_about, gdr_decode_input_callback);
|
||||
view_set_context(app->view_about, app);
|
||||
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, ProtoPirateViewAbout);
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, GDRViewAbout);
|
||||
} else {
|
||||
scene_manager_previous_scene(app->scene_manager);
|
||||
}
|
||||
@@ -530,15 +530,15 @@ void protopirate_scene_sub_decode_on_enter(void* context) {
|
||||
furi_record_close(RECORD_DIALOGS);
|
||||
}
|
||||
|
||||
bool protopirate_scene_sub_decode_on_event(void* context, SceneManagerEvent event) {
|
||||
ProtoPirateApp* app = context;
|
||||
bool gdr_scene_sub_decode_on_event(void* context, SceneManagerEvent event) {
|
||||
GDRApp* app = context;
|
||||
bool consumed = false;
|
||||
SubDecodeContext* ctx = g_decode_ctx;
|
||||
|
||||
if(!ctx) return false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == ProtoPirateCustomEventSubDecodeUpdate) {
|
||||
if(event.event == GDRCustomEventSubDecodeUpdate) {
|
||||
// Update receiver view with new history items (when signals are detected during decoding)
|
||||
if(ctx->state == DecodeStateDecodingRaw) {
|
||||
// History is updated in callback, just refresh animation
|
||||
@@ -547,22 +547,22 @@ bool protopirate_scene_sub_decode_on_event(void* context, SceneManagerEvent even
|
||||
ctx->state == DecodeStateShowHistory ||
|
||||
(ctx->state == DecodeStateDone && !ctx->showing_signal_info)) {
|
||||
// Rebuild history view
|
||||
uint16_t history_count = protopirate_history_get_item(ctx->history);
|
||||
uint16_t history_count = gdr_history_get_item(ctx->history);
|
||||
if(history_count > 0) {
|
||||
protopirate_view_receiver_sync_menu_from_history(
|
||||
app->protopirate_receiver, ctx->history);
|
||||
gdr_view_receiver_sync_menu_from_history(
|
||||
app->gdr_receiver, ctx->history);
|
||||
|
||||
protopirate_view_receiver_set_idx_menu(
|
||||
app->protopirate_receiver, ctx->selected_history_index);
|
||||
gdr_view_receiver_set_idx_menu(
|
||||
app->gdr_receiver, ctx->selected_history_index);
|
||||
|
||||
protopirate_scene_sub_decode_update_receiver_statusbar(app, ctx->history);
|
||||
gdr_scene_sub_decode_update_receiver_statusbar(app, ctx->history);
|
||||
}
|
||||
}
|
||||
consumed = true;
|
||||
} else if(event.event == ProtoPirateCustomEventSubDecodeSave) {
|
||||
} else if(event.event == GDRCustomEventSubDecodeSave) {
|
||||
// Save the file (same as receiver_info)
|
||||
FlipperFormat* ff =
|
||||
protopirate_history_get_raw_data(ctx->history, ctx->selected_history_index);
|
||||
gdr_history_get_raw_data(ctx->history, ctx->selected_history_index);
|
||||
|
||||
if(ff) {
|
||||
// Extract protocol name
|
||||
@@ -577,7 +577,7 @@ bool protopirate_scene_sub_decode_on_event(void* context, SceneManagerEvent even
|
||||
furi_string_replace_all(protocol, " ", "_");
|
||||
|
||||
FuriString* saved_path = furi_string_alloc();
|
||||
if(protopirate_storage_save_capture(
|
||||
if(gdr_storage_save_capture(
|
||||
ff, furi_string_get_cstr(protocol), saved_path)) {
|
||||
notification_message(app->notifications, &sequence_success);
|
||||
} else {
|
||||
@@ -594,64 +594,64 @@ bool protopirate_scene_sub_decode_on_event(void* context, SceneManagerEvent even
|
||||
notification_message(app->notifications, &sequence_error);
|
||||
}
|
||||
consumed = true;
|
||||
} else if(event.event == ProtoPirateCustomEventSubDecodeBruteforceStart) {
|
||||
} else if(event.event == GDRCustomEventSubDecodeBruteforceStart) {
|
||||
app->txrx->idx_menu_chosen = ctx->selected_history_index;
|
||||
protopirate_selected_capture_set(
|
||||
gdr_selected_capture_set(
|
||||
app,
|
||||
ctx->history,
|
||||
NULL,
|
||||
ctx->selected_history_index,
|
||||
ProtoPirateCaptureOwnerSubDecode);
|
||||
if(protopirate_psa_bf_plugin_ensure_loaded(app) && app->psa_bf_plugin &&
|
||||
GDRCaptureOwnerSubDecode);
|
||||
if(gdr_psa_bf_plugin_ensure_loaded(app) && app->psa_bf_plugin &&
|
||||
app->psa_bf_plugin->on_scene_event(
|
||||
app, ProtoPiratePsaBfContextSubDecode, event)) {
|
||||
app, GDRPsaBfContextSubDecode, event)) {
|
||||
if(app->psa_bf_plugin->is_running(app)) {
|
||||
view_dispatcher_switch_to_view(
|
||||
app->view_dispatcher, ProtoPirateViewWidget);
|
||||
app->view_dispatcher, GDRViewWidget);
|
||||
}
|
||||
}
|
||||
consumed = true;
|
||||
return consumed;
|
||||
|
||||
} else if(event.event == ProtoPirateCustomEventPsaBruteforceComplete) {
|
||||
} else if(event.event == GDRCustomEventPsaBruteforceComplete) {
|
||||
app->txrx->idx_menu_chosen = ctx->selected_history_index;
|
||||
protopirate_selected_capture_set(
|
||||
gdr_selected_capture_set(
|
||||
app,
|
||||
ctx->history,
|
||||
NULL,
|
||||
ctx->selected_history_index,
|
||||
ProtoPirateCaptureOwnerSubDecode);
|
||||
if(protopirate_psa_bf_plugin_ensure_loaded(app) && app->psa_bf_plugin) {
|
||||
GDRCaptureOwnerSubDecode);
|
||||
if(gdr_psa_bf_plugin_ensure_loaded(app) && app->psa_bf_plugin) {
|
||||
app->psa_bf_plugin->on_scene_event(
|
||||
app, ProtoPiratePsaBfContextSubDecode, event);
|
||||
app, GDRPsaBfContextSubDecode, event);
|
||||
}
|
||||
consumed = true;
|
||||
return consumed;
|
||||
|
||||
} else if(event.event == ProtoPirateCustomEventViewReceiverOK) {
|
||||
} else if(event.event == GDRCustomEventViewReceiverOK) {
|
||||
// User selected a signal from history - show signal info
|
||||
uint16_t idx = protopirate_view_receiver_get_idx_menu(app->protopirate_receiver);
|
||||
uint16_t history_count = protopirate_history_get_item(ctx->history);
|
||||
uint16_t idx = gdr_view_receiver_get_idx_menu(app->gdr_receiver);
|
||||
uint16_t history_count = gdr_history_get_item(ctx->history);
|
||||
if(idx < history_count) {
|
||||
ctx->selected_history_index = idx;
|
||||
protopirate_selected_capture_set(
|
||||
gdr_selected_capture_set(
|
||||
app,
|
||||
ctx->history,
|
||||
NULL,
|
||||
idx,
|
||||
ProtoPirateCaptureOwnerSubDecode);
|
||||
GDRCaptureOwnerSubDecode);
|
||||
ctx->state = DecodeStateShowSignalInfo;
|
||||
ctx->showing_signal_info = true;
|
||||
// Trigger state handler
|
||||
view_dispatcher_send_custom_event(
|
||||
app->view_dispatcher, ProtoPirateCustomEventSubDecodeUpdate);
|
||||
app->view_dispatcher, GDRCustomEventSubDecodeUpdate);
|
||||
}
|
||||
consumed = true;
|
||||
} else if(event.event == ProtoPirateCustomEventViewReceiverBack) {
|
||||
} else if(event.event == GDRCustomEventViewReceiverBack) {
|
||||
// User pressed back from history - reset and go to main menu
|
||||
protopirate_history_reset(ctx->history);
|
||||
gdr_history_reset(ctx->history);
|
||||
scene_manager_search_and_switch_to_previous_scene(
|
||||
app->scene_manager, ProtoPirateSceneStart);
|
||||
app->scene_manager, GDRSceneStart);
|
||||
consumed = true;
|
||||
}
|
||||
}
|
||||
@@ -661,16 +661,16 @@ bool protopirate_scene_sub_decode_on_event(void* context, SceneManagerEvent even
|
||||
ctx->animation_frame++;
|
||||
|
||||
app->txrx->idx_menu_chosen = ctx->selected_history_index;
|
||||
protopirate_selected_capture_set(
|
||||
gdr_selected_capture_set(
|
||||
app,
|
||||
ctx->history,
|
||||
NULL,
|
||||
ctx->selected_history_index,
|
||||
ProtoPirateCaptureOwnerSubDecode);
|
||||
if(protopirate_psa_bf_plugin_ensure_loaded(app) && app->psa_bf_plugin &&
|
||||
GDRCaptureOwnerSubDecode);
|
||||
if(gdr_psa_bf_plugin_ensure_loaded(app) && app->psa_bf_plugin &&
|
||||
app->psa_bf_plugin->is_running(app) &&
|
||||
app->psa_bf_plugin->on_scene_event(
|
||||
app, ProtoPiratePsaBfContextSubDecode, event)) {
|
||||
app, GDRPsaBfContextSubDecode, event)) {
|
||||
return consumed;
|
||||
}
|
||||
|
||||
@@ -883,16 +883,16 @@ bool protopirate_scene_sub_decode_on_event(void* context, SceneManagerEvent even
|
||||
break;
|
||||
}
|
||||
|
||||
protopirate_preset_init(
|
||||
gdr_preset_init(
|
||||
app, preset_name_short, ctx->frequency, preset_data, preset_data_size);
|
||||
|
||||
if(!protopirate_refresh_protocol_registry(app, true) || !app->txrx->receiver) {
|
||||
if(!gdr_refresh_protocol_registry(app, true) || !app->txrx->receiver) {
|
||||
FURI_LOG_E(TAG, "Failed to rebuild receiver for preset %s", preset_name_short);
|
||||
break;
|
||||
}
|
||||
|
||||
subghz_receiver_set_rx_callback(
|
||||
app->txrx->receiver, protopirate_sub_decode_receiver_callback, app);
|
||||
app->txrx->receiver, gdr_sub_decode_receiver_callback, app);
|
||||
|
||||
setup_ok = true;
|
||||
} while(false);
|
||||
@@ -970,7 +970,7 @@ bool protopirate_scene_sub_decode_on_event(void* context, SceneManagerEvent even
|
||||
|
||||
subghz_receiver_set_rx_callback(app->txrx->receiver, NULL, NULL);
|
||||
|
||||
uint16_t history_count = protopirate_history_get_item(ctx->history);
|
||||
uint16_t history_count = gdr_history_get_item(ctx->history);
|
||||
|
||||
if(history_count > 0) {
|
||||
ctx->state = DecodeStateShowSuccess;
|
||||
@@ -983,7 +983,7 @@ bool protopirate_scene_sub_decode_on_event(void* context, SceneManagerEvent even
|
||||
ctx->result,
|
||||
"RAW Signal\n\n"
|
||||
"Freq: %lu.%02lu MHz\n\n"
|
||||
"No ProtoPirate protocol\n"
|
||||
"No GDR protocol\n"
|
||||
"detected in signal.",
|
||||
ctx->frequency / 1000000,
|
||||
(ctx->frequency % 1000000) / 10000);
|
||||
@@ -1005,7 +1005,7 @@ bool protopirate_scene_sub_decode_on_event(void* context, SceneManagerEvent even
|
||||
ctx->result_display_counter++;
|
||||
if(ctx->result_display_counter >= SUCCESS_DISPLAY_TICKS) {
|
||||
// Check if we have history items (from RAW decoding) - show history list instead of widget
|
||||
uint16_t history_count = protopirate_history_get_item(ctx->history);
|
||||
uint16_t history_count = gdr_history_get_item(ctx->history);
|
||||
if(history_count > 0) {
|
||||
// Transition to showing history list
|
||||
ctx->state = DecodeStateShowHistory;
|
||||
@@ -1021,11 +1021,11 @@ bool protopirate_scene_sub_decode_on_event(void* context, SceneManagerEvent even
|
||||
app->widget,
|
||||
GuiButtonTypeRight,
|
||||
"Save",
|
||||
protopirate_scene_sub_decode_widget_callback,
|
||||
gdr_scene_sub_decode_widget_callback,
|
||||
app);
|
||||
}
|
||||
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, ProtoPirateViewWidget);
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, GDRViewWidget);
|
||||
ctx->state = DecodeStateDone;
|
||||
}
|
||||
}
|
||||
@@ -1038,7 +1038,7 @@ bool protopirate_scene_sub_decode_on_event(void* context, SceneManagerEvent even
|
||||
widget_reset(app->widget);
|
||||
widget_add_text_scroll_element(
|
||||
app->widget, 0, 0, 128, 64, furi_string_get_cstr(ctx->result));
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, ProtoPirateViewWidget);
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, GDRViewWidget);
|
||||
ctx->state = DecodeStateDone;
|
||||
}
|
||||
break;
|
||||
@@ -1046,26 +1046,26 @@ bool protopirate_scene_sub_decode_on_event(void* context, SceneManagerEvent even
|
||||
|
||||
case DecodeStateShowHistory: {
|
||||
// Show history list using receiver view (same as receive mode)
|
||||
uint16_t history_count = protopirate_history_get_item(ctx->history);
|
||||
uint16_t history_count = gdr_history_get_item(ctx->history);
|
||||
if(history_count > 0) {
|
||||
protopirate_view_receiver_set_history_mutex(app->protopirate_receiver, NULL);
|
||||
protopirate_view_receiver_sync_menu_from_history(
|
||||
app->protopirate_receiver, ctx->history);
|
||||
gdr_view_receiver_set_history_mutex(app->gdr_receiver, NULL);
|
||||
gdr_view_receiver_sync_menu_from_history(
|
||||
app->gdr_receiver, ctx->history);
|
||||
|
||||
// Set initial selection
|
||||
protopirate_view_receiver_set_idx_menu(
|
||||
app->protopirate_receiver, ctx->selected_history_index);
|
||||
gdr_view_receiver_set_idx_menu(
|
||||
app->gdr_receiver, ctx->selected_history_index);
|
||||
|
||||
// Set up callback
|
||||
protopirate_view_receiver_set_callback(
|
||||
app->protopirate_receiver,
|
||||
protopirate_scene_sub_decode_receiver_callback,
|
||||
gdr_view_receiver_set_callback(
|
||||
app->gdr_receiver,
|
||||
gdr_scene_sub_decode_receiver_callback,
|
||||
app);
|
||||
|
||||
protopirate_scene_sub_decode_update_receiver_statusbar(app, ctx->history);
|
||||
gdr_scene_sub_decode_update_receiver_statusbar(app, ctx->history);
|
||||
|
||||
// Switch to receiver view
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, ProtoPirateViewReceiver);
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, GDRViewReceiver);
|
||||
ctx->state = DecodeStateDone;
|
||||
ctx->showing_signal_info = false;
|
||||
}
|
||||
@@ -1076,12 +1076,12 @@ bool protopirate_scene_sub_decode_on_event(void* context, SceneManagerEvent even
|
||||
// Show signal info in widget (same layout as receiver_info)
|
||||
widget_reset(app->widget);
|
||||
|
||||
uint16_t history_count = protopirate_history_get_item(ctx->history);
|
||||
uint16_t history_count = gdr_history_get_item(ctx->history);
|
||||
if(ctx->selected_history_index < history_count) {
|
||||
FuriString* text = furi_string_alloc();
|
||||
|
||||
// Get menu text (first line) for header
|
||||
/*protopirate_history_get_text_item_menu(
|
||||
/*gdr_history_get_text_item_menu(
|
||||
ctx->history, text, ctx->selected_history_index);
|
||||
widget_add_string_element(
|
||||
app->widget,
|
||||
@@ -1094,7 +1094,7 @@ bool protopirate_scene_sub_decode_on_event(void* context, SceneManagerEvent even
|
||||
|
||||
// Get full text for body
|
||||
furi_string_reset(text);
|
||||
protopirate_history_get_text_item_detail(
|
||||
gdr_history_get_text_item_detail(
|
||||
ctx->history, ctx->selected_history_index, text, app->txrx->environment);
|
||||
widget_add_text_scroll_element(
|
||||
app->widget, 0, 0, 128, 50, furi_string_get_cstr(text));
|
||||
@@ -1104,12 +1104,12 @@ bool protopirate_scene_sub_decode_on_event(void* context, SceneManagerEvent even
|
||||
app->widget,
|
||||
GuiButtonTypeRight,
|
||||
"Save",
|
||||
protopirate_scene_sub_decode_widget_callback,
|
||||
gdr_scene_sub_decode_widget_callback,
|
||||
app);
|
||||
|
||||
// Store reference to history item's flipper format for saving
|
||||
FlipperFormat* ff =
|
||||
protopirate_history_get_raw_data(ctx->history, ctx->selected_history_index);
|
||||
gdr_history_get_raw_data(ctx->history, ctx->selected_history_index);
|
||||
if(ff) {
|
||||
ctx->can_save = true;
|
||||
|
||||
@@ -1121,16 +1121,16 @@ bool protopirate_scene_sub_decode_on_event(void* context, SceneManagerEvent even
|
||||
if(is_psa) {
|
||||
app->txrx->idx_menu_chosen = ctx->selected_history_index;
|
||||
bool needs_bf = false;
|
||||
if(protopirate_psa_bf_plugin_ensure_loaded(app) && app->psa_bf_plugin) {
|
||||
if(gdr_psa_bf_plugin_ensure_loaded(app) && app->psa_bf_plugin) {
|
||||
needs_bf = app->psa_bf_plugin->needs_bruteforce(
|
||||
app, ProtoPiratePsaBfContextSubDecode);
|
||||
app, GDRPsaBfContextSubDecode);
|
||||
}
|
||||
if(needs_bf) {
|
||||
widget_add_button_element(
|
||||
app->widget,
|
||||
GuiButtonTypeLeft,
|
||||
"Brute force",
|
||||
protopirate_scene_sub_decode_widget_callback,
|
||||
gdr_scene_sub_decode_widget_callback,
|
||||
app);
|
||||
}
|
||||
}
|
||||
@@ -1139,7 +1139,7 @@ bool protopirate_scene_sub_decode_on_event(void* context, SceneManagerEvent even
|
||||
furi_string_free(text);
|
||||
}
|
||||
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, ProtoPirateViewWidget);
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, GDRViewWidget);
|
||||
ctx->state = DecodeStateDone;
|
||||
ctx->showing_signal_info = true;
|
||||
break;
|
||||
@@ -1156,9 +1156,9 @@ bool protopirate_scene_sub_decode_on_event(void* context, SceneManagerEvent even
|
||||
}
|
||||
} else if(event.type == SceneManagerEventTypeBack) {
|
||||
app->txrx->idx_menu_chosen = ctx->selected_history_index;
|
||||
if(protopirate_psa_bf_plugin_ensure_loaded(app) && app->psa_bf_plugin &&
|
||||
if(gdr_psa_bf_plugin_ensure_loaded(app) && app->psa_bf_plugin &&
|
||||
app->psa_bf_plugin->on_scene_event(
|
||||
app, ProtoPiratePsaBfContextSubDecode, event)) {
|
||||
app, GDRPsaBfContextSubDecode, event)) {
|
||||
consumed = true;
|
||||
return consumed;
|
||||
}
|
||||
@@ -1169,7 +1169,7 @@ bool protopirate_scene_sub_decode_on_event(void* context, SceneManagerEvent even
|
||||
//ctx->selected_history_index = 0;
|
||||
ctx->state = DecodeStateShowHistory;
|
||||
view_dispatcher_send_custom_event(
|
||||
app->view_dispatcher, ProtoPirateCustomEventSubDecodeUpdate);
|
||||
app->view_dispatcher, GDRCustomEventSubDecodeUpdate);
|
||||
consumed = true;
|
||||
}
|
||||
// If in history view, back is handled by ViewReceiverBack event
|
||||
@@ -1178,14 +1178,14 @@ bool protopirate_scene_sub_decode_on_event(void* context, SceneManagerEvent even
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void protopirate_scene_sub_decode_on_exit(void* context) {
|
||||
ProtoPirateApp* app = context;
|
||||
void gdr_scene_sub_decode_on_exit(void* context) {
|
||||
GDRApp* app = context;
|
||||
|
||||
subghz_receiver_reset(app->txrx->receiver);
|
||||
|
||||
subghz_receiver_set_rx_callback(app->txrx->receiver, NULL, NULL);
|
||||
|
||||
protopirate_psa_bf_context_release(app);
|
||||
gdr_psa_bf_context_release(app);
|
||||
|
||||
if(g_decode_ctx) {
|
||||
if(g_decode_ctx->raw_reader) {
|
||||
@@ -1210,12 +1210,12 @@ void protopirate_scene_sub_decode_on_exit(void* context) {
|
||||
|
||||
if(app->txrx->history) {
|
||||
if(app->selected_capture.history == app->txrx->history) {
|
||||
protopirate_selected_capture_clear(app);
|
||||
gdr_selected_capture_clear(app);
|
||||
}
|
||||
protopirate_history_reset(app->txrx->history);
|
||||
gdr_history_reset(app->txrx->history);
|
||||
|
||||
FURI_LOG_D(TAG, "Freeing history %p", app->txrx->history);
|
||||
protopirate_history_free(app->txrx->history);
|
||||
gdr_history_free(app->txrx->history);
|
||||
app->txrx->history = NULL;
|
||||
}
|
||||
|
||||
@@ -1223,6 +1223,6 @@ void protopirate_scene_sub_decode_on_exit(void* context) {
|
||||
view_set_input_callback(app->view_about, NULL);
|
||||
widget_reset(app->widget);
|
||||
|
||||
protopirate_view_receiver_reset_menu(app->protopirate_receiver);
|
||||
gdr_view_receiver_reset_menu(app->gdr_receiver);
|
||||
}
|
||||
#endif
|
||||
+23
-23
@@ -1,11 +1,11 @@
|
||||
// scenes/protopirate_scene_timing_tuner.c
|
||||
#include "../protopirate_app_i.h"
|
||||
// scenes/gdr_scene_timing_tuner.c
|
||||
#include "../gdr_app_i.h"
|
||||
#ifdef ENABLE_TIMING_TUNER_SCENE
|
||||
#include "../protocols/protocol_items.h"
|
||||
#include <gui/elements.h>
|
||||
#include <math.h>
|
||||
|
||||
#define TAG "ProtoPirateTimingTuner"
|
||||
#define TAG "GDRTimingTuner"
|
||||
|
||||
#define MAX_TIMING_SAMPLES 512
|
||||
#define VISIBLE_LINES 6
|
||||
@@ -33,7 +33,7 @@ typedef struct {
|
||||
|
||||
// Protocol match info
|
||||
const char* matched_protocol;
|
||||
const ProtoPirateProtocolTiming* timing_info;
|
||||
const GDRProtocolTiming* timing_info;
|
||||
|
||||
// State
|
||||
bool is_receiving;
|
||||
@@ -44,7 +44,7 @@ typedef struct {
|
||||
uint8_t total_lines;
|
||||
|
||||
// App reference for callback
|
||||
ProtoPirateApp* app;
|
||||
GDRApp* app;
|
||||
} TimingTunerContext;
|
||||
|
||||
static TimingTunerContext* g_timing_ctx = NULL;
|
||||
@@ -494,7 +494,7 @@ static void timing_tuner_draw_callback(Canvas* canvas, void* context) {
|
||||
}
|
||||
|
||||
static bool timing_tuner_input_callback(InputEvent* event, void* context) {
|
||||
ProtoPirateApp* app = context;
|
||||
GDRApp* app = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event->type == InputTypeShort || event->type == InputTypeRepeat) {
|
||||
@@ -553,7 +553,7 @@ static void timing_tuner_rx_callback(
|
||||
SubGhzProtocolDecoderBase* decoder_base,
|
||||
void* context) {
|
||||
UNUSED(receiver);
|
||||
ProtoPirateApp* app = context;
|
||||
GDRApp* app = context;
|
||||
TimingTunerContext* ctx = g_timing_ctx;
|
||||
|
||||
if(!ctx || ctx->has_match) return;
|
||||
@@ -563,7 +563,7 @@ static void timing_tuner_rx_callback(
|
||||
|
||||
FURI_LOG_I(TAG, "Matched protocol: %s", protocol_name);
|
||||
|
||||
ctx->timing_info = protopirate_get_protocol_timing(protocol_name);
|
||||
ctx->timing_info = gdr_get_protocol_timing(protocol_name);
|
||||
|
||||
if(ctx->timing_info) {
|
||||
FURI_LOG_I(
|
||||
@@ -606,26 +606,26 @@ static void timing_tuner_pair_callback(void* context, bool level, uint32_t durat
|
||||
}
|
||||
}
|
||||
|
||||
void protopirate_scene_timing_tuner_on_enter(void* context) {
|
||||
void gdr_scene_timing_tuner_on_enter(void* context) {
|
||||
furi_check(context);
|
||||
ProtoPirateApp* app = context;
|
||||
GDRApp* app = context;
|
||||
|
||||
FURI_LOG_I(TAG, "Entering Timing Tuner");
|
||||
|
||||
if(!protopirate_ensure_view_about(app)) {
|
||||
if(!gdr_ensure_view_about(app)) {
|
||||
notification_message(app->notifications, &sequence_error);
|
||||
scene_manager_previous_scene(app->scene_manager);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!app->radio_initialized && !protopirate_radio_init(app)) {
|
||||
if(!app->radio_initialized && !gdr_radio_init(app)) {
|
||||
FURI_LOG_E(TAG, "Failed to initialize radio for timing tuner");
|
||||
notification_message(app->notifications, &sequence_error);
|
||||
scene_manager_previous_scene(app->scene_manager);
|
||||
return;
|
||||
}
|
||||
|
||||
protopirate_rx_stack_resume_after_tx(app);
|
||||
gdr_rx_stack_resume_after_tx(app);
|
||||
if(!app->txrx->receiver) {
|
||||
FURI_LOG_E(TAG, "Failed to allocate receiver for timing tuner");
|
||||
notification_message(app->notifications, &sequence_error);
|
||||
@@ -676,15 +676,15 @@ void protopirate_scene_timing_tuner_on_enter(void* context) {
|
||||
subghz_worker_set_pair_callback(
|
||||
app->txrx->worker, (SubGhzWorkerPairCallback)timing_tuner_pair_callback);
|
||||
|
||||
protopirate_begin(app, app->txrx->preset->data);
|
||||
protopirate_rx(app, app->txrx->preset->frequency);
|
||||
gdr_begin(app, app->txrx->preset->data);
|
||||
gdr_rx(app, app->txrx->preset->frequency);
|
||||
g_timing_ctx->is_receiving = true;
|
||||
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, ProtoPirateViewAbout);
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, GDRViewAbout);
|
||||
}
|
||||
|
||||
bool protopirate_scene_timing_tuner_on_event(void* context, SceneManagerEvent event) {
|
||||
ProtoPirateApp* app = context;
|
||||
bool gdr_scene_timing_tuner_on_event(void* context, SceneManagerEvent event) {
|
||||
GDRApp* app = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
@@ -693,10 +693,10 @@ bool protopirate_scene_timing_tuner_on_event(void* context, SceneManagerEvent ev
|
||||
consumed = true;
|
||||
} else if(event.event == 1) {
|
||||
if(g_timing_ctx && g_timing_ctx->is_receiving) {
|
||||
protopirate_rx_end(app);
|
||||
gdr_rx_end(app);
|
||||
g_timing_ctx->is_receiving = false;
|
||||
}
|
||||
scene_manager_next_scene(app->scene_manager, ProtoPirateSceneReceiverConfig);
|
||||
scene_manager_next_scene(app->scene_manager, GDRSceneReceiverConfig);
|
||||
consumed = true;
|
||||
}
|
||||
} else if(event.type == SceneManagerEventTypeTick) {
|
||||
@@ -714,13 +714,13 @@ bool protopirate_scene_timing_tuner_on_event(void* context, SceneManagerEvent ev
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void protopirate_scene_timing_tuner_on_exit(void* context) {
|
||||
ProtoPirateApp* app = context;
|
||||
void gdr_scene_timing_tuner_on_exit(void* context) {
|
||||
GDRApp* app = context;
|
||||
|
||||
FURI_LOG_I(TAG, "Exiting Timing Tuner");
|
||||
|
||||
if(g_timing_ctx && g_timing_ctx->is_receiving) {
|
||||
protopirate_rx_end(app);
|
||||
gdr_rx_end(app);
|
||||
}
|
||||
|
||||
subghz_worker_set_pair_callback(
|
||||
+43
-43
@@ -1,8 +1,8 @@
|
||||
// scenes/plugins/protopirate_emulate_plugin.c
|
||||
// scenes/plugins/gdr_emulate_plugin.c
|
||||
|
||||
#include "protopirate_emulate_plugin.h"
|
||||
#include "gdr_emulate_plugin.h"
|
||||
|
||||
#include "../../protopirate_app_i.h"
|
||||
#include "../../gdr_app_i.h"
|
||||
|
||||
#ifdef ENABLE_EMULATE_FEATURE
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
#include <furi.h>
|
||||
#include <string.h>
|
||||
|
||||
#define TAG "ProtoPirateEmulatePlugin"
|
||||
#define TAG "GDREmulatePlugin"
|
||||
|
||||
#define MIN_TX_TIME 666U
|
||||
|
||||
@@ -59,14 +59,14 @@ typedef struct {
|
||||
} EmulateResolvedPreset;
|
||||
|
||||
static EmulateContext* emulate_context = NULL;
|
||||
static const ProtoPirateEmulateHostApi* g_host_api = NULL;
|
||||
static const GDREmulateHostApi* g_host_api = NULL;
|
||||
|
||||
static void emulate_request_nav_pop(ProtoPirateApp* app) {
|
||||
static void emulate_request_nav_pop(GDRApp* app) {
|
||||
app->emulate_nav_pending = EMULATE_NAV_POP;
|
||||
}
|
||||
|
||||
static void emulate_request_nav_after_exit(ProtoPirateApp* app) {
|
||||
if(scene_manager_has_previous_scene(app->scene_manager, ProtoPirateSceneStart)) {
|
||||
static void emulate_request_nav_after_exit(GDRApp* app) {
|
||||
if(scene_manager_has_previous_scene(app->scene_manager, GDRSceneStart)) {
|
||||
app->emulate_nav_pending = EMULATE_NAV_POP;
|
||||
} else {
|
||||
app->emulate_nav_pending = EMULATE_NAV_STOP_APP;
|
||||
@@ -138,7 +138,7 @@ static const uint8_t tx_power_value[TX_PRESET_VALUES_COUNT] = {
|
||||
0x03 // -30dBm
|
||||
};
|
||||
|
||||
static bool emulate_radio_ready(ProtoPirateApp* app) {
|
||||
static bool emulate_radio_ready(GDRApp* app) {
|
||||
furi_check(app);
|
||||
return app->radio_initialized && app->txrx && app->txrx->radio_device &&
|
||||
app->txrx->environment;
|
||||
@@ -166,7 +166,7 @@ static void emulate_resolved_preset_release(EmulateResolvedPreset* preset) {
|
||||
}
|
||||
|
||||
static bool emulate_resolved_preset_assign_named(
|
||||
ProtoPirateApp* app,
|
||||
GDRApp* app,
|
||||
const char* preset_name,
|
||||
EmulateResolvedPreset* preset) {
|
||||
furi_check(app);
|
||||
@@ -215,7 +215,7 @@ static bool
|
||||
}
|
||||
|
||||
static bool emulate_context_resolve_tx_preset(
|
||||
ProtoPirateApp* app,
|
||||
GDRApp* app,
|
||||
EmulateContext* ctx,
|
||||
EmulateResolvedPreset* preset) {
|
||||
furi_check(app);
|
||||
@@ -269,7 +269,7 @@ static bool emulate_context_resolve_tx_preset(
|
||||
return false;
|
||||
}
|
||||
|
||||
static void emu_stop_tx(ProtoPirateApp* app) {
|
||||
static void emu_stop_tx(GDRApp* app) {
|
||||
FURI_LOG_I(TAG, "Stopping transmission");
|
||||
|
||||
if(app->txrx->radio_device) {
|
||||
@@ -287,7 +287,7 @@ static void emu_stop_tx(ProtoPirateApp* app) {
|
||||
if(app->txrx->radio_device) {
|
||||
subghz_devices_idle(app->txrx->radio_device);
|
||||
}
|
||||
app->txrx->txrx_state = ProtoPirateTxRxStateIDLE;
|
||||
app->txrx->txrx_state = GDRTxRxStateIDLE;
|
||||
app->start_tx_time = 0;
|
||||
emulate_context_reset_transmitter();
|
||||
|
||||
@@ -323,7 +323,7 @@ static void emulate_context_free(void) {
|
||||
emulate_context = NULL;
|
||||
}
|
||||
|
||||
static bool emulate_context_try_init_transmitter(ProtoPirateApp* app, EmulateContext* ctx) {
|
||||
static bool emulate_context_try_init_transmitter(GDRApp* app, EmulateContext* ctx) {
|
||||
if(ctx->transmitter) return true;
|
||||
if(!ctx->flipper_format || !ctx->protocol_name) return false;
|
||||
|
||||
@@ -517,7 +517,7 @@ static void emulate_draw_callback(Canvas* canvas, void* model) {
|
||||
}
|
||||
|
||||
static bool emulate_input_callback(InputEvent* event, void* context) {
|
||||
ProtoPirateApp* app = context;
|
||||
GDRApp* app = context;
|
||||
EmulateContext* ctx = emulate_context;
|
||||
|
||||
if(!ctx) return false;
|
||||
@@ -525,7 +525,7 @@ static bool emulate_input_callback(InputEvent* event, void* context) {
|
||||
if(event->type == InputTypePress) {
|
||||
if(event->key == InputKeyBack) {
|
||||
view_dispatcher_send_custom_event(
|
||||
app->view_dispatcher, ProtoPirateCustomEventEmulateExit);
|
||||
app->view_dispatcher, GDRCustomEventEmulateExit);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -540,13 +540,13 @@ static bool emulate_input_callback(InputEvent* event, void* context) {
|
||||
|
||||
ctx->is_transmitting = true;
|
||||
view_dispatcher_send_custom_event(
|
||||
app->view_dispatcher, ProtoPirateCustomEventEmulateTransmit);
|
||||
app->view_dispatcher, GDRCustomEventEmulateTransmit);
|
||||
|
||||
return true;
|
||||
} else if(event->type == InputTypeRelease) {
|
||||
if(ctx && ctx->is_transmitting) {
|
||||
view_dispatcher_send_custom_event(
|
||||
app->view_dispatcher, ProtoPirateCustomEventEmulateStop);
|
||||
app->view_dispatcher, GDRCustomEventEmulateStop);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -565,7 +565,7 @@ static uint8_t get_tx_preset_byte(uint8_t* preset_data) {
|
||||
}
|
||||
|
||||
static void plugin_on_enter(void* context) {
|
||||
ProtoPirateApp* app = context;
|
||||
GDRApp* app = context;
|
||||
furi_check(g_host_api);
|
||||
|
||||
if(!g_host_api->ensure_view_about || !g_host_api->ensure_view_about(app)) {
|
||||
@@ -710,21 +710,21 @@ static void plugin_on_enter(void* context) {
|
||||
view_set_context(app->view_about, app);
|
||||
view_set_previous_callback(app->view_about, NULL);
|
||||
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, ProtoPirateViewAbout);
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, GDRViewAbout);
|
||||
}
|
||||
|
||||
static bool plugin_on_event(void* context, SceneManagerEvent event) {
|
||||
#define INVALID_PRESET "Cannot set TX power on this preset."
|
||||
ProtoPirateApp* app = context;
|
||||
GDRApp* app = context;
|
||||
bool consumed = false;
|
||||
|
||||
EmulateContext* ctx = emulate_context;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
switch(event.event) {
|
||||
case ProtoPirateCustomEventEmulateTransmit:
|
||||
case GDRCustomEventEmulateTransmit:
|
||||
if(ctx && ctx->flipper_format) {
|
||||
if(app->txrx->txrx_state == ProtoPirateTxRxStateTx) {
|
||||
if(app->txrx->txrx_state == GDRTxRxStateTx) {
|
||||
FURI_LOG_W(TAG, "Previous transmission still active, stopping it");
|
||||
if(app->txrx->radio_device) {
|
||||
subghz_devices_stop_async_tx(app->txrx->radio_device);
|
||||
@@ -734,7 +734,7 @@ static bool plugin_on_event(void* context, SceneManagerEvent event) {
|
||||
if(app->txrx->radio_device) {
|
||||
subghz_devices_idle(app->txrx->radio_device);
|
||||
}
|
||||
app->txrx->txrx_state = ProtoPirateTxRxStateIDLE;
|
||||
app->txrx->txrx_state = GDRTxRxStateIDLE;
|
||||
}
|
||||
|
||||
emulate_context_reset_transmitter();
|
||||
@@ -801,7 +801,7 @@ static bool plugin_on_event(void* context, SceneManagerEvent event) {
|
||||
|
||||
if(subghz_devices_start_async_tx(
|
||||
app->txrx->radio_device, subghz_transmitter_yield, ctx->transmitter)) {
|
||||
app->txrx->txrx_state = ProtoPirateTxRxStateTx;
|
||||
app->txrx->txrx_state = GDRTxRxStateTx;
|
||||
notification_message(app->notifications, &emu_sequence_tx);
|
||||
notification_message(app->notifications, &sequence_blink_magenta_10);
|
||||
FURI_LOG_I(
|
||||
@@ -829,9 +829,9 @@ static bool plugin_on_event(void* context, SceneManagerEvent event) {
|
||||
consumed = true;
|
||||
break;
|
||||
|
||||
case ProtoPirateCustomEventEmulateStop:
|
||||
case GDRCustomEventEmulateStop:
|
||||
FURI_LOG_I(TAG, "Stop event received, txrx_state=%d", app->txrx->txrx_state);
|
||||
if(app->txrx->txrx_state == ProtoPirateTxRxStateTx && ctx) {
|
||||
if(app->txrx->txrx_state == GDRTxRxStateTx && ctx) {
|
||||
if((furi_get_tick() - app->start_tx_time) > emulate_min_tx_time(ctx)) {
|
||||
emu_stop_tx(app);
|
||||
ctx->is_transmitting = false;
|
||||
@@ -842,8 +842,8 @@ static bool plugin_on_event(void* context, SceneManagerEvent event) {
|
||||
consumed = true;
|
||||
break;
|
||||
|
||||
case ProtoPirateCustomEventEmulateExit:
|
||||
if(app->txrx->txrx_state == ProtoPirateTxRxStateTx) {
|
||||
case GDRCustomEventEmulateExit:
|
||||
if(app->txrx->txrx_state == GDRTxRxStateTx) {
|
||||
emu_stop_tx(app);
|
||||
if(ctx) {
|
||||
ctx->is_transmitting = false;
|
||||
@@ -859,7 +859,7 @@ static bool plugin_on_event(void* context, SceneManagerEvent event) {
|
||||
view_commit_model(app->view_about, true);
|
||||
|
||||
if(ctx && ctx->is_transmitting) {
|
||||
if(app->txrx->txrx_state == ProtoPirateTxRxStateTx) {
|
||||
if(app->txrx->txrx_state == GDRTxRxStateTx) {
|
||||
if((app->start_tx_time && ((furi_get_tick() - app->start_tx_time) >
|
||||
emulate_min_tx_time(ctx))) &&
|
||||
ctx->flag_stop_called) {
|
||||
@@ -879,10 +879,10 @@ static bool plugin_on_event(void* context, SceneManagerEvent event) {
|
||||
}
|
||||
|
||||
static void plugin_on_exit(void* context) {
|
||||
ProtoPirateApp* app = context;
|
||||
GDRApp* app = context;
|
||||
|
||||
// Stop any active transmission before tearing down callbacks.
|
||||
if(app->txrx && app->txrx->txrx_state == ProtoPirateTxRxStateTx) {
|
||||
if(app->txrx && app->txrx->txrx_state == GDRTxRxStateTx) {
|
||||
FURI_LOG_I(TAG, "Stopping transmission on exit");
|
||||
if(app->txrx->radio_device) {
|
||||
subghz_devices_stop_async_tx(app->txrx->radio_device);
|
||||
@@ -896,8 +896,8 @@ static void plugin_on_exit(void* context) {
|
||||
if(app->txrx->radio_device) {
|
||||
subghz_devices_idle(app->txrx->radio_device);
|
||||
}
|
||||
app->txrx->txrx_state = ProtoPirateTxRxStateIDLE;
|
||||
} else if(app->txrx && app->txrx->txrx_state != ProtoPirateTxRxStateIDLE) {
|
||||
app->txrx->txrx_state = GDRTxRxStateIDLE;
|
||||
} else if(app->txrx && app->txrx->txrx_state != GDRTxRxStateIDLE) {
|
||||
if(g_host_api && g_host_api->idle) g_host_api->idle(app);
|
||||
}
|
||||
|
||||
@@ -928,12 +928,12 @@ static void plugin_context_release(void* context) {
|
||||
emulate_context_free();
|
||||
}
|
||||
|
||||
static void plugin_set_host_api(const ProtoPirateEmulateHostApi* host_api) {
|
||||
static void plugin_set_host_api(const GDREmulateHostApi* host_api) {
|
||||
g_host_api = host_api;
|
||||
}
|
||||
|
||||
static const ProtoPirateEmulatePlugin protopirate_emulate_plugin = {
|
||||
.plugin_name = "ProtoPirate Emulate",
|
||||
static const GDREmulatePlugin gdr_emulate_plugin = {
|
||||
.plugin_name = "GDR Emulate",
|
||||
.set_host_api = plugin_set_host_api,
|
||||
.on_enter = plugin_on_enter,
|
||||
.on_event = plugin_on_event,
|
||||
@@ -941,14 +941,14 @@ static const ProtoPirateEmulatePlugin protopirate_emulate_plugin = {
|
||||
.context_release = plugin_context_release,
|
||||
};
|
||||
|
||||
static const FlipperAppPluginDescriptor protopirate_emulate_plugin_descriptor = {
|
||||
.appid = PROTOPIRATE_EMULATE_PLUGIN_APP_ID,
|
||||
.ep_api_version = PROTOPIRATE_EMULATE_PLUGIN_API_VERSION,
|
||||
.entry_point = &protopirate_emulate_plugin,
|
||||
static const FlipperAppPluginDescriptor gdr_emulate_plugin_descriptor = {
|
||||
.appid = GDR_EMULATE_PLUGIN_APP_ID,
|
||||
.ep_api_version = GDR_EMULATE_PLUGIN_API_VERSION,
|
||||
.entry_point = &gdr_emulate_plugin,
|
||||
};
|
||||
|
||||
const FlipperAppPluginDescriptor* protopirate_emulate_plugin_ep(void) {
|
||||
return &protopirate_emulate_plugin_descriptor;
|
||||
const FlipperAppPluginDescriptor* gdr_emulate_plugin_ep(void) {
|
||||
return &gdr_emulate_plugin_descriptor;
|
||||
}
|
||||
|
||||
#endif // ENABLE_EMULATE_FEATURE
|
||||
+5
-5
@@ -6,8 +6,8 @@
|
||||
#include <lib/flipper_application/flipper_application.h>
|
||||
#include <gui/scene_manager.h>
|
||||
|
||||
#define PROTOPIRATE_EMULATE_PLUGIN_APP_ID "protopirate_emulate_plugin"
|
||||
#define PROTOPIRATE_EMULATE_PLUGIN_API_VERSION 1U
|
||||
#define GDR_EMULATE_PLUGIN_APP_ID "gdr_emulate_plugin"
|
||||
#define GDR_EMULATE_PLUGIN_API_VERSION 1U
|
||||
|
||||
typedef struct {
|
||||
bool (*radio_init)(void* app);
|
||||
@@ -20,13 +20,13 @@ typedef struct {
|
||||
void (*idle)(void* app);
|
||||
void (*history_release_scratch)(void* app);
|
||||
void (*storage_delete_temp)(void);
|
||||
} ProtoPirateEmulateHostApi;
|
||||
} GDREmulateHostApi;
|
||||
|
||||
typedef struct {
|
||||
const char* plugin_name;
|
||||
void (*set_host_api)(const ProtoPirateEmulateHostApi* host_api);
|
||||
void (*set_host_api)(const GDREmulateHostApi* host_api);
|
||||
void (*on_enter)(void* app);
|
||||
bool (*on_event)(void* app, SceneManagerEvent event);
|
||||
void (*on_exit)(void* app);
|
||||
void (*context_release)(void* app);
|
||||
} ProtoPirateEmulatePlugin;
|
||||
} GDREmulatePlugin;
|
||||
@@ -0,0 +1,65 @@
|
||||
#include "gdr_psa_bf_plugin.h"
|
||||
|
||||
static void plugin_set_host_api(const GDRPsaBfHostApi* api) {
|
||||
(void)api;
|
||||
}
|
||||
|
||||
static bool plugin_needs_bruteforce(void* app, GDRPsaBfContext ctx) {
|
||||
(void)app;
|
||||
(void)ctx;
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool plugin_is_running(void* app) {
|
||||
(void)app;
|
||||
return false;
|
||||
}
|
||||
|
||||
static void plugin_on_scene_enter(void* app, GDRPsaBfContext ctx) {
|
||||
(void)app;
|
||||
(void)ctx;
|
||||
}
|
||||
|
||||
static bool plugin_on_scene_event(void* app, GDRPsaBfContext ctx, SceneManagerEvent event) {
|
||||
(void)app;
|
||||
(void)ctx;
|
||||
(void)event;
|
||||
return false;
|
||||
}
|
||||
|
||||
static void plugin_on_scene_exit(void* app, GDRPsaBfContext ctx) {
|
||||
(void)app;
|
||||
(void)ctx;
|
||||
}
|
||||
|
||||
static bool plugin_widget_left_should_bruteforce(void* app, GDRPsaBfContext ctx) {
|
||||
(void)app;
|
||||
(void)ctx;
|
||||
return false;
|
||||
}
|
||||
|
||||
static void plugin_context_release(void* app) {
|
||||
(void)app;
|
||||
}
|
||||
|
||||
static const GDRPsaBfPlugin gdr_psa_bf_plugin = {
|
||||
.plugin_name = "GDR PSA BF",
|
||||
.set_host_api = plugin_set_host_api,
|
||||
.needs_bruteforce = plugin_needs_bruteforce,
|
||||
.is_running = plugin_is_running,
|
||||
.on_scene_enter = plugin_on_scene_enter,
|
||||
.on_scene_event = plugin_on_scene_event,
|
||||
.on_scene_exit = plugin_on_scene_exit,
|
||||
.widget_left_should_bruteforce = plugin_widget_left_should_bruteforce,
|
||||
.context_release = plugin_context_release,
|
||||
};
|
||||
|
||||
static const FlipperAppPluginDescriptor gdr_psa_bf_plugin_descriptor = {
|
||||
.appid = GDR_PSA_BF_PLUGIN_APP_ID,
|
||||
.ep_api_version = GDR_PSA_BF_PLUGIN_API_VERSION,
|
||||
.entry_point = &gdr_psa_bf_plugin,
|
||||
};
|
||||
|
||||
const FlipperAppPluginDescriptor* gdr_psa_bf_plugin_ep(void) {
|
||||
return &gdr_psa_bf_plugin_descriptor;
|
||||
}
|
||||
+16
-16
@@ -8,17 +8,17 @@
|
||||
|
||||
#include "../../protocols/psa_bf_types.h"
|
||||
|
||||
#define PROTOPIRATE_PSA_BF_PLUGIN_APP_ID "protopirate_psa_bf_plugin"
|
||||
#define PROTOPIRATE_PSA_BF_PLUGIN_API_VERSION 1U
|
||||
#define GDR_PSA_BF_PLUGIN_APP_ID "gdr_psa_bf_plugin"
|
||||
#define GDR_PSA_BF_PLUGIN_API_VERSION 1U
|
||||
|
||||
typedef struct ProtoPirateApp ProtoPirateApp;
|
||||
typedef struct ProtoPirateHistory ProtoPirateHistory;
|
||||
typedef struct GDRApp GDRApp;
|
||||
typedef struct GDRHistory GDRHistory;
|
||||
typedef struct Widget Widget;
|
||||
|
||||
typedef enum {
|
||||
ProtoPiratePsaBfContextReceiverInfo,
|
||||
ProtoPiratePsaBfContextSubDecode,
|
||||
} ProtoPiratePsaBfContext;
|
||||
GDRPsaBfContextReceiverInfo,
|
||||
GDRPsaBfContextSubDecode,
|
||||
} GDRPsaBfContext;
|
||||
|
||||
typedef struct {
|
||||
bool (*ensure_widget)(void* app);
|
||||
@@ -26,7 +26,7 @@ typedef struct {
|
||||
FlipperFormat* (*get_history_flipper_format)(void* app);
|
||||
uint16_t (*get_history_index)(void* app);
|
||||
void (*set_history_index)(void* app, uint16_t idx);
|
||||
ProtoPirateHistory* (*get_history)(void* app);
|
||||
GDRHistory* (*get_history)(void* app);
|
||||
void (*history_set_item_str)(void* app, uint16_t idx, const char* str);
|
||||
void (*patch_flipper_format_on_success)(FlipperFormat* ff, const PsaBfState* state);
|
||||
void (*send_custom_event)(void* app, uint32_t event);
|
||||
@@ -35,16 +35,16 @@ typedef struct {
|
||||
void (*receiver_info_rebuild_widget)(void* app);
|
||||
void (*subdecode_signal_info_refresh)(void* app);
|
||||
void (*scene_previous)(void* app);
|
||||
} ProtoPiratePsaBfHostApi;
|
||||
} GDRPsaBfHostApi;
|
||||
|
||||
typedef struct {
|
||||
const char* plugin_name;
|
||||
void (*set_host_api)(const ProtoPiratePsaBfHostApi* api);
|
||||
bool (*needs_bruteforce)(void* app, ProtoPiratePsaBfContext ctx);
|
||||
void (*set_host_api)(const GDRPsaBfHostApi* api);
|
||||
bool (*needs_bruteforce)(void* app, GDRPsaBfContext ctx);
|
||||
bool (*is_running)(void* app);
|
||||
void (*on_scene_enter)(void* app, ProtoPiratePsaBfContext ctx);
|
||||
bool (*on_scene_event)(void* app, ProtoPiratePsaBfContext ctx, SceneManagerEvent event);
|
||||
void (*on_scene_exit)(void* app, ProtoPiratePsaBfContext ctx);
|
||||
bool (*widget_left_should_bruteforce)(void* app, ProtoPiratePsaBfContext ctx);
|
||||
void (*on_scene_enter)(void* app, GDRPsaBfContext ctx);
|
||||
bool (*on_scene_event)(void* app, GDRPsaBfContext ctx, SceneManagerEvent event);
|
||||
void (*on_scene_exit)(void* app, GDRPsaBfContext ctx);
|
||||
bool (*widget_left_should_bruteforce)(void* app, GDRPsaBfContext ctx);
|
||||
void (*context_release)(void* app);
|
||||
} ProtoPiratePsaBfPlugin;
|
||||
} GDRPsaBfPlugin;
|
||||
@@ -1,65 +0,0 @@
|
||||
#include "protopirate_psa_bf_plugin.h"
|
||||
|
||||
static void plugin_set_host_api(const ProtoPiratePsaBfHostApi* api) {
|
||||
(void)api;
|
||||
}
|
||||
|
||||
static bool plugin_needs_bruteforce(void* app, ProtoPiratePsaBfContext ctx) {
|
||||
(void)app;
|
||||
(void)ctx;
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool plugin_is_running(void* app) {
|
||||
(void)app;
|
||||
return false;
|
||||
}
|
||||
|
||||
static void plugin_on_scene_enter(void* app, ProtoPiratePsaBfContext ctx) {
|
||||
(void)app;
|
||||
(void)ctx;
|
||||
}
|
||||
|
||||
static bool plugin_on_scene_event(void* app, ProtoPiratePsaBfContext ctx, SceneManagerEvent event) {
|
||||
(void)app;
|
||||
(void)ctx;
|
||||
(void)event;
|
||||
return false;
|
||||
}
|
||||
|
||||
static void plugin_on_scene_exit(void* app, ProtoPiratePsaBfContext ctx) {
|
||||
(void)app;
|
||||
(void)ctx;
|
||||
}
|
||||
|
||||
static bool plugin_widget_left_should_bruteforce(void* app, ProtoPiratePsaBfContext ctx) {
|
||||
(void)app;
|
||||
(void)ctx;
|
||||
return false;
|
||||
}
|
||||
|
||||
static void plugin_context_release(void* app) {
|
||||
(void)app;
|
||||
}
|
||||
|
||||
static const ProtoPiratePsaBfPlugin protopirate_psa_bf_plugin = {
|
||||
.plugin_name = "ProtoPirate PSA BF",
|
||||
.set_host_api = plugin_set_host_api,
|
||||
.needs_bruteforce = plugin_needs_bruteforce,
|
||||
.is_running = plugin_is_running,
|
||||
.on_scene_enter = plugin_on_scene_enter,
|
||||
.on_scene_event = plugin_on_scene_event,
|
||||
.on_scene_exit = plugin_on_scene_exit,
|
||||
.widget_left_should_bruteforce = plugin_widget_left_should_bruteforce,
|
||||
.context_release = plugin_context_release,
|
||||
};
|
||||
|
||||
static const FlipperAppPluginDescriptor protopirate_psa_bf_plugin_descriptor = {
|
||||
.appid = PROTOPIRATE_PSA_BF_PLUGIN_APP_ID,
|
||||
.ep_api_version = PROTOPIRATE_PSA_BF_PLUGIN_API_VERSION,
|
||||
.entry_point = &protopirate_psa_bf_plugin,
|
||||
};
|
||||
|
||||
const FlipperAppPluginDescriptor* protopirate_psa_bf_plugin_ep(void) {
|
||||
return &protopirate_psa_bf_plugin_descriptor;
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
// scenes/protopirate_scene.c
|
||||
#include "protopirate_scene.h"
|
||||
|
||||
// Generate scene on_enter handlers array
|
||||
#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_enter,
|
||||
void (*const protopirate_scene_on_enter_handlers[])(void*) = {
|
||||
#include "protopirate_scene_config.h"
|
||||
};
|
||||
#undef ADD_SCENE
|
||||
|
||||
// Generate scene on_event handlers array
|
||||
#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_event,
|
||||
bool (*const protopirate_scene_on_event_handlers[])(void* context, SceneManagerEvent event) = {
|
||||
#include "protopirate_scene_config.h"
|
||||
};
|
||||
#undef ADD_SCENE
|
||||
|
||||
// Generate scene on_exit handlers array
|
||||
#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_exit,
|
||||
void (*const protopirate_scene_on_exit_handlers[])(void* context) = {
|
||||
#include "protopirate_scene_config.h"
|
||||
};
|
||||
#undef ADD_SCENE
|
||||
|
||||
// Initialize scene handlers configuration structure
|
||||
const SceneManagerHandlers protopirate_scene_handlers = {
|
||||
.on_enter_handlers = protopirate_scene_on_enter_handlers,
|
||||
.on_event_handlers = protopirate_scene_on_event_handlers,
|
||||
.on_exit_handlers = protopirate_scene_on_exit_handlers,
|
||||
.scene_num = ProtoPirateSceneNum,
|
||||
};
|
||||
@@ -1,29 +0,0 @@
|
||||
// scenes/protopirate_scene_config.h
|
||||
|
||||
#include "../defines.h"
|
||||
|
||||
ADD_SCENE(protopirate, start, Start)
|
||||
#ifdef ENABLE_SUB_DECODE_SCENE
|
||||
ADD_SCENE(protopirate, sub_decode, SubDecode)
|
||||
#endif
|
||||
ADD_SCENE(protopirate, about, About)
|
||||
#ifdef ENABLE_DUAL_RX_SCENE
|
||||
ADD_SCENE(protopirate, dual_receiver, DualReceiver)
|
||||
ADD_SCENE(protopirate, dual_receiver_config, DualReceiverConfig)
|
||||
#endif
|
||||
#ifdef ENABLE_SHIELD_RX_SCENE
|
||||
ADD_SCENE(protopirate, shield_receiver, ShieldReceiver)
|
||||
ADD_SCENE(protopirate, shield_receiver_config, ShieldReceiverConfig)
|
||||
#endif
|
||||
ADD_SCENE(protopirate, receiver, Receiver)
|
||||
ADD_SCENE(protopirate, receiver_config, ReceiverConfig)
|
||||
ADD_SCENE(protopirate, receiver_info, ReceiverInfo)
|
||||
ADD_SCENE(protopirate, need_saving, NeedSaving)
|
||||
ADD_SCENE(protopirate, saved, Saved)
|
||||
ADD_SCENE(protopirate, saved_info, SavedInfo)
|
||||
#ifdef ENABLE_EMULATE_FEATURE
|
||||
ADD_SCENE(protopirate, emulate, Emulate)
|
||||
#endif
|
||||
#ifdef ENABLE_TIMING_TUNER_SCENE
|
||||
ADD_SCENE(protopirate, timing_tuner, TimingTuner)
|
||||
#endif
|
||||
@@ -1,19 +0,0 @@
|
||||
// scenes/protopirate_scene_saved.c
|
||||
#include "../protopirate_app_i.h"
|
||||
|
||||
#define TAG "ProtoPirateSceneSaved"
|
||||
|
||||
void protopirate_scene_saved_on_enter(void* context) {
|
||||
ProtoPirateApp* app = context;
|
||||
scene_manager_previous_scene(app->scene_manager);
|
||||
}
|
||||
|
||||
bool protopirate_scene_saved_on_event(void* context, SceneManagerEvent event) {
|
||||
UNUSED(context);
|
||||
UNUSED(event);
|
||||
return false;
|
||||
}
|
||||
|
||||
void protopirate_scene_saved_on_exit(void* context) {
|
||||
UNUSED(context);
|
||||
}
|
||||
+83
-83
@@ -1,9 +1,9 @@
|
||||
// views/protopirate_dual_receiver.c
|
||||
#include "protopirate_dual_receiver.h"
|
||||
// views/gdr_dual_receiver.c
|
||||
#include "gdr_dual_receiver.h"
|
||||
|
||||
#ifdef ENABLE_DUAL_RX_SCENE
|
||||
|
||||
#include "../protopirate_history.h"
|
||||
#include "../gdr_history.h"
|
||||
#include <input/input.h>
|
||||
#include <gui/elements.h>
|
||||
#include <furi.h>
|
||||
@@ -15,9 +15,9 @@
|
||||
#define STATUS_TOP_Y (LIST_HEIGHT) // 36
|
||||
#define SUBGHZ_RAW_THRESHOLD_MIN -90.0f
|
||||
|
||||
struct ProtoPirateDualReceiver {
|
||||
struct GDRDualReceiver {
|
||||
View* view;
|
||||
ProtoPirateDualReceiverCallback callback;
|
||||
GDRDualReceiverCallback callback;
|
||||
void* context;
|
||||
};
|
||||
|
||||
@@ -30,52 +30,52 @@ typedef struct {
|
||||
} DualChainStatus;
|
||||
|
||||
typedef struct {
|
||||
ProtoPirateHistory* history;
|
||||
GDRHistory* history;
|
||||
FuriMutex* history_mutex;
|
||||
uint8_t list_offset;
|
||||
uint8_t history_item;
|
||||
DualChainStatus chain[2];
|
||||
FuriString* history_stat_str;
|
||||
FuriString* draw_scratch;
|
||||
} ProtoPirateDualReceiverModel;
|
||||
} GDRDualReceiverModel;
|
||||
|
||||
static size_t protopirate_view_dual_receiver_item_count(ProtoPirateDualReceiverModel* model) {
|
||||
return model->history ? protopirate_history_get_item(model->history) : 0U;
|
||||
static size_t gdr_view_dual_receiver_item_count(GDRDualReceiverModel* model) {
|
||||
return model->history ? gdr_history_get_item(model->history) : 0U;
|
||||
}
|
||||
|
||||
void protopirate_view_dual_receiver_set_callback(
|
||||
ProtoPirateDualReceiver* receiver,
|
||||
ProtoPirateDualReceiverCallback callback,
|
||||
void gdr_view_dual_receiver_set_callback(
|
||||
GDRDualReceiver* receiver,
|
||||
GDRDualReceiverCallback callback,
|
||||
void* context) {
|
||||
furi_check(receiver);
|
||||
receiver->callback = callback;
|
||||
receiver->context = context;
|
||||
}
|
||||
|
||||
void protopirate_view_dual_receiver_set_history(
|
||||
ProtoPirateDualReceiver* receiver,
|
||||
ProtoPirateHistory* history) {
|
||||
void gdr_view_dual_receiver_set_history(
|
||||
GDRDualReceiver* receiver,
|
||||
GDRHistory* history) {
|
||||
furi_check(receiver);
|
||||
with_view_model(
|
||||
receiver->view,
|
||||
ProtoPirateDualReceiverModel * model,
|
||||
GDRDualReceiverModel * model,
|
||||
{ model->history = history; },
|
||||
true);
|
||||
}
|
||||
|
||||
void protopirate_view_dual_receiver_set_history_mutex(
|
||||
ProtoPirateDualReceiver* receiver,
|
||||
void gdr_view_dual_receiver_set_history_mutex(
|
||||
GDRDualReceiver* receiver,
|
||||
FuriMutex* mutex) {
|
||||
furi_check(receiver);
|
||||
with_view_model(
|
||||
receiver->view,
|
||||
ProtoPirateDualReceiverModel * model,
|
||||
GDRDualReceiverModel * model,
|
||||
{ model->history_mutex = mutex; },
|
||||
false);
|
||||
}
|
||||
|
||||
void protopirate_view_dual_receiver_set_chain_status(
|
||||
ProtoPirateDualReceiver* receiver,
|
||||
void gdr_view_dual_receiver_set_chain_status(
|
||||
GDRDualReceiver* receiver,
|
||||
uint8_t slot,
|
||||
const char* tag,
|
||||
const char* frequency_str,
|
||||
@@ -85,7 +85,7 @@ void protopirate_view_dual_receiver_set_chain_status(
|
||||
if(slot > 1) return;
|
||||
with_view_model(
|
||||
receiver->view,
|
||||
ProtoPirateDualReceiverModel * model,
|
||||
GDRDualReceiverModel * model,
|
||||
{
|
||||
snprintf(model->chain[slot].tag, sizeof(model->chain[slot].tag), "%s", tag);
|
||||
furi_string_set_str(model->chain[slot].frequency_str, frequency_str);
|
||||
@@ -95,38 +95,38 @@ void protopirate_view_dual_receiver_set_chain_status(
|
||||
true);
|
||||
}
|
||||
|
||||
void protopirate_view_dual_receiver_set_rssi(
|
||||
ProtoPirateDualReceiver* receiver,
|
||||
void gdr_view_dual_receiver_set_rssi(
|
||||
GDRDualReceiver* receiver,
|
||||
uint8_t slot,
|
||||
float rssi) {
|
||||
furi_check(receiver);
|
||||
if(slot > 1) return;
|
||||
with_view_model(
|
||||
receiver->view,
|
||||
ProtoPirateDualReceiverModel * model,
|
||||
GDRDualReceiverModel * model,
|
||||
{ model->chain[slot].rssi = rssi; },
|
||||
true);
|
||||
}
|
||||
|
||||
void protopirate_view_dual_receiver_set_history_stat(
|
||||
ProtoPirateDualReceiver* receiver,
|
||||
void gdr_view_dual_receiver_set_history_stat(
|
||||
GDRDualReceiver* receiver,
|
||||
const char* history_stat_str) {
|
||||
furi_check(receiver);
|
||||
with_view_model(
|
||||
receiver->view,
|
||||
ProtoPirateDualReceiverModel * model,
|
||||
GDRDualReceiverModel * model,
|
||||
{ furi_string_set_str(model->history_stat_str, history_stat_str); },
|
||||
true);
|
||||
}
|
||||
|
||||
static void protopirate_view_dual_receiver_update_offset(ProtoPirateDualReceiver* receiver) {
|
||||
static void gdr_view_dual_receiver_update_offset(GDRDualReceiver* receiver) {
|
||||
with_view_model(
|
||||
receiver->view,
|
||||
ProtoPirateDualReceiverModel * model,
|
||||
GDRDualReceiverModel * model,
|
||||
{
|
||||
size_t history_item = model->history_item;
|
||||
size_t list_offset = model->list_offset;
|
||||
size_t item_count = protopirate_view_dual_receiver_item_count(model);
|
||||
size_t item_count = gdr_view_dual_receiver_item_count(model);
|
||||
|
||||
if(history_item < list_offset) {
|
||||
model->list_offset = history_item;
|
||||
@@ -146,7 +146,7 @@ static void protopirate_view_dual_receiver_update_offset(ProtoPirateDualReceiver
|
||||
true);
|
||||
}
|
||||
|
||||
static void protopirate_view_dual_receiver_draw_frame(Canvas* canvas, uint16_t idx, bool scrollbar) {
|
||||
static void gdr_view_dual_receiver_draw_frame(Canvas* canvas, uint16_t idx, bool scrollbar) {
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
canvas_draw_box(canvas, 0, 0 + idx * FRAME_HEIGHT, scrollbar ? 122 : 127, FRAME_HEIGHT);
|
||||
|
||||
@@ -161,7 +161,7 @@ static void protopirate_view_dual_receiver_draw_frame(Canvas* canvas, uint16_t i
|
||||
}
|
||||
|
||||
static void
|
||||
protopirate_view_dual_receiver_draw_rssi(Canvas* canvas, float rssi, uint8_t x, uint8_t y) {
|
||||
gdr_view_dual_receiver_draw_rssi(Canvas* canvas, float rssi, uint8_t x, uint8_t y) {
|
||||
uint8_t segments = 0;
|
||||
if(rssi > SUBGHZ_RAW_THRESHOLD_MIN) {
|
||||
float v = rssi - SUBGHZ_RAW_THRESHOLD_MIN;
|
||||
@@ -178,7 +178,7 @@ static void
|
||||
}
|
||||
}
|
||||
|
||||
static void protopirate_view_dual_receiver_draw_status_row(
|
||||
static void gdr_view_dual_receiver_draw_status_row(
|
||||
Canvas* canvas,
|
||||
DualChainStatus* chain,
|
||||
uint8_t baseline_y) {
|
||||
@@ -191,11 +191,11 @@ static void protopirate_view_dual_receiver_draw_status_row(
|
||||
furi_string_get_cstr(chain->frequency_str),
|
||||
furi_string_get_cstr(chain->modulation_str));
|
||||
canvas_draw_str(canvas, 0, baseline_y, row);
|
||||
protopirate_view_dual_receiver_draw_rssi(canvas, chain->rssi, 108, baseline_y);
|
||||
gdr_view_dual_receiver_draw_rssi(canvas, chain->rssi, 108, baseline_y);
|
||||
}
|
||||
|
||||
static void
|
||||
protopirate_view_dual_receiver_draw(Canvas* canvas, ProtoPirateDualReceiverModel* model) {
|
||||
gdr_view_dual_receiver_draw(Canvas* canvas, GDRDualReceiverModel* model) {
|
||||
canvas_clear(canvas);
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
@@ -204,19 +204,19 @@ static void
|
||||
furi_mutex_acquire(model->history_mutex, FuriWaitForever);
|
||||
}
|
||||
|
||||
size_t item_count = protopirate_view_dual_receiver_item_count(model);
|
||||
size_t item_count = gdr_view_dual_receiver_item_count(model);
|
||||
bool scrollbar = item_count > MENU_ITEMS;
|
||||
|
||||
if(item_count > 0) {
|
||||
size_t shift_position = model->list_offset;
|
||||
for(size_t i = 0; i < MIN(item_count, (size_t)MENU_ITEMS); i++) {
|
||||
size_t idx = shift_position + i;
|
||||
protopirate_history_get_text_item_menu(model->history, model->draw_scratch, idx);
|
||||
gdr_history_get_text_item_menu(model->history, model->draw_scratch, idx);
|
||||
elements_string_fit_width(
|
||||
canvas, model->draw_scratch, scrollbar ? MAX_LEN_PX - 6 : MAX_LEN_PX);
|
||||
|
||||
if(model->history_item == idx) {
|
||||
protopirate_view_dual_receiver_draw_frame(canvas, i, scrollbar);
|
||||
gdr_view_dual_receiver_draw_frame(canvas, i, scrollbar);
|
||||
} else {
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
}
|
||||
@@ -257,13 +257,13 @@ static void
|
||||
AlignTop,
|
||||
furi_string_get_cstr(model->history_stat_str));
|
||||
|
||||
protopirate_view_dual_receiver_draw_status_row(canvas, &model->chain[0], STATUS_TOP_Y + 10);
|
||||
protopirate_view_dual_receiver_draw_status_row(canvas, &model->chain[1], STATUS_TOP_Y + 20);
|
||||
gdr_view_dual_receiver_draw_status_row(canvas, &model->chain[0], STATUS_TOP_Y + 10);
|
||||
gdr_view_dual_receiver_draw_status_row(canvas, &model->chain[1], STATUS_TOP_Y + 20);
|
||||
}
|
||||
|
||||
static bool protopirate_view_dual_receiver_input(InputEvent* event, void* context) {
|
||||
static bool gdr_view_dual_receiver_input(InputEvent* event, void* context) {
|
||||
furi_check(context);
|
||||
ProtoPirateDualReceiver* receiver = context;
|
||||
GDRDualReceiver* receiver = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event->type == InputTypeShort || event->type == InputTypeLong ||
|
||||
@@ -272,32 +272,32 @@ static bool protopirate_view_dual_receiver_input(InputEvent* event, void* contex
|
||||
case InputKeyUp:
|
||||
with_view_model(
|
||||
receiver->view,
|
||||
ProtoPirateDualReceiverModel * model,
|
||||
GDRDualReceiverModel * model,
|
||||
{
|
||||
if(model->history_item > 0) model->history_item--;
|
||||
},
|
||||
true);
|
||||
protopirate_view_dual_receiver_update_offset(receiver);
|
||||
gdr_view_dual_receiver_update_offset(receiver);
|
||||
consumed = true;
|
||||
break;
|
||||
case InputKeyDown:
|
||||
with_view_model(
|
||||
receiver->view,
|
||||
ProtoPirateDualReceiverModel * model,
|
||||
GDRDualReceiverModel * model,
|
||||
{
|
||||
size_t item_count = protopirate_view_dual_receiver_item_count(model);
|
||||
size_t item_count = gdr_view_dual_receiver_item_count(model);
|
||||
if(item_count > 0 && model->history_item < item_count - 1) {
|
||||
model->history_item++;
|
||||
}
|
||||
},
|
||||
true);
|
||||
protopirate_view_dual_receiver_update_offset(receiver);
|
||||
gdr_view_dual_receiver_update_offset(receiver);
|
||||
consumed = true;
|
||||
break;
|
||||
case InputKeyLeft:
|
||||
if(receiver->callback) {
|
||||
receiver->callback(
|
||||
ProtoPirateCustomEventViewDualReceiverConfig, receiver->context);
|
||||
GDRCustomEventViewDualReceiverConfig, receiver->context);
|
||||
}
|
||||
consumed = true;
|
||||
break;
|
||||
@@ -306,12 +306,12 @@ static bool protopirate_view_dual_receiver_input(InputEvent* event, void* contex
|
||||
bool do_delete = false;
|
||||
with_view_model(
|
||||
receiver->view,
|
||||
ProtoPirateDualReceiverModel * model,
|
||||
{ do_delete = protopirate_view_dual_receiver_item_count(model) > 0; },
|
||||
GDRDualReceiverModel * model,
|
||||
{ do_delete = gdr_view_dual_receiver_item_count(model) > 0; },
|
||||
false);
|
||||
if(do_delete && receiver->callback) {
|
||||
receiver->callback(
|
||||
ProtoPirateCustomEventViewDualReceiverDeleteItem, receiver->context);
|
||||
GDRCustomEventViewDualReceiverDeleteItem, receiver->context);
|
||||
}
|
||||
}
|
||||
consumed = true;
|
||||
@@ -320,18 +320,18 @@ static bool protopirate_view_dual_receiver_input(InputEvent* event, void* contex
|
||||
bool do_ok = false;
|
||||
with_view_model(
|
||||
receiver->view,
|
||||
ProtoPirateDualReceiverModel * model,
|
||||
{ do_ok = protopirate_view_dual_receiver_item_count(model) > 0; },
|
||||
GDRDualReceiverModel * model,
|
||||
{ do_ok = gdr_view_dual_receiver_item_count(model) > 0; },
|
||||
false);
|
||||
if(do_ok && receiver->callback) {
|
||||
receiver->callback(ProtoPirateCustomEventViewDualReceiverOK, receiver->context);
|
||||
receiver->callback(GDRCustomEventViewDualReceiverOK, receiver->context);
|
||||
}
|
||||
consumed = true;
|
||||
break;
|
||||
}
|
||||
case InputKeyBack:
|
||||
if(receiver->callback) {
|
||||
receiver->callback(ProtoPirateCustomEventViewDualReceiverBack, receiver->context);
|
||||
receiver->callback(GDRCustomEventViewDualReceiverBack, receiver->context);
|
||||
}
|
||||
consumed = true;
|
||||
break;
|
||||
@@ -343,22 +343,22 @@ static bool protopirate_view_dual_receiver_input(InputEvent* event, void* contex
|
||||
return consumed;
|
||||
}
|
||||
|
||||
ProtoPirateDualReceiver* protopirate_view_dual_receiver_alloc(void) {
|
||||
ProtoPirateDualReceiver* receiver = malloc(sizeof(ProtoPirateDualReceiver));
|
||||
GDRDualReceiver* gdr_view_dual_receiver_alloc(void) {
|
||||
GDRDualReceiver* receiver = malloc(sizeof(GDRDualReceiver));
|
||||
furi_check(receiver);
|
||||
receiver->callback = NULL;
|
||||
receiver->context = NULL;
|
||||
|
||||
receiver->view = view_alloc();
|
||||
view_allocate_model(
|
||||
receiver->view, ViewModelTypeLocking, sizeof(ProtoPirateDualReceiverModel));
|
||||
receiver->view, ViewModelTypeLocking, sizeof(GDRDualReceiverModel));
|
||||
view_set_context(receiver->view, receiver);
|
||||
view_set_draw_callback(receiver->view, (ViewDrawCallback)protopirate_view_dual_receiver_draw);
|
||||
view_set_input_callback(receiver->view, protopirate_view_dual_receiver_input);
|
||||
view_set_draw_callback(receiver->view, (ViewDrawCallback)gdr_view_dual_receiver_draw);
|
||||
view_set_input_callback(receiver->view, gdr_view_dual_receiver_input);
|
||||
|
||||
with_view_model(
|
||||
receiver->view,
|
||||
ProtoPirateDualReceiverModel * model,
|
||||
GDRDualReceiverModel * model,
|
||||
{
|
||||
model->history = NULL;
|
||||
model->history_mutex = NULL;
|
||||
@@ -379,11 +379,11 @@ ProtoPirateDualReceiver* protopirate_view_dual_receiver_alloc(void) {
|
||||
return receiver;
|
||||
}
|
||||
|
||||
void protopirate_view_dual_receiver_free(ProtoPirateDualReceiver* receiver) {
|
||||
void gdr_view_dual_receiver_free(GDRDualReceiver* receiver) {
|
||||
furi_check(receiver);
|
||||
with_view_model(
|
||||
receiver->view,
|
||||
ProtoPirateDualReceiverModel * model,
|
||||
GDRDualReceiverModel * model,
|
||||
{
|
||||
furi_string_free(model->history_stat_str);
|
||||
furi_string_free(model->draw_scratch);
|
||||
@@ -397,16 +397,16 @@ void protopirate_view_dual_receiver_free(ProtoPirateDualReceiver* receiver) {
|
||||
free(receiver);
|
||||
}
|
||||
|
||||
View* protopirate_view_dual_receiver_get_view(ProtoPirateDualReceiver* receiver) {
|
||||
View* gdr_view_dual_receiver_get_view(GDRDualReceiver* receiver) {
|
||||
furi_check(receiver);
|
||||
return receiver->view;
|
||||
}
|
||||
|
||||
void protopirate_view_dual_receiver_reset_menu(ProtoPirateDualReceiver* receiver) {
|
||||
void gdr_view_dual_receiver_reset_menu(GDRDualReceiver* receiver) {
|
||||
furi_check(receiver);
|
||||
with_view_model(
|
||||
receiver->view,
|
||||
ProtoPirateDualReceiverModel * model,
|
||||
GDRDualReceiverModel * model,
|
||||
{
|
||||
model->history = NULL;
|
||||
model->history_item = 0;
|
||||
@@ -415,17 +415,17 @@ void protopirate_view_dual_receiver_reset_menu(ProtoPirateDualReceiver* receiver
|
||||
false);
|
||||
}
|
||||
|
||||
void protopirate_view_dual_receiver_sync_menu_from_history(
|
||||
ProtoPirateDualReceiver* receiver,
|
||||
ProtoPirateHistory* history) {
|
||||
void gdr_view_dual_receiver_sync_menu_from_history(
|
||||
GDRDualReceiver* receiver,
|
||||
GDRHistory* history) {
|
||||
furi_check(receiver);
|
||||
furi_check(history);
|
||||
with_view_model(
|
||||
receiver->view,
|
||||
ProtoPirateDualReceiverModel * model,
|
||||
GDRDualReceiverModel * model,
|
||||
{
|
||||
model->history = history;
|
||||
size_t item_count = protopirate_view_dual_receiver_item_count(model);
|
||||
size_t item_count = gdr_view_dual_receiver_item_count(model);
|
||||
if(item_count == 0) {
|
||||
model->history_item = 0;
|
||||
model->list_offset = 0;
|
||||
@@ -435,43 +435,43 @@ void protopirate_view_dual_receiver_sync_menu_from_history(
|
||||
}
|
||||
},
|
||||
true);
|
||||
protopirate_view_dual_receiver_update_offset(receiver);
|
||||
gdr_view_dual_receiver_update_offset(receiver);
|
||||
}
|
||||
|
||||
uint16_t protopirate_view_dual_receiver_get_idx_menu(ProtoPirateDualReceiver* receiver) {
|
||||
uint16_t gdr_view_dual_receiver_get_idx_menu(GDRDualReceiver* receiver) {
|
||||
furi_check(receiver);
|
||||
uint16_t idx = 0;
|
||||
with_view_model(
|
||||
receiver->view,
|
||||
ProtoPirateDualReceiverModel * model,
|
||||
GDRDualReceiverModel * model,
|
||||
{ idx = model->history_item; },
|
||||
false);
|
||||
return idx;
|
||||
}
|
||||
|
||||
void protopirate_view_dual_receiver_set_idx_menu(ProtoPirateDualReceiver* receiver, uint16_t idx) {
|
||||
void gdr_view_dual_receiver_set_idx_menu(GDRDualReceiver* receiver, uint16_t idx) {
|
||||
furi_check(receiver);
|
||||
with_view_model(
|
||||
receiver->view,
|
||||
ProtoPirateDualReceiverModel * model,
|
||||
GDRDualReceiverModel * model,
|
||||
{
|
||||
model->history_item = idx;
|
||||
size_t item_count = protopirate_view_dual_receiver_item_count(model);
|
||||
size_t item_count = gdr_view_dual_receiver_item_count(model);
|
||||
if(model->history_item >= item_count) {
|
||||
model->history_item = item_count > 0 ? item_count - 1 : 0;
|
||||
}
|
||||
},
|
||||
true);
|
||||
protopirate_view_dual_receiver_update_offset(receiver);
|
||||
gdr_view_dual_receiver_update_offset(receiver);
|
||||
}
|
||||
|
||||
void protopirate_view_dual_receiver_delete_item(ProtoPirateDualReceiver* receiver, uint16_t idx) {
|
||||
void gdr_view_dual_receiver_delete_item(GDRDualReceiver* receiver, uint16_t idx) {
|
||||
furi_check(receiver);
|
||||
with_view_model(
|
||||
receiver->view,
|
||||
ProtoPirateDualReceiverModel * model,
|
||||
GDRDualReceiverModel * model,
|
||||
{
|
||||
size_t item_count = protopirate_view_dual_receiver_item_count(model);
|
||||
size_t item_count = gdr_view_dual_receiver_item_count(model);
|
||||
if(idx <= item_count) {
|
||||
if(item_count == 0) {
|
||||
model->history = NULL;
|
||||
@@ -487,7 +487,7 @@ void protopirate_view_dual_receiver_delete_item(ProtoPirateDualReceiver* receive
|
||||
}
|
||||
},
|
||||
true);
|
||||
protopirate_view_dual_receiver_update_offset(receiver);
|
||||
gdr_view_dual_receiver_update_offset(receiver);
|
||||
}
|
||||
|
||||
#endif // ENABLE_DUAL_RX_SCENE
|
||||
@@ -0,0 +1,59 @@
|
||||
// views/gdr_dual_receiver.h
|
||||
#pragma once
|
||||
|
||||
#include "../helpers/gdr_types.h"
|
||||
|
||||
#ifdef ENABLE_DUAL_RX_SCENE
|
||||
|
||||
#include <gui/view.h>
|
||||
|
||||
typedef struct GDRDualReceiver GDRDualReceiver;
|
||||
typedef struct GDRHistory GDRHistory;
|
||||
|
||||
typedef void (*GDRDualReceiverCallback)(GDRCustomEvent event, void* context);
|
||||
|
||||
GDRDualReceiver* gdr_view_dual_receiver_alloc(void);
|
||||
void gdr_view_dual_receiver_free(GDRDualReceiver* receiver);
|
||||
View* gdr_view_dual_receiver_get_view(GDRDualReceiver* receiver);
|
||||
|
||||
void gdr_view_dual_receiver_set_callback(
|
||||
GDRDualReceiver* receiver,
|
||||
GDRDualReceiverCallback callback,
|
||||
void* context);
|
||||
|
||||
void gdr_view_dual_receiver_set_history(
|
||||
GDRDualReceiver* receiver,
|
||||
GDRHistory* history);
|
||||
|
||||
void gdr_view_dual_receiver_set_history_mutex(
|
||||
GDRDualReceiver* receiver,
|
||||
FuriMutex* mutex);
|
||||
|
||||
void gdr_view_dual_receiver_set_chain_status(
|
||||
GDRDualReceiver* receiver,
|
||||
uint8_t slot,
|
||||
const char* tag,
|
||||
const char* frequency_str,
|
||||
const char* modulation_str,
|
||||
bool external);
|
||||
|
||||
void gdr_view_dual_receiver_set_rssi(
|
||||
GDRDualReceiver* receiver,
|
||||
uint8_t slot,
|
||||
float rssi);
|
||||
|
||||
void gdr_view_dual_receiver_set_history_stat(
|
||||
GDRDualReceiver* receiver,
|
||||
const char* history_stat_str);
|
||||
|
||||
void gdr_view_dual_receiver_sync_menu_from_history(
|
||||
GDRDualReceiver* receiver,
|
||||
GDRHistory* history);
|
||||
|
||||
void gdr_view_dual_receiver_reset_menu(GDRDualReceiver* receiver);
|
||||
|
||||
uint16_t gdr_view_dual_receiver_get_idx_menu(GDRDualReceiver* receiver);
|
||||
void gdr_view_dual_receiver_set_idx_menu(GDRDualReceiver* receiver, uint16_t idx);
|
||||
void gdr_view_dual_receiver_delete_item(GDRDualReceiver* receiver, uint16_t idx);
|
||||
|
||||
#endif // ENABLE_DUAL_RX_SCENE
|
||||
+128
-128
@@ -1,12 +1,12 @@
|
||||
// views/protopirate_receiver.c
|
||||
#include "protopirate_receiver.h"
|
||||
#include "../protopirate_history.h"
|
||||
#include "../protopirate_app_i.h"
|
||||
// views/gdr_receiver.c
|
||||
#include "gdr_receiver.h"
|
||||
#include "../gdr_history.h"
|
||||
#include "../gdr_app_i.h"
|
||||
#include <input/input.h>
|
||||
#include <gui/elements.h>
|
||||
#include <furi.h>
|
||||
|
||||
#include "proto_pirate_icons.h"
|
||||
#include "gdr_icons.h"
|
||||
|
||||
#define FRAME_HEIGHT 12
|
||||
#define MAX_LEN_PX 112
|
||||
@@ -14,14 +14,14 @@
|
||||
#define UNLOCK_CNT 3
|
||||
#define SUBGHZ_RAW_THRESHOLD_MIN -90.0f
|
||||
|
||||
struct ProtoPirateReceiver {
|
||||
struct GDRReceiver {
|
||||
View* view;
|
||||
ProtoPirateReceiverCallback callback;
|
||||
GDRReceiverCallback callback;
|
||||
void* context;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
ProtoPirateHistory* history;
|
||||
GDRHistory* history;
|
||||
FuriMutex* history_mutex;
|
||||
uint8_t list_offset;
|
||||
uint8_t history_item;
|
||||
@@ -32,12 +32,12 @@ typedef struct {
|
||||
FuriString* history_stat_str;
|
||||
FuriString* draw_scratch;
|
||||
bool external_radio;
|
||||
ProtoPirateLock lock;
|
||||
GDRLock lock;
|
||||
uint8_t lock_count;
|
||||
uint8_t animation_frame;
|
||||
bool dolphin_view;
|
||||
bool sub_decode_mode;
|
||||
} ProtoPirateReceiverModel;
|
||||
} GDRReceiverModel;
|
||||
|
||||
typedef struct {
|
||||
int8_t x;
|
||||
@@ -63,24 +63,24 @@ static const RadarPoint radar_points[] = {
|
||||
{30, -12},
|
||||
};
|
||||
|
||||
static size_t protopirate_view_receiver_item_count(ProtoPirateReceiverModel* model) {
|
||||
static size_t gdr_view_receiver_item_count(GDRReceiverModel* model) {
|
||||
furi_check(model);
|
||||
return model->history ? protopirate_history_get_item(model->history) : 0U;
|
||||
return model->history ? gdr_history_get_item(model->history) : 0U;
|
||||
}
|
||||
|
||||
static void protopirate_view_receiver_history_lock(ProtoPirateReceiverModel* model) {
|
||||
static void gdr_view_receiver_history_lock(GDRReceiverModel* model) {
|
||||
if(model->history_mutex) {
|
||||
furi_mutex_acquire(model->history_mutex, FuriWaitForever);
|
||||
}
|
||||
}
|
||||
|
||||
static void protopirate_view_receiver_history_unlock(ProtoPirateReceiverModel* model) {
|
||||
static void gdr_view_receiver_history_unlock(GDRReceiverModel* model) {
|
||||
if(model->history_mutex) {
|
||||
furi_mutex_release(model->history_mutex);
|
||||
}
|
||||
}
|
||||
|
||||
static void protopirate_view_radar_point(
|
||||
static void gdr_view_radar_point(
|
||||
uint8_t center_x,
|
||||
uint8_t center_y,
|
||||
uint8_t radius,
|
||||
@@ -92,7 +92,7 @@ static void protopirate_view_radar_point(
|
||||
*y = center_y + ((int32_t)radius * p->y) / 32;
|
||||
}
|
||||
|
||||
static void protopirate_view_rssi_draw(Canvas* canvas, ProtoPirateReceiverModel* model) {
|
||||
static void gdr_view_rssi_draw(Canvas* canvas, GDRReceiverModel* model) {
|
||||
furi_check(model);
|
||||
uint8_t u_rssi = 0;
|
||||
|
||||
@@ -116,65 +116,65 @@ static void protopirate_view_rssi_draw(Canvas* canvas, ProtoPirateReceiverModel*
|
||||
}
|
||||
}
|
||||
|
||||
void protopirate_view_receiver_set_sub_decode_mode(
|
||||
ProtoPirateReceiver* receiver,
|
||||
void gdr_view_receiver_set_sub_decode_mode(
|
||||
GDRReceiver* receiver,
|
||||
bool sub_decode_mode) {
|
||||
furi_check(receiver);
|
||||
with_view_model(
|
||||
receiver->view,
|
||||
ProtoPirateReceiverModel * model,
|
||||
GDRReceiverModel * model,
|
||||
{ model->sub_decode_mode = sub_decode_mode; },
|
||||
true);
|
||||
}
|
||||
|
||||
void protopirate_view_receiver_set_rssi(ProtoPirateReceiver* receiver, float rssi) {
|
||||
void gdr_view_receiver_set_rssi(GDRReceiver* receiver, float rssi) {
|
||||
furi_check(receiver);
|
||||
with_view_model(
|
||||
receiver->view, ProtoPirateReceiverModel * model, { model->rssi = rssi; }, true);
|
||||
receiver->view, GDRReceiverModel * model, { model->rssi = rssi; }, true);
|
||||
}
|
||||
|
||||
void protopirate_view_receiver_set_lock(ProtoPirateReceiver* receiver, ProtoPirateLock lock) {
|
||||
void gdr_view_receiver_set_lock(GDRReceiver* receiver, GDRLock lock) {
|
||||
furi_check(receiver);
|
||||
with_view_model(
|
||||
receiver->view, ProtoPirateReceiverModel * model, { model->lock = lock; }, true);
|
||||
receiver->view, GDRReceiverModel * model, { model->lock = lock; }, true);
|
||||
}
|
||||
|
||||
void protopirate_view_receiver_set_autosave(ProtoPirateReceiver* receiver, bool auto_save) {
|
||||
void gdr_view_receiver_set_autosave(GDRReceiver* receiver, bool auto_save) {
|
||||
furi_check(receiver);
|
||||
with_view_model(
|
||||
receiver->view, ProtoPirateReceiverModel * model, { model->auto_save = auto_save; }, true);
|
||||
receiver->view, GDRReceiverModel * model, { model->auto_save = auto_save; }, true);
|
||||
}
|
||||
|
||||
void protopirate_view_receiver_set_history_mutex(
|
||||
ProtoPirateReceiver* receiver,
|
||||
void gdr_view_receiver_set_history_mutex(
|
||||
GDRReceiver* receiver,
|
||||
FuriMutex* history_mutex) {
|
||||
furi_check(receiver);
|
||||
with_view_model(
|
||||
receiver->view,
|
||||
ProtoPirateReceiverModel * model,
|
||||
GDRReceiverModel * model,
|
||||
{ model->history_mutex = history_mutex; },
|
||||
false);
|
||||
}
|
||||
|
||||
void protopirate_view_receiver_set_callback(
|
||||
ProtoPirateReceiver* receiver,
|
||||
ProtoPirateReceiverCallback callback,
|
||||
void gdr_view_receiver_set_callback(
|
||||
GDRReceiver* receiver,
|
||||
GDRReceiverCallback callback,
|
||||
void* context) {
|
||||
furi_check(receiver);
|
||||
receiver->callback = callback;
|
||||
receiver->context = context;
|
||||
}
|
||||
|
||||
static void protopirate_view_receiver_update_offset(ProtoPirateReceiver* receiver) {
|
||||
static void gdr_view_receiver_update_offset(GDRReceiver* receiver) {
|
||||
furi_check(receiver);
|
||||
with_view_model(
|
||||
receiver->view,
|
||||
ProtoPirateReceiverModel * model,
|
||||
GDRReceiverModel * model,
|
||||
{
|
||||
protopirate_view_receiver_history_lock(model);
|
||||
gdr_view_receiver_history_lock(model);
|
||||
size_t history_item = model->history_item;
|
||||
size_t list_offset = model->list_offset;
|
||||
size_t item_count = protopirate_view_receiver_item_count(model);
|
||||
size_t item_count = gdr_view_receiver_item_count(model);
|
||||
|
||||
if(history_item < list_offset) {
|
||||
model->list_offset = history_item;
|
||||
@@ -190,13 +190,13 @@ static void protopirate_view_receiver_update_offset(ProtoPirateReceiver* receive
|
||||
model->list_offset = max_offset;
|
||||
}
|
||||
}
|
||||
protopirate_view_receiver_history_unlock(model);
|
||||
gdr_view_receiver_history_unlock(model);
|
||||
},
|
||||
true);
|
||||
}
|
||||
|
||||
void protopirate_view_receiver_add_data_statusbar(
|
||||
ProtoPirateReceiver* receiver,
|
||||
void gdr_view_receiver_add_data_statusbar(
|
||||
GDRReceiver* receiver,
|
||||
const char* frequency_str,
|
||||
const char* preset_str,
|
||||
const char* history_stat_str,
|
||||
@@ -204,7 +204,7 @@ void protopirate_view_receiver_add_data_statusbar(
|
||||
furi_check(receiver);
|
||||
with_view_model(
|
||||
receiver->view,
|
||||
ProtoPirateReceiverModel * model,
|
||||
GDRReceiverModel * model,
|
||||
{
|
||||
furi_string_set_str(model->frequency_str, frequency_str);
|
||||
furi_string_set_str(model->preset_str, preset_str);
|
||||
@@ -214,7 +214,7 @@ void protopirate_view_receiver_add_data_statusbar(
|
||||
true);
|
||||
}
|
||||
|
||||
static void protopirate_view_receiver_draw_frame(Canvas* canvas, uint16_t idx, bool scrollbar) {
|
||||
static void gdr_view_receiver_draw_frame(Canvas* canvas, uint16_t idx, bool scrollbar) {
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
canvas_draw_box(canvas, 0, 0 + idx * FRAME_HEIGHT, scrollbar ? 122 : 127, FRAME_HEIGHT);
|
||||
|
||||
@@ -228,8 +228,8 @@ static void protopirate_view_receiver_draw_frame(Canvas* canvas, uint16_t idx, b
|
||||
canvas_draw_dot(canvas, scrollbar ? 121 : 126, (0 + idx * FRAME_HEIGHT) + 11);
|
||||
}
|
||||
|
||||
void protopirate_view_receiver_draw(Canvas* canvas, ProtoPirateReceiverModel* model) {
|
||||
protopirate_view_receiver_history_lock(model);
|
||||
void gdr_view_receiver_draw(Canvas* canvas, GDRReceiverModel* model) {
|
||||
gdr_view_receiver_history_lock(model);
|
||||
canvas_clear(canvas);
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
@@ -238,7 +238,7 @@ void protopirate_view_receiver_draw(Canvas* canvas, ProtoPirateReceiverModel* mo
|
||||
static uint8_t animation_frame = 0;
|
||||
animation_frame = (animation_frame + 1) % 96;
|
||||
|
||||
size_t item_count = protopirate_view_receiver_item_count(model);
|
||||
size_t item_count = gdr_view_receiver_item_count(model);
|
||||
bool scrollbar = item_count > MENU_ITEMS;
|
||||
|
||||
if(!model->sub_decode_mode) {
|
||||
@@ -246,7 +246,7 @@ void protopirate_view_receiver_draw(Canvas* canvas, ProtoPirateReceiverModel* mo
|
||||
elements_button_left(canvas, "Config");
|
||||
|
||||
// Draw RSSI
|
||||
protopirate_view_rssi_draw(canvas, model);
|
||||
gdr_view_rssi_draw(canvas, model);
|
||||
}
|
||||
|
||||
//Draw To Unlock, Locked etc...
|
||||
@@ -263,7 +263,7 @@ void protopirate_view_receiver_draw(Canvas* canvas, ProtoPirateReceiverModel* mo
|
||||
canvas_draw_icon(canvas, 16, 13, &I_WarningDolphin_45x42);
|
||||
canvas_draw_dot(canvas, 17, 61);
|
||||
} else {
|
||||
if(model->lock == ProtoPirateLockOn) {
|
||||
if(model->lock == GDRLockOn) {
|
||||
canvas_draw_icon(canvas, 64, 55, &I_Lock_7x8);
|
||||
canvas_draw_str(canvas, 74, 62, "Locked");
|
||||
} else {
|
||||
@@ -280,12 +280,12 @@ void protopirate_view_receiver_draw(Canvas* canvas, ProtoPirateReceiverModel* mo
|
||||
|
||||
for(size_t i = 0; i < MIN(item_count, MENU_ITEMS); i++) {
|
||||
size_t idx = shift_position + i;
|
||||
protopirate_history_get_text_item_menu(model->history, model->draw_scratch, idx);
|
||||
gdr_history_get_text_item_menu(model->history, model->draw_scratch, idx);
|
||||
elements_string_fit_width(
|
||||
canvas, model->draw_scratch, scrollbar ? MAX_LEN_PX - 6 : MAX_LEN_PX);
|
||||
|
||||
if(model->history_item == idx) {
|
||||
protopirate_view_receiver_draw_frame(canvas, i, scrollbar);
|
||||
gdr_view_receiver_draw_frame(canvas, i, scrollbar);
|
||||
} else {
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
}
|
||||
@@ -318,7 +318,7 @@ void protopirate_view_receiver_draw(Canvas* canvas, ProtoPirateReceiverModel* mo
|
||||
for(uint8_t i = 0; i < dot_count; i++) {
|
||||
int32_t x;
|
||||
int32_t y;
|
||||
protopirate_view_radar_point(
|
||||
gdr_view_radar_point(
|
||||
center_x, center_y, base_radius, i * step + wave * 2, &x, &y);
|
||||
if(x > 0 && x < 128 && y > 0 && y < 48) {
|
||||
canvas_draw_dot(canvas, x, y);
|
||||
@@ -331,7 +331,7 @@ void protopirate_view_receiver_draw(Canvas* canvas, ProtoPirateReceiverModel* mo
|
||||
for(uint8_t i = 0; i < COUNT_OF(radar_points); i += 2) {
|
||||
int32_t x;
|
||||
int32_t y;
|
||||
protopirate_view_radar_point(center_x, center_y, 15, i, &x, &y);
|
||||
gdr_view_radar_point(center_x, center_y, 15, i, &x, &y);
|
||||
canvas_draw_dot(canvas, x, y);
|
||||
}
|
||||
|
||||
@@ -339,14 +339,14 @@ void protopirate_view_receiver_draw(Canvas* canvas, ProtoPirateReceiverModel* mo
|
||||
for(int8_t i = -1; i <= 1; i++) {
|
||||
int32_t x;
|
||||
int32_t y;
|
||||
protopirate_view_radar_point(
|
||||
gdr_view_radar_point(
|
||||
center_x, center_y, i ? 20 : 22, sweep_idx + i, &x, &y);
|
||||
canvas_draw_line(canvas, center_x, center_y, x, y);
|
||||
}
|
||||
for(uint8_t i = 1; i <= 8; i++) {
|
||||
int32_t x;
|
||||
int32_t y;
|
||||
protopirate_view_radar_point(
|
||||
gdr_view_radar_point(
|
||||
center_x, center_y, 22 - i * 2, sweep_idx - i, &x, &y);
|
||||
if(i < 3 || !(i & 1)) canvas_draw_dot(canvas, x, y);
|
||||
}
|
||||
@@ -387,31 +387,31 @@ void protopirate_view_receiver_draw(Canvas* canvas, ProtoPirateReceiverModel* mo
|
||||
canvas, 110 - canvas_string_width(canvas, auto_save_text), 7, auto_save_text);
|
||||
}
|
||||
}
|
||||
protopirate_view_receiver_history_unlock(model);
|
||||
gdr_view_receiver_history_unlock(model);
|
||||
}
|
||||
|
||||
bool protopirate_view_receiver_input(InputEvent* event, void* context) {
|
||||
bool gdr_view_receiver_input(InputEvent* event, void* context) {
|
||||
furi_check(context);
|
||||
ProtoPirateReceiver* receiver = context;
|
||||
GDRReceiver* receiver = context;
|
||||
|
||||
bool consumed = false;
|
||||
|
||||
ProtoPirateLock lock;
|
||||
GDRLock lock;
|
||||
with_view_model(
|
||||
receiver->view, ProtoPirateReceiverModel * model, { lock = model->lock; }, false);
|
||||
receiver->view, GDRReceiverModel * model, { lock = model->lock; }, false);
|
||||
|
||||
if(lock == ProtoPirateLockOn) {
|
||||
if(lock == GDRLockOn) {
|
||||
bool do_unlock_cb = false;
|
||||
|
||||
with_view_model(
|
||||
receiver->view,
|
||||
ProtoPirateReceiverModel * model,
|
||||
GDRReceiverModel * model,
|
||||
{
|
||||
if(event->key == InputKeyBack) {
|
||||
if(event->type == InputTypeShort) {
|
||||
model->lock_count++;
|
||||
if(model->lock_count >= UNLOCK_CNT) {
|
||||
model->lock = ProtoPirateLockOff;
|
||||
model->lock = GDRLockOff;
|
||||
model->lock_count = 0;
|
||||
do_unlock_cb = true;
|
||||
}
|
||||
@@ -425,7 +425,7 @@ bool protopirate_view_receiver_input(InputEvent* event, void* context) {
|
||||
true);
|
||||
|
||||
if(do_unlock_cb && receiver->callback) {
|
||||
receiver->callback(ProtoPirateCustomEventViewReceiverUnlock, receiver->context);
|
||||
receiver->callback(GDRCustomEventViewReceiverUnlock, receiver->context);
|
||||
}
|
||||
|
||||
consumed = true;
|
||||
@@ -436,35 +436,35 @@ bool protopirate_view_receiver_input(InputEvent* event, void* context) {
|
||||
case InputKeyUp:
|
||||
with_view_model(
|
||||
receiver->view,
|
||||
ProtoPirateReceiverModel * model,
|
||||
GDRReceiverModel * model,
|
||||
{
|
||||
if(model->history_item > 0) {
|
||||
model->history_item--;
|
||||
}
|
||||
},
|
||||
true);
|
||||
protopirate_view_receiver_update_offset(receiver);
|
||||
gdr_view_receiver_update_offset(receiver);
|
||||
consumed = true;
|
||||
break;
|
||||
case InputKeyDown:
|
||||
with_view_model(
|
||||
receiver->view,
|
||||
ProtoPirateReceiverModel * model,
|
||||
GDRReceiverModel * model,
|
||||
{
|
||||
protopirate_view_receiver_history_lock(model);
|
||||
size_t item_count = protopirate_view_receiver_item_count(model);
|
||||
gdr_view_receiver_history_lock(model);
|
||||
size_t item_count = gdr_view_receiver_item_count(model);
|
||||
if(item_count > 0 && model->history_item < item_count - 1) {
|
||||
model->history_item++;
|
||||
}
|
||||
protopirate_view_receiver_history_unlock(model);
|
||||
gdr_view_receiver_history_unlock(model);
|
||||
},
|
||||
true);
|
||||
protopirate_view_receiver_update_offset(receiver);
|
||||
gdr_view_receiver_update_offset(receiver);
|
||||
consumed = true;
|
||||
break;
|
||||
case InputKeyLeft:
|
||||
if(receiver->callback) {
|
||||
receiver->callback(ProtoPirateCustomEventViewReceiverConfig, receiver->context);
|
||||
receiver->callback(GDRCustomEventViewReceiverConfig, receiver->context);
|
||||
}
|
||||
consumed = true;
|
||||
break;
|
||||
@@ -473,16 +473,16 @@ bool protopirate_view_receiver_input(InputEvent* event, void* context) {
|
||||
bool do_delete_cb = false;
|
||||
with_view_model(
|
||||
receiver->view,
|
||||
ProtoPirateReceiverModel * model,
|
||||
GDRReceiverModel * model,
|
||||
{
|
||||
protopirate_view_receiver_history_lock(model);
|
||||
do_delete_cb = protopirate_view_receiver_item_count(model) > 0;
|
||||
protopirate_view_receiver_history_unlock(model);
|
||||
gdr_view_receiver_history_lock(model);
|
||||
do_delete_cb = gdr_view_receiver_item_count(model) > 0;
|
||||
gdr_view_receiver_history_unlock(model);
|
||||
},
|
||||
false);
|
||||
if(do_delete_cb && receiver->callback) {
|
||||
receiver->callback(
|
||||
ProtoPirateCustomEventViewReceiverDeleteItem, receiver->context);
|
||||
GDRCustomEventViewReceiverDeleteItem, receiver->context);
|
||||
}
|
||||
}
|
||||
consumed = true;
|
||||
@@ -493,37 +493,37 @@ bool protopirate_view_receiver_input(InputEvent* event, void* context) {
|
||||
/* Read-only: do not redraw */
|
||||
with_view_model(
|
||||
receiver->view,
|
||||
ProtoPirateReceiverModel * model,
|
||||
GDRReceiverModel * model,
|
||||
{
|
||||
protopirate_view_receiver_history_lock(model);
|
||||
size_t item_count = protopirate_view_receiver_item_count(model);
|
||||
gdr_view_receiver_history_lock(model);
|
||||
size_t item_count = gdr_view_receiver_item_count(model);
|
||||
|
||||
if(item_count > 0) {
|
||||
do_ok_cb = true;
|
||||
} else if(event->type == InputTypeLong) {
|
||||
do_toggle = true;
|
||||
}
|
||||
protopirate_view_receiver_history_unlock(model);
|
||||
gdr_view_receiver_history_unlock(model);
|
||||
},
|
||||
false);
|
||||
/* Only redraw if we actually changed dolphin_view */
|
||||
if(do_toggle) {
|
||||
with_view_model(
|
||||
receiver->view,
|
||||
ProtoPirateReceiverModel * model,
|
||||
GDRReceiverModel * model,
|
||||
{ model->dolphin_view = !model->dolphin_view; },
|
||||
true);
|
||||
}
|
||||
|
||||
if(do_ok_cb && receiver->callback) {
|
||||
receiver->callback(ProtoPirateCustomEventViewReceiverOK, receiver->context);
|
||||
receiver->callback(GDRCustomEventViewReceiverOK, receiver->context);
|
||||
}
|
||||
|
||||
consumed = true;
|
||||
break;
|
||||
case InputKeyBack:
|
||||
if(receiver->callback) {
|
||||
receiver->callback(ProtoPirateCustomEventViewReceiverBack, receiver->context);
|
||||
receiver->callback(GDRCustomEventViewReceiverBack, receiver->context);
|
||||
}
|
||||
consumed = true;
|
||||
break;
|
||||
@@ -535,30 +535,30 @@ bool protopirate_view_receiver_input(InputEvent* event, void* context) {
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void protopirate_view_receiver_enter(void* context) {
|
||||
void gdr_view_receiver_enter(void* context) {
|
||||
furi_check(context);
|
||||
UNUSED(context);
|
||||
}
|
||||
|
||||
void protopirate_view_receiver_exit(void* context) {
|
||||
void gdr_view_receiver_exit(void* context) {
|
||||
furi_check(context);
|
||||
UNUSED(context);
|
||||
}
|
||||
|
||||
ProtoPirateReceiver* protopirate_view_receiver_alloc(bool auto_save) {
|
||||
ProtoPirateReceiver* receiver = malloc(sizeof(ProtoPirateReceiver));
|
||||
GDRReceiver* gdr_view_receiver_alloc(bool auto_save) {
|
||||
GDRReceiver* receiver = malloc(sizeof(GDRReceiver));
|
||||
|
||||
receiver->view = view_alloc();
|
||||
view_allocate_model(receiver->view, ViewModelTypeLocking, sizeof(ProtoPirateReceiverModel));
|
||||
view_allocate_model(receiver->view, ViewModelTypeLocking, sizeof(GDRReceiverModel));
|
||||
view_set_context(receiver->view, receiver);
|
||||
view_set_draw_callback(receiver->view, (ViewDrawCallback)protopirate_view_receiver_draw);
|
||||
view_set_input_callback(receiver->view, protopirate_view_receiver_input);
|
||||
view_set_enter_callback(receiver->view, protopirate_view_receiver_enter);
|
||||
view_set_exit_callback(receiver->view, protopirate_view_receiver_exit);
|
||||
view_set_draw_callback(receiver->view, (ViewDrawCallback)gdr_view_receiver_draw);
|
||||
view_set_input_callback(receiver->view, gdr_view_receiver_input);
|
||||
view_set_enter_callback(receiver->view, gdr_view_receiver_enter);
|
||||
view_set_exit_callback(receiver->view, gdr_view_receiver_exit);
|
||||
|
||||
with_view_model(
|
||||
receiver->view,
|
||||
ProtoPirateReceiverModel * model,
|
||||
GDRReceiverModel * model,
|
||||
{
|
||||
model->history = NULL;
|
||||
model->history_mutex = NULL;
|
||||
@@ -571,7 +571,7 @@ ProtoPirateReceiver* protopirate_view_receiver_alloc(bool auto_save) {
|
||||
model->history_item = 0;
|
||||
model->rssi = -127.0f;
|
||||
model->external_radio = false;
|
||||
model->lock = ProtoPirateLockOff;
|
||||
model->lock = GDRLockOff;
|
||||
model->lock_count = 0;
|
||||
model->auto_save = auto_save;
|
||||
model->animation_frame = 0;
|
||||
@@ -583,12 +583,12 @@ ProtoPirateReceiver* protopirate_view_receiver_alloc(bool auto_save) {
|
||||
return receiver;
|
||||
}
|
||||
|
||||
void protopirate_view_receiver_free(ProtoPirateReceiver* receiver) {
|
||||
void gdr_view_receiver_free(GDRReceiver* receiver) {
|
||||
furi_check(receiver);
|
||||
|
||||
with_view_model(
|
||||
receiver->view,
|
||||
ProtoPirateReceiverModel * model,
|
||||
GDRReceiverModel * model,
|
||||
{
|
||||
furi_string_free(model->frequency_str);
|
||||
furi_string_free(model->preset_str);
|
||||
@@ -601,11 +601,11 @@ void protopirate_view_receiver_free(ProtoPirateReceiver* receiver) {
|
||||
free(receiver);
|
||||
}
|
||||
|
||||
void protopirate_view_receiver_reset_menu(ProtoPirateReceiver* receiver) {
|
||||
void gdr_view_receiver_reset_menu(GDRReceiver* receiver) {
|
||||
furi_check(receiver);
|
||||
with_view_model(
|
||||
receiver->view,
|
||||
ProtoPirateReceiverModel * model,
|
||||
GDRReceiverModel * model,
|
||||
{
|
||||
model->history = NULL;
|
||||
model->history_mutex = NULL;
|
||||
@@ -615,19 +615,19 @@ void protopirate_view_receiver_reset_menu(ProtoPirateReceiver* receiver) {
|
||||
false);
|
||||
}
|
||||
|
||||
void protopirate_view_receiver_sync_menu_from_history(
|
||||
ProtoPirateReceiver* receiver,
|
||||
ProtoPirateHistory* history) {
|
||||
void gdr_view_receiver_sync_menu_from_history(
|
||||
GDRReceiver* receiver,
|
||||
GDRHistory* history) {
|
||||
furi_check(receiver);
|
||||
furi_check(history);
|
||||
|
||||
with_view_model(
|
||||
receiver->view,
|
||||
ProtoPirateReceiverModel * model,
|
||||
GDRReceiverModel * model,
|
||||
{
|
||||
protopirate_view_receiver_history_lock(model);
|
||||
gdr_view_receiver_history_lock(model);
|
||||
model->history = history;
|
||||
size_t item_count = protopirate_view_receiver_item_count(model);
|
||||
size_t item_count = gdr_view_receiver_item_count(model);
|
||||
if(item_count == 0) {
|
||||
model->history_item = 0;
|
||||
model->list_offset = 0;
|
||||
@@ -639,20 +639,20 @@ void protopirate_view_receiver_sync_menu_from_history(
|
||||
model->list_offset = item_count - 1;
|
||||
}
|
||||
}
|
||||
protopirate_view_receiver_history_unlock(model);
|
||||
gdr_view_receiver_history_unlock(model);
|
||||
},
|
||||
true);
|
||||
protopirate_view_receiver_update_offset(receiver);
|
||||
gdr_view_receiver_update_offset(receiver);
|
||||
}
|
||||
|
||||
void protopirate_view_receiver_pop_first_menu_item(ProtoPirateReceiver* receiver) {
|
||||
void gdr_view_receiver_pop_first_menu_item(GDRReceiver* receiver) {
|
||||
furi_check(receiver);
|
||||
with_view_model(
|
||||
receiver->view,
|
||||
ProtoPirateReceiverModel * model,
|
||||
GDRReceiverModel * model,
|
||||
{
|
||||
protopirate_view_receiver_history_lock(model);
|
||||
size_t item_count = protopirate_view_receiver_item_count(model);
|
||||
gdr_view_receiver_history_lock(model);
|
||||
size_t item_count = gdr_view_receiver_item_count(model);
|
||||
if(item_count > 0) {
|
||||
if(model->history_item > 0) {
|
||||
model->history_item--;
|
||||
@@ -661,21 +661,21 @@ void protopirate_view_receiver_pop_first_menu_item(ProtoPirateReceiver* receiver
|
||||
model->list_offset = item_count > 0 ? item_count - 1 : 0;
|
||||
}
|
||||
}
|
||||
protopirate_view_receiver_history_unlock(model);
|
||||
gdr_view_receiver_history_unlock(model);
|
||||
},
|
||||
true);
|
||||
protopirate_view_receiver_update_offset(receiver);
|
||||
gdr_view_receiver_update_offset(receiver);
|
||||
}
|
||||
|
||||
void protopirate_view_receiver_delete_item(ProtoPirateReceiver* receiver, uint16_t idx) {
|
||||
void gdr_view_receiver_delete_item(GDRReceiver* receiver, uint16_t idx) {
|
||||
furi_check(receiver);
|
||||
|
||||
with_view_model(
|
||||
receiver->view,
|
||||
ProtoPirateReceiverModel * model,
|
||||
GDRReceiverModel * model,
|
||||
{
|
||||
protopirate_view_receiver_history_lock(model);
|
||||
size_t item_count = protopirate_view_receiver_item_count(model);
|
||||
gdr_view_receiver_history_lock(model);
|
||||
size_t item_count = gdr_view_receiver_item_count(model);
|
||||
if(idx <= item_count) {
|
||||
if(item_count == 0) {
|
||||
model->history = NULL;
|
||||
@@ -693,49 +693,49 @@ void protopirate_view_receiver_delete_item(ProtoPirateReceiver* receiver, uint16
|
||||
}
|
||||
}
|
||||
}
|
||||
protopirate_view_receiver_history_unlock(model);
|
||||
gdr_view_receiver_history_unlock(model);
|
||||
},
|
||||
true);
|
||||
protopirate_view_receiver_update_offset(receiver);
|
||||
gdr_view_receiver_update_offset(receiver);
|
||||
}
|
||||
|
||||
void protopirate_view_receiver_append_menu_row_from_history(
|
||||
ProtoPirateReceiver* receiver,
|
||||
ProtoPirateHistory* history,
|
||||
void gdr_view_receiver_append_menu_row_from_history(
|
||||
GDRReceiver* receiver,
|
||||
GDRHistory* history,
|
||||
uint16_t idx) {
|
||||
furi_check(receiver);
|
||||
furi_check(history);
|
||||
UNUSED(idx);
|
||||
protopirate_view_receiver_sync_menu_from_history(receiver, history);
|
||||
gdr_view_receiver_sync_menu_from_history(receiver, history);
|
||||
}
|
||||
|
||||
View* protopirate_view_receiver_get_view(ProtoPirateReceiver* receiver) {
|
||||
View* gdr_view_receiver_get_view(GDRReceiver* receiver) {
|
||||
furi_check(receiver);
|
||||
return receiver->view;
|
||||
}
|
||||
|
||||
uint16_t protopirate_view_receiver_get_idx_menu(ProtoPirateReceiver* receiver) {
|
||||
uint16_t gdr_view_receiver_get_idx_menu(GDRReceiver* receiver) {
|
||||
furi_check(receiver);
|
||||
uint16_t idx = 0;
|
||||
with_view_model(
|
||||
receiver->view, ProtoPirateReceiverModel * model, { idx = model->history_item; }, false);
|
||||
receiver->view, GDRReceiverModel * model, { idx = model->history_item; }, false);
|
||||
return idx;
|
||||
}
|
||||
|
||||
void protopirate_view_receiver_set_idx_menu(ProtoPirateReceiver* receiver, uint16_t idx) {
|
||||
void gdr_view_receiver_set_idx_menu(GDRReceiver* receiver, uint16_t idx) {
|
||||
furi_check(receiver);
|
||||
with_view_model(
|
||||
receiver->view,
|
||||
ProtoPirateReceiverModel * model,
|
||||
GDRReceiverModel * model,
|
||||
{
|
||||
protopirate_view_receiver_history_lock(model);
|
||||
gdr_view_receiver_history_lock(model);
|
||||
model->history_item = idx;
|
||||
size_t item_count = protopirate_view_receiver_item_count(model);
|
||||
size_t item_count = gdr_view_receiver_item_count(model);
|
||||
if(model->history_item >= item_count) {
|
||||
model->history_item = item_count > 0 ? item_count - 1 : 0;
|
||||
}
|
||||
protopirate_view_receiver_history_unlock(model);
|
||||
gdr_view_receiver_history_unlock(model);
|
||||
},
|
||||
true);
|
||||
protopirate_view_receiver_update_offset(receiver);
|
||||
gdr_view_receiver_update_offset(receiver);
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user