1
mirror of https://github.com/DarkFlippers/unleashed-firmware.git synced 2025-12-12 12:42:30 +04:00

Merge branch 'dev' into release

This commit is contained in:
MX
2023-07-25 05:35:30 +03:00
67 changed files with 1211 additions and 910 deletions

View File

@@ -1,14 +1,10 @@
## New changes ## New changes
* SubGHz: OFW PR: change the operation of the TIM17 timer in CC1101_ext to 2µs -> **CAME Atomo and other protocols issues with external module should be fixed now** * Plugins: **22+ plugins was fixed (UI update issues) in extra pack and in base firmware pack**
* SubGHz: Temporatily revert new AM_Q in default modulations due to external CC1101 module issues * Plugins: Spectrum Analyzer - Modulation switching (hold OK) (by @ALEEF02 | PR #557)
* Plugins: NRF24 MouseJacker -> Fixed issue #551 - Wrong folder path * Plugins: BadBT -> Temp fix for macOS
* Plugins: Spectrum Analyzer -> Add a Precise mode and other small changes (by @ALEEF02 | PR #550 #553) * Plugins: Update TOTP (Authenticator) [(by akopachov)](https://github.com/akopachov/flipper-zero_authenticator) -> + added fix for UI update too
* Plugins: Updated Lightmeter [(by oleksiikutuzov)](https://github.com/oleksiikutuzov/flipperzero-lightmeter) * Infrared: Add Play / Pause in universal projector remote
* Plugins: Various uFBT fixes (by @hedger) * Infrared: Update Universal remote assets (by @amec0e)
* Infrared: Universal remote assets - Add Xiaomi TV and (Daikin AC from OFW PR 2913 by minchogaydarov)
* OFW PR 2912: NFC: Fix key invalidation (again) (by AloneLiberty)
* OFW PR 2907: Fix about screen (by andzhr)
* OFW PR 2896: BadUSB - Added French Canadian layout (by francis2054)
---- ----

View File

@@ -27,11 +27,11 @@ const uint8_t BAD_BT_EMPTY_MAC_ADDRESS[BAD_BT_MAC_ADDRESS_LEN] =
* Delays for waiting between HID key press and key release * Delays for waiting between HID key press and key release
*/ */
const uint8_t bt_hid_delays[LevelRssiNum] = { const uint8_t bt_hid_delays[LevelRssiNum] = {
30, // LevelRssi122_100 60, // LevelRssi122_100
25, // LevelRssi99_80 55, // LevelRssi99_80
20, // LevelRssi79_60 50, // LevelRssi79_60
17, // LevelRssi59_40 47, // LevelRssi59_40
14, // LevelRssi39_0 34, // LevelRssi39_0
}; };
uint8_t bt_timeout = 0; uint8_t bt_timeout = 0;

View File

@@ -73,143 +73,145 @@ int32_t i2ctools_app(void* p) {
// Share scanner with sender // Share scanner with sender
i2ctools->sender->scanner = i2ctools->scanner; i2ctools->sender->scanner = i2ctools->scanner;
while(furi_message_queue_get(event_queue, &event, FuriWaitForever) == FuriStatusOk) { while(1) {
// Back if(furi_message_queue_get(event_queue, &event, 100) == FuriStatusOk) {
if(event.key == InputKeyBack && event.type == InputTypeRelease) { // Back
if(i2ctools->main_view->current_view == MAIN_VIEW) { if(event.key == InputKeyBack && event.type == InputTypeRelease) {
break; if(i2ctools->main_view->current_view == MAIN_VIEW) {
} else { break;
if(i2ctools->main_view->current_view == SNIFF_VIEW) {
stop_interrupts();
i2ctools->sniffer->started = false;
i2ctools->sniffer->state = I2C_BUS_FREE;
}
i2ctools->main_view->current_view = MAIN_VIEW;
}
}
// Up
else if(event.key == InputKeyUp && event.type == InputTypeRelease) {
if(i2ctools->main_view->current_view == MAIN_VIEW) {
if((i2ctools->main_view->menu_index > SCAN_VIEW)) {
i2ctools->main_view->menu_index--;
}
} else if(i2ctools->main_view->current_view == SCAN_VIEW) {
if(i2ctools->scanner->menu_index > 0) {
i2ctools->scanner->menu_index--;
}
} else if(i2ctools->main_view->current_view == SNIFF_VIEW) {
if(i2ctools->sniffer->row_index > 0) {
i2ctools->sniffer->row_index--;
}
} else if(i2ctools->main_view->current_view == SEND_VIEW) {
if(i2ctools->sender->value < 0xFF) {
i2ctools->sender->value++;
i2ctools->sender->sended = false;
}
}
}
// Long Up
else if(
event.key == InputKeyUp &&
(event.type == InputTypeLong || event.type == InputTypeRepeat)) {
if(i2ctools->main_view->current_view == SCAN_VIEW) {
if(i2ctools->scanner->menu_index > 5) {
i2ctools->scanner->menu_index -= 5;
}
} else if(i2ctools->main_view->current_view == SEND_VIEW) {
if(i2ctools->sender->value < 0xF9) {
i2ctools->sender->value += 5;
i2ctools->sender->sended = false;
}
} else if(i2ctools->main_view->current_view == SNIFF_VIEW) {
if(i2ctools->sniffer->row_index > 5) {
i2ctools->sniffer->row_index -= 5;
} else { } else {
i2ctools->sniffer->row_index = 0; if(i2ctools->main_view->current_view == SNIFF_VIEW) {
stop_interrupts();
i2ctools->sniffer->started = false;
i2ctools->sniffer->state = I2C_BUS_FREE;
}
i2ctools->main_view->current_view = MAIN_VIEW;
} }
} }
} // Up
// Down else if(event.key == InputKeyUp && event.type == InputTypeRelease) {
else if(event.key == InputKeyDown && event.type == InputTypeRelease) { if(i2ctools->main_view->current_view == MAIN_VIEW) {
if(i2ctools->main_view->current_view == MAIN_VIEW) { if((i2ctools->main_view->menu_index > SCAN_VIEW)) {
if(i2ctools->main_view->menu_index < MENU_SIZE - 1) { i2ctools->main_view->menu_index--;
i2ctools->main_view->menu_index++; }
} } else if(i2ctools->main_view->current_view == SCAN_VIEW) {
} else if(i2ctools->main_view->current_view == SCAN_VIEW) { if(i2ctools->scanner->menu_index > 0) {
if(i2ctools->scanner->menu_index < ((int)i2ctools->scanner->nb_found / 3)) { i2ctools->scanner->menu_index--;
i2ctools->scanner->menu_index++; }
} } else if(i2ctools->main_view->current_view == SNIFF_VIEW) {
} else if(i2ctools->main_view->current_view == SNIFF_VIEW) { if(i2ctools->sniffer->row_index > 0) {
if((i2ctools->sniffer->row_index + 3) < i2ctools->sniffer->row_index--;
(int)i2ctools->sniffer->frames[i2ctools->sniffer->menu_index].data_index) { }
i2ctools->sniffer->row_index++; } else if(i2ctools->main_view->current_view == SEND_VIEW) {
} if(i2ctools->sender->value < 0xFF) {
} else if(i2ctools->main_view->current_view == SEND_VIEW) { i2ctools->sender->value++;
if(i2ctools->sender->value > 0x00) { i2ctools->sender->sended = false;
i2ctools->sender->value--; }
i2ctools->sender->sended = false;
} }
} }
} // Long Up
// Long Down else if(
else if( event.key == InputKeyUp &&
event.key == InputKeyDown && (event.type == InputTypeLong || event.type == InputTypeRepeat)) {
(event.type == InputTypeLong || event.type == InputTypeRepeat)) { if(i2ctools->main_view->current_view == SCAN_VIEW) {
if(i2ctools->main_view->current_view == SEND_VIEW) { if(i2ctools->scanner->menu_index > 5) {
if(i2ctools->sender->value > 0x05) { i2ctools->scanner->menu_index -= 5;
i2ctools->sender->value -= 5; }
i2ctools->sender->sended = false; } else if(i2ctools->main_view->current_view == SEND_VIEW) {
} else { if(i2ctools->sender->value < 0xF9) {
i2ctools->sender->value = 0; i2ctools->sender->value += 5;
i2ctools->sender->sended = false; i2ctools->sender->sended = false;
} }
} else if(i2ctools->main_view->current_view == SNIFF_VIEW) { } else if(i2ctools->main_view->current_view == SNIFF_VIEW) {
if((i2ctools->sniffer->row_index + 8) < if(i2ctools->sniffer->row_index > 5) {
(int)i2ctools->sniffer->frames[i2ctools->sniffer->menu_index].data_index) { i2ctools->sniffer->row_index -= 5;
i2ctools->sniffer->row_index += 5; } else {
i2ctools->sniffer->row_index = 0;
}
} }
} }
// Down
else if(event.key == InputKeyDown && event.type == InputTypeRelease) {
if(i2ctools->main_view->current_view == MAIN_VIEW) {
if(i2ctools->main_view->menu_index < MENU_SIZE - 1) {
i2ctools->main_view->menu_index++;
}
} else if(i2ctools->main_view->current_view == SCAN_VIEW) {
if(i2ctools->scanner->menu_index < ((int)i2ctools->scanner->nb_found / 3)) {
i2ctools->scanner->menu_index++;
}
} else if(i2ctools->main_view->current_view == SNIFF_VIEW) {
if((i2ctools->sniffer->row_index + 3) <
(int)i2ctools->sniffer->frames[i2ctools->sniffer->menu_index].data_index) {
i2ctools->sniffer->row_index++;
}
} else if(i2ctools->main_view->current_view == SEND_VIEW) {
if(i2ctools->sender->value > 0x00) {
i2ctools->sender->value--;
i2ctools->sender->sended = false;
}
}
}
// Long Down
else if(
event.key == InputKeyDown &&
(event.type == InputTypeLong || event.type == InputTypeRepeat)) {
if(i2ctools->main_view->current_view == SEND_VIEW) {
if(i2ctools->sender->value > 0x05) {
i2ctools->sender->value -= 5;
i2ctools->sender->sended = false;
} else {
i2ctools->sender->value = 0;
i2ctools->sender->sended = false;
}
} else if(i2ctools->main_view->current_view == SNIFF_VIEW) {
if((i2ctools->sniffer->row_index + 8) <
(int)i2ctools->sniffer->frames[i2ctools->sniffer->menu_index].data_index) {
i2ctools->sniffer->row_index += 5;
}
}
} else if(event.key == InputKeyOk && event.type == InputTypeRelease) { } else if(event.key == InputKeyOk && event.type == InputTypeRelease) {
if(i2ctools->main_view->current_view == MAIN_VIEW) { if(i2ctools->main_view->current_view == MAIN_VIEW) {
i2ctools->main_view->current_view = i2ctools->main_view->menu_index; i2ctools->main_view->current_view = i2ctools->main_view->menu_index;
} else if(i2ctools->main_view->current_view == SCAN_VIEW) { } else if(i2ctools->main_view->current_view == SCAN_VIEW) {
scan_i2c_bus(i2ctools->scanner); scan_i2c_bus(i2ctools->scanner);
} else if(i2ctools->main_view->current_view == SEND_VIEW) { } else if(i2ctools->main_view->current_view == SEND_VIEW) {
i2ctools->sender->must_send = true; i2ctools->sender->must_send = true;
} else if(i2ctools->main_view->current_view == SNIFF_VIEW) { } else if(i2ctools->main_view->current_view == SNIFF_VIEW) {
if(i2ctools->sniffer->started) { if(i2ctools->sniffer->started) {
stop_interrupts(); stop_interrupts();
i2ctools->sniffer->started = false; i2ctools->sniffer->started = false;
i2ctools->sniffer->state = I2C_BUS_FREE; i2ctools->sniffer->state = I2C_BUS_FREE;
} else { } else {
start_interrupts(i2ctools->sniffer); start_interrupts(i2ctools->sniffer);
i2ctools->sniffer->started = true; i2ctools->sniffer->started = true;
i2ctools->sniffer->state = I2C_BUS_FREE; i2ctools->sniffer->state = I2C_BUS_FREE;
}
} }
} } else if(event.key == InputKeyRight && event.type == InputTypeRelease) {
} else if(event.key == InputKeyRight && event.type == InputTypeRelease) { if(i2ctools->main_view->current_view == SEND_VIEW) {
if(i2ctools->main_view->current_view == SEND_VIEW) { if(i2ctools->sender->address_idx < (i2ctools->scanner->nb_found - 1)) {
if(i2ctools->sender->address_idx < (i2ctools->scanner->nb_found - 1)) { i2ctools->sender->address_idx++;
i2ctools->sender->address_idx++; i2ctools->sender->sended = false;
i2ctools->sender->sended = false; }
} else if(i2ctools->main_view->current_view == SNIFF_VIEW) {
if(i2ctools->sniffer->menu_index < i2ctools->sniffer->frame_index) {
i2ctools->sniffer->menu_index++;
i2ctools->sniffer->row_index = 0;
}
} }
} else if(i2ctools->main_view->current_view == SNIFF_VIEW) { } else if(event.key == InputKeyLeft && event.type == InputTypeRelease) {
if(i2ctools->sniffer->menu_index < i2ctools->sniffer->frame_index) { if(i2ctools->main_view->current_view == SEND_VIEW) {
i2ctools->sniffer->menu_index++; if(i2ctools->sender->address_idx > 0) {
i2ctools->sniffer->row_index = 0; i2ctools->sender->address_idx--;
} i2ctools->sender->sended = false;
} }
} else if(event.key == InputKeyLeft && event.type == InputTypeRelease) { } else if(i2ctools->main_view->current_view == SNIFF_VIEW) {
if(i2ctools->main_view->current_view == SEND_VIEW) { if(i2ctools->sniffer->menu_index > 0) {
if(i2ctools->sender->address_idx > 0) { i2ctools->sniffer->menu_index--;
i2ctools->sender->address_idx--; i2ctools->sniffer->row_index = 0;
i2ctools->sender->sended = false; }
}
} else if(i2ctools->main_view->current_view == SNIFF_VIEW) {
if(i2ctools->sniffer->menu_index > 0) {
i2ctools->sniffer->menu_index--;
i2ctools->sniffer->row_index = 0;
} }
} }
} }

View File

@@ -229,53 +229,58 @@ int32_t hex_viewer_app(void* p) {
hex_viewer_read_file(hex_viewer); hex_viewer_read_file(hex_viewer);
InputEvent input; InputEvent input;
while(furi_message_queue_get(hex_viewer->input_queue, &input, FuriWaitForever) == while(1) {
FuriStatusOk) { if(furi_message_queue_get(hex_viewer->input_queue, &input, 100) == FuriStatusOk) {
if(input.key == InputKeyBack) { if(input.key == InputKeyBack) {
break; break;
} else if(input.key == InputKeyUp) { } else if(input.key == InputKeyUp) {
furi_check(furi_mutex_acquire(hex_viewer->mutex, FuriWaitForever) == FuriStatusOk); furi_check(
if(hex_viewer->model->file_offset > 0) { furi_mutex_acquire(hex_viewer->mutex, FuriWaitForever) == FuriStatusOk);
hex_viewer->model->file_offset -= HEX_VIEWER_BYTES_PER_LINE; if(hex_viewer->model->file_offset > 0) {
if(!hex_viewer_read_file(hex_viewer)) break; hex_viewer->model->file_offset -= HEX_VIEWER_BYTES_PER_LINE;
if(!hex_viewer_read_file(hex_viewer)) break;
}
furi_mutex_release(hex_viewer->mutex);
} else if(input.key == InputKeyDown) {
furi_check(
furi_mutex_acquire(hex_viewer->mutex, FuriWaitForever) == FuriStatusOk);
uint32_t last_byte_on_screen =
hex_viewer->model->file_offset + hex_viewer->model->file_read_bytes;
if(hex_viewer->model->file_size > last_byte_on_screen) {
hex_viewer->model->file_offset += HEX_VIEWER_BYTES_PER_LINE;
if(!hex_viewer_read_file(hex_viewer)) break;
}
furi_mutex_release(hex_viewer->mutex);
} else if(input.key == InputKeyLeft) {
furi_check(
furi_mutex_acquire(hex_viewer->mutex, FuriWaitForever) == FuriStatusOk);
hex_viewer->model->mode = !hex_viewer->model->mode;
furi_mutex_release(hex_viewer->mutex);
} else if(input.key == InputKeyRight) {
FuriString* buffer;
buffer = furi_string_alloc();
furi_string_printf(
buffer,
"File path: %s\nFile size: %lu (0x%lX)",
furi_string_get_cstr(file_path),
hex_viewer->model->file_size,
hex_viewer->model->file_size);
DialogsApp* dialogs = furi_record_open(RECORD_DIALOGS);
DialogMessage* message = dialog_message_alloc();
dialog_message_set_header(
message, "Hex Viewer v1.1", 16, 2, AlignLeft, AlignTop);
dialog_message_set_icon(message, &I_hex_10px, 3, 2);
dialog_message_set_text(
message, furi_string_get_cstr(buffer), 3, 16, AlignLeft, AlignTop);
dialog_message_set_buttons(message, NULL, NULL, "Back");
dialog_message_show(dialogs, message);
furi_string_free(buffer);
dialog_message_free(message);
furi_record_close(RECORD_DIALOGS);
} }
furi_mutex_release(hex_viewer->mutex);
} else if(input.key == InputKeyDown) {
furi_check(furi_mutex_acquire(hex_viewer->mutex, FuriWaitForever) == FuriStatusOk);
uint32_t last_byte_on_screen =
hex_viewer->model->file_offset + hex_viewer->model->file_read_bytes;
if(hex_viewer->model->file_size > last_byte_on_screen) {
hex_viewer->model->file_offset += HEX_VIEWER_BYTES_PER_LINE;
if(!hex_viewer_read_file(hex_viewer)) break;
}
furi_mutex_release(hex_viewer->mutex);
} else if(input.key == InputKeyLeft) {
furi_check(furi_mutex_acquire(hex_viewer->mutex, FuriWaitForever) == FuriStatusOk);
hex_viewer->model->mode = !hex_viewer->model->mode;
furi_mutex_release(hex_viewer->mutex);
} else if(input.key == InputKeyRight) {
FuriString* buffer;
buffer = furi_string_alloc();
furi_string_printf(
buffer,
"File path: %s\nFile size: %lu (0x%lX)",
furi_string_get_cstr(file_path),
hex_viewer->model->file_size,
hex_viewer->model->file_size);
DialogsApp* dialogs = furi_record_open(RECORD_DIALOGS);
DialogMessage* message = dialog_message_alloc();
dialog_message_set_header(message, "Hex Viewer v1.1", 16, 2, AlignLeft, AlignTop);
dialog_message_set_icon(message, &I_hex_10px, 3, 2);
dialog_message_set_text(
message, furi_string_get_cstr(buffer), 3, 16, AlignLeft, AlignTop);
dialog_message_set_buttons(message, NULL, NULL, "Back");
dialog_message_show(dialogs, message);
furi_string_free(buffer);
dialog_message_free(message);
furi_record_close(RECORD_DIALOGS);
} }
view_port_update(hex_viewer->view_port); view_port_update(hex_viewer->view_port);

View File

@@ -140,30 +140,31 @@ int32_t ir_scope_app(void* p) {
InputEvent event; InputEvent event;
bool processing = true; bool processing = true;
while(processing && while(processing) {
furi_message_queue_get(event_queue, &event, FuriWaitForever) == FuriStatusOk) { if(furi_message_queue_get(event_queue, &event, 100) == FuriStatusOk) {
if(event.type == InputTypeRelease) { if(event.type == InputTypeRelease) {
furi_mutex_acquire(state.mutex, FuriWaitForever); furi_mutex_acquire(state.mutex, FuriWaitForever);
if(event.key == InputKeyBack) { if(event.key == InputKeyBack) {
processing = false; processing = false;
} else if(event.key == InputKeyUp) { } else if(event.key == InputKeyUp) {
state.us_per_sample = MIN(1000, state.us_per_sample + 25); state.us_per_sample = MIN(1000, state.us_per_sample + 25);
state.autoscale = false; state.autoscale = false;
} else if(event.key == InputKeyDown) { } else if(event.key == InputKeyDown) {
state.us_per_sample = MAX(25, state.us_per_sample - 25); state.us_per_sample = MAX(25, state.us_per_sample - 25);
state.autoscale = false; state.autoscale = false;
} else if(event.key == InputKeyOk) { } else if(event.key == InputKeyOk) {
state.autoscale = !state.autoscale; state.autoscale = !state.autoscale;
if(state.autoscale) if(state.autoscale)
state_set_autoscale(&state); state_set_autoscale(&state);
else else
state.us_per_sample = 200; state.us_per_sample = 200;
}
furi_mutex_release(state.mutex);
} }
view_port_update(view_port);
furi_mutex_release(state.mutex);
} }
view_port_update(view_port);
} }
// Clean up. // Clean up.

View File

@@ -497,7 +497,6 @@ int32_t solitaire_app(void* p) {
for(bool processing = true; processing;) { for(bool processing = true; processing;) {
FuriStatus event_status = furi_message_queue_get(event_queue, &event, 150); FuriStatus event_status = furi_message_queue_get(event_queue, &event, 150);
furi_mutex_acquire(game_state->mutex, FuriWaitForever); furi_mutex_acquire(game_state->mutex, FuriWaitForever);
bool hadChange = false;
if(event_status == FuriStatusOk) { if(event_status == FuriStatusOk) {
if(event.type == EventTypeKey) { if(event.type == EventTypeKey) {
if(event.input.type == InputTypeLong) { if(event.input.type == InputTypeLong) {
@@ -528,7 +527,6 @@ int32_t solitaire_app(void* p) {
game_state->state = GameStatePlay; game_state->state = GameStatePlay;
init(game_state); init(game_state);
} else { } else {
hadChange = true;
game_state->input = event.input.key; game_state->input = event.input.key;
} }
break; break;
@@ -546,11 +544,8 @@ int32_t solitaire_app(void* p) {
processing = game_state->processing; processing = game_state->processing;
game_state->input = InputKeyMAX; game_state->input = InputKeyMAX;
} }
} else {
//FURI_LOG_W(APP_NAME, "osMessageQueue: event timeout");
// event timeout
} }
if(hadChange || game_state->state == GameStateAnimate) view_port_update(view_port); view_port_update(view_port);
furi_mutex_release(game_state->mutex); furi_mutex_release(game_state->mutex);
} }

View File

@@ -12,6 +12,7 @@
typedef struct { typedef struct {
uint32_t center_freq; uint32_t center_freq;
uint8_t width; uint8_t width;
uint8_t modulation;
uint8_t band; uint8_t band;
uint8_t vscroll; uint8_t vscroll;
@@ -19,6 +20,7 @@ typedef struct {
uint32_t spacing; uint32_t spacing;
bool mode_change; bool mode_change;
bool modulation_change;
float max_rssi; float max_rssi;
uint8_t max_rssi_dec; uint8_t max_rssi_dec;
@@ -147,6 +149,24 @@ static void spectrum_analyzer_render_callback(Canvas* const canvas, void* ctx) {
snprintf(tmp_str, 21, "Mode: %s", temp_mode_str); snprintf(tmp_str, 21, "Mode: %s", temp_mode_str);
canvas_draw_str_aligned(canvas, 127, 4, AlignRight, AlignTop, tmp_str); canvas_draw_str_aligned(canvas, 127, 4, AlignRight, AlignTop, tmp_str);
} }
if(model->modulation_change) {
char temp_mod_str[12];
switch(model->modulation) {
case NARROW_MODULATION:
strncpy(temp_mod_str, "NARROW", 12);
break;
default:
strncpy(temp_mod_str, "DEFAULT", 12);
break;
}
// Current modulation label
char tmp_str[27];
snprintf(tmp_str, 27, "Modulation: %s", temp_mod_str);
canvas_draw_str_aligned(canvas, 127, 4, AlignRight, AlignTop, tmp_str);
}
// Draw cross and label // Draw cross and label
if(model->max_rssi > PEAK_THRESHOLD) { if(model->max_rssi > PEAK_THRESHOLD) {
// Compress height to max of 64 values (255>>2) // Compress height to max of 64 values (255>>2)
@@ -194,8 +214,8 @@ static void spectrum_analyzer_render_callback(Canvas* const canvas, void* ctx) {
static void spectrum_analyzer_input_callback(InputEvent* input_event, void* ctx) { static void spectrum_analyzer_input_callback(InputEvent* input_event, void* ctx) {
SpectrumAnalyzer* spectrum_analyzer = ctx; SpectrumAnalyzer* spectrum_analyzer = ctx;
// Only handle short presses // Handle short and long presses
if(input_event->type == InputTypeShort) { if(input_event->type == InputTypeShort || input_event->type == InputTypeLong) {
furi_message_queue_put(spectrum_analyzer->event_queue, input_event, FuriWaitForever); furi_message_queue_put(spectrum_analyzer->event_queue, input_event, FuriWaitForever);
} }
} }
@@ -376,6 +396,7 @@ SpectrumAnalyzer* spectrum_analyzer_alloc() {
model->center_freq = DEFAULT_FREQ; model->center_freq = DEFAULT_FREQ;
model->width = WIDE; model->width = WIDE;
model->modulation = DEFAULT_MODULATION;
model->band = BAND_400; model->band = BAND_400;
model->vscroll = DEFAULT_VSCROLL; model->vscroll = DEFAULT_VSCROLL;
@@ -470,65 +491,106 @@ int32_t spectrum_analyzer_app(void* p) {
break; break;
} }
switch(input.key) { switch(input.type) {
case InputKeyUp: case InputTypeShort:
model->vscroll = MAX(model->vscroll - vstep, MIN_VSCROLL); switch(input.key) {
FURI_LOG_D("Spectrum", "Vscroll: %u", model->vscroll); case InputKeyUp:
break; model->vscroll = MAX(model->vscroll - vstep, MIN_VSCROLL);
case InputKeyDown: FURI_LOG_D("Spectrum", "Vscroll: %u", model->vscroll);
model->vscroll = MIN(model->vscroll + vstep, MAX_VSCROLL);
FURI_LOG_D("Spectrum", "Vscroll: %u", model->vscroll);
break;
case InputKeyRight:
model->center_freq += hstep;
FURI_LOG_D("Spectrum", "center_freq: %lu", model->center_freq);
spectrum_analyzer_calculate_frequencies(model);
spectrum_analyzer_worker_set_frequencies(
spectrum_analyzer->worker, model->channel0_frequency, model->spacing, model->width);
break;
case InputKeyLeft:
model->center_freq -= hstep;
spectrum_analyzer_calculate_frequencies(model);
spectrum_analyzer_worker_set_frequencies(
spectrum_analyzer->worker, model->channel0_frequency, model->spacing, model->width);
FURI_LOG_D("Spectrum", "center_freq: %lu", model->center_freq);
break;
case InputKeyOk: {
switch(model->width) {
case WIDE:
model->width = NARROW;
break; break;
case NARROW: case InputKeyDown:
model->width = ULTRANARROW; model->vscroll = MIN(model->vscroll + vstep, MAX_VSCROLL);
FURI_LOG_D("Spectrum", "Vscroll: %u", model->vscroll);
break; break;
case ULTRANARROW: case InputKeyRight:
model->width = PRECISE; model->center_freq += hstep;
FURI_LOG_D("Spectrum", "center_freq: %lu", model->center_freq);
spectrum_analyzer_calculate_frequencies(model);
spectrum_analyzer_worker_set_frequencies(
spectrum_analyzer->worker,
model->channel0_frequency,
model->spacing,
model->width);
break; break;
case PRECISE: case InputKeyLeft:
model->width = ULTRAWIDE; model->center_freq -= hstep;
spectrum_analyzer_calculate_frequencies(model);
spectrum_analyzer_worker_set_frequencies(
spectrum_analyzer->worker,
model->channel0_frequency,
model->spacing,
model->width);
FURI_LOG_D("Spectrum", "center_freq: %lu", model->center_freq);
break; break;
case ULTRAWIDE: case InputKeyOk: {
model->width = WIDE; switch(model->width) {
case WIDE:
model->width = NARROW;
break;
case NARROW:
model->width = ULTRANARROW;
break;
case ULTRANARROW:
model->width = PRECISE;
break;
case PRECISE:
model->width = ULTRAWIDE;
break;
case ULTRAWIDE:
model->width = WIDE;
break;
default:
model->width = WIDE;
break;
}
}
model->mode_change = true;
view_port_update(spectrum_analyzer->view_port);
furi_delay_ms(1000);
model->mode_change = false;
spectrum_analyzer_calculate_frequencies(model);
spectrum_analyzer_worker_set_frequencies(
spectrum_analyzer->worker,
model->channel0_frequency,
model->spacing,
model->width);
FURI_LOG_D("Spectrum", "Width: %u", model->width);
break;
case InputKeyBack:
exit_loop = true;
break; break;
default: default:
model->width = WIDE;
break; break;
} }
}
model->mode_change = true;
view_port_update(spectrum_analyzer->view_port);
furi_delay_ms(1000);
model->mode_change = false;
spectrum_analyzer_calculate_frequencies(model);
spectrum_analyzer_worker_set_frequencies(
spectrum_analyzer->worker, model->channel0_frequency, model->spacing, model->width);
FURI_LOG_D("Spectrum", "Width: %u", model->width);
break; break;
case InputKeyBack: case InputTypeLong:
exit_loop = true; switch(input.key) {
case InputKeyOk:
FURI_LOG_D("Spectrum", "InputTypeLong");
switch(model->modulation) {
case NARROW_MODULATION:
model->modulation = DEFAULT_MODULATION;
break;
case DEFAULT_MODULATION:
default:
model->modulation = NARROW_MODULATION;
break;
}
model->modulation_change = true;
view_port_update(spectrum_analyzer->view_port);
furi_delay_ms(1000);
model->modulation_change = false;
spectrum_analyzer_worker_set_modulation(
spectrum_analyzer->worker, spectrum_analyzer->model->modulation);
break;
default:
break;
}
break; break;
default: default:
break; break;

View File

@@ -77,4 +77,8 @@
#define MID_900 848000000 #define MID_900 848000000
#define UPPER(a, b, c) ((((a) - (b) + ((c) / 2)) / (c)) * (c)) #define UPPER(a, b, c) ((((a) - (b) + ((c) / 2)) / (c)) * (c))
#define LOWER(a, b, c) ((((a) + (b)) / (c)) * (c)) #define LOWER(a, b, c) ((((a) + (b)) / (c)) * (c))
/* Modulation references */
#define DEFAULT_MODULATION 0
#define NARROW_MODULATION 1

View File

@@ -20,6 +20,7 @@ struct SpectrumAnalyzerWorker {
uint32_t channel0_frequency; uint32_t channel0_frequency;
uint32_t spacing; uint32_t spacing;
uint8_t width; uint8_t width;
uint8_t modulation;
float max_rssi; float max_rssi;
uint8_t max_rssi_dec; uint8_t max_rssi_dec;
uint8_t max_rssi_channel; uint8_t max_rssi_channel;
@@ -66,18 +67,45 @@ static int32_t spectrum_analyzer_worker_thread(void* context) {
subghz_devices_flush_rx(instance->radio_device); subghz_devices_flush_rx(instance->radio_device);
subghz_devices_set_rx(instance->radio_device); subghz_devices_set_rx(instance->radio_device);
const uint8_t radio_config[] = { // Default modulation
const uint8_t default_modulation[] = {
/* Frequency Synthesizer Control */
CC1101_FSCTRL0, CC1101_FSCTRL0,
0x00, 0x00,
CC1101_FSCTRL1, CC1101_FSCTRL1,
0x12, 0x12, // IF = (26*10^6) / (2^10) * 0x12 = 304687.5 Hz
CC1101_AGCCTRL2,
0xC0,
// Modem Configuration
// CC1101_MDMCFG0,
// 0x00, // Channel spacing is 25kHz
// CC1101_MDMCFG1,
// 0x00, // Channel spacing is 25kHz
// CC1101_MDMCFG2,
// 0x30, // Format ASK/OOK, No preamble/sync
// CC1101_MDMCFG3,
// 0x32, // Data rate is 121.399 kBaud
CC1101_MDMCFG4, CC1101_MDMCFG4,
0x6C, 0x6C, // Rx BW filter is 270.83 kHz
/* Frequency Offset Compensation Configuration */
// CC1101_FOCCFG,
// 0x18, // no frequency offset compensation, POST_K same as PRE_K, PRE_K is 4K, GATE is off
/* Automatic Gain Control */
// CC1101_AGCCTRL0,
// 0x91, // 10 - Medium hysteresis, medium asymmetric dead zone, medium gain ; 01 - 16 samples agc; 00 - Normal AGC, 01 - 8dB boundary
// CC1101_AGCCTRL1,
// 0x0, // 0; 0 - LNA 2 gain is decreased to minimum before decreasing LNA gain; 00 - Relative carrier sense threshold disabled; 0000 - RSSI to MAIN_TARGET
CC1101_AGCCTRL2,
0xC0, // 03 - The 3 highest DVGA gain settings can not be used; 000 - MAX LNA+LNA2; 000 - MAIN_TARGET 24 dB
/* Frontend configuration */
// CC1101_FREND0,
// 0x11, // Adjusts current TX LO buffer + high is PATABLE[1]
// CC1101_FREND1,
// 0xB6, //
CC1101_TEST2, CC1101_TEST2,
0x88, 0x88,
CC1101_TEST1, CC1101_TEST1,
@@ -97,8 +125,69 @@ static int32_t spectrum_analyzer_worker_thread(void* context) {
0x00, 0x00,
0x00, 0x00,
0x00, 0x00,
0x00};
// Narrow modulation
const uint8_t narrow_modulation[] = {
/* Frequency Synthesizer Control */
CC1101_FSCTRL0,
0x00, 0x00,
}; CC1101_FSCTRL1,
0x00, // IF = (26*10^6) / (2^10) * 0x00 = 0 Hz
// Modem Configuration
// CC1101_MDMCFG0,
// 0x00, // Channel spacing is 25kHz
// CC1101_MDMCFG1,
// 0x00, // Channel spacing is 25kHz
// CC1101_MDMCFG2,
// 0x30, // Format ASK/OOK, No preamble/sync
// CC1101_MDMCFG3,
// 0x32, // Data rate is 121.399 kBaud
CC1101_MDMCFG4,
0xFC, // Rx BW filter is 58.04 kHz
/* Frequency Offset Compensation Configuration */
// CC1101_FOCCFG,
// 0x18, // no frequency offset compensation, POST_K same as PRE_K, PRE_K is 4K, GATE is off
/* Automatic Gain Control */
CC1101_AGCCTRL0,
0x30, // 00 - NO hysteresis, symmetric dead zone, high gain ; 11 - 32 samples agc; 00 - Normal AGC, 00 - 8dB boundary
CC1101_AGCCTRL1,
0x0, // 0; 0 - LNA 2 gain is decreased to minimum before decreasing LNA gain; 00 - Relative carrier sense threshold disabled; 0000 - RSSI to MAIN_TARGET
CC1101_AGCCTRL2,
0x84, // 02 - The 2 highest DVGA gain settings can not be used; 000 - MAX LNA+LNA2; 100 - MAIN_TARGET 36 dB
/* Frontend configuration */
// CC1101_FREND0,
// 0x11, // Adjusts current TX LO buffer + high is PATABLE[1]
// CC1101_FREND1,
// 0xB6, //
CC1101_TEST2,
0x88,
CC1101_TEST1,
0x31,
CC1101_TEST0,
0x09,
/* End */
0,
0,
// ook_async_patable
0x00,
0xC0, // 12dBm 0xC0, 10dBm 0xC5, 7dBm 0xCD, 5dBm 0x86, 0dBm 0x50, -6dBm 0x37, -10dBm 0x26, -15dBm 0x1D, -20dBm 0x17, -30dBm 0x03
0x00,
0x00,
0x00,
0x00,
0x00,
0x00};
const uint8_t* modulations[] = {default_modulation, narrow_modulation};
while(instance->should_work) { while(instance->should_work) {
furi_delay_ms(50); furi_delay_ms(50);
@@ -106,7 +195,12 @@ static int32_t spectrum_analyzer_worker_thread(void* context) {
// FURI_LOG_T("SpectrumWorker", "spectrum_analyzer_worker_thread: Worker Loop"); // FURI_LOG_T("SpectrumWorker", "spectrum_analyzer_worker_thread: Worker Loop");
subghz_devices_idle(instance->radio_device); subghz_devices_idle(instance->radio_device);
subghz_devices_load_preset( subghz_devices_load_preset(
instance->radio_device, FuriHalSubGhzPresetCustom, (uint8_t*)radio_config); instance->radio_device,
FuriHalSubGhzPresetCustom,
(uint8_t*)modulations[instance->modulation]);
//subghz_devices_load_preset(
// instance->radio_device, FuriHalSubGhzPresetCustom, (uint8_t*)default_modulation);
//furi_hal_subghz_load_custom_preset(modulations[instance->modulation]);
// TODO: Check filter! // TODO: Check filter!
// spectrum_analyzer_worker_set_filter(instance); // spectrum_analyzer_worker_set_filter(instance);
@@ -222,6 +316,15 @@ void spectrum_analyzer_worker_set_frequencies(
instance->width = width; instance->width = width;
} }
void spectrum_analyzer_worker_set_modulation(SpectrumAnalyzerWorker* instance, uint8_t modulation) {
furi_assert(instance);
FURI_LOG_D(
"SpectrumWorker", "spectrum_analyzer_worker_set_modulation - modulation = %u", modulation);
instance->modulation = modulation;
}
void spectrum_analyzer_worker_start(SpectrumAnalyzerWorker* instance) { void spectrum_analyzer_worker_start(SpectrumAnalyzerWorker* instance) {
FURI_LOG_D("Spectrum", "spectrum_analyzer_worker_start"); FURI_LOG_D("Spectrum", "spectrum_analyzer_worker_start");

View File

@@ -28,6 +28,8 @@ void spectrum_analyzer_worker_set_frequencies(
uint32_t spacing, uint32_t spacing,
uint8_t width); uint8_t width);
void spectrum_analyzer_worker_set_modulation(SpectrumAnalyzerWorker* instance, uint8_t modulation);
void spectrum_analyzer_worker_start(SpectrumAnalyzerWorker* instance); void spectrum_analyzer_worker_start(SpectrumAnalyzerWorker* instance);
void spectrum_analyzer_worker_stop(SpectrumAnalyzerWorker* instance); void spectrum_analyzer_worker_stop(SpectrumAnalyzerWorker* instance);

View File

@@ -223,56 +223,58 @@ int32_t text_viewer_app(void* p) {
text_viewer_read_file(text_viewer); text_viewer_read_file(text_viewer);
InputEvent input; InputEvent input;
while(furi_message_queue_get(text_viewer->input_queue, &input, FuriWaitForever) == while(1) {
FuriStatusOk) { if(furi_message_queue_get(text_viewer->input_queue, &input, 100) == FuriStatusOk) {
if(input.key == InputKeyBack) { if(input.key == InputKeyBack) {
break; break;
} else if(input.key == InputKeyUp) { } else if(input.key == InputKeyUp) {
furi_check( furi_check(
furi_mutex_acquire(text_viewer->mutex, FuriWaitForever) == FuriStatusOk); furi_mutex_acquire(text_viewer->mutex, FuriWaitForever) == FuriStatusOk);
if(text_viewer->model->file_offset > 0) { if(text_viewer->model->file_offset > 0) {
text_viewer->model->file_offset -= TEXT_VIEWER_BYTES_PER_LINE; text_viewer->model->file_offset -= TEXT_VIEWER_BYTES_PER_LINE;
if(!text_viewer_read_file(text_viewer)) break; if(!text_viewer_read_file(text_viewer)) break;
}
furi_mutex_release(text_viewer->mutex);
} else if(input.key == InputKeyDown) {
furi_check(
furi_mutex_acquire(text_viewer->mutex, FuriWaitForever) == FuriStatusOk);
uint32_t last_byte_on_screen =
text_viewer->model->file_offset + text_viewer->model->file_read_bytes;
if(text_viewer->model->file_size > last_byte_on_screen) {
text_viewer->model->file_offset += TEXT_VIEWER_BYTES_PER_LINE;
if(!text_viewer_read_file(text_viewer)) break;
}
furi_mutex_release(text_viewer->mutex);
} else if(input.key == InputKeyLeft) {
furi_check(
furi_mutex_acquire(text_viewer->mutex, FuriWaitForever) == FuriStatusOk);
text_viewer->model->mode = !text_viewer->model->mode;
furi_mutex_release(text_viewer->mutex);
} else if(input.key == InputKeyRight) {
FuriString* buffer;
buffer = furi_string_alloc();
furi_string_printf(
buffer,
"File path: %s\nFile size: %lu (0x%lX)",
furi_string_get_cstr(file_path),
text_viewer->model->file_size,
text_viewer->model->file_size);
DialogsApp* dialogs = furi_record_open(RECORD_DIALOGS);
DialogMessage* message = dialog_message_alloc();
dialog_message_set_header(
message, "Text Viewer v1.1", 16, 2, AlignLeft, AlignTop);
dialog_message_set_icon(message, &I_text_10px, 3, 2);
dialog_message_set_text(
message, furi_string_get_cstr(buffer), 3, 16, AlignLeft, AlignTop);
dialog_message_set_buttons(message, NULL, NULL, "Back");
dialog_message_show(dialogs, message);
furi_string_free(buffer);
dialog_message_free(message);
furi_record_close(RECORD_DIALOGS);
} }
furi_mutex_release(text_viewer->mutex);
} else if(input.key == InputKeyDown) {
furi_check(
furi_mutex_acquire(text_viewer->mutex, FuriWaitForever) == FuriStatusOk);
uint32_t last_byte_on_screen =
text_viewer->model->file_offset + text_viewer->model->file_read_bytes;
if(text_viewer->model->file_size > last_byte_on_screen) {
text_viewer->model->file_offset += TEXT_VIEWER_BYTES_PER_LINE;
if(!text_viewer_read_file(text_viewer)) break;
}
furi_mutex_release(text_viewer->mutex);
} else if(input.key == InputKeyLeft) {
furi_check(
furi_mutex_acquire(text_viewer->mutex, FuriWaitForever) == FuriStatusOk);
text_viewer->model->mode = !text_viewer->model->mode;
furi_mutex_release(text_viewer->mutex);
} else if(input.key == InputKeyRight) {
FuriString* buffer;
buffer = furi_string_alloc();
furi_string_printf(
buffer,
"File path: %s\nFile size: %lu (0x%lX)",
furi_string_get_cstr(file_path),
text_viewer->model->file_size,
text_viewer->model->file_size);
DialogsApp* dialogs = furi_record_open(RECORD_DIALOGS);
DialogMessage* message = dialog_message_alloc();
dialog_message_set_header(message, "Text Viewer v1.1", 16, 2, AlignLeft, AlignTop);
dialog_message_set_icon(message, &I_text_10px, 3, 2);
dialog_message_set_text(
message, furi_string_get_cstr(buffer), 3, 16, AlignLeft, AlignTop);
dialog_message_set_buttons(message, NULL, NULL, "Back");
dialog_message_show(dialogs, message);
furi_string_free(buffer);
dialog_message_free(message);
furi_record_close(RECORD_DIALOGS);
} }
view_port_update(text_viewer->view_port); view_port_update(text_viewer->view_port);
} }

View File

@@ -3,9 +3,19 @@ App(
name="Authenticator", name="Authenticator",
apptype=FlipperAppType.EXTERNAL, apptype=FlipperAppType.EXTERNAL,
entry_point="totp_app", entry_point="totp_app",
requires=["gui", "cli", "dialogs", "storage", "input", "notification", "bt"], cdefines=["APP_TOTP"],
requires=[
"gui",
"cli",
"dialogs",
"storage",
"input",
"notification",
"bt"
],
stack_size=2 * 1024, stack_size=2 * 1024,
order=20, order=20,
fap_version="2.3",
fap_author="Alexander Kopachov (@akopachov)", fap_author="Alexander Kopachov (@akopachov)",
fap_description="Software-based TOTP authenticator for Flipper Zero device", fap_description="Software-based TOTP authenticator for Flipper Zero device",
fap_weburl="https://github.com/akopachov/flipper-zero_authenticator", fap_weburl="https://github.com/akopachov/flipper-zero_authenticator",
@@ -28,5 +38,8 @@ App(
Lib( Lib(
name="roll_value", name="roll_value",
), ),
Lib(
name="fonts",
),
], ],
) )

View File

@@ -22,10 +22,7 @@ extern const char* TOTP_CLI_COLOR_INFO;
#define TOTP_CLI_PRINTF(format, ...) printf(format, ##__VA_ARGS__) #define TOTP_CLI_PRINTF(format, ...) printf(format, ##__VA_ARGS__)
#define TOTP_CLI_PRINTF_COLORFUL(color, format, ...) \ #define TOTP_CLI_PRINTF_COLORFUL(color, format, ...) \
printf("\e[%s", color); \ TOTP_CLI_PRINTF("\e[%s" format "\e[0m", color, ##__VA_ARGS__)
printf(format, ##__VA_ARGS__); \
printf("\e[0m"); \
fflush(stdout)
#define TOTP_CLI_PRINTF_ERROR(format, ...) \ #define TOTP_CLI_PRINTF_ERROR(format, ...) \
TOTP_CLI_PRINTF_COLORFUL(TOTP_CLI_COLOR_ERROR, format, ##__VA_ARGS__) TOTP_CLI_PRINTF_COLORFUL(TOTP_CLI_COLOR_ERROR, format, ##__VA_ARGS__)

View File

@@ -102,15 +102,22 @@ void totp_cli_command_add_docopt_options() {
TOTP_CLI_PRINTF(" " DOCOPT_OPTION( TOTP_CLI_PRINTF(" " DOCOPT_OPTION(
TOTP_CLI_COMMAND_ARG_ALGO_PREFIX, TOTP_CLI_COMMAND_ARG_ALGO_PREFIX,
DOCOPT_ARGUMENT( DOCOPT_ARGUMENT(
TOTP_CLI_COMMAND_ARG_ALGO)) " Token hashing algorithm. Must be one of: " TOTP_TOKEN_ALGO_SHA1_NAME TOTP_CLI_COMMAND_ARG_ALGO)) " Token hashing algorithm. Must be one of: " TOKEN_HASH_ALGO_SHA1_NAME
", " TOTP_TOKEN_ALGO_SHA256_NAME ", " TOKEN_HASH_ALGO_SHA256_NAME
", " TOTP_TOKEN_ALGO_SHA512_NAME ", " TOKEN_HASH_ALGO_SHA512_NAME
", " TOTP_TOKEN_ALGO_STEAM_NAME ", " TOKEN_HASH_ALGO_STEAM_NAME
" " DOCOPT_DEFAULT(TOTP_TOKEN_ALGO_SHA1_NAME) "\r\n"); " " DOCOPT_DEFAULT(TOKEN_HASH_ALGO_SHA1_NAME) "\r\n");
TOTP_CLI_PRINTF(" " DOCOPT_OPTION( TOTP_CLI_PRINTF(
TOTP_CLI_COMMAND_ARG_DIGITS_PREFIX, " " DOCOPT_OPTION(
DOCOPT_ARGUMENT( TOTP_CLI_COMMAND_ARG_DIGITS_PREFIX,
TOTP_CLI_COMMAND_ARG_DIGITS)) " Number of digits to generate, one of: 5, 6, 8 " DOCOPT_DEFAULT("6") "\r\n"); DOCOPT_ARGUMENT(
TOTP_CLI_COMMAND_ARG_DIGITS)) " Number of digits to generate, one of: %" PRIu8
", %" PRIu8 ", %" PRIu8
" " DOCOPT_DEFAULT("%" PRIu8) "\r\n",
TokenDigitsCountFive,
TokenDigitsCountSix,
TokenDigitsCountEight,
TokenDigitsCountSix);
TOTP_CLI_PRINTF(" " DOCOPT_OPTION( TOTP_CLI_PRINTF(" " DOCOPT_OPTION(
TOTP_CLI_COMMAND_ARG_SECRET_ENCODING_PREFIX, TOTP_CLI_COMMAND_ARG_SECRET_ENCODING_PREFIX,
@@ -120,27 +127,32 @@ void totp_cli_command_add_docopt_options() {
" " DOCOPT_DEFAULT( " " DOCOPT_DEFAULT(
PLAIN_TOKEN_ENCODING_BASE32_NAME) "\r\n"); PLAIN_TOKEN_ENCODING_BASE32_NAME) "\r\n");
TOTP_CLI_PRINTF(" " DOCOPT_OPTION( TOTP_CLI_PRINTF(
TOTP_CLI_COMMAND_ARG_DURATION_PREFIX, " " DOCOPT_OPTION(
DOCOPT_ARGUMENT( TOTP_CLI_COMMAND_ARG_DURATION_PREFIX,
TOTP_CLI_COMMAND_ARG_DURATION)) " Token lifetime duration in seconds, between: 15 and 255 " DOCOPT_DEFAULT("30") "\r\n"); DOCOPT_ARGUMENT(
TOTP_CLI_COMMAND_ARG_DURATION)) " Token lifetime duration in seconds, between: %" PRIu8
" and %" PRIu8
" " DOCOPT_DEFAULT("%" PRIu8) "\r\n",
TokenDurationMin,
TokenDurationMax,
TokenDurationDefault);
TOTP_CLI_PRINTF(" " DOCOPT_SWITCH( TOTP_CLI_PRINTF(" " DOCOPT_SWITCH(
TOTP_CLI_COMMAND_ARG_UNSECURE_PREFIX) " Show console user input as-is without masking\r\n"); TOTP_CLI_COMMAND_ARG_UNSECURE_PREFIX) " Show console user input as-is without masking\r\n");
TOTP_CLI_PRINTF(" " DOCOPT_OPTION( TOTP_CLI_PRINTF(" " DOCOPT_OPTION(
TOTP_CLI_COMMAND_ARG_AUTOMATION_FEATURE_PREFIX, TOTP_CLI_COMMAND_ARG_AUTOMATION_FEATURE_PREFIX,
DOCOPT_ARGUMENT( DOCOPT_ARGUMENT(
TOTP_CLI_COMMAND_ARG_AUTOMATION_FEATURE)) " Token automation features to be enabled. Must be one of: " TOTP_TOKEN_AUTOMATION_FEATURE_NONE_NAME TOTP_CLI_COMMAND_ARG_AUTOMATION_FEATURE)) " Token automation features to be enabled. Must be one of: " TOKEN_AUTOMATION_FEATURE_NONE_NAME
", " TOTP_TOKEN_AUTOMATION_FEATURE_ENTER_AT_THE_END_NAME ", " TOKEN_AUTOMATION_FEATURE_ENTER_AT_THE_END_NAME
", " TOTP_TOKEN_AUTOMATION_FEATURE_TAB_AT_THE_END_NAME ", " TOKEN_AUTOMATION_FEATURE_TAB_AT_THE_END_NAME
" " DOCOPT_DEFAULT( " " DOCOPT_DEFAULT(
TOTP_TOKEN_AUTOMATION_FEATURE_NONE_NAME) "\r\n"); TOKEN_AUTOMATION_FEATURE_NONE_NAME) "\r\n");
TOTP_CLI_PRINTF(" # " TOTP_TOKEN_AUTOMATION_FEATURE_NONE_NAME TOTP_CLI_PRINTF(" # " TOKEN_AUTOMATION_FEATURE_NONE_NAME " - No features\r\n");
" - No features\r\n"); TOTP_CLI_PRINTF(" # " TOKEN_AUTOMATION_FEATURE_ENTER_AT_THE_END_NAME
TOTP_CLI_PRINTF(" # " TOTP_TOKEN_AUTOMATION_FEATURE_ENTER_AT_THE_END_NAME
" - Type <Enter> key at the end of token input automation\r\n"); " - Type <Enter> key at the end of token input automation\r\n");
TOTP_CLI_PRINTF(" # " TOTP_TOKEN_AUTOMATION_FEATURE_TAB_AT_THE_END_NAME TOTP_CLI_PRINTF(" # " TOKEN_AUTOMATION_FEATURE_TAB_AT_THE_END_NAME
" - Type <Tab> key at the end of token input automation\r\n"); " - Type <Tab> key at the end of token input automation\r\n");
TOTP_CLI_PRINTF(" # " TOTP_TOKEN_AUTOMATION_FEATURE_TYPE_SLOWER_NAME TOTP_CLI_PRINTF(" # " TOKEN_AUTOMATION_FEATURE_TYPE_SLOWER_NAME
" - Type slower\r\n"); " - Type slower\r\n");
} }

View File

@@ -4,19 +4,21 @@
#endif #endif
// Include Bluetooth token input automation // Include Bluetooth token input automation
#ifndef TOTP_NO_BADBT_TYPE
#define TOTP_BADBT_TYPE_ENABLED #define TOTP_BADBT_TYPE_ENABLED
#endif
// Include token input automation icons on the main screen // Include token input automation icons on the main screen
#ifndef TOTP_NO_AUTOMATION_ICONS
#define TOTP_AUTOMATION_ICONS_ENABLED #define TOTP_AUTOMATION_ICONS_ENABLED
#endif
// List of compatible firmwares // List of compatible firmwares
#define TOTP_FIRMWARE_OFFICIAL_STABLE 1 #define TOTP_FIRMWARE_OFFICIAL_STABLE (1)
#define TOTP_FIRMWARE_OFFICIAL_DEV 2 #define TOTP_FIRMWARE_OFFICIAL_DEV (2)
#define TOTP_FIRMWARE_UL_XFW 3 // XFW and UL now has same bluetooth mac/advname changing API #define TOTP_FIRMWARE_XTREME_UL (3)
// End of list // End of list
// Target firmware to build for #ifndef TOTP_TARGET_FIRMWARE
#define TOTP_TARGET_FIRMWARE TOTP_FIRMWARE_UL_XFW #define TOTP_TARGET_FIRMWARE TOTP_FIRMWARE_XTREME_UL
#endif
// Max custom fonts value
#define MAX_CUSTOM_FONTS (9)

View File

@@ -931,6 +931,7 @@ const FONT_CHAR_INFO _712Serif_24ptDescriptors[] = {
/* Font information for 7:12 Serif 24pt */ /* Font information for 7:12 Serif 24pt */
const FONT_INFO _712Serif_24ptFontInfo = { const FONT_INFO _712Serif_24ptFontInfo = {
"712 Serif",
14, /* Character height */ 14, /* Character height */
'-', /* Start character */ '-', /* Start character */
'Y', /* End character */ 'Y', /* End character */

View File

@@ -0,0 +1,23 @@
#include "available_fonts.h"
#include "712serif/712serif.h"
#include "bedstead/bedstead.h"
#include "dpcomic/dpcomic.h"
#include "funclimbing/funclimbing.h"
#include "graph35pix/graph35pix.h"
#include "karma_future/karma_future.h"
#include "mode_nine/mode_nine.h"
#include "pixelflag/pixelflag.h"
#include "redhat_mono/redhat_mono.h"
#include "zector/zector.h"
const FONT_INFO* const available_fonts[AVAILABLE_FONTS_COUNT] = {
&modeNine_15ptFontInfo,
&_712Serif_24ptFontInfo,
&bedstead_17ptFontInfo,
&dPComic_18ptFontInfo,
&funclimbingDemo_18ptFontInfo,
&graph35pix_12ptFontInfo,
&karmaFuture_14ptFontInfo,
&pixelFlag_18ptFontInfo,
&redHatMono_16ptFontInfo,
&zector_18ptFontInfo};

View File

@@ -0,0 +1,7 @@
#pragma once
#include "font_info.h"
#define AVAILABLE_FONTS_COUNT (10)
extern const FONT_INFO* const available_fonts[AVAILABLE_FONTS_COUNT];

View File

@@ -1047,6 +1047,7 @@ const FONT_CHAR_INFO bedstead_17ptDescriptors[] = {
/* Font information for Bedstead 17pt */ /* Font information for Bedstead 17pt */
const FONT_INFO bedstead_17ptFontInfo = { const FONT_INFO bedstead_17ptFontInfo = {
"Bedstead",
16, /* Character height */ 16, /* Character height */
'-', /* Start character */ '-', /* Start character */
'Y', /* End character */ 'Y', /* End character */

View File

@@ -1105,6 +1105,7 @@ const FONT_CHAR_INFO dPComic_18ptDescriptors[] = {
/* Font information for DPComic 18pt */ /* Font information for DPComic 18pt */
const FONT_INFO dPComic_18ptFontInfo = { const FONT_INFO dPComic_18ptFontInfo = {
"DP Comic",
17, /* Character height */ 17, /* Character height */
'-', /* Start character */ '-', /* Start character */
'Y', /* End character */ 'Y', /* End character */

View File

@@ -14,11 +14,11 @@ typedef struct {
// Describes a single font // Describes a single font
typedef struct { typedef struct {
const char* name; // Font name
const uint8_t height; // height, in pages (8 pixels), of the font's characters const uint8_t height; // height, in pages (8 pixels), of the font's characters
const uint8_t startChar; // the first character in the font (e.g. in charInfo and data) const uint8_t startChar; // the first character in the font (e.g. in charInfo and data)
const uint8_t endChar; // the last character in the font const uint8_t endChar; // the last character in the font
const uint8_t spacePixels; // number of pixels that a space character takes up const uint8_t spacePixels; // number of pixels that a space character takes up
const FONT_CHAR_INFO* charInfo; // pointer to array of char information const FONT_CHAR_INFO* charInfo; // pointer to array of char information
const uint8_t* data; // pointer to generated array of character visual representation const uint8_t* data; // pointer to generated array of character visual representation
} FONT_INFO; } FONT_INFO;

View File

@@ -1163,6 +1163,7 @@ const FONT_CHAR_INFO funclimbingDemo_18ptDescriptors[] = {
/* Font information for fun climbing (Demo) 18pt */ /* Font information for fun climbing (Demo) 18pt */
const FONT_INFO funclimbingDemo_18ptFontInfo = { const FONT_INFO funclimbingDemo_18ptFontInfo = {
"Fun Climbing",
18, /* Character height */ 18, /* Character height */
'-', /* Start character */ '-', /* Start character */
'Y', /* End character */ 'Y', /* End character */

View File

@@ -931,6 +931,7 @@ const FONT_CHAR_INFO graph35pix_12ptDescriptors[] = {
/* Font information for Graph 35+ pix 12pt */ /* Font information for Graph 35+ pix 12pt */
const FONT_INFO graph35pix_12ptFontInfo = { const FONT_INFO graph35pix_12ptFontInfo = {
"Graph 35pix",
14, /* Character height */ 14, /* Character height */
'-', /* Start character */ '-', /* Start character */
'Y', /* End character */ 'Y', /* End character */

View File

@@ -1163,6 +1163,7 @@ const FONT_CHAR_INFO karmaFuture_14ptDescriptors[] = {
/* Font information for Karma Future 14pt */ /* Font information for Karma Future 14pt */
const FONT_INFO karmaFuture_14ptFontInfo = { const FONT_INFO karmaFuture_14ptFontInfo = {
"Karma Future",
18, /* Character height */ 18, /* Character height */
'-', /* Start character */ '-', /* Start character */
'Y', /* End character */ 'Y', /* End character */

View File

@@ -932,6 +932,7 @@ const FONT_CHAR_INFO modeNine_15ptDescriptors[] = {
/* Font information for ModeNine 15pt */ /* Font information for ModeNine 15pt */
const FONT_INFO modeNine_15ptFontInfo = { const FONT_INFO modeNine_15ptFontInfo = {
"Mode Nine",
14, /* Character height */ 14, /* Character height */
'-', /* Start character */ '-', /* Start character */
'Y', /* End character */ 'Y', /* End character */

View File

@@ -1105,6 +1105,7 @@ const FONT_CHAR_INFO pixelFlag_18ptDescriptors[] = {
/* Font information for {PixelFlag} 18pt */ /* Font information for {PixelFlag} 18pt */
const FONT_INFO pixelFlag_18ptFontInfo = { const FONT_INFO pixelFlag_18ptFontInfo = {
"Pixel Flag",
17, /* Character height */ 17, /* Character height */
'-', /* Start character */ '-', /* Start character */
'Y', /* End character */ 'Y', /* End character */

View File

@@ -1048,6 +1048,7 @@ const FONT_CHAR_INFO redHatMono_16ptDescriptors[] = {
/* Font information for Red Hat Mono 16pt */ /* Font information for Red Hat Mono 16pt */
const FONT_INFO redHatMono_16ptFontInfo = { const FONT_INFO redHatMono_16ptFontInfo = {
"RedHat Mono",
16, /* Character height */ 16, /* Character height */
'-', /* Start character */ '-', /* Start character */
'Y', /* End character */ 'Y', /* End character */

View File

@@ -1047,6 +1047,7 @@ const FONT_CHAR_INFO zector_18ptDescriptors[] = {
/* Font information for Zector 18pt */ /* Font information for Zector 18pt */
const FONT_INFO zector_18ptFontInfo = { const FONT_INFO zector_18ptFontInfo = {
"Zector",
16, /* Character height */ 16, /* Character height */
'-', /* Start character */ '-', /* Start character */
'Y', /* End character */ 'Y', /* End character */

View File

@@ -15,9 +15,6 @@
#define CONFIG_FILE_PATH CONFIG_FILE_DIRECTORY_PATH "/totp.conf" #define CONFIG_FILE_PATH CONFIG_FILE_DIRECTORY_PATH "/totp.conf"
#define CONFIG_FILE_BACKUP_DIR CONFIG_FILE_DIRECTORY_PATH "/backups" #define CONFIG_FILE_BACKUP_DIR CONFIG_FILE_DIRECTORY_PATH "/backups"
#define CONFIG_FILE_BACKUP_BASE_PATH CONFIG_FILE_BACKUP_DIR "/totp.conf" #define CONFIG_FILE_BACKUP_BASE_PATH CONFIG_FILE_BACKUP_DIR "/totp.conf"
#define CONFIG_FILE_TEMP_PATH CONFIG_FILE_PATH ".tmp"
#define CONFIG_FILE_ORIG_PATH CONFIG_FILE_PATH ".orig"
#define CONFIG_FILE_PATH_PREVIOUS EXT_PATH("apps/Misc") "/totp.conf"
struct ConfigFileContext { struct ConfigFileContext {
/** /**
@@ -120,26 +117,6 @@ static bool totp_open_config_file(Storage* storage, FlipperFormat** file) {
totp_close_config_file(fff_data_file); totp_close_config_file(fff_data_file);
return false; return false;
} }
} else if(storage_common_stat(storage, CONFIG_FILE_PATH_PREVIOUS, NULL) == FSE_OK) {
FURI_LOG_D(LOGGING_TAG, "Old config file %s found", CONFIG_FILE_PATH_PREVIOUS);
if(storage_common_stat(storage, CONFIG_FILE_DIRECTORY_PATH, NULL) == FSE_NOT_EXIST) {
FURI_LOG_D(
LOGGING_TAG,
"Directory %s doesn't exist. Will create new.",
CONFIG_FILE_DIRECTORY_PATH);
if(!storage_simply_mkdir(storage, CONFIG_FILE_DIRECTORY_PATH)) {
FURI_LOG_E(LOGGING_TAG, "Error creating directory %s", CONFIG_FILE_DIRECTORY_PATH);
totp_close_config_file(fff_data_file);
return false;
}
}
if(storage_common_rename(storage, CONFIG_FILE_PATH_PREVIOUS, CONFIG_FILE_PATH) != FSE_OK) {
FURI_LOG_E(LOGGING_TAG, "Error moving config to %s", CONFIG_FILE_PATH);
totp_close_config_file(fff_data_file);
return false;
}
FURI_LOG_I(LOGGING_TAG, "Applied config file path migration");
return totp_open_config_file(storage, file);
} else { } else {
FURI_LOG_D(LOGGING_TAG, "Config file %s is not found. Will create new.", CONFIG_FILE_PATH); FURI_LOG_D(LOGGING_TAG, "Config file %s is not found. Will create new.", CONFIG_FILE_PATH);
if(storage_common_stat(storage, CONFIG_FILE_DIRECTORY_PATH, NULL) == FSE_NOT_EXIST) { if(storage_common_stat(storage, CONFIG_FILE_DIRECTORY_PATH, NULL) == FSE_NOT_EXIST) {
@@ -177,9 +154,8 @@ static bool totp_open_config_file(Storage* storage, FlipperFormat** file) {
flipper_format_write_uint32( flipper_format_write_uint32(
fff_data_file, TOTP_CONFIG_KEY_AUTOMATION_METHOD, &tmp_uint32, 1); fff_data_file, TOTP_CONFIG_KEY_AUTOMATION_METHOD, &tmp_uint32, 1);
// Default Font = 0
tmp_uint32 = 0; tmp_uint32 = 0;
flipper_format_write_uint32(fff_data_file, TOTP_CONFIG_KEY_SELECTED_FONT, &tmp_uint32, 1); flipper_format_write_uint32(fff_data_file, TOTP_CONFIG_KEY_FONT, &tmp_uint32, 1);
if(!flipper_format_rewind(fff_data_file)) { if(!flipper_format_rewind(fff_data_file)) {
totp_close_config_file(fff_data_file); totp_close_config_file(fff_data_file);
@@ -263,24 +239,6 @@ bool totp_config_file_update_automation_method(const PluginState* plugin_state)
return update_result; return update_result;
} }
bool totp_config_file_update_selected_font(const PluginState* plugin_state) {
FlipperFormat* file = plugin_state->config_file_context->config_file;
flipper_format_rewind(file);
bool update_result = false;
do {
uint32_t tmp_uint32 = plugin_state->selected_font;
if(!flipper_format_insert_or_update_uint32(
file, TOTP_CONFIG_KEY_SELECTED_FONT, &tmp_uint32, 1)) {
break;
}
update_result = true;
} while(false);
return update_result;
}
bool totp_config_file_update_user_settings(const PluginState* plugin_state) { bool totp_config_file_update_user_settings(const PluginState* plugin_state) {
FlipperFormat* file = plugin_state->config_file_context->config_file; FlipperFormat* file = plugin_state->config_file_context->config_file;
flipper_format_rewind(file); flipper_format_rewind(file);
@@ -302,9 +260,8 @@ bool totp_config_file_update_user_settings(const PluginState* plugin_state) {
break; break;
} }
tmp_uint32 = plugin_state->selected_font; tmp_uint32 = plugin_state->active_font_index;
if(!flipper_format_insert_or_update_uint32( if(!flipper_format_insert_or_update_uint32(file, TOTP_CONFIG_KEY_FONT, &tmp_uint32, 1)) {
file, TOTP_CONFIG_KEY_SELECTED_FONT, &tmp_uint32, 1)) {
break; break;
} }
@@ -456,15 +413,11 @@ bool totp_config_file_load(PluginState* const plugin_state) {
plugin_state->automation_method = tmp_uint32; plugin_state->automation_method = tmp_uint32;
// Load selected font if(!flipper_format_read_uint32(fff_data_file, TOTP_CONFIG_KEY_FONT, &tmp_uint32, 1)) {
flipper_format_rewind(fff_data_file);
if(!flipper_format_read_uint32(
fff_data_file, TOTP_CONFIG_KEY_SELECTED_FONT, &tmp_uint32, 1)) {
tmp_uint32 = 0; tmp_uint32 = 0;
} }
plugin_state->selected_font = tmp_uint32; plugin_state->active_font_index = tmp_uint32;
plugin_state->config_file_context = malloc(sizeof(ConfigFileContext)); plugin_state->config_file_context = malloc(sizeof(ConfigFileContext));
furi_check(plugin_state->config_file_context != NULL); furi_check(plugin_state->config_file_context != NULL);

View File

@@ -44,13 +44,6 @@ bool totp_config_file_update_notification_method(const PluginState* plugin_state
*/ */
bool totp_config_file_update_automation_method(const PluginState* plugin_state); bool totp_config_file_update_automation_method(const PluginState* plugin_state);
/**
* @brief Updates selected font in an application config file
* @param plugin_state application state
* @return Config file update result
*/
bool totp_config_file_update_selected_font(const PluginState* plugin_state);
/** /**
* @brief Updates application user settings * @brief Updates application user settings
* @param plugin_state application state * @param plugin_state application state

View File

@@ -4,7 +4,7 @@
#define CONFIG_FILE_DIRECTORY_PATH EXT_PATH("authenticator") #define CONFIG_FILE_DIRECTORY_PATH EXT_PATH("authenticator")
#define CONFIG_FILE_HEADER "Flipper TOTP plugin config file" #define CONFIG_FILE_HEADER "Flipper TOTP plugin config file"
#define CONFIG_FILE_ACTUAL_VERSION (5) #define CONFIG_FILE_ACTUAL_VERSION (6)
#define TOTP_CONFIG_KEY_TIMEZONE "Timezone" #define TOTP_CONFIG_KEY_TIMEZONE "Timezone"
#define TOTP_CONFIG_KEY_TOKEN_NAME "TokenName" #define TOTP_CONFIG_KEY_TOKEN_NAME "TokenName"
@@ -18,4 +18,4 @@
#define TOTP_CONFIG_KEY_PINSET "PinIsSet" #define TOTP_CONFIG_KEY_PINSET "PinIsSet"
#define TOTP_CONFIG_KEY_NOTIFICATION_METHOD "NotificationMethod" #define TOTP_CONFIG_KEY_NOTIFICATION_METHOD "NotificationMethod"
#define TOTP_CONFIG_KEY_AUTOMATION_METHOD "AutomationMethod" #define TOTP_CONFIG_KEY_AUTOMATION_METHOD "AutomationMethod"
#define TOTP_CONFIG_KEY_SELECTED_FONT "SelectedFont" #define TOTP_CONFIG_KEY_FONT "Font"

View File

@@ -58,11 +58,12 @@ bool totp_config_migrate_to_latest(
flipper_format_rewind(fff_backup_data_file); flipper_format_rewind(fff_backup_data_file);
// Font if(flipper_format_read_string(fff_backup_data_file, TOTP_CONFIG_KEY_FONT, temp_str)) {
flipper_format_write_string(fff_data_file, TOTP_CONFIG_KEY_FONT, temp_str);
if(flipper_format_read_string( } else {
fff_backup_data_file, TOTP_CONFIG_KEY_SELECTED_FONT, temp_str)) { uint32_t default_font_index = 0;
flipper_format_write_string(fff_data_file, TOTP_CONFIG_KEY_SELECTED_FONT, temp_str); flipper_format_write_uint32(
fff_data_file, TOTP_CONFIG_KEY_FONT, &default_font_index, 1);
} }
flipper_format_rewind(fff_backup_data_file); flipper_format_rewind(fff_backup_data_file);
@@ -84,13 +85,13 @@ bool totp_config_migrate_to_latest(
fff_backup_data_file, TOTP_CONFIG_KEY_TOKEN_ALGO, temp_str); fff_backup_data_file, TOTP_CONFIG_KEY_TOKEN_ALGO, temp_str);
if(current_version < 5) { if(current_version < 5) {
uint32_t algo_as_uint32t = SHA1; uint32_t algo_as_uint32t = TokenHashAlgoDefault;
if(furi_string_cmpi_str(temp_str, TOTP_TOKEN_ALGO_SHA256_NAME) == 0) { if(furi_string_cmpi_str(temp_str, TOKEN_HASH_ALGO_SHA256_NAME) == 0) {
algo_as_uint32t = SHA256; algo_as_uint32t = TokenHashAlgoSha256;
} else if(furi_string_cmpi_str(temp_str, TOTP_TOKEN_ALGO_SHA512_NAME) == 0) { } else if(furi_string_cmpi_str(temp_str, TOKEN_HASH_ALGO_SHA512_NAME) == 0) {
algo_as_uint32t = SHA512; algo_as_uint32t = TokenHashAlgoSha512;
} else if(furi_string_cmpi_str(temp_str, TOTP_TOKEN_ALGO_STEAM_NAME) == 0) { } else if(furi_string_cmpi_str(temp_str, TOKEN_HASH_ALGO_STEAM_NAME) == 0) {
algo_as_uint32t = STEAM; algo_as_uint32t = TokenHashAlgoSteam;
} }
flipper_format_write_uint32( flipper_format_write_uint32(
@@ -104,10 +105,10 @@ bool totp_config_migrate_to_latest(
fff_backup_data_file, TOTP_CONFIG_KEY_TOKEN_DIGITS, temp_str); fff_backup_data_file, TOTP_CONFIG_KEY_TOKEN_DIGITS, temp_str);
flipper_format_write_string(fff_data_file, TOTP_CONFIG_KEY_TOKEN_DIGITS, temp_str); flipper_format_write_string(fff_data_file, TOTP_CONFIG_KEY_TOKEN_DIGITS, temp_str);
} else { } else {
const uint32_t default_algo = SHA1; const uint32_t default_algo = TokenHashAlgoDefault;
flipper_format_write_uint32( flipper_format_write_uint32(
fff_data_file, TOTP_CONFIG_KEY_TOKEN_ALGO, &default_algo, 1); fff_data_file, TOTP_CONFIG_KEY_TOKEN_ALGO, &default_algo, 1);
const uint32_t default_digits = TotpSixDigitsCount; const uint32_t default_digits = TokenDigitsCountSix;
flipper_format_write_uint32( flipper_format_write_uint32(
fff_data_file, TOTP_CONFIG_KEY_TOKEN_DIGITS, &default_digits, 1); fff_data_file, TOTP_CONFIG_KEY_TOKEN_DIGITS, &default_digits, 1);
} }
@@ -118,7 +119,7 @@ bool totp_config_migrate_to_latest(
flipper_format_write_string( flipper_format_write_string(
fff_data_file, TOTP_CONFIG_KEY_TOKEN_DURATION, temp_str); fff_data_file, TOTP_CONFIG_KEY_TOKEN_DURATION, temp_str);
} else { } else {
const uint32_t default_duration = TOTP_TOKEN_DURATION_DEFAULT; const uint32_t default_duration = TokenDurationDefault;
flipper_format_write_uint32( flipper_format_write_uint32(
fff_data_file, TOTP_CONFIG_KEY_TOKEN_DURATION, &default_duration, 1); fff_data_file, TOTP_CONFIG_KEY_TOKEN_DURATION, &default_duration, 1);
} }

View File

@@ -496,19 +496,19 @@ bool totp_token_info_iterator_go_to(TokenInfoIteratorContext* context, size_t to
if(!flipper_format_read_uint32( if(!flipper_format_read_uint32(
context->config_file, TOTP_CONFIG_KEY_TOKEN_ALGO, &temp_data32, 1) || context->config_file, TOTP_CONFIG_KEY_TOKEN_ALGO, &temp_data32, 1) ||
!token_info_set_algo_from_int(tokenInfo, temp_data32)) { !token_info_set_algo_from_int(tokenInfo, temp_data32)) {
tokenInfo->algo = SHA1; tokenInfo->algo = TokenHashAlgoDefault;
} }
if(!flipper_format_read_uint32( if(!flipper_format_read_uint32(
context->config_file, TOTP_CONFIG_KEY_TOKEN_DIGITS, &temp_data32, 1) || context->config_file, TOTP_CONFIG_KEY_TOKEN_DIGITS, &temp_data32, 1) ||
!token_info_set_digits_from_int(tokenInfo, temp_data32)) { !token_info_set_digits_from_int(tokenInfo, temp_data32)) {
tokenInfo->digits = TotpSixDigitsCount; tokenInfo->digits = TokenDigitsCountSix;
} }
if(!flipper_format_read_uint32( if(!flipper_format_read_uint32(
context->config_file, TOTP_CONFIG_KEY_TOKEN_DURATION, &temp_data32, 1) || context->config_file, TOTP_CONFIG_KEY_TOKEN_DURATION, &temp_data32, 1) ||
!token_info_set_duration_from_int(tokenInfo, temp_data32)) { !token_info_set_duration_from_int(tokenInfo, temp_data32)) {
tokenInfo->duration = TOTP_TOKEN_DURATION_DEFAULT; tokenInfo->duration = TokenDurationDefault;
} }
if(flipper_format_read_uint32( if(flipper_format_read_uint32(

View File

@@ -90,11 +90,8 @@ CryptoSeedIVResult
} else { } else {
max_i = uid_size; max_i = uid_size;
} }
#if TOTP_TARGET_FIRMWARE == TOTP_FIRMWARE_UL_XFW
const uint8_t* uid = furi_hal_version_uid_default(); const uint8_t* uid = (const uint8_t*)UID64_BASE; //-V566
#else
const uint8_t* uid = furi_hal_version_uid();
#endif
for(uint8_t i = 0; i < max_i; i++) { for(uint8_t i = 0; i < max_i; i++) {
plugin_state->iv[i] = plugin_state->iv[i] ^ uid[i]; plugin_state->iv[i] = plugin_state->iv[i] ^ uid[i];
} }
@@ -137,4 +134,4 @@ bool totp_crypto_verify_key(const PluginState* plugin_state) {
free(decrypted_key); free(decrypted_key);
return key_valid; return key_valid;
} }

View File

@@ -63,4 +63,4 @@ void idle_timeout_free(IdleTimeoutContext* context) {
furi_timer_stop(context->timer); furi_timer_stop(context->timer);
furi_timer_free(context->timer); furi_timer_free(context->timer);
free(context); free(context);
} }

View File

@@ -41,4 +41,4 @@ void idle_timeout_report_activity(IdleTimeoutContext* context);
* @brief Disposes IDLE timeout and releases all the resources * @brief Disposes IDLE timeout and releases all the resources
* @param context IDLE timeout context * @param context IDLE timeout context
*/ */
void idle_timeout_free(IdleTimeoutContext* context); void idle_timeout_free(IdleTimeoutContext* context);

View File

@@ -116,7 +116,6 @@ static bool on_user_idle(void* context) {
} }
static bool totp_plugin_state_init(PluginState* const plugin_state) { static bool totp_plugin_state_init(PluginState* const plugin_state) {
plugin_state->selected_font = 0;
plugin_state->gui = furi_record_open(RECORD_GUI); plugin_state->gui = furi_record_open(RECORD_GUI);
plugin_state->notification_app = furi_record_open(RECORD_NOTIFICATION); plugin_state->notification_app = furi_record_open(RECORD_NOTIFICATION);
plugin_state->dialogs_app = furi_record_open(RECORD_DIALOGS); plugin_state->dialogs_app = furi_record_open(RECORD_DIALOGS);
@@ -208,7 +207,7 @@ int32_t totp_app() {
PluginEvent event; PluginEvent event;
bool processing = true; bool processing = true;
while(processing) { while(processing) {
FuriStatus event_status = furi_message_queue_get(event_queue, &event, FuriWaitForever); FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100);
if(furi_mutex_acquire(plugin_state->mutex, FuriWaitForever) == FuriStatusOk) { if(furi_mutex_acquire(plugin_state->mutex, FuriWaitForever) == FuriStatusOk) {
if(event_status == FuriStatusOk) { if(event_status == FuriStatusOk) {

View File

@@ -84,11 +84,6 @@ typedef struct {
*/ */
NotificationMethod notification_method; NotificationMethod notification_method;
/**
* @brief Numbers Font
*/
uint8_t selected_font;
/** /**
* @brief Main rendering loop mutex * @brief Main rendering loop mutex
*/ */
@@ -110,4 +105,9 @@ typedef struct {
* @brief IDLE timeout context * @brief IDLE timeout context
*/ */
IdleTimeoutContext* idle_timeout_context; IdleTimeoutContext* idle_timeout_context;
/**
* @brief Font index to be used to draw TOTP token
*/
uint8_t active_font_index;
} PluginState; } PluginState;

View File

@@ -69,13 +69,13 @@ bool token_info_set_secret(
bool token_info_set_digits_from_int(TokenInfo* token_info, uint8_t digits) { bool token_info_set_digits_from_int(TokenInfo* token_info, uint8_t digits) {
switch(digits) { switch(digits) {
case 5: case 5:
token_info->digits = TotpFiveDigitsCount; token_info->digits = TokenDigitsCountFive;
return true; return true;
case 6: case 6:
token_info->digits = TotpSixDigitsCount; token_info->digits = TokenDigitsCountSix;
return true; return true;
case 8: case 8:
token_info->digits = TotpEightDigitsCount; token_info->digits = TokenDigitsCountEight;
return true; return true;
default: default:
break; break;
@@ -85,32 +85,35 @@ bool token_info_set_digits_from_int(TokenInfo* token_info, uint8_t digits) {
} }
bool token_info_set_duration_from_int(TokenInfo* token_info, uint8_t duration) { bool token_info_set_duration_from_int(TokenInfo* token_info, uint8_t duration) {
if(duration >= 15) { #pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wtype-limits"
if(duration >= TokenDurationMin && duration <= TokenDurationMax) { //-V560
token_info->duration = duration; token_info->duration = duration;
return true; return true;
} }
#pragma GCC diagnostic pop
return false; return false;
} }
bool token_info_set_algo_from_str(TokenInfo* token_info, const FuriString* str) { bool token_info_set_algo_from_str(TokenInfo* token_info, const FuriString* str) {
if(furi_string_cmpi_str(str, TOTP_TOKEN_ALGO_SHA1_NAME) == 0) { if(furi_string_cmpi_str(str, TOKEN_HASH_ALGO_SHA1_NAME) == 0) {
token_info->algo = SHA1; token_info->algo = TokenHashAlgoSha1;
return true; return true;
} }
if(furi_string_cmpi_str(str, TOTP_TOKEN_ALGO_SHA256_NAME) == 0) { if(furi_string_cmpi_str(str, TOKEN_HASH_ALGO_SHA256_NAME) == 0) {
token_info->algo = SHA256; token_info->algo = TokenHashAlgoSha256;
return true; return true;
} }
if(furi_string_cmpi_str(str, TOTP_TOKEN_ALGO_SHA512_NAME) == 0) { if(furi_string_cmpi_str(str, TOKEN_HASH_ALGO_SHA512_NAME) == 0) {
token_info->algo = SHA512; token_info->algo = TokenHashAlgoSha512;
return true; return true;
} }
if(furi_string_cmpi_str(str, TOTP_TOKEN_ALGO_STEAM_NAME) == 0) { if(furi_string_cmpi_str(str, TOKEN_HASH_ALGO_STEAM_NAME) == 0) {
token_info->algo = STEAM; token_info->algo = TokenHashAlgoSteam;
return true; return true;
} }
@@ -119,17 +122,17 @@ bool token_info_set_algo_from_str(TokenInfo* token_info, const FuriString* str)
bool token_info_set_algo_from_int(TokenInfo* token_info, uint8_t algo_code) { bool token_info_set_algo_from_int(TokenInfo* token_info, uint8_t algo_code) {
switch(algo_code) { switch(algo_code) {
case SHA1: case TokenHashAlgoSha1:
token_info->algo = SHA1; token_info->algo = TokenHashAlgoSha1;
break; break;
case SHA256: case TokenHashAlgoSha256:
token_info->algo = SHA256; token_info->algo = TokenHashAlgoSha256;
break; break;
case SHA512: case TokenHashAlgoSha512:
token_info->algo = SHA512; token_info->algo = TokenHashAlgoSha512;
break; break;
case STEAM: case TokenHashAlgoSteam:
token_info->algo = STEAM; token_info->algo = TokenHashAlgoSteam;
break; break;
default: default:
return false; return false;
@@ -138,16 +141,16 @@ bool token_info_set_algo_from_int(TokenInfo* token_info, uint8_t algo_code) {
return true; return true;
} }
char* token_info_get_algo_as_cstr(const TokenInfo* token_info) { const char* token_info_get_algo_as_cstr(const TokenInfo* token_info) {
switch(token_info->algo) { switch(token_info->algo) {
case SHA1: case TokenHashAlgoSha1:
return TOTP_TOKEN_ALGO_SHA1_NAME; return TOKEN_HASH_ALGO_SHA1_NAME;
case SHA256: case TokenHashAlgoSha256:
return TOTP_TOKEN_ALGO_SHA256_NAME; return TOKEN_HASH_ALGO_SHA256_NAME;
case SHA512: case TokenHashAlgoSha512:
return TOTP_TOKEN_ALGO_SHA512_NAME; return TOKEN_HASH_ALGO_SHA512_NAME;
case STEAM: case TokenHashAlgoSteam:
return TOTP_TOKEN_ALGO_STEAM_NAME; return TOKEN_HASH_ALGO_STEAM_NAME;
default: default:
break; break;
} }
@@ -156,22 +159,22 @@ char* token_info_get_algo_as_cstr(const TokenInfo* token_info) {
} }
bool token_info_set_automation_feature_from_str(TokenInfo* token_info, const FuriString* str) { bool token_info_set_automation_feature_from_str(TokenInfo* token_info, const FuriString* str) {
if(furi_string_cmpi_str(str, TOTP_TOKEN_AUTOMATION_FEATURE_ENTER_AT_THE_END_NAME) == 0) { if(furi_string_cmpi_str(str, TOKEN_AUTOMATION_FEATURE_ENTER_AT_THE_END_NAME) == 0) {
token_info->automation_features |= TokenAutomationFeatureEnterAtTheEnd; token_info->automation_features |= TokenAutomationFeatureEnterAtTheEnd;
return true; return true;
} }
if(furi_string_cmpi_str(str, TOTP_TOKEN_AUTOMATION_FEATURE_TAB_AT_THE_END_NAME) == 0) { if(furi_string_cmpi_str(str, TOKEN_AUTOMATION_FEATURE_TAB_AT_THE_END_NAME) == 0) {
token_info->automation_features |= TokenAutomationFeatureTabAtTheEnd; token_info->automation_features |= TokenAutomationFeatureTabAtTheEnd;
return true; return true;
} }
if(furi_string_cmpi_str(str, TOTP_TOKEN_AUTOMATION_FEATURE_TYPE_SLOWER_NAME) == 0) { if(furi_string_cmpi_str(str, TOKEN_AUTOMATION_FEATURE_TYPE_SLOWER_NAME) == 0) {
token_info->automation_features |= TokenAutomationFeatureTypeSlower; token_info->automation_features |= TokenAutomationFeatureTypeSlower;
return true; return true;
} }
if(furi_string_cmpi_str(str, TOTP_TOKEN_AUTOMATION_FEATURE_NONE_NAME) == 0) { if(furi_string_cmpi_str(str, TOKEN_AUTOMATION_FEATURE_NONE_NAME) == 0) {
token_info->automation_features = TokenAutomationFeatureNone; token_info->automation_features = TokenAutomationFeatureNone;
return true; return true;
} }
@@ -195,9 +198,9 @@ TokenInfo* token_info_clone(const TokenInfo* src) {
void token_info_set_defaults(TokenInfo* token_info) { void token_info_set_defaults(TokenInfo* token_info) {
furi_check(token_info != NULL); furi_check(token_info != NULL);
token_info->algo = SHA1; token_info->algo = TokenHashAlgoDefault;
token_info->digits = TotpSixDigitsCount; token_info->digits = TokenDigitsCountDefault;
token_info->duration = TOTP_TOKEN_DURATION_DEFAULT; token_info->duration = TokenDurationDefault;
token_info->automation_features = TokenAutomationFeatureNone; token_info->automation_features = TokenAutomationFeatureNone;
furi_string_reset(token_info->name); furi_string_reset(token_info->name);
} }

View File

@@ -4,26 +4,20 @@
#include <stdbool.h> #include <stdbool.h>
#include <furi/core/string.h> #include <furi/core/string.h>
#define TOTP_TOKEN_DURATION_DEFAULT (30) #define TOKEN_HASH_ALGO_SHA1_NAME "sha1"
#define TOKEN_HASH_ALGO_STEAM_NAME "steam"
#define TOTP_TOKEN_ALGO_SHA1_NAME "sha1" #define TOKEN_HASH_ALGO_SHA256_NAME "sha256"
#define TOTP_TOKEN_ALGO_STEAM_NAME "steam" #define TOKEN_HASH_ALGO_SHA512_NAME "sha512"
#define TOTP_TOKEN_ALGO_SHA256_NAME "sha256"
#define TOTP_TOKEN_ALGO_SHA512_NAME "sha512"
#define TOTP_TOKEN_MAX_LENGTH (255)
#define PLAIN_TOKEN_ENCODING_BASE32_NAME "base32" #define PLAIN_TOKEN_ENCODING_BASE32_NAME "base32"
#define PLAIN_TOKEN_ENCODING_BASE64_NAME "base64" #define PLAIN_TOKEN_ENCODING_BASE64_NAME "base64"
#define TOKEN_AUTOMATION_FEATURE_NONE_NAME "none"
#define TOTP_TOKEN_AUTOMATION_FEATURE_NONE_NAME "none" #define TOKEN_AUTOMATION_FEATURE_ENTER_AT_THE_END_NAME "enter"
#define TOTP_TOKEN_AUTOMATION_FEATURE_ENTER_AT_THE_END_NAME "enter" #define TOKEN_AUTOMATION_FEATURE_TAB_AT_THE_END_NAME "tab"
#define TOTP_TOKEN_AUTOMATION_FEATURE_TAB_AT_THE_END_NAME "tab" #define TOKEN_AUTOMATION_FEATURE_TYPE_SLOWER_NAME "slower"
#define TOTP_TOKEN_AUTOMATION_FEATURE_TYPE_SLOWER_NAME "slower"
#define TOTP_TOKEN_DIGITS_MAX_COUNT (8)
typedef uint8_t TokenHashAlgo; typedef uint8_t TokenHashAlgo;
typedef uint8_t TokenDigitsCount; typedef uint8_t TokenDigitsCount;
typedef uint8_t TokenDuration;
typedef uint8_t TokenAutomationFeature; typedef uint8_t TokenAutomationFeature;
typedef uint8_t PlainTokenSecretEncoding; typedef uint8_t PlainTokenSecretEncoding;
@@ -34,22 +28,27 @@ enum TokenHashAlgos {
/** /**
* @brief SHA1 hashing algorithm * @brief SHA1 hashing algorithm
*/ */
SHA1 = 0, TokenHashAlgoSha1 = 0,
/** /**
* @brief SHA256 hashing algorithm * @brief SHA256 hashing algorithm
*/ */
SHA256 = 1, TokenHashAlgoSha256 = 1,
/** /**
* @brief SHA512 hashing algorithm * @brief SHA512 hashing algorithm
*/ */
SHA512 = 2, TokenHashAlgoSha512 = 2,
/** /**
* @brief Algorithm used by Steam (Valve) * @brief Algorithm used by Steam (Valve)
*/ */
STEAM = 3 TokenHashAlgoSteam = 3,
/**
* @brief Default token hashing algorithm
*/
TokenHashAlgoDefault = TokenHashAlgoSha1
}; };
/** /**
@@ -59,17 +58,47 @@ enum TokenDigitsCounts {
/** /**
* @brief 5 digits * @brief 5 digits
*/ */
TotpFiveDigitsCount = 5, TokenDigitsCountFive = 5,
/** /**
* @brief 6 digits * @brief 6 digits
*/ */
TotpSixDigitsCount = 6, TokenDigitsCountSix = 6,
/** /**
* @brief 8 digits * @brief 8 digits
*/ */
TotpEightDigitsCount = 8 TokenDigitsCountEight = 8,
/**
* @brief Default digits count
*/
TokenDigitsCountDefault = TokenDigitsCountSix,
/**
* @brief Maximum digits count
*/
TokenDigitsCountMax = TokenDigitsCountEight
};
/**
* @brief Token durations
*/
enum TokenDurations {
/**
* @brief Default token duration
*/
TokenDurationDefault = 30,
/**
* @brief Minimum token duration
*/
TokenDurationMin = 15,
/**
* @brief Maximum token duration
*/
TokenDurationMax = UINT8_MAX
}; };
/** /**
@@ -145,7 +174,7 @@ typedef struct {
/** /**
* @brief Desired TOTP token duration in seconds * @brief Desired TOTP token duration in seconds
*/ */
uint8_t duration; TokenDuration duration;
/** /**
* @brief Token input automation features * @brief Token input automation features
@@ -218,7 +247,7 @@ bool token_info_set_algo_from_int(TokenInfo* token_info, uint8_t algo_code);
* @param token_info instance which token hahsing algorithm name should be returned * @param token_info instance which token hahsing algorithm name should be returned
* @return token hashing algorithm name as C-string * @return token hashing algorithm name as C-string
*/ */
char* token_info_get_algo_as_cstr(const TokenInfo* token_info); const char* token_info_get_algo_as_cstr(const TokenInfo* token_info);
/** /**
* @brief Sets token automation feature from \c str value * @brief Sets token automation feature from \c str value

View File

@@ -0,0 +1,33 @@
#include "canvas_extensions.h"
void canvas_draw_str_ex(
Canvas* canvas,
uint8_t x,
uint8_t y,
const char* text,
size_t text_length,
const FONT_INFO* const font) {
const char* p_ch = text;
char ch;
size_t i = 0;
uint8_t offset_x = x;
uint8_t char_width = font->charInfo[0].width;
uint8_t offset_x_inc = char_width + font->spacePixels;
while(i < text_length && (ch = *p_ch) != 0) {
if(ch >= font->startChar && ch <= font->endChar) {
uint8_t char_index = ch - font->startChar;
canvas_draw_xbm(
canvas,
offset_x,
y,
char_width,
font->height,
&font->data[font->charInfo[char_index].offset]);
}
offset_x += offset_x_inc;
p_ch++;
i++;
}
}

View File

@@ -0,0 +1,13 @@
#pragma once
#include <stdint.h>
#include <gui/gui.h>
#include <font_info.h>
void canvas_draw_str_ex(
Canvas* canvas,
uint8_t x,
uint8_t y,
const char* text,
size_t text_length,
const FONT_INFO* const font);

View File

@@ -1,15 +0,0 @@
#pragma once
#include "../../features_config.h"
#include "font_info.h"
#include "mode_nine/mode_nine.h"
#include "redhat_mono/redhat_mono.h"
#include "bedstead/bedstead.h"
#include "zector/zector.h"
#include "712serif/712serif.h"
#include "graph35pix/graph35pix.h"
#include "karma_future/karma_future.h"
#include "funclimbing/funclimbing.h"
#include "dpcomic/dpcomic.h"
#include "pixelflag/pixelflag.h"

View File

@@ -1,81 +1,52 @@
#include "totp_input_text.h" #include "totp_input_text.h"
#include <gui/view_i.h>
void view_draw(View* view, Canvas* canvas) { #include <gui/view_dispatcher.h>
furi_assert(view); #include <gui/modules/text_input.h>
if(view->draw_callback) {
void* data = view_get_model(view); typedef struct {
view->draw_callback(canvas, data); InputTextResult* result;
view_unlock_model(view); ViewDispatcher* view_dispatcher;
} } InputTextContext;
static void commit_text_input_callback(void* ctx) {
InputTextContext* context = ctx;
context->result->user_input_length = strnlen(context->result->user_input, INPUT_BUFFER_SIZE);
context->result->success = true;
view_dispatcher_stop(context->view_dispatcher);
} }
bool view_input(View* view, InputEvent* event) { static bool back_event_callback(void* ctx) {
furi_assert(view); InputTextContext* context = ctx;
if(view->input_callback) { context->result->success = false;
return view->input_callback(event, view->context); view_dispatcher_stop(context->view_dispatcher);
} else { return false;
return false;
}
} }
void view_unlock_model(View* view) { void totp_input_text(Gui* gui, const char* header_text, InputTextResult* result) {
furi_assert(view); ViewDispatcher* view_dispatcher = view_dispatcher_alloc();
if(view->model_type == ViewModelTypeLocking) { TextInput* text_input = text_input_alloc();
ViewModelLocking* model = (ViewModelLocking*)(view->model); InputTextContext context = {.result = result, .view_dispatcher = view_dispatcher};
furi_check(furi_mutex_release(model->mutex) == FuriStatusOk); text_input_set_header_text(text_input, header_text);
}
}
static void commit_text_input_callback(void* context) {
InputTextSceneState* text_input_state = (InputTextSceneState*)context;
if(text_input_state->callback != NULL) {
InputTextSceneCallbackResult* result = malloc(sizeof(InputTextSceneCallbackResult));
furi_check(result != NULL);
result->user_input_length =
strnlen(text_input_state->text_input_buffer, INPUT_BUFFER_SIZE);
result->user_input = malloc(result->user_input_length + 1);
furi_check(result->user_input != NULL);
result->callback_data = text_input_state->callback_data;
strlcpy(
result->user_input,
text_input_state->text_input_buffer,
result->user_input_length + 1);
text_input_state->callback(result);
}
}
InputTextSceneState* totp_input_text_activate(InputTextSceneContext* context) {
InputTextSceneState* text_input_state = malloc(sizeof(InputTextSceneState));
furi_check(text_input_state != NULL);
text_input_state->text_input = text_input_alloc();
text_input_state->text_input_view = text_input_get_view(text_input_state->text_input);
text_input_state->callback = context->callback;
text_input_state->callback_data = context->callback_data;
text_input_set_header_text(text_input_state->text_input, context->header_text);
text_input_set_result_callback( text_input_set_result_callback(
text_input_state->text_input, text_input,
commit_text_input_callback, commit_text_input_callback,
text_input_state, &context,
&text_input_state->text_input_buffer[0], result->user_input,
INPUT_BUFFER_SIZE, INPUT_BUFFER_SIZE,
true); true);
return text_input_state;
}
void totp_input_text_render(Canvas* const canvas, InputTextSceneState* text_input_state) { view_dispatcher_enable_queue(view_dispatcher);
view_draw(text_input_state->text_input_view, canvas); view_dispatcher_add_view(view_dispatcher, 0, text_input_get_view(text_input));
}
bool totp_input_text_handle_event(PluginEvent* const event, InputTextSceneState* text_input_state) { view_dispatcher_attach_to_gui(view_dispatcher, gui, ViewDispatcherTypeFullscreen);
if(event->type == EventTypeKey) {
view_input(text_input_state->text_input_view, &event->input);
}
return true; view_dispatcher_set_navigation_event_callback(view_dispatcher, &back_event_callback);
} view_dispatcher_set_event_callback_context(view_dispatcher, &context);
view_dispatcher_switch_to_view(view_dispatcher, 0);
void totp_input_text_free(InputTextSceneState* state) { view_dispatcher_run(view_dispatcher);
text_input_free(state->text_input);
free(state); view_dispatcher_remove_view(view_dispatcher, 0);
view_dispatcher_free(view_dispatcher);
text_input_free(text_input);
} }

View File

@@ -1,36 +1,13 @@
#pragma once #pragma once
#include <gui/gui.h> #include <gui/gui.h>
#include <gui/view.h>
#include <gui/modules/text_input.h>
#include "../../../types/plugin_state.h"
#include "../../../types/plugin_event.h"
#define INPUT_BUFFER_SIZE (255) #define INPUT_BUFFER_SIZE (255)
typedef struct { typedef struct {
char* user_input; char user_input[INPUT_BUFFER_SIZE];
size_t user_input_length; size_t user_input_length;
void* callback_data; bool success;
} InputTextSceneCallbackResult; } InputTextResult;
typedef void (*InputTextSceneCallback)(InputTextSceneCallbackResult* result); void totp_input_text(Gui* gui, const char* header_text, InputTextResult* result);
typedef struct {
InputTextSceneCallback callback;
char* header_text;
void* callback_data;
} InputTextSceneContext;
typedef struct {
TextInput* text_input;
View* text_input_view;
char text_input_buffer[INPUT_BUFFER_SIZE];
InputTextSceneCallback callback;
void* callback_data;
} InputTextSceneState;
InputTextSceneState* totp_input_text_activate(InputTextSceneContext* context);
void totp_input_text_render(Canvas* const canvas, InputTextSceneState* text_input_state);
bool totp_input_text_handle_event(PluginEvent* const event, InputTextSceneState* text_input_state);
void totp_input_text_free(InputTextSceneState* state);

View File

@@ -13,9 +13,9 @@
char* TOKEN_ALGO_LIST[] = {"SHA1", "SHA256", "SHA512", "Steam"}; char* TOKEN_ALGO_LIST[] = {"SHA1", "SHA256", "SHA512", "Steam"};
char* TOKEN_DIGITS_TEXT_LIST[] = {"5 digits", "6 digits", "8 digits"}; char* TOKEN_DIGITS_TEXT_LIST[] = {"5 digits", "6 digits", "8 digits"};
TokenDigitsCount TOKEN_DIGITS_VALUE_LIST[] = { TokenDigitsCount TOKEN_DIGITS_VALUE_LIST[] = {
TotpFiveDigitsCount, TokenDigitsCountFive,
TotpSixDigitsCount, TokenDigitsCountSix,
TotpEightDigitsCount}; TokenDigitsCountEight};
typedef enum { typedef enum {
TokenNameTextBox, TokenNameTextBox,
@@ -33,10 +33,6 @@ typedef struct {
size_t token_secret_length; size_t token_secret_length;
bool saved; bool saved;
Control selected_control; Control selected_control;
InputTextSceneContext* token_name_input_context;
InputTextSceneContext* token_secret_input_context;
InputTextSceneState* input_state;
bool text_input_mode;
int16_t screen_y_offset; int16_t screen_y_offset;
TokenHashAlgo algo; TokenHashAlgo algo;
uint8_t digits_count_index; uint8_t digits_count_index;
@@ -51,24 +47,6 @@ struct TotpAddContext {
enum TotpIteratorUpdateTokenResultsEx { TotpIteratorUpdateTokenResultInvalidSecret = 1 }; enum TotpIteratorUpdateTokenResultsEx { TotpIteratorUpdateTokenResultInvalidSecret = 1 };
static void on_token_name_user_comitted(InputTextSceneCallbackResult* result) {
SceneState* scene_state = result->callback_data;
free(scene_state->token_name);
scene_state->token_name = result->user_input;
scene_state->token_name_length = result->user_input_length;
scene_state->text_input_mode = false;
free(result);
}
static void on_token_secret_user_comitted(InputTextSceneCallbackResult* result) {
SceneState* scene_state = result->callback_data;
free(scene_state->token_secret);
scene_state->token_secret = result->user_input;
scene_state->token_secret_length = result->user_input_length;
scene_state->text_input_mode = false;
free(result);
}
static void update_duration_text(SceneState* scene_state) { static void update_duration_text(SceneState* scene_state) {
furi_string_printf(scene_state->duration_text, "%d sec.", scene_state->duration); furi_string_printf(scene_state->duration_text, "%d sec.", scene_state->duration);
} }
@@ -95,6 +73,26 @@ static TotpIteratorUpdateTokenResult add_token_handler(TokenInfo* tokenInfo, con
return TotpIteratorUpdateTokenResultSuccess; return TotpIteratorUpdateTokenResultSuccess;
} }
static void ask_user_input(
const PluginState* plugin_state,
const char* header,
char** user_input,
size_t* user_input_length) {
InputTextResult input_result;
if(*user_input != NULL) {
strlcpy(input_result.user_input, *user_input, INPUT_BUFFER_SIZE);
}
totp_input_text(plugin_state->gui, header, &input_result);
if(input_result.success) {
if(*user_input != NULL) {
free(*user_input);
}
*user_input = strdup(input_result.user_input);
*user_input_length = input_result.user_input_length;
}
}
void totp_scene_add_new_token_activate(PluginState* plugin_state) { void totp_scene_add_new_token_activate(PluginState* plugin_state) {
SceneState* scene_state = malloc(sizeof(SceneState)); SceneState* scene_state = malloc(sizeof(SceneState));
furi_check(scene_state != NULL); furi_check(scene_state != NULL);
@@ -104,34 +102,17 @@ void totp_scene_add_new_token_activate(PluginState* plugin_state) {
scene_state->token_secret = "Secret"; scene_state->token_secret = "Secret";
scene_state->token_secret_length = strlen(scene_state->token_secret); scene_state->token_secret_length = strlen(scene_state->token_secret);
scene_state->token_name_input_context = malloc(sizeof(InputTextSceneContext));
furi_check(scene_state->token_name_input_context != NULL);
scene_state->token_name_input_context->header_text = "Enter token name";
scene_state->token_name_input_context->callback_data = scene_state;
scene_state->token_name_input_context->callback = on_token_name_user_comitted;
scene_state->token_secret_input_context = malloc(sizeof(InputTextSceneContext));
furi_check(scene_state->token_secret_input_context != NULL);
scene_state->token_secret_input_context->header_text = "Enter token secret";
scene_state->token_secret_input_context->callback_data = scene_state;
scene_state->token_secret_input_context->callback = on_token_secret_user_comitted;
scene_state->screen_y_offset = 0; scene_state->screen_y_offset = 0;
scene_state->digits_count_index = 1; scene_state->digits_count_index = 1;
scene_state->input_state = NULL; scene_state->duration = TokenDurationDefault;
scene_state->duration = TOTP_TOKEN_DURATION_DEFAULT;
scene_state->duration_text = furi_string_alloc(); scene_state->duration_text = furi_string_alloc();
update_duration_text(scene_state); update_duration_text(scene_state);
} }
void totp_scene_add_new_token_render(Canvas* const canvas, PluginState* plugin_state) { void totp_scene_add_new_token_render(Canvas* const canvas, const PluginState* plugin_state) {
SceneState* scene_state = plugin_state->current_scene_state; const SceneState* scene_state = plugin_state->current_scene_state;
if(scene_state->text_input_mode) {
totp_input_text_render(canvas, scene_state->input_state);
return;
}
ui_control_text_box_render( ui_control_text_box_render(
canvas, canvas,
@@ -195,31 +176,15 @@ void update_screen_y_offset(SceneState* scene_state) {
} }
} }
bool totp_scene_add_new_token_handle_event(PluginEvent* const event, PluginState* plugin_state) { bool totp_scene_add_new_token_handle_event(
const PluginEvent* const event,
PluginState* plugin_state) {
if(event->type != EventTypeKey) { if(event->type != EventTypeKey) {
return true; return true;
} }
SceneState* scene_state = plugin_state->current_scene_state; SceneState* scene_state = plugin_state->current_scene_state;
if(event->input.type == InputTypeLong && event->input.key == InputKeyBack) {
if(scene_state->text_input_mode) {
scene_state->text_input_mode = false;
} else {
return false;
}
}
if(scene_state->text_input_mode) {
if(event->input.type == InputTypeShort && event->input.key == InputKeyBack) {
PluginEvent long_back_cb_evt = {
.type = event->type, .input.key = InputKeyBack, .input.type = InputTypeLong};
return totp_input_text_handle_event(&long_back_cb_evt, scene_state->input_state);
}
return totp_input_text_handle_event(event, scene_state->input_state);
}
if(event->input.type == InputTypePress) { if(event->input.type == InputTypePress) {
switch(event->input.key) { switch(event->input.key) {
case InputKeyUp: case InputKeyUp:
@@ -243,7 +208,11 @@ bool totp_scene_add_new_token_handle_event(PluginEvent* const event, PluginState
case InputKeyRight: case InputKeyRight:
if(scene_state->selected_control == TokenAlgoSelect) { if(scene_state->selected_control == TokenAlgoSelect) {
totp_roll_value_uint8_t( totp_roll_value_uint8_t(
&scene_state->algo, 1, SHA1, STEAM, RollOverflowBehaviorRoll); &scene_state->algo,
1,
TokenHashAlgoSha1,
TokenHashAlgoSteam,
RollOverflowBehaviorRoll);
} else if(scene_state->selected_control == TokenLengthSelect) { } else if(scene_state->selected_control == TokenLengthSelect) {
totp_roll_value_uint8_t( totp_roll_value_uint8_t(
&scene_state->digits_count_index, 1, 0, 2, RollOverflowBehaviorRoll); &scene_state->digits_count_index, 1, 0, 2, RollOverflowBehaviorRoll);
@@ -256,7 +225,11 @@ bool totp_scene_add_new_token_handle_event(PluginEvent* const event, PluginState
case InputKeyLeft: case InputKeyLeft:
if(scene_state->selected_control == TokenAlgoSelect) { if(scene_state->selected_control == TokenAlgoSelect) {
totp_roll_value_uint8_t( totp_roll_value_uint8_t(
&scene_state->algo, -1, SHA1, STEAM, RollOverflowBehaviorRoll); &scene_state->algo,
-1,
TokenHashAlgoSha1,
TokenHashAlgoSteam,
RollOverflowBehaviorRoll);
} else if(scene_state->selected_control == TokenLengthSelect) { } else if(scene_state->selected_control == TokenLengthSelect) {
totp_roll_value_uint8_t( totp_roll_value_uint8_t(
&scene_state->digits_count_index, -1, 0, 2, RollOverflowBehaviorRoll); &scene_state->digits_count_index, -1, 0, 2, RollOverflowBehaviorRoll);
@@ -277,22 +250,18 @@ bool totp_scene_add_new_token_handle_event(PluginEvent* const event, PluginState
} else if(event->input.type == InputTypeRelease && event->input.key == InputKeyOk) { } else if(event->input.type == InputTypeRelease && event->input.key == InputKeyOk) {
switch(scene_state->selected_control) { switch(scene_state->selected_control) {
case TokenNameTextBox: case TokenNameTextBox:
if(scene_state->input_state != NULL) { ask_user_input(
totp_input_text_free(scene_state->input_state); plugin_state,
} "Token name",
scene_state->input_state = &scene_state->token_name,
totp_input_text_activate(scene_state->token_name_input_context); &scene_state->token_name_length);
scene_state->text_input_mode = true;
break; break;
case TokenSecretTextBox: case TokenSecretTextBox:
if(scene_state->input_state != NULL) { ask_user_input(
totp_input_text_free(scene_state->input_state); plugin_state,
} "Token secret",
scene_state->input_state = &scene_state->token_secret,
totp_input_text_activate(scene_state->token_secret_input_context); &scene_state->token_secret_length);
scene_state->text_input_mode = true;
break; break;
case TokenAlgoSelect: case TokenAlgoSelect:
break; break;
@@ -344,18 +313,8 @@ void totp_scene_add_new_token_deactivate(PluginState* plugin_state) {
free(scene_state->token_name); free(scene_state->token_name);
free(scene_state->token_secret); free(scene_state->token_secret);
free(scene_state->token_name_input_context->header_text);
free(scene_state->token_name_input_context);
free(scene_state->token_secret_input_context->header_text);
free(scene_state->token_secret_input_context);
furi_string_free(scene_state->duration_text); furi_string_free(scene_state->duration_text);
if(scene_state->input_state != NULL) {
totp_input_text_free(scene_state->input_state);
}
free(plugin_state->current_scene_state); free(plugin_state->current_scene_state);
plugin_state->current_scene_state = NULL; plugin_state->current_scene_state = NULL;
} }

View File

@@ -5,6 +5,8 @@
#include "../../../types/plugin_event.h" #include "../../../types/plugin_event.h"
void totp_scene_add_new_token_activate(PluginState* plugin_state); void totp_scene_add_new_token_activate(PluginState* plugin_state);
void totp_scene_add_new_token_render(Canvas* const canvas, PluginState* plugin_state); void totp_scene_add_new_token_render(Canvas* const canvas, const PluginState* plugin_state);
bool totp_scene_add_new_token_handle_event(PluginEvent* const event, PluginState* plugin_state); bool totp_scene_add_new_token_handle_event(
const PluginEvent* const event,
PluginState* plugin_state);
void totp_scene_add_new_token_deactivate(PluginState* plugin_state); void totp_scene_add_new_token_deactivate(PluginState* plugin_state);

View File

@@ -1,6 +1,8 @@
#include "totp_app_settings.h" #include "totp_app_settings.h"
#include <math.h> #include <math.h>
#include <totp_icons.h> #include <totp_icons.h>
#include <available_fonts.h>
#include "../../canvas_extensions.h"
#include "../../ui_controls.h" #include "../../ui_controls.h"
#include "../../common_dialogs.h" #include "../../common_dialogs.h"
#include "../../scene_director.h" #include "../../scene_director.h"
@@ -14,18 +16,20 @@
#include "../../../workers/bt_type_code/bt_type_code.h" #include "../../../workers/bt_type_code/bt_type_code.h"
#endif #endif
char* YES_NO_LIST[] = {"NO", "YES"}; static const char* YES_NO_LIST[] = {"NO", "YES"};
char* ON_OFF_LIST[] = {"OFF", "ON"}; static const char* ON_OFF_LIST[] = {"OFF", "ON"};
static const char* FONT_TEST_STR = "0123BCD";
static const uint8_t FONT_TEST_STR_LENGTH = 7;
typedef enum { typedef enum {
HoursInput, HoursInput,
MinutesInput, MinutesInput,
Sound, FontSelect,
Vibro, SoundSwitch,
FontSelector, VibroSwitch,
BadUsb, BadUsbSwitch,
#ifdef TOTP_BADBT_TYPE_ENABLED #ifdef TOTP_BADBT_TYPE_ENABLED
BadBt, BadBtSwitch,
#endif #endif
ConfirmButton ConfirmButton
} Control; } Control;
@@ -35,13 +39,13 @@ typedef struct {
uint8_t tz_offset_minutes; uint8_t tz_offset_minutes;
bool notification_sound; bool notification_sound;
bool notification_vibro; bool notification_vibro;
uint8_t selected_font;
bool badusb_enabled; bool badusb_enabled;
#ifdef TOTP_BADBT_TYPE_ENABLED #ifdef TOTP_BADBT_TYPE_ENABLED
bool badbt_enabled; bool badbt_enabled;
#endif #endif
uint8_t y_offset; uint8_t y_offset;
Control selected_control; Control selected_control;
uint8_t active_font;
} SceneState; } SceneState;
void totp_scene_app_settings_activate(PluginState* plugin_state) { void totp_scene_app_settings_activate(PluginState* plugin_state) {
@@ -56,10 +60,10 @@ void totp_scene_app_settings_activate(PluginState* plugin_state) {
scene_state->notification_sound = plugin_state->notification_method & NotificationMethodSound; scene_state->notification_sound = plugin_state->notification_method & NotificationMethodSound;
scene_state->notification_vibro = plugin_state->notification_method & NotificationMethodVibro; scene_state->notification_vibro = plugin_state->notification_method & NotificationMethodVibro;
scene_state->badusb_enabled = plugin_state->automation_method & AutomationMethodBadUsb; scene_state->badusb_enabled = plugin_state->automation_method & AutomationMethodBadUsb;
scene_state->selected_font = plugin_state->selected_font;
#ifdef TOTP_BADBT_TYPE_ENABLED #ifdef TOTP_BADBT_TYPE_ENABLED
scene_state->badbt_enabled = plugin_state->automation_method & AutomationMethodBadBt; scene_state->badbt_enabled = plugin_state->automation_method & AutomationMethodBadBt;
#endif #endif
scene_state->active_font = plugin_state->active_font_index;
} }
static void two_digit_to_str(int8_t num, char* str) { static void two_digit_to_str(int8_t num, char* str) {
@@ -113,75 +117,87 @@ void totp_scene_app_settings_render(Canvas* const canvas, const PluginState* plu
&I_totp_arrow_bottom_10x5); &I_totp_arrow_bottom_10x5);
canvas_set_font(canvas, FontPrimary); canvas_set_font(canvas, FontPrimary);
canvas_draw_str_aligned( canvas_draw_str_aligned(canvas, 0, 64 - scene_state->y_offset, AlignLeft, AlignTop, "Font");
canvas, 0, 64 - scene_state->y_offset, AlignLeft, AlignTop, "Notifications / UI");
canvas_set_font(canvas, FontSecondary); canvas_set_font(canvas, FontSecondary);
canvas_draw_str_aligned(canvas, 0, 78 - scene_state->y_offset, AlignLeft, AlignTop, "Sound:"); const FONT_INFO* const font = available_fonts[scene_state->active_font];
ui_control_select_render( ui_control_select_render(
canvas, canvas,
36, 0,
71 - scene_state->y_offset, 74 - scene_state->y_offset,
SCREEN_WIDTH - 36, SCREEN_WIDTH,
YES_NO_LIST[scene_state->notification_sound], font->name,
scene_state->selected_control == Sound); scene_state->selected_control == FontSelect);
canvas_draw_str_aligned(canvas, 0, 94 - scene_state->y_offset, AlignLeft, AlignTop, "Vibro:"); uint8_t font_x_offset =
ui_control_select_render( SCREEN_WIDTH_CENTER -
canvas, (((font->charInfo[0].width + font->spacePixels) * FONT_TEST_STR_LENGTH) >> 1);
36, uint8_t font_y_offset = 108 - scene_state->y_offset - (font->height >> 1);
87 - scene_state->y_offset, canvas_draw_str_ex(
SCREEN_WIDTH - 36, canvas, font_x_offset, font_y_offset, FONT_TEST_STR, FONT_TEST_STR_LENGTH, font);
YES_NO_LIST[scene_state->notification_vibro],
scene_state->selected_control == Vibro);
two_digit_to_str(scene_state->selected_font, &tmp_str[0]);
canvas_draw_str_aligned(
canvas, 0, 110 - scene_state->y_offset, AlignLeft, AlignTop, "UI Font:");
ui_control_select_render(
canvas,
36,
103 - scene_state->y_offset,
SCREEN_WIDTH - 36,
&tmp_str[0],
scene_state->selected_control == FontSelector);
canvas_draw_icon( canvas_draw_icon(
canvas, SCREEN_WIDTH_CENTER - 5, 123 - scene_state->y_offset, &I_totp_arrow_bottom_10x5); canvas, SCREEN_WIDTH_CENTER - 5, 123 - scene_state->y_offset, &I_totp_arrow_bottom_10x5);
canvas_set_font(canvas, FontPrimary); canvas_set_font(canvas, FontPrimary);
canvas_draw_str_aligned( canvas_draw_str_aligned(
canvas, 0, 128 - scene_state->y_offset, AlignLeft, AlignTop, "Automation"); canvas, 0, 128 - scene_state->y_offset, AlignLeft, AlignTop, "Notifications");
canvas_set_font(canvas, FontSecondary); canvas_set_font(canvas, FontSecondary);
canvas_draw_str_aligned( canvas_draw_str_aligned(canvas, 0, 145 - scene_state->y_offset, AlignLeft, AlignTop, "Sound:");
canvas, 0, 145 - scene_state->y_offset, AlignLeft, AlignTop, "BadUSB:");
ui_control_select_render( ui_control_select_render(
canvas, canvas,
36, 36,
138 - scene_state->y_offset, 138 - scene_state->y_offset,
SCREEN_WIDTH - 36, SCREEN_WIDTH - 36,
ON_OFF_LIST[scene_state->badusb_enabled], YES_NO_LIST[scene_state->notification_sound],
scene_state->selected_control == BadUsb); scene_state->selected_control == SoundSwitch);
#ifdef TOTP_BADBT_TYPE_ENABLED canvas_draw_str_aligned(canvas, 0, 163 - scene_state->y_offset, AlignLeft, AlignTop, "Vibro:");
canvas_draw_str_aligned(canvas, 0, 163 - scene_state->y_offset, AlignLeft, AlignTop, "BadBT:");
ui_control_select_render( ui_control_select_render(
canvas, canvas,
36, 36,
156 - scene_state->y_offset, 156 - scene_state->y_offset,
SCREEN_WIDTH - 36, SCREEN_WIDTH - 36,
YES_NO_LIST[scene_state->notification_vibro],
scene_state->selected_control == VibroSwitch);
canvas_draw_icon(
canvas, SCREEN_WIDTH_CENTER - 5, 187 - scene_state->y_offset, &I_totp_arrow_bottom_10x5);
canvas_set_font(canvas, FontPrimary);
canvas_draw_str_aligned(
canvas, 0, 192 - scene_state->y_offset, AlignLeft, AlignTop, "Automation");
canvas_set_font(canvas, FontSecondary);
canvas_draw_str_aligned(
canvas, 0, 209 - scene_state->y_offset, AlignLeft, AlignTop, "BadUSB:");
ui_control_select_render(
canvas,
36,
202 - scene_state->y_offset,
SCREEN_WIDTH - 36,
ON_OFF_LIST[scene_state->badusb_enabled],
scene_state->selected_control == BadUsbSwitch);
#ifdef TOTP_BADBT_TYPE_ENABLED
canvas_draw_str_aligned(canvas, 0, 227 - scene_state->y_offset, AlignLeft, AlignTop, "BadBT:");
ui_control_select_render(
canvas,
36,
220 - scene_state->y_offset,
SCREEN_WIDTH - 36,
ON_OFF_LIST[scene_state->badbt_enabled], ON_OFF_LIST[scene_state->badbt_enabled],
scene_state->selected_control == BadBt); scene_state->selected_control == BadBtSwitch);
#endif #endif
ui_control_button_render( ui_control_button_render(
canvas, canvas,
SCREEN_WIDTH_CENTER - 24, SCREEN_WIDTH_CENTER - 24,
#ifdef TOTP_BADBT_TYPE_ENABLED #ifdef TOTP_BADBT_TYPE_ENABLED
178 - scene_state->y_offset, 242 - scene_state->y_offset,
#else #else
165 - scene_state->y_offset, 229 - scene_state->y_offset,
#endif #endif
48, 48,
13, 13,
@@ -206,10 +222,12 @@ bool totp_scene_app_settings_handle_event(
HoursInput, HoursInput,
ConfirmButton, ConfirmButton,
RollOverflowBehaviorStop); RollOverflowBehaviorStop);
if(scene_state->selected_control > FontSelector) { if(scene_state->selected_control > VibroSwitch) {
scene_state->y_offset = 128; scene_state->y_offset = SCREEN_HEIGHT * 3;
} else if(scene_state->selected_control > FontSelect) {
scene_state->y_offset = SCREEN_HEIGHT * 2;
} else if(scene_state->selected_control > MinutesInput) { } else if(scene_state->selected_control > MinutesInput) {
scene_state->y_offset = 64; scene_state->y_offset = SCREEN_HEIGHT;
} else { } else {
scene_state->y_offset = 0; scene_state->y_offset = 0;
} }
@@ -221,10 +239,12 @@ bool totp_scene_app_settings_handle_event(
HoursInput, HoursInput,
ConfirmButton, ConfirmButton,
RollOverflowBehaviorStop); RollOverflowBehaviorStop);
if(scene_state->selected_control > FontSelector) { if(scene_state->selected_control > VibroSwitch) {
scene_state->y_offset = 128; scene_state->y_offset = SCREEN_HEIGHT * 3;
} else if(scene_state->selected_control > FontSelect) {
scene_state->y_offset = SCREEN_HEIGHT * 2;
} else if(scene_state->selected_control > MinutesInput) { } else if(scene_state->selected_control > MinutesInput) {
scene_state->y_offset = 64; scene_state->y_offset = SCREEN_HEIGHT;
} else { } else {
scene_state->y_offset = 0; scene_state->y_offset = 0;
} }
@@ -236,22 +256,25 @@ bool totp_scene_app_settings_handle_event(
} else if(scene_state->selected_control == MinutesInput) { } else if(scene_state->selected_control == MinutesInput) {
totp_roll_value_uint8_t( totp_roll_value_uint8_t(
&scene_state->tz_offset_minutes, 15, 0, 45, RollOverflowBehaviorRoll); &scene_state->tz_offset_minutes, 15, 0, 45, RollOverflowBehaviorRoll);
} else if(scene_state->selected_control == Sound) { } else if(scene_state->selected_control == FontSelect) {
totp_roll_value_uint8_t(
&scene_state->active_font,
1,
0,
AVAILABLE_FONTS_COUNT - 1,
RollOverflowBehaviorRoll);
} else if(scene_state->selected_control == SoundSwitch) {
scene_state->notification_sound = !scene_state->notification_sound; scene_state->notification_sound = !scene_state->notification_sound;
} else if(scene_state->selected_control == Vibro) { } else if(scene_state->selected_control == VibroSwitch) {
scene_state->notification_vibro = !scene_state->notification_vibro; scene_state->notification_vibro = !scene_state->notification_vibro;
} else if(scene_state->selected_control == BadUsb) { } else if(scene_state->selected_control == BadUsbSwitch) {
scene_state->badusb_enabled = !scene_state->badusb_enabled; scene_state->badusb_enabled = !scene_state->badusb_enabled;
} }
#ifdef TOTP_BADBT_TYPE_ENABLED #ifdef TOTP_BADBT_TYPE_ENABLED
else if(scene_state->selected_control == BadBt) { else if(scene_state->selected_control == BadBtSwitch) {
scene_state->badbt_enabled = !scene_state->badbt_enabled; scene_state->badbt_enabled = !scene_state->badbt_enabled;
} }
#endif #endif
else if(scene_state->selected_control == FontSelector) {
totp_roll_value_uint8_t(
&scene_state->selected_font, 1, 0, MAX_CUSTOM_FONTS, RollOverflowBehaviorStop);
}
break; break;
case InputKeyLeft: case InputKeyLeft:
if(scene_state->selected_control == HoursInput) { if(scene_state->selected_control == HoursInput) {
@@ -260,22 +283,25 @@ bool totp_scene_app_settings_handle_event(
} else if(scene_state->selected_control == MinutesInput) { } else if(scene_state->selected_control == MinutesInput) {
totp_roll_value_uint8_t( totp_roll_value_uint8_t(
&scene_state->tz_offset_minutes, -15, 0, 45, RollOverflowBehaviorRoll); &scene_state->tz_offset_minutes, -15, 0, 45, RollOverflowBehaviorRoll);
} else if(scene_state->selected_control == Sound) { } else if(scene_state->selected_control == FontSelect) {
totp_roll_value_uint8_t(
&scene_state->active_font,
-1,
0,
AVAILABLE_FONTS_COUNT - 1,
RollOverflowBehaviorRoll);
} else if(scene_state->selected_control == SoundSwitch) {
scene_state->notification_sound = !scene_state->notification_sound; scene_state->notification_sound = !scene_state->notification_sound;
} else if(scene_state->selected_control == Vibro) { } else if(scene_state->selected_control == VibroSwitch) {
scene_state->notification_vibro = !scene_state->notification_vibro; scene_state->notification_vibro = !scene_state->notification_vibro;
} else if(scene_state->selected_control == BadUsb) { } else if(scene_state->selected_control == BadUsbSwitch) {
scene_state->badusb_enabled = !scene_state->badusb_enabled; scene_state->badusb_enabled = !scene_state->badusb_enabled;
} }
#ifdef TOTP_BADBT_TYPE_ENABLED #ifdef TOTP_BADBT_TYPE_ENABLED
else if(scene_state->selected_control == BadBt) { else if(scene_state->selected_control == BadBtSwitch) {
scene_state->badbt_enabled = !scene_state->badbt_enabled; scene_state->badbt_enabled = !scene_state->badbt_enabled;
} }
#endif #endif
else if(scene_state->selected_control == FontSelector) {
totp_roll_value_uint8_t(
&scene_state->selected_font, -1, 0, MAX_CUSTOM_FONTS, RollOverflowBehaviorStop);
}
break; break;
case InputKeyOk: case InputKeyOk:
break; break;
@@ -302,7 +328,8 @@ bool totp_scene_app_settings_handle_event(
plugin_state->automation_method |= scene_state->badbt_enabled ? AutomationMethodBadBt : plugin_state->automation_method |= scene_state->badbt_enabled ? AutomationMethodBadBt :
AutomationMethodNone; AutomationMethodNone;
#endif #endif
plugin_state->selected_font = scene_state->selected_font;
plugin_state->active_font_index = scene_state->active_font;
if(!totp_config_file_update_user_settings(plugin_state)) { if(!totp_config_file_update_user_settings(plugin_state)) {
totp_dialogs_config_updating_error(plugin_state); totp_dialogs_config_updating_error(plugin_state);

View File

@@ -3,7 +3,9 @@
#include <notification/notification_messages.h> #include <notification/notification_messages.h>
#include <totp_icons.h> #include <totp_icons.h>
#include <roll_value.h> #include <roll_value.h>
#include <available_fonts.h>
#include "totp_scene_generate_token.h" #include "totp_scene_generate_token.h"
#include "../../canvas_extensions.h"
#include "../../../types/token_info.h" #include "../../../types/token_info.h"
#include "../../../types/common.h" #include "../../../types/common.h"
#include "../../constants.h" #include "../../constants.h"
@@ -16,7 +18,6 @@
#ifdef TOTP_BADBT_TYPE_ENABLED #ifdef TOTP_BADBT_TYPE_ENABLED
#include "../../../workers/bt_type_code/bt_type_code.h" #include "../../../workers/bt_type_code/bt_type_code.h"
#endif #endif
#include "../../fonts/active_font.h"
#define PROGRESS_BAR_MARGIN (3) #define PROGRESS_BAR_MARGIN (3)
#define PROGRESS_BAR_HEIGHT (4) #define PROGRESS_BAR_HEIGHT (4)
@@ -26,18 +27,18 @@ typedef struct {
uint8_t progress_bar_width; uint8_t progress_bar_width;
uint8_t code_total_length; uint8_t code_total_length;
uint8_t code_offset_x; uint8_t code_offset_x;
uint8_t code_offset_x_inc;
uint8_t code_offset_y; uint8_t code_offset_y;
} UiPrecalculatedDimensions; } UiPrecalculatedDimensions;
typedef struct { typedef struct {
char last_code[TOTP_TOKEN_DIGITS_MAX_COUNT + 1]; char last_code[TokenDigitsCountMax + 1];
TotpUsbTypeCodeWorkerContext* usb_type_code_worker_context; TotpUsbTypeCodeWorkerContext* usb_type_code_worker_context;
NotificationMessage const** notification_sequence_new_token; NotificationMessage const** notification_sequence_new_token;
NotificationMessage const** notification_sequence_automation; NotificationMessage const** notification_sequence_automation;
FuriMutex* last_code_update_sync; FuriMutex* last_code_update_sync;
TotpGenerateCodeWorkerContext* generate_code_worker_context; TotpGenerateCodeWorkerContext* generate_code_worker_context;
UiPrecalculatedDimensions ui_precalculated_dimensions; UiPrecalculatedDimensions ui_precalculated_dimensions;
const FONT_INFO* active_font;
} SceneState; } SceneState;
static const NotificationSequence* static const NotificationSequence*
@@ -141,60 +142,14 @@ static void draw_totp_code(Canvas* const canvas, const PluginState* const plugin
const TokenInfoIteratorContext* iterator_context = const TokenInfoIteratorContext* iterator_context =
totp_config_get_token_iterator_context(plugin_state); totp_config_get_token_iterator_context(plugin_state);
uint8_t code_length = totp_token_info_iterator_get_current_token(iterator_context)->digits; uint8_t code_length = totp_token_info_iterator_get_current_token(iterator_context)->digits;
uint8_t offset_x = scene_state->ui_precalculated_dimensions.code_offset_x;
const FONT_INFO* current_font;
switch(plugin_state->selected_font) {
case 0:
current_font = &modeNine_15ptFontInfo;
break;
case 1:
current_font = &redHatMono_16ptFontInfo;
break;
case 2:
current_font = &bedstead_17ptFontInfo;
break;
case 3:
current_font = &zector_18ptFontInfo;
break;
case 4:
current_font = &_712Serif_24ptFontInfo;
break;
case 5:
current_font = &graph35pix_12ptFontInfo;
break;
case 6:
current_font = &karmaFuture_14ptFontInfo;
break;
case 7:
current_font = &funclimbingDemo_18ptFontInfo;
break;
case 8:
current_font = &dPComic_18ptFontInfo;
break;
case 9:
current_font = &pixelFlag_18ptFontInfo;
break;
default:
current_font = &modeNine_15ptFontInfo;
break;
}
uint8_t char_width = current_font->charInfo[0].width;
uint8_t offset_x_inc = scene_state->ui_precalculated_dimensions.code_offset_x_inc;
for(uint8_t i = 0; i < code_length; i++) {
char ch = scene_state->last_code[i];
if(ch >= current_font->startChar && ch <= current_font->endChar) {
uint8_t char_index = ch - current_font->startChar;
canvas_draw_xbm(
canvas,
offset_x,
scene_state->ui_precalculated_dimensions.code_offset_y,
char_width,
current_font->height,
&current_font->data[current_font->charInfo[char_index].offset]);
}
offset_x += offset_x_inc; canvas_draw_str_ex(
} canvas,
scene_state->ui_precalculated_dimensions.code_offset_x,
scene_state->ui_precalculated_dimensions.code_offset_y,
scene_state->last_code,
code_length,
scene_state->active_font);
} }
static void on_new_token_code_generated(bool time_left, void* context) { static void on_new_token_code_generated(bool time_left, void* context) {
@@ -207,53 +162,15 @@ static void on_new_token_code_generated(bool time_left, void* context) {
SceneState* scene_state = plugin_state->current_scene_state; SceneState* scene_state = plugin_state->current_scene_state;
const TokenInfo* current_token = totp_token_info_iterator_get_current_token(iterator_context); const TokenInfo* current_token = totp_token_info_iterator_get_current_token(iterator_context);
const FONT_INFO* const font = scene_state->active_font;
const FONT_INFO* current_font; uint8_t char_width = font->charInfo[0].width;
switch(plugin_state->selected_font) {
case 0:
current_font = &modeNine_15ptFontInfo;
break;
case 1:
current_font = &redHatMono_16ptFontInfo;
break;
case 2:
current_font = &bedstead_17ptFontInfo;
break;
case 3:
current_font = &zector_18ptFontInfo;
break;
case 4:
current_font = &_712Serif_24ptFontInfo;
break;
case 5:
current_font = &graph35pix_12ptFontInfo;
break;
case 6:
current_font = &karmaFuture_14ptFontInfo;
break;
case 7:
current_font = &funclimbingDemo_18ptFontInfo;
break;
case 8:
current_font = &dPComic_18ptFontInfo;
break;
case 9:
current_font = &pixelFlag_18ptFontInfo;
break;
default:
current_font = &modeNine_15ptFontInfo;
break;
}
uint8_t char_width = current_font->charInfo[0].width;
scene_state->ui_precalculated_dimensions.code_total_length = scene_state->ui_precalculated_dimensions.code_total_length =
current_token->digits * (char_width + current_font->spacePixels); current_token->digits * (char_width + font->spacePixels);
scene_state->ui_precalculated_dimensions.code_offset_x = scene_state->ui_precalculated_dimensions.code_offset_x =
(SCREEN_WIDTH - scene_state->ui_precalculated_dimensions.code_total_length) >> 1; (SCREEN_WIDTH - scene_state->ui_precalculated_dimensions.code_total_length) >> 1;
scene_state->ui_precalculated_dimensions.code_offset_x_inc =
char_width + current_font->spacePixels;
scene_state->ui_precalculated_dimensions.code_offset_y = scene_state->ui_precalculated_dimensions.code_offset_y =
SCREEN_HEIGHT_CENTER - (current_font->height >> 1); SCREEN_HEIGHT_CENTER - (font->height >> 1);
if(time_left) { if(time_left) {
notification_message( notification_message(
@@ -283,11 +200,11 @@ void totp_scene_generate_token_activate(PluginState* plugin_state) {
scene_state->last_code_update_sync = furi_mutex_alloc(FuriMutexTypeNormal); scene_state->last_code_update_sync = furi_mutex_alloc(FuriMutexTypeNormal);
if(plugin_state->automation_method & AutomationMethodBadUsb) { if(plugin_state->automation_method & AutomationMethodBadUsb) {
scene_state->usb_type_code_worker_context = totp_usb_type_code_worker_start( scene_state->usb_type_code_worker_context = totp_usb_type_code_worker_start(
scene_state->last_code, scene_state->last_code, TokenDigitsCountMax + 1, scene_state->last_code_update_sync);
TOTP_TOKEN_DIGITS_MAX_COUNT + 1,
scene_state->last_code_update_sync);
} }
scene_state->active_font = available_fonts[plugin_state->active_font_index];
#ifdef TOTP_BADBT_TYPE_ENABLED #ifdef TOTP_BADBT_TYPE_ENABLED
if(plugin_state->automation_method & AutomationMethodBadBt) { if(plugin_state->automation_method & AutomationMethodBadBt) {
@@ -297,7 +214,7 @@ void totp_scene_generate_token_activate(PluginState* plugin_state) {
totp_bt_type_code_worker_start( totp_bt_type_code_worker_start(
plugin_state->bt_type_code_worker_context, plugin_state->bt_type_code_worker_context,
scene_state->last_code, scene_state->last_code,
TOTP_TOKEN_DIGITS_MAX_COUNT + 1, TokenDigitsCountMax + 1,
scene_state->last_code_update_sync); scene_state->last_code_update_sync);
} }
#endif #endif

View File

@@ -1,7 +1,7 @@
#include "bt_type_code.h" #include "bt_type_code.h"
#include <furi_hal_bt.h>
#include <furi_hal_bt_hid.h> #include <furi_hal_bt_hid.h>
#include <furi_hal_version.h> #include <furi_hal_version.h>
#include <bt/bt_service/bt_i.h>
#include <furi/core/thread.h> #include <furi/core/thread.h>
#include <furi/core/mutex.h> #include <furi/core/mutex.h>
#include <furi/core/string.h> #include <furi/core/string.h>
@@ -13,7 +13,7 @@
#include "../type_code_common.h" #include "../type_code_common.h"
#include "../../features_config.h" #include "../../features_config.h"
#if TOTP_TARGET_FIRMWARE == TOTP_FIRMWARE_UL_XFW #if TOTP_TARGET_FIRMWARE == TOTP_FIRMWARE_XTREME_UL
#define TOTP_BT_WORKER_BT_ADV_NAME_MAX_LEN FURI_HAL_BT_ADV_NAME_LENGTH #define TOTP_BT_WORKER_BT_ADV_NAME_MAX_LEN FURI_HAL_BT_ADV_NAME_LENGTH
#define TOTP_BT_WORKER_BT_MAC_ADDRESS_LEN GAP_MAC_ADDR_SIZE #define TOTP_BT_WORKER_BT_MAC_ADDRESS_LEN GAP_MAC_ADDR_SIZE
#endif #endif
@@ -29,7 +29,7 @@ struct TotpBtTypeCodeWorkerContext {
Bt* bt; Bt* bt;
bool is_advertising; bool is_advertising;
bool is_connected; bool is_connected;
#if TOTP_TARGET_FIRMWARE == TOTP_FIRMWARE_UL_XFW #if TOTP_TARGET_FIRMWARE == TOTP_FIRMWARE_XTREME_UL
char previous_bt_name[TOTP_BT_WORKER_BT_ADV_NAME_MAX_LEN]; char previous_bt_name[TOTP_BT_WORKER_BT_ADV_NAME_MAX_LEN];
uint8_t previous_bt_mac[TOTP_BT_WORKER_BT_MAC_ADDRESS_LEN]; uint8_t previous_bt_mac[TOTP_BT_WORKER_BT_MAC_ADDRESS_LEN];
#endif #endif
@@ -39,7 +39,7 @@ static inline bool totp_type_code_worker_stop_requested() {
return furi_thread_flags_get() & TotpBtTypeCodeWorkerEventStop; return furi_thread_flags_get() & TotpBtTypeCodeWorkerEventStop;
} }
#if TOTP_TARGET_FIRMWARE == TOTP_FIRMWARE_UL_XFW #if TOTP_TARGET_FIRMWARE == TOTP_FIRMWARE_XTREME_UL
static void totp_type_code_worker_bt_set_app_mac(uint8_t* mac) { static void totp_type_code_worker_bt_set_app_mac(uint8_t* mac) {
uint8_t max_i; uint8_t max_i;
size_t uid_size = furi_hal_version_uid_size(); size_t uid_size = furi_hal_version_uid_size();
@@ -49,7 +49,7 @@ static void totp_type_code_worker_bt_set_app_mac(uint8_t* mac) {
max_i = TOTP_BT_WORKER_BT_MAC_ADDRESS_LEN; max_i = TOTP_BT_WORKER_BT_MAC_ADDRESS_LEN;
} }
const uint8_t* uid = furi_hal_version_uid(); const uint8_t* uid = (const uint8_t*)UID64_BASE; //-V566
memcpy(mac, uid, max_i); memcpy(mac, uid, max_i);
for(uint8_t i = max_i; i < TOTP_BT_WORKER_BT_MAC_ADDRESS_LEN; i++) { for(uint8_t i = max_i; i < TOTP_BT_WORKER_BT_MAC_ADDRESS_LEN; i++) {
mac[i] = 0; mac[i] = 0;
@@ -161,7 +161,7 @@ TotpBtTypeCodeWorkerContext* totp_bt_type_code_worker_init() {
furi_delay_ms(200); furi_delay_ms(200);
bt_keys_storage_set_storage_path(context->bt, HID_BT_KEYS_STORAGE_PATH); bt_keys_storage_set_storage_path(context->bt, HID_BT_KEYS_STORAGE_PATH);
#if TOTP_TARGET_FIRMWARE == TOTP_FIRMWARE_UL_XFW #if TOTP_TARGET_FIRMWARE == TOTP_FIRMWARE_XTREME_UL
memcpy( memcpy(
&context->previous_bt_name[0], &context->previous_bt_name[0],
furi_hal_bt_get_profile_adv_name(FuriHalBtProfileHidKeyboard), furi_hal_bt_get_profile_adv_name(FuriHalBtProfileHidKeyboard),
@@ -184,7 +184,7 @@ TotpBtTypeCodeWorkerContext* totp_bt_type_code_worker_init() {
furi_hal_bt_start_advertising(); furi_hal_bt_start_advertising();
#if TOTP_TARGET_FIRMWARE == TOTP_FIRMWARE_UL_XFW #if TOTP_TARGET_FIRMWARE == TOTP_FIRMWARE_XTREME_UL
bt_enable_peer_key_update(context->bt); bt_enable_peer_key_update(context->bt);
#endif #endif
@@ -211,7 +211,7 @@ void totp_bt_type_code_worker_free(TotpBtTypeCodeWorkerContext* context) {
furi_delay_ms(200); furi_delay_ms(200);
bt_keys_storage_set_default_path(context->bt); bt_keys_storage_set_default_path(context->bt);
#if TOTP_TARGET_FIRMWARE == TOTP_FIRMWARE_UL_XFW #if TOTP_TARGET_FIRMWARE == TOTP_FIRMWARE_XTREME_UL
furi_hal_bt_set_profile_adv_name(FuriHalBtProfileHidKeyboard, context->previous_bt_name); furi_hal_bt_set_profile_adv_name(FuriHalBtProfileHidKeyboard, context->previous_bt_name);
furi_hal_bt_set_profile_mac_addr(FuriHalBtProfileHidKeyboard, context->previous_bt_mac); furi_hal_bt_set_profile_mac_addr(FuriHalBtProfileHidKeyboard, context->previous_bt_mac);
#endif #endif

View File

@@ -21,7 +21,7 @@ struct TotpGenerateCodeWorkerContext {
void* on_code_lifetime_changed_handler_context; void* on_code_lifetime_changed_handler_context;
}; };
static const char* STEAM_ALGO_ALPHABET = "23456789BCDFGHJKMNPQRTVWXY"; static const char STEAM_ALGO_ALPHABET[] = "23456789BCDFGHJKMNPQRTVWXY";
static void static void
int_token_to_str(uint64_t i_token_code, char* str, TokenDigitsCount len, TokenHashAlgo algo) { int_token_to_str(uint64_t i_token_code, char* str, TokenDigitsCount len, TokenHashAlgo algo) {
@@ -30,7 +30,7 @@ static void
if(i_token_code == OTP_ERROR) { if(i_token_code == OTP_ERROR) {
memset(str, '-', len); memset(str, '-', len);
} else { } else {
if(algo == STEAM) { if(algo == TokenHashAlgoSteam) {
char* s = str; char* s = str;
for(uint8_t i = 0; i < len; i++, s++) { for(uint8_t i = 0; i < len; i++, s++) {
*s = STEAM_ALGO_ALPHABET[i_token_code % 26]; *s = STEAM_ALGO_ALPHABET[i_token_code % 26];
@@ -48,12 +48,12 @@ static void
static TOTP_ALGO get_totp_algo_impl(TokenHashAlgo algo) { static TOTP_ALGO get_totp_algo_impl(TokenHashAlgo algo) {
switch(algo) { switch(algo) {
case SHA1: case TokenHashAlgoSha1:
case STEAM: case TokenHashAlgoSteam:
return TOTP_ALGO_SHA1; return TOTP_ALGO_SHA1;
case SHA256: case TokenHashAlgoSha256:
return TOTP_ALGO_SHA256; return TOTP_ALGO_SHA256;
case SHA512: case TokenHashAlgoSha512:
return TOTP_ALGO_SHA512; return TOTP_ALGO_SHA512;
default: default:
break; break;

View File

@@ -11,7 +11,7 @@ void infrared_scene_universal_projector_on_enter(void* context) {
infrared_brute_force_set_db_filename(brute_force, EXT_PATH("infrared/assets/projectors.ir")); infrared_brute_force_set_db_filename(brute_force, EXT_PATH("infrared/assets/projectors.ir"));
//TODO Improve Projectors universal remote //TODO Improve Projectors universal remote
button_panel_reserve(button_panel, 2, 2); button_panel_reserve(button_panel, 2, 3);
uint32_t i = 0; uint32_t i = 0;
button_panel_add_item( button_panel_add_item(
button_panel, button_panel,
@@ -61,6 +61,30 @@ void infrared_scene_universal_projector_on_enter(void* context) {
infrared_scene_universal_common_item_callback, infrared_scene_universal_common_item_callback,
context); context);
infrared_brute_force_add_record(brute_force, i++, "Vol_dn"); infrared_brute_force_add_record(brute_force, i++, "Vol_dn");
button_panel_add_item(
button_panel,
i,
0,
2,
3,
101,
&I_Play_25x27,
&I_Play_hvr_25x27,
infrared_scene_universal_common_item_callback,
context);
infrared_brute_force_add_record(brute_force, i++, "Play");
button_panel_add_item(
button_panel,
i,
1,
2,
36,
101,
&I_Pause_25x27,
&I_Pause_hvr_25x27,
infrared_scene_universal_common_item_callback,
context);
infrared_brute_force_add_record(brute_force, i++, "Pause");
button_panel_add_label(button_panel, 10, 11, FontPrimary, "Projector"); button_panel_add_label(button_panel, 10, 11, FontPrimary, "Projector");
button_panel_add_label(button_panel, 17, 60, FontSecondary, "Volume"); button_panel_add_label(button_panel, 17, 60, FontSecondary, "Volume");

View File

@@ -1,7 +1,7 @@
Filetype: IR library file Filetype: IR library file
Version: 1 Version: 1
# Last Updated 24th Jul, 2023 # Last Updated 24th Jul, 2023
# Last Checked 14th Jul, 2023 # Last Checked 24th Jul, 2023
# #
# Model: Electrolux EACM-16 HP/N3 # Model: Electrolux EACM-16 HP/N3
name: Off name: Off

View File

@@ -1,7 +1,7 @@
Filetype: IR library file Filetype: IR library file
Version: 1 Version: 1
# Last Updated 13th Jul, 2023 # Last Updated 24th Jul, 2023
# Last Checked 13th Jul, 2023 # Last Checked 24th Jul, 2023
# #
name: Power name: Power
type: parsed type: parsed
@@ -3728,3 +3728,27 @@ type: parsed
protocol: RC5 protocol: RC5
address: 15 00 00 00 address: 15 00 00 00
command: 35 00 00 00 command: 35 00 00 00
#
name: Mute
type: parsed
protocol: NEC
address: A0 00 00 00
command: 18 00 00 00
#
name: Power
type: parsed
protocol: NEC
address: A0 00 00 00
command: 1D 00 00 00
#
name: Vol_up
type: parsed
protocol: NEC
address: A0 00 00 00
command: 12 00 00 00
#
name: Vol_dn
type: parsed
protocol: NEC
address: A0 00 00 00
command: 0A 00 00 00

View File

@@ -1,7 +1,7 @@
Filetype: IR library file Filetype: IR library file
Version: 1 Version: 1
# Last Updated 13th Jul, 2023 # Last Updated 24th Jul, 2023
# Last Checked 13th Jul, 2023 # Last Checked 24th Jul, 2023
# #
name: Power name: Power
type: raw type: raw
@@ -1881,3 +1881,33 @@ type: parsed
protocol: NEC protocol: NEC
address: 30 00 00 00 address: 30 00 00 00
command: 87 00 00 00 command: 87 00 00 00
#
name: Power
type: raw
frequency: 38000
duty_cycle: 0.330000
data: 1255 435 1257 435 415 1278 1257 440 1256 435 415 1278 415 1278 415 1279 414 1279 414 1279 414 1278 1257 7176 1257 436 1256 435 415 1279 1256 438 1258 437 413 1279 414 1278 415 1278 415 1279 414 1279 414 1278 1257 7174 1256 436 1256 437 413 1278 1257 439 1257 435 415 1278 415 1278 415 1277 416 1279 414 1278 415 1278 1256 7175 1257 435 1257 435 415 1279 1256 440 1256 435 415 1278 415 1278 415 1278 415 1278 415 1280 413 1278 1257
#
name: Speed_up
type: raw
frequency: 38000
duty_cycle: 0.330000
data: 1284 409 1283 408 440 1253 1284 411 1285 407 441 1254 439 1253 440 1253 440 1251 442 1252 1285 409 439 7991 1285 409 1283 408 440 1253 1284 411 1285 407 441 1255 438 1253 440 1252 441 1251 442 1254 1283 407 441 7994 1283 410 1282 409 439 1254 1283 413 1283 409 439 1253 440 1253 440 1253 440 1253 440 1253 1284 407 441 7996 1284 409 1283 408 440 1253 1284 412 1284 408 440 1253 440 1253 440 1251 442 1253 440 1253 1284 409 439 7996 1284 407 1285 408 440 1254 1283 411 1285 409 439 1254 439 1253 440 1252 441 1253 440 1253 1284 408 440 7996 1284 408 1284 409 439 1255 1282 411 1285 408 440 1254 439 1252 441 1252 441 1254 439 1253 1284 407 441
#
name: Mode
type: raw
frequency: 38000
duty_cycle: 0.330000
data: 1251 439 1253 437 414 1282 1252 441 1255 436 415 1279 414 1280 413 1280 413 1279 1255 437 414 1279 414 8020 1253 438 1255 438 413 1281 1253 441 1255 438 413 1280 413 1279 414 1279 414 1280 1254 437 414 1280 413 8024 1253 438 1254 437 414 1281 1253 440 1256 437 414 1279 414 1279 414 1278 415 1280 1254 437 414 1280 413 8023 1254 440 1252 436 415 1279 1255 441 1255 436 415 1279 414 1279 414 1279 414 1279 1255 437 414 1279 414 8024 1253 437 1256 437 414 1280 1254 441 1255 437 414 1278 415 1280 413 1280 413 1280 1254 437 414 1279 414 8023 1254 438 1255 436 415 1280 1255 441 1255 436 415 1279 414 1279 414 1279 414 1280 1254 436 415 1280 413
#
name: Timer
type: raw
frequency: 38000
duty_cycle: 0.330000
data: 1252 437 1255 438 519 1174 1255 441 1255 437 518 1175 519 1173 520 1175 1253 437 518 1175 519 1175 518 7917 1253 438 1254 438 413 1281 1253 440 1256 437 414 1279 465 1228 465 1228 1254 436 415 1279 465 1227 466 7969 1253 438 1254 438 413 1280 1254 440 1256 436 415 1280 413 1278 466 1229 1254 437 414 1279 414 1278 415 8024 1252 437 1255 436 415 1279 1255 440 1256 437 414 1279 414 1279 414 1279 1255 437 414 1279 414 1278 415
#
name: Rotate
type: raw
frequency: 38000
duty_cycle: 0.330000
data: 1253 434 1258 435 492 1200 1258 438 1258 434 498 1194 494 1202 1257 433 494 1200 493 1200 493 1200 493 7940 1259 434 1258 433 493 1200 1259 438 1258 433 493 1199 494 1200 1259 434 492 1200 493 1200 493 1199 494 7939 1258 435 1257 434 497 1196 1258 437 1259 433 498 1196 492 1201 1258 434 497 1197 491 1200 493 1201 492 7941 1258 434 1258 435 495 1197 1258 437 1259 433 497 1197 497 1196 1259 434 496 1197 496 1197 496 1196 497 7939 1258 435 1257 434 495 1198 1258 438 1258 434 495 1198 495 1199 1257 435 494 1199 494 1197 496 1197 496

View File

@@ -1,7 +1,7 @@
Filetype: IR library file Filetype: IR library file
Version: 1 Version: 1
# Last Updated 16th Jun, 2023 # Last Updated 24th Jul, 2023
# Last Checked 13th Jul, 2023 # Last Checked 24th Jul, 2023
# #
# ON # ON
name: Power name: Power
@@ -988,3 +988,93 @@ type: parsed
protocol: NEC protocol: NEC
address: 02 00 00 00 address: 02 00 00 00
command: 11 00 00 00 command: 11 00 00 00
#
name: Mute
type: parsed
protocol: NECext
address: 87 4E 00 00
command: 51 AE 00 00
#
name: Pause
type: parsed
protocol: NECext
address: 00 30 00 00
command: A8 57 00 00
#
name: Play
type: parsed
protocol: NECext
address: 00 30 00 00
command: A9 56 00 00
#
name: Play
type: parsed
protocol: NECext
address: 83 55 00 00
command: 5E A1 00 00
#
name: Pause
type: parsed
protocol: NECext
address: 83 55 00 00
command: 5B A4 00 00
#
name: Play
type: parsed
protocol: NEC
address: 00 00 00 00
command: 93 00 00 00
#
name: Pause
type: parsed
protocol: NEC
address: 00 00 00 00
command: 93 00 00 00
#
name: Play
type: parsed
protocol: NEC
address: 01 00 00 00
command: 15 00 00 00
#
name: Pause
type: parsed
protocol: NEC
address: 01 00 00 00
command: 15 00 00 00
#
name: Play
type: parsed
protocol: NECext
address: B8 57 00 00
command: 18 E7 00 00
#
name: Play
type: raw
frequency: 38000
duty_cycle: 0.33
data: 8981 4411 532 1616 557 1592 557 465 556 465 556 466 555 467 554 468 554 1595 554 467 554 468 554 1595 554 467 580 1569 581 1568 581 1568 581 1569 580 441 581 1569 580 442 580 1570 579 1594 555 467 555 443 579 442 580 1594 554 467 555 1594 555 467 555 468 554 1595 554 1595 528 1620 529 42169 9008 2106 531
#
name: Pause
type: raw
frequency: 38000
duty_cycle: 0.33
data: 8981 4411 532 1616 557 1592 557 465 556 465 556 466 555 467 554 468 554 1595 554 467 554 468 554 1595 554 467 580 1569 581 1568 581 1568 581 1569 580 441 581 1569 580 442 580 1570 579 1594 555 467 555 443 579 442 580 1594 554 467 555 1594 555 467 555 468 554 1595 554 1595 528 1620 529 42169 9008 2106 531
#
name: Play
type: parsed
protocol: NEC
address: 31 00 00 00
command: 41 00 00 00
#
name: Pause
type: parsed
protocol: NEC
address: 31 00 00 00
command: 41 00 00 00
#
name: Play
type: parsed
protocol: NEC
address: 01 00 00 00
command: 03 00 00 00

View File

@@ -1,7 +1,7 @@
Filetype: IR library file Filetype: IR library file
Version: 1 Version: 1
# Last Updated 24th Jul, 2023 # Last Updated 24th Jul, 2023
# Last Checked 13th Jul, 2023 # Last Checked 24th Jul, 2023
# #
name: Power name: Power
type: parsed type: parsed
@@ -2275,7 +2275,7 @@ type: parsed
protocol: NEC protocol: NEC
address: A0 00 00 00 address: A0 00 00 00
command: 5F 00 00 00 command: 5F 00 00 00
# #
# Xiaomi TV # Xiaomi TV
# #
name: Power name: Power
@@ -2307,3 +2307,41 @@ type: raw
frequency: 38000 frequency: 38000
duty_cycle: 0.330000 duty_cycle: 0.330000
data: 1119 528 675 1154 647 558 674 841 675 1153 675 531 673 532 673 843 673 1155 675 1153 674 531 673 12312 1120 505 672 1156 673 532 673 844 673 1155 673 532 671 534 672 842 675 1155 670 1158 673 530 674 12312 1093 532 671 1156 675 530 672 845 672 1156 673 533 671 533 670 846 672 1156 674 1154 674 529 675 12312 1093 557 646 1182 646 532 674 843 673 1181 646 534 672 532 674 842 673 1158 670 1156 674 530 673 12315 1091 530 674 1155 673 530 673 844 673 1157 644 559 673 532 672 844 670 1157 672 1158 672 532 672 12313 1093 533 671 1157 672 532 673 845 671 1157 670 558 647 532 646 871 672 1157 671 1181 646 534 671 data: 1119 528 675 1154 647 558 674 841 675 1153 675 531 673 532 673 843 673 1155 675 1153 674 531 673 12312 1120 505 672 1156 673 532 673 844 673 1155 673 532 671 534 672 842 675 1155 670 1158 673 530 674 12312 1093 532 671 1156 675 530 672 845 672 1156 673 533 671 533 670 846 672 1156 674 1154 674 529 675 12312 1093 557 646 1182 646 532 674 843 673 1181 646 534 672 532 674 842 673 1158 670 1156 674 530 673 12315 1091 530 674 1155 673 530 673 844 673 1157 644 559 673 532 672 844 670 1157 672 1158 672 532 672 12313 1093 533 671 1157 672 532 673 845 671 1157 670 558 647 532 646 871 672 1157 671 1181 646 534 671
#
# Daewoo TV
#
name: Power
type: parsed
protocol: NEC
address: 80 00 00 00
command: 82 00 00 00
#
name: Vol_up
type: parsed
protocol: NEC
address: 80 00 00 00
command: 9F 00 00 00
#
name: Vol_dn
type: parsed
protocol: NEC
address: 80 00 00 00
command: 8B 00 00 00
#
name: Ch_next
type: parsed
protocol: NEC
address: 80 00 00 00
command: 9B 00 00 00
#
name: Ch_prev
type: parsed
protocol: NEC
address: 80 00 00 00
command: 8F 00 00 00
#
name: Mute
type: parsed
protocol: NEC
address: 80 00 00 00
command: D0 00 00 00