mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-04-24 03:29:57 -07:00
Merge branch 'dev' of https://github.com/Dmitry422/unleashed-firmware into dev
This commit is contained in:
102
CHANGELOG.md
102
CHANGELOG.md
@@ -1,93 +1,23 @@
|
||||
## Main changes
|
||||
- Current API: 86.0
|
||||
**WARNING! After install of this version your Desktop (fav apps) and LCD & Notifications settings will be reset to default values, please configure them again after this update!** (this is required due to big updates on that parts and config struct changes)
|
||||
* SubGHz: Add **Feron** protocol (static 32 bit) **full support** (by @xMasterX)
|
||||
* SubGHz: Add **Revers RB2 / RB2M Protocol** (static 64 bit) **full support** with add manually (by @xMasterX)
|
||||
* SubGHz: **Fix Hollarm protocol with more verification**
|
||||
* SubGHz: **Fix GangQi protocol** (by @DoberBit and @mishamyte (who spent 2 weeks on this))
|
||||
* SubGHz: **Came Atomo button hold simulation with full cycle** simulation (to allow proper pairing with receiver)
|
||||
* SubGHz: Add **Prastel (42bit static code)** support (OFW PR 4178 by @pmazzini)
|
||||
* Desktop: **Add support for Favorite App - Ok Long** (Warning! Old favourites apps list will be reset!) (PR #886 | by @DrEverr)
|
||||
* Display: **LCD Color Inversion** (Settings - LCD and Notifications - LCD Inversion) (PR #887 #893 | by @Dmitry422)
|
||||
* Display: **Night Shift Feature** (dimming backlight in selected time interval) (PR #885 | by @Dmitry422)
|
||||
* Display: **Сombining RGB Backlight mod** (by @quen0n) and original backlight support **in one firmware** (+ Rainbow/Wave effect (based on @Willy-JL idea)) (PR #877 #881 #890 | by @Dmitry422) - (**To enable RGB Backlight support go into Notifications settings**)
|
||||
* NFC: Use default UL/UL-C pwd/key as default value for key input (PR #891 | by @mishamyte)
|
||||
* OFW: LFRFID - **EM4305 support**
|
||||
* OFW: **Universal IR signal selection**
|
||||
* OFW: **BadUSB: Mouse control**
|
||||
* OFW: **Pinning of settings options**
|
||||
* OFW: NFC app now can launch MFKey32
|
||||
* OFW: BadUSB arbitrary key combinations
|
||||
* OFW PR 4136: BadUSB: Full USB/BLE parameter customization, UI improvements, and more (by @Willy-JL)
|
||||
* OFW: NFC - Added naming for DESFire cards + fix MF3ICD40 cards unable to be read
|
||||
* Apps: Add **FindMyFlipper to system apps and allow autostart** on system boot [app by @MatthewKuKanich](https://github.com/MatthewKuKanich/FindMyFlipper) and autoloader by @Willy-JL - to use app please check how to add keys in [app repo](https://github.com/MatthewKuKanich/FindMyFlipper)
|
||||
* README Update: Enhanced Visuals & Navigation (PR #871 #872 | by @m-xim)
|
||||
* Docs: Update FAQ.md (PR #865 | by @mi-lrn)
|
||||
* Input: **Vibro on Button press option** (PR #867 | by @Dmitry422)
|
||||
* Power: **Option to limit battery charging** (suppress charging on selected charge level) (PR #867 | by @Dmitry422) (idea and example by @oltenxyz)
|
||||
* iButton: TM01x Dallas write support (PR #899 | by @Leptopt1los)
|
||||
* SubGHz: Add keeloq ironlogic (aka il100) smart clone cloners support (thanks to Vitaly for RAWs)
|
||||
* SubGHz: Fix CAME 24bit decoder
|
||||
* SubGHz: Add 462.750 MHz to default subghz freqs list
|
||||
* SubGHz: Tune holtek ht12x to decode holtek only and not conflict with came 12bit
|
||||
* SubGHz: Fix Rename scene bug, that was replacing file name with random name when Rename is opened then closed then opened again
|
||||
* NFC: Ultralight C - Attempt of authentication with default key (PR #898 | by @mishamyte)
|
||||
* OFW PR 4210: Infrared: Add text scroll to remote buttons (by @956MB)
|
||||
* OFW PR 4205: fix sample durations when using external CC1101 (by @Aerosnail)
|
||||
* OFW PR 4206: Stop JS PWM on exit (by @portasynthinca3)
|
||||
* OFW PR 4212: Remove stupid "!" that broke subghz chat cli (by @GameLord2011)
|
||||
* Apps: **Check out more Apps updates and fixes by following** [this link](https://github.com/xMasterX/all-the-plugins/commits/dev)
|
||||
## Other changes
|
||||
* SubGHz: Move hardcoded extra modulations to user config - uncomment them in setting_user.example and remove .example from filename
|
||||
* SubGHz: Various bugfixes and experimental options (rolling counter overflow) (by @xMasterX)
|
||||
* Anims: Disable winter anims
|
||||
* NFC: mfclassic poller fix early key reuse in dictionary attack state machine (by @noproto)
|
||||
* OFW: RC fixes
|
||||
* OFW: Desktop: Fix freeze on boot if PIN set
|
||||
* OFW PR 4189: USB-UART bridge fix (by @portasynthinca3)
|
||||
* OFW: FBT: Fix for Python 3.13
|
||||
* OFW: sdk: bump API to force re-upload for the catalog
|
||||
* OFW: SDK: Fix missing RECORD_CLI define
|
||||
* OFW: Fix NULL dereference in CLI completions
|
||||
* OFW PR 4181: vcp, cli: Handle Tx/Rx events before Connect/Disconnect + extra fixes (by @portasynthinca3)
|
||||
* OFW: BLE: Slightly increase mfg_data size
|
||||
* OFW: fbt: Deterministic STARTUP order & additional checks
|
||||
* OFW: JS: Update and fix docs, fix Number.toString() with decimals
|
||||
* OFW: New JS value destructuring
|
||||
* OFW: Docs: Fix doxygen references from PR 4168
|
||||
* OFW: BLE advertising improvements
|
||||
* OFW: **New CLI architecture**
|
||||
* OFW: **CLI autocomplete and other sugar**
|
||||
* OFW: CLI commands in fals and threads
|
||||
* OFW: cli: fixed `free_blocks` command
|
||||
* OFW: docs: badusb arbitrary modkey chains
|
||||
* OFW: Separate cli_shell into toolbox
|
||||
* OFW: Move JS modules to new arg parser
|
||||
* OFW: Application chaining
|
||||
* OFW: Fix DWARF dead code elimination and linking
|
||||
* OFW: NFC: Fix crash on ISO15693-3 save when memory is empty or cannot be read
|
||||
* OFW: Reduced ieee754 parser size
|
||||
* OFW: Added Doom animation (by @doomwastaken)
|
||||
* OFW PR 4133: add nfc apdu cli command back (by @leommxj)
|
||||
* OFW: NFC: Support DESFire Transaction MAC file type (by @Willy-JL)
|
||||
* OFW: NFC: Fix NDEF parser for MIFARE Classic (by @Willy-JL)
|
||||
* OFW: GUI: Fix widget text scroll with 256+ lines (by @Willy-JL)
|
||||
* OFW: Infrared: Fix universals sending (by @Willy-JL)
|
||||
* OFW: HID Ble: increased stack and improvements (by @doomwastaken)
|
||||
* OFW: Stricter constness for const data (by @hedger)
|
||||
* OFW PR 4017: Alarm improvements: Snooze, timeouts, and dismissing from the locked state (by @Astrrra)
|
||||
* OFW: fix: flipper detected before it was rebooted
|
||||
* OFW: NFC: FeliCa Protocol Expose Read Block API and Allow Specifying Service
|
||||
* OFW: LFRFID: Fix Detection Conflict Between Securakey and Noralsy Format (by @zinongli)
|
||||
* OFW: Stdio API improvements
|
||||
* OFW: GUI: Widget view extra options for JS
|
||||
* OFW: Update heap implementation
|
||||
* OFW: Updated Button Panel
|
||||
* OFW: UART framing mode selection
|
||||
* OFW: gpio: clear irq status before calling user handler
|
||||
* OFW: Fix 5V on GPIO
|
||||
* OFW: Fixed repeat in subghz tx_from_file command
|
||||
* OFW: LFRFID: Noralsy Format/Brand
|
||||
* OFW: Faster di card reading
|
||||
* OFW: vscode: disabled auto-update for clangd since correct version is in the toolchain
|
||||
* OFW: Furi, USB, BLE, Debug: various bug fixes and improvements
|
||||
* OFW: EventLoop unsubscribe fix
|
||||
* OFW: nfc: Enable MFUL sync poller to be provided with passwords
|
||||
* OFW: ST25TB poller mode check
|
||||
* OFW: JS features & bugfixes (SDK 0.2) **Existing Widget JS module was removed and replaced with new ofw gui/widget module, old apps using widget may be incompatible now!**
|
||||
* OFW: Infrared: increase max carrier limit
|
||||
* OFW: Ensure that `furi_record_create` is passed a non-NULL data pointer
|
||||
* OFW: Update mbedtls & expose AES
|
||||
* OFW: Add the Showtime animation
|
||||
* Desktop: DEBUG - fix desktop anim switch override by favourite apps
|
||||
* CLI: Various fixes (by @WillyJL)
|
||||
* BadUSB: Fix key combos main keys being case sensitive (by @WillyJL)
|
||||
* System: log level none after update
|
||||
* Docs: Some updates on subghz remotes programming
|
||||
<br><br>
|
||||
#### Known NFC post-refactor regressions list:
|
||||
- Mifare Mini clones reading is broken (original mini working fine) (OFW)
|
||||
|
||||
@@ -155,7 +155,7 @@ Thanks to Official team (to their SubGHz Developer, Skorp) for implementing supp
|
||||
> | Came_Space | FAAC_RC,XT | Kingates_Stylo4k | Pantera | Tomahawk_TZ-9030 |
|
||||
> | Cenmax | FAAC_SLH | KGB/Subaru | Pantera_CLK | Tomahawk_Z,X_3-5 |
|
||||
> | Cenmax_St-5 | Faraon | Leopard | Pantera_XS/Jaguar | ZX-730-750-1055 |
|
||||
> | Cenmax_St-7 | Genius_Bravo | Magic_1 | Partisan_RX | |
|
||||
> | Cenmax_St-7 | Genius_Bravo | Magic_1 | Partisan_RX | IL-100(Smart) |
|
||||
> | Centurion | Gibidi | Magic_2 | Reff | |
|
||||
> | Monarch | Jolly Motors | Magic_3 | Sheriff | |
|
||||
> </details>
|
||||
@@ -173,7 +173,7 @@ Thanks to Official team (to their SubGHz Developer, Skorp) for implementing supp
|
||||
- Hay21 (dynamic 21 bit) with button parsing
|
||||
- Nero Radio 57bit (+ 56bit support)
|
||||
- CAME 12bit/24bit encoder fixes (Fixes are now merged in OFW)
|
||||
- Keeloq: Dea Mio, Genius Bravo, GSN, HCS101, AN-Motors, JCM Tech, MHouse, Nice Smilo, DTM Neo, FAAC RC,XT, Mutancode, Normstahl, Beninca + Allmatic, Stilmatic, CAME Space, Aprimatic (model TR and similar), Centurion Nova (thanks Carlos !), Hormann EcoStar, Novoferm, Sommer, Monarch (thanks @ashphx !), Jolly Motors (thanks @pkooiman !)
|
||||
- Keeloq: Dea Mio, Genius Bravo, GSN, HCS101, AN-Motors, JCM Tech, MHouse, Nice Smilo, DTM Neo, FAAC RC,XT, Mutancode, Normstahl, Beninca + Allmatic, Stilmatic, CAME Space, Aprimatic (model TR and similar), Centurion Nova (thanks Carlos !), Hormann EcoStar, Novoferm, Sommer, Monarch (thanks @ashphx !), Jolly Motors (thanks @pkooiman !), IL-100(Smart) (thx Vitaly for RAWs)
|
||||
</details>
|
||||
|
||||
<details>
|
||||
|
||||
@@ -612,11 +612,13 @@ void subghz_device_cc1101_ext_start_async_rx(
|
||||
furi_hal_bus_enable(FuriHalBusTIM17);
|
||||
|
||||
// Configure TIM
|
||||
LL_TIM_InitTypeDef TIM_InitStruct = {0};
|
||||
//Set the timer resolution to 2 us
|
||||
LL_TIM_SetPrescaler(TIM17, (64 << 1) - 1);
|
||||
LL_TIM_SetCounterMode(TIM17, LL_TIM_COUNTERMODE_UP);
|
||||
LL_TIM_SetAutoReload(TIM17, 0xFFFF);
|
||||
LL_TIM_SetClockDivision(TIM17, LL_TIM_CLOCKDIVISION_DIV1);
|
||||
TIM_InitStruct.Prescaler = (64 << 1) - 1;
|
||||
TIM_InitStruct.CounterMode = LL_TIM_COUNTERMODE_UP;
|
||||
TIM_InitStruct.Autoreload = 0xFFFF;
|
||||
TIM_InitStruct.ClockDivision = LL_TIM_CLOCKDIVISION_DIV1;
|
||||
LL_TIM_Init(TIM17, &TIM_InitStruct);
|
||||
|
||||
// Timer: advanced
|
||||
LL_TIM_SetClockSource(TIM17, LL_TIM_CLOCKSOURCE_INTERNAL);
|
||||
|
||||
@@ -213,9 +213,7 @@ static int32_t ducky_parse_line(BadUsbScript* bad_usb, FuriString* line) {
|
||||
|
||||
// Main key
|
||||
char next_char = *line_cstr;
|
||||
uint16_t main_key = ducky_get_keycode_by_name(line_cstr);
|
||||
if(!main_key && next_char) main_key = BADUSB_ASCII_TO_KEY(bad_usb, next_char);
|
||||
key = modifiers | main_key;
|
||||
key = modifiers | ducky_get_keycode(bad_usb, line_cstr, true);
|
||||
|
||||
if(key == 0 && next_char) ducky_error(bad_usb, "No keycode defined for %s", line_cstr);
|
||||
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
#include <lib/nfc/nfc_poller.h>
|
||||
#include <lib/nfc/protocols/iso14443_4a/iso14443_4a_poller.h>
|
||||
#include <lib/nfc/protocols/iso14443_4b/iso14443_4b_poller.h>
|
||||
#include <lib/nfc/protocols/iso15693_3/iso15693_3_poller.h>
|
||||
#include <toolbox/pipe.h>
|
||||
|
||||
#include <furi_hal_nfc.h>
|
||||
@@ -15,13 +14,12 @@
|
||||
#define FLAG_EVENT (1 << 10)
|
||||
|
||||
#define NFC_MAX_BUFFER_SIZE (256)
|
||||
#define NFC_BASE_PROTOCOL_MAX (3)
|
||||
#define NFC_BASE_PROTOCOL_MAX (2)
|
||||
#define POLLER_DONE (1 << 0)
|
||||
#define POLLER_ERR (1 << 1)
|
||||
static NfcProtocol BASE_PROTOCOL[NFC_BASE_PROTOCOL_MAX] = {
|
||||
NfcProtocolIso14443_4a,
|
||||
NfcProtocolIso14443_4b,
|
||||
NfcProtocolIso15693_3};
|
||||
NfcProtocolIso14443_4b};
|
||||
typedef struct ApduContext {
|
||||
BitBuffer* tx_buffer;
|
||||
BitBuffer* rx_buffer;
|
||||
@@ -88,19 +86,6 @@ static NfcCommand trx_callback(NfcGenericEvent event, void* context) {
|
||||
furi_thread_flags_set(apdu_context->thread_id, POLLER_ERR);
|
||||
return NfcCommandStop;
|
||||
}
|
||||
} else if(NfcProtocolIso15693_3 == event.protocol) {
|
||||
Iso15693_3Error err = iso15693_3_poller_send_frame(
|
||||
event.instance,
|
||||
apdu_context->tx_buffer,
|
||||
apdu_context->rx_buffer,
|
||||
ISO15693_3_FDT_POLL_FC);
|
||||
if(Iso15693_3ErrorNone == err) {
|
||||
furi_thread_flags_set(apdu_context->thread_id, POLLER_DONE);
|
||||
return NfcCommandContinue;
|
||||
} else {
|
||||
furi_thread_flags_set(apdu_context->thread_id, POLLER_ERR);
|
||||
return NfcCommandStop;
|
||||
}
|
||||
} else {
|
||||
// should never reach here
|
||||
furi_crash("Unknown protocol");
|
||||
|
||||
@@ -118,7 +118,8 @@ static int32_t subghz_frequency_analyzer_worker_thread(void* context) {
|
||||
for(size_t i = 0; i < subghz_setting_get_frequency_count(instance->setting); i++) {
|
||||
uint32_t current_frequency = subghz_setting_get_frequency(instance->setting, i);
|
||||
if(furi_hal_subghz_is_frequency_valid(current_frequency) &&
|
||||
(((current_frequency != 467750000) && (current_frequency != 464000000)) &&
|
||||
(((current_frequency != 462750000) && (current_frequency != 467750000) &&
|
||||
(current_frequency != 464000000)) &&
|
||||
(current_frequency <= 920000000))) {
|
||||
furi_hal_spi_acquire(&furi_hal_spi_bus_handle_subghz);
|
||||
cc1101_switch_to_idle(&furi_hal_spi_bus_handle_subghz);
|
||||
|
||||
@@ -1,62 +1,63 @@
|
||||
Filetype: Flipper SubGhz Keystore File
|
||||
Version: 0
|
||||
Encryption: 1
|
||||
IV: 46 75 72 69 20 63 68 65 63 6B 20 4F 77 4F 21 3F
|
||||
796353C129CC2B688FE158D36E82001F7450D58DD763BCF4D6FA1CE6C3D598EA
|
||||
1E7DDEB3B54A42B8993C32AF209CBCC9A1137CE334449F016B993D673EB15C69
|
||||
F9CB2DDC4E3D45694292C7DE45F1DC0BD74235B36F624AF39E8C3D211A713408
|
||||
538F46EF4250801434FEA469EE07E8C8BF71C6179442718A05455BB501D797C4
|
||||
F2BF384DBF7F828E025F020E47D1D637B497FB470444F0C6F9DC67C6830EDDE8A26A6EE89A321D3924D9099895AB2EA1
|
||||
2CA8A8A4866D5C2B715B520F641B41355A81BA73170842233806D8AA3E3F3D62
|
||||
80CF5DEF931CF902EE602319F7CD506D42E5FBC06ABBF9F05D474C8E8A2AAC4E
|
||||
15CB465F7A646226C987BB4928E92A61F350ADCDDE355B717730ADDD1B738950
|
||||
86B7597ED3EDF6826124ABD7AE419197DC4A93FA064179ACAD853EC670F93995
|
||||
28263A286F1ADA0E851E8A27AFD7706CF3513D8A24D41CF7E24A925FE3D86305
|
||||
AF29A08AB877F12681706D71B82B8E2447DA18EBF9731EF3CE91FA5ECAC4E98F8FDC817E0F67C3D7348DD2AF128F1E62
|
||||
A675C5BB6AC41336B5F5A27FC062FBF30DC39B1E5C498F0FD823261C3177FA58416C5402554742370CB0DAFD2895F6F8
|
||||
0073790C26BD0224F5560161A4D4C4F8E05498E995FD2BF12EA9926A5127E9A5
|
||||
235ADFE253B51260DCF5C66F9CB9602B91A0C57BE14D1BE1E11EB309643B29DB
|
||||
F9C2E3A926AAA108F474075F0B4EDFF3135492B1529EAB150CF78E748BF36E17
|
||||
50F442CC9D90B9FF8C786245EC442B911A28A04D829D0E45D7D2D4C5A3F5B864
|
||||
9EA00CD21C0BE1BB15A0CAD31097A44CAF42868F259E8ED25F361986C26161514FA85D78F3889B4185D2A1484C1DA88C
|
||||
52DFE7D9052F29071922876723C30CF6FE6247D6439590C5C7C0493120ACA096
|
||||
D5AF176D59779A92F6EFB34F271D76D60780C3EA83306326E0119CD3B0417687
|
||||
C4CC4E589CCCEC609B4DE39F926F83CCFFCC966871B9A998514910A3F59E86FB56C476DFFB4181E3D22E86A760C4C137
|
||||
50A64FEDA64B61A5C123906426EF726D98AC70C15F38245A931B5649F0944930679513D9862091275F10A804EBB610DE
|
||||
E7938C4F32E571582D73F855ACC40FF0153EFBAB6D184F2DBE8EAC63C4276D92
|
||||
7667993F35F1363C0A3AEB5222F07F91904B3F6FA375BF062B269B09706764CB
|
||||
9DF764EE4A70D331BA8870F4D27C3E90E811A5E306BC72701A99A0377AC7B189
|
||||
324D0FBC096A489983C45E82B2745A83A3725A87D2D2CA676A521075065D5047
|
||||
8EA1A30AE08CEBD03A52EB2512C7C69CB824E0B9BE900E25F15FAB17ADBB1188
|
||||
CE379182103FC4E0442745F6F202AB6ED8EBC051B5F5537916938D9DB8FCD6BE
|
||||
752BD22AA37D030C60E48CB57309AF631682AC4A0D67C3A7D1130EB056717FB6
|
||||
9ECFE7D24BF25BD543E1EAE8116D95C110BD4514EE279BCA71234865EB9166BD
|
||||
14B3FA8704BA3B284C65F1A6FD114E53B883E12EAFB24B574F84585BD20157DA
|
||||
D026E1E2CA70E33291482EEFCE11123540BBF591D400C92CEBB8CAF99A9DE882
|
||||
88E618EF5E76D1F5A60926D48D3D58FF67B4A92DE6EECA271EDAFC2419AE787B
|
||||
74E14AD8ADE2BC575048325D1B3990669CDB35D840169B913043DAC938862AE4
|
||||
BEB5388B6A7D5C9EF65BDD7577D1DD654B7FAECE5A4CF0937BB7D0C0C5494CD0
|
||||
761356D494E3C947CBDCA887A30071A675FE1BE6E77FC9016DB9B5659B7FF9E7
|
||||
7503725DFC7212F5F719AFC9DF29F07321511BE4896E12D1D10C68BB07C6483A2CE5FFDFD074CFC279E42E6DD860C496
|
||||
BD03D78399DE44449AEE9F00EBCABBF419EDEA1701B9979A97D57AECB5139D1E
|
||||
E80EB84DF9DA2E34B78F50D6488A30F8EFD11E7C6DBEB7CFEDE83BE5CA86B6DF
|
||||
9332A130138F2AC11A12030CF43EFF77E7CABE761EDE14748112E13267496CE9
|
||||
E657F3C95EEF0AF92A5C49F66BD9C053A82493C7D6267F1E7C038473AE488116
|
||||
6F37491FFE130F90B77D7E5EA4AA75A1DB0CA3644F68B6502DFC302DDB80367B
|
||||
3B37C5CCDD510873628D92B352907FEFF0AC2B38C751C2E46C3B97C3E365972B
|
||||
A4C845187BEC75669234EE07B839DCFF618678D2EAA5596350F0936A400099A5
|
||||
2C961EF4F2454771B2646ECBAA1D0B7DAA2FD8ECC7228037A36E24FE30C43ABAA446C1B5968C0E2DD141C55557A4CCB8
|
||||
C4E0D43E9670C2B91F6AF03D60F216625CC19C697331BC443194D2BB88E042DF
|
||||
3DC5584F43061AF79907D6342DF3344435B5AA6277B33D7DC56C429D1EB81BC4
|
||||
D9186791E907CBB9EF26EDDAEA9F0DBC8D24E213E55942ED5E1790B5A55F8758
|
||||
2B54CB727BBFD8567543448D2D24B3865329F89936D3B035ED2185BA88F1DF2E
|
||||
A08F0D881AF001E52FF2CF9D232A9A566EB1900B351AFEEFEE666BEC40588F64
|
||||
46A11CA89BA1998A247275EEDF504DAFC5F97B41DFF4943F531A9F8F43DF19C5
|
||||
EF70A3858E84B13DF606317381B2E9DFFC346E96AF7C1DF0001586B8BF35808F
|
||||
38EAF18DB8096C7427EBD36CBC5B0E945A3286278CC0227EB056F7ACB9E450D4
|
||||
28278D1DAA263E9A45ED17F67F6B6B0CF00F8C0F58F86C8161F8D4266FE556CB
|
||||
0B0C79FDD7C9EA31FAA4AA829EDDD2A3453C05A74F5B53BBEAE83E1F4913FD1C18BD235D14D06D9E567DDB273E4C1F2A
|
||||
7D663A93AE1B9A2E00E944B92838DED3376E09C5179C8F3037B2EAE9E7326C2A
|
||||
D64EC2C7BD8CFA152368DF6BB75D66EF24EAA9C864A1386184B793C0585D82BC
|
||||
51D8EB188E833891CCD15919FAC8FE56ACAB1007699F4FDCB53A6DDAB02E5CAA
|
||||
650866D34DECD1D1F3559EFD8D2A4C1DB51C005F5932608CB6062B384D7A1F59C8E3FBF2C0A5AEFFB631D7B88A630AAB
|
||||
IV: 4E 6F 20 66 75 72 69 20 63 68 65 63 6B 3F 21 3F
|
||||
2F0767B5B190608EB032D12BFA937D760A77D08D37F851E940767F1915E97ACF
|
||||
332F8DCCFDBF0485EC2EEED0C279F277E52A86A93BC5E4E96BE5F7276CC66713
|
||||
D9A02CC785FC0495063C424B0B1BAE7C120A2C24D4C0EE743F5D216718B16490
|
||||
4D9DD617090BDB100986B6987CAAC3652D2ADAB1AD9E368C5806D98562FF6B2F
|
||||
28D21748FF3826FA13C785A6721CC5927C81EDAB0C5CF31C92EAFF12AA91608298485D8A3AB443640237372ADF0DDC49
|
||||
5058E12C0A41EDCB5C0812554F619DADFB6E895B94421952ECD9255A04EE5E1A
|
||||
83A3EB8B22D94487A6B0F37856FB6AE9F42272BF25E1AE06DE03AA881A12D15F
|
||||
D0E207DE64402B43ECD0C341216B6BCDC449508116E81D8ACDE7FA0BFBEA56F7
|
||||
6C4F723DE3B775D4C07E12ED3C369250B4D2089ADE2207816DED130D4B498CDF
|
||||
B041911C56555E5F4676BF16819F61BF7A92402EB0427B8C2E7367B0AEA6B53C
|
||||
1AD460260F20146A763BF6D4CD26DF5139EE29FFF8B53F6C5367EA779E1BEE56D5DFD872EA0268FE27204175925079AA
|
||||
B1A9331AED36137CD078536A67775E2880D3CD7305373BC44A5649435E466AD2DC9FDE8AC1F572EF094D4B438C9509EA
|
||||
105819300A9152F16E3478151799ECBBB7CCCE63DADA3F6C6D16D46830E1E035
|
||||
354186E04BC90D672F76A427FC1CD35C2EFAE8D4D1C36247FFB71ACB862A3601
|
||||
84B533148282D0D8121E5BBBBD39DE16F398365B015E02417ECC535C88EB9C57
|
||||
E899C9DC779F82E798EE923D257D5F051E1254DCDA2A6A955882727AA8E98ED8
|
||||
B8EC34F9B75E61D34E9C075A5316FAFC395E8FBA4F76B215620C5B5C76C53DB7BF316E53582161AD20F64CAB8E3347B2
|
||||
966C3B0873F48889B51D7D9DACC0674CBC95B06E231E30F235C826285D529A54
|
||||
370DED014764D7278E342D3AB631AB37D8F8A8FAE08987E03D7FC279DEEEB913
|
||||
2318A2DA42EEA2A35FFC9BDFBB244DF3FF6933010D74B3465336C0E37FFDC48A200568F8D6003AB215388734B8AC1F20
|
||||
475B35437FECEE9792F53A671252E78566AA9894DE7A4DEC9AED70834864E804E87478009F424CE1424C00F162BB03C5
|
||||
01CE6251ED9682BA6366075081167196CD740D346C4DAC4E0012C7951C475AE7
|
||||
CB225891F937CA491B711AA942B04C61C7CFA6A8E912D91D0906B401737E03B4
|
||||
F35D279815DEF19C9C5BC9ED55E7C1A0366E37DCD0A93E6E168B5A2602201C7B
|
||||
3569D8DF2490797D40978F8325B94CC707383FEA1B46240BFDAECFEFB1F8176D
|
||||
3D7BAF13573BBF3102757C68D52236638CC57126FF3795A604CFFA2D3F1B9C26
|
||||
B9102C87D7DBCF35463F38B6B80B70408968B6E01A47F6A7E8A3E87A0577B4ED
|
||||
7673FAC14D94ABF72800A78E2DC4CAF2166FBB24719C22CFC1010492F4C87734
|
||||
1AF74DA07EA3A418EB86BB7ABAD6192B8E5A53F61B3E74CB898CB3EE4A7E244A
|
||||
832D18C44062DDE856384E19D1417FA48D809C2CB2107CDEC5281943559791A6
|
||||
CD482A8FAB2A2CBE25A0B4A4788F274CA7095AA24508C00DBB78DD12BFB11C37
|
||||
EAC52E802DB76B51058752D7EFA91BCB1212AB96B589F9A88465195C1DE3242E
|
||||
96CC75952A513AB5FE62A69AB6CDDA93C2156A3EA607C25B3201CE7284B3DAA9
|
||||
986E71EE87E860192141A1453929E575706E3FE72B7A9FEF5ACA696388649EB6
|
||||
FFF89FECC1C01FA3F266B95BDEF61A16F514E59599DAA07E908C604E9FE686C0
|
||||
ACC159D4AE78E26B5A1468F69D961028D0BF962D03E865415E7FE746553FEF15
|
||||
0FF46B2F9D4E907B9924675081D17C38C09957AA2F4C3C1F5568461DBA850F6301328CDC0FCEE83C7E8BA00CF8FC0F97
|
||||
7FD793C05E499739C3C4F8CC1D2D205A55928AB5BC60752A81D86DFBE30C50BD
|
||||
CE444F4A1BEB38C9E93579E1B7FB3E90B4F85D8DA94DFC622272DED093A35192
|
||||
C7C31D8AB9D717FAF842F850A3E0D6B404EB9A980D9679362ABA90594B1957AB
|
||||
1D48A6CFFBB6F14DD5BED1F8E74E6CC0292150546EDD76361792677434A8FE5F
|
||||
F7335B8877DDF17F0737ECF77E2E6286E78534CE28E72077360E8E24D7750DFE
|
||||
51051D9A8D5941661EBCF437B4640E6DA0B9B27518D761F3EF26BF7EABC691D4
|
||||
79F279733E18393FEDB50D654A0D0A532A64BED5ACBD13319439EEC007BC359C
|
||||
646666FDB75D439C0427A9E3EF47F145DBD4FF5FE2E244909D74F075B24FF5A9B47E7AF98271210057D937A0E4B1F46D
|
||||
DE7E814A2BD4D8823D9F2380EFAFFA1380A90391F87CBF24CE46BD46205EABAB
|
||||
1335C4C3E819E942F5C212E9BEFAF5D984316C0A2FF6E9886886B565625618A9
|
||||
65386F906F18FF9C3A20AB57F3241D4975FE312ACDEB7FB1B91F2B816CAA46E7
|
||||
DF8A8B33782D56667F4C98F8F91B49B71A9E83AF015D8841986D41663233A0DC
|
||||
27264455248878BB226FA1DED0922BD10313FF65F8A6A0E3CCDFB77890C838BB
|
||||
43A08F784F36A3E8049BA63A401F3F15B3CA2ED263F8638595B5F22A0B081369
|
||||
F9F82F89C15AD970320E3D7A83B272EB00CD0ED657E4D230AB33C995859EA77F
|
||||
70AD020D172E18E1011DF88E5F934F03F34DCE8148F8053B4FFA6F92CAC9FC93
|
||||
2B845F67BAB432CED64F2D68454A2B4B3BC46FFDC2A16D3340360C7BEA110BBB
|
||||
B85F16A2370B278FDB3C85E6455B8DA239D6413B727839DEFBCB5628A6C747266291AB9D9F4F5DA1826B219C1A29F956
|
||||
FFB7B10D96F241FDB994008AF85EC85D147A97AA599D05F5EE1BB2FC27644A26
|
||||
0BD42CA312CBBCAE556AA0159EC2CC2FA70BBB00D8DF7B63BBEA60A282481AED
|
||||
9CC73810056A21EA6F311B01BA7F44655A075D1F60947FBC9B6924C3BD0ED819
|
||||
024FCB96977ECA1C0D4B9C7C461361329D96E5AFF315124FEFC0DF2A400DE312F45D602DB40CD4EB088F144EB0B8DF41
|
||||
|
||||
@@ -93,6 +93,9 @@ void subghz_scene_save_name_on_enter(void* context) {
|
||||
bool subghz_scene_save_name_on_event(void* context, SceneManagerEvent event) {
|
||||
SubGhz* subghz = context;
|
||||
if(event.type == SceneManagerEventTypeBack) {
|
||||
// Set file path to default
|
||||
furi_string_set(subghz->file_path, SUBGHZ_APP_FOLDER);
|
||||
//
|
||||
if(!(strcmp(subghz->file_name_tmp, "") == 0) ||
|
||||
scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneReadRAW) !=
|
||||
SubGhzCustomEventManagerNoSet) {
|
||||
@@ -106,8 +109,6 @@ bool subghz_scene_save_name_on_event(void* context, SceneManagerEvent event) {
|
||||
} else {
|
||||
scene_manager_previous_scene(subghz->scene_manager);
|
||||
}
|
||||
// Set file path to default
|
||||
furi_string_set(subghz->file_path, SUBGHZ_APP_FOLDER);
|
||||
|
||||
return true;
|
||||
} else if(event.type == SceneManagerEventTypeCustom) {
|
||||
|
||||
@@ -1099,7 +1099,7 @@ static void subghz_cli_command_chat(PipeSide* pipe, FuriString* args) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!cli_is_pipe_broken_or_is_etx_next_char(pipe)) {
|
||||
if(cli_is_pipe_broken_or_is_etx_next_char(pipe)) {
|
||||
printf("\r\n");
|
||||
chat_event.event = SubGhzChatEventUserExit;
|
||||
subghz_chat_worker_put_event_chat(subghz_chat, &chat_event);
|
||||
|
||||
@@ -73,8 +73,9 @@ bool desktop_main_input_callback(InputEvent* event, void* context) {
|
||||
} else if(event->key == InputKeyOk) {
|
||||
if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) {
|
||||
main_view->callback(DesktopAnimationEventNewIdleAnimation, main_view->context);
|
||||
} else {
|
||||
main_view->callback(DesktopMainEventOpenFavoriteOkLong, main_view->context);
|
||||
}
|
||||
main_view->callback(DesktopMainEventOpenFavoriteOkLong, main_view->context);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <stdint.h>
|
||||
#include <m-array.h>
|
||||
|
||||
#define SCROLL_INTERVAL (333)
|
||||
#define ITEM_FIRST_OFFSET 17
|
||||
#define ITEM_NEXT_OFFSET 4
|
||||
#define ITEM_HEIGHT 14
|
||||
@@ -35,13 +36,56 @@ typedef struct {
|
||||
ButtonMenuItemArray_t items;
|
||||
size_t position;
|
||||
const char* header;
|
||||
size_t scroll_counter;
|
||||
FuriTimer* scroll_timer;
|
||||
} ButtonMenuModel;
|
||||
|
||||
static void button_menu_draw_text(
|
||||
Canvas* canvas,
|
||||
uint8_t item_x,
|
||||
uint8_t item_y,
|
||||
const char* text,
|
||||
bool selected,
|
||||
ButtonMenuModel* model) {
|
||||
FuriString* disp_str;
|
||||
disp_str = furi_string_alloc_set(text);
|
||||
bool draw_static = true;
|
||||
|
||||
if(selected) {
|
||||
size_t text_width = canvas_string_width(canvas, furi_string_get_cstr(disp_str));
|
||||
if(text_width >= ITEM_WIDTH - 8) {
|
||||
elements_scrollable_text_line(
|
||||
canvas,
|
||||
item_x + 4,
|
||||
item_y + ITEM_HEIGHT - 4,
|
||||
ITEM_WIDTH - 8,
|
||||
disp_str,
|
||||
model->scroll_counter,
|
||||
false);
|
||||
draw_static = false;
|
||||
}
|
||||
}
|
||||
|
||||
if(draw_static) {
|
||||
elements_string_fit_width(canvas, disp_str, ITEM_WIDTH - 6);
|
||||
canvas_draw_str_aligned(
|
||||
canvas,
|
||||
item_x + (ITEM_WIDTH / 2),
|
||||
item_y + (ITEM_HEIGHT / 2),
|
||||
AlignCenter,
|
||||
AlignCenter,
|
||||
furi_string_get_cstr(disp_str));
|
||||
}
|
||||
|
||||
furi_string_free(disp_str);
|
||||
}
|
||||
|
||||
static void button_menu_draw_control_button(
|
||||
Canvas* canvas,
|
||||
uint8_t item_position,
|
||||
const char* text,
|
||||
bool selected) {
|
||||
bool selected,
|
||||
ButtonMenuModel* model) {
|
||||
furi_assert(canvas);
|
||||
furi_assert(text);
|
||||
|
||||
@@ -54,20 +98,16 @@ static void button_menu_draw_control_button(
|
||||
elements_slightly_rounded_box(canvas, item_x, item_y, ITEM_WIDTH, ITEM_HEIGHT);
|
||||
canvas_set_color(canvas, ColorWhite);
|
||||
}
|
||||
canvas_draw_str_aligned(
|
||||
canvas,
|
||||
item_x + (ITEM_WIDTH / 2),
|
||||
item_y + (ITEM_HEIGHT / 2),
|
||||
AlignCenter,
|
||||
AlignCenter,
|
||||
text);
|
||||
|
||||
button_menu_draw_text(canvas, item_x, item_y, text, selected, model);
|
||||
}
|
||||
|
||||
static void button_menu_draw_common_button(
|
||||
Canvas* canvas,
|
||||
uint8_t item_position,
|
||||
const char* text,
|
||||
bool selected) {
|
||||
bool selected,
|
||||
ButtonMenuModel* model) {
|
||||
furi_assert(canvas);
|
||||
furi_assert(text);
|
||||
|
||||
@@ -83,19 +123,7 @@ static void button_menu_draw_common_button(
|
||||
canvas_draw_rframe(canvas, item_x, item_y, ITEM_WIDTH, ITEM_HEIGHT, 5);
|
||||
}
|
||||
|
||||
FuriString* disp_str;
|
||||
disp_str = furi_string_alloc_set(text);
|
||||
elements_string_fit_width(canvas, disp_str, ITEM_WIDTH - 6);
|
||||
|
||||
canvas_draw_str_aligned(
|
||||
canvas,
|
||||
item_x + (ITEM_WIDTH / 2),
|
||||
item_y + (ITEM_HEIGHT / 2),
|
||||
AlignCenter,
|
||||
AlignCenter,
|
||||
furi_string_get_cstr(disp_str));
|
||||
|
||||
furi_string_free(disp_str);
|
||||
button_menu_draw_text(canvas, item_x, item_y, text, selected, model);
|
||||
}
|
||||
|
||||
static void button_menu_view_draw_callback(Canvas* canvas, void* _model) {
|
||||
@@ -120,9 +148,17 @@ static void button_menu_view_draw_callback(Canvas* canvas, void* _model) {
|
||||
if(model->header) {
|
||||
FuriString* disp_str;
|
||||
disp_str = furi_string_alloc_set(model->header);
|
||||
elements_string_fit_width(canvas, disp_str, ITEM_WIDTH - 6);
|
||||
canvas_draw_str_aligned(
|
||||
canvas, 32, 10, AlignCenter, AlignCenter, furi_string_get_cstr(disp_str));
|
||||
size_t header_width = canvas_string_width(canvas, furi_string_get_cstr(disp_str));
|
||||
|
||||
if(header_width >= ITEM_WIDTH - 8) {
|
||||
elements_scrollable_text_line(
|
||||
canvas, 3, 13, ITEM_WIDTH - 8, disp_str, model->scroll_counter, false);
|
||||
} else {
|
||||
elements_string_fit_width(canvas, disp_str, ITEM_WIDTH - 8);
|
||||
canvas_draw_str_aligned(
|
||||
canvas, 32, 10, AlignCenter, AlignCenter, furi_string_get_cstr(disp_str));
|
||||
}
|
||||
|
||||
furi_string_free(disp_str);
|
||||
}
|
||||
|
||||
@@ -137,13 +173,15 @@ static void button_menu_view_draw_callback(Canvas* canvas, void* _model) {
|
||||
canvas,
|
||||
item_position % BUTTONS_PER_SCREEN,
|
||||
ButtonMenuItemArray_cref(it)->label,
|
||||
(item_position == model->position));
|
||||
(item_position == model->position),
|
||||
model);
|
||||
} else if(ButtonMenuItemArray_cref(it)->type == ButtonMenuItemTypeCommon) {
|
||||
button_menu_draw_common_button(
|
||||
canvas,
|
||||
item_position % BUTTONS_PER_SCREEN,
|
||||
ButtonMenuItemArray_cref(it)->label,
|
||||
(item_position == model->position));
|
||||
(item_position == model->position),
|
||||
model);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -158,8 +196,10 @@ static void button_menu_process_up(ButtonMenu* button_menu) {
|
||||
{
|
||||
if(model->position > 0) {
|
||||
model->position--;
|
||||
model->scroll_counter = 0;
|
||||
} else {
|
||||
model->position = ButtonMenuItemArray_size(model->items) - 1;
|
||||
model->scroll_counter = 0;
|
||||
}
|
||||
},
|
||||
true);
|
||||
@@ -174,8 +214,10 @@ static void button_menu_process_down(ButtonMenu* button_menu) {
|
||||
{
|
||||
if(model->position < (ButtonMenuItemArray_size(model->items) - 1)) {
|
||||
model->position++;
|
||||
model->scroll_counter = 0;
|
||||
} else {
|
||||
model->position = 0;
|
||||
model->scroll_counter = 0;
|
||||
}
|
||||
},
|
||||
true);
|
||||
@@ -193,8 +235,10 @@ static void button_menu_process_right(ButtonMenu* button_menu) {
|
||||
position_candidate -= position_candidate % BUTTONS_PER_SCREEN;
|
||||
if(position_candidate < (ButtonMenuItemArray_size(model->items))) {
|
||||
model->position = position_candidate;
|
||||
model->scroll_counter = 0;
|
||||
} else {
|
||||
model->position = 0;
|
||||
model->scroll_counter = 0;
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -217,6 +261,7 @@ static void button_menu_process_left(ButtonMenu* button_menu) {
|
||||
};
|
||||
position_candidate -= position_candidate % BUTTONS_PER_SCREEN;
|
||||
model->position = position_candidate;
|
||||
model->scroll_counter = 0;
|
||||
}
|
||||
},
|
||||
true);
|
||||
@@ -314,6 +359,7 @@ void button_menu_reset(ButtonMenu* button_menu) {
|
||||
ButtonMenuItemArray_reset(model->items);
|
||||
model->position = 0;
|
||||
model->header = NULL;
|
||||
model->scroll_counter = 0;
|
||||
},
|
||||
true);
|
||||
}
|
||||
@@ -351,6 +397,12 @@ ButtonMenuItem* button_menu_add_item(
|
||||
return item;
|
||||
}
|
||||
|
||||
static void button_menu_process_timer_callback(void* context) {
|
||||
ButtonMenu* button_menu = context;
|
||||
with_view_model(
|
||||
button_menu->view, ButtonMenuModel * model, { model->scroll_counter++; }, true);
|
||||
}
|
||||
|
||||
ButtonMenu* button_menu_alloc(void) {
|
||||
ButtonMenu* button_menu = malloc(sizeof(ButtonMenu));
|
||||
button_menu->view = view_alloc();
|
||||
@@ -367,6 +419,10 @@ ButtonMenu* button_menu_alloc(void) {
|
||||
ButtonMenuItemArray_init(model->items);
|
||||
model->position = 0;
|
||||
model->header = NULL;
|
||||
model->scroll_counter = 0;
|
||||
model->scroll_timer = furi_timer_alloc(
|
||||
button_menu_process_timer_callback, FuriTimerTypePeriodic, button_menu);
|
||||
furi_timer_start(model->scroll_timer, SCROLL_INTERVAL);
|
||||
},
|
||||
true);
|
||||
|
||||
@@ -380,7 +436,11 @@ void button_menu_free(ButtonMenu* button_menu) {
|
||||
with_view_model(
|
||||
button_menu->view,
|
||||
ButtonMenuModel * model,
|
||||
{ ButtonMenuItemArray_clear(model->items); },
|
||||
{
|
||||
ButtonMenuItemArray_clear(model->items);
|
||||
furi_timer_stop(model->scroll_timer);
|
||||
furi_timer_free(model->scroll_timer);
|
||||
},
|
||||
true);
|
||||
view_free(button_menu->view);
|
||||
free(button_menu);
|
||||
|
||||
@@ -399,9 +399,7 @@ static void rgb_backlight_installed_changed(VariableItem* item) {
|
||||
}
|
||||
|
||||
// Lock/Unlock all rgb settings depent from rgb_backlight_installed switch
|
||||
int slide = 1;
|
||||
|
||||
for(int i = slide; i < (slide + 8); i++) {
|
||||
for(int i = 1; i < 9; i++) {
|
||||
VariableItem* t_item = variable_item_list_get(app->variable_item_list_rgb, i);
|
||||
if(index == 0) {
|
||||
variable_item_set_locked(t_item, true, "RGB\nOFF!");
|
||||
@@ -534,7 +532,7 @@ static void rgb_backlight_rainbow_wide_changed(VariableItem* item) {
|
||||
notification_message_save_settings(app->notification);
|
||||
}
|
||||
|
||||
// open settings.rgb_view if user press OK on first (index=0) menu string and (debug mode or rgb_backlight_installed is true)
|
||||
// open settings.rgb_view if user press OK on last (index=10) menu string
|
||||
void variable_item_list_enter_callback(void* context, uint32_t index) {
|
||||
UNUSED(context);
|
||||
NotificationAppSettings* app = context;
|
||||
@@ -562,12 +560,10 @@ static void night_shift_changed(VariableItem* item) {
|
||||
app->notification->current_night_shift = night_shift_value[index];
|
||||
app->notification->current_night_shift = night_shift_value[index];
|
||||
|
||||
// force demo night_shift brightness ot rgb backlight and stock backlight
|
||||
// force demo night_shift brightness to rgb backlight and stock backlight
|
||||
notification_message(app->notification, &sequence_display_backlight_on);
|
||||
|
||||
int slide = 0;
|
||||
|
||||
for(int i = 4 + slide; i < (6 + slide); i++) {
|
||||
for(int i = 4; i < 6; i++) {
|
||||
VariableItem* t_item = variable_item_list_get(app->variable_item_list, i);
|
||||
if(index == 0) {
|
||||
variable_item_set_locked(t_item, true, "Night Shift\nOFF!");
|
||||
@@ -729,18 +725,15 @@ static NotificationAppSettings* alloc_settings(void) {
|
||||
variable_item_set_current_value_text(item, lcd_inversion_text[value_index]);
|
||||
|
||||
//--- RGB BACKLIGHT ---
|
||||
// Show RGB settings only when debug_mode or rgb_backlight_installed is active
|
||||
item = variable_item_list_add(app->variable_item_list, "RGB Mod Settings", 0, NULL, app);
|
||||
//--- RGB BACKLIGHT END ---
|
||||
|
||||
app->variable_item_list_rgb = variable_item_list_alloc();
|
||||
View* view_rgb = variable_item_list_get_view(app->variable_item_list_rgb);
|
||||
|
||||
// set callback for exit from settings.rgb_menu
|
||||
// set callback for exit from rgb settings menu
|
||||
view_set_previous_callback(view_rgb, notification_app_rgb_settings_exit);
|
||||
|
||||
// Show rgb_backlight_installed swith only in Debug mode
|
||||
|
||||
item = variable_item_list_add(
|
||||
app->variable_item_list_rgb,
|
||||
"RGB backlight installed",
|
||||
|
||||
@@ -23,6 +23,7 @@ typedef struct {
|
||||
} JsGpioPinInst;
|
||||
|
||||
ARRAY_DEF(ManagedPinsArray, JsGpioPinInst*, M_PTR_OPLIST); //-V575
|
||||
#define M_OPL_ManagedPinsArray_t() ARRAY_OPLIST(ManagedPinsArray)
|
||||
|
||||
/**
|
||||
* Per-module instance control structure
|
||||
@@ -444,20 +445,26 @@ static void js_gpio_destroy(void* inst) {
|
||||
JsGpioInst* module = (JsGpioInst*)inst;
|
||||
|
||||
// reset pins
|
||||
ManagedPinsArray_it_t iterator;
|
||||
for(ManagedPinsArray_it(iterator, module->managed_pins); !ManagedPinsArray_end_p(iterator);
|
||||
ManagedPinsArray_next(iterator)) {
|
||||
JsGpioPinInst* manager_data = *ManagedPinsArray_cref(iterator);
|
||||
if(manager_data->had_interrupt) {
|
||||
furi_hal_gpio_disable_int_callback(manager_data->pin);
|
||||
furi_hal_gpio_remove_int_callback(manager_data->pin);
|
||||
for
|
||||
M_EACH(item, module->managed_pins, ManagedPinsArray_t) {
|
||||
JsGpioPinInst* manager_data = *item;
|
||||
|
||||
if(manager_data->had_interrupt) {
|
||||
furi_hal_gpio_disable_int_callback(manager_data->pin);
|
||||
furi_hal_gpio_remove_int_callback(manager_data->pin);
|
||||
}
|
||||
if(manager_data->pwm_output != FuriHalPwmOutputIdNone) {
|
||||
if(furi_hal_pwm_is_running(manager_data->pwm_output))
|
||||
furi_hal_pwm_stop(manager_data->pwm_output);
|
||||
}
|
||||
furi_hal_gpio_init(manager_data->pin, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||
|
||||
furi_event_loop_maybe_unsubscribe(module->loop, manager_data->interrupt_semaphore);
|
||||
furi_semaphore_free(manager_data->interrupt_semaphore);
|
||||
|
||||
free(manager_data->interrupt_contract);
|
||||
free(manager_data);
|
||||
}
|
||||
furi_hal_gpio_init(manager_data->pin, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||
furi_event_loop_maybe_unsubscribe(module->loop, manager_data->interrupt_semaphore);
|
||||
furi_semaphore_free(manager_data->interrupt_semaphore);
|
||||
free(manager_data->interrupt_contract);
|
||||
free(manager_data);
|
||||
}
|
||||
|
||||
// free buffers
|
||||
furi_hal_adc_release(module->adc_handle);
|
||||
|
||||
@@ -345,7 +345,7 @@ int32_t update_task_worker_flash_writer(void* context) {
|
||||
furi_hal_rtc_set_flag(FuriHalRtcFlagStorageFormatInternal);
|
||||
#ifdef FURI_NDEBUG
|
||||
// Production
|
||||
furi_hal_rtc_set_log_level(FuriLogLevelDefault);
|
||||
furi_hal_rtc_set_log_level(FuriLogLevelNone);
|
||||
furi_hal_rtc_reset_flag(FuriHalRtcFlagDebug);
|
||||
furi_hal_rtc_reset_flag(FuriHalRtcFlagLegacySleep);
|
||||
furi_hal_rtc_set_heap_track_mode(FuriHalRtcHeapTrackModeNone);
|
||||
|
||||
@@ -73,6 +73,7 @@ Watch this video to learn more and see how different boards can be programmed (v
|
||||
|
||||
## Doorhan
|
||||
|
||||
With access to the receiver box:
|
||||
1. Create new remote with randomly generated serial: Go to SubGHz -> Add Manually -> KL: Doorhan 433Mhz or 315Mhz depends on your receiver (find out by reading your existing remote)
|
||||
2. Open your new remote file
|
||||
3. Push `P` button for ~2 sec, led will start flashing
|
||||
@@ -80,7 +81,29 @@ Watch this video to learn more and see how different boards can be programmed (v
|
||||
5. Led on the receiver board will flash and turn off
|
||||
6. Done!
|
||||
|
||||
Also you can program new remote using old remote on newer boards! See first video below:
|
||||
|
||||
With existing remote:
|
||||
1. Create new remote with randomly generated serial: Go to SubGHz -> Add Manually -> KL: Doorhan 433Mhz or 315Mhz depends on your receiver (find out by reading your existing remote)
|
||||
2. Open your new remote file
|
||||
3. For next steps be close to the receiver board, around 1-2 meters
|
||||
4. Press second button (lowest one) on the old remote, do not release second button and press 1st (upper) button, hold buttons for 1 sec and release them
|
||||
5. Press working button on the old remote (the button you use for operating the receiver, aka opening the gate, etc) hold for 1 sec and release
|
||||
6. Actions with old remote must be done in 5 seconds time, do not hold buttons for too long, and do not make it very fast
|
||||
7. Receiver will beep, you will have 10 seconds to add new remote, now press Send on new remote on flipper two times holding for at least 1 sec
|
||||
8. Receiver will beep again telling that new remote is added sucessfuly!
|
||||
9. Done!
|
||||
|
||||
With copy of existing remote on flipper:
|
||||
1. Create new remote with randomly generated serial: Go to SubGHz -> Add Manually -> KL: Doorhan 433Mhz or 315Mhz depends on your receiver (find out by reading your existing remote)
|
||||
2. Open your existing remote (original) file
|
||||
3. For next steps be close to the receiver board, around 1-2 meters
|
||||
4. Press left button (0x8) on the flipper, hold for 1 sec and release the button and press right (0xA) button, hold button for 1 sec and release
|
||||
5. Press working button on the flipper, should be center one aka Send (the button you use for operating the receiver, aka opening the gate, etc) hold for 1 sec and release
|
||||
6. Actions with original remote copy must be done in 5 seconds time, do not hold buttons for too long, and do not make it very fast
|
||||
7. Receiver will beep, now hold back and open new remote file, you will have 10 seconds to add new remote, press Send on new remote on flipper two times holding for at least 1 sec
|
||||
8. Receiver will beep again telling that new remote is added sucessfuly!
|
||||
9. Done!
|
||||
|
||||
Watch this videos to learn more (videos in Russian language): https://www.youtube.com/watch?v=wZ5121HYv50 / https://www.youtube.com/watch?v=1ucrDKF3vWc
|
||||
|
||||
## Somfy Telis
|
||||
@@ -122,19 +145,54 @@ How to get seed to make full clone of your remote (**will conflict with original
|
||||
|
||||
1. Open `Read` in SubGHz on your flipper
|
||||
2. (ONLY FOR ORIGINAL REMOTES) Hold all buttons on your remote at same time, example -> for 2 button remote - press them both at same time and hold OR press hidden button on back of remote with a pin or paper clip
|
||||
For 4 buttons remote press & hold two buttons at upper row
|
||||
3. You will receive signal on your flipper, open that signal and see `Fix:` value, it should start from `F` like `F00F1C9B`
|
||||
4. If `Fix:` is showing first `F` see `Hop:` value -> This is your remote Seed
|
||||
5. Write down Hop value
|
||||
4. If `Fix:` is showing first `F` see `Hop:` value -> This is your remote Seed (except first digit `F` (this is the button code, aka programming button pressed means `F`))
|
||||
5. Write down Hop value and replace first digit - `F` with `0`
|
||||
6. Press button on your remote that you want to clone and receive its signal on your flipper
|
||||
7. Open and write down `Fix:` value where first digit will be same as your button ID `Btn:`
|
||||
8. Create new remote using BFT Mitto [Manual] - Enter FIX from step 7, enter counter `FF F9`, enter seed from step 5
|
||||
9. Using counter values like `FF F9` can help bypassing current original remote counter value, and in result it also can fully desync original remote, only one remote can work at same time using this method
|
||||
10. Throw away your original remote since now it needs to be re-added into receiver board :C
|
||||
10. Also you can do this: Save your signal of the original remote (will say KL: Unknown),
|
||||
then copy file to the PC and edit it and insert/replace those values after the `Key: 01 23 45 67 89 AB CD EF` (your key will have different value)
|
||||
```
|
||||
Seed: 0X XX XX XX
|
||||
Manufacture: BFT
|
||||
```
|
||||
Replace `X`'s with digits from your Seed that you obtained by reading two button hold at the first steps,
|
||||
Save and copy that file back to the flipper
|
||||
Now you will have exact clone of your remote that will have same counter, by making couple presses you will make it higher than original and receiver will work with it, but original remote will reguire same amount of presses to work again, and vice versa.
|
||||
11. Also your original remote may become non working since it needs to be re-added into receiver board if you made counter much higher than original :C
|
||||
|
||||
## CAME Atomo
|
||||
Known names are: TOP42R / TOP44R - TOP44RGR (806TS-0130)
|
||||
|
||||
1. Use google to find instructions - `how to program new CAME Atomo remote into receiver`
|
||||
2. Watch this video to learn more (video in Russian language): https://www.youtube.com/watch?v=XeHUwfcSS30
|
||||
How to create new remote and bind it to receiver (will not conflict with original remotes):
|
||||
|
||||
With original remote (or copy of the original remote):
|
||||
|
||||
1. Create new remote with randomly generated serial: Go to SubGHz -> Add Manually -> CAME Atomo 433MHz or 868MHz
|
||||
2. Open your new remote file
|
||||
3. You need to be in minimum 3 meters to receiver
|
||||
4. Original Remote: Press and hold button that is bound with that receiver (the one you use with it), and hold it for about 10 seconds.
|
||||
5. You will have about 20 seconds to add new remote
|
||||
6. Long press Send on Flipper in new remote for like 3-4 sec and release - this will add new remote to the receiver
|
||||
7. Press and hold Send again after waiting 20 seconds - this will trigger the receiver
|
||||
8. Done, when using CAME Atomo from flipper please hold Send button for at least 2 seconds to allow code to be fully transmit, flipper transmits only while button is held
|
||||
|
||||
Note: Static 24/12 bit or TWEE remotes cannot trigger programming mode in the receiver and cannot be bound if programming mode was triggered by Atomo type remote, only Atomo remotes can be added if remote programming was done by Atomo remote, Static remotes have option to clone from one remote to another, but it requires first remote to be added to the receiver via button on the receiver board
|
||||
|
||||
With access to receiver box:
|
||||
|
||||
1. Create new remote with randomly generated serial: Go to SubGHz -> Add Manually -> CAME Atomo 433MHz or 868MHz
|
||||
2. Open your new remote file
|
||||
3. Open the receiver box and find programming button related to the used channel, for example RE432M/RE862M receiver has two independent channels which can have different remotes / buttons on them, when you found connected channel press "1" or "2" button on the receiver board to enter programming mode
|
||||
4. Long press Send on Flipper new remote for like 3-4 sec and release - this will add new remote to the receiver
|
||||
5. Click CLEAR button one time on the receiver board to exit programming mode, or wait about 20 seconds it will exit from programming mode automatically
|
||||
6. Done, when using CAME Atomo from flipper please hold Send button for at least 2 seconds to allow code to be fully transmit, flipper transmits only while button is held
|
||||
|
||||
|
||||
Watch this video to learn more (video in Russian language): https://www.youtube.com/watch?v=XeHUwfcSS30
|
||||
|
||||
## Nice Flor S
|
||||
|
||||
|
||||
@@ -60,6 +60,7 @@ if you need your custom one, make sure it doesn't listed here
|
||||
434775000, /* LPD433 last channels */
|
||||
438900000,
|
||||
440175000,
|
||||
462750000,
|
||||
464000000,
|
||||
467750000,
|
||||
|
||||
|
||||
@@ -38,6 +38,8 @@ static bool rw1990_read_and_compare(OneWireHost* host, const uint8_t* data, size
|
||||
}
|
||||
|
||||
bool rw1990_write_v1(OneWireHost* host, const uint8_t* data, size_t data_size) {
|
||||
onewire_host_set_timings_default(host);
|
||||
|
||||
// Unlock sequence
|
||||
onewire_host_reset(host);
|
||||
onewire_host_write(host, RW1990_1_CMD_WRITE_RECORD_FLAG);
|
||||
@@ -67,6 +69,8 @@ bool rw1990_write_v1(OneWireHost* host, const uint8_t* data, size_t data_size) {
|
||||
}
|
||||
|
||||
bool rw1990_write_v2(OneWireHost* host, const uint8_t* data, size_t data_size) {
|
||||
onewire_host_set_timings_default(host);
|
||||
|
||||
// Unlock sequence
|
||||
onewire_host_reset(host);
|
||||
onewire_host_write(host, RW1990_2_CMD_WRITE_RECORD_FLAG);
|
||||
|
||||
58
lib/ibutton/protocols/blanks/tm01x.c
Normal file
58
lib/ibutton/protocols/blanks/tm01x.c
Normal file
@@ -0,0 +1,58 @@
|
||||
#include <core/kernel.h>
|
||||
#include <one_wire/one_wire_host.h>
|
||||
#include <one_wire/maxim_crc.h>
|
||||
#include "tm01x.h"
|
||||
|
||||
// Commands for TM01x
|
||||
#define TM01X_CMD_WRITE_FLAG 0xC1
|
||||
#define TM01X_CMD_WRITE_ROM 0xC5
|
||||
#define TM01X_CMD_READ_ROM 0x33
|
||||
|
||||
#define TM01X_CMD_FINALIZE_CYFRAL 0xCA
|
||||
#define TM01X_CMD_FINALIZE_METAKOM 0xCB
|
||||
|
||||
static void tm01x_write_byte(OneWireHost* host, uint8_t value) {
|
||||
for(uint8_t bitMask = 0x01; bitMask; bitMask <<= 1) {
|
||||
onewire_host_write_bit(host, (bool)(bitMask & value));
|
||||
furi_delay_us(5000); // 5ms pause after each bit
|
||||
}
|
||||
}
|
||||
|
||||
// Helper function to read and verify written data
|
||||
static bool tm01x_read_and_verify(OneWireHost* host, const uint8_t* data, size_t data_size) {
|
||||
bool success = false;
|
||||
|
||||
if(onewire_host_reset(host)) {
|
||||
success = true;
|
||||
onewire_host_write(host, TM01X_CMD_READ_ROM);
|
||||
|
||||
for(size_t i = 0; i < data_size; ++i) {
|
||||
if(data[i] != onewire_host_read(host)) {
|
||||
success = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
bool tm01x_write_dallas(OneWireHost* host, const uint8_t* data, size_t data_size) {
|
||||
// Set TM01x specific timings
|
||||
onewire_host_set_timings_tm01x(host);
|
||||
|
||||
// Write sequence
|
||||
onewire_host_reset(host);
|
||||
onewire_host_write(host, TM01X_CMD_WRITE_FLAG);
|
||||
onewire_host_write_bit(host, true);
|
||||
furi_delay_us(5000);
|
||||
|
||||
onewire_host_reset(host);
|
||||
onewire_host_write(host, TM01X_CMD_WRITE_ROM);
|
||||
|
||||
for(size_t i = 0; i < data_size; ++i) {
|
||||
tm01x_write_byte(host, data[i]);
|
||||
}
|
||||
|
||||
return tm01x_read_and_verify(host, data, data_size);
|
||||
}
|
||||
7
lib/ibutton/protocols/blanks/tm01x.h
Normal file
7
lib/ibutton/protocols/blanks/tm01x.h
Normal file
@@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <core/kernel.h>
|
||||
#include <one_wire/one_wire_host.h>
|
||||
|
||||
// Function to write Dallas protocol to TM01x
|
||||
bool tm01x_write_dallas(OneWireHost* host, const uint8_t* data, size_t data_size);
|
||||
@@ -9,6 +9,8 @@
|
||||
#define TM2004_ANSWER_READ_MEMORY 0xF5
|
||||
|
||||
bool tm2004_write(OneWireHost* host, const uint8_t* data, size_t data_size) {
|
||||
onewire_host_set_timings_default(host);
|
||||
|
||||
onewire_host_reset(host);
|
||||
onewire_host_write(host, TM2004_CMD_WRITE_ROM);
|
||||
// Starting writing from address 0x0000
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
#include "../blanks/rw1990.h"
|
||||
#include "../blanks/tm2004.h"
|
||||
|
||||
#include "../blanks/tm01x.h"
|
||||
#define DS1990_FAMILY_CODE 0x01U
|
||||
#define DS1990_FAMILY_NAME "DS1990"
|
||||
|
||||
@@ -66,7 +66,8 @@ bool dallas_ds1990_write_id(OneWireHost* host, iButtonProtocolData* protocol_dat
|
||||
|
||||
return rw1990_write_v1(host, data->rom_data.bytes, sizeof(DallasCommonRomData)) ||
|
||||
rw1990_write_v2(host, data->rom_data.bytes, sizeof(DallasCommonRomData)) ||
|
||||
tm2004_write(host, data->rom_data.bytes, sizeof(DallasCommonRomData));
|
||||
tm2004_write(host, data->rom_data.bytes, sizeof(DallasCommonRomData)) ||
|
||||
tm01x_write_dallas(host, data->rom_data.bytes, sizeof(DallasCommonRomData));
|
||||
}
|
||||
|
||||
static bool dallas_ds1990_reset_callback(bool is_short, void* context) {
|
||||
|
||||
@@ -445,43 +445,35 @@ static NfcCommand mf_ultralight_poller_handler_auth(MfUltralightPoller* instance
|
||||
static NfcCommand mf_ultralight_poller_handler_auth_ultralight_c(MfUltralightPoller* instance) {
|
||||
NfcCommand command = NfcCommandContinue;
|
||||
FURI_LOG_D(TAG, "MfulC auth");
|
||||
if(mf_ultralight_support_feature(
|
||||
instance->feature_set, MfUltralightFeatureSupportAuthenticate)) {
|
||||
instance->mfu_event.type = MfUltralightPollerEventTypeAuthRequest;
|
||||
|
||||
command = instance->callback(instance->general_event, instance->context);
|
||||
if(!instance->mfu_event.data->auth_context.skip_auth) {
|
||||
FURI_LOG_D(TAG, "Trying to authenticate with 3des key");
|
||||
instance->auth_context.tdes_key = instance->mfu_event.data->auth_context.tdes_key;
|
||||
do {
|
||||
uint8_t output[MF_ULTRALIGHT_C_AUTH_DATA_SIZE];
|
||||
uint8_t RndA[MF_ULTRALIGHT_C_AUTH_RND_BLOCK_SIZE] = {0};
|
||||
furi_hal_random_fill_buf(RndA, sizeof(RndA));
|
||||
instance->error = mf_ultralight_poller_authenticate_start(instance, RndA, output);
|
||||
if(instance->error != MfUltralightErrorNone) break;
|
||||
do {
|
||||
if(mf_ultralight_support_feature(
|
||||
instance->feature_set, MfUltralightFeatureSupportAuthenticate)) {
|
||||
instance->mfu_event.type = MfUltralightPollerEventTypeAuthRequest;
|
||||
|
||||
uint8_t decoded_shifted_RndA[MF_ULTRALIGHT_C_AUTH_RND_BLOCK_SIZE] = {0};
|
||||
const uint8_t* RndB = output + MF_ULTRALIGHT_C_AUTH_RND_B_BLOCK_OFFSET;
|
||||
instance->error = mf_ultralight_poller_authenticate_end(
|
||||
instance, RndB, output, decoded_shifted_RndA);
|
||||
if(instance->error != MfUltralightErrorNone) break;
|
||||
command = instance->callback(instance->general_event, instance->context);
|
||||
if(!instance->mfu_event.data->auth_context.skip_auth) {
|
||||
FURI_LOG_D(TAG, "Trying to authenticate with 3des key");
|
||||
instance->auth_context.tdes_key = instance->mfu_event.data->auth_context.tdes_key;
|
||||
instance->error =
|
||||
mf_ultralight_poller_auth_tdes(instance, &instance->auth_context);
|
||||
|
||||
mf_ultralight_3des_shift_data(RndA);
|
||||
instance->auth_context.auth_success =
|
||||
(memcmp(RndA, decoded_shifted_RndA, sizeof(decoded_shifted_RndA)) == 0);
|
||||
|
||||
if(instance->auth_context.auth_success) {
|
||||
if(instance->error == MfUltralightErrorNone &&
|
||||
instance->auth_context.auth_success) {
|
||||
FURI_LOG_D(TAG, "Auth success");
|
||||
} else {
|
||||
FURI_LOG_D(TAG, "Auth failed");
|
||||
iso14443_3a_poller_halt(instance->iso14443_3a_poller);
|
||||
}
|
||||
} while(false);
|
||||
|
||||
if(instance->error != MfUltralightErrorNone || !instance->auth_context.auth_success) {
|
||||
FURI_LOG_D(TAG, "Auth failed");
|
||||
iso14443_3a_poller_halt(instance->iso14443_3a_poller);
|
||||
} else {
|
||||
// We assume here that it is card read without explicitly provided key
|
||||
// So we try to auth with default one
|
||||
instance->state = MfUltralightPollerStateTryDefaultMfulCKey;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
instance->state = MfUltralightPollerStateReadPages;
|
||||
instance->state = MfUltralightPollerStateReadPages;
|
||||
} while(false);
|
||||
|
||||
return command;
|
||||
}
|
||||
@@ -578,6 +570,40 @@ static NfcCommand mf_ultralight_poller_handler_try_default_pass(MfUltralightPoll
|
||||
return NfcCommandContinue;
|
||||
}
|
||||
|
||||
static NfcCommand
|
||||
mf_ultralight_poller_handler_try_default_ultralight_c_key(MfUltralightPoller* instance) {
|
||||
do {
|
||||
if(!mf_ultralight_support_feature(
|
||||
instance->feature_set, MfUltralightFeatureSupportAuthenticate)) {
|
||||
break;
|
||||
}
|
||||
|
||||
if(instance->auth_context.auth_success) {
|
||||
break;
|
||||
}
|
||||
|
||||
FURI_LOG_D(TAG, "Trying authentication with default 3DES key");
|
||||
|
||||
memcpy(
|
||||
&instance->auth_context.tdes_key.data,
|
||||
MF_ULTRALIGHT_C_DEFAULT_KEY,
|
||||
MF_ULTRALIGHT_C_AUTH_DES_KEY_SIZE);
|
||||
|
||||
instance->error = mf_ultralight_poller_auth_tdes(instance, &instance->auth_context);
|
||||
|
||||
if(instance->error == MfUltralightErrorNone && instance->auth_context.auth_success) {
|
||||
FURI_LOG_D(TAG, "Default 3DES key detected");
|
||||
} else {
|
||||
FURI_LOG_D(TAG, "Authentication attempt with default 3DES key failed");
|
||||
iso14443_3a_poller_halt(instance->iso14443_3a_poller);
|
||||
}
|
||||
|
||||
} while(false);
|
||||
|
||||
instance->state = MfUltralightPollerStateReadPages;
|
||||
return NfcCommandContinue;
|
||||
}
|
||||
|
||||
static NfcCommand
|
||||
mf_ultralight_poller_handler_check_mfuc_auth_status(MfUltralightPoller* instance) {
|
||||
instance->state = MfUltralightPollerStateReadSuccess;
|
||||
@@ -742,6 +768,8 @@ static const MfUltralightPollerReadHandler
|
||||
mf_ultralight_poller_handler_read_tearing_flags,
|
||||
[MfUltralightPollerStateAuth] = mf_ultralight_poller_handler_auth,
|
||||
[MfUltralightPollerStateTryDefaultPass] = mf_ultralight_poller_handler_try_default_pass,
|
||||
[MfUltralightPollerStateTryDefaultMfulCKey] =
|
||||
mf_ultralight_poller_handler_try_default_ultralight_c_key,
|
||||
[MfUltralightPollerStateCheckMfulCAuthStatus] =
|
||||
mf_ultralight_poller_handler_check_mfuc_auth_status,
|
||||
[MfUltralightPollerStateAuthMfulC] = mf_ultralight_poller_handler_auth_ultralight_c,
|
||||
|
||||
@@ -81,6 +81,19 @@ MfUltralightError mf_ultralight_poller_auth_pwd(
|
||||
MfUltralightPoller* instance,
|
||||
MfUltralightPollerAuthContext* data);
|
||||
|
||||
/**
|
||||
* @brief Perform 3DES authentication with key.
|
||||
*
|
||||
* Must ONLY be used inside the callback function.
|
||||
*
|
||||
* @param[in, out] instance pointer to the instance to be used in the transaction.
|
||||
* @param[in, out] data pointer to the authentication context.
|
||||
* @return MfUltralightErrorNone on success, an error code on failure.
|
||||
*/
|
||||
MfUltralightError mf_ultralight_poller_auth_tdes(
|
||||
MfUltralightPoller* instance,
|
||||
MfUltralightPollerAuthContext* data);
|
||||
|
||||
/**
|
||||
* @brief Start authentication procedure.
|
||||
*
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "mf_ultralight_poller_i.h"
|
||||
|
||||
#include <furi.h>
|
||||
#include <furi_hal.h>
|
||||
|
||||
#define TAG "MfUltralightPoller"
|
||||
|
||||
@@ -62,6 +63,38 @@ MfUltralightError mf_ultralight_poller_auth_pwd(
|
||||
return ret;
|
||||
}
|
||||
|
||||
MfUltralightError mf_ultralight_poller_auth_tdes(
|
||||
MfUltralightPoller* instance,
|
||||
MfUltralightPollerAuthContext* data) {
|
||||
furi_check(instance);
|
||||
furi_check(data);
|
||||
|
||||
MfUltralightError ret = MfUltralightErrorNone;
|
||||
|
||||
uint8_t output[MF_ULTRALIGHT_C_AUTH_DATA_SIZE];
|
||||
uint8_t RndA[MF_ULTRALIGHT_C_AUTH_RND_BLOCK_SIZE] = {0};
|
||||
furi_hal_random_fill_buf(RndA, sizeof(RndA));
|
||||
|
||||
ret = mf_ultralight_poller_authenticate_start(instance, RndA, output);
|
||||
|
||||
if(ret != MfUltralightErrorNone) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint8_t decoded_shifted_RndA[MF_ULTRALIGHT_C_AUTH_RND_BLOCK_SIZE] = {0};
|
||||
const uint8_t* RndB = output + MF_ULTRALIGHT_C_AUTH_RND_B_BLOCK_OFFSET;
|
||||
ret = mf_ultralight_poller_authenticate_end(instance, RndB, output, decoded_shifted_RndA);
|
||||
|
||||
if(ret != MfUltralightErrorNone) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
mf_ultralight_3des_shift_data(RndA);
|
||||
data->auth_success = (memcmp(RndA, decoded_shifted_RndA, sizeof(decoded_shifted_RndA)) == 0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static MfUltralightError mf_ultralight_poller_send_authenticate_cmd(
|
||||
MfUltralightPoller* instance,
|
||||
const uint8_t* cmd,
|
||||
@@ -134,7 +167,7 @@ MfUltralightError mf_ultralight_poller_authenticate_start(
|
||||
uint8_t* RndB = output + MF_ULTRALIGHT_C_AUTH_RND_B_BLOCK_OFFSET;
|
||||
mf_ultralight_3des_decrypt(
|
||||
&instance->des_context,
|
||||
instance->mfu_event.data->auth_context.tdes_key.data,
|
||||
instance->auth_context.tdes_key.data,
|
||||
iv,
|
||||
encRndB,
|
||||
sizeof(encRndB),
|
||||
@@ -145,7 +178,7 @@ MfUltralightError mf_ultralight_poller_authenticate_start(
|
||||
|
||||
mf_ultralight_3des_encrypt(
|
||||
&instance->des_context,
|
||||
instance->mfu_event.data->auth_context.tdes_key.data,
|
||||
instance->auth_context.tdes_key.data,
|
||||
encRndB,
|
||||
output,
|
||||
MF_ULTRALIGHT_C_AUTH_DATA_SIZE,
|
||||
@@ -179,7 +212,7 @@ MfUltralightError mf_ultralight_poller_authenticate_end(
|
||||
|
||||
mf_ultralight_3des_decrypt(
|
||||
&instance->des_context,
|
||||
instance->mfu_event.data->auth_context.tdes_key.data,
|
||||
instance->auth_context.tdes_key.data,
|
||||
RndB,
|
||||
bit_buffer_get_data(instance->rx_buffer) + 1,
|
||||
MF_ULTRALIGHT_C_AUTH_RND_BLOCK_SIZE,
|
||||
|
||||
@@ -59,6 +59,7 @@ typedef enum {
|
||||
MfUltralightPollerStateAuthMfulC,
|
||||
MfUltralightPollerStateReadPages,
|
||||
MfUltralightPollerStateTryDefaultPass,
|
||||
MfUltralightPollerStateTryDefaultMfulCKey,
|
||||
MfUltralightPollerStateCheckMfulCAuthStatus,
|
||||
MfUltralightPollerStateReadFailed,
|
||||
MfUltralightPollerStateReadSuccess,
|
||||
|
||||
@@ -8,16 +8,16 @@
|
||||
#include "one_wire_host.h"
|
||||
|
||||
typedef struct {
|
||||
uint16_t a;
|
||||
uint16_t b;
|
||||
uint16_t c;
|
||||
uint16_t d;
|
||||
uint16_t e;
|
||||
uint16_t f;
|
||||
uint16_t g;
|
||||
uint16_t h;
|
||||
uint16_t i;
|
||||
uint16_t j;
|
||||
uint16_t a; // Write 1 low time
|
||||
uint16_t b; // Write 1 high time
|
||||
uint16_t c; // Write 0 low time
|
||||
uint16_t d; // Write 0 high time
|
||||
uint16_t e; // Read low time
|
||||
uint16_t f; // Read high time
|
||||
uint16_t g; // Reset pre-delay
|
||||
uint16_t h; // Reset pulse
|
||||
uint16_t i; // Presence detect
|
||||
uint16_t j; // Reset post-delay
|
||||
} OneWireHostTimings;
|
||||
|
||||
static const OneWireHostTimings onewire_host_timings_normal = {
|
||||
@@ -46,6 +46,20 @@ static const OneWireHostTimings onewire_host_timings_overdrive = {
|
||||
.j = 40,
|
||||
};
|
||||
|
||||
// TM01x specific timings
|
||||
static const OneWireHostTimings onewire_host_timings_tm01x = {
|
||||
.a = 5,
|
||||
.b = 80,
|
||||
.c = 70,
|
||||
.d = 10,
|
||||
.e = 5,
|
||||
.f = 70,
|
||||
.g = 0,
|
||||
.h = 740,
|
||||
.i = 140,
|
||||
.j = 410,
|
||||
};
|
||||
|
||||
struct OneWireHost {
|
||||
const GpioPin* gpio_pin;
|
||||
const OneWireHostTimings* timings;
|
||||
@@ -354,3 +368,15 @@ void onewire_host_set_overdrive(OneWireHost* host, bool set) {
|
||||
|
||||
host->timings = set ? &onewire_host_timings_overdrive : &onewire_host_timings_normal;
|
||||
}
|
||||
|
||||
void onewire_host_set_timings_default(OneWireHost* host) {
|
||||
furi_check(host);
|
||||
|
||||
host->timings = &onewire_host_timings_normal;
|
||||
}
|
||||
|
||||
void onewire_host_set_timings_tm01x(OneWireHost* host) {
|
||||
furi_check(host);
|
||||
|
||||
host->timings = &onewire_host_timings_tm01x;
|
||||
}
|
||||
|
||||
@@ -125,6 +125,10 @@ bool onewire_host_search(OneWireHost* host, uint8_t* new_addr, OneWireHostSearch
|
||||
*/
|
||||
void onewire_host_set_overdrive(OneWireHost* host, bool set);
|
||||
|
||||
void onewire_host_set_timings_default(OneWireHost* host);
|
||||
|
||||
void onewire_host_set_timings_tm01x(OneWireHost* host);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -244,8 +244,11 @@ void subghz_protocol_decoder_came_feed(void* context, bool level, uint32_t durat
|
||||
switch(instance->decoder.parser_step) {
|
||||
case CameDecoderStepReset:
|
||||
if((!level) && (DURATION_DIFF(duration, subghz_protocol_came_const.te_short * 56) <
|
||||
subghz_protocol_came_const.te_delta * 47)) {
|
||||
subghz_protocol_came_const.te_delta * 63)) {
|
||||
// 17920 us + 7050 us = 24970 us max possible value old one
|
||||
// delta = 150 us x 63 = 9450 us + 17920 us = 27370 us max possible value
|
||||
//Found header CAME
|
||||
// 26700 us or 24000 us max possible values
|
||||
instance->decoder.parser_step = CameDecoderStepFoundStartBit;
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -234,8 +234,10 @@ void subghz_protocol_decoder_holtek_th12x_feed(void* context, bool level, uint32
|
||||
|
||||
switch(instance->decoder.parser_step) {
|
||||
case Holtek_HT12XDecoderStepReset:
|
||||
if((!level) && (DURATION_DIFF(duration, subghz_protocol_holtek_th12x_const.te_short * 36) <
|
||||
subghz_protocol_holtek_th12x_const.te_delta * 36)) {
|
||||
if((!level) && (DURATION_DIFF(duration, subghz_protocol_holtek_th12x_const.te_short * 28) <
|
||||
subghz_protocol_holtek_th12x_const.te_delta * 20)) {
|
||||
// 18720 us old max value
|
||||
// 12960 us corrected max value
|
||||
//Found Preambula
|
||||
instance->decoder.parser_step = Holtek_HT12XDecoderStepFoundStartBit;
|
||||
}
|
||||
|
||||
@@ -66,6 +66,7 @@ static const uint32_t subghz_frequency_list[] = {
|
||||
434775000, /* LPD433 last channels */
|
||||
438900000,
|
||||
440175000,
|
||||
462750000,
|
||||
464000000,
|
||||
467750000,
|
||||
|
||||
|
||||
@@ -136,9 +136,9 @@ void cli_registry_reload_external_commands(
|
||||
FURI_LOG_T(TAG, "Plugin: %s", plugin_filename);
|
||||
furi_string_set_str(plugin_name, plugin_filename);
|
||||
|
||||
furi_check(furi_string_end_with_str(plugin_name, ".fal"));
|
||||
if(!furi_string_end_with_str(plugin_name, ".fal")) continue;
|
||||
furi_string_replace_all_str(plugin_name, ".fal", "");
|
||||
furi_check(furi_string_start_with_str(plugin_name, config->fal_prefix));
|
||||
if(!furi_string_start_with_str(plugin_name, config->fal_prefix)) continue;
|
||||
furi_string_replace_at(plugin_name, 0, strlen(config->fal_prefix), "");
|
||||
|
||||
CliRegistryCommand command = {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
entry,status,name,type,params
|
||||
Version,+,86.0,,
|
||||
Version,+,86.1,,
|
||||
Header,+,applications/services/bt/bt_service/bt.h,,
|
||||
Header,+,applications/services/bt/bt_service/bt_keys_storage.h,,
|
||||
Header,+,applications/services/cli/cli.h,,
|
||||
@@ -2283,6 +2283,8 @@ Function,+,onewire_host_reset,_Bool,OneWireHost*
|
||||
Function,+,onewire_host_reset_search,void,OneWireHost*
|
||||
Function,+,onewire_host_search,_Bool,"OneWireHost*, uint8_t*, OneWireHostSearchMode"
|
||||
Function,+,onewire_host_set_overdrive,void,"OneWireHost*, _Bool"
|
||||
Function,+,onewire_host_set_timings_default,void,OneWireHost*
|
||||
Function,+,onewire_host_set_timings_tm01x,void,OneWireHost*
|
||||
Function,+,onewire_host_start,void,OneWireHost*
|
||||
Function,+,onewire_host_stop,void,OneWireHost*
|
||||
Function,+,onewire_host_target_search,void,"OneWireHost*, uint8_t"
|
||||
|
||||
|
@@ -1,5 +1,5 @@
|
||||
entry,status,name,type,params
|
||||
Version,+,86.0,,
|
||||
Version,+,86.1,,
|
||||
Header,+,applications/drivers/subghz/cc1101_ext/cc1101_ext_interconnect.h,,
|
||||
Header,+,applications/services/bt/bt_service/bt.h,,
|
||||
Header,+,applications/services/bt/bt_service/bt_keys_storage.h,,
|
||||
@@ -2741,6 +2741,7 @@ Function,+,mf_ultralight_is_equal,_Bool,"const MfUltralightData*, const MfUltral
|
||||
Function,+,mf_ultralight_is_page_pwd_or_pack,_Bool,"MfUltralightType, uint16_t"
|
||||
Function,+,mf_ultralight_load,_Bool,"MfUltralightData*, FlipperFormat*, uint32_t"
|
||||
Function,+,mf_ultralight_poller_auth_pwd,MfUltralightError,"MfUltralightPoller*, MfUltralightPollerAuthContext*"
|
||||
Function,+,mf_ultralight_poller_auth_tdes,MfUltralightError,"MfUltralightPoller*, MfUltralightPollerAuthContext*"
|
||||
Function,+,mf_ultralight_poller_authenticate_end,MfUltralightError,"MfUltralightPoller*, const uint8_t*, const uint8_t*, uint8_t*"
|
||||
Function,+,mf_ultralight_poller_authenticate_start,MfUltralightError,"MfUltralightPoller*, const uint8_t*, uint8_t*"
|
||||
Function,+,mf_ultralight_poller_read_counter,MfUltralightError,"MfUltralightPoller*, uint8_t, MfUltralightCounter*"
|
||||
@@ -2970,6 +2971,8 @@ Function,+,onewire_host_reset,_Bool,OneWireHost*
|
||||
Function,+,onewire_host_reset_search,void,OneWireHost*
|
||||
Function,+,onewire_host_search,_Bool,"OneWireHost*, uint8_t*, OneWireHostSearchMode"
|
||||
Function,+,onewire_host_set_overdrive,void,"OneWireHost*, _Bool"
|
||||
Function,+,onewire_host_set_timings_default,void,OneWireHost*
|
||||
Function,+,onewire_host_set_timings_tm01x,void,OneWireHost*
|
||||
Function,+,onewire_host_start,void,OneWireHost*
|
||||
Function,+,onewire_host_stop,void,OneWireHost*
|
||||
Function,+,onewire_host_target_search,void,"OneWireHost*, uint8_t"
|
||||
|
||||
|
Reference in New Issue
Block a user