Merge remote-tracking branch 'origin/dev' into electra

This commit is contained in:
Methodius 2024-05-03 22:17:14 +03:00
commit d73832a5dd
No known key found for this signature in database
GPG Key ID: 122FA99A00B41679
30 changed files with 164 additions and 1428 deletions

View File

@ -1,19 +1,37 @@
## New changes
* NFC: Temp fix for `iso14443_4_layer_decode_block` crash
* NFC: CharlieCard parser (by @zacharyweiss)
* SubGHz: FAAC RC XT - add 0xB button code on arrow buttons for programming mode
* SubGHz: Add Manually - Sommer FM fixes
* SubGHz: Enabled tx-rx state on unused gpio pin by default (**external amp option was removed and is enabled by default now**)
* SubGHz: **Status output !TX/RX on the GDO2 CC1101 pin** (by @quen0n | PR #742)
* SubGHz: Reworked saved settings (by @xMasterX and @Willy-JL)
* Desktop: Fixes for animation unload (by @Willy-JL)
* iButton: Updated DS1420 for latest ibutton changes
* Misc: Allow no prefix usage of name_generator_make_detailed_datetime
* Misc: Allow setting view dispatcher callbacks to NULL
* Misc: Added `void` due to `-Wstrict-prototypes`
* Misc: Some code cleanup and proper log levels in nfc parsers
* Infrared: Allow external apps to use infrared settings (by @Willy-JL)
* JS & HAL: Various fixes and FURI_HAL_RANDOM_MAX define added (by @Willy-JL)
* JS: **BadUSB layout support** (by @Willy-JL)
* JS: Module `widget` and path globals (by @jamisonderek)
* JS: New Modules `widget`, `vgm` and path globals (by @jamisonderek)
* Apps: NFC Magic - **Gen2 writing support, Gen4 NTAG password and PACK fixes** (by @Astrrra)
* Apps: MFKey - **fixed crashes** (by @noproto)
* Apps: MFKey - **fixed crashes**, add more free ram (by @noproto & @Willy-JL)
* Apps: **Check out Apps updates by following** [this link](https://github.com/xMasterX/all-the-plugins/commits/dev)
* OFW PR 3616: NFC: Mf Desfire fix reading big files (by gornekich)
* OFW: iButton: fix crash when deleting some keys
* OFW: Desktop: cleanup error popups
* OFW: Troika parser visual fixes
* OFW: Fix the retry/exit confirmation prompts in iButton
* OFW: nfc app: add legacy keys for plantain cards
* OFW: GUI: Fix array out of bounds in menu exit
* OFW: add support for S(WTX) request in iso14443_4a_poller
* OFW: Mosgortrans parser output fixes
* OFW: BLE: Add GapPairingNone support
* OFW: iButton new UI
* OFW: FuriHal: add ADC API
* OFW: Mf Desfire multiple file rights support
* OFW: **Felica poller** (NFC-F)
* OFW: Desktop/Loader: Unload animations before loading FAPs
* OFW: JS Documentation
@ -49,8 +67,7 @@
#### Known NFC post-refactor regressions list:
- Mifare Mini clones reading is broken (original mini working fine) (OFW)
- NFC CLI was removed with refactoring (OFW) (will be back soon)
- Current list of affected apps: https://github.com/xMasterX/all-the-plugins/tree/dev/apps_broken_by_last_refactors
- Also in app **Enhanced Sub-GHz Chat** - NFC part was temporarily removed to make app usable, NFC part of the app requires remaking it with new nfc stack
- Mifare Nested not ported to latest API yet, `unlshd-065` is the latest version on old NFC API that works with "nested app"
----

View File

@ -17,14 +17,21 @@ void ibutton_scene_delete_confirm_on_enter(void* context) {
ibutton_protocols_render_uid(ibutton->protocols, key, uid);
furi_string_cat_printf(
uid,
"\n%s %s",
ibutton_protocols_get_manufacturer(ibutton->protocols, ibutton_key_get_protocol_id(key)),
ibutton_protocols_get_name(ibutton->protocols, ibutton_key_get_protocol_id(key)));
furi_string_cat(tmp, uid);
furi_string_push_back(tmp, '\n');
const char* protocol =
ibutton_protocols_get_name(ibutton->protocols, ibutton_key_get_protocol_id(key));
const char* manufacturer =
ibutton_protocols_get_manufacturer(ibutton->protocols, ibutton_key_get_protocol_id(key));
if(strcasecmp(protocol, manufacturer) != 0 && strcasecmp(manufacturer, "N/A") != 0) {
furi_string_cat_printf(tmp, "%s ", manufacturer);
}
furi_string_cat(tmp, protocol);
widget_add_text_box_element(
widget, 0, 0, 128, 64, AlignCenter, AlignTop, furi_string_get_cstr(tmp), false);

View File

@ -21,17 +21,14 @@ void ibutton_scene_emulate_on_enter(void* context) {
widget_add_icon_element(widget, 3, 10, &I_iButtonKey_49x44);
if(furi_string_empty(ibutton->file_path)) {
furi_string_printf(
tmp,
"Unsaved\n%s",
ibutton_protocols_get_name(ibutton->protocols, ibutton_key_get_protocol_id(key)));
} else {
furi_string_printf(tmp, "%s", ibutton->key_name);
}
furi_string_printf(
tmp,
"[%s]\n%s",
ibutton_protocols_get_name(ibutton->protocols, ibutton_key_get_protocol_id(key)),
furi_string_empty(ibutton->file_path) ? "Unsaved Key" : ibutton->key_name);
widget_add_text_box_element(
widget, 52, 23, 75, 26, AlignCenter, AlignTop, furi_string_get_cstr(tmp), false);
widget, 52, 24, 75, 40, AlignCenter, AlignTop, furi_string_get_cstr(tmp), true);
widget_add_string_multiline_element(
widget, 88, 10, AlignCenter, AlignTop, FontPrimary, "Emulating");

View File

@ -10,12 +10,23 @@ void ibutton_scene_info_on_enter(void* context) {
FuriString* tmp = furi_string_alloc();
FuriString* brief_data = furi_string_alloc();
furi_string_printf(
tmp,
"Name:%s\n\e#%s %s\e#\n",
ibutton->key_name,
ibutton_protocols_get_manufacturer(ibutton->protocols, protocol_id),
ibutton_protocols_get_name(ibutton->protocols, protocol_id));
if((strcmp(
ibutton_protocols_get_manufacturer(ibutton->protocols, protocol_id),
ibutton_protocols_get_name(ibutton->protocols, protocol_id)) != 0) &&
(strcmp(ibutton_protocols_get_manufacturer(ibutton->protocols, protocol_id), "N/A") != 0)) {
furi_string_printf(
tmp,
"Name:%s\n\e#%s %s\e#\n",
ibutton->key_name,
ibutton_protocols_get_manufacturer(ibutton->protocols, protocol_id),
ibutton_protocols_get_name(ibutton->protocols, protocol_id));
} else {
furi_string_printf(
tmp,
"Name:%s\n\e#%s\e#\n",
ibutton->key_name,
ibutton_protocols_get_name(ibutton->protocols, protocol_id));
}
ibutton_protocols_render_brief_data(ibutton->protocols, key, brief_data);

View File

@ -40,15 +40,14 @@ void ibutton_scene_write_on_enter(void* context) {
widget_add_icon_element(widget, 3, 10, &I_iButtonKey_49x44);
if(furi_string_empty(ibutton->file_path)) {
furi_string_printf(
tmp, "Unsaved\n%s", ibutton_protocols_get_name(ibutton->protocols, protocol_id));
} else {
furi_string_printf(tmp, "%s", ibutton->key_name);
}
furi_string_printf(
tmp,
"[%s]\n%s",
ibutton_protocols_get_name(ibutton->protocols, protocol_id),
furi_string_empty(ibutton->file_path) ? "Unsaved Key" : ibutton->key_name);
widget_add_text_box_element(
widget, 52, 23, 75, 26, AlignCenter, AlignTop, furi_string_get_cstr(tmp), false);
widget, 52, 24, 75, 40, AlignCenter, AlignTop, furi_string_get_cstr(tmp), true);
ibutton_worker_write_set_callback(worker, ibutton_scene_write_callback, ibutton);

View File

@ -6,16 +6,15 @@ void lfrfid_scene_emulate_on_enter(void* context) {
FuriString* display_text = furi_string_alloc_set("\e#Emulating\e#\n");
if(furi_string_empty(app->file_name)) {
furi_string_cat(display_text, "Unsaved\n");
furi_string_cat(display_text, protocol_dict_get_name(app->dict, app->protocol_id));
} else {
furi_string_cat(display_text, app->file_name);
}
furi_string_cat_printf(
display_text,
"[%s]\n%s",
protocol_dict_get_name(app->dict, app->protocol_id),
furi_string_empty(app->file_name) ? "Unsaved Tag" : furi_string_get_cstr(app->file_name));
widget_add_icon_element(widget, 0, 0, &I_NFC_dolphin_emulation_51x64);
widget_add_text_box_element(
widget, 55, 16, 67, 48, AlignCenter, AlignTop, furi_string_get_cstr(display_text), true);
widget, 51, 6, 79, 50, AlignCenter, AlignTop, furi_string_get_cstr(display_text), false);
furi_string_free(display_text);

View File

@ -25,12 +25,18 @@ void lfrfid_scene_write_on_enter(void* context) {
popup_set_header(popup, "Writing", 94, 16, AlignCenter, AlignTop);
if(!furi_string_empty(app->file_name)) {
popup_set_text(popup, furi_string_get_cstr(app->file_name), 94, 29, AlignCenter, AlignTop);
snprintf(
app->text_store,
LFRFID_TEXT_STORE_SIZE,
"[%s]\n%s",
protocol_dict_get_name(app->dict, app->protocol_id),
furi_string_get_cstr(app->file_name));
popup_set_text(popup, app->text_store, 94, 29, AlignCenter, AlignTop);
} else {
snprintf(
app->text_store,
LFRFID_TEXT_STORE_SIZE,
"Unsaved\n%s",
"[%s]\nUnsaved Tag",
protocol_dict_get_name(app->dict, app->protocol_id));
popup_set_text(popup, app->text_store, 94, 29, AlignCenter, AlignTop);
}

View File

@ -22,8 +22,14 @@ void lfrfid_scene_write_and_set_pass_on_enter(void* context) {
LfRfid* app = context;
Popup* popup = app->popup;
popup_set_header(popup, "Writing\nwith password", 89, 30, AlignCenter, AlignTop);
popup_set_icon(popup, 0, 3, &I_RFIDDolphinSend_97x61);
popup_set_header(popup, "Writing\nwith\npassword", 94, 8, AlignCenter, AlignTop);
popup_set_icon(popup, 0, 8, &I_NFC_manual_60x50);
snprintf(
app->text_store,
LFRFID_TEXT_STORE_SIZE,
"[%s]",
protocol_dict_get_name(app->dict, app->protocol_id));
popup_set_text(popup, app->text_store, 94, 45, AlignCenter, AlignTop);
view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidViewPopup);

View File

@ -1,121 +0,0 @@
#include "mf_plus.h"
#include "mf_plus_render.h"
#include <nfc/protocols/mf_plus/mf_plus_poller.h>
#include "nfc/nfc_app_i.h"
#include "../nfc_protocol_support_common.h"
#include "../nfc_protocol_support_gui_common.h"
#include "../iso14443_4a/iso14443_4a_i.h"
static void nfc_scene_info_on_enter_mf_plus(NfcApp* instance) {
const NfcDevice* device = instance->nfc_device;
const MfPlusData* data = nfc_device_get_data(device, NfcProtocolMfPlus);
FuriString* temp_str = furi_string_alloc();
nfc_append_filename_string_when_present(instance, temp_str);
furi_string_cat_printf(
temp_str, "\e#%s\n", nfc_device_get_name(device, NfcDeviceNameTypeFull));
furi_string_replace(temp_str, "Mifare", "MIFARE");
nfc_render_mf_plus_info(data, NfcProtocolFormatTypeFull, temp_str);
widget_add_text_scroll_element(
instance->widget, 0, 0, 128, 52, furi_string_get_cstr(temp_str));
furi_string_free(temp_str);
}
static NfcCommand nfc_scene_read_poller_callback_mf_plus(NfcGenericEvent event, void* context) {
furi_assert(event.protocol == NfcProtocolMfPlus);
NfcApp* instance = context;
const MfPlusPollerEvent* mf_plus_event = event.event_data;
if(mf_plus_event->type == MfPlusPollerEventTypeReadSuccess) {
nfc_device_set_data(
instance->nfc_device, NfcProtocolMfPlus, nfc_poller_get_data(instance->poller));
FURI_LOG_D(
"MFP",
"Read success: %s",
nfc_device_get_name(instance->nfc_device, NfcDeviceNameTypeFull));
view_dispatcher_send_custom_event(instance->view_dispatcher, NfcCustomEventPollerSuccess);
return NfcCommandStop;
}
return NfcCommandContinue;
}
static void nfc_scene_read_on_enter_mf_plus(NfcApp* instance) {
nfc_poller_start(instance->poller, nfc_scene_read_poller_callback_mf_plus, instance);
}
static void nfc_scene_read_success_on_enter_mf_plus(NfcApp* instance) {
const NfcDevice* device = instance->nfc_device;
const MfPlusData* data = nfc_device_get_data(device, NfcProtocolMfPlus);
FuriString* temp_str = furi_string_alloc();
furi_string_cat_printf(
temp_str, "\e#%s\n", nfc_device_get_name(device, NfcDeviceNameTypeFull));
furi_string_replace(temp_str, "Mifare", "MIFARE");
nfc_render_mf_plus_info(data, NfcProtocolFormatTypeShort, temp_str);
widget_add_text_scroll_element(
instance->widget, 0, 0, 128, 52, furi_string_get_cstr(temp_str));
furi_string_free(temp_str);
}
static void nfc_scene_emulate_on_enter_mf_plus(NfcApp* instance) {
const Iso14443_4aData* iso14443_4a_data =
nfc_device_get_data(instance->nfc_device, NfcProtocolIso14443_4a);
instance->listener =
nfc_listener_alloc(instance->nfc, NfcProtocolIso14443_4a, iso14443_4a_data);
nfc_listener_start(
instance->listener, nfc_scene_emulate_listener_callback_iso14443_4a, instance);
}
const NfcProtocolSupportBase nfc_protocol_support_mf_plus = {
.features = NfcProtocolFeatureMoreInfo,
.scene_info =
{
.on_enter = nfc_scene_info_on_enter_mf_plus,
.on_event = nfc_protocol_support_common_on_event_empty,
},
.scene_more_info =
{
.on_enter = nfc_protocol_support_common_on_enter_empty,
.on_event = nfc_protocol_support_common_on_event_empty,
},
.scene_read =
{
.on_enter = nfc_scene_read_on_enter_mf_plus,
.on_event = nfc_protocol_support_common_on_event_empty,
},
.scene_read_menu =
{
.on_enter = nfc_protocol_support_common_on_enter_empty,
.on_event = nfc_protocol_support_common_on_event_empty,
},
.scene_read_success =
{
.on_enter = nfc_scene_read_success_on_enter_mf_plus,
.on_event = nfc_protocol_support_common_on_event_empty,
},
.scene_saved_menu =
{
.on_enter = nfc_protocol_support_common_on_enter_empty,
.on_event = nfc_protocol_support_common_on_event_empty,
},
.scene_save_name =
{
.on_enter = nfc_protocol_support_common_on_enter_empty,
.on_event = nfc_protocol_support_common_on_event_empty,
},
.scene_emulate =
{
.on_enter = nfc_scene_emulate_on_enter_mf_plus,
.on_event = nfc_protocol_support_common_on_event_empty,
},
};

View File

@ -1,5 +0,0 @@
#pragma once
#include "../nfc_protocol_support_base.h"
extern const NfcProtocolSupportBase nfc_protocol_support_mf_plus;

View File

@ -1,67 +0,0 @@
#include "mf_plus_render.h"
#include "../iso14443_4a/iso14443_4a_render.h"
void nfc_render_mf_plus_info(
const MfPlusData* data,
NfcProtocolFormatType format_type,
FuriString* str) {
nfc_render_iso14443_4a_brief(mf_plus_get_base_data(data), str);
if(format_type != NfcProtocolFormatTypeFull) return;
furi_string_cat(str, "\n\e#ISO14443-4 data");
nfc_render_iso14443_4a_extra(mf_plus_get_base_data(data), str);
}
void nfc_render_mf_plus_data(const MfPlusData* data, FuriString* str) {
nfc_render_mf_plus_version(&data->version, str);
}
void nfc_render_mf_plus_version(const MfPlusVersion* data, FuriString* str) {
furi_string_cat_printf(
str,
"%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
data->uid[0],
data->uid[1],
data->uid[2],
data->uid[3],
data->uid[4],
data->uid[5],
data->uid[6]);
furi_string_cat_printf(
str,
"hw %02x type %02x sub %02x\n"
" maj %02x min %02x\n"
" size %02x proto %02x\n",
data->hw_vendor,
data->hw_type,
data->hw_subtype,
data->hw_major,
data->hw_minor,
data->hw_storage,
data->hw_proto);
furi_string_cat_printf(
str,
"sw %02x type %02x sub %02x\n"
" maj %02x min %02x\n"
" size %02x proto %02x\n",
data->sw_vendor,
data->sw_type,
data->sw_subtype,
data->sw_major,
data->sw_minor,
data->sw_storage,
data->sw_proto);
furi_string_cat_printf(
str,
"batch %02x:%02x:%02x:%02x:%02x\n"
"week %d year %d\n",
data->batch[0],
data->batch[1],
data->batch[2],
data->batch[3],
data->batch[4],
data->prod_week,
data->prod_year);
}

View File

@ -1,14 +0,0 @@
#pragma once
#include <nfc/protocols/mf_plus/mf_plus.h>
#include "../nfc_protocol_support_render_common.h"
void nfc_render_mf_plus_info(
const MfPlusData* data,
NfcProtocolFormatType format_type,
FuriString* str);
void nfc_render_mf_plus_data(const MfPlusData* data, FuriString* str);
void nfc_render_mf_plus_version(const MfPlusVersion* data, FuriString* str);

View File

@ -17,7 +17,6 @@
#include "felica/felica.h"
#include "mf_ultralight/mf_ultralight.h"
#include "mf_classic/mf_classic.h"
#include "mf_plus/mf_plus.h"
#include "mf_desfire/mf_desfire.h"
#include "emv/emv.h"
#include "slix/slix.h"
@ -40,7 +39,6 @@ const NfcProtocolSupportBase* nfc_protocol_support[NfcProtocolNum] = {
[NfcProtocolFelica] = &nfc_protocol_support_felica,
[NfcProtocolMfUltralight] = &nfc_protocol_support_mf_ultralight,
[NfcProtocolMfClassic] = &nfc_protocol_support_mf_classic,
[NfcProtocolMfPlus] = &nfc_protocol_support_mf_plus,
[NfcProtocolMfDesfire] = &nfc_protocol_support_mf_desfire,
[NfcProtocolSlix] = &nfc_protocol_support_slix,
[NfcProtocolSt25tb] = &nfc_protocol_support_st25tb,

View File

@ -15,13 +15,11 @@ struct HidMouseJiggler {
typedef struct {
bool connected;
bool running;
int interval_idx;
uint8_t counter;
int min_interval; // Minimum interval for random range
int max_interval; // Maximum interval for random range
HidTransport transport;
} HidMouseJigglerModel;
const int intervals[6] = {500, 2000, 5000, 10000, 30000, 60000};
static void hid_mouse_jiggler_draw_callback(Canvas* canvas, void* context) {
furi_assert(context);
HidMouseJigglerModel* model = context;
@ -35,22 +33,26 @@ static void hid_mouse_jiggler_draw_callback(Canvas* canvas, void* context) {
}
}
// Title "Mouse Jiggler"
canvas_set_font(canvas, FontPrimary);
elements_multiline_text_aligned(canvas, 17, 2, AlignLeft, AlignTop, "Mouse Jiggler");
// Timeout
elements_multiline_text(canvas, AlignLeft, 26, "Interval (ms):");
canvas_set_font(canvas, FontSecondary);
if(model->interval_idx != 0) canvas_draw_icon(canvas, 74, 19, &I_ButtonLeft_4x7);
if(model->interval_idx != (int)COUNT_OF(intervals) - 1)
canvas_draw_icon(canvas, 80, 19, &I_ButtonRight_4x7);
FuriString* interval_str = furi_string_alloc_printf("%d", intervals[model->interval_idx]);
elements_multiline_text(canvas, 91, 26, furi_string_get_cstr(interval_str));
furi_string_free(interval_str);
// Display the current min interval in minutes
canvas_set_font(canvas, FontSecondary); // Assuming there's a smaller font available
FuriString* min_interval_str = furi_string_alloc_printf("Min: %d min", model->min_interval);
elements_multiline_text_aligned(
canvas, 0, 16, AlignLeft, AlignTop, furi_string_get_cstr(min_interval_str));
furi_string_free(min_interval_str);
// Display the current max interval in minutes
FuriString* max_interval_str = furi_string_alloc_printf("Max: %d min", model->max_interval);
elements_multiline_text_aligned(
canvas, 0, 28, AlignLeft, AlignTop, furi_string_get_cstr(max_interval_str));
furi_string_free(max_interval_str);
// "Press Start to jiggle"
canvas_set_font(canvas, FontPrimary);
elements_multiline_text(canvas, AlignLeft, 40, "Press Start\nto jiggle");
canvas_set_font(canvas, FontSecondary);
elements_multiline_text(canvas, AlignLeft, 50, "Press Start\nto jiggle");
// Ok
canvas_draw_icon(canvas, 63, 30, &I_Space_65x18);
@ -79,11 +81,20 @@ static void hid_mouse_jiggler_timer_callback(void* context) {
HidMouseJigglerModel * model,
{
if(model->running) {
model->counter++;
hid_hal_mouse_move(
hid_mouse_jiggler->hid,
(model->counter % 2 == 0) ? MOUSE_MOVE_SHORT : -MOUSE_MOVE_SHORT,
0);
// Generate a random interval in minutes and convert to milliseconds
int randomIntervalMinutes =
model->min_interval + rand() % (model->max_interval - model->min_interval + 1);
// Randomize the mouse movement distance and direction
int move_x = (rand() % 2001) - 1000; // Randomly between -1000 and 1000
int move_y = (rand() % 2001) - 1000; // Randomly between -1000 and 1000
// Perform the mouse move with the randomized values
hid_hal_mouse_move(hid_mouse_jiggler->hid, move_x, move_y);
// Restart timer with the new random interval
furi_timer_stop(hid_mouse_jiggler->timer);
furi_timer_start(hid_mouse_jiggler->timer, randomIntervalMinutes * 60000);
}
},
false);
@ -105,23 +116,51 @@ static bool hid_mouse_jiggler_input_callback(InputEvent* event, void* context) {
hid_mouse_jiggler->view,
HidMouseJigglerModel * model,
{
if(event->type == InputTypePress && event->key == InputKeyOk) {
model->running = !model->running;
if(model->running) {
furi_timer_stop(hid_mouse_jiggler->timer);
furi_timer_start(hid_mouse_jiggler->timer, intervals[model->interval_idx]);
};
consumed = true;
}
if(event->type == InputTypePress && event->key == InputKeyRight && !model->running &&
model->interval_idx < (int)COUNT_OF(intervals) - 1) {
model->interval_idx++;
consumed = true;
}
if(event->type == InputTypePress && event->key == InputKeyLeft && !model->running &&
model->interval_idx > 0) {
model->interval_idx--;
consumed = true;
if(event->type == InputTypePress) {
switch(event->key) {
case InputKeyOk:
model->running = !model->running;
if(model->running) {
furi_timer_stop(hid_mouse_jiggler->timer);
int randomIntervalMinutes =
model->min_interval +
rand() % (model->max_interval - model->min_interval + 1);
furi_timer_start(hid_mouse_jiggler->timer, randomIntervalMinutes * 60000);
}
consumed = true;
break;
case InputKeyUp:
if(!model->running && model->min_interval < model->max_interval) {
model->min_interval++; // Increment min interval by 1 minute
}
consumed = true;
break;
case InputKeyDown:
if(!model->running && model->min_interval > 1) { // Minimum 1 minute
model->min_interval--; // Decrement min interval by 1 minute
}
consumed = true;
break;
case InputKeyRight:
if(!model->running && model->max_interval < 30) { // Maximum 30 minutes
model->max_interval++; // Increment max interval by 1 minute
}
consumed = true;
break;
case InputKeyLeft:
if(!model->running && model->max_interval > model->min_interval + 1) {
model->max_interval--; // Decrement max interval by 1 minute
}
consumed = true;
break;
default:
break;
}
}
},
true);
@ -149,8 +188,9 @@ HidMouseJiggler* hid_mouse_jiggler_alloc(Hid* hid) {
hid_mouse_jiggler->view,
HidMouseJigglerModel * model,
{
model->transport = hid->transport;
model->interval_idx = 2;
// Initialize the min and max interval values
model->min_interval = 2; // 2 minutes
model->max_interval = 15; // 15 minutes
},
true);

View File

@ -2,8 +2,6 @@
#include <gui/view.h>
#define MOUSE_MOVE_SHORT 5
typedef struct Hid Hid;
typedef struct HidMouseJiggler HidMouseJiggler;

View File

@ -21,7 +21,6 @@ env.Append(
File("protocols/iso14443_4b/iso14443_4b.h"),
File("protocols/mf_ultralight/mf_ultralight.h"),
File("protocols/mf_classic/mf_classic.h"),
File("protocols/mf_plus/mf_plus.h"),
File("protocols/mf_desfire/mf_desfire.h"),
File("protocols/emv/emv.h"),
File("protocols/slix/slix.h"),
@ -34,7 +33,6 @@ env.Append(
File("protocols/iso14443_4b/iso14443_4b_poller.h"),
File("protocols/mf_ultralight/mf_ultralight_poller.h"),
File("protocols/mf_classic/mf_classic_poller.h"),
File("protocols/mf_plus/mf_plus_poller.h"),
File("protocols/mf_desfire/mf_desfire_poller.h"),
File("protocols/emv/emv_poller.h"),
File("protocols/st25tb/st25tb_poller.h"),

View File

@ -1,189 +0,0 @@
#include "mf_plus_i.h"
#include <bit_lib/bit_lib.h>
#include <furi.h>
#define MF_PLUS_PROTOCOL_NAME "Mifare Plus"
static const char* mf_plus_type_strings[] = {
[MfPlusTypeS] = "Plus S",
[MfPlusTypeX] = "Plus X",
[MfPlusTypeSE] = "Plus SE",
[MfPlusTypeEV1] = "Plus EV1",
[MfPlusTypeEV2] = "Plus EV2",
[MfPlusTypePlus] = "Plus",
[MfPlusTypeUnknown] = "Unknown",
};
static const char* mf_plus_size_strings[] = {
[MfPlusSize1K] = "1K",
[MfPlusSize2K] = "2K",
[MfPlusSize4K] = "4K",
[MfPlusSizeUnknown] = "Unknown",
};
static const char* mf_plus_security_level_strings[] = {
[MfPlusSecurityLevel0] = "SL0",
[MfPlusSecurityLevel1] = "SL1",
[MfPlusSecurityLevel2] = "SL2",
[MfPlusSecurityLevel3] = "SL3",
[MfPlusSecurityLevelUnknown] = "Unknown",
};
const NfcDeviceBase nfc_device_mf_plus = {
.protocol_name = MF_PLUS_PROTOCOL_NAME,
.alloc = (NfcDeviceAlloc)mf_plus_alloc,
.free = (NfcDeviceFree)mf_plus_free,
.reset = (NfcDeviceReset)mf_plus_reset,
.copy = (NfcDeviceCopy)mf_plus_copy,
.verify = (NfcDeviceVerify)mf_plus_verify,
.load = (NfcDeviceLoad)mf_plus_load,
.save = (NfcDeviceSave)mf_plus_save,
.is_equal = (NfcDeviceEqual)mf_plus_is_equal,
.get_name = (NfcDeviceGetName)mf_plus_get_device_name,
.get_uid = (NfcDeviceGetUid)mf_plus_get_uid,
.set_uid = (NfcDeviceSetUid)mf_plus_set_uid,
.get_base_data = (NfcDeviceGetBaseData)mf_plus_get_base_data,
};
MfPlusData* mf_plus_alloc(void) {
MfPlusData* data = malloc(sizeof(MfPlusData));
data->device_name = furi_string_alloc();
data->iso14443_4a_data = iso14443_4a_alloc();
data->type = MfPlusTypeUnknown;
data->security_level = MfPlusSecurityLevelUnknown;
data->size = MfPlusSizeUnknown;
return data;
}
void mf_plus_free(MfPlusData* data) {
furi_check(data);
furi_string_free(data->device_name);
iso14443_4a_free(data->iso14443_4a_data);
free(data);
}
void mf_plus_reset(MfPlusData* data) {
furi_check(data);
iso14443_4a_reset(data->iso14443_4a_data);
memset(&data->version, 0, sizeof(data->version));
data->type = MfPlusTypeUnknown;
data->security_level = MfPlusSecurityLevelUnknown;
data->size = MfPlusSizeUnknown;
}
void mf_plus_copy(MfPlusData* data, const MfPlusData* other) {
furi_check(data);
furi_check(other);
iso14443_4a_copy(data->iso14443_4a_data, other->iso14443_4a_data);
data->version = other->version;
data->type = other->type;
data->security_level = other->security_level;
data->size = other->size;
}
bool mf_plus_verify(MfPlusData* data, const FuriString* device_type) {
UNUSED(data);
return furi_string_equal_str(device_type, MF_PLUS_PROTOCOL_NAME);
}
bool mf_plus_load(MfPlusData* data, FlipperFormat* ff, uint32_t version) {
furi_assert(data);
bool success = false;
do {
if(!iso14443_4a_load(data->iso14443_4a_data, ff, version)) break;
if(!mf_plus_version_load(&data->version, ff)) break;
if(!mf_plus_type_load(&data->type, ff)) break;
if(!mf_plus_security_level_load(&data->security_level, ff)) break;
if(!mf_plus_size_load(&data->size, ff)) break;
success = true;
} while(false);
return success;
}
bool mf_plus_save(const MfPlusData* data, FlipperFormat* ff) {
furi_assert(data);
bool success = false;
do {
if(!iso14443_4a_save(data->iso14443_4a_data, ff)) break;
if(!flipper_format_write_comment_cstr(ff, MF_PLUS_PROTOCOL_NAME " specific data")) break;
if(!mf_plus_version_save(&data->version, ff)) break;
if(!mf_plus_type_save(&data->type, ff)) break;
if(!mf_plus_security_level_save(&data->security_level, ff)) break;
if(!mf_plus_size_save(&data->size, ff)) break;
success = true;
} while(false);
return success;
}
bool mf_plus_is_equal(const MfPlusData* data, const MfPlusData* other) {
furi_assert(data);
furi_assert(other);
bool equal = false;
do {
if(!iso14443_4a_is_equal(data->iso14443_4a_data, other->iso14443_4a_data)) break;
if(memcmp(&data->version, &other->version, sizeof(data->version)) != 0) break;
if(data->security_level != other->security_level) break;
if(data->type != other->type) break;
if(data->size != other->size) break;
equal = true;
} while(false);
return equal;
}
const char* mf_plus_get_device_name(const MfPlusData* data, NfcDeviceNameType name_type) {
furi_check(data);
FuriString* full_name = furi_string_alloc();
const char* name = NULL;
do {
if(name_type == NfcDeviceNameTypeFull) {
furi_string_reset(data->device_name);
furi_string_cat_printf(
data->device_name,
"Mifare %s %s %s",
mf_plus_type_strings[data->type], // Includes "Plus" for regular Mifare Plus cards
mf_plus_size_strings[data->size],
mf_plus_security_level_strings[data->security_level]);
name = furi_string_get_cstr(data->device_name);
FURI_LOG_D("Mifare Plus", "Full name: %s", name);
} else if(name_type == NfcDeviceNameTypeShort) {
name = "Mifare Plus";
} else {
break;
}
} while(false);
furi_string_free(full_name);
FURI_LOG_D("Mifare Plus", "Name: %s", name);
return name;
}
const uint8_t* mf_plus_get_uid(const MfPlusData* data, size_t* uid_len) {
furi_assert(data);
return iso14443_4a_get_uid(data->iso14443_4a_data, uid_len);
}
bool mf_plus_set_uid(MfPlusData* data, const uint8_t* uid, size_t uid_len) {
furi_assert(data);
return iso14443_4a_set_uid(data->iso14443_4a_data, uid, uid_len);
}
Iso14443_4aData* mf_plus_get_base_data(const MfPlusData* data) {
furi_check(data);
return data->iso14443_4a_data;
}

View File

@ -1,117 +0,0 @@
#pragma once
#include <lib/nfc/protocols/iso14443_4a/iso14443_4a.h>
#include <lib/toolbox/simple_array.h>
#ifdef __cplusplus
extern "C" {
#endif
#define MF_PLUS_UID_SIZE (7)
#define MF_PLUS_BATCH_SIZE (5)
#define MF_PLUS_CMD_GET_VERSION (0x60)
typedef enum {
MfPlusErrorNone,
MfPlusErrorUnknown,
MfPlusErrorNotPresent,
MfPlusErrorProtocol,
MfPlusErrorAuth,
MfPlusErrorPartialRead,
MfPlusErrorTimeout,
} MfPlusError;
typedef enum {
MfPlusTypePlus,
MfPlusTypeEV1,
MfPlusTypeEV2,
MfPlusTypeS,
MfPlusTypeSE,
MfPlusTypeX,
MfPlusTypeUnknown,
MfPlusTypeNum,
} MfPlusType;
typedef enum {
MfPlusSize1K,
MfPlusSize2K,
MfPlusSize4K,
MfPlusSizeUnknown,
MfPlusSizeNum,
} MfPlusSize;
typedef enum {
MfPlusSecurityLevel0,
MfPlusSecurityLevel1,
MfPlusSecurityLevel2,
MfPlusSecurityLevel3,
MfPlusSecurityLevelUnknown,
MfPlusSecurityLevelNum,
} MfPlusSecurityLevel;
typedef struct {
uint8_t hw_vendor;
uint8_t hw_type;
uint8_t hw_subtype;
uint8_t hw_major;
uint8_t hw_minor;
uint8_t hw_storage;
uint8_t hw_proto;
uint8_t sw_vendor;
uint8_t sw_type;
uint8_t sw_subtype;
uint8_t sw_major;
uint8_t sw_minor;
uint8_t sw_storage;
uint8_t sw_proto;
uint8_t uid[MF_PLUS_UID_SIZE];
uint8_t batch[MF_PLUS_BATCH_SIZE];
uint8_t prod_week;
uint8_t prod_year;
} MfPlusVersion;
typedef struct {
Iso14443_4aData* iso14443_4a_data;
MfPlusVersion version;
MfPlusType type;
MfPlusSize size;
MfPlusSecurityLevel security_level;
FuriString* device_name;
} MfPlusData;
extern const NfcDeviceBase nfc_device_mf_plus;
MfPlusData* mf_plus_alloc(void);
void mf_plus_free(MfPlusData* data);
void mf_plus_reset(MfPlusData* data);
void mf_plus_copy(MfPlusData* data, const MfPlusData* other);
bool mf_plus_verify(MfPlusData* data, const FuriString* device_type);
bool mf_plus_load(MfPlusData* data, FlipperFormat* ff, uint32_t version);
bool mf_plus_save(const MfPlusData* data, FlipperFormat* ff);
bool mf_plus_is_equal(const MfPlusData* data, const MfPlusData* other);
const char* mf_plus_get_device_name(const MfPlusData* data, NfcDeviceNameType name_type);
const uint8_t* mf_plus_get_uid(const MfPlusData* data, size_t* uid_len);
bool mf_plus_set_uid(MfPlusData* data, const uint8_t* uid, size_t uid_len);
Iso14443_4aData* mf_plus_get_base_data(const MfPlusData* data);
#ifdef __cplusplus
}
#endif

View File

@ -1,216 +0,0 @@
#include "mf_plus_i.h"
#define MF_PLUS_FFF_VERSION_KEY \
MF_PLUS_FFF_PICC_PREFIX " " \
"Version"
#define MF_PLUS_FFF_SECURITY_LEVEL_KEY "Security Level"
#define MF_PLUS_FFF_CARD_TYPE_KEY "Card Type"
#define MF_PLUS_FFF_MEMORY_SIZE_KEY "Memory Size"
bool mf_plus_version_parse(MfPlusVersion* data, const BitBuffer* buf) {
const bool can_parse = bit_buffer_get_size_bytes(buf) == sizeof(MfPlusVersion);
if(can_parse) {
bit_buffer_write_bytes(buf, data, sizeof(MfPlusVersion));
}
return can_parse;
}
bool mf_plus_security_level_parse(MfPlusSecurityLevel* data, const BitBuffer* buf) {
const bool can_parse = bit_buffer_get_size_bytes(buf) == sizeof(MfPlusSecurityLevel);
if(can_parse) {
bit_buffer_write_bytes(buf, data, sizeof(MfPlusSecurityLevel));
}
return can_parse;
}
bool mf_plus_type_parse(MfPlusType* data, const BitBuffer* buf) {
const bool can_parse = bit_buffer_get_size_bytes(buf) == sizeof(MfPlusType);
if(can_parse) {
bit_buffer_write_bytes(buf, data, sizeof(MfPlusType));
}
return can_parse;
}
bool mf_plus_size_parse(MfPlusSize* data, const BitBuffer* buf) {
const bool can_parse = bit_buffer_get_size_bytes(buf) == sizeof(MfPlusSize);
if(can_parse) {
bit_buffer_write_bytes(buf, data, sizeof(MfPlusSize));
}
return can_parse;
}
bool mf_plus_version_load(MfPlusVersion* data, FlipperFormat* ff) {
return flipper_format_read_hex(
ff, MF_PLUS_FFF_VERSION_KEY, (uint8_t*)data, sizeof(MfPlusVersion));
}
bool mf_plus_security_level_load(MfPlusSecurityLevel* data, FlipperFormat* ff) {
FuriString* security_level_string = furi_string_alloc();
flipper_format_read_string(ff, MF_PLUS_FFF_SECURITY_LEVEL_KEY, security_level_string);
// Take the last character of the string
char security_level_char = furi_string_get_char(
security_level_string, furi_string_utf8_length(security_level_string) - 1);
switch(security_level_char) {
case '0':
*data = MfPlusSecurityLevel0;
break;
case '1':
*data = MfPlusSecurityLevel1;
break;
case '2':
*data = MfPlusSecurityLevel2;
break;
case '3':
*data = MfPlusSecurityLevel3;
break;
default:
*data = MfPlusSecurityLevelUnknown;
break;
}
furi_string_free(security_level_string);
return true;
}
bool mf_plus_type_load(MfPlusType* data, FlipperFormat* ff) {
FuriString* type_string = furi_string_alloc();
flipper_format_read_string(ff, MF_PLUS_FFF_CARD_TYPE_KEY, type_string);
if(furi_string_equal_str(type_string, "Mifare Plus")) {
*data = MfPlusTypePlus;
} else if(furi_string_equal_str(type_string, "Mifare Plus X")) {
*data = MfPlusTypeX;
} else if(furi_string_equal_str(type_string, "Mifare Plus S")) {
*data = MfPlusTypeS;
} else if(furi_string_equal_str(type_string, "Mifare Plus SE")) {
*data = MfPlusTypeSE;
} else if(furi_string_equal_str(type_string, "Mifare Plus EV1")) {
*data = MfPlusTypeEV1;
} else if(furi_string_equal_str(type_string, "Mifare Plus EV2")) {
*data = MfPlusTypeEV2;
} else {
*data = MfPlusTypeUnknown;
}
furi_string_free(type_string);
return true;
}
bool mf_plus_size_load(MfPlusSize* data, FlipperFormat* ff) {
FuriString* size_string = furi_string_alloc();
flipper_format_read_string(ff, MF_PLUS_FFF_MEMORY_SIZE_KEY, size_string);
if(furi_string_equal_str(size_string, "1K")) {
*data = MfPlusSize1K;
} else if(furi_string_equal_str(size_string, "2K")) {
*data = MfPlusSize2K;
} else if(furi_string_equal_str(size_string, "4K")) {
*data = MfPlusSize4K;
} else {
*data = MfPlusSizeUnknown;
}
furi_string_free(size_string);
return true;
}
bool mf_plus_version_save(const MfPlusVersion* data, FlipperFormat* ff) {
return flipper_format_write_hex(
ff, MF_PLUS_FFF_VERSION_KEY, (const uint8_t*)data, sizeof(MfPlusVersion));
}
bool mf_plus_security_level_save(const MfPlusSecurityLevel* data, FlipperFormat* ff) {
FuriString* security_level_string = furi_string_alloc();
switch(*data) {
case MfPlusSecurityLevel0:
furi_string_cat(security_level_string, "SL0");
break;
case MfPlusSecurityLevel1:
furi_string_cat(security_level_string, "SL1");
break;
case MfPlusSecurityLevel2:
furi_string_cat(security_level_string, "SL2");
break;
case MfPlusSecurityLevel3:
furi_string_cat(security_level_string, "SL3");
break;
default:
furi_string_cat(security_level_string, "Unknown");
break;
}
flipper_format_write_string(ff, MF_PLUS_FFF_SECURITY_LEVEL_KEY, security_level_string);
furi_string_free(security_level_string);
return true;
}
bool mf_plus_type_save(const MfPlusType* data, FlipperFormat* ff) {
FuriString* type_string = furi_string_alloc();
switch(*data) {
case MfPlusTypePlus:
furi_string_cat(type_string, "Mifare Plus");
break;
case MfPlusTypeX:
furi_string_cat(type_string, "Mifare Plus X");
break;
case MfPlusTypeS:
furi_string_cat(type_string, "Mifare Plus S");
break;
case MfPlusTypeSE:
furi_string_cat(type_string, "Mifare Plus SE");
break;
case MfPlusTypeEV1:
furi_string_cat(type_string, "Mifare Plus EV1");
break;
case MfPlusTypeEV2:
furi_string_cat(type_string, "Mifare Plus EV2");
break;
default:
furi_string_cat(type_string, "Unknown");
break;
}
flipper_format_write_string(ff, MF_PLUS_FFF_CARD_TYPE_KEY, type_string);
furi_string_free(type_string);
return true;
}
bool mf_plus_size_save(const MfPlusSize* data, FlipperFormat* ff) {
FuriString* size_string = furi_string_alloc();
switch(*data) {
case MfPlusSize1K:
furi_string_cat(size_string, "1K");
break;
case MfPlusSize2K:
furi_string_cat(size_string, "2K");
break;
case MfPlusSize4K:
furi_string_cat(size_string, "4K");
break;
default:
furi_string_cat(size_string, "Unknown");
break;
}
flipper_format_write_string(ff, MF_PLUS_FFF_MEMORY_SIZE_KEY, size_string);
furi_string_free(size_string);
return true;
}

View File

@ -1,29 +0,0 @@
#pragma once
#include "mf_plus.h"
#define MF_PLUS_FFF_PICC_PREFIX "PICC"
bool mf_plus_version_parse(MfPlusVersion* data, const BitBuffer* buf);
bool mf_plus_security_level_parse(MfPlusSecurityLevel* data, const BitBuffer* buf);
bool mf_plus_type_parse(MfPlusType* data, const BitBuffer* buf);
bool mf_plus_size_parse(MfPlusSize* data, const BitBuffer* buf);
bool mf_plus_version_load(MfPlusVersion* data, FlipperFormat* ff);
bool mf_plus_security_level_load(MfPlusSecurityLevel* data, FlipperFormat* ff);
bool mf_plus_type_load(MfPlusType* data, FlipperFormat* ff);
bool mf_plus_size_load(MfPlusSize* data, FlipperFormat* ff);
bool mf_plus_version_save(const MfPlusVersion* data, FlipperFormat* ff);
bool mf_plus_security_level_save(const MfPlusSecurityLevel* data, FlipperFormat* ff);
bool mf_plus_type_save(const MfPlusType* data, FlipperFormat* ff);
bool mf_plus_size_save(const MfPlusSize* data, FlipperFormat* ff);

View File

@ -1,367 +0,0 @@
#include "mf_plus_poller_i.h"
#include <nfc/protocols/nfc_poller_base.h>
#include <furi.h>
#define TAG "MfPlusPoller"
#define MF_PLUS_BUF_SIZE (64U)
#define MF_PLUS_RESULT_BUF_SIZE (512U)
const char* mf_plus_ats_t1_tk_values[] = {
"\xC1\x05\x2F\x2F\x00\x35\xC7", // Mifare Plus S
"\xC1\x05\x2F\x2F\x01\xBC\xD6", // Mifare Plus X
"\xC1\x05\x2F\x2F\x00\xF6\xD1", // Mifare Plus SE
"\xC1\x05\x2F\x2F\x01\xF6\xD1", // Mifare Plus SE
};
typedef NfcCommand (*MfPlusPollerReadHandler)(MfPlusPoller* instance);
const MfPlusData* mf_plus_poller_get_data(MfPlusPoller* instance) {
furi_assert(instance);
return instance->data;
}
bool mf_plus_poller_get_type_from_iso4(const Iso14443_4aData* iso4_data, MfPlusData* mf_plus_data) {
furi_assert(iso4_data);
furi_assert(mf_plus_data);
switch(iso4_data->iso14443_3a_data->sak) {
case 0x08:
if(memcmp(
simple_array_get_data(iso4_data->ats_data.t1_tk),
mf_plus_ats_t1_tk_values[0],
simple_array_get_count(iso4_data->ats_data.t1_tk)) == 0) {
// Mifare Plus S 2K SL1
mf_plus_data->type = MfPlusTypeS;
mf_plus_data->size = MfPlusSize2K;
mf_plus_data->security_level = MfPlusSecurityLevel1;
FURI_LOG_D(TAG, "Mifare Plus S 2K SL1");
return true;
} else if(
memcmp(
simple_array_get_data(iso4_data->ats_data.t1_tk),
mf_plus_ats_t1_tk_values[1],
simple_array_get_count(iso4_data->ats_data.t1_tk)) == 0) {
// Mifare Plus X 2K SL1
mf_plus_data->type = MfPlusTypeX;
mf_plus_data->size = MfPlusSize2K;
mf_plus_data->security_level = MfPlusSecurityLevel1;
FURI_LOG_D(TAG, "Mifare Plus X 2K SL1");
return true;
} else if(
memcmp(
simple_array_get_data(iso4_data->ats_data.t1_tk),
mf_plus_ats_t1_tk_values[2],
simple_array_get_count(iso4_data->ats_data.t1_tk)) == 0 ||
memcmp(
simple_array_get_data(iso4_data->ats_data.t1_tk),
mf_plus_ats_t1_tk_values[3],
simple_array_get_count(iso4_data->ats_data.t1_tk)) == 0) {
// Mifare Plus SE 1K SL1
mf_plus_data->type = MfPlusTypeSE;
mf_plus_data->size = MfPlusSize1K;
mf_plus_data->security_level = MfPlusSecurityLevel1;
FURI_LOG_D(TAG, "Mifare Plus SE 1K SL1");
return true;
} else {
FURI_LOG_D(TAG, "Sak 08 but no known Mifare Plus type");
return false;
}
case 0x18:
if(memcmp(
simple_array_get_data(iso4_data->ats_data.t1_tk),
mf_plus_ats_t1_tk_values[0],
simple_array_get_count(iso4_data->ats_data.t1_tk)) == 0) {
// Mifare Plus S 4K SL1
mf_plus_data->type = MfPlusTypeS;
mf_plus_data->size = MfPlusSize4K;
mf_plus_data->security_level = MfPlusSecurityLevel1;
FURI_LOG_D(TAG, "Mifare Plus S 4K SL1");
return true;
} else if(
memcmp(
simple_array_get_data(iso4_data->ats_data.t1_tk),
mf_plus_ats_t1_tk_values[1],
simple_array_get_count(iso4_data->ats_data.t1_tk)) == 0) {
// Mifare Plus X 4K SL1
mf_plus_data->type = MfPlusTypeX;
mf_plus_data->size = MfPlusSize4K;
mf_plus_data->security_level = MfPlusSecurityLevel1;
FURI_LOG_D(TAG, "Mifare Plus X 4K SL1");
return true;
} else {
FURI_LOG_D(TAG, "Sak 18 but no known Mifare Plus type");
return false;
}
case 0x20:
if(memcmp(
iso4_data->ats_data.t1_tk,
mf_plus_ats_t1_tk_values[0],
simple_array_get_count(iso4_data->ats_data.t1_tk)) == 0) {
// Mifare Plus S 2/4K SL3
mf_plus_data->type = MfPlusTypeS;
mf_plus_data->security_level = MfPlusSecurityLevel3;
if(iso4_data->iso14443_3a_data->atqa[1] == 0x04) {
// Mifare Plus S 2K SL3
mf_plus_data->size = MfPlusSize2K;
FURI_LOG_D(TAG, "Mifare Plus S 2K SL3");
} else if(iso4_data->iso14443_3a_data->atqa[1] == 0x02) {
// Mifare Plus S 4K SL3
mf_plus_data->size = MfPlusSize4K;
FURI_LOG_D(TAG, "Mifare Plus S 4K SL3");
} else {
FURI_LOG_D(TAG, "Sak 20 but no known Mifare Plus type (S)");
return false;
}
return true;
} else if(
memcmp(
iso4_data->ats_data.t1_tk,
mf_plus_ats_t1_tk_values[1],
simple_array_get_count(iso4_data->ats_data.t1_tk)) == 0) {
mf_plus_data->type = MfPlusTypeX;
mf_plus_data->security_level = MfPlusSecurityLevel3;
if(iso4_data->iso14443_3a_data->atqa[1] == 0x04) {
mf_plus_data->size = MfPlusSize2K;
FURI_LOG_D(TAG, "Mifare Plus X 2K SL3");
} else if(iso4_data->iso14443_3a_data->atqa[1] == 0x02) {
mf_plus_data->size = MfPlusSize4K;
FURI_LOG_D(TAG, "Mifare Plus X 4K SL3");
} else {
FURI_LOG_D(TAG, "Sak 20 but no known Mifare Plus type (X)");
return false;
}
return true;
} else {
FURI_LOG_D(TAG, "Sak 20 but no known Mifare Plus type");
return false;
}
}
FURI_LOG_D(TAG, "No known Mifare Plus type");
return false;
}
static bool mf_plus_poller_detect_type(MfPlusPoller* instance) {
furi_assert(instance);
bool detected = false;
const Iso14443_4aData* iso14443_4a_data =
iso14443_4a_poller_get_data(instance->iso14443_4a_poller);
const MfPlusError error = mf_plus_poller_read_version(instance, &instance->data->version);
if(error == MfPlusErrorNone) {
FURI_LOG_D(TAG, "Read version success: %d", error);
if(instance->data->version.hw_major == 0x02 || instance->data->version.hw_major == 0x82) {
detected = true;
if(iso14443_4a_data->iso14443_3a_data->sak == 0x10) {
// Mifare Plus 2K SL2
instance->data->type = MfPlusTypePlus;
instance->data->size = MfPlusSize2K;
instance->data->security_level = MfPlusSecurityLevel2;
} else if(iso14443_4a_data->iso14443_3a_data->sak == 0x11) {
// Mifare Plus 4K SL3
instance->data->type = MfPlusTypePlus;
instance->data->size = MfPlusSize4K;
instance->data->security_level = MfPlusSecurityLevel3;
} else {
// Mifare Plus EV1/EV2
// Revision
switch(instance->data->version.hw_major) {
case 0x11:
instance->data->type = MfPlusTypeEV1;
break;
case 0x22:
instance->data->type = MfPlusTypeEV2;
break;
default:
instance->data->type = MfPlusTypeUnknown;
break;
}
// Storage size
switch(instance->data->version.hw_storage) {
case 0x16:
instance->data->size = MfPlusSize2K;
break;
case 0x18:
instance->data->size = MfPlusSize4K;
break;
default:
instance->data->size = MfPlusSizeUnknown;
break;
}
// Security level
if(iso14443_4a_data->iso14443_3a_data->sak == 0x20) {
// Mifare Plus EV1/2 SL3
instance->data->security_level = MfPlusSecurityLevel3;
} else {
// Mifare Plus EV1/2 SL1
instance->data->security_level = MfPlusSecurityLevel1;
}
}
}
} else {
FURI_LOG_D(TAG, "Read version error: %d", error);
detected = mf_plus_poller_get_type_from_iso4(iso14443_4a_data, instance->data);
}
return detected;
}
MfPlusPoller* mf_plus_poller_alloc(Iso14443_4aPoller* iso14443_4a_poller) {
furi_assert(iso14443_4a_poller);
MfPlusPoller* instance = malloc(sizeof(MfPlusPoller));
furi_assert(instance);
instance->iso14443_4a_poller = iso14443_4a_poller;
instance->data = mf_plus_alloc();
instance->tx_buffer = bit_buffer_alloc(MF_PLUS_BUF_SIZE);
instance->rx_buffer = bit_buffer_alloc(MF_PLUS_BUF_SIZE);
instance->input_buffer = bit_buffer_alloc(MF_PLUS_BUF_SIZE);
instance->result_buffer = bit_buffer_alloc(MF_PLUS_RESULT_BUF_SIZE);
instance->general_event.protocol = NfcProtocolMfPlus;
instance->general_event.event_data = &instance->mfp_event;
instance->general_event.instance = instance;
instance->mfp_event.data = &instance->mfp_event_data;
return instance;
}
static NfcCommand mf_plus_poller_handler_idle(MfPlusPoller* instance) {
furi_assert(instance);
bit_buffer_reset(instance->input_buffer);
bit_buffer_reset(instance->result_buffer);
bit_buffer_reset(instance->tx_buffer);
bit_buffer_reset(instance->rx_buffer);
iso14443_4a_copy(
instance->data->iso14443_4a_data,
iso14443_4a_poller_get_data(instance->iso14443_4a_poller));
instance->state = MfPlusPollerStateReadVersion;
return NfcCommandContinue;
}
static NfcCommand mf_plus_poller_handler_read_version(MfPlusPoller* instance) {
bool success = mf_plus_poller_detect_type(instance);
if(success) {
instance->state = MfPlusPollerStateReadSuccess;
} else {
instance->state = MfPlusPollerStateReadFailed;
}
return NfcCommandContinue;
}
static NfcCommand mf_plus_poller_handler_read_failed(MfPlusPoller* instance) {
furi_assert(instance);
FURI_LOG_D(TAG, "Read failed");
iso14443_4a_poller_halt(instance->iso14443_4a_poller);
instance->mfp_event.data->error = instance->error;
NfcCommand command = instance->callback(instance->general_event, instance->context);
instance->state = MfPlusPollerStateIdle;
return command;
}
static NfcCommand mf_plus_poller_handler_read_success(MfPlusPoller* instance) {
furi_assert(instance);
FURI_LOG_D(TAG, "Read success");
iso14443_4a_poller_halt(instance->iso14443_4a_poller);
instance->mfp_event.type = MfPlusPollerEventTypeReadSuccess;
NfcCommand command = instance->callback(instance->general_event, instance->context);
return command;
}
static const MfPlusPollerReadHandler mf_plus_poller_read_handler[MfPlusPollerStateNum] = {
[MfPlusPollerStateIdle] = mf_plus_poller_handler_idle,
[MfPlusPollerStateReadVersion] = mf_plus_poller_handler_read_version,
[MfPlusPollerStateReadFailed] = mf_plus_poller_handler_read_failed,
[MfPlusPollerStateReadSuccess] = mf_plus_poller_handler_read_success,
};
static void mf_plus_poller_set_callback(
MfPlusPoller* instance,
NfcGenericCallback callback,
void* context) {
furi_assert(instance);
furi_assert(callback);
instance->callback = callback;
instance->context = context;
}
static NfcCommand mf_plus_poller_run(NfcGenericEvent event, void* context) {
furi_assert(event.protocol = NfcProtocolIso14443_4a);
MfPlusPoller* instance = context;
furi_assert(instance);
const Iso14443_4aPollerEvent* iso14443_4a_event = event.event_data;
furi_assert(iso14443_4a_event);
NfcCommand command = NfcCommandContinue;
if(iso14443_4a_event->type == Iso14443_4aPollerEventTypeReady) {
command = mf_plus_poller_read_handler[instance->state](instance);
} else if(iso14443_4a_event->type == Iso14443_4aPollerEventTypeError) {
instance->mfp_event.type = MfPlusPollerEventTypeReadFailed;
command = instance->callback(instance->general_event, instance->context);
}
return command;
}
void mf_plus_poller_free(MfPlusPoller* instance) {
furi_assert(instance);
furi_assert(instance->data);
bit_buffer_free(instance->tx_buffer);
bit_buffer_free(instance->rx_buffer);
bit_buffer_free(instance->input_buffer);
bit_buffer_free(instance->result_buffer);
mf_plus_free(instance->data);
free(instance);
}
static bool mf_plus_poller_detect(NfcGenericEvent event, void* context) {
furi_assert(event.protocol = NfcProtocolIso14443_4a);
MfPlusPoller* instance = context;
furi_assert(instance);
Iso14443_4aPollerEvent* iso14443_4a_event = event.event_data;
furi_assert(iso14443_4a_event);
bool detected = false;
if(iso14443_4a_event->type == Iso14443_4aPollerEventTypeReady) {
detected = mf_plus_poller_detect_type(instance);
}
return detected;
}
const NfcPollerBase mf_plus_poller = {
.alloc = (NfcPollerAlloc)mf_plus_poller_alloc,
.free = (NfcPollerFree)mf_plus_poller_free,
.set_callback = (NfcPollerSetCallback)mf_plus_poller_set_callback,
.run = (NfcPollerRun)mf_plus_poller_run,
.detect = (NfcPollerDetect)mf_plus_poller_detect,
.get_data = (NfcPollerGetData)mf_plus_poller_get_data,
};

View File

@ -1,55 +0,0 @@
#pragma once
#include "mf_plus.h"
#include <lib/nfc/protocols/iso14443_4a/iso14443_4a.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief MIFARE Plus poller opaque type definition.
*/
typedef struct MfPlusPoller MfPlusPoller;
/**
* @brief Enumeration of possible MfPlus poller event types.
*/
typedef enum {
MfPlusPollerEventTypeReadSuccess, /**< Card was read successfully. */
MfPlusPollerEventTypeReadFailed, /**< Poller failed to read the card. */
} MfPlusPollerEventType;
/**
* @brief MIFARE Plus poller event data.
*/
typedef union {
MfPlusError error; /**< Error code indicating card reading fail reason. */
} MfPlusPollerEventData;
/**
* @brief MIFARE Plus poller event structure.
*
* Upon emission of an event, an instance of this struct will be passed to the callback.
*/
typedef struct {
MfPlusPollerEventType type; /**< Type of emitted event. */
MfPlusPollerEventData* data; /**< Pointer to event specific data. */
} MfPlusPollerEvent;
/**
* @brief Read MfPlus card version.
*
* Must ONLY be used inside the callback function.
*
* @param[in, out] instance pointer to the instance to be used in the transaction.
* @param[out] data pointer to the MfPlusVersion structure to be filled with version data.
* @return MfPlusErrorNone on success, an error code on failure.
*/
MfPlusError mf_plus_poller_read_version(MfPlusPoller* instance, MfPlusVersion* data);
#ifdef __cplusplus
}
#endif

View File

@ -1,5 +0,0 @@
#pragma once
#include <nfc/protocols/nfc_poller_base.h>
extern const NfcPollerBase mf_plus_poller;

View File

@ -1,73 +0,0 @@
#include "mf_plus_poller_i.h"
#include <furi.h>
#include "mf_plus_i.h"
#define TAG "MfPlusPoller"
MfPlusError mf_plus_process_error(Iso14443_4aError error) {
switch(error) {
case Iso14443_4aErrorNone:
return MfPlusErrorNone;
case Iso14443_4aErrorNotPresent:
return MfPlusErrorNotPresent;
case Iso14443_4aErrorTimeout:
return MfPlusErrorTimeout;
default:
return MfPlusErrorProtocol;
}
}
MfPlusError
mf_plus_send_chunk(MfPlusPoller* instance, const BitBuffer* tx_buffer, BitBuffer* rx_buffer) {
furi_assert(instance);
furi_assert(instance->iso14443_4a_poller);
furi_assert(instance->tx_buffer);
furi_assert(instance->rx_buffer);
furi_assert(tx_buffer);
furi_assert(rx_buffer);
MfPlusError error = MfPlusErrorNone;
do {
Iso14443_4aError iso14443_4a_error = iso14443_4a_poller_send_block(
instance->iso14443_4a_poller, tx_buffer, instance->rx_buffer);
if(iso14443_4a_error != Iso14443_4aErrorNone) {
error = mf_plus_process_error(iso14443_4a_error);
break;
}
bit_buffer_reset(instance->tx_buffer);
if(bit_buffer_get_size_bytes(instance->rx_buffer) > sizeof(uint8_t)) {
bit_buffer_copy_right(rx_buffer, instance->rx_buffer, sizeof(uint8_t));
} else {
bit_buffer_reset(rx_buffer);
}
} while(false);
return error;
}
MfPlusError mf_plus_poller_read_version(MfPlusPoller* instance, MfPlusVersion* data) {
furi_assert(instance);
bit_buffer_reset(instance->input_buffer);
bit_buffer_append_byte(instance->input_buffer, MF_PLUS_CMD_GET_VERSION);
MfPlusError error;
do {
error = mf_plus_send_chunk(instance, instance->input_buffer, instance->result_buffer);
if(error != MfPlusErrorNone) break;
if(!mf_plus_version_parse(data, instance->result_buffer)) {
error = MfPlusErrorProtocol;
}
} while(false);
return error;
}

View File

@ -1,54 +0,0 @@
#pragma once
#include "mf_plus_poller.h"
#include <lib/nfc/protocols/iso14443_4a/iso14443_4a_poller_i.h>
#ifdef __cplusplus
extern "C" {
#endif
#define MF_PLUS_FWT_FC (60000)
typedef enum {
MfPlusCardStateDetected,
MfPlusCardStateLost,
} MfPlusCardState;
typedef enum {
MfPlusPollerStateIdle,
MfPlusPollerStateReadVersion,
MfPlusPollerStateReadFailed,
MfPlusPollerStateReadSuccess,
MfPlusPollerStateNum,
} MfPlusPollerState;
struct MfPlusPoller {
Iso14443_4aPoller* iso14443_4a_poller;
MfPlusData* data;
MfPlusPollerState state;
BitBuffer* tx_buffer;
BitBuffer* rx_buffer;
BitBuffer* input_buffer;
BitBuffer* result_buffer;
MfPlusError error;
NfcGenericEvent general_event;
MfPlusPollerEvent mfp_event;
MfPlusPollerEventData mfp_event_data;
NfcGenericCallback callback;
void* context;
};
MfPlusError mf_plus_process_error(Iso14443_4aError error);
MfPlusPoller* mf_plus_poller_alloc(Iso14443_4aPoller* iso14443_4a_poller);
void mf_plus_poller_free(MfPlusPoller* instance);
#ifdef __cplusplus
}
#endif

View File

@ -20,7 +20,6 @@
#include <nfc/protocols/felica/felica.h>
#include <nfc/protocols/mf_ultralight/mf_ultralight.h>
#include <nfc/protocols/mf_classic/mf_classic.h>
#include <nfc/protocols/mf_plus/mf_plus.h>
#include <nfc/protocols/mf_desfire/mf_desfire.h>
#include <nfc/protocols/emv/emv.h>
#include <nfc/protocols/slix/slix_device_defs.h>
@ -41,7 +40,6 @@ const NfcDeviceBase* nfc_devices[NfcProtocolNum] = {
[NfcProtocolFelica] = &nfc_device_felica,
[NfcProtocolMfUltralight] = &nfc_device_mf_ultralight,
[NfcProtocolMfClassic] = &nfc_device_mf_classic,
[NfcProtocolMfPlus] = &nfc_device_mf_plus,
[NfcProtocolMfDesfire] = &nfc_device_mf_desfire,
[NfcProtocolSlix] = &nfc_device_slix,
[NfcProtocolSt25tb] = &nfc_device_st25tb,

View File

@ -8,7 +8,6 @@
#include <nfc/protocols/felica/felica_poller_defs.h>
#include <nfc/protocols/mf_ultralight/mf_ultralight_poller_defs.h>
#include <nfc/protocols/mf_classic/mf_classic_poller_defs.h>
#include <nfc/protocols/mf_plus/mf_plus_poller_defs.h>
#include <nfc/protocols/mf_desfire/mf_desfire_poller_defs.h>
#include <nfc/protocols/emv/emv_poller_defs.h>
#include <nfc/protocols/slix/slix_poller_defs.h>
@ -23,7 +22,6 @@ const NfcPollerBase* nfc_pollers_api[NfcProtocolNum] = {
[NfcProtocolFelica] = &nfc_poller_felica,
[NfcProtocolMfUltralight] = &mf_ultralight_poller,
[NfcProtocolMfClassic] = &mf_classic_poller,
[NfcProtocolMfPlus] = &mf_plus_poller,
[NfcProtocolMfDesfire] = &mf_desfire_poller,
[NfcProtocolSlix] = &nfc_poller_slix,
[NfcProtocolSt25tb] = &nfc_poller_st25tb,

View File

@ -63,7 +63,6 @@ static const NfcProtocol nfc_protocol_iso14443_3b_children_protocol[] = {
/** List of ISO14443-4A child protocols. */
static const NfcProtocol nfc_protocol_iso14443_4a_children_protocol[] = {
NfcProtocolMfDesfire,
NfcProtocolMfPlus,
NfcProtocolEmv,
};
@ -132,12 +131,6 @@ static const NfcProtocolTreeNode nfc_protocol_nodes[NfcProtocolNum] = {
.children_num = 0,
.children_protocol = NULL,
},
[NfcProtocolMfPlus] =
{
.parent_protocol = NfcProtocolIso14443_4a,
.children_num = 0,
.children_protocol = NULL,
},
[NfcProtocolMfDesfire] =
{
.parent_protocol = NfcProtocolIso14443_4a,

View File

@ -184,7 +184,6 @@ typedef enum {
NfcProtocolFelica,
NfcProtocolMfUltralight,
NfcProtocolMfClassic,
NfcProtocolMfPlus,
NfcProtocolMfDesfire,
NfcProtocolSlix,
NfcProtocolSt25tb,

View File

@ -154,8 +154,6 @@ Header,+,lib/nfc/protocols/mf_classic/mf_classic_poller.h,,
Header,+,lib/nfc/protocols/mf_classic/mf_classic_poller_sync.h,,
Header,+,lib/nfc/protocols/mf_desfire/mf_desfire.h,,
Header,+,lib/nfc/protocols/mf_desfire/mf_desfire_poller.h,,
Header,+,lib/nfc/protocols/mf_plus/mf_plus.h,,
Header,+,lib/nfc/protocols/mf_plus/mf_plus_poller.h,,
Header,+,lib/nfc/protocols/mf_ultralight/mf_ultralight.h,,
Header,+,lib/nfc/protocols/mf_ultralight/mf_ultralight_listener.h,,
Header,+,lib/nfc/protocols/mf_ultralight/mf_ultralight_poller.h,,
@ -2548,19 +2546,6 @@ Function,+,mf_desfire_save,_Bool,"const MfDesfireData*, FlipperFormat*"
Function,+,mf_desfire_send_chunks,MfDesfireError,"MfDesfirePoller*, const BitBuffer*, BitBuffer*"
Function,+,mf_desfire_set_uid,_Bool,"MfDesfireData*, const uint8_t*, size_t"
Function,+,mf_desfire_verify,_Bool,"MfDesfireData*, const FuriString*"
Function,+,mf_plus_alloc,MfPlusData*,
Function,+,mf_plus_copy,void,"MfPlusData*, const MfPlusData*"
Function,+,mf_plus_free,void,MfPlusData*
Function,+,mf_plus_get_base_data,Iso14443_4aData*,const MfPlusData*
Function,+,mf_plus_get_device_name,const char*,"const MfPlusData*, NfcDeviceNameType"
Function,+,mf_plus_get_uid,const uint8_t*,"const MfPlusData*, size_t*"
Function,+,mf_plus_is_equal,_Bool,"const MfPlusData*, const MfPlusData*"
Function,+,mf_plus_load,_Bool,"MfPlusData*, FlipperFormat*, uint32_t"
Function,+,mf_plus_poller_read_version,MfPlusError,"MfPlusPoller*, MfPlusVersion*"
Function,+,mf_plus_reset,void,MfPlusData*
Function,+,mf_plus_save,_Bool,"const MfPlusData*, FlipperFormat*"
Function,+,mf_plus_set_uid,_Bool,"MfPlusData*, const uint8_t*, size_t"
Function,+,mf_plus_verify,_Bool,"MfPlusData*, const FuriString*"
Function,+,mf_ultralight_alloc,MfUltralightData*,
Function,+,mf_ultralight_copy,void,"MfUltralightData*, const MfUltralightData*"
Function,+,mf_ultralight_detect_protocol,_Bool,const Iso14443_3aData*
@ -3874,7 +3859,6 @@ Variable,-,nfc_device_emv,const NfcDeviceBase,
Variable,-,nfc_device_felica,const NfcDeviceBase,
Variable,-,nfc_device_mf_classic,const NfcDeviceBase,
Variable,-,nfc_device_mf_desfire,const NfcDeviceBase,
Variable,-,nfc_device_mf_plus,const NfcDeviceBase,
Variable,-,nfc_device_mf_ultralight,const NfcDeviceBase,
Variable,-,nfc_device_st25tb,const NfcDeviceBase,
Variable,+,sequence_audiovisual_alert,const NotificationSequence,

1 entry status name type params
154 Header + lib/nfc/protocols/mf_classic/mf_classic_poller_sync.h
155 Header + lib/nfc/protocols/mf_desfire/mf_desfire.h
156 Header + lib/nfc/protocols/mf_desfire/mf_desfire_poller.h
Header + lib/nfc/protocols/mf_plus/mf_plus.h
Header + lib/nfc/protocols/mf_plus/mf_plus_poller.h
157 Header + lib/nfc/protocols/mf_ultralight/mf_ultralight.h
158 Header + lib/nfc/protocols/mf_ultralight/mf_ultralight_listener.h
159 Header + lib/nfc/protocols/mf_ultralight/mf_ultralight_poller.h
2546 Function + mf_desfire_send_chunks MfDesfireError MfDesfirePoller*, const BitBuffer*, BitBuffer*
2547 Function + mf_desfire_set_uid _Bool MfDesfireData*, const uint8_t*, size_t
2548 Function + mf_desfire_verify _Bool MfDesfireData*, const FuriString*
Function + mf_plus_alloc MfPlusData*
Function + mf_plus_copy void MfPlusData*, const MfPlusData*
Function + mf_plus_free void MfPlusData*
Function + mf_plus_get_base_data Iso14443_4aData* const MfPlusData*
Function + mf_plus_get_device_name const char* const MfPlusData*, NfcDeviceNameType
Function + mf_plus_get_uid const uint8_t* const MfPlusData*, size_t*
Function + mf_plus_is_equal _Bool const MfPlusData*, const MfPlusData*
Function + mf_plus_load _Bool MfPlusData*, FlipperFormat*, uint32_t
Function + mf_plus_poller_read_version MfPlusError MfPlusPoller*, MfPlusVersion*
Function + mf_plus_reset void MfPlusData*
Function + mf_plus_save _Bool const MfPlusData*, FlipperFormat*
Function + mf_plus_set_uid _Bool MfPlusData*, const uint8_t*, size_t
Function + mf_plus_verify _Bool MfPlusData*, const FuriString*
2549 Function + mf_ultralight_alloc MfUltralightData*
2550 Function + mf_ultralight_copy void MfUltralightData*, const MfUltralightData*
2551 Function + mf_ultralight_detect_protocol _Bool const Iso14443_3aData*
3859 Variable - nfc_device_felica const NfcDeviceBase
3860 Variable - nfc_device_mf_classic const NfcDeviceBase
3861 Variable - nfc_device_mf_desfire const NfcDeviceBase
Variable - nfc_device_mf_plus const NfcDeviceBase
3862 Variable - nfc_device_mf_ultralight const NfcDeviceBase
3863 Variable - nfc_device_st25tb const NfcDeviceBase
3864 Variable + sequence_audiovisual_alert const NotificationSequence