mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-05-13 04:08:35 -07:00
Merge remote-tracking branch 'upstream/dev' into dev
This commit is contained in:
@@ -153,7 +153,9 @@ void archive_update_focus(ArchiveBrowserView* browser, const char* target) {
|
||||
|
||||
archive_get_items(browser, furi_string_get_cstr(browser->path));
|
||||
|
||||
if(!archive_file_get_array_size(browser) && archive_is_home(browser)) {
|
||||
ArchiveTabEnum tab = archive_get_tab(browser);
|
||||
if(!archive_file_get_array_size(browser) && archive_is_home(browser) &&
|
||||
(tab != ArchiveTabBrowser)) {
|
||||
archive_switch_tab(browser, TAB_LEFT);
|
||||
} else {
|
||||
with_view_model(
|
||||
@@ -220,7 +222,8 @@ void archive_file_array_rm_selected(ArchiveBrowserView* browser) {
|
||||
},
|
||||
false);
|
||||
|
||||
if((items_cnt == 0) && (archive_is_home(browser))) {
|
||||
ArchiveTabEnum tab = archive_get_tab(browser);
|
||||
if((items_cnt == 0) && (archive_is_home(browser)) && (tab != ArchiveTabBrowser)) {
|
||||
archive_switch_tab(browser, TAB_LEFT);
|
||||
}
|
||||
|
||||
|
||||
@@ -585,6 +585,10 @@ static bool archive_view_input(InputEvent* event, void* context) {
|
||||
((model->item_idx - scroll_speed) + model->item_cnt) %
|
||||
model->item_cnt;
|
||||
}
|
||||
// Fix for empty folders, we can't select -1 item
|
||||
if(model->item_idx < 0) {
|
||||
model->item_idx = 0;
|
||||
}
|
||||
if(is_file_list_load_required(model)) {
|
||||
model->list_loading = true;
|
||||
browser->callback(ArchiveBrowserEventLoadPrevItems, browser->context);
|
||||
|
||||
Binary file not shown.
@@ -3,7 +3,7 @@ App(
|
||||
name="GPIO",
|
||||
apptype=FlipperAppType.MENUEXTERNAL,
|
||||
entry_point="gpio_app",
|
||||
stack_size=1 * 1024,
|
||||
stack_size=2 * 1024,
|
||||
icon="A_GPIO_14",
|
||||
order=50,
|
||||
fap_libs=["assets"],
|
||||
|
||||
@@ -70,7 +70,12 @@ GpioApp* gpio_app_alloc() {
|
||||
GpioAppViewUsbUartCfg,
|
||||
variable_item_list_get_view(app->var_item_list));
|
||||
|
||||
scene_manager_next_scene(app->scene_manager, GpioSceneStart);
|
||||
if(furi_hal_serial_control_is_busy(FuriHalSerialIdUsart) ||
|
||||
furi_hal_serial_control_is_busy(FuriHalSerialIdLpuart)) {
|
||||
scene_manager_next_scene(app->scene_manager, GpioSceneErrorExpansion);
|
||||
} else {
|
||||
scene_manager_next_scene(app->scene_manager, GpioSceneStart);
|
||||
}
|
||||
|
||||
return app;
|
||||
}
|
||||
|
||||
@@ -3,4 +3,5 @@ ADD_SCENE(gpio, test, Test)
|
||||
ADD_SCENE(gpio, usb_uart, UsbUart)
|
||||
ADD_SCENE(gpio, usb_uart_cfg, UsbUartCfg)
|
||||
ADD_SCENE(gpio, usb_uart_close_rpc, UsbUartCloseRpc)
|
||||
ADD_SCENE(gpio, error_expansion, ErrorExpansion)
|
||||
ADD_SCENE(gpio, exit_confirm, ExitConfirm)
|
||||
|
||||
43
applications/main/gpio/scenes/gpio_scene_error_expansion.c
Normal file
43
applications/main/gpio/scenes/gpio_scene_error_expansion.c
Normal file
@@ -0,0 +1,43 @@
|
||||
#include "../gpio_app_i.h"
|
||||
#include "../gpio_custom_event.h"
|
||||
|
||||
void gpio_scene_error_expansion_on_enter(void* context) {
|
||||
GpioApp* app = context;
|
||||
|
||||
widget_add_icon_element(app->widget, 78, 0, &I_ActiveConnection_50x64);
|
||||
widget_add_string_multiline_element(
|
||||
app->widget, 3, 2, AlignLeft, AlignTop, FontPrimary, "Ext. Module\nis connected!");
|
||||
widget_add_string_multiline_element(
|
||||
app->widget,
|
||||
3,
|
||||
30,
|
||||
AlignLeft,
|
||||
AlignTop,
|
||||
FontSecondary,
|
||||
"Disconnect External\n"
|
||||
"Module\n"
|
||||
"to use this function.");
|
||||
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, GpioAppViewUsbUartCloseRpc);
|
||||
}
|
||||
|
||||
bool gpio_scene_error_expansion_on_event(void* context, SceneManagerEvent event) {
|
||||
GpioApp* app = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == GpioCustomEventErrorBack) {
|
||||
if(!scene_manager_previous_scene(app->scene_manager)) {
|
||||
scene_manager_stop(app->scene_manager);
|
||||
view_dispatcher_stop(app->view_dispatcher);
|
||||
}
|
||||
consumed = true;
|
||||
}
|
||||
}
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void gpio_scene_error_expansion_on_exit(void* context) {
|
||||
GpioApp* app = context;
|
||||
widget_reset(app->widget);
|
||||
}
|
||||
@@ -46,7 +46,7 @@ void line_ensure_flow_invariant(GpioApp* app) {
|
||||
// selected. This function enforces that invariant by resetting flow_pins
|
||||
// to None if it is configured to 16,15 when LPUART is selected.
|
||||
|
||||
uint8_t available_flow_pins = app->usb_uart_cfg->uart_ch == FuriHalUartIdLPUART1 ? 3 : 4;
|
||||
uint8_t available_flow_pins = app->usb_uart_cfg->uart_ch == FuriHalSerialIdLpuart ? 3 : 4;
|
||||
VariableItem* item = app->var_item_flow;
|
||||
variable_item_set_values_count(item, available_flow_pins);
|
||||
|
||||
@@ -77,9 +77,9 @@ static void line_port_cb(VariableItem* item) {
|
||||
variable_item_set_current_value_text(item, uart_ch[index]);
|
||||
|
||||
if(index == 0)
|
||||
app->usb_uart_cfg->uart_ch = FuriHalUartIdUSART1;
|
||||
app->usb_uart_cfg->uart_ch = FuriHalSerialIdUsart;
|
||||
else if(index == 1)
|
||||
app->usb_uart_cfg->uart_ch = FuriHalUartIdLPUART1;
|
||||
app->usb_uart_cfg->uart_ch = FuriHalSerialIdLpuart;
|
||||
|
||||
line_ensure_flow_invariant(app);
|
||||
view_dispatcher_send_custom_event(app->view_dispatcher, GpioUsbUartEventConfigSet);
|
||||
|
||||
@@ -29,17 +29,18 @@ typedef enum {
|
||||
|
||||
WorkerEvtTxStop = (1 << 2),
|
||||
WorkerEvtCdcRx = (1 << 3),
|
||||
WorkerEvtCdcTxComplete = (1 << 4),
|
||||
|
||||
WorkerEvtCfgChange = (1 << 4),
|
||||
WorkerEvtCfgChange = (1 << 5),
|
||||
|
||||
WorkerEvtLineCfgSet = (1 << 5),
|
||||
WorkerEvtCtrlLineSet = (1 << 6),
|
||||
WorkerEvtLineCfgSet = (1 << 6),
|
||||
WorkerEvtCtrlLineSet = (1 << 7),
|
||||
|
||||
} WorkerEvtFlags;
|
||||
|
||||
#define WORKER_ALL_RX_EVENTS \
|
||||
(WorkerEvtStop | WorkerEvtRxDone | WorkerEvtCfgChange | WorkerEvtLineCfgSet | \
|
||||
WorkerEvtCtrlLineSet)
|
||||
WorkerEvtCtrlLineSet | WorkerEvtCdcTxComplete)
|
||||
#define WORKER_ALL_TX_EVENTS (WorkerEvtTxStop | WorkerEvtCdcRx)
|
||||
|
||||
struct UsbUartBridge {
|
||||
@@ -50,6 +51,7 @@ struct UsbUartBridge {
|
||||
FuriThread* tx_thread;
|
||||
|
||||
FuriStreamBuffer* rx_stream;
|
||||
FuriHalSerialHandle* serial_handle;
|
||||
|
||||
FuriMutex* usb_mutex;
|
||||
|
||||
@@ -80,11 +82,23 @@ static const CdcCallbacks cdc_cb = {
|
||||
|
||||
static int32_t usb_uart_tx_thread(void* context);
|
||||
|
||||
static void usb_uart_on_irq_cb(UartIrqEvent ev, uint8_t data, void* context) {
|
||||
static void usb_uart_on_irq_rx_dma_cb(
|
||||
FuriHalSerialHandle* handle,
|
||||
FuriHalSerialRxEvent ev,
|
||||
size_t size,
|
||||
void* context) {
|
||||
UsbUartBridge* usb_uart = (UsbUartBridge*)context;
|
||||
|
||||
if(ev == UartIrqEventRXNE) {
|
||||
furi_stream_buffer_send(usb_uart->rx_stream, &data, 1, 0);
|
||||
if(ev & (FuriHalSerialRxEventData | FuriHalSerialRxEventIdle)) {
|
||||
uint8_t data[FURI_HAL_SERIAL_DMA_BUFFER_SIZE] = {0};
|
||||
while(size) {
|
||||
size_t ret = furi_hal_serial_dma_rx(
|
||||
handle,
|
||||
data,
|
||||
(size > FURI_HAL_SERIAL_DMA_BUFFER_SIZE) ? FURI_HAL_SERIAL_DMA_BUFFER_SIZE : size);
|
||||
furi_stream_buffer_send(usb_uart->rx_stream, data, ret, 0);
|
||||
size -= ret;
|
||||
};
|
||||
furi_thread_flags_set(furi_thread_get_id(usb_uart->thread), WorkerEvtRxDone);
|
||||
}
|
||||
}
|
||||
@@ -116,32 +130,33 @@ static void usb_uart_vcp_deinit(UsbUartBridge* usb_uart, uint8_t vcp_ch) {
|
||||
}
|
||||
|
||||
static void usb_uart_serial_init(UsbUartBridge* usb_uart, uint8_t uart_ch) {
|
||||
if(uart_ch == FuriHalUartIdUSART1) {
|
||||
furi_hal_console_disable();
|
||||
} else if(uart_ch == FuriHalUartIdLPUART1) {
|
||||
furi_hal_uart_init(uart_ch, 115200);
|
||||
}
|
||||
furi_hal_uart_set_irq_cb(uart_ch, usb_uart_on_irq_cb, usb_uart);
|
||||
furi_assert(!usb_uart->serial_handle);
|
||||
|
||||
usb_uart->serial_handle = furi_hal_serial_control_acquire(uart_ch);
|
||||
furi_assert(usb_uart->serial_handle);
|
||||
|
||||
furi_hal_serial_init(usb_uart->serial_handle, 115200);
|
||||
furi_hal_serial_dma_rx_start(
|
||||
usb_uart->serial_handle, usb_uart_on_irq_rx_dma_cb, usb_uart, false);
|
||||
}
|
||||
|
||||
static void usb_uart_serial_deinit(UsbUartBridge* usb_uart, uint8_t uart_ch) {
|
||||
UNUSED(usb_uart);
|
||||
furi_hal_uart_set_irq_cb(uart_ch, NULL, NULL);
|
||||
if(uart_ch == FuriHalUartIdUSART1)
|
||||
furi_hal_console_enable();
|
||||
else if(uart_ch == FuriHalUartIdLPUART1)
|
||||
furi_hal_uart_deinit(uart_ch);
|
||||
static void usb_uart_serial_deinit(UsbUartBridge* usb_uart) {
|
||||
furi_assert(usb_uart->serial_handle);
|
||||
|
||||
furi_hal_serial_deinit(usb_uart->serial_handle);
|
||||
furi_hal_serial_control_release(usb_uart->serial_handle);
|
||||
usb_uart->serial_handle = NULL;
|
||||
}
|
||||
|
||||
static void usb_uart_set_baudrate(UsbUartBridge* usb_uart, uint32_t baudrate) {
|
||||
if(baudrate != 0) {
|
||||
furi_hal_uart_set_br(usb_uart->cfg.uart_ch, baudrate);
|
||||
furi_hal_serial_set_br(usb_uart->serial_handle, baudrate);
|
||||
usb_uart->st.baudrate_cur = baudrate;
|
||||
} else {
|
||||
struct usb_cdc_line_coding* line_cfg =
|
||||
furi_hal_cdc_get_port_settings(usb_uart->cfg.vcp_ch);
|
||||
if(line_cfg->dwDTERate > 0) {
|
||||
furi_hal_uart_set_br(usb_uart->cfg.uart_ch, line_cfg->dwDTERate);
|
||||
furi_hal_serial_set_br(usb_uart->serial_handle, line_cfg->dwDTERate);
|
||||
usb_uart->st.baudrate_cur = line_cfg->dwDTERate;
|
||||
}
|
||||
}
|
||||
@@ -191,7 +206,7 @@ static int32_t usb_uart_worker(void* context) {
|
||||
furi_thread_flags_wait(WORKER_ALL_RX_EVENTS, FuriFlagWaitAny, FuriWaitForever);
|
||||
furi_check(!(events & FuriFlagError));
|
||||
if(events & WorkerEvtStop) break;
|
||||
if(events & WorkerEvtRxDone) {
|
||||
if(events & (WorkerEvtRxDone | WorkerEvtCdcTxComplete)) {
|
||||
size_t len = furi_stream_buffer_receive(
|
||||
usb_uart->rx_stream, usb_uart->rx_buf, USB_CDC_PKT_LEN, 0);
|
||||
if(len > 0) {
|
||||
@@ -223,7 +238,7 @@ static int32_t usb_uart_worker(void* context) {
|
||||
furi_thread_flags_set(furi_thread_get_id(usb_uart->tx_thread), WorkerEvtTxStop);
|
||||
furi_thread_join(usb_uart->tx_thread);
|
||||
|
||||
usb_uart_serial_deinit(usb_uart, usb_uart->cfg.uart_ch);
|
||||
usb_uart_serial_deinit(usb_uart);
|
||||
usb_uart_serial_init(usb_uart, usb_uart->cfg_new.uart_ch);
|
||||
|
||||
usb_uart->cfg.uart_ch = usb_uart->cfg_new.uart_ch;
|
||||
@@ -274,7 +289,7 @@ static int32_t usb_uart_worker(void* context) {
|
||||
}
|
||||
}
|
||||
usb_uart_vcp_deinit(usb_uart, usb_uart->cfg.vcp_ch);
|
||||
usb_uart_serial_deinit(usb_uart, usb_uart->cfg.uart_ch);
|
||||
usb_uart_serial_deinit(usb_uart);
|
||||
|
||||
furi_hal_gpio_init(USB_USART_DE_RE_PIN, GpioModeAnalog, GpioPullNo, GpioSpeedLow);
|
||||
|
||||
@@ -320,18 +335,10 @@ static int32_t usb_uart_tx_thread(void* context) {
|
||||
if(usb_uart->cfg.software_de_re != 0)
|
||||
furi_hal_gpio_write(USB_USART_DE_RE_PIN, false);
|
||||
|
||||
furi_hal_uart_tx(usb_uart->cfg.uart_ch, data, len);
|
||||
furi_hal_serial_tx(usb_uart->serial_handle, data, len);
|
||||
|
||||
if(usb_uart->cfg.software_de_re != 0) {
|
||||
//TODO: FL-3276 port to new USART API
|
||||
if(usb_uart->cfg.uart_ch == FuriHalUartIdUSART1) {
|
||||
while(!LL_USART_IsActiveFlag_TC(USART1))
|
||||
;
|
||||
} else if(usb_uart->cfg.uart_ch == FuriHalUartIdLPUART1) {
|
||||
while(!LL_LPUART_IsActiveFlag_TC(LPUART1))
|
||||
;
|
||||
}
|
||||
|
||||
furi_hal_serial_tx_wait_complete(usb_uart->serial_handle);
|
||||
furi_hal_gpio_write(USB_USART_DE_RE_PIN, true);
|
||||
}
|
||||
}
|
||||
@@ -345,6 +352,7 @@ static int32_t usb_uart_tx_thread(void* context) {
|
||||
static void vcp_on_cdc_tx_complete(void* context) {
|
||||
UsbUartBridge* usb_uart = (UsbUartBridge*)context;
|
||||
furi_semaphore_release(usb_uart->tx_sem);
|
||||
furi_thread_flags_set(furi_thread_get_id(usb_uart->thread), WorkerEvtCdcTxComplete);
|
||||
}
|
||||
|
||||
static void vcp_on_cdc_rx(void* context) {
|
||||
|
||||
@@ -1,6 +1,30 @@
|
||||
#include "lfrfid_i.h"
|
||||
#include <dolphin/dolphin.h>
|
||||
|
||||
//TODO: use .txt file in resources for passwords.
|
||||
const uint32_t default_passwords[] = {
|
||||
0x51243648, 0x000D8787, 0x19920427, 0x50524F58, 0xF9DCEBA0, 0x65857569, 0x05D73B9F, 0x89A69E60,
|
||||
0x314159E0, 0xAA55BBBB, 0xA5B4C3D2, 0x1C0B5848, 0x00434343, 0x444E4752, 0x4E457854, 0x44B44CAE,
|
||||
0x88661858, 0xE9920427, 0x575F4F4B, 0x50520901, 0x20206666, 0x65857569, 0x5469616E, 0x7686962A,
|
||||
0xC0F5009A, 0x07CEE75D, 0xfeedbeef, 0xdeadc0de, 0x00000000, 0x11111111, 0x22222222, 0x33333333,
|
||||
0x44444444, 0x55555555, 0x66666666, 0x77777777, 0x88888888, 0x99999999, 0xAAAAAAAA, 0xBBBBBBBB,
|
||||
0xCCCCCCCC, 0xDDDDDDDD, 0xEEEEEEEE, 0xFFFFFFFF, 0xa0a1a2a3, 0xb0b1b2b3, 0x50415353, 0x00000001,
|
||||
0x00000002, 0x0000000a, 0x0000000b, 0x01020304, 0x02030405, 0x03040506, 0x04050607, 0x05060708,
|
||||
0x06070809, 0x0708090A, 0x08090A0B, 0x090A0B0C, 0x0A0B0C0D, 0x0B0C0D0E, 0x0C0D0E0F, 0x01234567,
|
||||
0x12345678, 0x10000000, 0x20000000, 0x30000000, 0x40000000, 0x50000000, 0x60000000, 0x70000000,
|
||||
0x80000000, 0x90000000, 0xA0000000, 0xB0000000, 0xC0000000, 0xD0000000, 0xE0000000, 0xF0000000,
|
||||
0x10101010, 0x01010101, 0x11223344, 0x22334455, 0x33445566, 0x44556677, 0x55667788, 0x66778899,
|
||||
0x778899AA, 0x8899AABB, 0x99AABBCC, 0xAABBCCDD, 0xBBCCDDEE, 0xCCDDEEFF, 0x0CB7E7FC, 0xFABADA11,
|
||||
0x87654321, 0x12341234, 0x69696969, 0x12121212, 0x12344321, 0x1234ABCD, 0x11112222, 0x13131313,
|
||||
0x10041004, 0x31415926, 0xabcd1234, 0x20002000, 0x19721972, 0xaa55aa55, 0x55aa55aa, 0x4f271149,
|
||||
0x07d7bb0b, 0x9636ef8f, 0xb5f44686, 0x9E3779B9, 0xC6EF3720, 0x7854794A, 0xF1EA5EED, 0x69314718,
|
||||
0x57721566, 0x93C467E3, 0x27182818, 0x50415353};
|
||||
|
||||
const uint32_t* lfrfid_get_t5577_default_passwords(uint8_t* len) {
|
||||
*len = sizeof(default_passwords) / sizeof(uint32_t);
|
||||
return default_passwords;
|
||||
}
|
||||
|
||||
static bool lfrfid_debug_custom_event_callback(void* context, uint32_t event) {
|
||||
furi_assert(context);
|
||||
LfRfid* app = context;
|
||||
|
||||
@@ -25,11 +25,13 @@ void lfrfid_on_system_start() {
|
||||
|
||||
static void lfrfid_cli_print_usage() {
|
||||
printf("Usage:\r\n");
|
||||
printf("rfid read <optional: normal | indala>\r\n");
|
||||
printf("rfid <write | emulate> <key_type> <key_data>\r\n");
|
||||
printf("rfid raw_read <ask | psk> <filename>\r\n");
|
||||
printf("rfid raw_emulate <filename>\r\n");
|
||||
printf("rfid raw_analyze <filename>\r\n");
|
||||
printf("rfid read <optional: normal | indala> - read in ASK/PSK mode\r\n");
|
||||
printf("rfid <write | emulate> <key_type> <key_data> - write or emulate a card\r\n");
|
||||
printf("rfid raw_read <ask | psk> <filename> - read and save raw data to a file\r\n");
|
||||
printf(
|
||||
"rfid raw_emulate <filename> - emulate raw data (not very useful, but helps debug protocols)\r\n");
|
||||
printf(
|
||||
"rfid raw_analyze <filename> - outputs raw data to the cli and tries to decode it (useful for protocol development)\r\n");
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
|
||||
@@ -98,6 +98,8 @@ struct LfRfid {
|
||||
uint8_t* old_key_data;
|
||||
uint8_t* new_key_data;
|
||||
|
||||
uint8_t password[4];
|
||||
|
||||
RpcAppSystem* rpc_ctx;
|
||||
LfRfidRpcState rpc_state;
|
||||
|
||||
@@ -145,3 +147,5 @@ void lfrfid_popup_timeout_callback(void* context);
|
||||
void lfrfid_widget_callback(GuiButtonType result, InputType type, void* context);
|
||||
|
||||
void lfrfid_text_input_callback(void* context);
|
||||
|
||||
const uint32_t* lfrfid_get_t5577_default_passwords(uint8_t* len);
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "../lfrfid_i.h"
|
||||
#include "tools/t5577.h"
|
||||
#define TAG "Clear T5577"
|
||||
|
||||
static void lfrfid_clear_t5577_password_and_config_to_EM(LfRfid* app) {
|
||||
@@ -6,7 +7,7 @@ static void lfrfid_clear_t5577_password_and_config_to_EM(LfRfid* app) {
|
||||
char curr_buf[32] = {};
|
||||
|
||||
uint8_t default_passwords_len;
|
||||
const uint32_t* default_passwords = t5577_get_default_passwords(&default_passwords_len);
|
||||
const uint32_t* default_passwords = lfrfid_get_t5577_default_passwords(&default_passwords_len);
|
||||
|
||||
popup_set_header(popup, "Removing\npassword", 90, 36, AlignCenter, AlignCenter);
|
||||
popup_set_icon(popup, 0, 3, &I_RFIDDolphinSend_97x61);
|
||||
@@ -15,14 +16,26 @@ static void lfrfid_clear_t5577_password_and_config_to_EM(LfRfid* app) {
|
||||
|
||||
LFRFIDT5577 data = {
|
||||
.block[0] = 0b00000000000101001000000001000000,
|
||||
.blocks_to_write = 1,
|
||||
.block[7] = 0,
|
||||
.mask = 0b10000001,
|
||||
};
|
||||
|
||||
// Clear custom password
|
||||
uint32_t custom_pass = (app->password[0] << 24) | (app->password[1] << 16) |
|
||||
(app->password[2] << 8) | (app->password[3]);
|
||||
snprintf(curr_buf, sizeof(curr_buf), "Custom password");
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidViewPopup);
|
||||
|
||||
t5577_write_with_mask(&data, 0, true, custom_pass);
|
||||
|
||||
furi_delay_ms(8);
|
||||
|
||||
// Clear default passwords
|
||||
for(uint8_t i = 0; i < default_passwords_len; i++) {
|
||||
snprintf(curr_buf, sizeof(curr_buf), "Pass %d of %d", i, default_passwords_len);
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidViewPopup);
|
||||
|
||||
t5577_write_with_pass(&data, default_passwords[i]);
|
||||
t5577_write_with_mask(&data, 0, true, default_passwords[i]);
|
||||
furi_delay_ms(8);
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ ADD_SCENE(lfrfid, exit_confirm, ExitConfirm)
|
||||
ADD_SCENE(lfrfid, delete_confirm, DeleteConfirm)
|
||||
ADD_SCENE(lfrfid, read_key_menu, ReadKeyMenu)
|
||||
ADD_SCENE(lfrfid, write, Write)
|
||||
ADD_SCENE(lfrfid, write_with_pass, WriteWithPass)
|
||||
ADD_SCENE(lfrfid, write_and_set_pass, WriteAndSetPass)
|
||||
ADD_SCENE(lfrfid, write_success, WriteSuccess)
|
||||
ADD_SCENE(lfrfid, emulate, Emulate)
|
||||
ADD_SCENE(lfrfid, save_name, SaveName)
|
||||
@@ -18,6 +18,7 @@ ADD_SCENE(lfrfid, save_type, SaveType)
|
||||
ADD_SCENE(lfrfid, saved_info, SavedInfo)
|
||||
ADD_SCENE(lfrfid, clear_t5577, ClearT5577)
|
||||
ADD_SCENE(lfrfid, clear_t5577_confirm, ClearT5577Confirm)
|
||||
ADD_SCENE(lfrfid, enter_password, EnterPassword)
|
||||
ADD_SCENE(lfrfid, delete_success, DeleteSuccess)
|
||||
ADD_SCENE(lfrfid, extra_actions, ExtraActions)
|
||||
ADD_SCENE(lfrfid, raw_info, RawInfo)
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
#include "../lfrfid_i.h"
|
||||
#include "gui/scene_manager.h"
|
||||
|
||||
int next_scene;
|
||||
|
||||
void lfrfid_scene_enter_password_on_enter(void* context) {
|
||||
LfRfid* app = context;
|
||||
ByteInput* byte_input = app->byte_input;
|
||||
|
||||
// true - use password for write, false - use password for clear pass
|
||||
next_scene = scene_manager_get_scene_state(app->scene_manager, LfRfidSceneEnterPassword);
|
||||
|
||||
bool password_set = app->password[0] | app->password[1] | app->password[2] | app->password[3];
|
||||
|
||||
if(next_scene == LfRfidSceneWriteAndSetPass && !password_set) {
|
||||
uint8_t password_list_size;
|
||||
const uint32_t* password_list = lfrfid_get_t5577_default_passwords(&password_list_size);
|
||||
uint32_t pass = password_list[furi_get_tick() % password_list_size];
|
||||
|
||||
for(uint8_t i = 0; i < 4; i++) app->password[i] = (pass >> (8 * i)) & 0xFF;
|
||||
}
|
||||
|
||||
byte_input_set_header_text(byte_input, "Enter the password in hex");
|
||||
|
||||
byte_input_set_result_callback(
|
||||
byte_input, lfrfid_text_input_callback, NULL, app, app->password, 4);
|
||||
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidViewByteInput);
|
||||
}
|
||||
|
||||
bool lfrfid_scene_enter_password_on_event(void* context, SceneManagerEvent event) {
|
||||
LfRfid* app = context;
|
||||
SceneManager* scene_manager = app->scene_manager;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == LfRfidEventNext) {
|
||||
consumed = true;
|
||||
|
||||
scene_manager_next_scene(scene_manager, next_scene);
|
||||
scene_manager_set_scene_state(scene_manager, LfRfidSceneEnterPassword, 1);
|
||||
}
|
||||
} else if(event.type == SceneManagerEventTypeBack) {
|
||||
uint32_t prev_scenes[] = {LfRfidSceneExtraActions, LfRfidSceneSavedKeyMenu};
|
||||
scene_manager_set_scene_state(scene_manager, LfRfidSceneEnterPassword, 0);
|
||||
scene_manager_search_and_switch_to_previous_scene_one_of(
|
||||
scene_manager, prev_scenes, sizeof(prev_scenes[0]));
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void lfrfid_scene_enter_password_on_exit(void* context) {
|
||||
UNUSED(context);
|
||||
}
|
||||
@@ -80,7 +80,9 @@ bool lfrfid_scene_extra_actions_on_event(void* context, SceneManagerEvent event)
|
||||
dolphin_deed(DolphinDeedRfidRead);
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexClearT5577) {
|
||||
scene_manager_next_scene(app->scene_manager, LfRfidSceneClearT5577Confirm);
|
||||
scene_manager_set_scene_state(
|
||||
app->scene_manager, LfRfidSceneEnterPassword, LfRfidSceneClearT5577Confirm);
|
||||
scene_manager_next_scene(app->scene_manager, LfRfidSceneEnterPassword);
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexRAW) {
|
||||
scene_manager_next_scene(app->scene_manager, LfRfidSceneRawName);
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
typedef enum {
|
||||
SubmenuIndexEmulate,
|
||||
SubmenuIndexWrite,
|
||||
SubmenuIndexWriteWithPass,
|
||||
SubmenuIndexWriteAndSetPass,
|
||||
SubmenuIndexEdit,
|
||||
SubmenuIndexDelete,
|
||||
SubmenuIndexInfo,
|
||||
@@ -26,8 +26,8 @@ void lfrfid_scene_saved_key_menu_on_enter(void* context) {
|
||||
submenu, "Write", SubmenuIndexWrite, lfrfid_scene_saved_key_menu_submenu_callback, app);
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Write with pass",
|
||||
SubmenuIndexWriteWithPass,
|
||||
"Write and set pass",
|
||||
SubmenuIndexWriteAndSetPass,
|
||||
lfrfid_scene_saved_key_menu_submenu_callback,
|
||||
app);
|
||||
submenu_add_item(
|
||||
@@ -55,8 +55,10 @@ bool lfrfid_scene_saved_key_menu_on_event(void* context, SceneManagerEvent event
|
||||
} else if(event.event == SubmenuIndexWrite) {
|
||||
scene_manager_next_scene(app->scene_manager, LfRfidSceneWrite);
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexWriteWithPass) {
|
||||
scene_manager_next_scene(app->scene_manager, LfRfidSceneWriteWithPass);
|
||||
} else if(event.event == SubmenuIndexWriteAndSetPass) {
|
||||
scene_manager_set_scene_state(
|
||||
app->scene_manager, LfRfidSceneEnterPassword, LfRfidSceneWriteAndSetPass);
|
||||
scene_manager_next_scene(app->scene_manager, LfRfidSceneEnterPassword);
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexEdit) {
|
||||
scene_manager_next_scene(app->scene_manager, LfRfidSceneSaveData);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "../lfrfid_i.h"
|
||||
#include "gui/scene_manager.h"
|
||||
|
||||
static void lfrfid_write_with_pass_callback(LFRFIDWorkerWriteResult result, void* context) {
|
||||
static void lfrfid_write_and_set_pass_callback(LFRFIDWorkerWriteResult result, void* context) {
|
||||
LfRfid* app = context;
|
||||
uint32_t event = 0;
|
||||
|
||||
@@ -17,22 +18,11 @@ static void lfrfid_write_with_pass_callback(LFRFIDWorkerWriteResult result, void
|
||||
view_dispatcher_send_custom_event(app->view_dispatcher, event);
|
||||
}
|
||||
|
||||
void lfrfid_scene_write_with_pass_on_enter(void* context) {
|
||||
void lfrfid_scene_write_and_set_pass_on_enter(void* context) {
|
||||
LfRfid* app = context;
|
||||
Popup* popup = app->popup;
|
||||
|
||||
popup_set_header(popup, "Writing", 89, 30, AlignCenter, AlignTop);
|
||||
if(!furi_string_empty(app->file_name)) {
|
||||
popup_set_text(popup, furi_string_get_cstr(app->file_name), 89, 43, AlignCenter, AlignTop);
|
||||
} else {
|
||||
popup_set_text(
|
||||
popup,
|
||||
protocol_dict_get_name(app->dict, app->protocol_id),
|
||||
89,
|
||||
43,
|
||||
AlignCenter,
|
||||
AlignTop);
|
||||
}
|
||||
popup_set_header(popup, "Writing\nwith password", 89, 30, AlignCenter, AlignTop);
|
||||
popup_set_icon(popup, 0, 3, &I_RFIDDolphinSend_97x61);
|
||||
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidViewPopup);
|
||||
@@ -41,12 +31,12 @@ void lfrfid_scene_write_with_pass_on_enter(void* context) {
|
||||
protocol_dict_get_data(app->dict, app->protocol_id, app->old_key_data, size);
|
||||
|
||||
lfrfid_worker_start_thread(app->lfworker);
|
||||
lfrfid_worker_write_with_pass_start(
|
||||
app->lfworker, (LFRFIDProtocol)app->protocol_id, lfrfid_write_with_pass_callback, app);
|
||||
lfrfid_worker_write_and_set_pass_start(
|
||||
app->lfworker, (LFRFIDProtocol)app->protocol_id, lfrfid_write_and_set_pass_callback, app);
|
||||
notification_message(app->notifications, &sequence_blink_start_magenta);
|
||||
}
|
||||
|
||||
bool lfrfid_scene_write_with_pass_on_event(void* context, SceneManagerEvent event) {
|
||||
bool lfrfid_scene_write_and_set_pass_on_event(void* context, SceneManagerEvent event) {
|
||||
LfRfid* app = context;
|
||||
Popup* popup = app->popup;
|
||||
bool consumed = false;
|
||||
@@ -82,7 +72,7 @@ bool lfrfid_scene_write_with_pass_on_event(void* context, SceneManagerEvent even
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void lfrfid_scene_write_with_pass_on_exit(void* context) {
|
||||
void lfrfid_scene_write_and_set_pass_on_exit(void* context) {
|
||||
LfRfid* app = context;
|
||||
notification_message(app->notifications, &sequence_blink_stop);
|
||||
popup_reset(app->popup);
|
||||
@@ -18,20 +18,20 @@ void nfc_render_iso15693_3_info(
|
||||
}
|
||||
|
||||
void nfc_render_iso15693_3_brief(const Iso15693_3Data* data, FuriString* str) {
|
||||
furi_string_cat_printf(str, "UID:");
|
||||
furi_string_cat_printf(str, "UID:\n");
|
||||
|
||||
size_t uid_len;
|
||||
const uint8_t* uid = iso15693_3_get_uid(data, &uid_len);
|
||||
|
||||
for(size_t i = 0; i < uid_len; i++) {
|
||||
furi_string_cat_printf(str, " %02X", uid[i]);
|
||||
furi_string_cat_printf(str, "%02X ", uid[i]);
|
||||
}
|
||||
|
||||
if(data->system_info.flags & ISO15693_3_SYSINFO_FLAG_MEMORY) {
|
||||
const uint16_t block_count = iso15693_3_get_block_count(data);
|
||||
const uint8_t block_size = iso15693_3_get_block_size(data);
|
||||
|
||||
furi_string_cat_printf(str, "Memory: %u bytes\n", block_count * block_size);
|
||||
furi_string_cat_printf(str, "\nMemory: %u bytes\n", block_count * block_size);
|
||||
furi_string_cat_printf(str, "(%u blocks x %u bytes)", block_count, block_size);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,8 @@ static void nfc_scene_info_on_enter_mf_classic(NfcApp* instance) {
|
||||
FuriString* temp_str = furi_string_alloc();
|
||||
furi_string_cat_printf(
|
||||
temp_str, "\e#%s\n", nfc_device_get_name(device, NfcDeviceNameTypeFull));
|
||||
furi_string_replace(temp_str, "Mifare", "MIFARE");
|
||||
|
||||
nfc_render_mf_classic_info(data, NfcProtocolFormatTypeFull, temp_str);
|
||||
|
||||
widget_add_text_scroll_element(
|
||||
@@ -119,13 +121,15 @@ static void nfc_scene_read_menu_on_enter_mf_classic(NfcApp* instance) {
|
||||
}
|
||||
}
|
||||
|
||||
static void nfc_scene_read_success_on_enter_mf_classic(NfcApp* instance) {
|
||||
static void nfc_scene_read_success_on_enter_mf_classic(NfcApp* instance) { //-V524
|
||||
const NfcDevice* device = instance->nfc_device;
|
||||
const MfClassicData* data = nfc_device_get_data(device, NfcProtocolMfClassic);
|
||||
|
||||
FuriString* temp_str = furi_string_alloc();
|
||||
furi_string_cat_printf(
|
||||
temp_str, "\e#%s\n", nfc_device_get_name(device, NfcDeviceNameTypeFull));
|
||||
furi_string_replace(temp_str, "Mifare", "MIFARE");
|
||||
|
||||
nfc_render_mf_classic_info(data, NfcProtocolFormatTypeShort, temp_str);
|
||||
|
||||
widget_add_text_scroll_element(
|
||||
@@ -168,7 +172,7 @@ static void nfc_scene_emulate_on_enter_mf_classic(NfcApp* instance) {
|
||||
|
||||
static bool nfc_scene_read_menu_on_event_mf_classic(NfcApp* instance, uint32_t event) {
|
||||
if(event == SubmenuIndexDetectReader) {
|
||||
scene_manager_next_scene(instance->scene_manager, NfcSceneMfClassicDetectReader);
|
||||
scene_manager_next_scene(instance->scene_manager, NfcSceneSaveConfirm);
|
||||
dolphin_deed(DolphinDeedNfcDetectReader);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -391,12 +391,15 @@ static void nfc_protocol_support_scene_saved_menu_on_enter(NfcApp* instance) {
|
||||
nfc_protocol_support[protocol]->scene_saved_menu.on_enter(instance);
|
||||
|
||||
// Trailer submenu items
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Info",
|
||||
SubmenuIndexCommonInfo,
|
||||
nfc_protocol_support_common_submenu_callback,
|
||||
instance);
|
||||
if(nfc_has_shadow_file(instance)) {
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Restore to Original State",
|
||||
SubmenuIndexCommonRestore,
|
||||
nfc_protocol_support_common_submenu_callback,
|
||||
instance);
|
||||
}
|
||||
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Rename",
|
||||
@@ -409,15 +412,12 @@ static void nfc_protocol_support_scene_saved_menu_on_enter(NfcApp* instance) {
|
||||
SubmenuIndexCommonDelete,
|
||||
nfc_protocol_support_common_submenu_callback,
|
||||
instance);
|
||||
|
||||
if(nfc_has_shadow_file(instance)) {
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Restore Data Changes",
|
||||
SubmenuIndexCommonRestore,
|
||||
nfc_protocol_support_common_submenu_callback,
|
||||
instance);
|
||||
}
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Info",
|
||||
SubmenuIndexCommonInfo,
|
||||
nfc_protocol_support_common_submenu_callback,
|
||||
instance);
|
||||
|
||||
submenu_set_selected_item(
|
||||
instance->submenu,
|
||||
@@ -582,9 +582,18 @@ static void nfc_protocol_support_scene_emulate_on_enter(NfcApp* instance) {
|
||||
|
||||
} else {
|
||||
widget_add_string_element(widget, 90, 13, AlignCenter, AlignTop, FontPrimary, "Emulating");
|
||||
furi_string_set(
|
||||
temp_str, nfc_device_get_name(instance->nfc_device, NfcDeviceNameTypeFull));
|
||||
furi_string_cat_printf(temp_str, "\n%s", furi_string_get_cstr(instance->file_name));
|
||||
if(!furi_string_empty(instance->file_name)) {
|
||||
furi_string_printf(
|
||||
temp_str,
|
||||
"%s\n%s",
|
||||
nfc_device_get_name(instance->nfc_device, NfcDeviceNameTypeFull),
|
||||
furi_string_get_cstr(instance->file_name));
|
||||
} else {
|
||||
furi_string_printf(
|
||||
temp_str,
|
||||
"Unsaved\n%s",
|
||||
nfc_device_get_name(instance->nfc_device, NfcDeviceNameTypeFull));
|
||||
}
|
||||
}
|
||||
|
||||
widget_add_text_box_element(
|
||||
|
||||
@@ -23,6 +23,7 @@ ADD_SCENE(nfc, debug, Debug)
|
||||
ADD_SCENE(nfc, field, Field)
|
||||
ADD_SCENE(nfc, retry_confirm, RetryConfirm)
|
||||
ADD_SCENE(nfc, exit_confirm, ExitConfirm)
|
||||
ADD_SCENE(nfc, save_confirm, SaveConfirm)
|
||||
|
||||
ADD_SCENE(nfc, mf_ultralight_write, MfUltralightWrite)
|
||||
ADD_SCENE(nfc, mf_ultralight_write_success, MfUltralightWriteSuccess)
|
||||
|
||||
@@ -24,7 +24,7 @@ void nfc_scene_extra_actions_on_enter(void* context) {
|
||||
instance);
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Mifare Classic Keys",
|
||||
"MIFARE Classic Keys",
|
||||
SubmenuIndexMfClassicKeys,
|
||||
nfc_scene_extra_actions_submenu_callback,
|
||||
instance);
|
||||
|
||||
@@ -134,6 +134,13 @@ bool nfc_scene_mf_classic_detect_reader_on_event(void* context, SceneManagerEven
|
||||
instance->listener = NULL;
|
||||
}
|
||||
mfkey32_logger_free(instance->mfkey32_logger);
|
||||
if(scene_manager_has_previous_scene(instance->scene_manager, NfcSceneSaveSuccess)) {
|
||||
consumed = scene_manager_search_and_switch_to_previous_scene(
|
||||
instance->scene_manager, NfcSceneStart);
|
||||
} else if(scene_manager_has_previous_scene(instance->scene_manager, NfcSceneReadSuccess)) {
|
||||
consumed = scene_manager_search_and_switch_to_previous_scene(
|
||||
instance->scene_manager, NfcSceneReadSuccess);
|
||||
}
|
||||
}
|
||||
|
||||
return consumed;
|
||||
|
||||
@@ -18,15 +18,16 @@ void nfc_scene_mf_classic_mfkey_complete_on_enter(void* context) {
|
||||
widget_add_string_multiline_element(
|
||||
instance->widget,
|
||||
64,
|
||||
32,
|
||||
AlignCenter,
|
||||
13,
|
||||
AlignCenter,
|
||||
AlignTop,
|
||||
FontSecondary,
|
||||
"Now use Mfkey32\nto extract keys");
|
||||
"Now use Mfkey32 to extract \nkeys: lab.flipper.net/nfc-tools");
|
||||
widget_add_icon_element(instance->widget, 50, 39, &I_MFKey_qr_25x25);
|
||||
widget_add_button_element(
|
||||
instance->widget,
|
||||
GuiButtonTypeCenter,
|
||||
"OK",
|
||||
GuiButtonTypeRight,
|
||||
"Finish",
|
||||
nfc_scene_mf_classic_mfkey_complete_callback,
|
||||
instance);
|
||||
|
||||
@@ -38,7 +39,7 @@ bool nfc_scene_mf_classic_mfkey_complete_on_event(void* context, SceneManagerEve
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == GuiButtonTypeCenter) {
|
||||
if(event.event == GuiButtonTypeRight) {
|
||||
consumed = scene_manager_search_and_switch_to_previous_scene(
|
||||
instance->scene_manager, NfcSceneStart);
|
||||
}
|
||||
|
||||
@@ -65,8 +65,9 @@ static void nfc_scene_mf_classic_write_initial_setup_view(NfcApp* instance) {
|
||||
scene_manager_get_scene_state(instance->scene_manager, NfcSceneMfClassicWriteInitial);
|
||||
|
||||
if(state == NfcSceneMfClassicWriteInitialStateCardSearch) {
|
||||
popup_set_header(instance->popup, "Writing", 95, 20, AlignCenter, AlignCenter);
|
||||
popup_set_text(
|
||||
instance->popup, "Apply the initial\ncard only", 128, 32, AlignRight, AlignCenter);
|
||||
instance->popup, "Apply the initial\ncard only", 95, 38, AlignCenter, AlignCenter);
|
||||
popup_set_icon(instance->popup, 0, 8, &I_NFC_manual_60x50);
|
||||
} else {
|
||||
popup_set_header(popup, "Writing\nDon't move...", 52, 32, AlignLeft, AlignCenter);
|
||||
|
||||
@@ -46,8 +46,9 @@ static void nfc_scene_mf_ultralight_write_setup_view(NfcApp* instance) {
|
||||
scene_manager_get_scene_state(instance->scene_manager, NfcSceneMfUltralightWrite);
|
||||
|
||||
if(state == NfcSceneMfUltralightWriteStateCardSearch) {
|
||||
popup_set_header(instance->popup, "Writing", 95, 20, AlignCenter, AlignCenter);
|
||||
popup_set_text(
|
||||
instance->popup, "Apply the initial\ncard only", 128, 32, AlignRight, AlignCenter);
|
||||
instance->popup, "Apply the initial\ncard only", 95, 38, AlignCenter, AlignCenter);
|
||||
popup_set_icon(instance->popup, 0, 8, &I_NFC_manual_60x50);
|
||||
} else {
|
||||
popup_set_header(popup, "Writing\nDon't move...", 52, 32, AlignLeft, AlignCenter);
|
||||
|
||||
44
applications/main/nfc/scenes/nfc_scene_save_confirm.c
Normal file
44
applications/main/nfc/scenes/nfc_scene_save_confirm.c
Normal file
@@ -0,0 +1,44 @@
|
||||
#include "../nfc_app_i.h"
|
||||
|
||||
void nfc_scene_save_confirm_dialog_callback(DialogExResult result, void* context) {
|
||||
NfcApp* nfc = context;
|
||||
|
||||
view_dispatcher_send_custom_event(nfc->view_dispatcher, result);
|
||||
}
|
||||
|
||||
void nfc_scene_save_confirm_on_enter(void* context) {
|
||||
NfcApp* nfc = context;
|
||||
DialogEx* dialog_ex = nfc->dialog_ex;
|
||||
|
||||
dialog_ex_set_left_button_text(dialog_ex, "Skip");
|
||||
dialog_ex_set_right_button_text(dialog_ex, "Save");
|
||||
dialog_ex_set_header(dialog_ex, "Save the Key?", 64, 0, AlignCenter, AlignTop);
|
||||
dialog_ex_set_text(dialog_ex, "All unsaved data will be lost", 64, 12, AlignCenter, AlignTop);
|
||||
dialog_ex_set_context(dialog_ex, nfc);
|
||||
dialog_ex_set_result_callback(dialog_ex, nfc_scene_save_confirm_dialog_callback);
|
||||
|
||||
view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewDialogEx);
|
||||
}
|
||||
|
||||
bool nfc_scene_save_confirm_on_event(void* context, SceneManagerEvent event) {
|
||||
NfcApp* nfc = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == DialogExResultRight) {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveName);
|
||||
consumed = true;
|
||||
} else if(event.event == DialogExResultLeft) {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicDetectReader);
|
||||
consumed = true;
|
||||
}
|
||||
}
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void nfc_scene_save_confirm_on_exit(void* context) {
|
||||
NfcApp* nfc = context;
|
||||
|
||||
// Clean view
|
||||
dialog_ex_reset(nfc->dialog_ex);
|
||||
}
|
||||
@@ -28,6 +28,9 @@ bool nfc_scene_save_success_on_event(void* context, SceneManagerEvent event) {
|
||||
if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneMfClassicKeys)) {
|
||||
consumed = scene_manager_search_and_switch_to_previous_scene(
|
||||
nfc->scene_manager, NfcSceneMfClassicKeys);
|
||||
} else if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneSaveConfirm)) {
|
||||
scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicDetectReader);
|
||||
consumed = true;
|
||||
} else {
|
||||
consumed = scene_manager_search_and_switch_to_another_scene(
|
||||
nfc->scene_manager, NfcSceneFileSelect);
|
||||
|
||||
@@ -32,10 +32,20 @@ void nfc_scene_set_type_on_enter(void* context) {
|
||||
nfc_protocol_support_common_submenu_callback,
|
||||
instance);
|
||||
|
||||
FuriString* str = furi_string_alloc();
|
||||
for(size_t i = 0; i < NfcDataGeneratorTypeNum; i++) {
|
||||
const char* name = nfc_data_generator_get_name(i);
|
||||
submenu_add_item(submenu, name, i, nfc_protocol_support_common_submenu_callback, instance);
|
||||
furi_string_cat_str(str, nfc_data_generator_get_name(i));
|
||||
furi_string_replace_str(str, "Mifare", "MIFARE");
|
||||
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
furi_string_get_cstr(str),
|
||||
i,
|
||||
nfc_protocol_support_common_submenu_callback,
|
||||
instance);
|
||||
furi_string_reset(str);
|
||||
}
|
||||
furi_string_free(str);
|
||||
|
||||
view_dispatcher_switch_to_view(instance->view_dispatcher, NfcViewMenu);
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ static void detect_reader_draw_callback(Canvas* canvas, void* model) {
|
||||
if(m->state == DetectReaderStateDone) {
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
canvas_draw_str_aligned(canvas, 51, 22, AlignLeft, AlignTop, "Completed!");
|
||||
canvas_draw_icon(canvas, 20, 23, &I_check_big_20x17);
|
||||
canvas_draw_icon(canvas, 24, 23, &I_check_big_20x17);
|
||||
} else {
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
canvas_draw_str_aligned(canvas, 51, 22, AlignLeft, AlignTop, "Collecting...");
|
||||
|
||||
@@ -24,12 +24,14 @@ typedef enum {
|
||||
SubmenuIndexSommer_FM_868,
|
||||
SubmenuIndexStilmatic,
|
||||
SubmenuIndexDTMNeo433,
|
||||
SubmenuIndexDeaMio433,
|
||||
SubmenuIndexGibidi433,
|
||||
SubmenuIndexNiceMHouse_433_92,
|
||||
SubmenuIndexJCM_433_92,
|
||||
SubmenuIndexFAACRCXT_433_92,
|
||||
SubmenuIndexFAACRCXT_868,
|
||||
SubmenuIndexNormstahl_433_92,
|
||||
SubmenuIndexGeniusBravo433,
|
||||
SubmenuIndexGSN,
|
||||
SubmenuIndexAprimatic,
|
||||
SubmenuIndexHCS101_433_92,
|
||||
|
||||
@@ -81,7 +81,6 @@ static int32_t subghz_frequency_analyzer_worker_thread(void* context) {
|
||||
uint32_t frequency = 0;
|
||||
float rssi_temp = 0;
|
||||
uint32_t frequency_temp = 0;
|
||||
CC1101Status status;
|
||||
|
||||
FuriHalSpiBusHandle* spi_bus = instance->spi_bus;
|
||||
const SubGhzDevice* radio_device = instance->radio_device;
|
||||
@@ -143,9 +142,8 @@ static int32_t subghz_frequency_analyzer_worker_thread(void* context) {
|
||||
frequency = cc1101_set_frequency(spi_bus, current_frequency);
|
||||
|
||||
cc1101_calibrate(spi_bus);
|
||||
do {
|
||||
status = cc1101_get_status(spi_bus);
|
||||
} while(status.STATE != CC1101StateIDLE);
|
||||
|
||||
furi_check(cc1101_wait_status_state(spi_bus, CC1101StateIDLE, 10000));
|
||||
|
||||
cc1101_switch_to_rx(spi_bus);
|
||||
furi_hal_spi_release(spi_bus);
|
||||
@@ -191,9 +189,8 @@ static int32_t subghz_frequency_analyzer_worker_thread(void* context) {
|
||||
frequency = cc1101_set_frequency(spi_bus, i);
|
||||
|
||||
cc1101_calibrate(spi_bus);
|
||||
do {
|
||||
status = cc1101_get_status(spi_bus);
|
||||
} while(status.STATE != CC1101StateIDLE);
|
||||
|
||||
furi_check(cc1101_wait_status_state(spi_bus, CC1101StateIDLE, 10000));
|
||||
|
||||
cc1101_switch_to_rx(spi_bus);
|
||||
furi_hal_spi_release(spi_bus);
|
||||
|
||||
@@ -63,6 +63,10 @@ bool subghz_scene_frequency_analyzer_on_event(void* context, SceneManagerEvent e
|
||||
#ifdef FURI_DEBUG
|
||||
subghz_last_settings_log(subghz->last_settings);
|
||||
#endif
|
||||
// Disable Hopping before opening the receiver scene!
|
||||
if(subghz->last_settings->enable_hopping) {
|
||||
subghz->last_settings->enable_hopping = false;
|
||||
}
|
||||
subghz_last_settings_save(subghz->last_settings);
|
||||
}
|
||||
|
||||
|
||||
@@ -165,6 +165,9 @@ bool subghz_scene_receiver_info_on_event(void* context, SceneManagerEvent event)
|
||||
if(subghz_txrx_protocol_is_serializable(subghz->txrx)) {
|
||||
subghz_file_name_clear(subghz);
|
||||
|
||||
subghz->save_datetime =
|
||||
subghz_history_get_datetime(subghz->history, subghz->idx_menu_chosen);
|
||||
subghz->save_datetime_set = true;
|
||||
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneSaveName);
|
||||
}
|
||||
return true;
|
||||
|
||||
@@ -6,44 +6,12 @@
|
||||
#include <dolphin/dolphin.h>
|
||||
#include <toolbox/name_generator.h>
|
||||
|
||||
#define MAX_TEXT_INPUT_LEN 23
|
||||
|
||||
void subghz_scene_save_name_text_input_callback(void* context) {
|
||||
furi_assert(context);
|
||||
SubGhz* subghz = context;
|
||||
view_dispatcher_send_custom_event(subghz->view_dispatcher, SubGhzCustomEventSceneSaveName);
|
||||
}
|
||||
|
||||
void subghz_scene_save_name_get_timefilename(
|
||||
FuriString* name,
|
||||
const char* proto_name,
|
||||
bool fulldate) {
|
||||
FuriHalRtcDateTime datetime = {0};
|
||||
furi_hal_rtc_get_datetime(&datetime);
|
||||
if(fulldate) {
|
||||
furi_string_printf(
|
||||
name,
|
||||
"%s_%.4d%.2d%.2d-%.2d%.2d%.2d",
|
||||
proto_name,
|
||||
datetime.year,
|
||||
datetime.month,
|
||||
datetime.day,
|
||||
datetime.hour,
|
||||
datetime.minute,
|
||||
datetime.second);
|
||||
} else {
|
||||
furi_string_printf(
|
||||
name,
|
||||
"%s_%.2d%.2d-%.2d%.2d%.2d",
|
||||
proto_name,
|
||||
datetime.month,
|
||||
datetime.day,
|
||||
datetime.hour,
|
||||
datetime.minute,
|
||||
datetime.second);
|
||||
}
|
||||
}
|
||||
|
||||
void subghz_scene_save_name_on_enter(void* context) {
|
||||
SubGhz* subghz = context;
|
||||
|
||||
@@ -54,35 +22,33 @@ void subghz_scene_save_name_on_enter(void* context) {
|
||||
FuriString* file_name = furi_string_alloc();
|
||||
FuriString* dir_name = furi_string_alloc();
|
||||
|
||||
char file_name_buf[SUBGHZ_MAX_LEN_NAME] = {0};
|
||||
FuriHalRtcDateTime* datetime = subghz->save_datetime_set ? &subghz->save_datetime : NULL;
|
||||
subghz->save_datetime_set = false;
|
||||
if(!subghz_path_is_file(subghz->file_path)) {
|
||||
char file_name_buf[SUBGHZ_MAX_LEN_NAME] = {0};
|
||||
if(subghz->last_settings->timestamp_file_names) {
|
||||
SubGhzProtocolDecoderBase* decoder_result = subghz_txrx_get_decoder(subghz->txrx);
|
||||
if(decoder_result != 0x0) {
|
||||
if(decoder_result != NULL) {
|
||||
if(strlen(decoder_result->protocol->name) != 0) {
|
||||
if(scene_manager_has_previous_scene(
|
||||
subghz->scene_manager, SubGhzSceneSetType)) {
|
||||
subghz_scene_save_name_get_timefilename(file_name, "S", true);
|
||||
} else {
|
||||
subghz_scene_save_name_get_timefilename(
|
||||
file_name, decoder_result->protocol->name, false);
|
||||
}
|
||||
SubGhzProtocolDecoderBase* decoder_result = subghz_txrx_get_decoder(subghz->txrx);
|
||||
|
||||
} else {
|
||||
subghz_scene_save_name_get_timefilename(file_name, "S", true);
|
||||
bool skip_dec_is_present = false;
|
||||
if(decoder_result != 0x0) {
|
||||
if(decoder_result != NULL) {
|
||||
if(strlen(decoder_result->protocol->name) != 0 &&
|
||||
subghz->last_settings->timestamp_file_names) {
|
||||
if(!scene_manager_has_previous_scene(
|
||||
subghz->scene_manager, SubGhzSceneSetType)) {
|
||||
name_generator_make_auto_datetime(
|
||||
file_name_buf,
|
||||
SUBGHZ_MAX_LEN_NAME,
|
||||
decoder_result->protocol->name,
|
||||
datetime);
|
||||
skip_dec_is_present = true;
|
||||
}
|
||||
} else {
|
||||
subghz_scene_save_name_get_timefilename(file_name, "S", true);
|
||||
}
|
||||
} else {
|
||||
subghz_scene_save_name_get_timefilename(file_name, "S", true);
|
||||
}
|
||||
} else {
|
||||
name_generator_make_auto(
|
||||
file_name_buf, SUBGHZ_MAX_LEN_NAME, SUBGHZ_APP_FILENAME_PREFIX);
|
||||
furi_string_set(file_name, file_name_buf);
|
||||
}
|
||||
if(!skip_dec_is_present) {
|
||||
name_generator_make_auto_datetime(file_name_buf, SUBGHZ_MAX_LEN_NAME, NULL, datetime);
|
||||
}
|
||||
furi_string_set(file_name, file_name_buf);
|
||||
furi_string_set(subghz->file_path, SUBGHZ_APP_FOLDER);
|
||||
//highlighting the entire filename by default
|
||||
dev_name_empty = true;
|
||||
@@ -96,7 +62,9 @@ void subghz_scene_save_name_on_enter(void* context) {
|
||||
if(scene_manager_get_scene_state(subghz->scene_manager, SubGhzSceneReadRAW) ==
|
||||
SubGhzCustomEventManagerSetRAW) {
|
||||
dev_name_empty = true;
|
||||
subghz_scene_save_name_get_timefilename(file_name, "RAW", true);
|
||||
name_generator_make_auto_datetime(
|
||||
file_name_buf, SUBGHZ_MAX_LEN_NAME, "RAW", datetime);
|
||||
furi_string_set(file_name, file_name_buf);
|
||||
}
|
||||
}
|
||||
furi_string_set(subghz->file_path, dir_name);
|
||||
@@ -109,7 +77,7 @@ void subghz_scene_save_name_on_enter(void* context) {
|
||||
subghz_scene_save_name_text_input_callback,
|
||||
subghz,
|
||||
subghz->file_name_tmp,
|
||||
MAX_TEXT_INPUT_LEN,
|
||||
SUBGHZ_MAX_LEN_NAME,
|
||||
dev_name_empty);
|
||||
|
||||
ValidatorIsFile* validator_is_file = validator_is_file_alloc_init(
|
||||
|
||||
@@ -24,5 +24,7 @@ bool subghz_scene_saved_on_event(void* context, SceneManagerEvent event) {
|
||||
}
|
||||
|
||||
void subghz_scene_saved_on_exit(void* context) {
|
||||
SubGhz* subghz = context;
|
||||
scene_manager_set_scene_state(subghz->scene_manager, SubGhzSceneSavedMenu, 0);
|
||||
UNUSED(context);
|
||||
}
|
||||
|
||||
@@ -139,6 +139,12 @@ void subghz_scene_set_type_on_enter(void* context) {
|
||||
SubmenuIndexIronLogic,
|
||||
subghz_scene_set_type_submenu_callback,
|
||||
subghz);
|
||||
submenu_add_item(
|
||||
subghz->submenu,
|
||||
"KL: DEA Mio 433MHz",
|
||||
SubmenuIndexDeaMio433,
|
||||
subghz_scene_set_type_submenu_callback,
|
||||
subghz);
|
||||
submenu_add_item(
|
||||
subghz->submenu,
|
||||
"KL: DTM Neo 433MHz",
|
||||
@@ -193,6 +199,12 @@ void subghz_scene_set_type_on_enter(void* context) {
|
||||
SubmenuIndexFAACRCXT_868,
|
||||
subghz_scene_set_type_submenu_callback,
|
||||
subghz);
|
||||
submenu_add_item(
|
||||
subghz->submenu,
|
||||
"KL: Genius Bravo 433MHz",
|
||||
SubmenuIndexGeniusBravo433,
|
||||
subghz_scene_set_type_submenu_callback,
|
||||
subghz);
|
||||
submenu_add_item(
|
||||
subghz->submenu,
|
||||
"KL: Nice Mhouse 433MHz",
|
||||
@@ -747,6 +759,30 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) {
|
||||
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowError);
|
||||
}
|
||||
break;
|
||||
case SubmenuIndexDeaMio433:
|
||||
generated_protocol = subghz_txrx_gen_keeloq_protocol(
|
||||
subghz->txrx,
|
||||
"AM650",
|
||||
433920000,
|
||||
(key & 0x0FFFF000) | 0x00000869,
|
||||
0x2,
|
||||
0x0003,
|
||||
"Dea_Mio");
|
||||
if(!generated_protocol) {
|
||||
furi_string_set(
|
||||
subghz->error_str, "Function requires\nan SD card with\nfresh databases.");
|
||||
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowError);
|
||||
}
|
||||
break;
|
||||
case SubmenuIndexGeniusBravo433:
|
||||
generated_protocol = subghz_txrx_gen_keeloq_protocol(
|
||||
subghz->txrx, "AM650", 433920000, key & 0x00FFFFFF, 0x6, 0x0003, "Genius_Bravo");
|
||||
if(!generated_protocol) {
|
||||
furi_string_set(
|
||||
subghz->error_str, "Function requires\nan SD card with\nfresh databases.");
|
||||
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowError);
|
||||
}
|
||||
break;
|
||||
case SubmenuIndexJCM_433_92:
|
||||
generated_protocol = subghz_txrx_gen_keeloq_protocol(
|
||||
subghz->txrx, "AM650", 433920000, key & 0x00FFFFFF, 0x2, 0x0003, "JCM_Tech");
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
#include <notification/notification_messages.h>
|
||||
#include <flipper_format/flipper_format_i.h>
|
||||
|
||||
#include <lib/subghz/blocks/custom_btn.h>
|
||||
|
||||
#define SUBGHZ_FREQUENCY_RANGE_STR \
|
||||
"299999755...348000000 or 386999938...464000000 or 778999847...928000000"
|
||||
|
||||
@@ -49,6 +51,26 @@ static void subghz_cli_radio_device_power_off() {
|
||||
if(furi_hal_power_is_otg_enabled()) furi_hal_power_disable_otg();
|
||||
}
|
||||
|
||||
static SubGhzEnvironment* subghz_cli_environment_init(void) {
|
||||
SubGhzEnvironment* environment = subghz_environment_alloc();
|
||||
if(subghz_environment_load_keystore(environment, SUBGHZ_KEYSTORE_DIR_NAME)) {
|
||||
printf("Load_keystore keeloq_mfcodes \033[0;32mOK\033[0m\r\n");
|
||||
} else {
|
||||
printf("Load_keystore keeloq_mfcodes \033[0;31mERROR\033[0m\r\n");
|
||||
}
|
||||
if(subghz_environment_load_keystore(environment, SUBGHZ_KEYSTORE_DIR_USER_NAME)) {
|
||||
printf("Load_keystore keeloq_mfcodes_user \033[0;32mOK\033[0m\r\n");
|
||||
} else {
|
||||
printf("Load_keystore keeloq_mfcodes_user \033[0;33mAbsent\033[0m\r\n");
|
||||
}
|
||||
subghz_environment_set_alutech_at_4n_rainbow_table_file_name(
|
||||
environment, SUBGHZ_ALUTECH_AT_4N_DIR_NAME);
|
||||
subghz_environment_set_nice_flor_s_rainbow_table_file_name(
|
||||
environment, SUBGHZ_NICE_FLOR_S_DIR_NAME);
|
||||
subghz_environment_set_protocol_registry(environment, (void*)&subghz_protocol_registry);
|
||||
return environment;
|
||||
}
|
||||
|
||||
void subghz_cli_command_tx_carrier(Cli* cli, FuriString* args, void* context) {
|
||||
UNUSED(context);
|
||||
uint32_t frequency = 433920000;
|
||||
@@ -323,14 +345,7 @@ void subghz_cli_command_rx(Cli* cli, FuriString* args, void* context) {
|
||||
furi_stream_buffer_alloc(sizeof(LevelDuration) * 1024, sizeof(LevelDuration));
|
||||
furi_check(instance->stream);
|
||||
|
||||
SubGhzEnvironment* environment = subghz_environment_alloc();
|
||||
subghz_environment_load_keystore(environment, SUBGHZ_KEYSTORE_DIR_NAME);
|
||||
subghz_environment_load_keystore(environment, SUBGHZ_KEYSTORE_DIR_USER_NAME);
|
||||
subghz_environment_set_alutech_at_4n_rainbow_table_file_name(
|
||||
environment, SUBGHZ_ALUTECH_AT_4N_DIR_NAME);
|
||||
subghz_environment_set_nice_flor_s_rainbow_table_file_name(
|
||||
environment, SUBGHZ_NICE_FLOR_S_DIR_NAME);
|
||||
subghz_environment_set_protocol_registry(environment, (void*)&subghz_protocol_registry);
|
||||
SubGhzEnvironment* environment = subghz_cli_environment_init();
|
||||
|
||||
SubGhzReceiver* receiver = subghz_receiver_alloc_init(environment);
|
||||
subghz_receiver_set_filter(receiver, SubGhzProtocolFlag_Decodable);
|
||||
@@ -512,23 +527,7 @@ void subghz_cli_command_decode_raw(Cli* cli, FuriString* args, void* context) {
|
||||
// Allocate context
|
||||
SubGhzCliCommandRx* instance = malloc(sizeof(SubGhzCliCommandRx));
|
||||
|
||||
SubGhzEnvironment* environment = subghz_environment_alloc();
|
||||
if(subghz_environment_load_keystore(environment, SUBGHZ_KEYSTORE_DIR_NAME)) {
|
||||
printf("SubGhz decode_raw: Load_keystore keeloq_mfcodes \033[0;32mOK\033[0m\r\n");
|
||||
} else {
|
||||
printf("SubGhz decode_raw: Load_keystore keeloq_mfcodes \033[0;31mERROR\033[0m\r\n");
|
||||
}
|
||||
if(subghz_environment_load_keystore(environment, SUBGHZ_KEYSTORE_DIR_USER_NAME)) {
|
||||
printf("SubGhz decode_raw: Load_keystore keeloq_mfcodes_user \033[0;32mOK\033[0m\r\n");
|
||||
} else {
|
||||
printf(
|
||||
"SubGhz decode_raw: Load_keystore keeloq_mfcodes_user \033[0;31mERROR\033[0m\r\n");
|
||||
}
|
||||
subghz_environment_set_alutech_at_4n_rainbow_table_file_name(
|
||||
environment, SUBGHZ_ALUTECH_AT_4N_DIR_NAME);
|
||||
subghz_environment_set_nice_flor_s_rainbow_table_file_name(
|
||||
environment, SUBGHZ_NICE_FLOR_S_DIR_NAME);
|
||||
subghz_environment_set_protocol_registry(environment, (void*)&subghz_protocol_registry);
|
||||
SubGhzEnvironment* environment = subghz_cli_environment_init();
|
||||
|
||||
SubGhzReceiver* receiver = subghz_receiver_alloc_init(environment);
|
||||
subghz_receiver_set_filter(receiver, SubGhzProtocolFlag_Decodable);
|
||||
@@ -573,6 +572,267 @@ void subghz_cli_command_decode_raw(Cli* cli, FuriString* args, void* context) {
|
||||
furi_string_free(file_name);
|
||||
}
|
||||
|
||||
static FuriHalSubGhzPreset subghz_cli_get_preset_name(const char* preset_name) {
|
||||
FuriHalSubGhzPreset preset = FuriHalSubGhzPresetIDLE;
|
||||
if(!strcmp(preset_name, "FuriHalSubGhzPresetOok270Async")) {
|
||||
preset = FuriHalSubGhzPresetOok270Async;
|
||||
} else if(!strcmp(preset_name, "FuriHalSubGhzPresetOok650Async")) {
|
||||
preset = FuriHalSubGhzPresetOok650Async;
|
||||
} else if(!strcmp(preset_name, "FuriHalSubGhzPreset2FSKDev238Async")) {
|
||||
preset = FuriHalSubGhzPreset2FSKDev238Async;
|
||||
} else if(!strcmp(preset_name, "FuriHalSubGhzPreset2FSKDev476Async")) {
|
||||
preset = FuriHalSubGhzPreset2FSKDev476Async;
|
||||
} else if(!strcmp(preset_name, "FuriHalSubGhzPresetCustom")) {
|
||||
preset = FuriHalSubGhzPresetCustom;
|
||||
} else {
|
||||
printf("subghz tx_from_file: unknown preset");
|
||||
}
|
||||
return preset;
|
||||
}
|
||||
|
||||
void subghz_cli_command_tx_from_file(Cli* cli, FuriString* args, void* context) { // -V524
|
||||
UNUSED(context);
|
||||
FuriString* file_name;
|
||||
file_name = furi_string_alloc();
|
||||
furi_string_set(file_name, ANY_PATH("subghz/test.sub"));
|
||||
uint32_t repeat = 10;
|
||||
uint32_t device_ind = 0; // 0 - CC1101_INT, 1 - CC1101_EXT
|
||||
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
FlipperFormat* fff_data_file = flipper_format_file_alloc(storage);
|
||||
FlipperFormat* fff_data_raw = flipper_format_string_alloc();
|
||||
FuriString* temp_str;
|
||||
temp_str = furi_string_alloc();
|
||||
uint32_t temp_data32;
|
||||
bool check_file = false;
|
||||
const SubGhzDevice* device = NULL;
|
||||
|
||||
uint32_t frequency = 0;
|
||||
SubGhzTransmitter* transmitter = NULL;
|
||||
|
||||
subghz_devices_init();
|
||||
|
||||
SubGhzEnvironment* environment = subghz_cli_environment_init();
|
||||
|
||||
do {
|
||||
if(furi_string_size(args)) {
|
||||
if(!args_read_string_and_trim(args, file_name)) {
|
||||
cli_print_usage(
|
||||
"subghz tx_from_file: ",
|
||||
"<file_name: path_file> <Repeat count> <Device: 0 - CC1101_INT, 1 - CC1101_EXT>",
|
||||
furi_string_get_cstr(args));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(furi_string_size(args)) {
|
||||
int ret = sscanf(furi_string_get_cstr(args), "%lu %lu", &repeat, &device_ind);
|
||||
if(ret != 2) {
|
||||
printf("sscanf returned %d, repeat: %lu device: %lu\r\n", ret, repeat, device_ind);
|
||||
cli_print_usage(
|
||||
"subghz tx_from_file:",
|
||||
"<file_name: path_file> <Repeat count> <Device: 0 - CC1101_INT, 1 - CC1101_EXT>",
|
||||
furi_string_get_cstr(args));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
device = subghz_cli_command_get_device(&device_ind);
|
||||
if(device == NULL) {
|
||||
printf("subghz tx_from_file: \033[0;31mError device not found\033[0m\r\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if(!flipper_format_file_open_existing(fff_data_file, furi_string_get_cstr(file_name))) {
|
||||
printf(
|
||||
"subghz tx_from_file: \033[0;31mError open file\033[0m %s\r\n",
|
||||
furi_string_get_cstr(file_name));
|
||||
break;
|
||||
}
|
||||
|
||||
if(!flipper_format_read_header(fff_data_file, temp_str, &temp_data32)) {
|
||||
printf("subghz tx_from_file: \033[0;31mMissing or incorrect header\033[0m\r\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if(((!strcmp(furi_string_get_cstr(temp_str), SUBGHZ_KEY_FILE_TYPE)) ||
|
||||
(!strcmp(furi_string_get_cstr(temp_str), SUBGHZ_RAW_FILE_TYPE))) &&
|
||||
temp_data32 == SUBGHZ_KEY_FILE_VERSION) {
|
||||
} else {
|
||||
printf("subghz tx_from_file: \033[0;31mType or version mismatch\033[0m\r\n");
|
||||
break;
|
||||
}
|
||||
|
||||
//Load frequency
|
||||
if(!flipper_format_read_uint32(fff_data_file, "Frequency", &frequency, 1)) {
|
||||
printf("subghz tx_from_file: \033[0;31mMissing Frequency\033[0m\r\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if(!subghz_devices_is_frequency_valid(device, frequency)) {
|
||||
printf("subghz tx_from_file: \033[0;31mFrequency not supported\033[0m\r\n");
|
||||
break;
|
||||
}
|
||||
|
||||
//Load preset
|
||||
if(!flipper_format_read_string(fff_data_file, "Preset", temp_str)) {
|
||||
printf("subghz tx_from_file: \033[0;31mMissing Preset\033[0m\r\n");
|
||||
break;
|
||||
}
|
||||
|
||||
subghz_devices_begin(device);
|
||||
subghz_devices_reset(device);
|
||||
|
||||
if(!strcmp(furi_string_get_cstr(temp_str), "FuriHalSubGhzPresetCustom")) {
|
||||
uint8_t* custom_preset_data;
|
||||
uint32_t custom_preset_data_size;
|
||||
if(!flipper_format_get_value_count(fff_data_file, "Custom_preset_data", &temp_data32))
|
||||
break;
|
||||
if(!temp_data32 || (temp_data32 % 2)) {
|
||||
printf("subghz tx_from_file: \033[0;31mCustom_preset_data size error\033[0m\r\n");
|
||||
break;
|
||||
}
|
||||
custom_preset_data_size = sizeof(uint8_t) * temp_data32;
|
||||
custom_preset_data = malloc(custom_preset_data_size);
|
||||
if(!flipper_format_read_hex(
|
||||
fff_data_file,
|
||||
"Custom_preset_data",
|
||||
custom_preset_data,
|
||||
custom_preset_data_size)) {
|
||||
printf("subghz tx_from_file: \033[0;31mCustom_preset_data read error\033[0m\r\n");
|
||||
break;
|
||||
}
|
||||
subghz_devices_load_preset(
|
||||
device,
|
||||
subghz_cli_get_preset_name(furi_string_get_cstr(temp_str)),
|
||||
custom_preset_data);
|
||||
free(custom_preset_data);
|
||||
} else {
|
||||
subghz_devices_load_preset(
|
||||
device, subghz_cli_get_preset_name(furi_string_get_cstr(temp_str)), NULL);
|
||||
}
|
||||
|
||||
subghz_devices_set_frequency(device, frequency);
|
||||
|
||||
//Load protocol
|
||||
if(!flipper_format_read_string(fff_data_file, "Protocol", temp_str)) {
|
||||
printf("subghz tx_from_file: \033[0;31mMissing protocol\033[0m\r\n");
|
||||
break;
|
||||
}
|
||||
|
||||
SubGhzProtocolStatus status;
|
||||
bool is_init_protocol = true;
|
||||
if(!strcmp(furi_string_get_cstr(temp_str), "RAW")) { // if RAW protocol
|
||||
subghz_protocol_raw_gen_fff_data(
|
||||
fff_data_raw, furi_string_get_cstr(file_name), subghz_devices_get_name(device));
|
||||
|
||||
transmitter =
|
||||
subghz_transmitter_alloc_init(environment, furi_string_get_cstr(temp_str));
|
||||
if(transmitter == NULL) {
|
||||
printf("subghz tx_from_file: \033[0;31mError transmitter\033[0m\r\n");
|
||||
is_init_protocol = false;
|
||||
}
|
||||
|
||||
if(is_init_protocol) {
|
||||
status = subghz_transmitter_deserialize(transmitter, fff_data_raw);
|
||||
if(status != SubGhzProtocolStatusOk) {
|
||||
printf(
|
||||
"subghz tx_from_file: \033[0;31mError deserialize protocol\033[0m %d\r\n",
|
||||
status);
|
||||
is_init_protocol = false;
|
||||
}
|
||||
}
|
||||
|
||||
} else { //if not RAW protocol
|
||||
flipper_format_insert_or_update_uint32(fff_data_file, "Repeat", &repeat, 1);
|
||||
|
||||
transmitter =
|
||||
subghz_transmitter_alloc_init(environment, furi_string_get_cstr(temp_str));
|
||||
if(transmitter == NULL) {
|
||||
printf("subghz tx_from_file: \033[0;31mError transmitter\033[0m\r\n");
|
||||
is_init_protocol = false;
|
||||
}
|
||||
if(is_init_protocol) {
|
||||
status = subghz_transmitter_deserialize(transmitter, fff_data_file);
|
||||
if(status != SubGhzProtocolStatusOk) {
|
||||
printf(
|
||||
"subghz tx_from_file: \033[0;31mError deserialize protocol\033[0m %d\r\n",
|
||||
status);
|
||||
is_init_protocol = false;
|
||||
}
|
||||
}
|
||||
|
||||
flipper_format_delete_key(fff_data_file, "Repeat");
|
||||
}
|
||||
|
||||
if(is_init_protocol) {
|
||||
check_file = true;
|
||||
} else {
|
||||
subghz_devices_sleep(device);
|
||||
subghz_devices_end(device);
|
||||
subghz_transmitter_free(transmitter);
|
||||
}
|
||||
|
||||
} while(false);
|
||||
|
||||
flipper_format_free(fff_data_file);
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
|
||||
if(check_file) {
|
||||
furi_hal_power_suppress_charge_enter();
|
||||
|
||||
printf(
|
||||
"Listening at \033[0;33m%s\033[0m. Frequency=%lu, Protocol=%s\r\n\r\nPress CTRL+C to stop\r\n\r\n",
|
||||
furi_string_get_cstr(file_name),
|
||||
frequency,
|
||||
furi_string_get_cstr(temp_str));
|
||||
do {
|
||||
//delay in downloading files and other preparatory processes
|
||||
furi_delay_ms(200);
|
||||
if(subghz_devices_start_async_tx(device, subghz_transmitter_yield, transmitter)) {
|
||||
while(
|
||||
!(subghz_devices_is_async_complete_tx(device) ||
|
||||
cli_cmd_interrupt_received(cli))) {
|
||||
printf(".");
|
||||
fflush(stdout);
|
||||
furi_delay_ms(333);
|
||||
}
|
||||
subghz_devices_stop_async_tx(device);
|
||||
|
||||
} else {
|
||||
printf("Transmission on this frequency is restricted in your settings\r\n");
|
||||
}
|
||||
|
||||
if(!strcmp(furi_string_get_cstr(temp_str), "RAW")) {
|
||||
subghz_transmitter_stop(transmitter);
|
||||
repeat--;
|
||||
if(!cli_cmd_interrupt_received(cli) && repeat)
|
||||
subghz_transmitter_deserialize(transmitter, fff_data_raw);
|
||||
}
|
||||
|
||||
} while(!cli_cmd_interrupt_received(cli) &&
|
||||
(repeat && !strcmp(furi_string_get_cstr(temp_str), "RAW")));
|
||||
|
||||
subghz_devices_sleep(device);
|
||||
subghz_devices_end(device);
|
||||
subghz_cli_radio_device_power_off();
|
||||
|
||||
furi_hal_power_suppress_charge_exit();
|
||||
|
||||
subghz_transmitter_free(transmitter);
|
||||
}
|
||||
flipper_format_free(fff_data_raw);
|
||||
furi_string_free(file_name);
|
||||
furi_string_free(temp_str);
|
||||
subghz_devices_deinit();
|
||||
// Reset custom settings
|
||||
subghz_environment_reset_keeloq(environment);
|
||||
faac_slh_reset_prog_mode();
|
||||
subghz_custom_btns_reset();
|
||||
// Free environment
|
||||
subghz_environment_free(environment);
|
||||
}
|
||||
|
||||
static void subghz_cli_command_print_usage() {
|
||||
printf("Usage:\r\n");
|
||||
printf("subghz <cmd> <args>\r\n");
|
||||
@@ -585,11 +845,13 @@ static void subghz_cli_command_print_usage() {
|
||||
printf("\trx <frequency:in Hz> <device: 0 - CC1101_INT, 1 - CC1101_EXT>\t - Receive\r\n");
|
||||
printf("\trx_raw <frequency:in Hz>\t - Receive RAW\r\n");
|
||||
printf("\tdecode_raw <file_name: path_RAW_file>\t - Testing\r\n");
|
||||
printf(
|
||||
"\ttx_from_file <file_name: path_file> <repeat: count> <device: 0 - CC1101_INT, 1 - CC1101_EXT>\t - Transmitting from file\r\n");
|
||||
|
||||
if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) {
|
||||
printf("\r\n");
|
||||
printf(" debug cmd:\r\n");
|
||||
printf("\ttx_carrier <frequency:in Hz>\t - Transmit carrier\r\n");
|
||||
printf("\ttx_carrier <frequency:in Hz>\t - Transmitting carrier\r\n");
|
||||
printf("\trx_carrier <frequency:in Hz>\t - Receive carrier\r\n");
|
||||
printf(
|
||||
"\tencrypt_keeloq <path_decrypted_file> <path_encrypted_file> <IV:16 bytes in hex>\t - Encrypt keeloq manufacture keys\r\n");
|
||||
@@ -901,6 +1163,11 @@ static void subghz_cli_command(Cli* cli, FuriString* args, void* context) {
|
||||
break;
|
||||
}
|
||||
|
||||
if(furi_string_cmp_str(cmd, "tx_from_file") == 0) {
|
||||
subghz_cli_command_tx_from_file(cli, args, context);
|
||||
break;
|
||||
}
|
||||
|
||||
if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) {
|
||||
if(furi_string_cmp_str(cmd, "encrypt_keeloq") == 0) {
|
||||
subghz_cli_command_encrypt_keeloq(cli, args);
|
||||
|
||||
@@ -131,6 +131,16 @@ const char* subghz_history_get_protocol_name(SubGhzHistory* instance, uint16_t i
|
||||
return furi_string_get_cstr(instance->tmp_string);
|
||||
}
|
||||
|
||||
FuriHalRtcDateTime subghz_history_get_datetime(SubGhzHistory* instance, uint16_t idx) {
|
||||
furi_assert(instance);
|
||||
SubGhzHistoryItem* item = SubGhzHistoryItemArray_get(instance->history->data, idx);
|
||||
if(item) {
|
||||
return item->datetime;
|
||||
} else {
|
||||
return (FuriHalRtcDateTime){};
|
||||
}
|
||||
}
|
||||
|
||||
FlipperFormat* subghz_history_get_raw_data(SubGhzHistory* instance, uint16_t idx) {
|
||||
furi_assert(instance);
|
||||
SubGhzHistoryItem* item = SubGhzHistoryItemArray_get(instance->history->data, idx);
|
||||
|
||||
@@ -70,6 +70,14 @@ uint8_t subghz_history_get_type_protocol(SubGhzHistory* instance, uint16_t idx);
|
||||
*/
|
||||
const char* subghz_history_get_protocol_name(SubGhzHistory* instance, uint16_t idx);
|
||||
|
||||
/** Get datetime from history[idx]
|
||||
*
|
||||
* @param instance - SubGhzHistory instance
|
||||
* @param idx - record index
|
||||
* @return datetime - FuriHalRtcDateTime received timestamp
|
||||
*/
|
||||
FuriHalRtcDateTime subghz_history_get_datetime(SubGhzHistory* instance, uint16_t idx);
|
||||
|
||||
/** Get string item menu to history[idx]
|
||||
*
|
||||
* @param instance - SubGhzHistory instance
|
||||
|
||||
@@ -79,6 +79,9 @@ struct SubGhz {
|
||||
SubGhzReadRAW* subghz_read_raw;
|
||||
bool raw_send_only;
|
||||
|
||||
bool save_datetime_set;
|
||||
FuriHalRtcDateTime save_datetime;
|
||||
|
||||
SubGhzLastSettings* last_settings;
|
||||
|
||||
SubGhzProtocolFlag filter;
|
||||
|
||||
@@ -8,8 +8,6 @@
|
||||
#include <furi_hal_usb_hid_u2f.h>
|
||||
#include <storage/storage.h>
|
||||
|
||||
#include <furi_hal_console.h>
|
||||
|
||||
#define TAG "U2fHid"
|
||||
#define WORKER_TAG TAG "Worker"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user