mirror of
https://github.com/DarkFlippers/unleashed-firmware
synced 2024-11-27 15:00:46 +00:00
Merge branch 'Eng1n33r:dev' into dev
This commit is contained in:
commit
d65c7b5f4c
33 changed files with 1664 additions and 109 deletions
|
@ -1,7 +1,9 @@
|
||||||
### New changes
|
### New changes
|
||||||
* Set poweroff button timer to 2sec
|
* Add SubGhz Bruteforce plugin (by @Ganapati & @xMasterX) (PR #57) - saving functionality and many fixes by @xMasterX
|
||||||
* Debug apps (USB Mouse, UART Echo) now included in release build
|
* GUI Changes to LFRFID Fuzzer
|
||||||
* OFW: Toolchain update
|
* NRFSniff: Adds unique count display (by @Graf3x) (PR #56)
|
||||||
|
* Updated universal remote assets (by @Amec0e)
|
||||||
|
* OFW: SubGhz: fix decoder keeloq
|
||||||
|
|
||||||
**Note: To avoid issues prefer installing using web updater or by self update package, all needed assets will be installed**
|
**Note: To avoid issues prefer installing using web updater or by self update package, all needed assets will be installed**
|
||||||
|
|
||||||
|
|
|
@ -46,5 +46,4 @@ typedef struct {
|
||||||
PinCode pin_code;
|
PinCode pin_code;
|
||||||
uint8_t is_locked;
|
uint8_t is_locked;
|
||||||
uint32_t auto_lock_delay_ms;
|
uint32_t auto_lock_delay_ms;
|
||||||
uint8_t displayBatteryPercentage;
|
|
||||||
} DesktopSettings;
|
} DesktopSettings;
|
||||||
|
|
|
@ -8,7 +8,6 @@
|
||||||
#define SCENE_EVENT_SELECT_FAVORITE_SECONDARY 1
|
#define SCENE_EVENT_SELECT_FAVORITE_SECONDARY 1
|
||||||
#define SCENE_EVENT_SELECT_PIN_SETUP 2
|
#define SCENE_EVENT_SELECT_PIN_SETUP 2
|
||||||
#define SCENE_EVENT_SELECT_AUTO_LOCK_DELAY 3
|
#define SCENE_EVENT_SELECT_AUTO_LOCK_DELAY 3
|
||||||
#define SCENE_EVENT_SELECT_BATTERY_DISPLAY 4
|
|
||||||
|
|
||||||
#define AUTO_LOCK_DELAY_COUNT 9
|
#define AUTO_LOCK_DELAY_COUNT 9
|
||||||
const char* const auto_lock_delay_text[AUTO_LOCK_DELAY_COUNT] = {
|
const char* const auto_lock_delay_text[AUTO_LOCK_DELAY_COUNT] = {
|
||||||
|
@ -26,32 +25,12 @@ const char* const auto_lock_delay_text[AUTO_LOCK_DELAY_COUNT] = {
|
||||||
const uint32_t auto_lock_delay_value[AUTO_LOCK_DELAY_COUNT] =
|
const uint32_t auto_lock_delay_value[AUTO_LOCK_DELAY_COUNT] =
|
||||||
{0, 10000, 15000, 30000, 60000, 90000, 120000, 300000, 600000};
|
{0, 10000, 15000, 30000, 60000, 90000, 120000, 300000, 600000};
|
||||||
|
|
||||||
#define BATTERY_VIEW_COUNT 5
|
|
||||||
|
|
||||||
const char* const battery_view_count_text[BATTERY_VIEW_COUNT] = {
|
|
||||||
"Bar",
|
|
||||||
"%",
|
|
||||||
"Inv. %",
|
|
||||||
"Retro 3",
|
|
||||||
"Retro 5",
|
|
||||||
};
|
|
||||||
|
|
||||||
const uint32_t displayBatteryPercentage_value[BATTERY_VIEW_COUNT] = {0, 1, 2, 3, 4};
|
|
||||||
|
|
||||||
static void desktop_settings_scene_start_var_list_enter_callback(void* context, uint32_t index) {
|
static void desktop_settings_scene_start_var_list_enter_callback(void* context, uint32_t index) {
|
||||||
DesktopSettingsApp* app = context;
|
DesktopSettingsApp* app = context;
|
||||||
view_dispatcher_send_custom_event(app->view_dispatcher, index);
|
view_dispatcher_send_custom_event(app->view_dispatcher, index);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void desktop_settings_scene_start_battery_view_changed(VariableItem* item) {
|
|
||||||
DesktopSettingsApp* app = variable_item_get_context(item);
|
|
||||||
uint8_t index = variable_item_get_current_value_index(item);
|
|
||||||
|
|
||||||
variable_item_set_current_value_text(item, battery_view_count_text[index]);
|
|
||||||
app->settings.displayBatteryPercentage = index;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void desktop_settings_scene_start_auto_lock_delay_changed(VariableItem* item) {
|
static void desktop_settings_scene_start_auto_lock_delay_changed(VariableItem* item) {
|
||||||
DesktopSettingsApp* app = variable_item_get_context(item);
|
DesktopSettingsApp* app = variable_item_get_context(item);
|
||||||
uint8_t index = variable_item_get_current_value_index(item);
|
uint8_t index = variable_item_get_current_value_index(item);
|
||||||
|
@ -87,20 +66,6 @@ void desktop_settings_scene_start_on_enter(void* context) {
|
||||||
variable_item_set_current_value_index(item, value_index);
|
variable_item_set_current_value_index(item, value_index);
|
||||||
variable_item_set_current_value_text(item, auto_lock_delay_text[value_index]);
|
variable_item_set_current_value_text(item, auto_lock_delay_text[value_index]);
|
||||||
|
|
||||||
item = variable_item_list_add(
|
|
||||||
variable_item_list,
|
|
||||||
"Battery View",
|
|
||||||
BATTERY_VIEW_COUNT,
|
|
||||||
desktop_settings_scene_start_battery_view_changed,
|
|
||||||
app);
|
|
||||||
|
|
||||||
value_index = value_index_uint32(
|
|
||||||
app->settings.displayBatteryPercentage,
|
|
||||||
displayBatteryPercentage_value,
|
|
||||||
BATTERY_VIEW_COUNT);
|
|
||||||
variable_item_set_current_value_index(item, value_index);
|
|
||||||
variable_item_set_current_value_text(item, battery_view_count_text[value_index]);
|
|
||||||
|
|
||||||
view_dispatcher_switch_to_view(app->view_dispatcher, DesktopSettingsAppViewVarItemList);
|
view_dispatcher_switch_to_view(app->view_dispatcher, DesktopSettingsAppViewVarItemList);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,9 +92,6 @@ bool desktop_settings_scene_start_on_event(void* context, SceneManagerEvent even
|
||||||
case SCENE_EVENT_SELECT_AUTO_LOCK_DELAY:
|
case SCENE_EVENT_SELECT_AUTO_LOCK_DELAY:
|
||||||
consumed = true;
|
consumed = true;
|
||||||
break;
|
break;
|
||||||
case SCENE_EVENT_SELECT_BATTERY_DISPLAY:
|
|
||||||
consumed = true;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return consumed;
|
return consumed;
|
||||||
|
|
|
@ -6,5 +6,5 @@ App(
|
||||||
cdefines=["APP_FLIP_FRID"],
|
cdefines=["APP_FLIP_FRID"],
|
||||||
requires=["gui"],
|
requires=["gui"],
|
||||||
stack_size=1 * 1024,
|
stack_size=1 * 1024,
|
||||||
order=29,
|
order=13,
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include "flipfrid_scene_run_attack.h"
|
#include "flipfrid_scene_run_attack.h"
|
||||||
|
#include <gui/elements.h>
|
||||||
|
|
||||||
uint8_t counter = 0;
|
uint8_t counter = 0;
|
||||||
#define TIME_BETWEEN_CARDS 5
|
#define TIME_BETWEEN_CARDS 5
|
||||||
|
@ -182,7 +183,7 @@ void flipfrid_scene_run_attack_on_draw(Canvas* canvas, FlipFridState* context) {
|
||||||
canvas_set_color(canvas, ColorBlack);
|
canvas_set_color(canvas, ColorBlack);
|
||||||
|
|
||||||
// Frame
|
// Frame
|
||||||
canvas_draw_frame(canvas, 0, 0, 128, 64);
|
//canvas_draw_frame(canvas, 0, 0, 128, 64);
|
||||||
|
|
||||||
// Title
|
// Title
|
||||||
canvas_set_font(canvas, FontPrimary);
|
canvas_set_font(canvas, FontPrimary);
|
||||||
|
@ -202,11 +203,12 @@ void flipfrid_scene_run_attack_on_draw(Canvas* canvas, FlipFridState* context) {
|
||||||
canvas_draw_str_aligned(canvas, 64, 24, AlignCenter, AlignTop, uid);
|
canvas_draw_str_aligned(canvas, 64, 24, AlignCenter, AlignTop, uid);
|
||||||
|
|
||||||
canvas_set_font(canvas, FontSecondary);
|
canvas_set_font(canvas, FontSecondary);
|
||||||
char start_stop_msg[20];
|
//char start_stop_msg[20];
|
||||||
if(context->is_attacking) {
|
if(context->is_attacking) {
|
||||||
snprintf(start_stop_msg, sizeof(start_stop_msg), " Press OK to stop ");
|
elements_button_center(canvas, "Stop");
|
||||||
|
//snprintf(start_stop_msg, sizeof(start_stop_msg), " Press OK to stop ");
|
||||||
} else {
|
} else {
|
||||||
snprintf(start_stop_msg, sizeof(start_stop_msg), " Press OK to start ");
|
elements_button_center(canvas, "Start");
|
||||||
}
|
}
|
||||||
canvas_draw_str_aligned(canvas, 64, 44, AlignCenter, AlignTop, start_stop_msg);
|
//canvas_draw_str_aligned(canvas, 64, 44, AlignCenter, AlignTop, start_stop_msg);
|
||||||
}
|
}
|
||||||
|
|
|
@ -104,7 +104,7 @@ void flipfrid_scene_select_field_on_draw(Canvas* canvas, FlipFridState* context)
|
||||||
canvas_set_color(canvas, ColorBlack);
|
canvas_set_color(canvas, ColorBlack);
|
||||||
|
|
||||||
// Frame
|
// Frame
|
||||||
canvas_draw_frame(canvas, 0, 0, 128, 64);
|
//canvas_draw_frame(canvas, 0, 0, 128, 64);
|
||||||
|
|
||||||
// Title
|
// Title
|
||||||
canvas_set_font(canvas, FontPrimary);
|
canvas_set_font(canvas, FontPrimary);
|
||||||
|
|
|
@ -12,7 +12,6 @@ const CanvasFontParameters canvas_font_params[FontTotalNumber] = {
|
||||||
[FontSecondary] = {.leading_default = 11, .leading_min = 9, .height = 7, .descender = 2},
|
[FontSecondary] = {.leading_default = 11, .leading_min = 9, .height = 7, .descender = 2},
|
||||||
[FontKeyboard] = {.leading_default = 11, .leading_min = 9, .height = 7, .descender = 2},
|
[FontKeyboard] = {.leading_default = 11, .leading_min = 9, .height = 7, .descender = 2},
|
||||||
[FontBigNumbers] = {.leading_default = 18, .leading_min = 16, .height = 15, .descender = 0},
|
[FontBigNumbers] = {.leading_default = 18, .leading_min = 16, .height = 15, .descender = 0},
|
||||||
[FontBatteryPercent] = {.leading_default = 11, .leading_min = 9, .height = 6, .descender = 0},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Canvas* canvas_init() {
|
Canvas* canvas_init() {
|
||||||
|
@ -133,8 +132,6 @@ void canvas_set_font(Canvas* canvas, Font font) {
|
||||||
u8g2_SetFont(&canvas->fb, u8g2_font_profont11_mr);
|
u8g2_SetFont(&canvas->fb, u8g2_font_profont11_mr);
|
||||||
} else if(font == FontBigNumbers) {
|
} else if(font == FontBigNumbers) {
|
||||||
u8g2_SetFont(&canvas->fb, u8g2_font_profont22_tn);
|
u8g2_SetFont(&canvas->fb, u8g2_font_profont22_tn);
|
||||||
} else if(font == FontBatteryPercent) {
|
|
||||||
u8g2_SetFont(&canvas->fb, u8g2_font_5x7_tf); //u8g2_font_micro_tr);
|
|
||||||
} else {
|
} else {
|
||||||
furi_crash(NULL);
|
furi_crash(NULL);
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,6 @@ typedef enum {
|
||||||
FontSecondary,
|
FontSecondary,
|
||||||
FontKeyboard,
|
FontKeyboard,
|
||||||
FontBigNumbers,
|
FontBigNumbers,
|
||||||
FontBatteryPercent,
|
|
||||||
|
|
||||||
// Keep last for fonts number calculation
|
// Keep last for fonts number calculation
|
||||||
FontTotalNumber,
|
FontTotalNumber,
|
||||||
|
|
|
@ -78,5 +78,6 @@ App(
|
||||||
"wifi_scanner",
|
"wifi_scanner",
|
||||||
"multi_converter",
|
"multi_converter",
|
||||||
"flipfrid",
|
"flipfrid",
|
||||||
|
"subbrute",
|
||||||
],
|
],
|
||||||
)
|
)
|
|
@ -1,6 +1,5 @@
|
||||||
#include "power_i.h"
|
#include "power_i.h"
|
||||||
#include "views/power_off.h"
|
#include "views/power_off.h"
|
||||||
#include "desktop/desktop_settings/desktop_settings.h"
|
|
||||||
|
|
||||||
#include <furi.h>
|
#include <furi.h>
|
||||||
#include <furi_hal.h>
|
#include <furi_hal.h>
|
||||||
|
@ -15,51 +14,7 @@ void power_draw_battery_callback(Canvas* canvas, void* context) {
|
||||||
canvas_draw_icon(canvas, 0, 0, &I_Battery_26x8);
|
canvas_draw_icon(canvas, 0, 0, &I_Battery_26x8);
|
||||||
|
|
||||||
if(power->info.gauge_is_ok) {
|
if(power->info.gauge_is_ok) {
|
||||||
|
|
||||||
char batteryPercentile[5];
|
|
||||||
snprintf(batteryPercentile, sizeof(batteryPercentile), "%d", power->info.charge);
|
|
||||||
strcat(batteryPercentile, "%");
|
|
||||||
|
|
||||||
if((power->displayBatteryPercentage == 1) && (power->state != PowerStateCharging)) { //if display battery percentage, black background white text
|
|
||||||
canvas_set_font(canvas, FontBatteryPercent);
|
|
||||||
canvas_set_color(canvas, ColorBlack);
|
|
||||||
canvas_draw_box(canvas, 1, 1, 22, 6);
|
|
||||||
canvas_set_color(canvas, ColorWhite);
|
|
||||||
canvas_draw_str_aligned(canvas, 12, 4, AlignCenter, AlignCenter, batteryPercentile);
|
|
||||||
} else if((power->displayBatteryPercentage == 2) && (power->state != PowerStateCharging)) { //if display inverted percentage, white background black text
|
|
||||||
canvas_set_font(canvas, FontBatteryPercent);
|
|
||||||
canvas_set_color(canvas, ColorBlack);
|
|
||||||
canvas_draw_str_aligned(canvas, 12, 4, AlignCenter, AlignCenter, batteryPercentile);
|
|
||||||
} else if((power->displayBatteryPercentage == 3) && (power->state != PowerStateCharging)) { //Retro style segmented display, 3 parts
|
|
||||||
if(power->info.charge > 25) {
|
|
||||||
canvas_draw_box(canvas, 2, 2, 6, 4);
|
|
||||||
}
|
|
||||||
if(power->info.charge > 50) {
|
|
||||||
canvas_draw_box(canvas, 9, 2, 6, 4);
|
|
||||||
}
|
|
||||||
if(power->info.charge > 75) {
|
|
||||||
canvas_draw_box(canvas, 16, 2, 6, 4);
|
|
||||||
}
|
|
||||||
} else if((power->displayBatteryPercentage == 4) && (power->state != PowerStateCharging)) { //Retro style segmented display, 5 parts
|
|
||||||
if(power->info.charge > 10) {
|
|
||||||
canvas_draw_box(canvas, 2, 2, 3, 4);
|
|
||||||
}
|
|
||||||
if(power->info.charge > 30) {
|
|
||||||
canvas_draw_box(canvas, 6, 2, 3, 4);
|
|
||||||
}
|
|
||||||
if(power->info.charge > 50) {
|
|
||||||
canvas_draw_box(canvas, 10, 2, 3, 4);
|
|
||||||
}
|
|
||||||
if(power->info.charge > 70) {
|
|
||||||
canvas_draw_box(canvas, 14, 2, 3, 4);
|
|
||||||
}
|
|
||||||
if(power->info.charge > 90) {
|
|
||||||
canvas_draw_box(canvas, 18, 2, 3, 4);
|
|
||||||
}
|
|
||||||
} else { //default bar display, added here to serve as fallback/default behaviour.
|
|
||||||
canvas_draw_box(canvas, 2, 2, (power->info.charge + 4) / 5, 4);
|
canvas_draw_box(canvas, 2, 2, (power->info.charge + 4) / 5, 4);
|
||||||
}
|
|
||||||
|
|
||||||
if(power->state == PowerStateCharging) {
|
if(power->state == PowerStateCharging) {
|
||||||
canvas_set_bitmap_mode(canvas, 1);
|
canvas_set_bitmap_mode(canvas, 1);
|
||||||
canvas_set_color(canvas, ColorWhite);
|
canvas_set_color(canvas, ColorWhite);
|
||||||
|
|
|
@ -36,7 +36,6 @@ struct Power {
|
||||||
|
|
||||||
bool battery_low;
|
bool battery_low;
|
||||||
bool show_low_bat_level_message;
|
bool show_low_bat_level_message;
|
||||||
uint8_t displayBatteryPercentage;
|
|
||||||
uint8_t battery_level;
|
uint8_t battery_level;
|
||||||
uint8_t power_off_timeout;
|
uint8_t power_off_timeout;
|
||||||
|
|
||||||
|
|
8
applications/subbrute/LICENSE.md
Normal file
8
applications/subbrute/LICENSE.md
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
/*
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
* "THE BEER-WARE LICENSE" (Revision 42):
|
||||||
|
* @G4N4P4T1 wrote this file. As long as you retain this notice you
|
||||||
|
* can do whatever you want with this stuff. If we meet some day, and you think
|
||||||
|
* this stuff is worth it, you can buy me a beer in return.
|
||||||
|
* ----------------------------------------------------------------------------
|
||||||
|
*/
|
4
applications/subbrute/README.md
Normal file
4
applications/subbrute/README.md
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
# FlipFrid
|
||||||
|
|
||||||
|
SubGhz Fuzzer
|
||||||
|
select your base message, the field to fuzz and let's get fuzzy !
|
10
applications/subbrute/application.fam
Normal file
10
applications/subbrute/application.fam
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
App(
|
||||||
|
appid="subbrute",
|
||||||
|
name="SubGHz Bruteforcer",
|
||||||
|
apptype=FlipperAppType.PLUGIN,
|
||||||
|
entry_point="subbrute_start",
|
||||||
|
cdefines=["APP_SUB_BRUTE"],
|
||||||
|
requires=["gui","dialogs"],
|
||||||
|
stack_size=2 * 1024,
|
||||||
|
order=11,
|
||||||
|
)
|
198
applications/subbrute/scene/subbrute_scene_entrypoint.c
Normal file
198
applications/subbrute/scene/subbrute_scene_entrypoint.c
Normal file
|
@ -0,0 +1,198 @@
|
||||||
|
#include "subbrute_scene_entrypoint.h"
|
||||||
|
#include "../subbrute_utils.h"
|
||||||
|
|
||||||
|
string_t subbrute_menu_items[9];
|
||||||
|
|
||||||
|
void subbrute_scene_entrypoint_menu_callback(SubBruteState* context, uint32_t index) {
|
||||||
|
string_set_str(context->preset, "FuriHalSubGhzPresetOok650Async");
|
||||||
|
string_set_str(context->protocol, "RAW");
|
||||||
|
context->repeat = 5;
|
||||||
|
context->te = 0;
|
||||||
|
context->attack = index;
|
||||||
|
switch(index) {
|
||||||
|
case SubBruteAttackLoadFile:
|
||||||
|
context->current_scene = SceneSelectFile;
|
||||||
|
break;
|
||||||
|
case SubBruteAttackCAME12bit433:
|
||||||
|
context->frequency = 433920000;
|
||||||
|
context->bit = 12;
|
||||||
|
string_set_str(context->protocol, "CAME");
|
||||||
|
string_set_str(context->preset, "FuriHalSubGhzPresetOok650Async");
|
||||||
|
if(!subbrute_is_frequency_allowed(context)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
context->current_scene = SceneAttack;
|
||||||
|
break;
|
||||||
|
case SubBruteAttackCAME12bit868:
|
||||||
|
context->frequency = 868350000;
|
||||||
|
context->bit = 12;
|
||||||
|
string_set_str(context->protocol, "CAME");
|
||||||
|
string_set_str(context->preset, "FuriHalSubGhzPresetOok650Async");
|
||||||
|
if(!subbrute_is_frequency_allowed(context)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
context->current_scene = SceneAttack;
|
||||||
|
break;
|
||||||
|
case SubBruteAttackChamberlain9bit315:
|
||||||
|
context->frequency = 315000000;
|
||||||
|
context->bit = 9;
|
||||||
|
string_set_str(context->protocol, "Cham_Code");
|
||||||
|
string_set_str(context->preset, "FuriHalSubGhzPresetOok650Async");
|
||||||
|
|
||||||
|
if(!subbrute_is_frequency_allowed(context)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
context->current_scene = SceneAttack;
|
||||||
|
break;
|
||||||
|
case SubBruteAttackChamberlain9bit390:
|
||||||
|
context->frequency = 390000000;
|
||||||
|
context->bit = 9;
|
||||||
|
string_set_str(context->protocol, "Cham_Code");
|
||||||
|
string_set_str(context->preset, "FuriHalSubGhzPresetOok650Async");
|
||||||
|
|
||||||
|
if(!subbrute_is_frequency_allowed(context)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
context->current_scene = SceneAttack;
|
||||||
|
break;
|
||||||
|
case SubBruteAttackLinear10bit300:
|
||||||
|
context->frequency = 300000000;
|
||||||
|
context->bit = 10;
|
||||||
|
string_set_str(context->protocol, "Linear");
|
||||||
|
string_set_str(context->preset, "FuriHalSubGhzPresetOok650Async");
|
||||||
|
if(!subbrute_is_frequency_allowed(context)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
context->current_scene = SceneAttack;
|
||||||
|
break;
|
||||||
|
case SubBruteAttackLinear10bit310:
|
||||||
|
context->frequency = 310000000;
|
||||||
|
context->bit = 10;
|
||||||
|
string_set_str(context->protocol, "Linear");
|
||||||
|
string_set_str(context->preset, "FuriHalSubGhzPresetOok650Async");
|
||||||
|
if(!subbrute_is_frequency_allowed(context)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
context->current_scene = SceneAttack;
|
||||||
|
break;
|
||||||
|
case SubBruteAttackNICE12bit433:
|
||||||
|
context->frequency = 433920000;
|
||||||
|
context->bit = 12;
|
||||||
|
string_set_str(context->protocol, "Nice FLO");
|
||||||
|
string_set_str(context->preset, "FuriHalSubGhzPresetOok650Async");
|
||||||
|
if(!subbrute_is_frequency_allowed(context)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
context->current_scene = SceneAttack;
|
||||||
|
break;
|
||||||
|
case SubBruteAttackNICE12bit868:
|
||||||
|
context->frequency = 868350000;
|
||||||
|
context->bit = 12;
|
||||||
|
string_set_str(context->protocol, "Nice FLO");
|
||||||
|
string_set_str(context->preset, "FuriHalSubGhzPresetOok650Async");
|
||||||
|
if(!subbrute_is_frequency_allowed(context)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
context->current_scene = SceneAttack;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void subbrute_scene_entrypoint_on_enter(SubBruteState* context) {
|
||||||
|
// Clear the previous payload
|
||||||
|
context->menu_index = 0;
|
||||||
|
for(uint32_t i = 0; i < 9; i++) {
|
||||||
|
string_init(subbrute_menu_items[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
string_set(subbrute_menu_items[0], "BF existing dump");
|
||||||
|
string_set(subbrute_menu_items[1], "CAME 12bit 433mhz");
|
||||||
|
string_set(subbrute_menu_items[2], "CAME 12bit 868mhz");
|
||||||
|
string_set(subbrute_menu_items[3], "Chamberlain 9bit 315mhz");
|
||||||
|
string_set(subbrute_menu_items[4], "Chamberlain 9bit 390mhz");
|
||||||
|
string_set(subbrute_menu_items[5], "Linear 10bit 300mhz");
|
||||||
|
string_set(subbrute_menu_items[6], "Linear 10bit 310mhz");
|
||||||
|
string_set(subbrute_menu_items[7], "NICE 12bit 433mhz");
|
||||||
|
string_set(subbrute_menu_items[8], "NICE 12bit 868mhz");
|
||||||
|
}
|
||||||
|
|
||||||
|
void subbrute_scene_entrypoint_on_exit(SubBruteState* context) {
|
||||||
|
UNUSED(context);
|
||||||
|
for(uint32_t i = 0; i < 9; i++) {
|
||||||
|
string_clear(subbrute_menu_items[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void subbrute_scene_entrypoint_on_tick(SubBruteState* context) {
|
||||||
|
UNUSED(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
void subbrute_scene_entrypoint_on_event(SubBruteEvent event, SubBruteState* context) {
|
||||||
|
if(event.evt_type == EventTypeKey) {
|
||||||
|
if(event.input_type == InputTypeShort) {
|
||||||
|
switch(event.key) {
|
||||||
|
case InputKeyDown:
|
||||||
|
if(context->menu_index < SubBruteAttackNICE12bit868) {
|
||||||
|
context->menu_index++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case InputKeyUp:
|
||||||
|
if(context->menu_index > SubBruteAttackLoadFile) {
|
||||||
|
context->menu_index--;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case InputKeyLeft:
|
||||||
|
case InputKeyRight:
|
||||||
|
break;
|
||||||
|
case InputKeyOk:
|
||||||
|
subbrute_scene_entrypoint_menu_callback(context, context->menu_index);
|
||||||
|
break;
|
||||||
|
case InputKeyBack:
|
||||||
|
context->is_running = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void subbrute_scene_entrypoint_on_draw(Canvas* canvas, SubBruteState* context) {
|
||||||
|
canvas_clear(canvas);
|
||||||
|
canvas_set_color(canvas, ColorBlack);
|
||||||
|
|
||||||
|
// Title
|
||||||
|
canvas_set_font(canvas, FontPrimary);
|
||||||
|
canvas_draw_str_aligned(canvas, 64, 6, AlignCenter, AlignTop, "SubGHz Fuzzer");
|
||||||
|
|
||||||
|
if(context->menu_index > SubBruteAttackLoadFile) {
|
||||||
|
canvas_set_font(canvas, FontSecondary);
|
||||||
|
canvas_draw_str_aligned(
|
||||||
|
canvas,
|
||||||
|
64,
|
||||||
|
24,
|
||||||
|
AlignCenter,
|
||||||
|
AlignTop,
|
||||||
|
string_get_cstr(subbrute_menu_items[context->menu_index - 1]));
|
||||||
|
}
|
||||||
|
|
||||||
|
canvas_set_font(canvas, FontPrimary);
|
||||||
|
canvas_draw_str_aligned(
|
||||||
|
canvas,
|
||||||
|
64,
|
||||||
|
36,
|
||||||
|
AlignCenter,
|
||||||
|
AlignTop,
|
||||||
|
string_get_cstr(subbrute_menu_items[context->menu_index]));
|
||||||
|
|
||||||
|
if(context->menu_index < SubBruteAttackNICE12bit868) {
|
||||||
|
canvas_set_font(canvas, FontSecondary);
|
||||||
|
canvas_draw_str_aligned(
|
||||||
|
canvas,
|
||||||
|
64,
|
||||||
|
48,
|
||||||
|
AlignCenter,
|
||||||
|
AlignTop,
|
||||||
|
string_get_cstr(subbrute_menu_items[context->menu_index + 1]));
|
||||||
|
}
|
||||||
|
}
|
8
applications/subbrute/scene/subbrute_scene_entrypoint.h
Normal file
8
applications/subbrute/scene/subbrute_scene_entrypoint.h
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
#pragma once
|
||||||
|
#include "../subbrute.h"
|
||||||
|
|
||||||
|
void subbrute_scene_entrypoint_on_enter(SubBruteState* context);
|
||||||
|
void subbrute_scene_entrypoint_on_exit(SubBruteState* context);
|
||||||
|
void subbrute_scene_entrypoint_on_tick(SubBruteState* context);
|
||||||
|
void subbrute_scene_entrypoint_on_event(SubBruteEvent event, SubBruteState* context);
|
||||||
|
void subbrute_scene_entrypoint_on_draw(Canvas* canvas, SubBruteState* context);
|
212
applications/subbrute/scene/subbrute_scene_load_file.c
Normal file
212
applications/subbrute/scene/subbrute_scene_load_file.c
Normal file
|
@ -0,0 +1,212 @@
|
||||||
|
#include "subbrute_scene_load_file.h"
|
||||||
|
#include "subbrute_scene_entrypoint.h"
|
||||||
|
#include "../subbrute_utils.h"
|
||||||
|
#include <lib/subghz/protocols/registry.h>
|
||||||
|
|
||||||
|
#define SUBGHZ_APP_PATH_FOLDER "/ext/subghz"
|
||||||
|
|
||||||
|
bool subbrute_load(SubBruteState* context, const char* file_path) {
|
||||||
|
bool result = false;
|
||||||
|
|
||||||
|
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||||
|
FlipperFormat* fff_data_file = flipper_format_file_alloc(storage);
|
||||||
|
|
||||||
|
string_t temp_str;
|
||||||
|
string_init(temp_str);
|
||||||
|
uint32_t temp_data32;
|
||||||
|
|
||||||
|
do {
|
||||||
|
if(!flipper_format_file_open_existing(fff_data_file, file_path)) {
|
||||||
|
FURI_LOG_E(TAG, "Error open file %s", file_path);
|
||||||
|
string_reset(context->notification_msg);
|
||||||
|
string_set_str(context->notification_msg, "Error open file");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(!flipper_format_read_header(fff_data_file, temp_str, &temp_data32)) {
|
||||||
|
FURI_LOG_E(TAG, "Missing or incorrect header");
|
||||||
|
string_reset(context->notification_msg);
|
||||||
|
string_set_str(context->notification_msg, "Missing or incorrect header");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Frequency
|
||||||
|
if(flipper_format_read_uint32(fff_data_file, "Frequency", &temp_data32, 1)) {
|
||||||
|
FURI_LOG_I(TAG, "Frequency: %d", temp_data32);
|
||||||
|
context->frequency = temp_data32;
|
||||||
|
if(!subbrute_is_frequency_allowed(context)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
FURI_LOG_E(TAG, "Missing or incorrect Frequency");
|
||||||
|
string_reset(context->notification_msg);
|
||||||
|
string_set_str(context->notification_msg, "Missing or incorrect Frequency");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Preset
|
||||||
|
if(!flipper_format_read_string(fff_data_file, "Preset", context->preset)) {
|
||||||
|
FURI_LOG_E(TAG, "Preset FAIL");
|
||||||
|
string_reset(context->notification_msg);
|
||||||
|
string_set_str(context->notification_msg, "Preset FAIL");
|
||||||
|
}
|
||||||
|
// Protocol
|
||||||
|
if(!flipper_format_read_string(fff_data_file, "Protocol", context->protocol)) {
|
||||||
|
FURI_LOG_E(TAG, "Missing Protocol");
|
||||||
|
string_reset(context->notification_msg);
|
||||||
|
string_set_str(context->notification_msg, "Missing Protocol");
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
FURI_LOG_I(TAG, "Protocol: %s", string_get_cstr(context->protocol));
|
||||||
|
}
|
||||||
|
|
||||||
|
if(strcmp(string_get_cstr(context->protocol), "RAW") == 0) {
|
||||||
|
FURI_LOG_E(TAG, "RAW unsupported");
|
||||||
|
string_reset(context->notification_msg);
|
||||||
|
string_set_str(context->notification_msg, "RAW unsupported");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const SubGhzProtocol* registry =
|
||||||
|
subghz_protocol_registry_get_by_name(string_get_cstr(context->protocol));
|
||||||
|
|
||||||
|
if(registry && registry->type == SubGhzProtocolTypeDynamic) {
|
||||||
|
FURI_LOG_D(TAG, "Protocol is dynamic - not supported");
|
||||||
|
string_reset(context->notification_msg);
|
||||||
|
string_set_str(context->notification_msg, "Dynamic protocol unsupported");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
context->decoder_result = subghz_receiver_search_decoder_base_by_name(
|
||||||
|
context->receiver, string_get_cstr(context->protocol));
|
||||||
|
|
||||||
|
if(context->decoder_result) {
|
||||||
|
FURI_LOG_I(TAG, "Found decoder");
|
||||||
|
} else {
|
||||||
|
FURI_LOG_E(TAG, "Protocol not found");
|
||||||
|
string_reset(context->notification_msg);
|
||||||
|
string_set_str(context->notification_msg, "Protocol not found");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bit
|
||||||
|
if(!flipper_format_read_uint32(fff_data_file, "Bit", &temp_data32, 1)) {
|
||||||
|
FURI_LOG_E(TAG, "Missing or incorrect Bit");
|
||||||
|
string_reset(context->notification_msg);
|
||||||
|
string_set_str(context->notification_msg, "Missing or incorrect Bit");
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
FURI_LOG_I(TAG, "Bit: %d", temp_data32);
|
||||||
|
context->bit = temp_data32;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Key
|
||||||
|
if(!flipper_format_read_string(fff_data_file, "Key", temp_str)) {
|
||||||
|
FURI_LOG_E(TAG, "Missing or incorrect Key");
|
||||||
|
string_reset(context->notification_msg);
|
||||||
|
string_set_str(context->notification_msg, "Missing or incorrect Key");
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
FURI_LOG_I(TAG, "Key: %s", string_get_cstr(temp_str));
|
||||||
|
string_set(context->key, string_get_cstr(temp_str));
|
||||||
|
}
|
||||||
|
|
||||||
|
// TE
|
||||||
|
if(!flipper_format_read_uint32(fff_data_file, "TE", &temp_data32, 1)) {
|
||||||
|
FURI_LOG_E(TAG, "Missing or incorrect TE");
|
||||||
|
//string_reset(context->notification_msg);
|
||||||
|
//string_set_str(context->notification_msg, "Missing or incorrect TE");
|
||||||
|
//break;
|
||||||
|
} else {
|
||||||
|
FURI_LOG_I(TAG, "TE: %d", temp_data32);
|
||||||
|
context->te = temp_data32;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Repeat
|
||||||
|
if(flipper_format_read_uint32(fff_data_file, "Repeat", &temp_data32, 1)) {
|
||||||
|
FURI_LOG_I(TAG, "Repeat: %d", temp_data32);
|
||||||
|
context->repeat = temp_data32;
|
||||||
|
} else {
|
||||||
|
FURI_LOG_I(TAG, "Repeat: 3 (default)");
|
||||||
|
context->repeat = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
result = true;
|
||||||
|
} while(0);
|
||||||
|
|
||||||
|
string_clear(temp_str);
|
||||||
|
flipper_format_file_close(fff_data_file);
|
||||||
|
flipper_format_free(fff_data_file);
|
||||||
|
if(result) {
|
||||||
|
FURI_LOG_I(TAG, "Loaded successfully");
|
||||||
|
string_reset(context->notification_msg);
|
||||||
|
string_set_str(context->notification_msg, "File looks ok.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void subbrute_scene_load_file_on_enter(SubBruteState* context) {
|
||||||
|
if(subbrute_load_protocol_from_file(context)) {
|
||||||
|
context->current_scene = SceneSelectField;
|
||||||
|
} else {
|
||||||
|
subbrute_scene_entrypoint_on_enter(context);
|
||||||
|
context->current_scene = SceneEntryPoint;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void subbrute_scene_load_file_on_exit(SubBruteState* context) {
|
||||||
|
UNUSED(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
void subbrute_scene_load_file_on_tick(SubBruteState* context) {
|
||||||
|
UNUSED(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
void subbrute_scene_load_file_on_event(SubBruteEvent event, SubBruteState* context) {
|
||||||
|
UNUSED(context);
|
||||||
|
if(event.evt_type == EventTypeKey) {
|
||||||
|
if(event.input_type == InputTypeShort) {
|
||||||
|
switch(event.key) {
|
||||||
|
case InputKeyDown:
|
||||||
|
case InputKeyUp:
|
||||||
|
case InputKeyLeft:
|
||||||
|
case InputKeyRight:
|
||||||
|
case InputKeyOk:
|
||||||
|
break;
|
||||||
|
case InputKeyBack:
|
||||||
|
context->current_scene = SceneEntryPoint;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void subbrute_scene_load_file_on_draw(Canvas* canvas, SubBruteState* context) {
|
||||||
|
UNUSED(context);
|
||||||
|
canvas_clear(canvas);
|
||||||
|
canvas_set_color(canvas, ColorBlack);
|
||||||
|
|
||||||
|
// Frame
|
||||||
|
//canvas_draw_frame(canvas, 0, 0, 128, 64);
|
||||||
|
|
||||||
|
// Title
|
||||||
|
canvas_set_font(canvas, FontPrimary);
|
||||||
|
canvas_draw_str_aligned(canvas, 64, 16, AlignCenter, AlignTop, "SubGHz Fuzzer");
|
||||||
|
canvas_draw_str_aligned(canvas, 64, 32, AlignCenter, AlignTop, "Error: Press back");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool subbrute_load_protocol_from_file(SubBruteState* context) {
|
||||||
|
string_t file_path;
|
||||||
|
string_init(file_path);
|
||||||
|
string_set_str(file_path, SUBGHZ_APP_PATH_FOLDER);
|
||||||
|
|
||||||
|
// Input events and views are managed by file_select
|
||||||
|
bool res = dialog_file_browser_show(
|
||||||
|
context->dialogs, file_path, file_path, SUBGHZ_APP_EXTENSION, true, &I_sub1_10px, true);
|
||||||
|
|
||||||
|
if(res) {
|
||||||
|
res = subbrute_load(context, string_get_cstr(file_path));
|
||||||
|
}
|
||||||
|
|
||||||
|
string_clear(file_path);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
8
applications/subbrute/scene/subbrute_scene_load_file.h
Normal file
8
applications/subbrute/scene/subbrute_scene_load_file.h
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
#include "../subbrute.h"
|
||||||
|
|
||||||
|
void subbrute_scene_load_file_on_enter(SubBruteState* context);
|
||||||
|
void subbrute_scene_load_file_on_exit(SubBruteState* context);
|
||||||
|
void subbrute_scene_load_file_on_tick(SubBruteState* context);
|
||||||
|
void subbrute_scene_load_file_on_event(SubBruteEvent event, SubBruteState* context);
|
||||||
|
void subbrute_scene_load_file_on_draw(Canvas* canvas, SubBruteState* context);
|
||||||
|
bool subbrute_load_protocol_from_file(SubBruteState* context);
|
320
applications/subbrute/scene/subbrute_scene_run_attack.c
Normal file
320
applications/subbrute/scene/subbrute_scene_run_attack.c
Normal file
|
@ -0,0 +1,320 @@
|
||||||
|
#include "subbrute_scene_run_attack.h"
|
||||||
|
#include <lib/subghz/transmitter.h>
|
||||||
|
#include <gui/elements.h>
|
||||||
|
|
||||||
|
uint64_t subbrute_counter = 0;
|
||||||
|
uint64_t max_value;
|
||||||
|
bool locked = false;
|
||||||
|
bool toSave = false;
|
||||||
|
char subbrute_payload_byte[4];
|
||||||
|
#define SUBBRUTE_DELAY 1
|
||||||
|
|
||||||
|
FuriHalSubGhzPreset str_to_preset(string_t preset) {
|
||||||
|
if(string_cmp_str(preset, "FuriHalSubGhzPresetOok270Async") == 0) {
|
||||||
|
return FuriHalSubGhzPresetOok270Async;
|
||||||
|
}
|
||||||
|
if(string_cmp_str(preset, "FuriHalSubGhzPresetOok650Async") == 0) {
|
||||||
|
return FuriHalSubGhzPresetOok650Async;
|
||||||
|
}
|
||||||
|
if(string_cmp_str(preset, "FuriHalSubGhzPreset2FSKDev238Async") == 0) {
|
||||||
|
return FuriHalSubGhzPreset2FSKDev238Async;
|
||||||
|
}
|
||||||
|
if(string_cmp_str(preset, "FuriHalSubGhzPreset2FSKDev476Async") == 0) {
|
||||||
|
return FuriHalSubGhzPreset2FSKDev476Async;
|
||||||
|
}
|
||||||
|
if(string_cmp_str(preset, "FuriHalSubGhzPresetMSK99_97KbAsync") == 0) {
|
||||||
|
return FuriHalSubGhzPresetMSK99_97KbAsync;
|
||||||
|
}
|
||||||
|
if(string_cmp_str(preset, "FuriHalSubGhzPresetMSK99_97KbAsync") == 0) {
|
||||||
|
return FuriHalSubGhzPresetMSK99_97KbAsync;
|
||||||
|
}
|
||||||
|
return FuriHalSubGhzPresetCustom;
|
||||||
|
}
|
||||||
|
|
||||||
|
void subbrute_emit(SubBruteState* context) {
|
||||||
|
//FURI_LOG_D(TAG, string_get_cstr(context->flipper_format_string));
|
||||||
|
|
||||||
|
furi_hal_subghz_start_async_tx(subghz_transmitter_yield, context->transmitter);
|
||||||
|
while(!(furi_hal_subghz_is_async_tx_complete())) {
|
||||||
|
furi_delay_ms(5);
|
||||||
|
}
|
||||||
|
|
||||||
|
furi_hal_subghz_stop_async_tx();
|
||||||
|
}
|
||||||
|
|
||||||
|
void prepare_emit(SubBruteState* context) {
|
||||||
|
furi_hal_subghz_init();
|
||||||
|
|
||||||
|
context->transmitter =
|
||||||
|
subghz_transmitter_alloc_init(context->environment, string_get_cstr(context->protocol));
|
||||||
|
|
||||||
|
furi_hal_subghz_reset();
|
||||||
|
furi_hal_subghz_load_preset(str_to_preset(context->preset));
|
||||||
|
|
||||||
|
furi_hal_subghz_set_frequency_and_path(context->frequency);
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear_emit(SubBruteState* context) {
|
||||||
|
furi_hal_subghz_stop_async_tx();
|
||||||
|
furi_hal_subghz_idle();
|
||||||
|
furi_hal_subghz_sleep();
|
||||||
|
|
||||||
|
subghz_transmitter_free(context->transmitter);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
void subbrute_send_raw_packet(SubBruteState* context) {
|
||||||
|
string_reset(context->candidate);
|
||||||
|
|
||||||
|
// Payload to padded binary string
|
||||||
|
int* binaryNum = (int*)malloc(sizeof(int) * context->bit);
|
||||||
|
uint32_t i = 0;
|
||||||
|
for(i = 0; i < context->bit; i++) {
|
||||||
|
binaryNum[i] = 0;
|
||||||
|
}
|
||||||
|
i = 0;
|
||||||
|
uint64_t counter = context->payload;
|
||||||
|
while(counter > 0) {
|
||||||
|
binaryNum[i] = counter % 2;
|
||||||
|
counter = counter / 2;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// printing binary array in reverse order and build raw payload
|
||||||
|
for(uint32_t loop = 0; loop < context->repeat; loop++) {
|
||||||
|
for(int j = (int)context->bit - 1; j >= 0; j--) {
|
||||||
|
if(binaryNum[j] == 1) {
|
||||||
|
string_cat(context->candidate, context->subbrute_raw_one);
|
||||||
|
} else {
|
||||||
|
string_cat(context->candidate, context->subbrute_raw_zero);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
string_cat(context->candidate, context->subbrute_raw_stop);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(binaryNum);
|
||||||
|
|
||||||
|
string_init_printf(
|
||||||
|
context->flipper_format_string,
|
||||||
|
"Filetype: Flipper SubGhz RAW File\n"
|
||||||
|
"Version: 1\n"
|
||||||
|
"Frequency: %d\n"
|
||||||
|
"Preset: %s\n"
|
||||||
|
"Protocol: RAW\n"
|
||||||
|
"RAW_Data: %s",
|
||||||
|
context->frequency,
|
||||||
|
string_get_cstr(context->preset),
|
||||||
|
string_get_cstr(context->candidate));
|
||||||
|
|
||||||
|
subbrute_emit(context);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
void subbrute_send_packet_parsed(SubBruteState* context) {
|
||||||
|
if(context->attack == SubBruteAttackLoadFile) {
|
||||||
|
snprintf(subbrute_payload_byte, 4, "%02X ", (uint8_t)context->payload);
|
||||||
|
string_replace_at(context->candidate, context->str_index, 3, subbrute_payload_byte);
|
||||||
|
} else {
|
||||||
|
string_t buffer;
|
||||||
|
string_init(buffer);
|
||||||
|
string_init_printf(buffer, "%16X", context->payload);
|
||||||
|
int j = 0;
|
||||||
|
string_set_str(context->candidate, " ");
|
||||||
|
for(uint8_t i = 0; i < 16; i++) {
|
||||||
|
if(string_get_char(buffer, i) != ' ') {
|
||||||
|
string_set_char(context->candidate, i + j, string_get_char(buffer, i));
|
||||||
|
} else {
|
||||||
|
string_set_char(context->candidate, i + j, '0');
|
||||||
|
}
|
||||||
|
if(i % 2 != 0) {
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
string_clear(buffer);
|
||||||
|
}
|
||||||
|
if(strcmp(string_get_cstr(context->protocol), "Princeton") == 0) {
|
||||||
|
string_init_printf(
|
||||||
|
context->flipper_format_string,
|
||||||
|
"Filetype: Flipper SubGhz Key File\n"
|
||||||
|
"Version: 1\n"
|
||||||
|
"Frequency: %u\n"
|
||||||
|
"Preset: %s\n"
|
||||||
|
"Protocol: %s\n"
|
||||||
|
"Bit: %d\n"
|
||||||
|
"Key: %s\n"
|
||||||
|
"TE: %d\n",
|
||||||
|
context->frequency,
|
||||||
|
string_get_cstr(context->preset),
|
||||||
|
string_get_cstr(context->protocol),
|
||||||
|
context->bit,
|
||||||
|
string_get_cstr(context->candidate),
|
||||||
|
context->te);
|
||||||
|
} else {
|
||||||
|
string_init_printf(
|
||||||
|
context->flipper_format_string,
|
||||||
|
"Filetype: Flipper SubGhz Key File\n"
|
||||||
|
"Version: 1\n"
|
||||||
|
"Frequency: %u\n"
|
||||||
|
"Preset: %s\n"
|
||||||
|
"Protocol: %s\n"
|
||||||
|
"Bit: %d\n"
|
||||||
|
"Key: %s\n",
|
||||||
|
context->frequency,
|
||||||
|
string_get_cstr(context->preset),
|
||||||
|
string_get_cstr(context->protocol),
|
||||||
|
context->bit,
|
||||||
|
string_get_cstr(context->candidate));
|
||||||
|
}
|
||||||
|
|
||||||
|
stream_clean(context->stream);
|
||||||
|
stream_write_string(context->stream, context->flipper_format_string);
|
||||||
|
subghz_transmitter_deserialize(context->transmitter, context->flipper_format);
|
||||||
|
|
||||||
|
subbrute_emit(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
void subbrute_send_packet(SubBruteState* context) {
|
||||||
|
///if(string_cmp_str(context->protocol, "RAW") == 0) {
|
||||||
|
// subbrute_send_raw_packet(context);
|
||||||
|
//} else {
|
||||||
|
subbrute_send_packet_parsed(context);
|
||||||
|
//}
|
||||||
|
string_clear(context->flipper_format_string);
|
||||||
|
}
|
||||||
|
|
||||||
|
void subbrute_scene_run_attack_on_enter(SubBruteState* context) {
|
||||||
|
if(!toSave) {
|
||||||
|
if(context->attack == SubBruteAttackLoadFile) {
|
||||||
|
max_value = 0xFF;
|
||||||
|
} else {
|
||||||
|
string_t max_value_s;
|
||||||
|
string_init(max_value_s);
|
||||||
|
for(uint8_t i = 0; i < context->bit; i++) {
|
||||||
|
string_cat_printf(max_value_s, "1");
|
||||||
|
}
|
||||||
|
max_value = (uint64_t)strtol(string_get_cstr(max_value_s), NULL, 2);
|
||||||
|
string_clear(max_value_s);
|
||||||
|
}
|
||||||
|
context->str_index = (context->key_index * 3);
|
||||||
|
string_init_set(context->candidate, context->key);
|
||||||
|
context->flipper_format = flipper_format_string_alloc();
|
||||||
|
context->stream = flipper_format_get_raw_stream(context->flipper_format);
|
||||||
|
context->environment = subghz_environment_alloc();
|
||||||
|
context->transmitter = subghz_transmitter_alloc_init(
|
||||||
|
context->environment, string_get_cstr(context->protocol));
|
||||||
|
prepare_emit(context);
|
||||||
|
} else {
|
||||||
|
toSave = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void subbrute_scene_run_attack_on_exit(SubBruteState* context) {
|
||||||
|
if(!toSave) {
|
||||||
|
clear_emit(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void subbrute_scene_run_attack_on_tick(SubBruteState* context) {
|
||||||
|
if(!context->is_attacking || locked) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(0 != subbrute_counter) {
|
||||||
|
locked = true;
|
||||||
|
subbrute_send_packet(context);
|
||||||
|
|
||||||
|
if(context->payload == max_value) {
|
||||||
|
context->payload = 0x00;
|
||||||
|
subbrute_counter = 0;
|
||||||
|
context->is_attacking = false;
|
||||||
|
notification_message(context->notify, &sequence_blink_stop);
|
||||||
|
notification_message(context->notify, &sequence_single_vibro);
|
||||||
|
} else {
|
||||||
|
context->payload++;
|
||||||
|
}
|
||||||
|
locked = false;
|
||||||
|
}
|
||||||
|
if(subbrute_counter > SUBBRUTE_DELAY) {
|
||||||
|
subbrute_counter = 0;
|
||||||
|
} else {
|
||||||
|
subbrute_counter++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void subbrute_scene_run_attack_on_event(SubBruteEvent event, SubBruteState* context) {
|
||||||
|
if(event.evt_type == EventTypeKey) {
|
||||||
|
if(event.input_type == InputTypeShort) {
|
||||||
|
switch(event.key) {
|
||||||
|
case InputKeyDown:
|
||||||
|
if(!context->is_attacking) {
|
||||||
|
toSave = true;
|
||||||
|
context->current_scene = SceneSaveName;
|
||||||
|
}
|
||||||
|
case InputKeyUp:
|
||||||
|
break;
|
||||||
|
case InputKeyLeft:
|
||||||
|
if(!context->is_attacking && context->payload > 0x00) {
|
||||||
|
context->payload--;
|
||||||
|
subbrute_send_packet(context);
|
||||||
|
notification_message(context->notify, &sequence_blink_blue_10);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case InputKeyRight:
|
||||||
|
if(!context->is_attacking && context->payload < max_value) {
|
||||||
|
context->payload++;
|
||||||
|
subbrute_send_packet(context);
|
||||||
|
notification_message(context->notify, &sequence_blink_blue_10);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case InputKeyOk:
|
||||||
|
if(!context->is_attacking) {
|
||||||
|
context->is_attacking = true;
|
||||||
|
notification_message(context->notify, &sequence_blink_start_blue);
|
||||||
|
} else {
|
||||||
|
context->is_attacking = false;
|
||||||
|
notification_message(context->notify, &sequence_blink_stop);
|
||||||
|
notification_message(context->notify, &sequence_single_vibro);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case InputKeyBack:
|
||||||
|
locked = false;
|
||||||
|
context->is_attacking = false;
|
||||||
|
string_reset(context->notification_msg);
|
||||||
|
context->payload = 0x00;
|
||||||
|
subbrute_counter = 0;
|
||||||
|
notification_message(context->notify, &sequence_blink_stop);
|
||||||
|
if(context->attack == SubBruteAttackLoadFile) {
|
||||||
|
context->current_scene = SceneSelectField;
|
||||||
|
} else {
|
||||||
|
context->current_scene = SceneEntryPoint;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void subbrute_scene_run_attack_on_draw(Canvas* canvas, SubBruteState* context) {
|
||||||
|
canvas_clear(canvas);
|
||||||
|
canvas_set_color(canvas, ColorBlack);
|
||||||
|
|
||||||
|
// Frame
|
||||||
|
//canvas_draw_frame(canvas, 0, 0, 128, 64);
|
||||||
|
|
||||||
|
// Title
|
||||||
|
canvas_set_font(canvas, FontPrimary);
|
||||||
|
canvas_draw_str_aligned(canvas, 64, 8, AlignCenter, AlignTop, "Fire in the hole!");
|
||||||
|
|
||||||
|
char msg_index[26];
|
||||||
|
snprintf(
|
||||||
|
msg_index, sizeof(msg_index), "< %04d / %04d >", (int)context->payload, (int)max_value);
|
||||||
|
|
||||||
|
canvas_draw_str_aligned(canvas, 64, 24, AlignCenter, AlignTop, msg_index);
|
||||||
|
|
||||||
|
canvas_set_font(canvas, FontSecondary);
|
||||||
|
char start_stop_msg[20];
|
||||||
|
snprintf(start_stop_msg, sizeof(start_stop_msg), " Press (V) to save ");
|
||||||
|
if(context->is_attacking) {
|
||||||
|
elements_button_center(canvas, "Stop");
|
||||||
|
} else {
|
||||||
|
elements_button_center(canvas, "Start");
|
||||||
|
}
|
||||||
|
canvas_draw_str_aligned(canvas, 64, 39, AlignCenter, AlignTop, start_stop_msg);
|
||||||
|
}
|
8
applications/subbrute/scene/subbrute_scene_run_attack.h
Normal file
8
applications/subbrute/scene/subbrute_scene_run_attack.h
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
#include "../subbrute.h"
|
||||||
|
|
||||||
|
void subbrute_scene_run_attack_on_enter(SubBruteState* context);
|
||||||
|
void subbrute_scene_run_attack_on_exit(SubBruteState* context);
|
||||||
|
void subbrute_scene_run_attack_on_tick(SubBruteState* context);
|
||||||
|
void subbrute_scene_run_attack_on_event(SubBruteEvent event, SubBruteState* context);
|
||||||
|
void subbrute_scene_run_attack_on_draw(Canvas* canvas, SubBruteState* context);
|
||||||
|
void send_packet();
|
222
applications/subbrute/scene/subbrute_scene_save_name.c
Normal file
222
applications/subbrute/scene/subbrute_scene_save_name.c
Normal file
|
@ -0,0 +1,222 @@
|
||||||
|
#include "../subbrute.h"
|
||||||
|
#include "m-string.h"
|
||||||
|
#include "subghz/types.h"
|
||||||
|
#include <lib/toolbox/random_name.h>
|
||||||
|
#include <gui/modules/validators.h>
|
||||||
|
#include <lib/toolbox/path.h>
|
||||||
|
|
||||||
|
#define MAX_TEXT_INPUT_LEN 22
|
||||||
|
|
||||||
|
bool backpressed = false;
|
||||||
|
|
||||||
|
bool subbrute_path_is_file(string_t path) {
|
||||||
|
return string_end_with_str_p(path, ".sub");
|
||||||
|
}
|
||||||
|
// method modified from subghz_i.c
|
||||||
|
// https://github.com/flipperdevices/flipperzero-firmware/blob/b0daa601ad5b87427a45f9089c8b403a01f72c2a/applications/subghz/subghz_i.c#L417-L456
|
||||||
|
bool subbrute_save_protocol_to_file(Stream* flipper_format_stream, const char* dev_file_name) {
|
||||||
|
furi_assert(dev_file_name);
|
||||||
|
|
||||||
|
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||||
|
|
||||||
|
bool saved = false;
|
||||||
|
string_t file_dir;
|
||||||
|
string_init(file_dir);
|
||||||
|
|
||||||
|
path_extract_dirname(dev_file_name, file_dir);
|
||||||
|
do {
|
||||||
|
if(!storage_simply_mkdir(storage, string_get_cstr(file_dir))) {
|
||||||
|
FURI_LOG_E(TAG, "(save) Cannot mkdir");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!storage_simply_remove(storage, dev_file_name)) {
|
||||||
|
FURI_LOG_E(TAG, "(save) Cannot remove");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
stream_seek(flipper_format_stream, 0, StreamOffsetFromStart);
|
||||||
|
stream_save_to_file(flipper_format_stream, storage, dev_file_name, FSOM_CREATE_ALWAYS);
|
||||||
|
|
||||||
|
saved = true;
|
||||||
|
FURI_LOG_D(TAG, "(save) OK Save");
|
||||||
|
} while(0);
|
||||||
|
string_clear(file_dir);
|
||||||
|
furi_record_close(RECORD_STORAGE);
|
||||||
|
return saved;
|
||||||
|
}
|
||||||
|
|
||||||
|
void custom_callback(SubBruteState* context) {
|
||||||
|
if(strcmp(context->file_name_tmp, "")) {
|
||||||
|
string_cat_printf(context->file_path, "/%s%s", context->file_name_tmp, ".sub");
|
||||||
|
if(subbrute_path_is_file(context->file_path_tmp)) {
|
||||||
|
context->current_scene = SceneAttack;
|
||||||
|
return; //false;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
subbrute_save_protocol_to_file(context->stream, string_get_cstr(context->file_path));
|
||||||
|
}
|
||||||
|
|
||||||
|
string_set_str(context->file_path, EXT_PATH("subghz"));
|
||||||
|
string_reset(context->file_path_tmp);
|
||||||
|
|
||||||
|
//scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSaveSuccess);
|
||||||
|
context->current_scene = SceneAttack;
|
||||||
|
return; //true;
|
||||||
|
} else {
|
||||||
|
//error no file name
|
||||||
|
context->current_scene = SceneAttack;
|
||||||
|
return; //true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void subbrute_scene_save_name_text_input_callback(void* context) {
|
||||||
|
furi_assert(context);
|
||||||
|
SubBruteState* statee = context;
|
||||||
|
custom_callback(statee);
|
||||||
|
}
|
||||||
|
|
||||||
|
void subbrute_scene_save_name_on_tick(SubBruteState* context) {
|
||||||
|
if(backpressed) {
|
||||||
|
void* validator_context = text_input_get_validator_callback_context(context->text_input);
|
||||||
|
text_input_set_validator(context->text_input, NULL, NULL);
|
||||||
|
validator_is_file_free(validator_context);
|
||||||
|
|
||||||
|
// Clear view
|
||||||
|
text_input_reset(context->text_input);
|
||||||
|
|
||||||
|
// TextInput
|
||||||
|
view_dispatcher_remove_view(context->view_dispatcher, 0);
|
||||||
|
text_input_free(context->text_input);
|
||||||
|
|
||||||
|
// Popup
|
||||||
|
view_dispatcher_remove_view(context->view_dispatcher, 1);
|
||||||
|
popup_free(context->popup);
|
||||||
|
|
||||||
|
context->current_scene = SceneAttack;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool subbrute_back_event_callback(void* context) {
|
||||||
|
UNUSED(context);
|
||||||
|
backpressed = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void subbrute_scene_save_name_on_enter(SubBruteState* context) {
|
||||||
|
// Text Input
|
||||||
|
context->text_input = text_input_alloc();
|
||||||
|
view_dispatcher_add_view(
|
||||||
|
context->view_dispatcher, 0, text_input_get_view(context->text_input));
|
||||||
|
|
||||||
|
// Popup
|
||||||
|
context->popup = popup_alloc();
|
||||||
|
view_dispatcher_add_view(context->view_dispatcher, 1, popup_get_view(context->popup));
|
||||||
|
|
||||||
|
// Setup view
|
||||||
|
TextInput* text_input = context->text_input;
|
||||||
|
bool dev_name_empty = false;
|
||||||
|
|
||||||
|
string_t file_name;
|
||||||
|
string_t dir_name;
|
||||||
|
string_init(file_name);
|
||||||
|
string_init(dir_name);
|
||||||
|
|
||||||
|
if(!subbrute_path_is_file(context->file_path)) {
|
||||||
|
char file_name_buf[64] = {0};
|
||||||
|
set_random_name(file_name_buf, 64);
|
||||||
|
string_set_str(file_name, file_name_buf);
|
||||||
|
string_set_str(context->file_path, EXT_PATH("subghz"));
|
||||||
|
//highlighting the entire filename by default
|
||||||
|
dev_name_empty = true;
|
||||||
|
} else {
|
||||||
|
string_set(context->file_path_tmp, context->file_path);
|
||||||
|
path_extract_dirname(string_get_cstr(context->file_path), dir_name);
|
||||||
|
path_extract_filename(context->file_path, file_name, true);
|
||||||
|
string_set(context->file_path, dir_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
strncpy(context->file_name_tmp, string_get_cstr(file_name), 64);
|
||||||
|
text_input_set_header_text(text_input, "Name signal");
|
||||||
|
text_input_set_result_callback(
|
||||||
|
text_input,
|
||||||
|
subbrute_scene_save_name_text_input_callback,
|
||||||
|
context,
|
||||||
|
context->file_name_tmp,
|
||||||
|
MAX_TEXT_INPUT_LEN, // buffer size
|
||||||
|
dev_name_empty);
|
||||||
|
|
||||||
|
ValidatorIsFile* validator_is_file =
|
||||||
|
validator_is_file_alloc_init(string_get_cstr(context->file_path), ".sub", "");
|
||||||
|
text_input_set_validator(text_input, validator_is_file_callback, validator_is_file);
|
||||||
|
|
||||||
|
string_clear(file_name);
|
||||||
|
string_clear(dir_name);
|
||||||
|
|
||||||
|
view_dispatcher_set_navigation_event_callback(
|
||||||
|
context->view_dispatcher, subbrute_back_event_callback);
|
||||||
|
|
||||||
|
view_dispatcher_switch_to_view(context->view_dispatcher, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void subbrute_scene_save_name_on_event(SubBruteEvent event, SubBruteState* context) {
|
||||||
|
UNUSED(context);
|
||||||
|
if(event.evt_type == EventTypeKey) {
|
||||||
|
if(event.input_type == InputTypeShort) {
|
||||||
|
switch(event.key) {
|
||||||
|
case InputKeyDown:
|
||||||
|
case InputKeyUp:
|
||||||
|
case InputKeyLeft:
|
||||||
|
case InputKeyRight:
|
||||||
|
case InputKeyOk:
|
||||||
|
break;
|
||||||
|
case InputKeyBack:
|
||||||
|
//context->current_scene = SceneAttack;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void subbrute_scene_save_name_on_exit(SubBruteState* context) {
|
||||||
|
if(!backpressed) {
|
||||||
|
// Clear validator
|
||||||
|
void* validator_context = text_input_get_validator_callback_context(context->text_input);
|
||||||
|
text_input_set_validator(context->text_input, NULL, NULL);
|
||||||
|
validator_is_file_free(validator_context);
|
||||||
|
|
||||||
|
// Clear view
|
||||||
|
text_input_reset(context->text_input);
|
||||||
|
|
||||||
|
// Setup view
|
||||||
|
Popup* popup = context->popup;
|
||||||
|
popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59);
|
||||||
|
popup_set_header(popup, "Saved!", 13, 22, AlignLeft, AlignBottom);
|
||||||
|
popup_set_timeout(popup, 1500);
|
||||||
|
popup_set_context(popup, context);
|
||||||
|
popup_set_callback(popup, NULL);
|
||||||
|
popup_enable_timeout(popup);
|
||||||
|
view_dispatcher_switch_to_view(context->view_dispatcher, 1);
|
||||||
|
|
||||||
|
furi_delay_ms(1050);
|
||||||
|
// Clear view
|
||||||
|
//Popup* popup = subghz->popup;
|
||||||
|
popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignBottom);
|
||||||
|
popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop);
|
||||||
|
popup_set_icon(popup, 0, 0, NULL);
|
||||||
|
popup_set_callback(popup, NULL);
|
||||||
|
popup_set_context(popup, NULL);
|
||||||
|
popup_set_timeout(popup, 0);
|
||||||
|
popup_disable_timeout(popup);
|
||||||
|
|
||||||
|
// TextInput
|
||||||
|
view_dispatcher_remove_view(context->view_dispatcher, 0);
|
||||||
|
text_input_free(context->text_input);
|
||||||
|
|
||||||
|
// Popup
|
||||||
|
view_dispatcher_remove_view(context->view_dispatcher, 1);
|
||||||
|
popup_free(context->popup);
|
||||||
|
} else {
|
||||||
|
backpressed = false;
|
||||||
|
}
|
||||||
|
}
|
6
applications/subbrute/scene/subbrute_scene_save_name.h
Normal file
6
applications/subbrute/scene/subbrute_scene_save_name.h
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
#include "../subbrute.h"
|
||||||
|
|
||||||
|
void subbrute_scene_save_name_on_enter(SubBruteState* context);
|
||||||
|
void subbrute_scene_save_name_on_exit(SubBruteState* context);
|
||||||
|
void subbrute_scene_save_name_on_event(SubBruteEvent event, SubBruteState* context);
|
||||||
|
void subbrute_scene_save_name_on_tick(SubBruteState* context);
|
121
applications/subbrute/scene/subbrute_scene_select_field.c
Normal file
121
applications/subbrute/scene/subbrute_scene_select_field.c
Normal file
|
@ -0,0 +1,121 @@
|
||||||
|
#include "subbrute_scene_select_field.h"
|
||||||
|
|
||||||
|
void center_displayed_key(SubBruteState* context, uint8_t index) {
|
||||||
|
const char* key_cstr = string_get_cstr(context->key);
|
||||||
|
uint8_t str_index = (index * 3);
|
||||||
|
|
||||||
|
char display_menu[17] = {
|
||||||
|
'X', 'X', ' ', 'X', 'X', ' ', '<', 'X', 'X', '>', ' ', 'X', 'X', ' ', 'X', 'X', '\0'};
|
||||||
|
|
||||||
|
if(index > 1) {
|
||||||
|
display_menu[0] = key_cstr[str_index - 6];
|
||||||
|
display_menu[1] = key_cstr[str_index - 5];
|
||||||
|
} else {
|
||||||
|
display_menu[0] = ' ';
|
||||||
|
display_menu[1] = ' ';
|
||||||
|
}
|
||||||
|
|
||||||
|
if(index > 0) {
|
||||||
|
display_menu[3] = key_cstr[str_index - 3];
|
||||||
|
display_menu[4] = key_cstr[str_index - 2];
|
||||||
|
} else {
|
||||||
|
display_menu[3] = ' ';
|
||||||
|
display_menu[4] = ' ';
|
||||||
|
}
|
||||||
|
|
||||||
|
display_menu[7] = key_cstr[str_index];
|
||||||
|
display_menu[8] = key_cstr[str_index + 1];
|
||||||
|
|
||||||
|
if((str_index + 4) <= (uint8_t)strlen(key_cstr)) {
|
||||||
|
display_menu[11] = key_cstr[str_index + 3];
|
||||||
|
display_menu[12] = key_cstr[str_index + 4];
|
||||||
|
} else {
|
||||||
|
display_menu[11] = ' ';
|
||||||
|
display_menu[12] = ' ';
|
||||||
|
}
|
||||||
|
|
||||||
|
if((str_index + 8) <= (uint8_t)strlen(key_cstr)) {
|
||||||
|
display_menu[14] = key_cstr[str_index + 6];
|
||||||
|
display_menu[15] = key_cstr[str_index + 7];
|
||||||
|
} else {
|
||||||
|
display_menu[14] = ' ';
|
||||||
|
display_menu[15] = ' ';
|
||||||
|
}
|
||||||
|
|
||||||
|
string_reset(context->notification_msg);
|
||||||
|
string_set_str(context->notification_msg, display_menu);
|
||||||
|
}
|
||||||
|
|
||||||
|
void subbrute_scene_select_field_on_enter(SubBruteState* context) {
|
||||||
|
string_clear(context->notification_msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void subbrute_scene_select_field_on_exit(SubBruteState* context) {
|
||||||
|
UNUSED(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
void subbrute_scene_select_field_on_tick(SubBruteState* context) {
|
||||||
|
UNUSED(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
void subbrute_scene_select_field_on_event(SubBruteEvent event, SubBruteState* context) {
|
||||||
|
if(event.evt_type == EventTypeKey) {
|
||||||
|
if(event.input_type == InputTypeShort) {
|
||||||
|
//const char* key_cstr = string_get_cstr(context->key);
|
||||||
|
|
||||||
|
// don't look, it's ugly but I'm a python dev so...
|
||||||
|
/*uint8_t nb_bytes = 0;
|
||||||
|
for(uint8_t i = 0; i < strlen(key_cstr); i++) {
|
||||||
|
if(' ' == key_cstr[i]) {
|
||||||
|
nb_bytes++;
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
|
||||||
|
switch(event.key) {
|
||||||
|
case InputKeyDown:
|
||||||
|
case InputKeyUp:
|
||||||
|
break;
|
||||||
|
case InputKeyLeft:
|
||||||
|
if(context->key_index > 0) {
|
||||||
|
context->key_index--;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case InputKeyRight:
|
||||||
|
if(context->key_index < 7) {
|
||||||
|
context->key_index++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case InputKeyOk:
|
||||||
|
string_reset(context->notification_msg);
|
||||||
|
context->current_scene = SceneAttack;
|
||||||
|
break;
|
||||||
|
case InputKeyBack:
|
||||||
|
string_reset(context->notification_msg);
|
||||||
|
context->current_scene = SceneSelectFile;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
//FURI_LOG_D(TAG, "Position: %d/%d", context->key_index, nb_bytes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void subbrute_scene_select_field_on_draw(Canvas* canvas, SubBruteState* context) {
|
||||||
|
canvas_clear(canvas);
|
||||||
|
canvas_set_color(canvas, ColorBlack);
|
||||||
|
|
||||||
|
// Frame
|
||||||
|
//canvas_draw_frame(canvas, 0, 0, 128, 64);
|
||||||
|
|
||||||
|
// Title
|
||||||
|
canvas_set_font(canvas, FontPrimary);
|
||||||
|
canvas_draw_str_aligned(canvas, 64, 10, AlignCenter, AlignTop, "use < > to select field");
|
||||||
|
|
||||||
|
char msg_index[18];
|
||||||
|
snprintf(msg_index, sizeof(msg_index), "Field index : %d", context->key_index);
|
||||||
|
canvas_draw_str_aligned(canvas, 64, 26, AlignCenter, AlignTop, msg_index);
|
||||||
|
|
||||||
|
center_displayed_key(context, context->key_index);
|
||||||
|
canvas_set_font(canvas, FontSecondary);
|
||||||
|
canvas_draw_str_aligned(
|
||||||
|
canvas, 64, 40, AlignCenter, AlignTop, string_get_cstr(context->notification_msg));
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
#include "../subbrute.h"
|
||||||
|
|
||||||
|
void subbrute_scene_select_field_on_enter(SubBruteState* context);
|
||||||
|
void subbrute_scene_select_field_on_exit(SubBruteState* context);
|
||||||
|
void subbrute_scene_select_field_on_tick(SubBruteState* context);
|
||||||
|
void subbrute_scene_select_field_on_event(SubBruteEvent event, SubBruteState* context);
|
||||||
|
void subbrute_scene_select_field_on_draw(Canvas* canvas, SubBruteState* context);
|
||||||
|
void center_displayed_key(SubBruteState* context, uint8_t index);
|
269
applications/subbrute/subbrute.c
Normal file
269
applications/subbrute/subbrute.c
Normal file
|
@ -0,0 +1,269 @@
|
||||||
|
#include "subbrute.h"
|
||||||
|
|
||||||
|
#include "scene/subbrute_scene_load_file.h"
|
||||||
|
#include "scene/subbrute_scene_select_field.h"
|
||||||
|
#include "scene/subbrute_scene_run_attack.h"
|
||||||
|
#include "scene/subbrute_scene_entrypoint.h"
|
||||||
|
#include "scene/subbrute_scene_save_name.h"
|
||||||
|
|
||||||
|
static void draw_callback(Canvas* const canvas, void* ctx) {
|
||||||
|
SubBruteState* subbrute_state = (SubBruteState*)acquire_mutex((ValueMutex*)ctx, 100);
|
||||||
|
|
||||||
|
if(subbrute_state == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw correct Canvas
|
||||||
|
switch(subbrute_state->current_scene) {
|
||||||
|
case NoneScene:
|
||||||
|
case SceneSelectFile:
|
||||||
|
subbrute_scene_load_file_on_draw(canvas, subbrute_state);
|
||||||
|
break;
|
||||||
|
case SceneSelectField:
|
||||||
|
subbrute_scene_select_field_on_draw(canvas, subbrute_state);
|
||||||
|
break;
|
||||||
|
case SceneAttack:
|
||||||
|
subbrute_scene_run_attack_on_draw(canvas, subbrute_state);
|
||||||
|
break;
|
||||||
|
case SceneEntryPoint:
|
||||||
|
subbrute_scene_entrypoint_on_draw(canvas, subbrute_state);
|
||||||
|
break;
|
||||||
|
case SceneSaveName:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
release_mutex((ValueMutex*)ctx, subbrute_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
void input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) {
|
||||||
|
furi_assert(event_queue);
|
||||||
|
|
||||||
|
SubBruteEvent event = {
|
||||||
|
.evt_type = EventTypeKey, .key = input_event->key, .input_type = input_event->type};
|
||||||
|
furi_message_queue_put(event_queue, &event, 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void timer_callback(FuriMessageQueue* event_queue) {
|
||||||
|
furi_assert(event_queue);
|
||||||
|
SubBruteEvent event = {
|
||||||
|
.evt_type = EventTypeTick, .key = InputKeyUp, .input_type = InputTypeRelease};
|
||||||
|
furi_message_queue_put(event_queue, &event, 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
SubBruteState* subbrute_alloc() {
|
||||||
|
SubBruteState* subbrute = malloc(sizeof(SubBruteState));
|
||||||
|
|
||||||
|
string_init(subbrute->protocol);
|
||||||
|
string_init(subbrute->preset);
|
||||||
|
string_init(subbrute->file_path);
|
||||||
|
string_init(subbrute->file_path_tmp);
|
||||||
|
string_init_set(subbrute->notification_msg, "");
|
||||||
|
string_init(subbrute->candidate);
|
||||||
|
string_init(subbrute->flipper_format_string);
|
||||||
|
|
||||||
|
subbrute->previous_scene = NoneScene;
|
||||||
|
subbrute->current_scene = SceneSelectFile;
|
||||||
|
subbrute->is_running = true;
|
||||||
|
subbrute->is_attacking = false;
|
||||||
|
subbrute->key_index = 7;
|
||||||
|
subbrute->notify = furi_record_open(RECORD_NOTIFICATION);
|
||||||
|
|
||||||
|
subbrute->view_dispatcher = view_dispatcher_alloc();
|
||||||
|
|
||||||
|
//Dialog
|
||||||
|
subbrute->dialogs = furi_record_open(RECORD_DIALOGS);
|
||||||
|
|
||||||
|
subbrute->preset_def = malloc(sizeof(SubGhzPresetDefinition));
|
||||||
|
|
||||||
|
subbrute->flipper_format = flipper_format_string_alloc();
|
||||||
|
subbrute->environment = subghz_environment_alloc();
|
||||||
|
subbrute->receiver = subghz_receiver_alloc_init(subbrute->environment);
|
||||||
|
subghz_receiver_set_filter(subbrute->receiver, SubGhzProtocolFlag_Decodable);
|
||||||
|
|
||||||
|
return subbrute;
|
||||||
|
}
|
||||||
|
|
||||||
|
void subbrute_free(SubBruteState* subbrute) {
|
||||||
|
//Dialog
|
||||||
|
furi_record_close(RECORD_DIALOGS);
|
||||||
|
|
||||||
|
notification_message(subbrute->notify, &sequence_blink_stop);
|
||||||
|
|
||||||
|
furi_record_close(RECORD_NOTIFICATION);
|
||||||
|
|
||||||
|
view_dispatcher_free(subbrute->view_dispatcher);
|
||||||
|
|
||||||
|
string_clear(subbrute->preset);
|
||||||
|
string_clear(subbrute->candidate);
|
||||||
|
|
||||||
|
// Path strings
|
||||||
|
string_clear(subbrute->file_path);
|
||||||
|
string_clear(subbrute->file_path_tmp);
|
||||||
|
string_clear(subbrute->notification_msg);
|
||||||
|
string_clear(subbrute->candidate);
|
||||||
|
string_clear(subbrute->flipper_format_string);
|
||||||
|
|
||||||
|
flipper_format_free(subbrute->flipper_format);
|
||||||
|
subghz_environment_free(subbrute->environment);
|
||||||
|
subghz_receiver_free(subbrute->receiver);
|
||||||
|
|
||||||
|
free(subbrute->preset_def);
|
||||||
|
|
||||||
|
// The rest
|
||||||
|
free(subbrute);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ENTRYPOINT
|
||||||
|
int32_t subbrute_start(void* p) {
|
||||||
|
UNUSED(p);
|
||||||
|
// Input
|
||||||
|
FURI_LOG_I(TAG, "Initializing input");
|
||||||
|
FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(SubBruteEvent));
|
||||||
|
SubBruteState* subbrute_state = subbrute_alloc();
|
||||||
|
ValueMutex subbrute_state_mutex;
|
||||||
|
|
||||||
|
// Mutex
|
||||||
|
FURI_LOG_I(TAG, "Initializing flipfrid mutex");
|
||||||
|
if(!init_mutex(&subbrute_state_mutex, subbrute_state, sizeof(SubBruteState))) {
|
||||||
|
FURI_LOG_E(TAG, "cannot create mutex\r\n");
|
||||||
|
furi_message_queue_free(event_queue);
|
||||||
|
subbrute_free(subbrute_state);
|
||||||
|
return 255;
|
||||||
|
}
|
||||||
|
|
||||||
|
furi_hal_power_suppress_charge_enter();
|
||||||
|
|
||||||
|
// Configure view port
|
||||||
|
FURI_LOG_I(TAG, "Initializing viewport");
|
||||||
|
ViewPort* view_port = view_port_alloc();
|
||||||
|
view_port_draw_callback_set(view_port, draw_callback, &subbrute_state_mutex);
|
||||||
|
view_port_input_callback_set(view_port, input_callback, event_queue);
|
||||||
|
|
||||||
|
// Configure timer
|
||||||
|
FURI_LOG_I(TAG, "Initializing timer");
|
||||||
|
FuriTimer* timer = furi_timer_alloc(timer_callback, FuriTimerTypePeriodic, event_queue);
|
||||||
|
furi_timer_start(timer, furi_kernel_get_tick_frequency() / 10); // 10 times per second
|
||||||
|
|
||||||
|
// Register view port in GUI
|
||||||
|
FURI_LOG_I(TAG, "Initializing gui");
|
||||||
|
subbrute_state->gui = furi_record_open(RECORD_GUI);
|
||||||
|
gui_add_view_port(subbrute_state->gui, view_port, GuiLayerFullscreen);
|
||||||
|
|
||||||
|
view_dispatcher_attach_to_gui(
|
||||||
|
subbrute_state->view_dispatcher, subbrute_state->gui, ViewDispatcherTypeFullscreen);
|
||||||
|
|
||||||
|
subbrute_state->current_scene = SceneEntryPoint;
|
||||||
|
|
||||||
|
// Init values
|
||||||
|
SubBruteEvent event;
|
||||||
|
while(subbrute_state->is_running) {
|
||||||
|
// Get next event
|
||||||
|
FuriStatus event_status = furi_message_queue_get(event_queue, &event, 25);
|
||||||
|
if(event_status == FuriStatusOk) {
|
||||||
|
if(event.evt_type == EventTypeKey) {
|
||||||
|
//Handle event key
|
||||||
|
FURI_LOG_D(TAG, "EVENT ###");
|
||||||
|
switch(subbrute_state->current_scene) {
|
||||||
|
case SceneSelectFile:
|
||||||
|
subbrute_scene_load_file_on_event(event, subbrute_state);
|
||||||
|
break;
|
||||||
|
case SceneSelectField:
|
||||||
|
subbrute_scene_select_field_on_event(event, subbrute_state);
|
||||||
|
break;
|
||||||
|
case SceneSaveName:
|
||||||
|
subbrute_scene_save_name_on_event(event, subbrute_state);
|
||||||
|
break;
|
||||||
|
case SceneAttack:
|
||||||
|
subbrute_scene_run_attack_on_event(event, subbrute_state);
|
||||||
|
break;
|
||||||
|
case NoneScene:
|
||||||
|
case SceneEntryPoint:
|
||||||
|
subbrute_scene_entrypoint_on_event(event, subbrute_state);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if(event.evt_type == EventTypeTick) {
|
||||||
|
//Handle event tick
|
||||||
|
if(subbrute_state->current_scene != subbrute_state->previous_scene) {
|
||||||
|
// Trigger Exit Scene
|
||||||
|
switch(subbrute_state->previous_scene) {
|
||||||
|
case SceneSelectFile:
|
||||||
|
subbrute_scene_load_file_on_exit(subbrute_state);
|
||||||
|
break;
|
||||||
|
case SceneSelectField:
|
||||||
|
subbrute_scene_select_field_on_exit(subbrute_state);
|
||||||
|
break;
|
||||||
|
case SceneAttack:
|
||||||
|
subbrute_scene_run_attack_on_exit(subbrute_state);
|
||||||
|
break;
|
||||||
|
case SceneEntryPoint:
|
||||||
|
subbrute_scene_entrypoint_on_exit(subbrute_state);
|
||||||
|
break;
|
||||||
|
case SceneSaveName:
|
||||||
|
subbrute_scene_save_name_on_exit(subbrute_state);
|
||||||
|
break;
|
||||||
|
case NoneScene:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Trigger Entry Scene
|
||||||
|
switch(subbrute_state->current_scene) {
|
||||||
|
case NoneScene:
|
||||||
|
case SceneSelectFile:
|
||||||
|
subbrute_scene_load_file_on_enter(subbrute_state);
|
||||||
|
break;
|
||||||
|
case SceneSelectField:
|
||||||
|
subbrute_scene_select_field_on_enter(subbrute_state);
|
||||||
|
break;
|
||||||
|
case SceneAttack:
|
||||||
|
subbrute_scene_run_attack_on_enter(subbrute_state);
|
||||||
|
break;
|
||||||
|
case SceneSaveName:
|
||||||
|
subbrute_scene_save_name_on_enter(subbrute_state);
|
||||||
|
break;
|
||||||
|
case SceneEntryPoint:
|
||||||
|
subbrute_scene_entrypoint_on_enter(subbrute_state);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
subbrute_state->previous_scene = subbrute_state->current_scene;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Trigger Tick Scene
|
||||||
|
switch(subbrute_state->current_scene) {
|
||||||
|
case NoneScene:
|
||||||
|
case SceneSelectFile:
|
||||||
|
subbrute_scene_load_file_on_tick(subbrute_state);
|
||||||
|
break;
|
||||||
|
case SceneSelectField:
|
||||||
|
subbrute_scene_select_field_on_tick(subbrute_state);
|
||||||
|
break;
|
||||||
|
case SceneAttack:
|
||||||
|
subbrute_scene_run_attack_on_tick(subbrute_state);
|
||||||
|
break;
|
||||||
|
case SceneEntryPoint:
|
||||||
|
subbrute_scene_entrypoint_on_tick(subbrute_state);
|
||||||
|
break;
|
||||||
|
case SceneSaveName:
|
||||||
|
subbrute_scene_save_name_on_tick(subbrute_state);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
view_port_update(view_port);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cleanup
|
||||||
|
furi_timer_stop(timer);
|
||||||
|
furi_timer_free(timer);
|
||||||
|
|
||||||
|
furi_hal_power_suppress_charge_exit();
|
||||||
|
|
||||||
|
FURI_LOG_I(TAG, "Cleaning up");
|
||||||
|
gui_remove_view_port(subbrute_state->gui, view_port);
|
||||||
|
view_port_free(view_port);
|
||||||
|
furi_message_queue_free(event_queue);
|
||||||
|
furi_record_close(RECORD_GUI);
|
||||||
|
subbrute_free(subbrute_state);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
105
applications/subbrute/subbrute.h
Normal file
105
applications/subbrute/subbrute.h
Normal file
|
@ -0,0 +1,105 @@
|
||||||
|
#pragma once
|
||||||
|
#include <furi.h>
|
||||||
|
#include <furi_hal.h>
|
||||||
|
#include <input/input.h>
|
||||||
|
#include <gui/gui.h>
|
||||||
|
#include "m-string.h"
|
||||||
|
|
||||||
|
#include <toolbox/stream/stream.h>
|
||||||
|
#include <lib/subghz/transmitter.h>
|
||||||
|
#include <lib/subghz/receiver.h>
|
||||||
|
#include <flipper_format/flipper_format_i.h>
|
||||||
|
#include <dialogs/dialogs.h>
|
||||||
|
#include <notification/notification.h>
|
||||||
|
#include <notification/notification_messages.h>
|
||||||
|
#include <gui/view_dispatcher.h>
|
||||||
|
#include <gui/modules/text_input.h>
|
||||||
|
#include <gui/modules/popup.h>
|
||||||
|
|
||||||
|
#define TAG "SUBBRUTE"
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
NoneScene,
|
||||||
|
SceneSelectFile,
|
||||||
|
SceneSelectField,
|
||||||
|
SceneAttack,
|
||||||
|
SceneEntryPoint,
|
||||||
|
SceneSaveName
|
||||||
|
} SubBruteScene;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
SubBruteAttackLoadFile,
|
||||||
|
SubBruteAttackCAME12bit433,
|
||||||
|
SubBruteAttackCAME12bit868,
|
||||||
|
SubBruteAttackChamberlain9bit315,
|
||||||
|
SubBruteAttackChamberlain9bit390,
|
||||||
|
SubBruteAttackLinear10bit300,
|
||||||
|
SubBruteAttackLinear10bit310,
|
||||||
|
SubBruteAttackNICE12bit433,
|
||||||
|
SubBruteAttackNICE12bit868,
|
||||||
|
} SubBruteAttacks;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
EventTypeTick,
|
||||||
|
EventTypeKey,
|
||||||
|
EventTypeCustom,
|
||||||
|
} EventType;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
EventType evt_type;
|
||||||
|
InputKey key;
|
||||||
|
InputType input_type;
|
||||||
|
} SubBruteEvent;
|
||||||
|
|
||||||
|
// STRUCTS
|
||||||
|
typedef struct {
|
||||||
|
// Application stuff
|
||||||
|
bool is_running;
|
||||||
|
bool is_attacking;
|
||||||
|
SubBruteScene current_scene;
|
||||||
|
SubBruteScene previous_scene;
|
||||||
|
NotificationApp* notify;
|
||||||
|
Gui* gui;
|
||||||
|
ViewDispatcher* view_dispatcher;
|
||||||
|
TextInput* text_input;
|
||||||
|
Popup* popup;
|
||||||
|
|
||||||
|
// SubGhz Stuff
|
||||||
|
FlipperFormat* flipper_format;
|
||||||
|
SubGhzEnvironment* environment;
|
||||||
|
SubGhzTransmitter* transmitter;
|
||||||
|
SubGhzReceiver* receiver;
|
||||||
|
SubGhzProtocolDecoderBase* decoder_result;
|
||||||
|
SubGhzPresetDefinition* preset_def;
|
||||||
|
string_t preset;
|
||||||
|
Stream* stream;
|
||||||
|
string_t protocol;
|
||||||
|
uint32_t frequency;
|
||||||
|
uint32_t repeat;
|
||||||
|
uint32_t bit;
|
||||||
|
string_t key;
|
||||||
|
uint32_t te;
|
||||||
|
|
||||||
|
// Context Stuff
|
||||||
|
DialogsApp* dialogs;
|
||||||
|
char file_name_tmp[64];
|
||||||
|
string_t file_path;
|
||||||
|
string_t file_path_tmp;
|
||||||
|
string_t notification_msg;
|
||||||
|
uint8_t key_index;
|
||||||
|
uint64_t payload;
|
||||||
|
string_t candidate;
|
||||||
|
uint8_t str_index;
|
||||||
|
string_t flipper_format_string;
|
||||||
|
|
||||||
|
SubBruteAttacks attack;
|
||||||
|
|
||||||
|
//Menu stuff
|
||||||
|
uint8_t menu_index;
|
||||||
|
|
||||||
|
// RAW stuff
|
||||||
|
string_t subbrute_raw_one;
|
||||||
|
string_t subbrute_raw_zero;
|
||||||
|
string_t subbrute_raw_stop;
|
||||||
|
|
||||||
|
} SubBruteState;
|
13
applications/subbrute/subbrute_utils.c
Normal file
13
applications/subbrute/subbrute_utils.c
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
#include "subbrute_utils.h"
|
||||||
|
|
||||||
|
bool subbrute_is_frequency_allowed(SubBruteState* context) {
|
||||||
|
// I know you don't like it but laws are laws
|
||||||
|
// It's opensource so do whatever you want, but remember the risks :)
|
||||||
|
// (Yes, this comment is the only purpose of this function)
|
||||||
|
bool r = furi_hal_subghz_is_tx_allowed(context->frequency);
|
||||||
|
if(!r) {
|
||||||
|
FURI_LOG_E(TAG, "Frequency %d is not allowed in your region", context->frequency);
|
||||||
|
notification_message(context->notify, &sequence_single_vibro);
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
4
applications/subbrute/subbrute_utils.h
Normal file
4
applications/subbrute/subbrute_utils.h
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
#pragma once
|
||||||
|
#include "subbrute.h"
|
||||||
|
|
||||||
|
bool subbrute_is_frequency_allowed(SubBruteState* context);
|
|
@ -1,5 +1,5 @@
|
||||||
V:0
|
V:0
|
||||||
T:1662385171
|
T:1662605174
|
||||||
D:badusb
|
D:badusb
|
||||||
D:dolphin
|
D:dolphin
|
||||||
D:infrared
|
D:infrared
|
||||||
|
@ -243,10 +243,10 @@ F:f267f0654781049ca323b11bb4375519:581:dolphin/L3_Lab_research_128x54/frame_9.bm
|
||||||
F:41106c0cbc5144f151b2b2d3daaa0527:727:dolphin/L3_Lab_research_128x54/meta.txt
|
F:41106c0cbc5144f151b2b2d3daaa0527:727:dolphin/L3_Lab_research_128x54/meta.txt
|
||||||
D:infrared/assets
|
D:infrared/assets
|
||||||
F:13fe3def425723bccd05fe09c745a335:122232:infrared/assets/ac.ir
|
F:13fe3def425723bccd05fe09c745a335:122232:infrared/assets/ac.ir
|
||||||
F:f0569fce8a54aa74780632cb4042cc85:58026:infrared/assets/audio.ir
|
F:7a2e10eb171faa5d767703313f5fd7a5:58541:infrared/assets/audio.ir
|
||||||
F:1703fea41cb6ef71553b91a1004dc936:82397:infrared/assets/fans.ir
|
F:faa49194e6ba4e5bc1ae5b2f90909d29:87512:infrared/assets/fans.ir
|
||||||
F:08d864cf44e2557fb25aec8837740de5:6567:infrared/assets/projectors.ir
|
F:08d864cf44e2557fb25aec8837740de5:6567:infrared/assets/projectors.ir
|
||||||
F:77bc8314d113b8618942589f21a491fc:127350:infrared/assets/tv.ir
|
F:33bf57fcfae734a83a0d6a40e6695a81:133948:infrared/assets/tv.ir
|
||||||
F:a157a80f5a668700403d870c23b9567d:470:music_player/Marble_Machine.fmf
|
F:a157a80f5a668700403d870c23b9567d:470:music_player/Marble_Machine.fmf
|
||||||
D:nfc/assets
|
D:nfc/assets
|
||||||
F:81dc04c7b181f94b644079a71476dff4:4742:nfc/assets/aid.nfc
|
F:81dc04c7b181f94b644079a71476dff4:4742:nfc/assets/aid.nfc
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
Filetype: IR library file
|
Filetype: IR library file
|
||||||
Version: 1
|
Version: 1
|
||||||
# Last Updated 3rd Sep, 2022
|
# Last Updated 7th Sep, 2022
|
||||||
#
|
#
|
||||||
name: POWER
|
name: POWER
|
||||||
type: parsed
|
type: parsed
|
||||||
|
@ -1299,3 +1299,39 @@ frequency: 38000
|
||||||
duty_cycle: 0.330000
|
duty_cycle: 0.330000
|
||||||
data: 8500 4203 653 1468 569 538 542 1579 550 532 548 534 546 1575 544 536 544 1578 541 540 550 1572 547 534 546 1575 544 1577 542 539 541 1580 550 532 548 534 546 535 545 1576 543 1577 542 1579 551 532 548 534 546 536 544 1577 542 1578 552 531 549 533 547 534 546 1574 545 1575 544 1577 542 26533 8492 4211 573 1573 546 535 545 1576 543 539 551 530 550 1571 548 533 547 1574 545 536 544 1577 542 540 550 1570 549 1572 547 534 546 1576 543 539 541 541 549 532 548 1573 546 1574 545 1576 543 539 551 531 549 533 547 1573 546 1576 543 539 541 541 549 532 548 1573 546 1574 545 1576 543 26532 8493 4209 575 1571 548 533 547 1575 544 537 543 539 541 1580 550 531 549 1572 547 534 546 1576 543 538 542 1579 551 1570 549 532 548 1574 545 537 543 538 542 540 550 1570 549 1572 547 1575 544 537 543 539 541 540 550 1571 548 1573 546 536 544 538 542 539 551 1570 549 1572 547 1574 545 26530 8496 4207 567 1579 551 531 549 1572 547 535 545 536 544 1576 543 538 542 1579 551 530 550 1571 548 534 546 1574 545 1576 543 538 542 1579 551 532 548 533 547 534 546 1576 543 1577 542 1579 551 532 548 534 546 535 545 1576 543 1578 541 540 550 532 548 533 547 1574 545 1575 544 1577 542 26531 8495 4210 574 1571 548 534 546 1575 544 538 542 539 551 1569 550 531 549 1572 547 535 545 1576 543 539 541 1579 550 1571 548 534 546 1575 544 538 542 540 550 531 549 1572 547 1549 570 1551 568 539 551 531 549 532 548 1573 546 1550 569 538 542 540 550 531 549 1571 548 1548 571 1550 569
|
data: 8500 4203 653 1468 569 538 542 1579 550 532 548 534 546 1575 544 536 544 1578 541 540 550 1572 547 534 546 1575 544 1577 542 539 541 1580 550 532 548 534 546 535 545 1576 543 1577 542 1579 551 532 548 534 546 536 544 1577 542 1578 552 531 549 533 547 534 546 1574 545 1575 544 1577 542 26533 8492 4211 573 1573 546 535 545 1576 543 539 551 530 550 1571 548 533 547 1574 545 536 544 1577 542 540 550 1570 549 1572 547 534 546 1576 543 539 541 541 549 532 548 1573 546 1574 545 1576 543 539 551 531 549 533 547 1573 546 1576 543 539 541 541 549 532 548 1573 546 1574 545 1576 543 26532 8493 4209 575 1571 548 533 547 1575 544 537 543 539 541 1580 550 531 549 1572 547 534 546 1576 543 538 542 1579 551 1570 549 532 548 1574 545 537 543 538 542 540 550 1570 549 1572 547 1575 544 537 543 539 541 540 550 1571 548 1573 546 536 544 538 542 539 551 1570 549 1572 547 1574 545 26530 8496 4207 567 1579 551 531 549 1572 547 535 545 536 544 1576 543 538 542 1579 551 530 550 1571 548 534 546 1574 545 1576 543 538 542 1579 551 532 548 533 547 534 546 1576 543 1577 542 1579 551 532 548 534 546 535 545 1576 543 1578 541 540 550 532 548 533 547 1574 545 1575 544 1577 542 26531 8495 4210 574 1571 548 534 546 1575 544 538 542 539 551 1569 550 531 549 1572 547 535 545 1576 543 539 541 1579 550 1571 548 534 546 1575 544 538 542 540 550 531 549 1572 547 1549 570 1551 568 539 551 531 549 532 548 1573 546 1550 569 538 542 540 550 531 549 1571 548 1548 571 1550 569
|
||||||
#
|
#
|
||||||
|
name: POWER
|
||||||
|
type: parsed
|
||||||
|
protocol: NECext
|
||||||
|
address: 00 EF 00 00
|
||||||
|
command: 1C E3 00 00
|
||||||
|
#
|
||||||
|
name: VOL+
|
||||||
|
type: parsed
|
||||||
|
protocol: NECext
|
||||||
|
address: 00 EF 00 00
|
||||||
|
command: 00 FF 00 00
|
||||||
|
#
|
||||||
|
name: VOL-
|
||||||
|
type: parsed
|
||||||
|
protocol: NECext
|
||||||
|
address: 00 EF 00 00
|
||||||
|
command: 04 FB 00 00
|
||||||
|
#
|
||||||
|
name: POWER
|
||||||
|
type: parsed
|
||||||
|
protocol: NEC42
|
||||||
|
address: 6E 00 00 00
|
||||||
|
command: 00 00 00 00
|
||||||
|
#
|
||||||
|
name: VOL+
|
||||||
|
type: parsed
|
||||||
|
protocol: NEC42
|
||||||
|
address: 6E 00 00 00
|
||||||
|
command: 4D 00 00 00
|
||||||
|
#
|
||||||
|
name: VOL-
|
||||||
|
type: parsed
|
||||||
|
protocol: NEC42
|
||||||
|
address: 6E 00 00 00
|
||||||
|
command: 4E 00 00 00
|
||||||
|
#
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
Filetype: IR library file
|
Filetype: IR library file
|
||||||
Version: 1
|
Version: 1
|
||||||
# Last Updated 29th Aug, 2022
|
# Last Updated 7th Sep, 2022
|
||||||
#
|
#
|
||||||
name: POWER
|
name: POWER
|
||||||
type: parsed
|
type: parsed
|
||||||
|
@ -852,3 +852,46 @@ type: raw
|
||||||
frequency: 38000
|
frequency: 38000
|
||||||
duty_cycle: 0.330000
|
duty_cycle: 0.330000
|
||||||
data: 1294 388 1291 390 455 1215 1289 392 1298 384 451 1220 460 1210 459 1210 1294 388 457 1212 457 1212 457 7954 1301 382 1298 384 461 1207 1297 387 1293 389 456 1212 457 1212 457 1213 1291 392 463 1205 465 1205 464 9263 1295 414 1266 417 428 1214 1301 409 1271 412 433 1209 460 1209 460 1210 1294 415 430 1213 456 1213 456 7959 1296 413 1267 415 430 1213 1302 408 1271 411 434 1208 461 1209 460 1209 1295 414 431 1212 457 1213 456 9272 1297 412 1268 415 430 1212 1292 417 1273 410 435 1207 462 1208 461 1208 1296 413 432 1211 458 1211 458 7956 1299 410 1270 413 432 1210 1294 390 1300 409 436 1206 463 1207 463 1207 1298 387 458 1210 459 1211 458
|
data: 1294 388 1291 390 455 1215 1289 392 1298 384 451 1220 460 1210 459 1210 1294 388 457 1212 457 1212 457 7954 1301 382 1298 384 461 1207 1297 387 1293 389 456 1212 457 1212 457 1213 1291 392 463 1205 465 1205 464 9263 1295 414 1266 417 428 1214 1301 409 1271 412 433 1209 460 1209 460 1210 1294 415 430 1213 456 1213 456 7959 1296 413 1267 415 430 1213 1302 408 1271 411 434 1208 461 1209 460 1209 1295 414 431 1212 457 1213 456 9272 1297 412 1268 415 430 1212 1292 417 1273 410 435 1207 462 1208 461 1208 1296 413 432 1211 458 1211 458 7956 1299 410 1270 413 432 1210 1294 390 1300 409 436 1206 463 1207 463 1207 1298 387 458 1210 459 1211 458
|
||||||
|
#
|
||||||
|
name: POWER
|
||||||
|
type: raw
|
||||||
|
frequency: 38000
|
||||||
|
duty_cycle: 0.330000
|
||||||
|
data: 1251 410 1245 415 407 1252 1246 415 1250 410 412 1247 408 1252 413 1247 408 1252 413 1247 408 1252 1246 7350 1248 438 1227 433 389 1245 1253 434 1221 439 383 1250 415 1245 410 1250 405 1255 410 1249 406 1255 1253 7340 1247 439 1226 407 415 1245 1253 433 1222 412 410 1250 405 1255 410 1249 406 1254 411 1249 406 1254 1254 7340 1247 412 1253 407 415 1245 1253 407 1248 412 410 1250 405 1255 410 1249 406 1254 411 1248 407 1253 1245 7349 1249 411 1254 406 405 1254 1254 406 1249 411 411 1248 407 1252 413 1246 409 1251 414 1245 410 1250 1248
|
||||||
|
#
|
||||||
|
name: TIMER
|
||||||
|
type: raw
|
||||||
|
frequency: 38000
|
||||||
|
duty_cycle: 0.330000
|
||||||
|
data: 1250 409 1246 441 381 1252 1246 414 1252 435 387 1246 409 1250 405 1255 1243 417 405 1281 384 1275 380 8188 1244 416 1249 437 385 1249 1249 437 1218 443 379 1253 412 1248 407 1253 1245 415 407 1252 413 1246 409 8186 1246 414 1251 435 387 1272 1226 408 1247 439 383 1276 379 1281 384 1249 1249 437 385 1248 407 1253 412 8181 1251 409 1246 440 382 1277 1221 439 1226 434 378 1255 410 1249 406 1254 1244 416 406 1253 412 1247 408 8187 1245 441 1225 435 387 1273 1225 435 1220 440 382 1251 414 1245 410 1250 1248 412 410 1249 406 1254 411
|
||||||
|
#
|
||||||
|
name: SPEED+
|
||||||
|
type: raw
|
||||||
|
frequency: 38000
|
||||||
|
duty_cycle: 0.330000
|
||||||
|
data: 1243 444 1221 438 384 1276 1222 438 1217 443 379 1254 411 1274 381 1252 413 1246 409 1251 1247 413 409 8185 1247 440 1225 435 387 1246 1252 408 1247 440 382 1277 388 1245 410 1276 379 1280 385 1249 1249 411 411 8184 1248 412 1243 444 378 1282 1216 444 1221 439 383 1250 405 1254 411 1248 407 1253 412 1248 1250 410 412 8182 1250 410 1245 442 380 1253 1245 415 1250 437 385 1247 408 1252 413 1272 383 1251 414 1272 1226 408 414 8180 1252 409 1246 440 382 1252 1246 440 1225 435 387 1272 383 1250 405 1254 411 1249 406 1254 1244 416 406 8188 1244 416 1249 437 385 1249 1249 411 1244 443 379 1253 412 1273 382 1278 387 1246 409 1251 1247 413 409
|
||||||
|
#
|
||||||
|
name: SPEED+
|
||||||
|
type: raw
|
||||||
|
frequency: 38000
|
||||||
|
duty_cycle: 0.330000
|
||||||
|
data: 1305 379 1283 402 434 1251 431 1253 1276 408 1275 411 435 1249 1280 404 432 1253 1276 408 438 1247 1282 7144 1281 404 1279 407 439 1247 435 1250 1310 375 1307 379 467 1218 1311 374 431 1254 1306 379 436 1249 1311 7119 1305 380 1302 382 464 1222 460 1224 1305 380 1302 382 464 1221 1308 377 469 1217 1302 383 463 1222 1307 7121 1303 380 1303 382 464 1221 462 1223 1306 378 1305 381 465 1220 1309 375 430 1254 1306 380 435 1250 1279 7148 1276 408 1274 411 435 1250 432 1252 1277 408 1274 410 436 1249 1280 404 432 1253 1276 408 438 1247 1282
|
||||||
|
#
|
||||||
|
name: POWER
|
||||||
|
type: raw
|
||||||
|
frequency: 38000
|
||||||
|
duty_cycle: 0.330000
|
||||||
|
data: 1282 402 1281 404 432 1252 430 1254 1275 408 1275 410 436 1248 435 1249 434 1251 1278 405 431 1254 439 7984 1277 407 1276 408 438 1246 436 1248 1281 402 1281 403 433 1251 432 1253 430 1254 1275 408 438 1246 437 7985 1276 407 1276 408 438 1246 436 1248 1281 402 1281 403 433 1252 431 1253 440 1245 1274 409 437 1248 435 7990 1333 351 1332 352 433 1252 431 1254 1326 358 1335 349 436 1249 434 1250 433 1252 1328 355 440 1244 438 7984 1328 355 1328 356 439 1245 438 1247 1333 350 1333 351 434 1250 433 1252 431 1253 1327 357 438 1246 437 7988 1273 410 1273 411 435 1249 434 1250 1279 405 1278 406 440 1244 439 1246 436 1247 1282 402 434 1251 432
|
||||||
|
#
|
||||||
|
name: TIMER
|
||||||
|
type: raw
|
||||||
|
frequency: 38000
|
||||||
|
duty_cycle: 0.330000
|
||||||
|
data: 1282 403 1279 405 431 1254 439 1246 1273 412 434 1251 432 1254 1275 410 436 1249 433 1251 431 1254 1275 7152 1283 402 1281 405 431 1254 439 1246 1273 412 434 1251 432 1254 1305 379 436 1249 433 1252 430 1254 1306 7122 1302 382 1311 374 462 1223 459 1226 1303 381 465 1221 461 1223 1306 379 467 1218 464 1221 461 1224 1305 7123 1312 373 1310 375 461 1224 469 1216 1303 381 465 1221 461 1223 1306 379 467 1218 464 1221 461 1224 1305 7123 1312 374 1308 376 460 1225 468 1218 1311 374 462 1223 459 1226 1303 382 464 1222 460 1224 469 1217 1302 7128 1306 379 1303 382 464 1221 461 1224 1305 380 466 1219 463 1221 1277 408 469 1217 465 1219 463 1222 1307 7122 1282 403 1279 405 462 1223 459 1226 1283 402 465 1221 461 1224 1274 410 467 1218 464 1221 461 1224 1274 7155 1280 405 1278 408 438 1247 435 1250 1279 406 440 1245 437 1249 1280 405 431 1255 438 1249 433 1252 1277
|
||||||
|
#
|
||||||
|
name: ROTATE
|
||||||
|
type: raw
|
||||||
|
frequency: 38000
|
||||||
|
duty_cycle: 0.330000
|
||||||
|
data: 1279 406 1307 377 438 1246 436 1249 1311 373 463 1221 462 1224 469 1216 466 1218 465 1220 463 1222 460 7967 1304 380 1303 382 464 1221 462 1223 1276 409 468 1217 466 1220 463 1223 459 1225 468 1217 465 1220 462 7966 1275 410 1303 382 464 1220 463 1222 1276 409 468 1218 465 1220 463 1223 459 1225 468 1217 435 1250 463 7965 1306 378 1304 381 465 1220 463 1222 1307 378 468 1217 465 1219 433 1253 440 1245 437 1248 434 1251 462 7966 1275 411 1282 404 432 1254 439 1248 1281 404 432 1254 439 1247 436 1250 433 1253 440 1246 437 1248 435 7995 1276 409 1284 402 434 1252 431 1255 1274 411 435 1251 431 1254 439 1247 436 1250 433 1253 440 1246 436 7992 1279 407 1276 410 436 1249 433 1252 1277 409 447 1238 434 1252 431 1254 439 1247 435 1250 433 1253 440 7990 1281 404 1278 406 440 1245 438 1249 1280 405 441 1245 437 1248 435 1251 432 1254 439 1247 435 1250 433
|
||||||
|
#
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
Filetype: IR library file
|
Filetype: IR library file
|
||||||
Version: 1
|
Version: 1
|
||||||
# Last Updated 27 Aug, 2022
|
# Last Updated 7th Sep, 2022
|
||||||
#
|
#
|
||||||
name: POWER
|
name: POWER
|
||||||
type: parsed
|
type: parsed
|
||||||
|
@ -3062,3 +3062,39 @@ protocol: NECext
|
||||||
address: 40 40 00 00
|
address: 40 40 00 00
|
||||||
command: 0F F0 00 00
|
command: 0F F0 00 00
|
||||||
#
|
#
|
||||||
|
name: POWER
|
||||||
|
type: raw
|
||||||
|
frequency: 38000
|
||||||
|
duty_cycle: 0.330000
|
||||||
|
data: 3476 1735 443 429 446 1300 451 422 453 420 445 428 447 426 449 423 452 448 417 429 446 426 449 424 451 422 443 430 445 1300 451 422 453 420 445 428 447 426 449 423 452 421 444 429 446 427 448 424 451 1295 445 427 448 425 450 423 452 420 445 429 446 426 449 424 451 421 444 1303 448 425 450 1296 444 1301 450 1296 444 1302 448 424 451 422 453 1293 447 426 449 1296 444 1302 448 1297 454 1293 447 425 450 1296 444 74939 3477 1734 444 429 446 1300 451 422 453 419 446 455 420 425 450 423 452 420 445 428 447 426 449 424 451 421 444 429 446 1300 451 422 453 420 445 428 447 425 450 423 452 420 445 429 446 426 449 424 451 1295 445 427 448 425 450 422 453 420 445 428 447 426 449 424 451 421 444 1302 449 424 451 1295 445 1301 450 1296 444 1302 449 424 451 422 453 1292 448 425 450 1296 444 1301 450 1297 443 1302 448 425 450 1295 445 74938 3478 1734 444 428 447 1299 452 421 444 429 446 427 448 425 450 422 453 420 444 428 447 426 449 423 452 421 444 429 446 1300 451 422 453 419 446 428 447 425 450 423 452 421 444 429 446 426 449 424 451 1295 445 427 448 425 450 423 452 420 445 428 447 426 449 424 451 421 444 1302 448 424 451 1295 445 1301 450 1296 444 1302 449 424 451 422 453 1292 448 425 450 1296 444 1301 450 1296 444 1302 449 424 451 1295 445 74938 3479 1733 445 428 447 1299 452 421 444 429 446 426 449 424 451 421 454 419 446 427 448 425 450 422 453 420 445 428 447 1299 452 421 444 429 446 426 449 424 451 422 453 419 446 427 448 425 450 422 453 1293 447 426 449 423 452 421 444 429 446 426 449 424 451 422 453 419 446 1301 450 422 453 1293 447 1299 452 1294 446 1300 451 422 453 419 446 1301 449 423 452 1294 446 1300 451 1295 445 1300 451 422 453 1293 447
|
||||||
|
#
|
||||||
|
name: MUTE
|
||||||
|
type: raw
|
||||||
|
frequency: 38000
|
||||||
|
duty_cycle: 0.330000
|
||||||
|
data: 3476 1736 473 399 445 1301 481 392 452 421 444 429 446 427 448 424 451 422 453 419 446 427 448 425 450 423 452 420 445 1301 450 423 452 421 444 429 446 427 448 424 451 422 453 419 446 427 448 425 450 1296 444 428 447 426 449 423 452 421 444 429 446 427 448 424 451 422 453 419 446 1301 450 423 452 420 445 1301 450 1297 443 429 446 427 448 424 451 1295 445 428 478 394 450 1296 444 1302 449 424 451 1294 446 74876 3479 1732 446 427 448 1298 453 420 445 428 447 425 450 423 452 421 444 429 446 426 449 424 451 421 444 429 446 427 448 1298 453 420 445 428 447 426 449 423 452 421 444 429 446 426 449 424 451 421 444 1303 448 425 450 423 452 420 445 428 447 426 449 423 452 421 444 429 446 426 449 1297 454 419 446 428 447 1298 453 1293 447 426 449 423 452 421 444 1302 449 424 451 422 453 1293 447 1298 453 420 445 1302 449 74849 3474 1738 450 422 453 1293 447 425 450 423 452 420 445 428 447 426 449 424 451 421 444 429 446 427 448 425 450 422 453 1293 447 426 449 423 452 421 444 429 446 426 449 424 451 422 453 419 446 427 448 1298 453 420 445 428 447 426 449 423 452 421 444 429 446 426 449 424 451 422 443 1303 448 425 450 423 452 1293 447 1299 452 421 444 429 446 427 448 1298 453 420 445 428 447 1299 452 1294 446 426 449 1297 443 74855 3479 1733 445 427 448 1298 453 420 445 428 447 426 449 423 452 421 444 429 446 427 448 424 451 422 453 419 446 427 448 1298 453 420 445 428 447 426 449 424 451 421 444 429 446 427 448 425 450 422 453 1293 447 426 449 423 452 421 444 429 446 427 448 424 451 422 453 419 446 427 448 1298 453 420 445 428 447 1299 452 1294 446 427 448 424 451 422 453 1293 447 425 450 423 452 1293 447 1299 452 421 444 1302 449
|
||||||
|
#
|
||||||
|
name: VOL+
|
||||||
|
type: raw
|
||||||
|
frequency: 38000
|
||||||
|
duty_cycle: 0.330000
|
||||||
|
data: 3482 1730 448 425 450 1296 444 429 446 427 448 424 451 422 453 420 445 428 447 425 450 423 452 421 444 429 446 426 449 1297 454 419 446 427 448 425 450 423 452 420 445 428 447 426 449 424 451 421 444 1303 448 425 450 422 453 420 445 428 447 425 450 423 452 421 444 429 446 427 448 424 451 422 453 419 446 428 447 1298 453 420 445 428 447 426 449 424 451 421 444 429 446 427 448 1298 453 420 445 1301 450
|
||||||
|
#
|
||||||
|
name: VOL-
|
||||||
|
type: raw
|
||||||
|
frequency: 38000
|
||||||
|
duty_cycle: 0.330000
|
||||||
|
data: 3512 1700 478 395 480 1266 474 399 476 396 479 394 481 392 473 400 475 397 478 395 480 393 482 390 475 398 477 396 479 1267 473 399 476 397 478 395 480 392 473 400 475 398 477 396 479 394 481 391 474 1272 479 394 481 392 473 400 475 398 477 395 480 393 482 391 474 399 476 1269 482 391 474 399 476 397 478 395 480 1266 474 398 477 396 479 1267 473 399 476 397 478 394 481 392 473 1273 478 395 480 1266 474
|
||||||
|
#
|
||||||
|
name: CH+
|
||||||
|
type: raw
|
||||||
|
frequency: 38000
|
||||||
|
duty_cycle: 0.330000
|
||||||
|
data: 3505 1707 481 391 474 1272 479 394 481 392 473 400 475 398 477 395 480 393 482 391 474 399 476 396 479 394 481 392 473 1273 478 395 480 393 482 390 475 398 477 396 479 394 481 391 474 399 476 397 478 1268 472 400 475 398 477 395 480 393 482 391 474 399 476 396 479 394 481 392 473 400 475 1271 480 393 482 1264 476 1269 482 391 474 399 476 397 478 395 480 1266 474 398 477 1269 482 1264 476 397 478 1267 473 106476 3510 1702 476 396 479 1267 473 400 475 398 477 395 480 393 482 391 474 398 477 396 479 394 481 391 474 399 476 397 478 1268 472 401 474 398 477 396 479 394 481 391 474 399 476 397 478 395 480 392 473 1274 477 396 479 393 482 391 474 399 476 397 478 394 481 392 473 400 475 398 477 395 480 1266 474 399 476 1270 481 1265 475 397 478 395 480 393 472 401 474 1271 480 393 482 1264 476 1270 481 392 473 1273 478
|
||||||
|
#
|
||||||
|
name: CH-
|
||||||
|
type: raw
|
||||||
|
frequency: 38000
|
||||||
|
duty_cycle: 0.330000
|
||||||
|
data: 3503 1708 480 392 473 1274 477 396 479 393 482 391 474 399 476 397 478 395 480 392 473 400 475 398 446 427 448 424 482 1264 476 397 478 394 481 392 473 400 475 398 477 395 480 393 482 391 474 399 476 1270 480 392 473 400 475 398 477 395 480 393 482 391 474 399 476 397 478 1268 472 400 475 1271 480 393 482 1264 476 1270 481 392 473 400 475 1270 481 393 472 1274 477 396 479 1267 473 1273 478 395 480 1266 474 74632 3510 1702 476 397 478 1268 472 400 475 398 477 395 480 393 482 391 474 399 476 396 479 394 481 392 473 400 475 398 477 1268 483 391 474 399 476 396 479 394 481 391 474 399 476 397 478 395 480 392 473 1273 478 396 479 393 482 391 484 388 477 397 478 395 480 392 473 400 475 1271 479 394 481 1264 476 397 478 1268 472 1273 478 395 480 393 482 1264 476 397 478 1267 473 400 475 1271 480 1266 474 399 476 1270 481 74602 3509 1703 475 397 478 1268 482 390 475 398 477 396 479 394 481 391 474 399 476 397 478 395 480 392 473 400 475 398 477 1269 482 391 474 399 476 397 478 394 481 392 473 400 475 397 478 395 480 393 482 1264 476 396 479 394 481 392 473 400 475 398 477 395 480 393 482 391 474 1272 479 394 481 1265 475 397 478 1268 472 1274 476 396 479 394 481 1264 476 397 478 1268 483 390 475 1272 479 1267 473 400 475 1270 481
|
||||||
|
#
|
||||||
|
|
|
@ -485,7 +485,7 @@ void subghz_protocol_decoder_keeloq_feed(void* context, bool level, uint32_t dur
|
||||||
(DURATION_DIFF(instance->decoder.te_last, subghz_protocol_keeloq_const.te_short) <
|
(DURATION_DIFF(instance->decoder.te_last, subghz_protocol_keeloq_const.te_short) <
|
||||||
subghz_protocol_keeloq_const.te_delta) &&
|
subghz_protocol_keeloq_const.te_delta) &&
|
||||||
(DURATION_DIFF(duration, subghz_protocol_keeloq_const.te_long) <
|
(DURATION_DIFF(duration, subghz_protocol_keeloq_const.te_long) <
|
||||||
subghz_protocol_keeloq_const.te_delta)) {
|
subghz_protocol_keeloq_const.te_delta * 2)) {
|
||||||
if(instance->decoder.decode_count_bit <
|
if(instance->decoder.decode_count_bit <
|
||||||
subghz_protocol_keeloq_const.min_count_bit_for_found) {
|
subghz_protocol_keeloq_const.min_count_bit_for_found) {
|
||||||
subghz_protocol_blocks_add_bit(&instance->decoder, 1);
|
subghz_protocol_blocks_add_bit(&instance->decoder, 1);
|
||||||
|
@ -493,7 +493,7 @@ void subghz_protocol_decoder_keeloq_feed(void* context, bool level, uint32_t dur
|
||||||
instance->decoder.parser_step = KeeloqDecoderStepSaveDuration;
|
instance->decoder.parser_step = KeeloqDecoderStepSaveDuration;
|
||||||
} else if(
|
} else if(
|
||||||
(DURATION_DIFF(instance->decoder.te_last, subghz_protocol_keeloq_const.te_long) <
|
(DURATION_DIFF(instance->decoder.te_last, subghz_protocol_keeloq_const.te_long) <
|
||||||
subghz_protocol_keeloq_const.te_delta) &&
|
subghz_protocol_keeloq_const.te_delta * 2) &&
|
||||||
(DURATION_DIFF(duration, subghz_protocol_keeloq_const.te_short) <
|
(DURATION_DIFF(duration, subghz_protocol_keeloq_const.te_short) <
|
||||||
subghz_protocol_keeloq_const.te_delta)) {
|
subghz_protocol_keeloq_const.te_delta)) {
|
||||||
if(instance->decoder.decode_count_bit <
|
if(instance->decoder.decode_count_bit <
|
||||||
|
|
Loading…
Reference in a new issue