diff --git a/applications/gui/modules/widget.c b/applications/gui/modules/widget.c index 8d7acb013..b37a64701 100644 --- a/applications/gui/modules/widget.c +++ b/applications/gui/modules/widget.c @@ -162,6 +162,19 @@ void widget_add_text_box_element( widget_add_element(widget, text_box_element); } +void widget_add_text_scroll_element( + Widget* widget, + uint8_t x, + uint8_t y, + uint8_t width, + uint8_t height, + const char* text) { + furi_assert(widget); + WidgetElement* text_scroll_element = + widget_element_text_scroll_create(x, y, width, height, text); + widget_add_element(widget, text_scroll_element); +} + void widget_add_button_element( Widget* widget, GuiButtonType button_type, diff --git a/applications/gui/modules/widget.h b/applications/gui/modules/widget.h index 55af59d7c..587fa3c65 100755 --- a/applications/gui/modules/widget.h +++ b/applications/gui/modules/widget.h @@ -105,6 +105,27 @@ void widget_add_text_box_element( const char* text, bool strip_to_dots); +/** Add Text Scroll Element + * + * @param widget Widget instance + * @param x x coordinate + * @param y y coordinate + * @param width width to fit text + * @param height height to fit text + * @param[in] text Formatted text. Default format: align left, Secondary font. + * The following formats are available: + * "\e#Bold text" - sets bold font before until next '\n' symbol + * "\ecBold text" - sets center horizontal align before until next '\n' symbol + * "\erBold text" - sets right horizontal align before until next '\n' symbol + */ +void widget_add_text_scroll_element( + Widget* widget, + uint8_t x, + uint8_t y, + uint8_t width, + uint8_t height, + const char* text); + /** Add Button Element * * @param widget Widget instance diff --git a/applications/gui/modules/widget_elements/widget_element_i.h b/applications/gui/modules/widget_elements/widget_element_i.h index bcbd4afdb..316ed7400 100755 --- a/applications/gui/modules/widget_elements/widget_element_i.h +++ b/applications/gui/modules/widget_elements/widget_element_i.h @@ -29,6 +29,7 @@ struct WidgetElement { // generic model holder void* model; + FuriMutex* model_mutex; // pointer to widget that hold our element Widget* parent; @@ -80,3 +81,10 @@ WidgetElement* widget_element_frame_create( uint8_t width, uint8_t height, uint8_t radius); + +WidgetElement* widget_element_text_scroll_create( + uint8_t x, + uint8_t y, + uint8_t width, + uint8_t height, + const char* text); diff --git a/applications/gui/modules/widget_elements/widget_element_text_scroll.c b/applications/gui/modules/widget_elements/widget_element_text_scroll.c new file mode 100644 index 000000000..6682b106a --- /dev/null +++ b/applications/gui/modules/widget_elements/widget_element_text_scroll.c @@ -0,0 +1,245 @@ +#include "widget_element_i.h" +#include +#include +#include + +#define WIDGET_ELEMENT_TEXT_SCROLL_BAR_OFFSET (4) + +typedef struct { + Font font; + Align horizontal; + string_t text; +} TextScrollLineArray; + +ARRAY_DEF(TextScrollLineArray, TextScrollLineArray, M_POD_OPLIST) + +typedef struct { + TextScrollLineArray_t line_array; + uint8_t x; + uint8_t y; + uint8_t width; + uint8_t height; + string_t text; + uint8_t scroll_pos_total; + uint8_t scroll_pos_current; + bool text_formatted; +} WidgetElementTextScrollModel; + +static bool + widget_element_text_scroll_process_ctrl_symbols(TextScrollLineArray* line, string_t text) { + bool processed = false; + + do { + if(string_get_char(text, 0) != '\e') break; + char ctrl_symbol = string_get_char(text, 1); + if(ctrl_symbol == 'c') { + line->horizontal = AlignCenter; + } else if(ctrl_symbol == 'r') { + line->horizontal = AlignRight; + } else if(ctrl_symbol == '#') { + line->font = FontPrimary; + } + string_right(text, 2); + processed = true; + } while(false); + + return processed; +} + +void widget_element_text_scroll_add_line(WidgetElement* element, TextScrollLineArray* line) { + WidgetElementTextScrollModel* model = element->model; + TextScrollLineArray new_line; + new_line.font = line->font; + new_line.horizontal = line->horizontal; + string_init_set(new_line.text, line->text); + TextScrollLineArray_push_back(model->line_array, new_line); +} + +static void widget_element_text_scroll_fill_lines(Canvas* canvas, WidgetElement* element) { + WidgetElementTextScrollModel* model = element->model; + TextScrollLineArray line_tmp; + bool all_text_processed = false; + string_init(line_tmp.text); + bool reached_new_line = true; + uint16_t total_height = 0; + + while(!all_text_processed) { + if(reached_new_line) { + // Set default line properties + line_tmp.font = FontSecondary; + line_tmp.horizontal = AlignLeft; + string_reset(line_tmp.text); + // Process control symbols + while(widget_element_text_scroll_process_ctrl_symbols(&line_tmp, model->text)) + ; + } + // Set canvas font + canvas_set_font(canvas, line_tmp.font); + CanvasFontParameters* params = canvas_get_font_params(canvas, line_tmp.font); + total_height += params->height; + if(total_height > model->height) { + model->scroll_pos_total++; + } + + uint8_t line_width = 0; + uint16_t char_i = 0; + while(true) { + char next_char = string_get_char(model->text, char_i++); + if(next_char == '\0') { + string_push_back(line_tmp.text, '\0'); + widget_element_text_scroll_add_line(element, &line_tmp); + total_height += params->leading_default - params->height; + all_text_processed = true; + break; + } else if(next_char == '\n') { + string_push_back(line_tmp.text, '\0'); + widget_element_text_scroll_add_line(element, &line_tmp); + string_right(model->text, char_i); + total_height += params->leading_default - params->height; + reached_new_line = true; + break; + } else { + line_width += canvas_glyph_width(canvas, next_char); + if(line_width > model->width) { + string_push_back(line_tmp.text, '\0'); + widget_element_text_scroll_add_line(element, &line_tmp); + string_right(model->text, char_i - 1); + string_reset(line_tmp.text); + total_height += params->leading_default - params->height; + reached_new_line = false; + break; + } else { + string_push_back(line_tmp.text, next_char); + } + } + } + } + + string_clear(line_tmp.text); +} + +static void widget_element_text_scroll_draw(Canvas* canvas, WidgetElement* element) { + furi_assert(canvas); + furi_assert(element); + + furi_mutex_acquire(element->model_mutex, FuriWaitForever); + + WidgetElementTextScrollModel* model = element->model; + if(!model->text_formatted) { + widget_element_text_scroll_fill_lines(canvas, element); + model->text_formatted = true; + } + + uint8_t y = model->y; + uint8_t x = model->x; + uint16_t curr_line = 0; + if(TextScrollLineArray_size(model->line_array)) { + TextScrollLineArray_it_t it; + for(TextScrollLineArray_it(it, model->line_array); !TextScrollLineArray_end_p(it); + TextScrollLineArray_next(it), curr_line++) { + if(curr_line < model->scroll_pos_current) continue; + TextScrollLineArray* line = TextScrollLineArray_ref(it); + CanvasFontParameters* params = canvas_get_font_params(canvas, line->font); + if(y + params->descender > model->y + model->height) break; + canvas_set_font(canvas, line->font); + if(line->horizontal == AlignLeft) { + x = model->x; + } else if(line->horizontal == AlignCenter) { + x = (model->x + model->width) / 2; + } else if(line->horizontal == AlignRight) { + x = model->x + model->width; + } + canvas_draw_str_aligned( + canvas, x, y, line->horizontal, AlignTop, string_get_cstr(line->text)); + y += params->leading_default; + } + // Draw scroll bar + if(model->scroll_pos_total > 1) { + elements_scrollbar_pos( + canvas, + model->x + model->width + WIDGET_ELEMENT_TEXT_SCROLL_BAR_OFFSET, + model->y, + model->height, + model->scroll_pos_current, + model->scroll_pos_total); + } + } + + furi_mutex_release(element->model_mutex); +} + +static bool widget_element_text_scroll_input(InputEvent* event, WidgetElement* element) { + furi_assert(event); + furi_assert(element); + + furi_mutex_acquire(element->model_mutex, FuriWaitForever); + + WidgetElementTextScrollModel* model = element->model; + bool consumed = false; + + if((event->type == InputTypeShort) || (event->type == InputTypeRepeat)) { + if(event->key == InputKeyUp) { + if(model->scroll_pos_current > 0) { + model->scroll_pos_current--; + } + consumed = true; + } else if(event->key == InputKeyDown) { + if((model->scroll_pos_total > 1) && + (model->scroll_pos_current < model->scroll_pos_total - 1)) { + model->scroll_pos_current++; + } + consumed = true; + } + } + + furi_mutex_release(element->model_mutex); + + return consumed; +} + +static void widget_element_text_scroll_free(WidgetElement* text_scroll) { + furi_assert(text_scroll); + + WidgetElementTextScrollModel* model = text_scroll->model; + TextScrollLineArray_it_t it; + for(TextScrollLineArray_it(it, model->line_array); !TextScrollLineArray_end_p(it); + TextScrollLineArray_next(it)) { + TextScrollLineArray* line = TextScrollLineArray_ref(it); + string_clear(line->text); + } + TextScrollLineArray_clear(model->line_array); + string_clear(model->text); + free(text_scroll->model); + furi_mutex_free(text_scroll->model_mutex); + free(text_scroll); +} + +WidgetElement* widget_element_text_scroll_create( + uint8_t x, + uint8_t y, + uint8_t width, + uint8_t height, + const char* text) { + furi_assert(text); + + // Allocate and init model + WidgetElementTextScrollModel* model = malloc(sizeof(WidgetElementTextScrollModel)); + model->x = x; + model->y = y; + model->width = width - WIDGET_ELEMENT_TEXT_SCROLL_BAR_OFFSET; + model->height = height; + model->scroll_pos_current = 0; + model->scroll_pos_total = 1; + TextScrollLineArray_init(model->line_array); + string_init_set_str(model->text, text); + + WidgetElement* text_scroll = malloc(sizeof(WidgetElement)); + text_scroll->parent = NULL; + text_scroll->draw = widget_element_text_scroll_draw; + text_scroll->input = widget_element_text_scroll_input; + text_scroll->free = widget_element_text_scroll_free; + text_scroll->model = model; + text_scroll->model_mutex = furi_mutex_alloc(FuriMutexTypeNormal); + + return text_scroll; +} diff --git a/applications/nfc/nfc.c b/applications/nfc/nfc.c index 6b8843db2..3422e91af 100644 --- a/applications/nfc/nfc.c +++ b/applications/nfc/nfc.c @@ -89,11 +89,6 @@ Nfc* nfc_alloc() { nfc->widget = widget_alloc(); view_dispatcher_add_view(nfc->view_dispatcher, NfcViewWidget, widget_get_view(nfc->widget)); - // Bank Card - nfc->bank_card = bank_card_alloc(); - view_dispatcher_add_view( - nfc->view_dispatcher, NfcViewBankCard, bank_card_get_view(nfc->bank_card)); - // Mifare Classic Dict Attack nfc->dict_attack = dict_attack_alloc(); view_dispatcher_add_view( @@ -159,10 +154,6 @@ void nfc_free(Nfc* nfc) { view_dispatcher_remove_view(nfc->view_dispatcher, NfcViewWidget); widget_free(nfc->widget); - // Bank Card - view_dispatcher_remove_view(nfc->view_dispatcher, NfcViewBankCard); - bank_card_free(nfc->bank_card); - // Mifare Classic Dict Attack view_dispatcher_remove_view(nfc->view_dispatcher, NfcViewDictAttack); dict_attack_free(nfc->dict_attack); diff --git a/applications/nfc/nfc_i.h b/applications/nfc/nfc_i.h index 5a916e803..bcfe4a219 100644 --- a/applications/nfc/nfc_i.h +++ b/applications/nfc/nfc_i.h @@ -25,8 +25,8 @@ #include #include #include +#include -#include "views/bank_card.h" #include "views/dict_attack.h" #include @@ -70,7 +70,6 @@ struct Nfc { ByteInput* byte_input; TextBox* text_box; Widget* widget; - BankCard* bank_card; DictAttack* dict_attack; const NfcGenerator* generator; @@ -85,7 +84,6 @@ typedef enum { NfcViewByteInput, NfcViewTextBox, NfcViewWidget, - NfcViewBankCard, NfcViewDictAttack, } NfcView; diff --git a/applications/nfc/scenes/nfc_scene_config.h b/applications/nfc/scenes/nfc_scene_config.h index 2b5cb5cf1..ff34a11d8 100755 --- a/applications/nfc/scenes/nfc_scene_config.h +++ b/applications/nfc/scenes/nfc_scene_config.h @@ -12,7 +12,10 @@ ADD_SCENE(nfc, save_name, SaveName) ADD_SCENE(nfc, save_success, SaveSuccess) ADD_SCENE(nfc, file_select, FileSelect) ADD_SCENE(nfc, emulate_uid, EmulateUid) +ADD_SCENE(nfc, nfca_read_success, NfcaReadSuccess) +ADD_SCENE(nfc, nfca_menu, NfcaMenu) ADD_SCENE(nfc, mf_ultralight_read_success, MfUltralightReadSuccess) +ADD_SCENE(nfc, mf_ultralight_data, MfUltralightData) ADD_SCENE(nfc, mf_ultralight_menu, MfUltralightMenu) ADD_SCENE(nfc, mf_ultralight_emulate, MfUltralightEmulate) ADD_SCENE(nfc, mf_ultralight_read_auth, MfUltralightReadAuth) @@ -25,13 +28,13 @@ ADD_SCENE(nfc, mf_desfire_menu, MfDesfireMenu) ADD_SCENE(nfc, mf_desfire_data, MfDesfireData) ADD_SCENE(nfc, mf_desfire_app, MfDesfireApp) ADD_SCENE(nfc, mf_classic_read_success, MfClassicReadSuccess) -ADD_SCENE(nfc, mf_classic_info, MfClassicInfo) ADD_SCENE(nfc, mf_classic_menu, MfClassicMenu) ADD_SCENE(nfc, mf_classic_emulate, MfClassicEmulate) ADD_SCENE(nfc, mf_classic_keys, MfClassicKeys) ADD_SCENE(nfc, mf_classic_keys_add, MfClassicKeysAdd) ADD_SCENE(nfc, mf_classic_dict_attack, MfClassicDictAttack) ADD_SCENE(nfc, emv_read_success, EmvReadSuccess) +ADD_SCENE(nfc, emv_menu, EmvMenu) ADD_SCENE(nfc, emulate_apdu_sequence, EmulateApduSequence) ADD_SCENE(nfc, device_info, DeviceInfo) ADD_SCENE(nfc, delete, Delete) @@ -45,3 +48,4 @@ ADD_SCENE(nfc, rpc, Rpc) ADD_SCENE(nfc, exit_confirm, ExitConfirm) ADD_SCENE(nfc, retry_confirm, RetryConfirm) ADD_SCENE(nfc, detect_reader, DetectReader) +ADD_SCENE(nfc, nfc_data_info, NfcDataInfo) diff --git a/applications/nfc/scenes/nfc_scene_delete.c b/applications/nfc/scenes/nfc_scene_delete.c index 1946b9290..987927e19 100755 --- a/applications/nfc/scenes/nfc_scene_delete.c +++ b/applications/nfc/scenes/nfc_scene_delete.c @@ -9,58 +9,43 @@ void nfc_scene_delete_widget_callback(GuiButtonType result, InputType type, void void nfc_scene_delete_on_enter(void* context) { Nfc* nfc = context; + FuriHalNfcDevData* nfc_data = &nfc->dev->dev_data.nfc_data; // Setup Custom Widget view - char temp_str[64]; - snprintf(temp_str, sizeof(temp_str), "\e#Delete %s?\e#", nfc->dev->dev_name); + string_t temp_str; + string_init(temp_str); + + string_printf(temp_str, "\e#Delete %s?\e#", nfc->dev->dev_name); widget_add_text_box_element( - nfc->widget, 0, 0, 128, 23, AlignCenter, AlignCenter, temp_str, false); + nfc->widget, 0, 0, 128, 23, AlignCenter, AlignCenter, string_get_cstr(temp_str), false); widget_add_button_element( - nfc->widget, GuiButtonTypeLeft, "Back", nfc_scene_delete_widget_callback, nfc); + nfc->widget, GuiButtonTypeLeft, "Cancel", nfc_scene_delete_widget_callback, nfc); widget_add_button_element( nfc->widget, GuiButtonTypeRight, "Delete", nfc_scene_delete_widget_callback, nfc); - FuriHalNfcDevData* data = &nfc->dev->dev_data.nfc_data; - if(data->uid_len == 4) { - snprintf( - temp_str, - sizeof(temp_str), - "UID: %02X %02X %02X %02X", - data->uid[0], - data->uid[1], - data->uid[2], - data->uid[3]); - } else if(data->uid_len == 7) { - snprintf( - temp_str, - sizeof(temp_str), - "UID: %02X %02X %02X %02X %02X %02X %02X", - data->uid[0], - data->uid[1], - data->uid[2], - data->uid[3], - data->uid[4], - data->uid[5], - data->uid[6]); - } - widget_add_string_element(nfc->widget, 64, 23, AlignCenter, AlignTop, FontSecondary, temp_str); - const char* protocol_name = NULL; + string_set_str(temp_str, "UID:"); + for(size_t i = 0; i < nfc_data->uid_len; i++) { + string_cat_printf(temp_str, " %02X", nfc_data->uid[i]); + } + widget_add_string_element( + nfc->widget, 64, 24, AlignCenter, AlignTop, FontSecondary, string_get_cstr(temp_str)); + NfcProtocol protocol = nfc->dev->dev_data.protocol; if(protocol == NfcDeviceProtocolEMV) { - protocol_name = nfc_guess_protocol(protocol); + string_set_str(temp_str, "EMV bank card"); } else if(protocol == NfcDeviceProtocolMifareUl) { - protocol_name = nfc_mf_ul_type(nfc->dev->dev_data.mf_ul_data.type, false); + string_set_str(temp_str, nfc_mf_ul_type(nfc->dev->dev_data.mf_ul_data.type, true)); + } else if(protocol == NfcDeviceProtocolMifareClassic) { + string_set_str(temp_str, nfc_mf_classic_type(nfc->dev->dev_data.mf_classic_data.type)); + } else if(protocol == NfcDeviceProtocolMifareDesfire) { + string_set_str(temp_str, "MIFARE DESFire"); + } else { + string_set_str(temp_str, "Unknown ISO tag"); } - if(protocol_name) { - widget_add_string_element( - nfc->widget, 10, 33, AlignLeft, AlignTop, FontSecondary, protocol_name); - } - // TODO change dinamically - widget_add_string_element(nfc->widget, 118, 33, AlignRight, AlignTop, FontSecondary, "NFC-A"); - snprintf(temp_str, sizeof(temp_str), "SAK: %02X", data->sak); - widget_add_string_element(nfc->widget, 10, 43, AlignLeft, AlignTop, FontSecondary, temp_str); - snprintf(temp_str, sizeof(temp_str), "ATQA: %02X%02X", data->atqa[0], data->atqa[1]); - widget_add_string_element(nfc->widget, 118, 43, AlignRight, AlignTop, FontSecondary, temp_str); + widget_add_string_element( + nfc->widget, 64, 34, AlignCenter, AlignTop, FontSecondary, string_get_cstr(temp_str)); + widget_add_string_element(nfc->widget, 64, 44, AlignCenter, AlignTop, FontSecondary, "NFC-A"); + string_clear(temp_str); view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget); } @@ -71,7 +56,7 @@ bool nfc_scene_delete_on_event(void* context, SceneManagerEvent event) { if(event.type == SceneManagerEventTypeCustom) { if(event.event == GuiButtonTypeLeft) { - return scene_manager_previous_scene(nfc->scene_manager); + consumed = scene_manager_previous_scene(nfc->scene_manager); } else if(event.event == GuiButtonTypeRight) { if(nfc_device_delete(nfc->dev, true)) { scene_manager_next_scene(nfc->scene_manager, NfcSceneDeleteSuccess); diff --git a/applications/nfc/scenes/nfc_scene_delete_success.c b/applications/nfc/scenes/nfc_scene_delete_success.c index 547aeab7e..713b99ebf 100755 --- a/applications/nfc/scenes/nfc_scene_delete_success.c +++ b/applications/nfc/scenes/nfc_scene_delete_success.c @@ -26,7 +26,7 @@ bool nfc_scene_delete_success_on_event(void* context, SceneManagerEvent event) { if(event.type == SceneManagerEventTypeCustom) { if(event.event == NfcCustomEventViewExit) { consumed = scene_manager_search_and_switch_to_previous_scene( - nfc->scene_manager, NfcSceneStart); + nfc->scene_manager, NfcSceneFileSelect); } } return consumed; diff --git a/applications/nfc/scenes/nfc_scene_device_info.c b/applications/nfc/scenes/nfc_scene_device_info.c index b79c51046..8228c7ea3 100644 --- a/applications/nfc/scenes/nfc_scene_device_info.c +++ b/applications/nfc/scenes/nfc_scene_device_info.c @@ -1,11 +1,6 @@ #include "../nfc_i.h" #include "../helpers/nfc_emv_parser.h" -enum { - NfcSceneDeviceInfoUid, - NfcSceneDeviceInfoData, -}; - void nfc_scene_device_info_widget_callback(GuiButtonType result, InputType type, void* context) { Nfc* nfc = context; if(type == InputTypeShort) { @@ -13,197 +8,65 @@ void nfc_scene_device_info_widget_callback(GuiButtonType result, InputType type, } } -void nfc_scene_device_info_dialog_callback(DialogExResult result, void* context) { - Nfc* nfc = context; - if(result == DialogExResultLeft) { - view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventViewExit); - } -} - -void nfc_scene_device_info_bank_card_callback(GuiButtonType result, InputType type, void* context) { - UNUSED(result); - Nfc* nfc = context; - if(type == InputTypeShort) { - view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventViewExit); - } -} - void nfc_scene_device_info_on_enter(void* context) { Nfc* nfc = context; + NfcDeviceData* dev_data = &nfc->dev->dev_data; - bool data_display_supported = (nfc->dev->format == NfcDeviceSaveFormatUid) || - (nfc->dev->format == NfcDeviceSaveFormatMifareUl) || - (nfc->dev->format == NfcDeviceSaveFormatMifareDesfire) || - (nfc->dev->format == NfcDeviceSaveFormatBankCard); - // Setup Custom Widget view - widget_add_text_box_element( - nfc->widget, 0, 0, 128, 22, AlignCenter, AlignTop, nfc->dev->dev_name, false); - widget_add_button_element( - nfc->widget, GuiButtonTypeLeft, "Back", nfc_scene_device_info_widget_callback, nfc); - if(data_display_supported) { - widget_add_button_element( - nfc->widget, GuiButtonTypeRight, "Data", nfc_scene_device_info_widget_callback, nfc); - } - char temp_str[32]; - FuriHalNfcDevData* data = &nfc->dev->dev_data.nfc_data; - if(data->uid_len == 4) { - snprintf( - temp_str, - sizeof(temp_str), - "UID: %02X %02X %02X %02X", - data->uid[0], - data->uid[1], - data->uid[2], - data->uid[3]); - } else if(data->uid_len == 7) { - snprintf( - temp_str, - sizeof(temp_str), - "UID: %02X %02X %02X %02X %02X %02X %02X", - data->uid[0], - data->uid[1], - data->uid[2], - data->uid[3], - data->uid[4], - data->uid[5], - data->uid[6]); - } - widget_add_string_element(nfc->widget, 64, 21, AlignCenter, AlignTop, FontSecondary, temp_str); + string_t temp_str; + string_init(temp_str); - const char* protocol_name = NULL; - NfcProtocol protocol = nfc->dev->dev_data.protocol; - if(protocol == NfcDeviceProtocolEMV || protocol == NfcDeviceProtocolMifareDesfire) { - protocol_name = nfc_guess_protocol(protocol); - } else if(protocol == NfcDeviceProtocolMifareUl) { - protocol_name = nfc_mf_ul_type(nfc->dev->dev_data.mf_ul_data.type, false); - } else if(protocol == NfcDeviceProtocolMifareClassic) { - protocol_name = nfc_mf_classic_type(nfc->dev->dev_data.mf_classic_data.type); - } - if(protocol_name) { - widget_add_string_element( - nfc->widget, 10, 32, AlignLeft, AlignTop, FontSecondary, protocol_name); - } - // TODO change dinamically - widget_add_string_element(nfc->widget, 118, 32, AlignRight, AlignTop, FontSecondary, "NFC-A"); - snprintf(temp_str, sizeof(temp_str), "SAK: %02X", data->sak); - widget_add_string_element(nfc->widget, 10, 42, AlignLeft, AlignTop, FontSecondary, temp_str); - snprintf(temp_str, sizeof(temp_str), "ATQA: %02X%02X", data->atqa[0], data->atqa[1]); - widget_add_string_element(nfc->widget, 118, 42, AlignRight, AlignTop, FontSecondary, temp_str); - - // Setup Data View - if(nfc->dev->format == NfcDeviceSaveFormatUid) { - DialogEx* dialog_ex = nfc->dialog_ex; - dialog_ex_set_left_button_text(dialog_ex, "Back"); - dialog_ex_set_text(dialog_ex, "No data", 64, 32, AlignCenter, AlignCenter); - dialog_ex_set_context(dialog_ex, nfc); - dialog_ex_set_result_callback(dialog_ex, nfc_scene_device_info_dialog_callback); - } else if(nfc->dev->format == NfcDeviceSaveFormatMifareUl) { - MfUltralightData* mf_ul_data = &nfc->dev->dev_data.mf_ul_data; - TextBox* text_box = nfc->text_box; - text_box_set_font(text_box, TextBoxFontHex); - for(uint16_t i = 0; i < mf_ul_data->data_size; i += 2) { - if(!(i % 8) && i) { - string_push_back(nfc->text_box_store, '\n'); - } - string_cat_printf( - nfc->text_box_store, "%02X%02X ", mf_ul_data->data[i], mf_ul_data->data[i + 1]); + if(dev_data->protocol == NfcDeviceProtocolEMV) { + EmvData* emv_data = &dev_data->emv_data; + string_printf(temp_str, "\e#%s\n", emv_data->name); + for(uint8_t i = 0; i < emv_data->number_len; i += 2) { + string_cat_printf(temp_str, "%02X%02X ", emv_data->number[i], emv_data->number[i + 1]); } - text_box_set_text(text_box, string_get_cstr(nfc->text_box_store)); - } else if(nfc->dev->format == NfcDeviceSaveFormatMifareDesfire) { - MifareDesfireData* mf_df_data = &nfc->dev->dev_data.mf_df_data; - uint16_t n_apps = 0; - uint16_t n_files = 0; - for(MifareDesfireApplication* app = mf_df_data->app_head; app; app = app->next) { - n_apps++; - for(MifareDesfireFile* file = app->file_head; file; file = file->next) { - n_files++; - } - } - nfc_text_store_set( - nfc, - "%d application%s, %d file%s", - n_apps, - n_apps == 1 ? "" : "s", - n_files, - n_files == 1 ? "" : "s"); - widget_add_string_element( - nfc->widget, 64, 17, AlignCenter, AlignBottom, FontSecondary, nfc->text_store); - } else if(nfc->dev->format == NfcDeviceSaveFormatBankCard) { - EmvData* emv_data = &nfc->dev->dev_data.emv_data; - BankCard* bank_card = nfc->bank_card; - bank_card_set_name(bank_card, emv_data->name); - bank_card_set_number(bank_card, emv_data->number, emv_data->number_len); - bank_card_set_back_callback(bank_card, nfc_scene_device_info_bank_card_callback, nfc); + string_strim(temp_str); + + // Add expiration date if(emv_data->exp_mon) { - bank_card_set_exp_date(bank_card, emv_data->exp_mon, emv_data->exp_year); + string_cat_printf(temp_str, "\nExp: %02X/%02X", emv_data->exp_mon, emv_data->exp_year); } - string_t display_str; - string_init(display_str); - if(emv_data->country_code) { + // Parse currency code + if((emv_data->currency_code)) { + string_t currency_name; + string_init(currency_name); + if(nfc_emv_parser_get_currency_name( + nfc->dev->storage, emv_data->currency_code, currency_name)) { + string_cat_printf(temp_str, "\nCur: %s ", string_get_cstr(currency_name)); + } + string_clear(currency_name); + } + // Parse country code + if((emv_data->country_code)) { string_t country_name; string_init(country_name); if(nfc_emv_parser_get_country_name( nfc->dev->storage, emv_data->country_code, country_name)) { - string_printf(display_str, "Reg:%s", string_get_cstr(country_name)); - bank_card_set_country_name(bank_card, string_get_cstr(display_str)); + string_cat_printf(temp_str, "Reg: %s", string_get_cstr(country_name)); } string_clear(country_name); } - if(emv_data->currency_code) { - string_t currency_name; - string_init(currency_name); - if(nfc_emv_parser_get_currency_name( - nfc->dev->storage, emv_data->country_code, currency_name)) { - string_printf(display_str, "Cur:%s", string_get_cstr(currency_name)); - bank_card_set_currency_name(bank_card, string_get_cstr(display_str)); - } - string_clear(currency_name); - } - string_clear(display_str); + } else if(dev_data->protocol == NfcDeviceProtocolMifareClassic) { + string_set(temp_str, nfc->dev->dev_data.parsed_data); } - scene_manager_set_scene_state(nfc->scene_manager, NfcSceneDeviceInfo, NfcSceneDeviceInfoUid); + + widget_add_text_scroll_element(nfc->widget, 0, 0, 128, 52, string_get_cstr(temp_str)); + string_clear(temp_str); + + widget_add_button_element( + nfc->widget, GuiButtonTypeRight, "More", nfc_scene_device_info_widget_callback, nfc); + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget); } bool nfc_scene_device_info_on_event(void* context, SceneManagerEvent event) { Nfc* nfc = context; bool consumed = false; - uint32_t state = scene_manager_get_scene_state(nfc->scene_manager, NfcSceneDeviceInfo); if(event.type == SceneManagerEventTypeCustom) { - if((state == NfcSceneDeviceInfoUid) && (event.event == GuiButtonTypeLeft)) { - consumed = scene_manager_previous_scene(nfc->scene_manager); - } else if((state == NfcSceneDeviceInfoUid) && (event.event == GuiButtonTypeRight)) { - if(nfc->dev->format == NfcDeviceSaveFormatUid) { - scene_manager_set_scene_state( - nfc->scene_manager, NfcSceneDeviceInfo, NfcSceneDeviceInfoData); - view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewDialogEx); - consumed = true; - } else if(nfc->dev->format == NfcDeviceSaveFormatMifareUl) { - scene_manager_set_scene_state( - nfc->scene_manager, NfcSceneDeviceInfo, NfcSceneDeviceInfoData); - view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewTextBox); - consumed = true; - } else if(nfc->dev->format == NfcDeviceSaveFormatBankCard) { - scene_manager_set_scene_state( - nfc->scene_manager, NfcSceneDeviceInfo, NfcSceneDeviceInfoData); - view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewBankCard); - consumed = true; - } else if(nfc->dev->format == NfcDeviceSaveFormatMifareDesfire) { - scene_manager_next_scene(nfc->scene_manager, NfcSceneMfDesfireData); - consumed = true; - } - } else if(state == NfcSceneDeviceInfoData && event.event == NfcCustomEventViewExit) { - scene_manager_set_scene_state( - nfc->scene_manager, NfcSceneDeviceInfo, NfcSceneDeviceInfoUid); - view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget); - consumed = true; - } - } else if(event.type == SceneManagerEventTypeBack) { - if(state == NfcSceneDeviceInfoData) { - scene_manager_set_scene_state( - nfc->scene_manager, NfcSceneDeviceInfo, NfcSceneDeviceInfoUid); - view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget); + if(event.event == GuiButtonTypeRight) { + scene_manager_next_scene(nfc->scene_manager, NfcSceneNfcDataInfo); consumed = true; } } @@ -215,12 +78,4 @@ void nfc_scene_device_info_on_exit(void* context) { // Clear views widget_reset(nfc->widget); - if(nfc->dev->format == NfcDeviceSaveFormatUid) { - dialog_ex_reset(nfc->dialog_ex); - } else if(nfc->dev->format == NfcDeviceSaveFormatMifareUl) { - text_box_reset(nfc->text_box); - string_reset(nfc->text_box_store); - } else if(nfc->dev->format == NfcDeviceSaveFormatBankCard) { - bank_card_clear(nfc->bank_card); - } } diff --git a/applications/nfc/scenes/nfc_scene_emv_menu.c b/applications/nfc/scenes/nfc_scene_emv_menu.c new file mode 100644 index 000000000..1da630fcf --- /dev/null +++ b/applications/nfc/scenes/nfc_scene_emv_menu.c @@ -0,0 +1,54 @@ +#include "../nfc_i.h" + +enum SubmenuIndex { + SubmenuIndexSave, + SubmenuIndexInfo, +}; + +void nfc_scene_emv_menu_submenu_callback(void* context, uint32_t index) { + Nfc* nfc = context; + + view_dispatcher_send_custom_event(nfc->view_dispatcher, index); +} + +void nfc_scene_emv_menu_on_enter(void* context) { + Nfc* nfc = context; + Submenu* submenu = nfc->submenu; + + submenu_add_item(submenu, "Save", SubmenuIndexSave, nfc_scene_emv_menu_submenu_callback, nfc); + submenu_add_item(submenu, "Info", SubmenuIndexInfo, nfc_scene_emv_menu_submenu_callback, nfc); + submenu_set_selected_item( + nfc->submenu, scene_manager_get_scene_state(nfc->scene_manager, NfcSceneEmvMenu)); + + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu); +} + +bool nfc_scene_emv_menu_on_event(void* context, SceneManagerEvent event) { + Nfc* nfc = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == SubmenuIndexSave) { + nfc->dev->format = NfcDeviceSaveFormatBankCard; + // Clear device name + nfc_device_set_name(nfc->dev, ""); + scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveName); + consumed = true; + } else if(event.event == SubmenuIndexInfo) { + scene_manager_next_scene(nfc->scene_manager, NfcSceneNfcDataInfo); + consumed = true; + } + scene_manager_set_scene_state(nfc->scene_manager, NfcSceneEmvMenu, event.event); + } else if(event.type == SceneManagerEventTypeBack) { + consumed = scene_manager_previous_scene(nfc->scene_manager); + } + + return consumed; +} + +void nfc_scene_emv_menu_on_exit(void* context) { + Nfc* nfc = context; + + // Clear view + submenu_reset(nfc->submenu); +} diff --git a/applications/nfc/scenes/nfc_scene_emv_read_success.c b/applications/nfc/scenes/nfc_scene_emv_read_success.c index eefe560e3..9cf7ff9e9 100644 --- a/applications/nfc/scenes/nfc_scene_emv_read_success.c +++ b/applications/nfc/scenes/nfc_scene_emv_read_success.c @@ -15,85 +15,48 @@ void nfc_scene_emv_read_success_widget_callback( void nfc_scene_emv_read_success_on_enter(void* context) { Nfc* nfc = context; EmvData* emv_data = &nfc->dev->dev_data.emv_data; - FuriHalNfcDevData* nfc_data = &nfc->dev->dev_data.nfc_data; DOLPHIN_DEED(DolphinDeedNfcReadSuccess); // Setup Custom Widget view - // Add frame - widget_add_frame_element(nfc->widget, 0, 0, 128, 64, 6); - // Add buttons widget_add_button_element( nfc->widget, GuiButtonTypeLeft, "Retry", nfc_scene_emv_read_success_widget_callback, nfc); widget_add_button_element( - nfc->widget, GuiButtonTypeRight, "Save", nfc_scene_emv_read_success_widget_callback, nfc); - // Add card name - widget_add_string_element( - nfc->widget, 64, 3, AlignCenter, AlignTop, FontSecondary, nfc->dev->dev_data.emv_data.name); - // Add card number - string_t pan_str; - string_init(pan_str); + nfc->widget, GuiButtonTypeRight, "More", nfc_scene_emv_read_success_widget_callback, nfc); + + string_t temp_str; + string_init_printf(temp_str, "\e#%s\n", emv_data->name); for(uint8_t i = 0; i < emv_data->number_len; i += 2) { - string_cat_printf(pan_str, "%02X%02X ", emv_data->number[i], emv_data->number[i + 1]); + string_cat_printf(temp_str, "%02X%02X ", emv_data->number[i], emv_data->number[i + 1]); } - string_strim(pan_str); - widget_add_string_element( - nfc->widget, 64, 13, AlignCenter, AlignTop, FontSecondary, string_get_cstr(pan_str)); - string_clear(pan_str); - // Parse country code - string_t country_name; - string_init(country_name); - if((emv_data->country_code) && - nfc_emv_parser_get_country_name(nfc->dev->storage, emv_data->country_code, country_name)) { - string_t disp_country; - string_init_printf(disp_country, "Reg:%s", country_name); - widget_add_string_element( - nfc->widget, 7, 23, AlignLeft, AlignTop, FontSecondary, string_get_cstr(disp_country)); - string_clear(disp_country); - } - string_clear(country_name); - // Parse currency code - string_t currency_name; - string_init(currency_name); - if((emv_data->currency_code) && - nfc_emv_parser_get_currency_name( - nfc->dev->storage, emv_data->currency_code, currency_name)) { - string_t disp_currency; - string_init_printf(disp_currency, "Cur:%s", currency_name); - widget_add_string_element( - nfc->widget, - 121, - 23, - AlignRight, - AlignTop, - FontSecondary, - string_get_cstr(disp_currency)); - string_clear(disp_currency); - } - string_clear(currency_name); - char temp_str[32]; - // Add ATQA - snprintf(temp_str, sizeof(temp_str), "ATQA: %02X%02X", nfc_data->atqa[0], nfc_data->atqa[1]); - widget_add_string_element(nfc->widget, 121, 32, AlignRight, AlignTop, FontSecondary, temp_str); - // Add UID - snprintf( - temp_str, - sizeof(temp_str), - "UID: %02X %02X %02X %02X", - nfc_data->uid[0], - nfc_data->uid[1], - nfc_data->uid[2], - nfc_data->uid[3]); - widget_add_string_element(nfc->widget, 7, 42, AlignLeft, AlignTop, FontSecondary, temp_str); - // Add SAK - snprintf(temp_str, sizeof(temp_str), "SAK: %02X", nfc_data->sak); - widget_add_string_element(nfc->widget, 121, 42, AlignRight, AlignTop, FontSecondary, temp_str); + string_strim(temp_str); + // Add expiration date if(emv_data->exp_mon) { - char exp_str[16]; - snprintf( - exp_str, sizeof(exp_str), "Exp: %02X/%02X", emv_data->exp_mon, emv_data->exp_year); - widget_add_string_element(nfc->widget, 7, 32, AlignLeft, AlignTop, FontSecondary, exp_str); + string_cat_printf(temp_str, "\nExp: %02X/%02X", emv_data->exp_mon, emv_data->exp_year); } + // Parse currency code + if((emv_data->currency_code)) { + string_t currency_name; + string_init(currency_name); + if(nfc_emv_parser_get_currency_name( + nfc->dev->storage, emv_data->currency_code, currency_name)) { + string_cat_printf(temp_str, "\nCur: %s ", string_get_cstr(currency_name)); + } + string_clear(currency_name); + } + // Parse country code + if((emv_data->country_code)) { + string_t country_name; + string_init(country_name); + if(nfc_emv_parser_get_country_name( + nfc->dev->storage, emv_data->country_code, country_name)) { + string_cat_printf(temp_str, "Reg: %s", string_get_cstr(country_name)); + } + string_clear(country_name); + } + + widget_add_text_scroll_element(nfc->widget, 0, 0, 128, 52, string_get_cstr(temp_str)); + string_clear(temp_str); view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget); } @@ -107,10 +70,7 @@ bool nfc_scene_emv_read_success_on_event(void* context, SceneManagerEvent event) scene_manager_next_scene(nfc->scene_manager, NfcSceneRetryConfirm); consumed = true; } else if(event.event == GuiButtonTypeRight) { - // Clear device name - nfc_device_set_name(nfc->dev, ""); - nfc->dev->format = NfcDeviceSaveFormatBankCard; - scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveName); + scene_manager_next_scene(nfc->scene_manager, NfcSceneEmvMenu); consumed = true; } } else if(event.type == SceneManagerEventTypeBack) { diff --git a/applications/nfc/scenes/nfc_scene_file_select.c b/applications/nfc/scenes/nfc_scene_file_select.c index 0278c3b9c..693fdec20 100755 --- a/applications/nfc/scenes/nfc_scene_file_select.c +++ b/applications/nfc/scenes/nfc_scene_file_select.c @@ -6,6 +6,7 @@ void nfc_scene_file_select_on_enter(void* context) { // Process file_select return nfc_device_set_loading_callback(nfc->dev, nfc_show_loading_popup, nfc); if(nfc_file_select(nfc->dev)) { + scene_manager_set_scene_state(nfc->scene_manager, NfcSceneSavedMenu, 0); scene_manager_next_scene(nfc->scene_manager, NfcSceneSavedMenu); } else { scene_manager_search_and_switch_to_previous_scene(nfc->scene_manager, NfcSceneStart); diff --git a/applications/nfc/scenes/nfc_scene_mf_classic_info.c b/applications/nfc/scenes/nfc_scene_mf_classic_info.c deleted file mode 100644 index b658dfa48..000000000 --- a/applications/nfc/scenes/nfc_scene_mf_classic_info.c +++ /dev/null @@ -1,72 +0,0 @@ -#include "../nfc_i.h" - -void nfc_scene_mf_classic_info_widget_callback(GuiButtonType result, InputType type, void* context) { - furi_assert(context); - Nfc* nfc = context; - - if(type == InputTypeShort) { - view_dispatcher_send_custom_event(nfc->view_dispatcher, result); - } -} - -void nfc_scene_mf_classic_info_on_enter(void* context) { - Nfc* nfc = context; - NfcDeviceData* dev_data = &nfc->dev->dev_data; - MfClassicData* mf_data = &dev_data->mf_classic_data; - string_t str_tmp; - string_init(str_tmp); - - // Setup view - Widget* widget = nfc->widget; - - widget_add_string_element( - widget, 0, 0, AlignLeft, AlignTop, FontSecondary, mf_classic_get_type_str(mf_data->type)); - widget_add_string_element( - widget, 0, 11, AlignLeft, AlignTop, FontSecondary, "ISO 14443-3 (Type A)"); - string_printf(str_tmp, "UID:"); - for(size_t i = 0; i < dev_data->nfc_data.uid_len; i++) { - string_cat_printf(str_tmp, " %02X", dev_data->nfc_data.uid[i]); - } - widget_add_string_element( - widget, 0, 22, AlignLeft, AlignTop, FontSecondary, string_get_cstr(str_tmp)); - string_printf( - str_tmp, - "ATQA: %02X %02X SAK: %02X", - dev_data->nfc_data.atqa[0], - dev_data->nfc_data.atqa[1], - dev_data->nfc_data.sak); - widget_add_string_element( - widget, 0, 33, AlignLeft, AlignTop, FontSecondary, string_get_cstr(str_tmp)); - uint8_t sectors_total = mf_classic_get_total_sectors_num(mf_data->type); - uint8_t keys_total = sectors_total * 2; - uint8_t keys_found = 0; - uint8_t sectors_read = 0; - mf_classic_get_read_sectors_and_keys(mf_data, §ors_read, &keys_found); - string_printf(str_tmp, "Keys Found: %d/%d", keys_found, keys_total); - widget_add_string_element( - widget, 0, 44, AlignLeft, AlignTop, FontSecondary, string_get_cstr(str_tmp)); - string_printf(str_tmp, "Sectors Read: %d/%d", sectors_read, sectors_total); - widget_add_string_element( - widget, 0, 55, AlignLeft, AlignTop, FontSecondary, string_get_cstr(str_tmp)); - - string_clear(str_tmp); - view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget); -} - -bool nfc_scene_mf_classic_info_on_event(void* context, SceneManagerEvent event) { - Nfc* nfc = context; - bool consumed = false; - - if(event.type == SceneManagerEventTypeBack) { - consumed = scene_manager_previous_scene(nfc->scene_manager); - } - - return consumed; -} - -void nfc_scene_mf_classic_info_on_exit(void* context) { - Nfc* nfc = context; - - // Clear view - widget_reset(nfc->widget); -} diff --git a/applications/nfc/scenes/nfc_scene_mf_classic_keys.c b/applications/nfc/scenes/nfc_scene_mf_classic_keys.c index 0faa73673..fcb8bc189 100644 --- a/applications/nfc/scenes/nfc_scene_mf_classic_keys.c +++ b/applications/nfc/scenes/nfc_scene_mf_classic_keys.c @@ -34,6 +34,7 @@ void nfc_scene_mf_classic_keys_on_enter(void* context) { widget_add_string_element(nfc->widget, 0, 32, AlignLeft, AlignTop, FontSecondary, temp_str); widget_add_button_element( nfc->widget, GuiButtonTypeCenter, "Add", nfc_scene_mf_classic_keys_widget_callback, nfc); + widget_add_icon_element(nfc->widget, 90, 12, &I_Keychain); view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget); } diff --git a/applications/nfc/scenes/nfc_scene_mf_classic_menu.c b/applications/nfc/scenes/nfc_scene_mf_classic_menu.c index 6ee0ad868..76d02e01e 100644 --- a/applications/nfc/scenes/nfc_scene_mf_classic_menu.c +++ b/applications/nfc/scenes/nfc_scene_mf_classic_menu.c @@ -50,7 +50,7 @@ bool nfc_scene_mf_classic_menu_on_event(void* context, SceneManagerEvent event) } else if(event.event == SubmenuIndexInfo) { scene_manager_set_scene_state( nfc->scene_manager, NfcSceneMfClassicMenu, SubmenuIndexInfo); - scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicInfo); + scene_manager_next_scene(nfc->scene_manager, NfcSceneNfcDataInfo); consumed = true; } } else if(event.type == SceneManagerEventTypeBack) { diff --git a/applications/nfc/scenes/nfc_scene_mf_classic_read_success.c b/applications/nfc/scenes/nfc_scene_mf_classic_read_success.c index bd782305c..efe676706 100644 --- a/applications/nfc/scenes/nfc_scene_mf_classic_read_success.c +++ b/applications/nfc/scenes/nfc_scene_mf_classic_read_success.c @@ -17,8 +17,6 @@ void nfc_scene_mf_classic_read_success_on_enter(void* context) { Nfc* nfc = context; NfcDeviceData* dev_data = &nfc->dev->dev_data; MfClassicData* mf_data = &dev_data->mf_classic_data; - string_t str_tmp; - string_init(str_tmp); DOLPHIN_DEED(DolphinDeedNfcReadSuccess); @@ -29,48 +27,27 @@ void nfc_scene_mf_classic_read_success_on_enter(void* context) { widget_add_button_element( widget, GuiButtonTypeRight, "More", nfc_scene_mf_classic_read_success_widget_callback, nfc); + string_t temp_str; if(string_size(nfc->dev->dev_data.parsed_data)) { - widget_add_text_box_element( - nfc->widget, - 0, - 0, - 128, - 32, - AlignLeft, - AlignTop, - string_get_cstr(nfc->dev->dev_data.parsed_data), - true); + string_init_set(temp_str, nfc->dev->dev_data.parsed_data); } else { - widget_add_string_element( - widget, - 0, - 0, - AlignLeft, - AlignTop, - FontSecondary, - mf_classic_get_type_str(mf_data->type)); - widget_add_string_element( - widget, 0, 11, AlignLeft, AlignTop, FontSecondary, "ISO 14443-3 (Type A)"); - string_printf(str_tmp, "UID:"); + string_init_printf(temp_str, "\e#%s\n", nfc_mf_classic_type(mf_data->type)); + string_cat_printf(temp_str, "UID:"); for(size_t i = 0; i < dev_data->nfc_data.uid_len; i++) { - string_cat_printf(str_tmp, " %02X", dev_data->nfc_data.uid[i]); + string_cat_printf(temp_str, " %02X", dev_data->nfc_data.uid[i]); } - widget_add_string_element( - widget, 0, 22, AlignLeft, AlignTop, FontSecondary, string_get_cstr(str_tmp)); uint8_t sectors_total = mf_classic_get_total_sectors_num(mf_data->type); uint8_t keys_total = sectors_total * 2; uint8_t keys_found = 0; uint8_t sectors_read = 0; mf_classic_get_read_sectors_and_keys(mf_data, §ors_read, &keys_found); - string_printf(str_tmp, "Keys Found: %d/%d", keys_found, keys_total); - widget_add_string_element( - widget, 0, 33, AlignLeft, AlignTop, FontSecondary, string_get_cstr(str_tmp)); - string_printf(str_tmp, "Sectors Read: %d/%d", sectors_read, sectors_total); - widget_add_string_element( - widget, 0, 44, AlignLeft, AlignTop, FontSecondary, string_get_cstr(str_tmp)); + string_cat_printf(temp_str, "\nKeys Found: %d/%d", keys_found, keys_total); + string_cat_printf(temp_str, "\nSectors Read: %d/%d", sectors_read, sectors_total); } - string_clear(str_tmp); + widget_add_text_scroll_element(widget, 0, 0, 128, 52, string_get_cstr(temp_str)); + string_clear(temp_str); + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget); } diff --git a/applications/nfc/scenes/nfc_scene_mf_desfire_menu.c b/applications/nfc/scenes/nfc_scene_mf_desfire_menu.c index f15251143..1e2f2d2f2 100644 --- a/applications/nfc/scenes/nfc_scene_mf_desfire_menu.c +++ b/applications/nfc/scenes/nfc_scene_mf_desfire_menu.c @@ -2,6 +2,8 @@ enum SubmenuIndex { SubmenuIndexSave, + SubmenuIndexEmulateUid, + SubmenuIndexInfo, }; void nfc_scene_mf_desfire_menu_submenu_callback(void* context, uint32_t index) { @@ -16,6 +18,15 @@ void nfc_scene_mf_desfire_menu_on_enter(void* context) { submenu_add_item( submenu, "Save", SubmenuIndexSave, nfc_scene_mf_desfire_menu_submenu_callback, nfc); + submenu_add_item( + submenu, + "Emulate UID", + SubmenuIndexEmulateUid, + nfc_scene_mf_desfire_menu_submenu_callback, + nfc); + submenu_add_item( + submenu, "Info", SubmenuIndexInfo, nfc_scene_mf_desfire_menu_submenu_callback, nfc); + submenu_set_selected_item( nfc->submenu, scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMfDesfireMenu)); @@ -35,6 +46,12 @@ bool nfc_scene_mf_desfire_menu_on_event(void* context, SceneManagerEvent event) nfc_device_set_name(nfc->dev, ""); scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveName); consumed = true; + } else if(event.event == SubmenuIndexEmulateUid) { + scene_manager_next_scene(nfc->scene_manager, NfcSceneEmulateUid); + consumed = true; + } else if(event.event == SubmenuIndexInfo) { + scene_manager_next_scene(nfc->scene_manager, NfcSceneNfcDataInfo); + consumed = true; } } diff --git a/applications/nfc/scenes/nfc_scene_mf_desfire_read_success.c b/applications/nfc/scenes/nfc_scene_mf_desfire_read_success.c index a04f4e55c..4827c2851 100644 --- a/applications/nfc/scenes/nfc_scene_mf_desfire_read_success.c +++ b/applications/nfc/scenes/nfc_scene_mf_desfire_read_success.c @@ -1,90 +1,85 @@ #include "../nfc_i.h" #include -#define NFC_SCENE_READ_SUCCESS_SHIFT " " - -enum { - MfDesfireReadSuccessStateShowUID, - MfDesfireReadSuccessStateShowData, -}; - -void nfc_scene_mf_desfire_read_success_dialog_callback(DialogExResult result, void* context) { +void nfc_scene_mf_desfire_read_success_widget_callback( + GuiButtonType result, + InputType type, + void* context) { Nfc* nfc = context; - view_dispatcher_send_custom_event(nfc->view_dispatcher, result); + if(type == InputTypeShort) { + view_dispatcher_send_custom_event(nfc->view_dispatcher, result); + } } void nfc_scene_mf_desfire_read_success_on_enter(void* context) { Nfc* nfc = context; + FuriHalNfcDevData* nfc_data = &nfc->dev->dev_data.nfc_data; MifareDesfireData* data = &nfc->dev->dev_data.mf_df_data; - DialogEx* dialog_ex = nfc->dialog_ex; - dialog_ex_set_left_button_text(dialog_ex, "Retry"); - dialog_ex_set_center_button_text(dialog_ex, "Data"); - dialog_ex_set_right_button_text(dialog_ex, "More"); - dialog_ex_set_icon(dialog_ex, 8, 16, &I_Medium_chip_22x21); + Widget* widget = nfc->widget; + + // Prepare string for data display + string_t temp_str; + string_init_printf(temp_str, "\e#MIFARE DESfire\n"); + string_cat_printf(temp_str, "UID:"); + for(size_t i = 0; i < nfc_data->uid_len; i++) { + string_cat_printf(temp_str, " %02X", nfc_data->uid[i]); + } + + uint32_t bytes_total = 1 << (data->version.sw_storage >> 1); + uint32_t bytes_free = data->free_memory ? data->free_memory->bytes : 0; + string_cat_printf(temp_str, "\n%d", bytes_total); + if(data->version.sw_storage & 1) { + string_push_back(temp_str, '+'); + } + string_cat_printf(temp_str, " bytes, %d bytes free\n", bytes_free); uint16_t n_apps = 0; uint16_t n_files = 0; - for(MifareDesfireApplication* app = data->app_head; app; app = app->next) { n_apps++; for(MifareDesfireFile* file = app->file_head; file; file = file->next) { n_files++; } } + string_cat_printf(temp_str, "%d Application", n_apps); + if(n_apps != 1) { + string_push_back(temp_str, 's'); + } + string_cat_printf(temp_str, ", %d file", n_files); + if(n_files != 1) { + string_push_back(temp_str, 's'); + } - // TODO rework info view - nfc_text_store_set( - nfc, - NFC_SCENE_READ_SUCCESS_SHIFT "Mifare DESFire\n" NFC_SCENE_READ_SUCCESS_SHIFT - "%d%s bytes\n" NFC_SCENE_READ_SUCCESS_SHIFT "%d bytes free\n" - "%d application%s, %d file%s", - 1 << (data->version.sw_storage >> 1), - (data->version.sw_storage & 1) ? "+" : "", - data->free_memory ? data->free_memory->bytes : 0, - n_apps, - n_apps == 1 ? "" : "s", - n_files, - n_files == 1 ? "" : "s"); - dialog_ex_set_text(dialog_ex, nfc->text_store, 8, 6, AlignLeft, AlignTop); - dialog_ex_set_context(dialog_ex, nfc); - dialog_ex_set_result_callback(dialog_ex, nfc_scene_mf_desfire_read_success_dialog_callback); + // Add text scroll element + widget_add_text_scroll_element(widget, 0, 0, 128, 52, string_get_cstr(temp_str)); + string_clear(temp_str); - scene_manager_set_scene_state( - nfc->scene_manager, NfcSceneMfDesfireReadSuccess, MfDesfireReadSuccessStateShowUID); - view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewDialogEx); + // Add button elements + widget_add_button_element( + widget, GuiButtonTypeLeft, "Retry", nfc_scene_mf_desfire_read_success_widget_callback, nfc); + widget_add_button_element( + widget, GuiButtonTypeRight, "More", nfc_scene_mf_desfire_read_success_widget_callback, nfc); + + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget); } bool nfc_scene_mf_desfire_read_success_on_event(void* context, SceneManagerEvent event) { Nfc* nfc = context; bool consumed = false; - uint32_t state = - scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMfDesfireReadSuccess); if(event.type == SceneManagerEventTypeCustom) { - if(state == MfDesfireReadSuccessStateShowUID && event.event == DialogExResultLeft) { + if(event.event == GuiButtonTypeLeft) { scene_manager_next_scene(nfc->scene_manager, NfcSceneRetryConfirm); consumed = true; - } else if(state == MfDesfireReadSuccessStateShowUID && event.event == DialogExResultCenter) { - scene_manager_next_scene(nfc->scene_manager, NfcSceneMfDesfireData); - consumed = true; - } else if(state == MfDesfireReadSuccessStateShowUID && event.event == DialogExResultRight) { + } else if(event.event == GuiButtonTypeRight) { scene_manager_next_scene(nfc->scene_manager, NfcSceneMfDesfireMenu); consumed = true; } } else if(event.type == SceneManagerEventTypeBack) { - if(state == MfDesfireReadSuccessStateShowData) { - view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewDialogEx); - scene_manager_set_scene_state( - nfc->scene_manager, - NfcSceneMfDesfireReadSuccess, - MfDesfireReadSuccessStateShowUID); - consumed = true; - } else { - scene_manager_next_scene(nfc->scene_manager, NfcSceneExitConfirm); - consumed = true; - } + scene_manager_next_scene(nfc->scene_manager, NfcSceneExitConfirm); + consumed = true; } return consumed; @@ -94,5 +89,5 @@ void nfc_scene_mf_desfire_read_success_on_exit(void* context) { Nfc* nfc = context; // Clean dialog - dialog_ex_reset(nfc->dialog_ex); + widget_reset(nfc->widget); } diff --git a/applications/nfc/scenes/nfc_scene_mf_ultralight_data.c b/applications/nfc/scenes/nfc_scene_mf_ultralight_data.c new file mode 100644 index 000000000..d4184a6b4 --- /dev/null +++ b/applications/nfc/scenes/nfc_scene_mf_ultralight_data.c @@ -0,0 +1,32 @@ +#include "../nfc_i.h" + +void nfc_scene_mf_ultralight_data_on_enter(void* context) { + Nfc* nfc = context; + MfUltralightData* data = &nfc->dev->dev_data.mf_ul_data; + TextBox* text_box = nfc->text_box; + + text_box_set_font(text_box, TextBoxFontHex); + for(uint16_t i = 0; i < data->data_size; i += 2) { + if(!(i % 8) && i) { + string_push_back(nfc->text_box_store, '\n'); + } + string_cat_printf(nfc->text_box_store, "%02X%02X ", data->data[i], data->data[i + 1]); + } + text_box_set_text(text_box, string_get_cstr(nfc->text_box_store)); + + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewTextBox); +} + +bool nfc_scene_mf_ultralight_data_on_event(void* context, SceneManagerEvent event) { + UNUSED(context); + UNUSED(event); + return false; +} + +void nfc_scene_mf_ultralight_data_on_exit(void* context) { + Nfc* nfc = context; + + // Clean view + text_box_reset(nfc->text_box); + string_reset(nfc->text_box_store); +} \ No newline at end of file diff --git a/applications/nfc/scenes/nfc_scene_mf_ultralight_menu.c b/applications/nfc/scenes/nfc_scene_mf_ultralight_menu.c index 9174a8b19..ba9f22338 100644 --- a/applications/nfc/scenes/nfc_scene_mf_ultralight_menu.c +++ b/applications/nfc/scenes/nfc_scene_mf_ultralight_menu.c @@ -4,6 +4,7 @@ enum SubmenuIndex { SubmenuIndexUnlock, SubmenuIndexSave, SubmenuIndexEmulate, + SubmenuIndexInfo, }; void nfc_scene_mf_ultralight_menu_submenu_callback(void* context, uint32_t index) { @@ -33,6 +34,9 @@ void nfc_scene_mf_ultralight_menu_on_enter(void* context) { SubmenuIndexEmulate, nfc_scene_mf_ultralight_menu_submenu_callback, nfc); + submenu_add_item( + submenu, "Info", SubmenuIndexInfo, nfc_scene_mf_ultralight_menu_submenu_callback, nfc); + submenu_set_selected_item( nfc->submenu, scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMfUltralightMenu)); @@ -56,6 +60,9 @@ bool nfc_scene_mf_ultralight_menu_on_event(void* context, SceneManagerEvent even } else if(event.event == SubmenuIndexUnlock) { scene_manager_next_scene(nfc->scene_manager, NfcSceneMfUltralightUnlockMenu); consumed = true; + } else if(event.event == SubmenuIndexInfo) { + scene_manager_next_scene(nfc->scene_manager, NfcSceneNfcDataInfo); + consumed = true; } scene_manager_set_scene_state(nfc->scene_manager, NfcSceneMfUltralightMenu, event.event); diff --git a/applications/nfc/scenes/nfc_scene_mf_ultralight_read_success.c b/applications/nfc/scenes/nfc_scene_mf_ultralight_read_success.c index 65750b963..d775bb71d 100644 --- a/applications/nfc/scenes/nfc_scene_mf_ultralight_read_success.c +++ b/applications/nfc/scenes/nfc_scene_mf_ultralight_read_success.c @@ -1,11 +1,6 @@ #include "../nfc_i.h" #include -enum { - ReadMifareUlStateShowInfo, - ReadMifareUlStateShowData, -}; - void nfc_scene_mf_ultralight_read_success_widget_callback( GuiButtonType result, InputType type, @@ -31,12 +26,6 @@ void nfc_scene_mf_ultralight_read_success_on_enter(void* context) { "Retry", nfc_scene_mf_ultralight_read_success_widget_callback, nfc); - widget_add_button_element( - widget, - GuiButtonTypeCenter, - "Data", - nfc_scene_mf_ultralight_read_success_widget_callback, - nfc); widget_add_button_element( widget, GuiButtonTypeRight, @@ -44,71 +33,38 @@ void nfc_scene_mf_ultralight_read_success_on_enter(void* context) { nfc_scene_mf_ultralight_read_success_widget_callback, nfc); - widget_add_string_element( - widget, 0, 0, AlignLeft, AlignTop, FontSecondary, nfc_mf_ul_type(mf_ul_data->type, true)); - string_t data_str; - string_init_printf(data_str, "UID:"); + string_t temp_str; + string_init_printf(temp_str, "\e#%s\n", nfc_mf_ul_type(mf_ul_data->type, true)); + string_cat_printf(temp_str, "UID:"); for(size_t i = 0; i < data->uid_len; i++) { - string_cat_printf(data_str, " %02X", data->uid[i]); + string_cat_printf(temp_str, " %02X", data->uid[i]); } - widget_add_string_element( - widget, 0, 13, AlignLeft, AlignTop, FontSecondary, string_get_cstr(data_str)); - string_printf( - data_str, "Pages Read: %d/%d", mf_ul_data->data_read / 4, mf_ul_data->data_size / 4); - widget_add_string_element( - widget, 0, 24, AlignLeft, AlignTop, FontSecondary, string_get_cstr(data_str)); + string_cat_printf( + temp_str, "\nPages Read: %d/%d", mf_ul_data->data_read / 4, mf_ul_data->data_size / 4); if(mf_ul_data->data_read != mf_ul_data->data_size) { - widget_add_string_element( - widget, 0, 35, AlignLeft, AlignTop, FontSecondary, "Password-protected pages!"); + string_cat_printf(temp_str, "\nPassword-protected pages!"); } - string_clear(data_str); + widget_add_text_scroll_element(widget, 0, 0, 128, 52, string_get_cstr(temp_str)); + string_clear(temp_str); - // Setup TextBox view - TextBox* text_box = nfc->text_box; - text_box_set_font(text_box, TextBoxFontHex); - for(uint16_t i = 0; i < mf_ul_data->data_size; i += 2) { - if(!(i % 8) && i) { - string_push_back(nfc->text_box_store, '\n'); - } - string_cat_printf( - nfc->text_box_store, "%02X%02X ", mf_ul_data->data[i], mf_ul_data->data[i + 1]); - } - text_box_set_text(text_box, string_get_cstr(nfc->text_box_store)); - - scene_manager_set_scene_state( - nfc->scene_manager, NfcSceneMfUltralightReadSuccess, ReadMifareUlStateShowInfo); view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget); } bool nfc_scene_mf_ultralight_read_success_on_event(void* context, SceneManagerEvent event) { Nfc* nfc = context; bool consumed = false; - uint32_t state = - scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMfUltralightReadSuccess); if(event.type == SceneManagerEventTypeCustom) { - if(state == ReadMifareUlStateShowInfo && event.event == GuiButtonTypeLeft) { + if(event.event == GuiButtonTypeLeft) { scene_manager_next_scene(nfc->scene_manager, NfcSceneRetryConfirm); consumed = true; - } else if(state == ReadMifareUlStateShowInfo && event.event == GuiButtonTypeRight) { + } else if(event.event == GuiButtonTypeRight) { scene_manager_next_scene(nfc->scene_manager, NfcSceneMfUltralightMenu); consumed = true; - } else if(state == ReadMifareUlStateShowInfo && event.event == GuiButtonTypeCenter) { - view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewTextBox); - scene_manager_set_scene_state( - nfc->scene_manager, NfcSceneMfUltralightReadSuccess, ReadMifareUlStateShowData); - consumed = true; } } else if(event.type == SceneManagerEventTypeBack) { - if(state == ReadMifareUlStateShowData) { - view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget); - scene_manager_set_scene_state( - nfc->scene_manager, NfcSceneMfUltralightReadSuccess, ReadMifareUlStateShowInfo); - consumed = true; - } else { - scene_manager_next_scene(nfc->scene_manager, NfcSceneExitConfirm); - consumed = true; - } + scene_manager_next_scene(nfc->scene_manager, NfcSceneExitConfirm); + consumed = true; } return consumed; @@ -117,8 +73,6 @@ bool nfc_scene_mf_ultralight_read_success_on_event(void* context, SceneManagerEv void nfc_scene_mf_ultralight_read_success_on_exit(void* context) { Nfc* nfc = context; - // Clean views + // Clean view widget_reset(nfc->widget); - text_box_reset(nfc->text_box); - string_reset(nfc->text_box_store); } diff --git a/applications/nfc/scenes/nfc_scene_nfc_data_info.c b/applications/nfc/scenes/nfc_scene_nfc_data_info.c new file mode 100644 index 000000000..33f5e44af --- /dev/null +++ b/applications/nfc/scenes/nfc_scene_nfc_data_info.c @@ -0,0 +1,133 @@ +#include "../nfc_i.h" + +void nfc_scene_nfc_data_info_widget_callback(GuiButtonType result, InputType type, void* context) { + Nfc* nfc = context; + if(type == InputTypeShort) { + view_dispatcher_send_custom_event(nfc->view_dispatcher, result); + } +} + +void nfc_scene_nfc_data_info_on_enter(void* context) { + Nfc* nfc = context; + Widget* widget = nfc->widget; + FuriHalNfcDevData* nfc_data = &nfc->dev->dev_data.nfc_data; + NfcDeviceData* dev_data = &nfc->dev->dev_data; + NfcProtocol protocol = dev_data->protocol; + uint8_t text_scroll_height = 0; + if((protocol == NfcDeviceProtocolMifareDesfire) || (protocol == NfcDeviceProtocolMifareUl)) { + widget_add_button_element( + widget, GuiButtonTypeRight, "More", nfc_scene_nfc_data_info_widget_callback, nfc); + text_scroll_height = 52; + } else { + text_scroll_height = 64; + } + + string_t temp_str; + string_init(temp_str); + // Set name if present + if(nfc->dev->dev_name[0] != '\0') { + string_printf(temp_str, "\ec%s\n", nfc->dev->dev_name); + } + + // Set tag type + if(protocol == NfcDeviceProtocolEMV) { + string_cat_printf(temp_str, "\e#EMV Bank Card\n"); + } else if(protocol == NfcDeviceProtocolMifareUl) { + string_cat_printf(temp_str, "\e#%s\n", nfc_mf_ul_type(dev_data->mf_ul_data.type, true)); + } else if(protocol == NfcDeviceProtocolMifareClassic) { + string_cat_printf( + temp_str, "\e#%s\n", nfc_mf_classic_type(dev_data->mf_classic_data.type)); + } else if(protocol == NfcDeviceProtocolMifareDesfire) { + string_cat_printf(temp_str, "\e#MIFARE DESfire\n"); + } else { + string_cat_printf(temp_str, "\e#Unknown ISO tag\n"); + } + + // Set tag iso data + char iso_type = FURI_BIT(nfc_data->sak, 5) ? '4' : '3'; + string_cat_printf(temp_str, "ISO 14443-%c (NFC-A)\n", iso_type); + string_cat_printf(temp_str, "UID:"); + for(size_t i = 0; i < nfc_data->uid_len; i++) { + string_cat_printf(temp_str, " %02X", nfc_data->uid[i]); + } + string_cat_printf(temp_str, "\nATQA: %02X %02X ", nfc_data->atqa[1], nfc_data->atqa[0]); + string_cat_printf(temp_str, " SAK: %02X", nfc_data->sak); + + // Set application specific data + if(protocol == NfcDeviceProtocolMifareDesfire) { + MifareDesfireData* data = &dev_data->mf_df_data; + uint32_t bytes_total = 1 << (data->version.sw_storage >> 1); + uint32_t bytes_free = data->free_memory ? data->free_memory->bytes : 0; + string_cat_printf(temp_str, "\n%d", bytes_total); + if(data->version.sw_storage & 1) { + string_push_back(temp_str, '+'); + } + string_cat_printf(temp_str, " bytes, %d bytes free\n", bytes_free); + + uint16_t n_apps = 0; + uint16_t n_files = 0; + for(MifareDesfireApplication* app = data->app_head; app; app = app->next) { + n_apps++; + for(MifareDesfireFile* file = app->file_head; file; file = file->next) { + n_files++; + } + } + string_cat_printf(temp_str, "%d Application", n_apps); + if(n_apps != 1) { + string_push_back(temp_str, 's'); + } + string_cat_printf(temp_str, ", %d file", n_files); + if(n_files != 1) { + string_push_back(temp_str, 's'); + } + } else if(protocol == NfcDeviceProtocolMifareUl) { + MfUltralightData* data = &dev_data->mf_ul_data; + string_cat_printf( + temp_str, "\nPages Read %d/%d", data->data_read / 4, data->data_size / 4); + if(data->data_size > data->data_read) { + string_cat_printf(temp_str, "\nPassword-protected"); + } + } else if(protocol == NfcDeviceProtocolMifareClassic) { + MfClassicData* data = &dev_data->mf_classic_data; + uint8_t sectors_total = mf_classic_get_total_sectors_num(data->type); + uint8_t keys_total = sectors_total * 2; + uint8_t keys_found = 0; + uint8_t sectors_read = 0; + mf_classic_get_read_sectors_and_keys(data, §ors_read, &keys_found); + string_cat_printf(temp_str, "\nKeys Found %d/%d", keys_found, keys_total); + string_cat_printf(temp_str, "\nSectors Read %d/%d", sectors_read, sectors_total); + } + + // Add text scroll widget + widget_add_text_scroll_element( + widget, 0, 0, 128, text_scroll_height, string_get_cstr(temp_str)); + string_clear(temp_str); + + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget); +} + +bool nfc_scene_nfc_data_info_on_event(void* context, SceneManagerEvent event) { + Nfc* nfc = context; + NfcProtocol protocol = nfc->dev->dev_data.protocol; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == GuiButtonTypeRight) { + if(protocol == NfcDeviceProtocolMifareDesfire) { + scene_manager_next_scene(nfc->scene_manager, NfcSceneMfDesfireApp); + consumed = true; + } else if(protocol == NfcDeviceProtocolMifareUl) { + scene_manager_next_scene(nfc->scene_manager, NfcSceneMfUltralightData); + consumed = true; + } + } + } + + return consumed; +} + +void nfc_scene_nfc_data_info_on_exit(void* context) { + Nfc* nfc = context; + + widget_reset(nfc->widget); +} \ No newline at end of file diff --git a/applications/nfc/scenes/nfc_scene_nfca_menu.c b/applications/nfc/scenes/nfc_scene_nfca_menu.c new file mode 100644 index 000000000..00d0d943d --- /dev/null +++ b/applications/nfc/scenes/nfc_scene_nfca_menu.c @@ -0,0 +1,62 @@ +#include "../nfc_i.h" + +enum SubmenuIndex { + SubmenuIndexSaveUid, + SubmenuIndexEmulateUid, + SubmenuIndexInfo, +}; + +void nfc_scene_nfca_menu_submenu_callback(void* context, uint32_t index) { + Nfc* nfc = context; + + view_dispatcher_send_custom_event(nfc->view_dispatcher, index); +} + +void nfc_scene_nfca_menu_on_enter(void* context) { + Nfc* nfc = context; + Submenu* submenu = nfc->submenu; + + submenu_add_item( + submenu, "Save UID", SubmenuIndexSaveUid, nfc_scene_nfca_menu_submenu_callback, nfc); + submenu_add_item( + submenu, "Emulate UID", SubmenuIndexEmulateUid, nfc_scene_nfca_menu_submenu_callback, nfc); + submenu_add_item(submenu, "Info", SubmenuIndexInfo, nfc_scene_nfca_menu_submenu_callback, nfc); + + submenu_set_selected_item( + nfc->submenu, scene_manager_get_scene_state(nfc->scene_manager, NfcSceneNfcaMenu)); + + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu); +} + +bool nfc_scene_nfca_menu_on_event(void* context, SceneManagerEvent event) { + Nfc* nfc = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == SubmenuIndexSaveUid) { + nfc->dev->format = NfcDeviceSaveFormatUid; + // Clear device name + nfc_device_set_name(nfc->dev, ""); + scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveName); + consumed = true; + } else if(event.event == SubmenuIndexEmulateUid) { + scene_manager_next_scene(nfc->scene_manager, NfcSceneEmulateUid); + consumed = true; + } else if(event.event == SubmenuIndexInfo) { + scene_manager_next_scene(nfc->scene_manager, NfcSceneNfcDataInfo); + consumed = true; + } + scene_manager_set_scene_state(nfc->scene_manager, NfcSceneNfcaMenu, event.event); + } else if(event.type == SceneManagerEventTypeBack) { + consumed = scene_manager_previous_scene(nfc->scene_manager); + } + + return consumed; +} + +void nfc_scene_nfca_menu_on_exit(void* context) { + Nfc* nfc = context; + + // Clear view + submenu_reset(nfc->submenu); +} diff --git a/applications/nfc/scenes/nfc_scene_nfca_read_success.c b/applications/nfc/scenes/nfc_scene_nfca_read_success.c new file mode 100644 index 000000000..3467a03b6 --- /dev/null +++ b/applications/nfc/scenes/nfc_scene_nfca_read_success.c @@ -0,0 +1,72 @@ +#include "../nfc_i.h" +#include + +void nfc_scene_nfca_read_success_widget_callback( + GuiButtonType result, + InputType type, + void* context) { + furi_assert(context); + Nfc* nfc = context; + + if(type == InputTypeShort) { + view_dispatcher_send_custom_event(nfc->view_dispatcher, result); + } +} + +void nfc_scene_nfca_read_success_on_enter(void* context) { + Nfc* nfc = context; + + DOLPHIN_DEED(DolphinDeedNfcReadSuccess); + + // Setup view + FuriHalNfcDevData* data = &nfc->dev->dev_data.nfc_data; + Widget* widget = nfc->widget; + + string_t temp_str; + string_init_set_str(temp_str, "\e#Unknown ISO tag\n"); + + char iso_type = FURI_BIT(data->sak, 5) ? '4' : '3'; + string_cat_printf(temp_str, "ISO 14443-%c (NFC-A)\n", iso_type); + string_cat_printf(temp_str, "UID:"); + for(size_t i = 0; i < data->uid_len; i++) { + string_cat_printf(temp_str, " %02X", data->uid[i]); + } + string_cat_printf(temp_str, "\nATQA: %02X %02X ", data->atqa[1], data->atqa[0]); + string_cat_printf(temp_str, " SAK: %02X", data->sak); + + widget_add_text_scroll_element(widget, 0, 0, 128, 52, string_get_cstr(temp_str)); + string_clear(temp_str); + + widget_add_button_element( + widget, GuiButtonTypeLeft, "Retry", nfc_scene_nfca_read_success_widget_callback, nfc); + widget_add_button_element( + widget, GuiButtonTypeRight, "More", nfc_scene_nfca_read_success_widget_callback, nfc); + + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget); +} + +bool nfc_scene_nfca_read_success_on_event(void* context, SceneManagerEvent event) { + Nfc* nfc = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == GuiButtonTypeLeft) { + scene_manager_next_scene(nfc->scene_manager, NfcSceneRetryConfirm); + consumed = true; + } else if(event.event == GuiButtonTypeRight) { + scene_manager_next_scene(nfc->scene_manager, NfcSceneNfcaMenu); + consumed = true; + } + } else if(event.type == SceneManagerEventTypeBack) { + scene_manager_next_scene(nfc->scene_manager, NfcSceneExitConfirm); + consumed = true; + } + return consumed; +} + +void nfc_scene_nfca_read_success_on_exit(void* context) { + Nfc* nfc = context; + + // Clear view + widget_reset(nfc->widget); +} diff --git a/applications/nfc/scenes/nfc_scene_read.c b/applications/nfc/scenes/nfc_scene_read.c index 491b419ef..00b7c8fac 100644 --- a/applications/nfc/scenes/nfc_scene_read.c +++ b/applications/nfc/scenes/nfc_scene_read.c @@ -59,11 +59,14 @@ bool nfc_scene_read_on_event(void* context, SceneManagerEvent event) { if(event.type == SceneManagerEventTypeCustom) { if((event.event == NfcWorkerEventReadUidNfcB) || (event.event == NfcWorkerEventReadUidNfcF) || - (event.event == NfcWorkerEventReadUidNfcV) || - (event.event == NfcWorkerEventReadUidNfcA)) { + (event.event == NfcWorkerEventReadUidNfcV)) { notification_message(nfc->notifications, &sequence_success); scene_manager_next_scene(nfc->scene_manager, NfcSceneReadCardSuccess); consumed = true; + } else if(event.event == NfcWorkerEventReadUidNfcA) { + notification_message(nfc->notifications, &sequence_success); + scene_manager_next_scene(nfc->scene_manager, NfcSceneNfcaReadSuccess); + consumed = true; } else if(event.event == NfcWorkerEventReadMfUltralight) { notification_message(nfc->notifications, &sequence_success); scene_manager_next_scene(nfc->scene_manager, NfcSceneMfUltralightReadSuccess); diff --git a/applications/nfc/scenes/nfc_scene_read_card_success.c b/applications/nfc/scenes/nfc_scene_read_card_success.c index b889ce08d..0cb38cbdf 100755 --- a/applications/nfc/scenes/nfc_scene_read_card_success.c +++ b/applications/nfc/scenes/nfc_scene_read_card_success.c @@ -16,44 +16,26 @@ void nfc_scene_read_card_success_widget_callback( void nfc_scene_read_card_success_on_enter(void* context) { Nfc* nfc = context; - string_t data_str; - string_t uid_str; - string_init(data_str); - string_init(uid_str); + string_t temp_str; + string_init(temp_str); DOLPHIN_DEED(DolphinDeedNfcReadSuccess); // Setup view FuriHalNfcDevData* data = &nfc->dev->dev_data.nfc_data; Widget* widget = nfc->widget; - string_set_str(data_str, nfc_get_dev_type(data->type)); - string_set_str(uid_str, "UID:"); + string_set_str(temp_str, nfc_get_dev_type(data->type)); + widget_add_string_element( + widget, 64, 12, AlignCenter, AlignBottom, FontPrimary, string_get_cstr(temp_str)); + string_set_str(temp_str, "UID:"); for(uint8_t i = 0; i < data->uid_len; i++) { - string_cat_printf(uid_str, " %02X", data->uid[i]); + string_cat_printf(temp_str, " %02X", data->uid[i]); } - + widget_add_string_element( + widget, 64, 32, AlignCenter, AlignCenter, FontSecondary, string_get_cstr(temp_str)); widget_add_button_element( widget, GuiButtonTypeLeft, "Retry", nfc_scene_read_card_success_widget_callback, nfc); - if(data->type == FuriHalNfcTypeA) { - widget_add_button_element( - widget, GuiButtonTypeRight, "Save", nfc_scene_read_card_success_widget_callback, nfc); - widget_add_icon_element(widget, 8, 13, &I_Medium_chip_22x21); - widget_add_string_element( - widget, 37, 12, AlignLeft, AlignBottom, FontPrimary, string_get_cstr(data_str)); - string_printf( - data_str, "ATQA: %02X%02X\nSAK: %02X", data->atqa[0], data->atqa[1], data->sak); - widget_add_string_multiline_element( - widget, 37, 16, AlignLeft, AlignTop, FontSecondary, string_get_cstr(data_str)); - widget_add_string_element( - widget, 64, 46, AlignCenter, AlignBottom, FontSecondary, string_get_cstr(uid_str)); - } else { - widget_add_string_element( - widget, 64, 12, AlignCenter, AlignBottom, FontPrimary, string_get_cstr(data_str)); - widget_add_string_element( - widget, 64, 32, AlignCenter, AlignCenter, FontSecondary, string_get_cstr(uid_str)); - } - string_clear(data_str); - string_clear(uid_str); + string_clear(temp_str); view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget); } @@ -65,11 +47,6 @@ bool nfc_scene_read_card_success_on_event(void* context, SceneManagerEvent event if(event.type == SceneManagerEventTypeCustom) { if(event.event == GuiButtonTypeLeft) { consumed = scene_manager_previous_scene(nfc->scene_manager); - } else if(event.event == GuiButtonTypeRight) { - nfc->dev->format = NfcDeviceSaveFormatUid; - nfc_device_set_name(nfc->dev, ""); - scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveName); - consumed = true; } } return consumed; diff --git a/applications/nfc/scenes/nfc_scene_saved_menu.c b/applications/nfc/scenes/nfc_scene_saved_menu.c index e6b08e71b..c7aec5d87 100644 --- a/applications/nfc/scenes/nfc_scene_saved_menu.c +++ b/applications/nfc/scenes/nfc_scene_saved_menu.c @@ -44,8 +44,6 @@ void nfc_scene_saved_menu_on_enter(void* context) { } submenu_add_item( submenu, "Info", SubmenuIndexInfo, nfc_scene_saved_menu_submenu_callback, nfc); - submenu_set_selected_item( - nfc->submenu, scene_manager_get_scene_state(nfc->scene_manager, NfcSceneSavedMenu)); if(nfc->dev->shadow_file_exist) { submenu_add_item( submenu, @@ -58,12 +56,15 @@ void nfc_scene_saved_menu_on_enter(void* context) { submenu, "Rename", SubmenuIndexRename, nfc_scene_saved_menu_submenu_callback, nfc); submenu_add_item( submenu, "Delete", SubmenuIndexDelete, nfc_scene_saved_menu_submenu_callback, nfc); + submenu_set_selected_item( + nfc->submenu, scene_manager_get_scene_state(nfc->scene_manager, NfcSceneSavedMenu)); view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu); } bool nfc_scene_saved_menu_on_event(void* context, SceneManagerEvent event) { Nfc* nfc = context; + NfcDeviceData* dev_data = &nfc->dev->dev_data; bool consumed = false; if(event.type == SceneManagerEventTypeCustom) { @@ -87,7 +88,18 @@ bool nfc_scene_saved_menu_on_event(void* context, SceneManagerEvent event) { scene_manager_next_scene(nfc->scene_manager, NfcSceneDelete); consumed = true; } else if(event.event == SubmenuIndexInfo) { - scene_manager_next_scene(nfc->scene_manager, NfcSceneDeviceInfo); + bool application_info_present = false; + if(dev_data->protocol == NfcDeviceProtocolEMV) { + application_info_present = true; + } else if(dev_data->protocol == NfcDeviceProtocolMifareClassic) { + application_info_present = nfc_supported_card_verify_and_parse(dev_data); + } + + if(application_info_present) { + scene_manager_next_scene(nfc->scene_manager, NfcSceneDeviceInfo); + } else { + scene_manager_next_scene(nfc->scene_manager, NfcSceneNfcDataInfo); + } consumed = true; } else if(event.event == SubmenuIndexRestoreOriginal) { scene_manager_next_scene(nfc->scene_manager, NfcSceneRestoreOriginalConfirm); diff --git a/applications/nfc/views/bank_card.c b/applications/nfc/views/bank_card.c deleted file mode 100755 index 31cc56ee8..000000000 --- a/applications/nfc/views/bank_card.c +++ /dev/null @@ -1,80 +0,0 @@ -#include "bank_card.h" -#include "../helpers/nfc_emv_parser.h" -#include - -struct BankCard { - Widget* widget; -}; - -BankCard* bank_card_alloc() { - BankCard* bank_card = malloc(sizeof(BankCard)); - bank_card->widget = widget_alloc(); - return bank_card; -} - -void bank_card_free(BankCard* bank_card) { - furi_assert(bank_card); - widget_free(bank_card->widget); - free(bank_card); -} - -View* bank_card_get_view(BankCard* bank_card) { - furi_assert(bank_card); - return widget_get_view(bank_card->widget); -} - -void bank_card_clear(BankCard* bank_card) { - furi_assert(bank_card); - widget_reset(bank_card->widget); -} - -void bank_card_set_name(BankCard* bank_card, char* name) { - furi_assert(bank_card); - furi_assert(name); - widget_add_string_element( - bank_card->widget, 64, 6, AlignCenter, AlignTop, FontSecondary, name); -} - -void bank_card_set_number(BankCard* bank_card, uint8_t* number, uint8_t len) { - furi_assert(bank_card); - furi_assert(number); - string_t num_str; - string_init(num_str); - for(uint8_t i = 0; i < len; i += 2) { - string_cat_printf(num_str, "%02X%02X ", number[i], number[i + 1]); - } - // Add number - widget_add_string_element( - bank_card->widget, 64, 32, AlignCenter, AlignTop, FontSecondary, string_get_cstr(num_str)); - string_clear(num_str); - // Add icon - widget_add_icon_element(bank_card->widget, 8, 15, &I_Detailed_chip_17x13); - // Add frame - widget_add_frame_element(bank_card->widget, 0, 0, 128, 64, 6); -} - -void bank_card_set_back_callback(BankCard* bank_card, ButtonCallback callback, void* context) { - furi_assert(bank_card); - furi_assert(callback); - widget_add_button_element(bank_card->widget, GuiButtonTypeLeft, "Back", callback, context); -} - -void bank_card_set_exp_date(BankCard* bank_card, uint8_t mon, uint8_t year) { - furi_assert(bank_card); - char exp_date_str[16]; - snprintf(exp_date_str, sizeof(exp_date_str), "Exp: %02X/%02X", mon, year); - widget_add_string_element( - bank_card->widget, 122, 54, AlignRight, AlignBottom, FontSecondary, exp_date_str); -} - -void bank_card_set_country_name(BankCard* bank_card, const char* country_name) { - furi_assert(bank_card); - widget_add_string_element( - bank_card->widget, 120, 18, AlignRight, AlignTop, FontSecondary, country_name); -} - -void bank_card_set_currency_name(BankCard* bank_card, const char* currency_name) { - furi_assert(bank_card); - widget_add_string_element( - bank_card->widget, 31, 18, AlignLeft, AlignTop, FontSecondary, currency_name); -} diff --git a/applications/nfc/views/bank_card.h b/applications/nfc/views/bank_card.h deleted file mode 100644 index 628d9deb8..000000000 --- a/applications/nfc/views/bank_card.h +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once -#include -#include -#include - -typedef struct BankCard BankCard; - -BankCard* bank_card_alloc(); - -void bank_card_free(BankCard* bank_card); - -void bank_card_clear(BankCard* bank_card); - -View* bank_card_get_view(BankCard* bank_card); - -void bank_card_set_back_callback(BankCard* bank_card, ButtonCallback callback, void* context); - -void bank_card_set_name(BankCard* bank_card, char* name); - -void bank_card_set_number(BankCard* bank_card, uint8_t* number, uint8_t len); - -void bank_card_set_exp_date(BankCard* bank_card, uint8_t mon, uint8_t year); - -void bank_card_set_country_name(BankCard* bank_card, const char* country_name); - -void bank_card_set_currency_name(BankCard* bank_card, const char* currency_name); diff --git a/applications/subghz/scenes/subghz_scene_receiver_config.c b/applications/subghz/scenes/subghz_scene_receiver_config.c index bf2f0cdba..c59630f7e 100644 --- a/applications/subghz/scenes/subghz_scene_receiver_config.c +++ b/applications/subghz/scenes/subghz_scene_receiver_config.c @@ -100,7 +100,7 @@ static void subghz_scene_receiver_config_set_preset(VariableItem* item) { subghz_setting_get_preset_data_size(subghz->setting, index)); } -static void subghz_scene_receiver_config_set_hopping_runing(VariableItem* item) { +static void subghz_scene_receiver_config_set_hopping_running(VariableItem* item) { SubGhz* subghz = variable_item_get_context(item); uint8_t index = variable_item_get_current_value_index(item); @@ -176,7 +176,7 @@ void subghz_scene_receiver_config_on_enter(void* context) { subghz->variable_item_list, "Hopping:", HOPPING_COUNT, - subghz_scene_receiver_config_set_hopping_runing, + subghz_scene_receiver_config_set_hopping_running, subghz); value_index = subghz_scene_receiver_config_hopper_value_index( subghz->txrx->hopper_state, hopping_value, HOPPING_COUNT, subghz); diff --git a/applications/subghz/subghz_i.c b/applications/subghz/subghz_i.c index 316fefded..f78ac39e0 100644 --- a/applications/subghz/subghz_i.c +++ b/applications/subghz/subghz_i.c @@ -292,7 +292,7 @@ bool subghz_key_load(SubGhz* subghz, const char* file_path, bool show_dialog) { if(!strcmp(string_get_cstr(temp_str), "FuriHalSubGhzPresetCustom")) { //Todo add Custom_preset_module - //delete peset if it already exists + //delete preset if it already exists subghz_setting_delete_custom_preset( subghz->setting, string_get_cstr(subghz->txrx->preset->name)); //load custom preset from file diff --git a/applications/u2f/u2f.c b/applications/u2f/u2f.c index 051dca696..767733ce6 100644 --- a/applications/u2f/u2f.c +++ b/applications/u2f/u2f.c @@ -4,6 +4,7 @@ #include "u2f_data.h" #include #include +#include // for lfs_tobe32 #include "toolbox/sha256.h" #include "toolbox/hmac_sha256.h" @@ -256,6 +257,7 @@ static uint16_t u2f_authenticate(U2fData* U2F, uint8_t* buf) { uint8_t flags = 0; uint8_t hash[32]; uint8_t signature[64]; + uint32_t be_u2f_counter; if(u2f_data_check(false) == false) { U2F->ready = false; @@ -275,11 +277,14 @@ static uint16_t u2f_authenticate(U2fData* U2F, uint8_t* buf) { } U2F->user_present = false; + // The 4 byte counter is represented in big endian. Increment it before use + be_u2f_counter = lfs_tobe32(U2F->counter + 1); + // Generate hash sha256_start(&sha_ctx); sha256_update(&sha_ctx, req->app_id, 32); sha256_update(&sha_ctx, &flags, 1); - sha256_update(&sha_ctx, (uint8_t*)&(U2F->counter), 4); + sha256_update(&sha_ctx, (uint8_t*)&(be_u2f_counter), 4); sha256_update(&sha_ctx, req->challenge, 32); sha256_finish(&sha_ctx, hash); @@ -309,12 +314,12 @@ static uint16_t u2f_authenticate(U2fData* U2F, uint8_t* buf) { uECC_sign(priv_key, hash, 32, signature, U2F->p_curve); resp->user_present = flags; - resp->counter = U2F->counter; + resp->counter = be_u2f_counter; uint8_t signature_len = u2f_der_encode_signature(resp->signature, signature); memcpy(resp->signature + signature_len, state_no_error, 2); - FURI_LOG_D(TAG, "Counter: %lu", U2F->counter); U2F->counter++; + FURI_LOG_D(TAG, "Counter: %lu", U2F->counter); u2f_data_cnt_write(U2F->counter); if(U2F->callback != NULL) U2F->callback(U2fNotifyAuthSuccess, U2F->context); diff --git a/applications/u2f/u2f_data.c b/applications/u2f/u2f_data.c index 0419fc7e1..117fbdbe3 100644 --- a/applications/u2f/u2f_data.c +++ b/applications/u2f/u2f_data.c @@ -1,5 +1,5 @@ #include -#include "u2f_hid.h" +#include "u2f_data.h" #include #include #include @@ -28,7 +28,8 @@ #define U2F_DEVICE_KEY_VERSION 1 #define U2F_COUNTER_FILE_TYPE "Flipper U2F Counter File" -#define U2F_COUNTER_VERSION 1 +#define U2F_COUNTER_VERSION 2 +#define U2F_COUNTER_VERSION_OLD 1 #define U2F_COUNTER_CONTROL_VAL 0xAA5500FF @@ -359,6 +360,7 @@ bool u2f_data_cnt_read(uint32_t* cnt_val) { furi_assert(cnt_val); bool state = false; + bool old_counter = false; uint8_t iv[16]; U2fCounterData cnt; uint8_t cnt_encr[48]; @@ -376,9 +378,16 @@ bool u2f_data_cnt_read(uint32_t* cnt_val) { FURI_LOG_E(TAG, "Missing or incorrect header"); break; } - if(strcmp(string_get_cstr(filetype), U2F_COUNTER_FILE_TYPE) != 0 || - version != U2F_COUNTER_VERSION) { - FURI_LOG_E(TAG, "Type or version mismatch"); + if(strcmp(string_get_cstr(filetype), U2F_COUNTER_FILE_TYPE) != 0) { + FURI_LOG_E(TAG, "Type mismatch"); + break; + } + if(version == U2F_COUNTER_VERSION_OLD) { + // Counter is from previous U2F app version with endianness bug + FURI_LOG_W(TAG, "Counter from old version"); + old_counter = true; + } else if(version != U2F_COUNTER_VERSION) { + FURI_LOG_E(TAG, "Version mismatch"); break; } if(!flipper_format_read_hex(flipper_format, "IV", iv, 16)) { @@ -409,6 +418,13 @@ bool u2f_data_cnt_read(uint32_t* cnt_val) { flipper_format_free(flipper_format); furi_record_close(RECORD_STORAGE); string_clear(filetype); + + if(old_counter && state) { + // Change counter endianness and rewrite counter file + *cnt_val = __REV(cnt.counter); + state = u2f_data_cnt_write(*cnt_val); + } + return state; } diff --git a/assets/icons/NFC/Keychain.png b/assets/icons/NFC/Keychain.png new file mode 100644 index 000000000..7ba1b11da Binary files /dev/null and b/assets/icons/NFC/Keychain.png differ diff --git a/lib/nfc/nfc_device.c b/lib/nfc/nfc_device.c index 9da891327..0bfdb3dac 100644 --- a/lib/nfc/nfc_device.c +++ b/lib/nfc/nfc_device.c @@ -1217,6 +1217,7 @@ void nfc_device_data_clear(NfcDeviceData* dev_data) { void nfc_device_clear(NfcDevice* dev) { furi_assert(dev); + nfc_device_set_name(dev, ""); nfc_device_data_clear(&dev->dev_data); dev->format = NfcDeviceSaveFormatUid; string_reset(dev->load_path); diff --git a/lib/nfc/nfc_worker.c b/lib/nfc/nfc_worker.c index a92f148a2..45bbc5f41 100644 --- a/lib/nfc/nfc_worker.c +++ b/lib/nfc/nfc_worker.c @@ -143,7 +143,7 @@ static bool nfc_worker_read_mf_classic(NfcWorker* nfc_worker, FuriHalNfcTxRxCont if(nfc_supported_card[i].verify(nfc_worker, tx_rx)) { if(nfc_supported_card[i].read(nfc_worker, tx_rx)) { read_success = true; - nfc_supported_card[i].parse(nfc_worker); + nfc_supported_card[i].parse(nfc_worker->dev_data); } } } diff --git a/lib/nfc/parsers/nfc_supported_card.c b/lib/nfc/parsers/nfc_supported_card.c index 59482a123..480c970e7 100644 --- a/lib/nfc/parsers/nfc_supported_card.c +++ b/lib/nfc/parsers/nfc_supported_card.c @@ -11,3 +11,17 @@ NfcSupportedCard nfc_supported_card[NfcSupportedCardTypeEnd] = { .parse = troyka_parser_parse, }, }; + +bool nfc_supported_card_verify_and_parse(NfcDeviceData* dev_data) { + furi_assert(dev_data); + + bool card_parsed = false; + for(size_t i = 0; i < COUNT_OF(nfc_supported_card); i++) { + if(nfc_supported_card[i].parse(dev_data)) { + card_parsed = true; + break; + } + } + + return card_parsed; +} diff --git a/lib/nfc/parsers/nfc_supported_card.h b/lib/nfc/parsers/nfc_supported_card.h index 5c94c78cd..9b5d1c053 100644 --- a/lib/nfc/parsers/nfc_supported_card.h +++ b/lib/nfc/parsers/nfc_supported_card.h @@ -2,6 +2,7 @@ #include #include "../nfc_worker.h" +#include "../nfc_device.h" #include @@ -15,7 +16,7 @@ typedef bool (*NfcSupportedCardVerify)(NfcWorker* nfc_worker, FuriHalNfcTxRxCont typedef bool (*NfcSupportedCardRead)(NfcWorker* nfc_worker, FuriHalNfcTxRxContext* tx_rx); -typedef bool (*NfcSupportedCardParse)(NfcWorker* nfc_worker); +typedef bool (*NfcSupportedCardParse)(NfcDeviceData* dev_data); typedef struct { NfcProtocol protocol; @@ -25,3 +26,5 @@ typedef struct { } NfcSupportedCard; extern NfcSupportedCard nfc_supported_card[NfcSupportedCardTypeEnd]; + +bool nfc_supported_card_verify_and_parse(NfcDeviceData* dev_data); diff --git a/lib/nfc/parsers/troyka_parser.c b/lib/nfc/parsers/troyka_parser.c index 3167b5181..51ffa42e1 100644 --- a/lib/nfc/parsers/troyka_parser.c +++ b/lib/nfc/parsers/troyka_parser.c @@ -49,23 +49,31 @@ bool troyka_parser_read(NfcWorker* nfc_worker, FuriHalNfcTxRxContext* tx_rx) { return mf_classic_read_card(tx_rx, &reader, &nfc_worker->dev_data->mf_classic_data) == 16; } -bool troyka_parser_parse(NfcWorker* nfc_worker) { - MfClassicData* data = &nfc_worker->dev_data->mf_classic_data; - uint8_t* temp_ptr = &data->block[8 * 4 + 1].value[5]; - uint16_t balance = ((temp_ptr[0] << 8) | temp_ptr[1]) / 25; - temp_ptr = &data->block[8 * 4].value[3]; - uint32_t number = 0; - for(size_t i = 0; i < 4; i++) { - number <<= 8; - number |= temp_ptr[i]; - } - number >>= 4; +bool troyka_parser_parse(NfcDeviceData* dev_data) { + MfClassicData* data = &dev_data->mf_classic_data; + bool troyka_parsed = false; - string_printf( - nfc_worker->dev_data->parsed_data, - "Troyka Transport card\nNumber: %ld\nBalance: %d rub", - number, - balance); + do { + // Verify key + MfClassicSectorTrailer* sec_tr = mf_classic_get_sector_trailer_by_sector(data, 8); + uint64_t key = nfc_util_bytes2num(sec_tr->key_a, 6); + if(key != troyka_keys[8].key_a) break; - return true; + // Parse data + uint8_t* temp_ptr = &data->block[8 * 4 + 1].value[5]; + uint16_t balance = ((temp_ptr[0] << 8) | temp_ptr[1]) / 25; + temp_ptr = &data->block[8 * 4].value[3]; + uint32_t number = 0; + for(size_t i = 0; i < 4; i++) { + number <<= 8; + number |= temp_ptr[i]; + } + number >>= 4; + + string_printf( + dev_data->parsed_data, "\e#Troyka\nNum: %ld\nBalance: %d rur.", number, balance); + troyka_parsed = true; + } while(false); + + return troyka_parsed; } diff --git a/lib/nfc/parsers/troyka_parser.h b/lib/nfc/parsers/troyka_parser.h index 0d5cee233..445fe40e5 100644 --- a/lib/nfc/parsers/troyka_parser.h +++ b/lib/nfc/parsers/troyka_parser.h @@ -6,4 +6,4 @@ bool troyka_parser_verify(NfcWorker* nfc_worker, FuriHalNfcTxRxContext* tx_rx); bool troyka_parser_read(NfcWorker* nfc_worker, FuriHalNfcTxRxContext* tx_rx); -bool troyka_parser_parse(NfcWorker* nfc_worker); +bool troyka_parser_parse(NfcDeviceData* dev_data); diff --git a/lib/nfc/protocols/mifare_ultralight.c b/lib/nfc/protocols/mifare_ultralight.c index c043f2069..f637d378a 100644 --- a/lib/nfc/protocols/mifare_ultralight.c +++ b/lib/nfc/protocols/mifare_ultralight.c @@ -191,7 +191,7 @@ bool mf_ultralight_authenticate(FuriHalNfcTxRxContext* tx_rx, uint32_t key, uint } if(pack != NULL) { - *pack = (tx_rx->rx_data[0] << 8) | tx_rx->rx_data[1]; + *pack = (tx_rx->rx_data[1] << 8) | tx_rx->rx_data[0]; } FURI_LOG_I(TAG, "Auth success. Password: %08X. PACK: %04X", key, *pack); @@ -697,48 +697,6 @@ bool mf_ultralight_read_counters(FuriHalNfcTxRxContext* tx_rx, MfUltralightData* return counter_read == (is_single_counter ? 1 : 3); } -int16_t mf_ultralight_get_authlim( - FuriHalNfcTxRxContext* tx_rx, - MfUltralightReader* reader, - MfUltralightData* data) { - mf_ultralight_read_version(tx_rx, reader, data); - if(!(reader->supported_features & MfUltralightSupportAuth)) { - // No authentication - return -2; - } - - uint8_t config_pages_index; - if(data->type >= MfUltralightTypeUL11 && data->type <= MfUltralightTypeNTAG216) { - config_pages_index = reader->pages_to_read - 4; - } else if( - data->type >= MfUltralightTypeNTAGI2CPlus1K && - data->type <= MfUltralightTypeNTAGI2CPlus1K) { - config_pages_index = 0xe3; - } else { - // No config pages - return -2; - } - - if(!mf_ultralight_read_pages_direct(tx_rx, config_pages_index, data->data)) { - // Config pages are not readable due to protection - return -1; - } - - MfUltralightConfigPages* config_pages = (MfUltralightConfigPages*)&data->data; - if(config_pages->auth0 >= reader->pages_to_read) { - // Authentication is not configured - return -2; - } - - int16_t authlim = config_pages->access.authlim; - if(authlim > 0 && data->type >= MfUltralightTypeNTAGI2CPlus1K && - data->type <= MfUltralightTypeNTAGI2CPlus2K) { - authlim = 1 << authlim; - } - - return authlim; -} - bool mf_ultralight_read_tearing_flags(FuriHalNfcTxRxContext* tx_rx, MfUltralightData* data) { uint8_t flag_read = 0; diff --git a/lib/nfc/protocols/mifare_ultralight.h b/lib/nfc/protocols/mifare_ultralight.h index 727bffab2..9642824f7 100644 --- a/lib/nfc/protocols/mifare_ultralight.h +++ b/lib/nfc/protocols/mifare_ultralight.h @@ -56,13 +56,6 @@ typedef enum { MfUltralightTypeNum, } MfUltralightType; -typedef enum { - MfUltralightAuthLimitUnknown, - MfUltralightAuthLimitNotSupported, - MfUltralightAuthLimitConfigured, - MfUltralightAuthLimitNotConfigured, -} MfUltralightAuthLimit; - typedef enum { MfUltralightSupportNone = 0, MfUltralightSupportFastRead = 1 << 0, @@ -245,11 +238,6 @@ bool mf_ul_prepare_emulation_response( uint32_t* data_type, void* context); -int16_t mf_ultralight_get_authlim( - FuriHalNfcTxRxContext* tx_rx, - MfUltralightReader* reader, - MfUltralightData* data); - uint32_t mf_ul_pwdgen_amiibo(FuriHalNfcDevData* data); uint32_t mf_ul_pwdgen_xiaomi(FuriHalNfcDevData* data); diff --git a/lib/subghz/blocks/encoder.h b/lib/subghz/blocks/encoder.h index 80ffe4900..6ad734cbd 100644 --- a/lib/subghz/blocks/encoder.h +++ b/lib/subghz/blocks/encoder.h @@ -7,7 +7,7 @@ #include typedef struct { - bool is_runing; + bool is_running; size_t repeat; size_t front; size_t size_upload; diff --git a/lib/subghz/protocols/bett.c b/lib/subghz/protocols/bett.c index bd3b45feb..aca8b8c4f 100644 --- a/lib/subghz/protocols/bett.c +++ b/lib/subghz/protocols/bett.c @@ -94,7 +94,7 @@ void* subghz_protocol_encoder_bett_alloc(SubGhzEnvironment* environment) { instance->encoder.repeat = 10; instance->encoder.size_upload = 52; //max 24bit*2 + 2 (start, stop) instance->encoder.upload = malloc(instance->encoder.size_upload * sizeof(LevelDuration)); - instance->encoder.is_runing = false; + instance->encoder.is_running = false; return instance; } @@ -174,7 +174,7 @@ bool subghz_protocol_encoder_bett_deserialize(void* context, FlipperFormat* flip flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); subghz_protocol_encoder_bett_get_upload(instance); - instance->encoder.is_runing = true; + instance->encoder.is_running = true; res = true; } while(false); @@ -184,14 +184,14 @@ bool subghz_protocol_encoder_bett_deserialize(void* context, FlipperFormat* flip void subghz_protocol_encoder_bett_stop(void* context) { SubGhzProtocolEncoderBETT* instance = context; - instance->encoder.is_runing = false; + instance->encoder.is_running = false; } LevelDuration subghz_protocol_encoder_bett_yield(void* context) { SubGhzProtocolEncoderBETT* instance = context; - if(instance->encoder.repeat == 0 || !instance->encoder.is_runing) { - instance->encoder.is_runing = false; + if(instance->encoder.repeat == 0 || !instance->encoder.is_running) { + instance->encoder.is_running = false; return level_duration_reset(); } diff --git a/lib/subghz/protocols/came.c b/lib/subghz/protocols/came.c index d28b735c5..37048017e 100644 --- a/lib/subghz/protocols/came.c +++ b/lib/subghz/protocols/came.c @@ -85,7 +85,7 @@ void* subghz_protocol_encoder_came_alloc(SubGhzEnvironment* environment) { instance->encoder.repeat = 10; instance->encoder.size_upload = 52; //max 24bit*2 + 2 (start, stop) instance->encoder.upload = malloc(instance->encoder.size_upload * sizeof(LevelDuration)); - instance->encoder.is_runing = false; + instance->encoder.is_running = false; return instance; } @@ -157,7 +157,7 @@ bool subghz_protocol_encoder_came_deserialize(void* context, FlipperFormat* flip flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); subghz_protocol_encoder_came_get_upload(instance); - instance->encoder.is_runing = true; + instance->encoder.is_running = true; res = true; } while(false); @@ -167,14 +167,14 @@ bool subghz_protocol_encoder_came_deserialize(void* context, FlipperFormat* flip void subghz_protocol_encoder_came_stop(void* context) { SubGhzProtocolEncoderCame* instance = context; - instance->encoder.is_runing = false; + instance->encoder.is_running = false; } LevelDuration subghz_protocol_encoder_came_yield(void* context) { SubGhzProtocolEncoderCame* instance = context; - if(instance->encoder.repeat == 0 || !instance->encoder.is_runing) { - instance->encoder.is_runing = false; + if(instance->encoder.repeat == 0 || !instance->encoder.is_running) { + instance->encoder.is_running = false; return level_duration_reset(); } diff --git a/lib/subghz/protocols/came_twee.c b/lib/subghz/protocols/came_twee.c index 9bf87ea2b..b5b409c59 100644 --- a/lib/subghz/protocols/came_twee.c +++ b/lib/subghz/protocols/came_twee.c @@ -112,7 +112,7 @@ void* subghz_protocol_encoder_came_twee_alloc(SubGhzEnvironment* environment) { instance->encoder.repeat = 10; instance->encoder.size_upload = 1536; //max upload 92*14 = 1288 !!!! instance->encoder.upload = malloc(instance->encoder.size_upload * sizeof(LevelDuration)); - instance->encoder.is_runing = false; + instance->encoder.is_running = false; return instance; } @@ -261,7 +261,7 @@ bool subghz_protocol_encoder_came_twee_deserialize(void* context, FlipperFormat* subghz_protocol_came_twee_remote_controller(&instance->generic); subghz_protocol_encoder_came_twee_get_upload(instance); - instance->encoder.is_runing = true; + instance->encoder.is_running = true; res = true; } while(false); @@ -271,14 +271,14 @@ bool subghz_protocol_encoder_came_twee_deserialize(void* context, FlipperFormat* void subghz_protocol_encoder_came_twee_stop(void* context) { SubGhzProtocolEncoderCameTwee* instance = context; - instance->encoder.is_runing = false; + instance->encoder.is_running = false; } LevelDuration subghz_protocol_encoder_came_twee_yield(void* context) { SubGhzProtocolEncoderCameTwee* instance = context; - if(instance->encoder.repeat == 0 || !instance->encoder.is_runing) { - instance->encoder.is_runing = false; + if(instance->encoder.repeat == 0 || !instance->encoder.is_running) { + instance->encoder.is_running = false; return level_duration_reset(); } diff --git a/lib/subghz/protocols/chamberlain_code.c b/lib/subghz/protocols/chamberlain_code.c index 3128b71ec..6c99d8451 100644 --- a/lib/subghz/protocols/chamberlain_code.c +++ b/lib/subghz/protocols/chamberlain_code.c @@ -108,7 +108,7 @@ void* subghz_protocol_encoder_chamb_code_alloc(SubGhzEnvironment* environment) { instance->encoder.repeat = 10; instance->encoder.size_upload = 24; instance->encoder.upload = malloc(instance->encoder.size_upload * sizeof(LevelDuration)); - instance->encoder.is_runing = false; + instance->encoder.is_running = false; return instance; } @@ -225,7 +225,7 @@ bool subghz_protocol_encoder_chamb_code_deserialize(void* context, FlipperFormat flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); subghz_protocol_encoder_chamb_code_get_upload(instance); - instance->encoder.is_runing = true; + instance->encoder.is_running = true; res = true; } while(false); @@ -235,14 +235,14 @@ bool subghz_protocol_encoder_chamb_code_deserialize(void* context, FlipperFormat void subghz_protocol_encoder_chamb_code_stop(void* context) { SubGhzProtocolEncoderChamb_Code* instance = context; - instance->encoder.is_runing = false; + instance->encoder.is_running = false; } LevelDuration subghz_protocol_encoder_chamb_code_yield(void* context) { SubGhzProtocolEncoderChamb_Code* instance = context; - if(instance->encoder.repeat == 0 || !instance->encoder.is_runing) { - instance->encoder.is_runing = false; + if(instance->encoder.repeat == 0 || !instance->encoder.is_running) { + instance->encoder.is_running = false; return level_duration_reset(); } diff --git a/lib/subghz/protocols/doitrand.c b/lib/subghz/protocols/doitrand.c index c26cbc5b6..9a0a58190 100644 --- a/lib/subghz/protocols/doitrand.c +++ b/lib/subghz/protocols/doitrand.c @@ -85,7 +85,7 @@ void* subghz_protocol_encoder_doitrand_alloc(SubGhzEnvironment* environment) { instance->encoder.repeat = 10; instance->encoder.size_upload = 128; instance->encoder.upload = malloc(instance->encoder.size_upload * sizeof(LevelDuration)); - instance->encoder.is_runing = false; + instance->encoder.is_running = false; return instance; } @@ -155,7 +155,7 @@ bool subghz_protocol_encoder_doitrand_deserialize(void* context, FlipperFormat* flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); subghz_protocol_encoder_doitrand_get_upload(instance); - instance->encoder.is_runing = true; + instance->encoder.is_running = true; res = true; } while(false); @@ -165,14 +165,14 @@ bool subghz_protocol_encoder_doitrand_deserialize(void* context, FlipperFormat* void subghz_protocol_encoder_doitrand_stop(void* context) { SubGhzProtocolEncoderDoitrand* instance = context; - instance->encoder.is_runing = false; + instance->encoder.is_running = false; } LevelDuration subghz_protocol_encoder_doitrand_yield(void* context) { SubGhzProtocolEncoderDoitrand* instance = context; - if(instance->encoder.repeat == 0 || !instance->encoder.is_runing) { - instance->encoder.is_runing = false; + if(instance->encoder.repeat == 0 || !instance->encoder.is_running) { + instance->encoder.is_running = false; return level_duration_reset(); } diff --git a/lib/subghz/protocols/gate_tx.c b/lib/subghz/protocols/gate_tx.c index 66174d011..d7efb3862 100644 --- a/lib/subghz/protocols/gate_tx.c +++ b/lib/subghz/protocols/gate_tx.c @@ -78,7 +78,7 @@ void* subghz_protocol_encoder_gate_tx_alloc(SubGhzEnvironment* environment) { instance->encoder.repeat = 10; instance->encoder.size_upload = 52; //max 24bit*2 + 2 (start, stop) instance->encoder.upload = malloc(instance->encoder.size_upload * sizeof(LevelDuration)); - instance->encoder.is_runing = false; + instance->encoder.is_running = false; return instance; } @@ -148,7 +148,7 @@ bool subghz_protocol_encoder_gate_tx_deserialize(void* context, FlipperFormat* f flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); subghz_protocol_encoder_gate_tx_get_upload(instance); - instance->encoder.is_runing = true; + instance->encoder.is_running = true; res = true; } while(false); @@ -158,14 +158,14 @@ bool subghz_protocol_encoder_gate_tx_deserialize(void* context, FlipperFormat* f void subghz_protocol_encoder_gate_tx_stop(void* context) { SubGhzProtocolEncoderGateTx* instance = context; - instance->encoder.is_runing = false; + instance->encoder.is_running = false; } LevelDuration subghz_protocol_encoder_gate_tx_yield(void* context) { SubGhzProtocolEncoderGateTx* instance = context; - if(instance->encoder.repeat == 0 || !instance->encoder.is_runing) { - instance->encoder.is_runing = false; + if(instance->encoder.repeat == 0 || !instance->encoder.is_running) { + instance->encoder.is_running = false; return level_duration_reset(); } diff --git a/lib/subghz/protocols/holtek.c b/lib/subghz/protocols/holtek.c index ed5e4fb54..137ba85d3 100644 --- a/lib/subghz/protocols/holtek.c +++ b/lib/subghz/protocols/holtek.c @@ -89,7 +89,7 @@ void* subghz_protocol_encoder_holtek_alloc(SubGhzEnvironment* environment) { instance->encoder.repeat = 10; instance->encoder.size_upload = 128; instance->encoder.upload = malloc(instance->encoder.size_upload * sizeof(LevelDuration)); - instance->encoder.is_runing = false; + instance->encoder.is_running = false; return instance; } @@ -161,7 +161,7 @@ bool subghz_protocol_encoder_holtek_deserialize(void* context, FlipperFormat* fl flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); subghz_protocol_encoder_holtek_get_upload(instance); - instance->encoder.is_runing = true; + instance->encoder.is_running = true; res = true; } while(false); @@ -171,14 +171,14 @@ bool subghz_protocol_encoder_holtek_deserialize(void* context, FlipperFormat* fl void subghz_protocol_encoder_holtek_stop(void* context) { SubGhzProtocolEncoderHoltek* instance = context; - instance->encoder.is_runing = false; + instance->encoder.is_running = false; } LevelDuration subghz_protocol_encoder_holtek_yield(void* context) { SubGhzProtocolEncoderHoltek* instance = context; - if(instance->encoder.repeat == 0 || !instance->encoder.is_runing) { - instance->encoder.is_runing = false; + if(instance->encoder.repeat == 0 || !instance->encoder.is_running) { + instance->encoder.is_running = false; return level_duration_reset(); } diff --git a/lib/subghz/protocols/honeywell_wdb.c b/lib/subghz/protocols/honeywell_wdb.c index 292229130..e1e21426d 100644 --- a/lib/subghz/protocols/honeywell_wdb.c +++ b/lib/subghz/protocols/honeywell_wdb.c @@ -91,7 +91,7 @@ void* subghz_protocol_encoder_honeywell_wdb_alloc(SubGhzEnvironment* environment instance->encoder.repeat = 10; instance->encoder.size_upload = 128; instance->encoder.upload = malloc(instance->encoder.size_upload * sizeof(LevelDuration)); - instance->encoder.is_runing = false; + instance->encoder.is_running = false; return instance; } @@ -163,7 +163,7 @@ bool subghz_protocol_encoder_honeywell_wdb_deserialize( flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); subghz_protocol_encoder_honeywell_wdb_get_upload(instance); - instance->encoder.is_runing = true; + instance->encoder.is_running = true; res = true; } while(false); @@ -173,14 +173,14 @@ bool subghz_protocol_encoder_honeywell_wdb_deserialize( void subghz_protocol_encoder_honeywell_wdb_stop(void* context) { SubGhzProtocolEncoderHoneywell_WDB* instance = context; - instance->encoder.is_runing = false; + instance->encoder.is_running = false; } LevelDuration subghz_protocol_encoder_honeywell_wdb_yield(void* context) { SubGhzProtocolEncoderHoneywell_WDB* instance = context; - if(instance->encoder.repeat == 0 || !instance->encoder.is_runing) { - instance->encoder.is_runing = false; + if(instance->encoder.repeat == 0 || !instance->encoder.is_running) { + instance->encoder.is_running = false; return level_duration_reset(); } diff --git a/lib/subghz/protocols/hormann.c b/lib/subghz/protocols/hormann.c index ac6312511..0197f59e6 100644 --- a/lib/subghz/protocols/hormann.c +++ b/lib/subghz/protocols/hormann.c @@ -81,7 +81,7 @@ void* subghz_protocol_encoder_hormann_alloc(SubGhzEnvironment* environment) { instance->encoder.repeat = 10; instance->encoder.size_upload = 2048; instance->encoder.upload = malloc(instance->encoder.size_upload * sizeof(LevelDuration)); - instance->encoder.is_runing = false; + instance->encoder.is_running = false; return instance; } @@ -164,7 +164,7 @@ bool subghz_protocol_encoder_hormann_deserialize(void* context, FlipperFormat* f flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); subghz_protocol_encoder_hormann_get_upload(instance); - instance->encoder.is_runing = true; + instance->encoder.is_running = true; res = true; } while(false); @@ -174,14 +174,14 @@ bool subghz_protocol_encoder_hormann_deserialize(void* context, FlipperFormat* f void subghz_protocol_encoder_hormann_stop(void* context) { SubGhzProtocolEncoderHormann* instance = context; - instance->encoder.is_runing = false; + instance->encoder.is_running = false; } LevelDuration subghz_protocol_encoder_hormann_yield(void* context) { SubGhzProtocolEncoderHormann* instance = context; - if(instance->encoder.repeat == 0 || !instance->encoder.is_runing) { - instance->encoder.is_runing = false; + if(instance->encoder.repeat == 0 || !instance->encoder.is_running) { + instance->encoder.is_running = false; return level_duration_reset(); } diff --git a/lib/subghz/protocols/keeloq.c b/lib/subghz/protocols/keeloq.c index 1d3ae74bd..32582faf9 100644 --- a/lib/subghz/protocols/keeloq.c +++ b/lib/subghz/protocols/keeloq.c @@ -113,7 +113,7 @@ void* subghz_protocol_encoder_keeloq_alloc(SubGhzEnvironment* environment) { instance->encoder.repeat = 100; instance->encoder.size_upload = 256; instance->encoder.upload = malloc(instance->encoder.size_upload * sizeof(LevelDuration)); - instance->encoder.is_runing = false; + instance->encoder.is_running = false; return instance; } @@ -371,7 +371,7 @@ bool subghz_protocol_encoder_keeloq_deserialize(void* context, FlipperFormat* fl break; } - instance->encoder.is_runing = true; + instance->encoder.is_running = true; res = true; } while(false); @@ -381,14 +381,14 @@ bool subghz_protocol_encoder_keeloq_deserialize(void* context, FlipperFormat* fl void subghz_protocol_encoder_keeloq_stop(void* context) { SubGhzProtocolEncoderKeeloq* instance = context; - instance->encoder.is_runing = false; + instance->encoder.is_running = false; } LevelDuration subghz_protocol_encoder_keeloq_yield(void* context) { SubGhzProtocolEncoderKeeloq* instance = context; - if(instance->encoder.repeat == 0 || !instance->encoder.is_runing) { - instance->encoder.is_runing = false; + if(instance->encoder.repeat == 0 || !instance->encoder.is_running) { + instance->encoder.is_running = false; return level_duration_reset(); } diff --git a/lib/subghz/protocols/linear.c b/lib/subghz/protocols/linear.c index c989a6183..92ba02a8f 100644 --- a/lib/subghz/protocols/linear.c +++ b/lib/subghz/protocols/linear.c @@ -84,7 +84,7 @@ void* subghz_protocol_encoder_linear_alloc(SubGhzEnvironment* environment) { instance->encoder.repeat = 10; instance->encoder.size_upload = 28; //max 10bit*2 + 2 (start, stop) instance->encoder.upload = malloc(instance->encoder.size_upload * sizeof(LevelDuration)); - instance->encoder.is_runing = false; + instance->encoder.is_running = false; return instance; } @@ -166,7 +166,7 @@ bool subghz_protocol_encoder_linear_deserialize(void* context, FlipperFormat* fl flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); subghz_protocol_encoder_linear_get_upload(instance); - instance->encoder.is_runing = true; + instance->encoder.is_running = true; res = true; } while(false); @@ -176,14 +176,14 @@ bool subghz_protocol_encoder_linear_deserialize(void* context, FlipperFormat* fl void subghz_protocol_encoder_linear_stop(void* context) { SubGhzProtocolEncoderLinear* instance = context; - instance->encoder.is_runing = false; + instance->encoder.is_running = false; } LevelDuration subghz_protocol_encoder_linear_yield(void* context) { SubGhzProtocolEncoderLinear* instance = context; - if(instance->encoder.repeat == 0 || !instance->encoder.is_runing) { - instance->encoder.is_runing = false; + if(instance->encoder.repeat == 0 || !instance->encoder.is_running) { + instance->encoder.is_running = false; return level_duration_reset(); } diff --git a/lib/subghz/protocols/marantec.c b/lib/subghz/protocols/marantec.c index d46927246..bdce6593d 100644 --- a/lib/subghz/protocols/marantec.c +++ b/lib/subghz/protocols/marantec.c @@ -80,7 +80,7 @@ void* subghz_protocol_encoder_marantec_alloc(SubGhzEnvironment* environment) { instance->encoder.repeat = 10; instance->encoder.size_upload = 256; instance->encoder.upload = malloc(instance->encoder.size_upload * sizeof(LevelDuration)); - instance->encoder.is_runing = false; + instance->encoder.is_running = false; return instance; } @@ -208,7 +208,7 @@ bool subghz_protocol_encoder_marantec_deserialize(void* context, FlipperFormat* subghz_protocol_marantec_remote_controller(&instance->generic); subghz_protocol_encoder_marantec_get_upload(instance); - instance->encoder.is_runing = true; + instance->encoder.is_running = true; res = true; } while(false); @@ -218,14 +218,14 @@ bool subghz_protocol_encoder_marantec_deserialize(void* context, FlipperFormat* void subghz_protocol_encoder_marantec_stop(void* context) { SubGhzProtocolEncoderMarantec* instance = context; - instance->encoder.is_runing = false; + instance->encoder.is_running = false; } LevelDuration subghz_protocol_encoder_marantec_yield(void* context) { SubGhzProtocolEncoderMarantec* instance = context; - if(instance->encoder.repeat == 0 || !instance->encoder.is_runing) { - instance->encoder.is_runing = false; + if(instance->encoder.repeat == 0 || !instance->encoder.is_running) { + instance->encoder.is_running = false; return level_duration_reset(); } diff --git a/lib/subghz/protocols/megacode.c b/lib/subghz/protocols/megacode.c index bfe1a76b9..909e72171 100644 --- a/lib/subghz/protocols/megacode.c +++ b/lib/subghz/protocols/megacode.c @@ -90,7 +90,7 @@ void* subghz_protocol_encoder_megacode_alloc(SubGhzEnvironment* environment) { instance->encoder.repeat = 10; instance->encoder.size_upload = 52; instance->encoder.upload = malloc(instance->encoder.size_upload * sizeof(LevelDuration)); - instance->encoder.is_runing = false; + instance->encoder.is_running = false; return instance; } @@ -194,7 +194,7 @@ bool subghz_protocol_encoder_megacode_deserialize(void* context, FlipperFormat* flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); subghz_protocol_encoder_megacode_get_upload(instance); - instance->encoder.is_runing = true; + instance->encoder.is_running = true; res = true; } while(false); @@ -204,14 +204,14 @@ bool subghz_protocol_encoder_megacode_deserialize(void* context, FlipperFormat* void subghz_protocol_encoder_megacode_stop(void* context) { SubGhzProtocolEncoderMegaCode* instance = context; - instance->encoder.is_runing = false; + instance->encoder.is_running = false; } LevelDuration subghz_protocol_encoder_megacode_yield(void* context) { SubGhzProtocolEncoderMegaCode* instance = context; - if(instance->encoder.repeat == 0 || !instance->encoder.is_runing) { - instance->encoder.is_runing = false; + if(instance->encoder.repeat == 0 || !instance->encoder.is_running) { + instance->encoder.is_running = false; return level_duration_reset(); } diff --git a/lib/subghz/protocols/nero_radio.c b/lib/subghz/protocols/nero_radio.c index b6b1587ff..69326f5a0 100644 --- a/lib/subghz/protocols/nero_radio.c +++ b/lib/subghz/protocols/nero_radio.c @@ -80,7 +80,7 @@ void* subghz_protocol_encoder_nero_radio_alloc(SubGhzEnvironment* environment) { instance->encoder.repeat = 10; instance->encoder.size_upload = 256; instance->encoder.upload = malloc(instance->encoder.size_upload * sizeof(LevelDuration)); - instance->encoder.is_runing = false; + instance->encoder.is_running = false; return instance; } @@ -173,7 +173,7 @@ bool subghz_protocol_encoder_nero_radio_deserialize(void* context, FlipperFormat flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); subghz_protocol_encoder_nero_radio_get_upload(instance); - instance->encoder.is_runing = true; + instance->encoder.is_running = true; res = true; } while(false); @@ -183,14 +183,14 @@ bool subghz_protocol_encoder_nero_radio_deserialize(void* context, FlipperFormat void subghz_protocol_encoder_nero_radio_stop(void* context) { SubGhzProtocolEncoderNeroRadio* instance = context; - instance->encoder.is_runing = false; + instance->encoder.is_running = false; } LevelDuration subghz_protocol_encoder_nero_radio_yield(void* context) { SubGhzProtocolEncoderNeroRadio* instance = context; - if(instance->encoder.repeat == 0 || !instance->encoder.is_runing) { - instance->encoder.is_runing = false; + if(instance->encoder.repeat == 0 || !instance->encoder.is_running) { + instance->encoder.is_running = false; return level_duration_reset(); } diff --git a/lib/subghz/protocols/nero_sketch.c b/lib/subghz/protocols/nero_sketch.c index 0b87ec11b..c93b36a53 100644 --- a/lib/subghz/protocols/nero_sketch.c +++ b/lib/subghz/protocols/nero_sketch.c @@ -79,7 +79,7 @@ void* subghz_protocol_encoder_nero_sketch_alloc(SubGhzEnvironment* environment) instance->encoder.repeat = 10; instance->encoder.size_upload = 256; instance->encoder.upload = malloc(instance->encoder.size_upload * sizeof(LevelDuration)); - instance->encoder.is_runing = false; + instance->encoder.is_running = false; return instance; } @@ -167,7 +167,7 @@ bool subghz_protocol_encoder_nero_sketch_deserialize(void* context, FlipperForma flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); subghz_protocol_encoder_nero_sketch_get_upload(instance); - instance->encoder.is_runing = true; + instance->encoder.is_running = true; res = true; } while(false); @@ -177,14 +177,14 @@ bool subghz_protocol_encoder_nero_sketch_deserialize(void* context, FlipperForma void subghz_protocol_encoder_nero_sketch_stop(void* context) { SubGhzProtocolEncoderNeroSketch* instance = context; - instance->encoder.is_runing = false; + instance->encoder.is_running = false; } LevelDuration subghz_protocol_encoder_nero_sketch_yield(void* context) { SubGhzProtocolEncoderNeroSketch* instance = context; - if(instance->encoder.repeat == 0 || !instance->encoder.is_runing) { - instance->encoder.is_runing = false; + if(instance->encoder.repeat == 0 || !instance->encoder.is_running) { + instance->encoder.is_running = false; return level_duration_reset(); } diff --git a/lib/subghz/protocols/nice_flo.c b/lib/subghz/protocols/nice_flo.c index 236b42223..07b18e3ea 100644 --- a/lib/subghz/protocols/nice_flo.c +++ b/lib/subghz/protocols/nice_flo.c @@ -78,7 +78,7 @@ void* subghz_protocol_encoder_nice_flo_alloc(SubGhzEnvironment* environment) { instance->encoder.repeat = 10; instance->encoder.size_upload = 52; //max 24bit*2 + 2 (start, stop) instance->encoder.upload = malloc(instance->encoder.size_upload * sizeof(LevelDuration)); - instance->encoder.is_runing = false; + instance->encoder.is_running = false; return instance; } @@ -150,7 +150,7 @@ bool subghz_protocol_encoder_nice_flo_deserialize(void* context, FlipperFormat* flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); subghz_protocol_encoder_nice_flo_get_upload(instance); - instance->encoder.is_runing = true; + instance->encoder.is_running = true; res = true; } while(false); @@ -160,14 +160,14 @@ bool subghz_protocol_encoder_nice_flo_deserialize(void* context, FlipperFormat* void subghz_protocol_encoder_nice_flo_stop(void* context) { SubGhzProtocolEncoderNiceFlo* instance = context; - instance->encoder.is_runing = false; + instance->encoder.is_running = false; } LevelDuration subghz_protocol_encoder_nice_flo_yield(void* context) { SubGhzProtocolEncoderNiceFlo* instance = context; - if(instance->encoder.repeat == 0 || !instance->encoder.is_runing) { - instance->encoder.is_runing = false; + if(instance->encoder.repeat == 0 || !instance->encoder.is_running) { + instance->encoder.is_running = false; return level_duration_reset(); } diff --git a/lib/subghz/protocols/phoenix_v2.c b/lib/subghz/protocols/phoenix_v2.c index e71e28349..3d2796e44 100644 --- a/lib/subghz/protocols/phoenix_v2.c +++ b/lib/subghz/protocols/phoenix_v2.c @@ -80,7 +80,7 @@ void* subghz_protocol_encoder_phoenix_v2_alloc(SubGhzEnvironment* environment) { instance->encoder.repeat = 10; instance->encoder.size_upload = 128; instance->encoder.upload = malloc(instance->encoder.size_upload * sizeof(LevelDuration)); - instance->encoder.is_runing = false; + instance->encoder.is_running = false; return instance; } @@ -151,7 +151,7 @@ bool subghz_protocol_encoder_phoenix_v2_deserialize(void* context, FlipperFormat flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); subghz_protocol_encoder_phoenix_v2_get_upload(instance); - instance->encoder.is_runing = true; + instance->encoder.is_running = true; res = true; } while(false); @@ -161,14 +161,14 @@ bool subghz_protocol_encoder_phoenix_v2_deserialize(void* context, FlipperFormat void subghz_protocol_encoder_phoenix_v2_stop(void* context) { SubGhzProtocolEncoderPhoenix_V2* instance = context; - instance->encoder.is_runing = false; + instance->encoder.is_running = false; } LevelDuration subghz_protocol_encoder_phoenix_v2_yield(void* context) { SubGhzProtocolEncoderPhoenix_V2* instance = context; - if(instance->encoder.repeat == 0 || !instance->encoder.is_runing) { - instance->encoder.is_runing = false; + if(instance->encoder.repeat == 0 || !instance->encoder.is_running) { + instance->encoder.is_running = false; return level_duration_reset(); } diff --git a/lib/subghz/protocols/power_smart.c b/lib/subghz/protocols/power_smart.c index 53e9f3380..bd009d887 100644 --- a/lib/subghz/protocols/power_smart.c +++ b/lib/subghz/protocols/power_smart.c @@ -87,7 +87,7 @@ void* subghz_protocol_encoder_power_smart_alloc(SubGhzEnvironment* environment) instance->encoder.repeat = 10; instance->encoder.size_upload = 1024; instance->encoder.upload = malloc(instance->encoder.size_upload * sizeof(LevelDuration)); - instance->encoder.is_runing = false; + instance->encoder.is_running = false; return instance; } @@ -212,7 +212,7 @@ bool subghz_protocol_encoder_power_smart_deserialize(void* context, FlipperForma subghz_protocol_power_smart_remote_controller(&instance->generic); subghz_protocol_encoder_power_smart_get_upload(instance); - instance->encoder.is_runing = true; + instance->encoder.is_running = true; res = true; } while(false); @@ -222,14 +222,14 @@ bool subghz_protocol_encoder_power_smart_deserialize(void* context, FlipperForma void subghz_protocol_encoder_power_smart_stop(void* context) { SubGhzProtocolEncoderPowerSmart* instance = context; - instance->encoder.is_runing = false; + instance->encoder.is_running = false; } LevelDuration subghz_protocol_encoder_power_smart_yield(void* context) { SubGhzProtocolEncoderPowerSmart* instance = context; - if(instance->encoder.repeat == 0 || !instance->encoder.is_runing) { - instance->encoder.is_runing = false; + if(instance->encoder.repeat == 0 || !instance->encoder.is_running) { + instance->encoder.is_running = false; return level_duration_reset(); } diff --git a/lib/subghz/protocols/princeton.c b/lib/subghz/protocols/princeton.c index 3fdeaae94..2ddfa2cb6 100644 --- a/lib/subghz/protocols/princeton.c +++ b/lib/subghz/protocols/princeton.c @@ -89,7 +89,7 @@ void* subghz_protocol_encoder_princeton_alloc(SubGhzEnvironment* environment) { instance->encoder.repeat = 10; instance->encoder.size_upload = 52; //max 24bit*2 + 2 (start, stop) instance->encoder.upload = malloc(instance->encoder.size_upload * sizeof(LevelDuration)); - instance->encoder.is_runing = false; + instance->encoder.is_running = false; return instance; } @@ -168,7 +168,7 @@ bool subghz_protocol_encoder_princeton_deserialize(void* context, FlipperFormat* flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); subghz_protocol_encoder_princeton_get_upload(instance); - instance->encoder.is_runing = true; + instance->encoder.is_running = true; res = true; } while(false); @@ -178,14 +178,14 @@ bool subghz_protocol_encoder_princeton_deserialize(void* context, FlipperFormat* void subghz_protocol_encoder_princeton_stop(void* context) { SubGhzProtocolEncoderPrinceton* instance = context; - instance->encoder.is_runing = false; + instance->encoder.is_running = false; } LevelDuration subghz_protocol_encoder_princeton_yield(void* context) { SubGhzProtocolEncoderPrinceton* instance = context; - if(instance->encoder.repeat == 0 || !instance->encoder.is_runing) { - instance->encoder.is_runing = false; + if(instance->encoder.repeat == 0 || !instance->encoder.is_running) { + instance->encoder.is_running = false; return level_duration_reset(); } diff --git a/lib/subghz/protocols/raw.c b/lib/subghz/protocols/raw.c index 9ab649a7b..0419a39a0 100644 --- a/lib/subghz/protocols/raw.c +++ b/lib/subghz/protocols/raw.c @@ -37,7 +37,7 @@ struct SubGhzProtocolDecoderRAW { struct SubGhzProtocolEncoderRAW { SubGhzProtocolEncoderBase base; - bool is_runing; + bool is_running; string_t file_name; SubGhzFileEncoderWorker* file_worker_encoder; }; @@ -269,13 +269,13 @@ void* subghz_protocol_encoder_raw_alloc(SubGhzEnvironment* environment) { instance->base.protocol = &subghz_protocol_raw; string_init(instance->file_name); - instance->is_runing = false; + instance->is_running = false; return instance; } void subghz_protocol_encoder_raw_stop(void* context) { SubGhzProtocolEncoderRAW* instance = context; - instance->is_runing = false; + instance->is_running = false; if(subghz_file_encoder_worker_is_running(instance->file_worker_encoder)) { subghz_file_encoder_worker_stop(instance->file_worker_encoder); subghz_file_encoder_worker_free(instance->file_worker_encoder); @@ -308,11 +308,11 @@ static bool subghz_protocol_encoder_raw_worker_init(SubGhzProtocolEncoderRAW* in instance->file_worker_encoder, string_get_cstr(instance->file_name))) { //the worker needs a file in order to open and read part of the file furi_delay_ms(100); - instance->is_runing = true; + instance->is_running = true; } else { subghz_protocol_encoder_raw_stop(instance); } - return instance->is_runing; + return instance->is_running; } void subghz_protocol_raw_gen_fff_data(FlipperFormat* flipper_format, const char* file_path) { @@ -357,6 +357,6 @@ bool subghz_protocol_encoder_raw_deserialize(void* context, FlipperFormat* flipp LevelDuration subghz_protocol_encoder_raw_yield(void* context) { SubGhzProtocolEncoderRAW* instance = context; - if(!instance->is_runing) return level_duration_reset(); + if(!instance->is_running) return level_duration_reset(); return subghz_file_encoder_worker_get_level_duration(instance->file_worker_encoder); } diff --git a/lib/subghz/protocols/secplus_v1.c b/lib/subghz/protocols/secplus_v1.c index a9798a502..04dc5d729 100644 --- a/lib/subghz/protocols/secplus_v1.c +++ b/lib/subghz/protocols/secplus_v1.c @@ -101,7 +101,7 @@ void* subghz_protocol_encoder_secplus_v1_alloc(SubGhzEnvironment* environment) { instance->encoder.repeat = 10; instance->encoder.size_upload = 128; instance->encoder.upload = malloc(instance->encoder.size_upload * sizeof(LevelDuration)); - instance->encoder.is_runing = false; + instance->encoder.is_running = false; return instance; } @@ -298,7 +298,7 @@ bool subghz_protocol_encoder_secplus_v1_deserialize(void* context, FlipperFormat break; } - instance->encoder.is_runing = true; + instance->encoder.is_running = true; res = true; } while(false); @@ -308,14 +308,14 @@ bool subghz_protocol_encoder_secplus_v1_deserialize(void* context, FlipperFormat void subghz_protocol_encoder_secplus_v1_stop(void* context) { SubGhzProtocolEncoderSecPlus_v1* instance = context; - instance->encoder.is_runing = false; + instance->encoder.is_running = false; } LevelDuration subghz_protocol_encoder_secplus_v1_yield(void* context) { SubGhzProtocolEncoderSecPlus_v1* instance = context; - if(instance->encoder.repeat == 0 || !instance->encoder.is_runing) { - instance->encoder.is_runing = false; + if(instance->encoder.repeat == 0 || !instance->encoder.is_running) { + instance->encoder.is_running = false; return level_duration_reset(); } diff --git a/lib/subghz/protocols/secplus_v2.c b/lib/subghz/protocols/secplus_v2.c index 954e8c817..1ba255652 100644 --- a/lib/subghz/protocols/secplus_v2.c +++ b/lib/subghz/protocols/secplus_v2.c @@ -93,7 +93,7 @@ void* subghz_protocol_encoder_secplus_v2_alloc(SubGhzEnvironment* environment) { instance->encoder.repeat = 10; instance->encoder.size_upload = 256; instance->encoder.upload = malloc(instance->encoder.size_upload * sizeof(LevelDuration)); - instance->encoder.is_runing = false; + instance->encoder.is_running = false; return instance; } @@ -555,7 +555,7 @@ bool subghz_protocol_encoder_secplus_v2_deserialize(void* context, FlipperFormat break; } - instance->encoder.is_runing = true; + instance->encoder.is_running = true; res = true; } while(false); @@ -565,14 +565,14 @@ bool subghz_protocol_encoder_secplus_v2_deserialize(void* context, FlipperFormat void subghz_protocol_encoder_secplus_v2_stop(void* context) { SubGhzProtocolEncoderSecPlus_v2* instance = context; - instance->encoder.is_runing = false; + instance->encoder.is_running = false; } LevelDuration subghz_protocol_encoder_secplus_v2_yield(void* context) { SubGhzProtocolEncoderSecPlus_v2* instance = context; - if(instance->encoder.repeat == 0 || !instance->encoder.is_runing) { - instance->encoder.is_runing = false; + if(instance->encoder.repeat == 0 || !instance->encoder.is_running) { + instance->encoder.is_running = false; return level_duration_reset(); }