diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
new file mode 100644
index 000000000..5b19d123b
--- /dev/null
+++ b/.github/workflows/build.yml
@@ -0,0 +1,159 @@
+name: 'Build'
+
+on:
+ push:
+ branches:
+ - dev
+ - "release*"
+ tags:
+ - '*'
+ pull_request:
+
+env:
+ TARGETS: f7
+ DEFAULT_TARGET: f7
+ FBT_TOOLCHAIN_PATH: /home/runner/work
+
+jobs:
+ main:
+ runs-on: ubuntu-latest
+ steps:
+ - name: 'Decontaminate previous build leftovers'
+ run: |
+ if [ -d .git ]; then
+ git submodule status || git checkout "$(git rev-list --max-parents=0 HEAD | tail -n 1)"
+ fi
+
+ - name: 'Checkout code'
+ uses: actions/checkout@v3
+ with:
+ fetch-depth: 0
+ ref: ${{ github.event.pull_request.head.sha }}
+
+ - name: 'Get commit details'
+ id: names
+ run: |
+ if [[ ${{ github.event_name }} == 'pull_request' ]]; then
+ TYPE="pull"
+ elif [[ "${{ github.ref }}" == "refs/tags/"* ]]; then
+ TYPE="tag"
+ else
+ TYPE="other"
+ fi
+ python3 scripts/get_env.py "--event_file=${{ github.event_path }}" "--type=$TYPE"
+ echo random_hash=$(openssl rand -base64 40 | shasum -a 256 | awk '{print $1}') >> $GITHUB_OUTPUT
+ echo "event_type=$TYPE" >> $GITHUB_OUTPUT
+
+ - name: 'Make artifacts directory'
+ run: |
+ rm -rf artifacts
+ mkdir artifacts
+
+ - name: 'Bundle scripts'
+ run: |
+ tar czpf artifacts/flipper-z-any-scripts-${SUFFIX}.tgz scripts debug
+
+ - name: 'Build the firmware'
+ run: |
+ set -e
+ for TARGET in ${TARGETS}; do
+ ./fbt TARGET_HW="$(echo "${TARGET}" | sed 's/f//')" \
+ copro_dist updater_package ${{ startsWith(github.ref, 'refs/tags') && 'DEBUG=0 COMPACT=1' || '' }}
+ done
+
+ - name: 'Move upload files'
+ run: |
+ set -e
+ for TARGET in ${TARGETS}; do
+ mv dist/${TARGET}-*/* artifacts/
+ done
+
+ - name: "Check for uncommitted changes"
+ run: |
+ git diff --exit-code
+
+ - name: 'Bundle resources'
+ run: |
+ tar czpf "artifacts/flipper-z-any-resources-${SUFFIX}.tgz" -C assets resources
+
+ - name: 'Bundle core2 firmware'
+ run: |
+ cp build/core2_firmware.tgz "artifacts/flipper-z-any-core2_firmware-${SUFFIX}.tgz"
+
+ - name: 'Updater artifact'
+ uses: actions/upload-artifact@v3
+ with:
+ name: updater
+ path: |
+ artifacts/f7-*
+
+ - name: 'Firmware artifact'
+ uses: actions/upload-artifact@v3
+ with:
+ name: firmware
+ path: |
+ artifacts
+
+ - name: 'Find Previous Comment'
+ if: ${{ github.event.pull_request }}
+ uses: peter-evans/find-comment@v1
+ id: fc
+ with:
+ issue-number: ${{ github.event.pull_request.number }}
+ comment-author: 'github-actions[bot]'
+ body-includes: 'Compiled firmware for commit'
+
+ - name: Artifact info
+ id: artifact-info
+ uses: dawidd6/action-download-artifact@v2
+ with:
+ dry_run: true
+
+ - name: 'Create or update comment'
+ if: ${{ github.event.pull_request}}
+ uses: peter-evans/create-or-update-comment@v1
+ with:
+ comment-id: ${{ steps.fc.outputs.comment-id }}
+ issue-number: ${{ github.event.pull_request.number }}
+ body: |
+ **Compiled firmware for commit `${{steps.names.outputs.commit_sha}}`:**
+ - [📦 Update package](${{steps.artifact-info.outputs.artifacts[0].archive_download_url}})
+ edit-mode: replace
+
+ compact:
+ if: ${{ !startsWith(github.ref, 'refs/tags') }}
+ runs-on: ubuntu-latest
+ steps:
+ - name: 'Decontaminate previous build leftovers'
+ run: |
+ if [ -d .git ]
+ then
+ git submodule status \
+ || git checkout "$(git rev-list --max-parents=0 HEAD | tail -n 1)"
+ fi
+
+ - name: 'Checkout code'
+ uses: actions/checkout@v3
+ with:
+ fetch-depth: 0
+ submodules: true
+ ref: ${{ github.event.pull_request.head.sha }}
+
+ - name: 'Get commit details'
+ run: |
+ if [[ ${{ github.event_name }} == 'pull_request' ]]; then
+ TYPE="pull"
+ elif [[ "${{ github.ref }}" == "refs/tags/"* ]]; then
+ TYPE="tag"
+ else
+ TYPE="other"
+ fi
+ python3 scripts/get_env.py "--event_file=${{ github.event_path }}" "--type=$TYPE"
+
+ - name: 'Build the firmware'
+ run: |
+ set -e
+ for TARGET in ${TARGETS}; do
+ ./fbt TARGET_HW="$(echo "${TARGET}" | sed 's/f//')" \
+ updater_package DEBUG=0 COMPACT=1
+ done
diff --git a/.github/workflows/check_submodules.yml b/.github/workflows/check_submodules.yml
new file mode 100644
index 000000000..d1a1a64c3
--- /dev/null
+++ b/.github/workflows/check_submodules.yml
@@ -0,0 +1,47 @@
+name: 'Check submodules branch'
+
+on:
+ push:
+ branches:
+ - dev
+ - "release*"
+ tags:
+ - '*'
+ pull_request:
+
+jobs:
+ check_protobuf:
+ runs-on: ubuntu-latest
+ steps:
+ - name: 'Decontaminate previous build leftovers'
+ run: |
+ if [ -d .git ]; then
+ git submodule status || git checkout "$(git rev-list --max-parents=0 HEAD | tail -n 1)"
+ fi
+
+ - name: 'Checkout code'
+ uses: actions/checkout@v3
+ with:
+ fetch-depth: 0
+ ref: ${{ github.event.pull_request.head.sha }}
+
+ - name: 'Check protobuf branch'
+ run: |
+ git submodule update --init
+ SUB_PATH="assets/protobuf";
+ SUB_BRANCH="dev";
+ SUB_COMMITS_MIN=40;
+ cd "$SUB_PATH";
+ SUBMODULE_HASH="$(git rev-parse HEAD)";
+ BRANCHES=$(git branch -r --contains "$SUBMODULE_HASH");
+ COMMITS_IN_BRANCH="$(git rev-list --count dev)";
+ if [ $COMMITS_IN_BRANCH -lt $SUB_COMMITS_MIN ]; then
+ echo "name=fails::error" >> $GITHUB_OUTPUT
+ echo "::error::Error: Too low commits in $SUB_BRANCH of submodule $SUB_PATH: $COMMITS_IN_BRANCH(expected $SUB_COMMITS_MIN+)";
+ exit 1;
+ fi
+ if ! grep -q "/$SUB_BRANCH" <<< "$BRANCHES"; then
+ echo "name=fails::error" >> $GITHUB_OUTPUT
+ echo "::error::Error: Submodule $SUB_PATH is not on branch $SUB_BRANCH";
+ exit 1;
+ fi
diff --git a/.github/workflows/lint_c.yml b/.github/workflows/lint_c.yml
new file mode 100644
index 000000000..232e3c689
--- /dev/null
+++ b/.github/workflows/lint_c.yml
@@ -0,0 +1,46 @@
+name: 'Lint C/C++ with clang-format'
+
+on:
+ push:
+ branches:
+ - dev
+ - "release*"
+ tags:
+ - '*'
+ pull_request:
+
+env:
+ TARGETS: f7
+ SET_GH_OUTPUT: 1
+
+jobs:
+ lint_c_cpp:
+ runs-on: ubuntu-latest
+ steps:
+ - name: 'Decontaminate previous build leftovers'
+ run: |
+ if [ -d .git ]; then
+ git submodule status || git checkout "$(git rev-list --max-parents=0 HEAD | tail -n 1)"
+ fi
+
+ - name: 'Checkout code'
+ uses: actions/checkout@v3
+ with:
+ fetch-depth: 0
+ ref: ${{ github.event.pull_request.head.sha }}
+
+ - name: 'Check code formatting'
+ id: syntax_check
+ run: ./fbt lint
+
+ - name: Report code formatting errors
+ if: failure() && steps.syntax_check.outputs.errors && github.event.pull_request
+ uses: peter-evans/create-or-update-comment@v1
+ with:
+ issue-number: ${{ github.event.pull_request.number }}
+ body: |
+ Please fix following code formatting errors:
+ ```
+ ${{ steps.syntax_check.outputs.errors }}
+ ```
+ You might want to run `./fbt format` for an auto-fix.
diff --git a/.github/workflows/lint_python.yml b/.github/workflows/lint_python.yml
new file mode 100644
index 000000000..4b92e0e90
--- /dev/null
+++ b/.github/workflows/lint_python.yml
@@ -0,0 +1,32 @@
+name: 'Python Lint'
+
+on:
+ push:
+ branches:
+ - dev
+ - "release*"
+ tags:
+ - '*'
+ pull_request:
+
+env:
+ SET_GH_OUTPUT: 1
+
+jobs:
+ lint_python:
+ runs-on: ubuntu-latest
+ steps:
+ - name: 'Decontaminate previous build leftovers'
+ run: |
+ if [ -d .git ]; then
+ git submodule status || git checkout "$(git rev-list --max-parents=0 HEAD | tail -n 1)"
+ fi
+
+ - name: 'Checkout code'
+ uses: actions/checkout@v3
+ with:
+ fetch-depth: 0
+ ref: ${{ github.event.pull_request.head.sha }}
+
+ - name: 'Check code formatting'
+ run: ./fbt lint_py
diff --git a/ReadMe.md b/ReadMe.md
index f8c94a7fc..0a0d2adda 100644
--- a/ReadMe.md
+++ b/ReadMe.md
@@ -7,7 +7,7 @@
[Intro](https://github.com/ClaraCrazy/Flipper-Xtreme#What-makes-it-special) | [Animations](https://github.com/ClaraCrazy/Flipper-Xtreme#Animations--Asset-Packs) | [Docs](https://github.com/ClaraCrazy/Flipper-Xtreme/wiki) | [Changelog](https://github.com/ClaraCrazy/Flipper-Xtreme#list-of-changes) | [Known bugs](https://github.com/ClaraCrazy/Flipper-Xtreme#Known-bugs) | [Install](https://github.com/ClaraCrazy/Flipper-Xtreme#Install) | [Build](https://github.com/ClaraCrazy/Flipper-Xtreme#build-it-yourself) | [Discord](https://discord.gg/flipper-xtreme)
-----
-This firmware is a complete overhaul of the [Official Firmware](https://github.com/flipperdevices/flipperzero-firmware), it also features some of the badly implemented ideas from RogueMaster, and lots of awesome code-bits from [Unleashed](https://github.com/DarkFlippers/unleashed-firmware).
+This firmware is a complete overhaul of the [Official Firmware](https://github.com/flipperdevices/flipperzero-firmware), it also features lots of awesome code-bits from [Unleashed](https://github.com/DarkFlippers/unleashed-firmware).
-----
@@ -19,9 +19,11 @@ The goal of this Firmware is to regularly bring out amazing updates based on wha
- The focus of this firmware is functionality & stability: If an App doesnt work, its gone
+- Asset Packs: Are you tired of having to remake your custom animations after every update, switching manifests and having a hard time sharing them, especially once you modify scanning assets too? Those times are over. Scroll down to learn more
+
- Giving the level system a purpose: Right now, each level unlocks a new wallpaper. More on that below
-- Clean upgraded code: RM wrote some updates to certain files. These are... painful, to say the least. Here its all built with perfection in mind and integrated in a mostly clean way. I invite you all to compare the code with theirs.
+- Clean upgraded code: Some people wrote updates to certain files. These are... painful, to say the least. Here its all built with perfection in mind and integrated in a mostly clean way. I invite you all to compare the code with theirs.
- Up2Date: This firmware receives updates from a few repositories, not just from its Upstream. If there are functional, but yet un-merged Pull requests on another flipper firmware that are good, they will be in here!
@@ -37,12 +39,16 @@ You can easily create your own pack, or find some user made ones in the discord
+
+
Once you have some packs, upload them to your Flipper in SD/dolphin_custom (if you did this right you should see SD/dolphin_custom/PackName/Anims and/or SD/dolphin_custom/PackName/Icons).
+
+
After installing the packs to Flipper, hit the Arrow UP button on the main menu and go to Xtreme Settings. Here choose which pack you want and tweak the other settings how you prefer, then press back to reboot and enjoy your new assets & animations!
@@ -179,4 +185,4 @@ This helps us a lot, thanks for the free license for this project!
[PVS-Studio](https://pvs-studio.com/en/pvs-studio/?utm_source=github&utm_medium=organic&utm_campaign=open_source) - static analyzer for C, C++, C#, and Java code.
----
-
"What we do for ourselves dies with us. What we do for others and the world remains and is immortal.” ― Albert Pike
+ "What we do for ourselves dies with us. What we do for others and the world remains and is immortal.” ― Albert Pine
diff --git a/applications/debug/battery_test_app/application.fam b/applications/debug/battery_test_app/application.fam
index b388445cc..f97d10279 100644
--- a/applications/debug/battery_test_app/application.fam
+++ b/applications/debug/battery_test_app/application.fam
@@ -11,4 +11,5 @@ App(
stack_size=1 * 1024,
order=130,
fap_category="Debug",
+ fap_libs=["assets"],
)
diff --git a/applications/debug/battery_test_app/views/battery_info.c b/applications/debug/battery_test_app/views/battery_info.c
new file mode 100644
index 000000000..5353a2e2a
--- /dev/null
+++ b/applications/debug/battery_test_app/views/battery_info.c
@@ -0,0 +1,148 @@
+#include "battery_info.h"
+#include
+#include
+#include
+
+#define LOW_CHARGE_THRESHOLD 10
+#define HIGH_DRAIN_CURRENT_THRESHOLD 100
+
+struct BatteryInfo {
+ View* view;
+};
+
+static void draw_stat(Canvas* canvas, int x, int y, const Icon* icon, char* val) {
+ canvas_draw_frame(canvas, x - 7, y + 7, 30, 13);
+ canvas_draw_icon(canvas, x, y, icon);
+ canvas_set_color(canvas, ColorWhite);
+ canvas_draw_box(canvas, x - 4, y + 16, 24, 6);
+ canvas_set_color(canvas, ColorBlack);
+ canvas_draw_str_aligned(canvas, x + 8, y + 22, AlignCenter, AlignBottom, val);
+};
+
+static void draw_battery(Canvas* canvas, BatteryInfoModel* data, int x, int y) {
+ char emote[20] = {};
+ char header[20] = {};
+ char value[20] = {};
+
+ int32_t drain_current = data->gauge_current * (-1000);
+ uint32_t charge_current = data->gauge_current * 1000;
+
+ // Draw battery
+ canvas_draw_icon(canvas, x, y, &I_BatteryBody_52x28);
+ if(charge_current > 0) {
+ canvas_draw_icon(canvas, x + 16, y + 7, &I_FaceCharging_29x14);
+ } else if(drain_current > HIGH_DRAIN_CURRENT_THRESHOLD) {
+ canvas_draw_icon(canvas, x + 16, y + 7, &I_FaceConfused_29x14);
+ } else if(data->charge < LOW_CHARGE_THRESHOLD) {
+ canvas_draw_icon(canvas, x + 16, y + 7, &I_FaceNopower_29x14);
+ } else {
+ canvas_draw_icon(canvas, x + 16, y + 7, &I_FaceNormal_29x14);
+ }
+
+ // Draw bubble
+ elements_bubble(canvas, 53, 0, 71, 39);
+
+ // Set text
+ if(charge_current > 0) {
+ snprintf(emote, sizeof(emote), "%s", "Yummy!");
+ snprintf(header, sizeof(header), "%s", "Charging at");
+ snprintf(
+ value,
+ sizeof(value),
+ "%lu.%luV %lumA",
+ (uint32_t)(data->vbus_voltage),
+ (uint32_t)(data->vbus_voltage * 10) % 10,
+ charge_current);
+ } else if(drain_current > 0) {
+ snprintf(
+ emote,
+ sizeof(emote),
+ "%s",
+ drain_current > HIGH_DRAIN_CURRENT_THRESHOLD ? "Oh no!" : "Om-nom-nom!");
+ snprintf(header, sizeof(header), "%s", "Consumption is");
+ snprintf(
+ value,
+ sizeof(value),
+ "%ld %s",
+ drain_current,
+ drain_current > HIGH_DRAIN_CURRENT_THRESHOLD ? "mA!" : "mA");
+ } else if(drain_current != 0) {
+ snprintf(header, 20, "...");
+ } else if(data->charging_voltage < 4.2) {
+ // Non-default battery charging limit, mention it
+ snprintf(emote, sizeof(emote), "Charged!");
+ snprintf(header, sizeof(header), "Limited to");
+ snprintf(
+ value,
+ sizeof(value),
+ "%lu.%luV",
+ (uint32_t)(data->charging_voltage),
+ (uint32_t)(data->charging_voltage * 10) % 10);
+ } else {
+ snprintf(header, sizeof(header), "Charged!");
+ }
+
+ canvas_draw_str_aligned(canvas, 92, y + 3, AlignCenter, AlignCenter, emote);
+ canvas_draw_str_aligned(canvas, 92, y + 15, AlignCenter, AlignCenter, header);
+ canvas_draw_str_aligned(canvas, 92, y + 27, AlignCenter, AlignCenter, value);
+};
+
+static void battery_info_draw_callback(Canvas* canvas, void* context) {
+ furi_assert(context);
+ BatteryInfoModel* model = context;
+
+ canvas_clear(canvas);
+ canvas_set_color(canvas, ColorBlack);
+ draw_battery(canvas, model, 0, 5);
+
+ char batt_level[10];
+ char temperature[10];
+ char voltage[10];
+ char health[10];
+
+ snprintf(batt_level, sizeof(batt_level), "%lu%%", (uint32_t)model->charge);
+ snprintf(temperature, sizeof(temperature), "%lu C", (uint32_t)model->gauge_temperature);
+ snprintf(
+ voltage,
+ sizeof(voltage),
+ "%lu.%01lu V",
+ (uint32_t)model->gauge_voltage,
+ (uint32_t)(model->gauge_voltage * 10) % 10UL);
+ snprintf(health, sizeof(health), "%d%%", model->health);
+
+ draw_stat(canvas, 8, 42, &I_Battery_16x16, batt_level);
+ draw_stat(canvas, 40, 42, &I_Temperature_16x16, temperature);
+ draw_stat(canvas, 72, 42, &I_Voltage_16x16, voltage);
+ draw_stat(canvas, 104, 42, &I_Health_16x16, health);
+}
+
+BatteryInfo* battery_info_alloc() {
+ BatteryInfo* battery_info = malloc(sizeof(BatteryInfo));
+ battery_info->view = view_alloc();
+ view_set_context(battery_info->view, battery_info);
+ view_allocate_model(battery_info->view, ViewModelTypeLocking, sizeof(BatteryInfoModel));
+ view_set_draw_callback(battery_info->view, battery_info_draw_callback);
+
+ return battery_info;
+}
+
+void battery_info_free(BatteryInfo* battery_info) {
+ furi_assert(battery_info);
+ view_free(battery_info->view);
+ free(battery_info);
+}
+
+View* battery_info_get_view(BatteryInfo* battery_info) {
+ furi_assert(battery_info);
+ return battery_info->view;
+}
+
+void battery_info_set_data(BatteryInfo* battery_info, BatteryInfoModel* data) {
+ furi_assert(battery_info);
+ furi_assert(data);
+ with_view_model(
+ battery_info->view,
+ BatteryInfoModel * model,
+ { memcpy(model, data, sizeof(BatteryInfoModel)); },
+ true);
+}
diff --git a/applications/debug/battery_test_app/views/battery_info.h b/applications/debug/battery_test_app/views/battery_info.h
new file mode 100644
index 000000000..7bfacf69e
--- /dev/null
+++ b/applications/debug/battery_test_app/views/battery_info.h
@@ -0,0 +1,23 @@
+#pragma once
+
+#include
+
+typedef struct BatteryInfo BatteryInfo;
+
+typedef struct {
+ float vbus_voltage;
+ float gauge_voltage;
+ float gauge_current;
+ float gauge_temperature;
+ float charging_voltage;
+ uint8_t charge;
+ uint8_t health;
+} BatteryInfoModel;
+
+BatteryInfo* battery_info_alloc();
+
+void battery_info_free(BatteryInfo* battery_info);
+
+View* battery_info_get_view(BatteryInfo* battery_info);
+
+void battery_info_set_data(BatteryInfo* battery_info, BatteryInfoModel* data);
diff --git a/applications/debug/bt_debug_app/bt_debug_app.c b/applications/debug/bt_debug_app/bt_debug_app.c
index 405051a4a..bf13f6570 100644
--- a/applications/debug/bt_debug_app/bt_debug_app.c
+++ b/applications/debug/bt_debug_app/bt_debug_app.c
@@ -31,9 +31,6 @@ uint32_t bt_debug_start_view(void* context) {
BtDebugApp* bt_debug_app_alloc() {
BtDebugApp* app = malloc(sizeof(BtDebugApp));
- // Load settings
- bt_settings_load(&app->settings);
-
// Gui
app->gui = furi_record_open(RECORD_GUI);
@@ -105,13 +102,15 @@ int32_t bt_debug_app(void* p) {
}
BtDebugApp* app = bt_debug_app_alloc();
+ // Was bt active?
+ const bool was_active = furi_hal_bt_is_active();
// Stop advertising
furi_hal_bt_stop_advertising();
view_dispatcher_run(app->view_dispatcher);
// Restart advertising
- if(app->settings.enabled) {
+ if(was_active) {
furi_hal_bt_start_advertising();
}
bt_debug_app_free(app);
diff --git a/applications/debug/bt_debug_app/bt_debug_app.h b/applications/debug/bt_debug_app/bt_debug_app.h
index cd59e4d00..0ad94d7dd 100644
--- a/applications/debug/bt_debug_app/bt_debug_app.h
+++ b/applications/debug/bt_debug_app/bt_debug_app.h
@@ -4,15 +4,14 @@
#include
#include
#include
+#include
+
#include
-#include
#include "views/bt_carrier_test.h"
#include "views/bt_packet_test.h"
-#include
typedef struct {
- BtSettings settings;
Gui* gui;
ViewDispatcher* view_dispatcher;
Submenu* submenu;
diff --git a/applications/debug/display_test/application.fam b/applications/debug/display_test/application.fam
index 4b40322fb..e8a00d2ae 100644
--- a/applications/debug/display_test/application.fam
+++ b/applications/debug/display_test/application.fam
@@ -5,6 +5,7 @@ App(
entry_point="display_test_app",
cdefines=["APP_DISPLAY_TEST"],
requires=["gui"],
+ fap_libs=["misc"],
stack_size=1 * 1024,
order=120,
fap_category="Debug",
diff --git a/applications/debug/display_test/display_test.c b/applications/debug/display_test/display_test.c
index 5b46d2b41..8065a23a1 100644
--- a/applications/debug/display_test/display_test.c
+++ b/applications/debug/display_test/display_test.c
@@ -91,7 +91,6 @@ static void display_test_reload_config(DisplayTest* instance) {
instance->config_contrast,
instance->config_regulation_ratio,
instance->config_bias);
- gui_update(instance->gui);
}
static void display_config_set_bias(VariableItem* item) {
diff --git a/applications/debug/rpc_debug_app/scenes/rpc_debug_app_scene_input_error_code.c b/applications/debug/rpc_debug_app/scenes/rpc_debug_app_scene_input_error_code.c
index eae12e6ee..367ca7a4f 100644
--- a/applications/debug/rpc_debug_app/scenes/rpc_debug_app_scene_input_error_code.c
+++ b/applications/debug/rpc_debug_app/scenes/rpc_debug_app_scene_input_error_code.c
@@ -44,7 +44,11 @@ bool rpc_debug_app_scene_input_error_code_on_event(void* context, SceneManagerEv
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == RpcDebugAppCustomEventInputErrorCode) {
- rpc_system_app_set_error_code(app->rpc, (uint32_t)atol(app->text_store));
+ char* end;
+ int error_code = strtol(app->text_store, &end, 10);
+ if(!*end) {
+ rpc_system_app_set_error_code(app->rpc, error_code);
+ }
scene_manager_previous_scene(app->scene_manager);
consumed = true;
}
diff --git a/applications/debug/unit_tests/nfc/nfc_test.c b/applications/debug/unit_tests/nfc/nfc_test.c
index e9e7b35f6..d613be2b9 100644
--- a/applications/debug/unit_tests/nfc/nfc_test.c
+++ b/applications/debug/unit_tests/nfc/nfc_test.c
@@ -466,6 +466,10 @@ static void mf_classic_generator_test(uint8_t uid_len, MfClassicType type) {
nfc_device_free(nfc_keys);
}
+MU_TEST(mf_mini_file_test) {
+ mf_classic_generator_test(4, MfClassicTypeMini);
+}
+
MU_TEST(mf_classic_1k_4b_file_test) {
mf_classic_generator_test(4, MfClassicType1k);
}
@@ -486,6 +490,7 @@ MU_TEST_SUITE(nfc) {
nfc_test_alloc();
MU_RUN_TEST(nfca_file_test);
+ MU_RUN_TEST(mf_mini_file_test);
MU_RUN_TEST(mf_classic_1k_4b_file_test);
MU_RUN_TEST(mf_classic_4k_4b_file_test);
MU_RUN_TEST(mf_classic_1k_7b_file_test);
diff --git a/applications/services/bt/bt_settings.h b/applications/services/bt/bt_settings.h
index 260d9c0e0..9ed8be89c 100644
--- a/applications/services/bt/bt_settings.h
+++ b/applications/services/bt/bt_settings.h
@@ -5,6 +5,10 @@
#include
#include
+#ifdef __cplusplus
+extern "C" {
+#endif
+
typedef struct {
bool enabled;
} BtSettings;
@@ -12,3 +16,7 @@ typedef struct {
bool bt_settings_load(BtSettings* bt_settings);
bool bt_settings_save(BtSettings* bt_settings);
+
+#ifdef __cplusplus
+}
+#endif
\ No newline at end of file
diff --git a/assets/resources/nfc/assets/mf_classic_dict.nfc b/assets/resources/nfc/assets/mf_classic_dict.nfc
index ecb2c54dd..d62d0655b 100644
--- a/assets/resources/nfc/assets/mf_classic_dict.nfc
+++ b/assets/resources/nfc/assets/mf_classic_dict.nfc
@@ -1,31 +1,41 @@
###########################
# Do not edit, this file will be overwritten after firmware update
# Use the user_dict file for user keys
-# Last update 19th October, 2022
+# Last updated 25 January 2023
# -------------------------
+
# MIFARE DEFAULT KEYS
# -- ICEMAN FORK VERSION --
# -- CONTRIBUTE TO THIS LIST, SHARING IS CARING --
# https://github.com/RfidResearchGroup/proxmark3/blob/master/client/dictionaries/mfc_default_keys.dic
+
# DEFAULTKEY(FIRSTKEYUSEDBYPROGRAMIFNOUSERDEFINEDKEY)
FFFFFFFFFFFF
+
# BLANKKEY
000000000000
+
# NFC FORUM MADKEY
# MAD ACCESS KEY A (REVERSED)
A5A4A3A2A1A0
+
# MAD ACCESS KEY B
89ECA97F8C2A
+
# KEY A WIEN
# KEY B WIEN
+
# ICOPY-X
E00000000000
E7D6064C5860
B27CCAB30DBD
+
# LIB / NAT BIEB
D2ECE8B9395E
+
# NSCP DEFAULT KEY
1494E81663D7
+
# KIEV KEYS
569369C5A0E5
632193BE1C3C
@@ -34,40 +44,52 @@ D2ECE8B9395E
9DE89E070277
EFF603E1EFE9
F14EE7CAE863
+
# KIEV / OV-CHIPKAART
B5FF67CBA951
+
# RKF
# VÄSTTRAFIKEN KEYA, RKF ÖSTGÖTATRAFIKEN KEYA
FC00018778F7
0297927C0F77
54726176656C
+
# VÄSTTRAFIKEN KEYB
00000FFE2488
776974687573
EE0042F88840
+
# RKF SLKEYA
26940B21FF5D
A64598A77478
+
# RKF SLKEYB
5C598C9C58B5
E4D2770A89BE
+
# RKF REJSKORTDANMARK KEYA
722BFCC5375F
F1D83F964314
+
# RKF JOJOPRIVAKEYA
505249564141
+
# RKF JOJOPRIVAKEYB
505249564142
+
# RKF JOJOGROUPKEYA
47524F555041
+
# RKF JOJOGROUPKEYB
47524F555042
434F4D4D4F41
434F4D4D4F42
4B0B20107CCB
+
# TNP3XXX
# ACCESS CONTROL SYSTEM
605F5E5D5C5B
+
# MORE KEYS FROM MFC_DEFAULT_KEYS.LUA
000000000001
000000000002
@@ -82,8 +104,10 @@ F1D83F964314
200000000000
222222222222
27DD91F1FCF1
+
# DIRECTORYANDEVENTLOGKEYB
2BA9621E0A36
+
# DIRECTORYANDEVENTLOGKEYA
4AF9D7ADEBE4
333333333333
@@ -104,6 +128,7 @@ A00000000000
A053A292A4AF
A94133013401
AAAAAAAAAAAA
+
# KEYFROMLADYADA.NET
B00000000000
B127C6F41436
@@ -113,31 +138,41 @@ C934FE34D934
CCCCCCCCCCCC
DDDDDDDDDDDD
EEEEEEEEEEEE
+
# ELEVATOR
# DATA FROM FORUM
FFFFFF545846
F1A97341A9FC
+
# HOTEL SYSTEM
44AB09010845
85FED980EA5A
+
# ARD (FR) KEY A
43454952534E
+
# ARD (FR) KEY B
4A2B29111213
4143414F5250
+
# TEHRAN RAILWAY
A9B43414F585
1FB235AC1388
+
# DATA FROM HTTP://IRQ5.IO/2013/04/13/DECODING-BCARD-CONFERENCE-BADGES/
# BCARD KEYB
F4A9EF2AFC6D
+
# DATA FROM ...
# S0 B
89EAC97F8C2A
+
# S4 A
43C7600DEE6B
+
# S6 A
0120BF672A64
+
# S6 B
FB0B20DF1F34
A9F953DEF0A3
@@ -146,6 +181,7 @@ A9F953DEF0A3
21EDF95E7433
C121FF19F681
3D5D9996359A
+
# HERE BE BIP KEYS...
3A42F33AF429
1FC235AC1309
@@ -179,32 +215,41 @@ D49E2826664F
51284C3686A6
3DF14C8000A1
6A470D54127C
+
# DATA FROM HTTP://PASTEBIN.COM/AK9BFTPW
# LÄNSTRAFIKEN I VÄSTERBOTTEN
48FFE71294A0
E3429281EFC1
16F21A82EC84
460722122510
+
# 3DPRINTER
# EPI ENVISIONTE 3DPRINTER
AAFB06045877
+
# GYM
# FYSIKEN A
3E65E4FB65B3
+
# FYSIKEN B
25094DF6F148
+
# CLEVERFIT
A05DBD98E0FC
+
# HOTEL KEYCARD
D3B595E9DD63
AFBECD121004
+
# SIMONSVOSS
6471A5EF2D1A
+
# ID06
4E3552426B32
22BDACF5A33F
6E7747394E63
763958704B78
+
# 24-7
D21762B2DE3B
0E83A374B513
@@ -218,8 +263,10 @@ F101622750B7
710732200D34
7C335FB121B5
B39AE17435DC
+
# KEY A
454841585443
+
# DATA FROM HTTP://PASTEBIN.COM/GQ6NK38G
D39BB83F5297
85675B200017
@@ -245,9 +292,11 @@ FEE470A4CB58
75EDE6A84460
DF27A8F1CB8E
B0C9DD55DD4D
+
# DATA FROM HTTP://BIT.LY/1BDSBJL
A0B0C0D0E0F0
A1B1C1D1E1F1
+
# DATA FROM MSK SOCIAL
A229E68AD9E5
49C2B5296EF4
@@ -274,6 +323,7 @@ C7C0ADB3284F
D8A274B2E026
B20B83CB145C
9AFA6CB4FC3D
+
# DATA FROM HTTP://PASTEBIN.COM/RRJUEDCM
0D258FE90296
E55A3CA71826
@@ -287,16 +337,19 @@ EEB420209D0C
1ACC3189578C
C2B7EC7D4EB1
369A4663ACD2
+
# DATA FROM HTTPS://GITHUB.COM/ZHANGJINGYE03/ZXCARDUMPER
# ZXCARD KEY A/B
668770666644
003003003003
+
# DATA FROM HTTP://PHREAKERCLUB.COM/FORUM/SHOWTHREAD.PHP?P=41266
26973EA74321
71F3A315AD26
51044EFB5AAB
AC70CA327A04
EB0A8FF88ADE
+
# TRANSPORT SYSTEM METROMONEY
2803BCB0C7E1
9C616585E26D
@@ -305,6 +358,7 @@ EB0A8FF88ADE
A160FCD5EC4C
112233445566
361A62F35BC9
+
# TRANSPORT SYSTEM SPAIN
83F3CB98C258
070D486BC555
@@ -338,14 +392,18 @@ C52876869800
5145C34DBA19
25352912CD8D
81B20C274C3F
+
# DATA FROM MALL
# PLAYLAND BALIKESIR
ABBA1234FCB0
+
# A TRIO BOWLING BAHCELIEVLER
314F495254FF
4152414B4E41
+
# KARINCA PARK NIGDE
4E474434FFFF
+
# DATA FROM HTTPS://GITHUB.COM/RADIOWAR/NFCGUI
44DD5A385AAF
21A600056CB0
@@ -383,10 +441,12 @@ CBA6AE869AD5
A7ABBC77CC9E
F792C4C76A5C
BFB6796A11DB
+
# DATA FROM SALTO A/B
6A1987C40A21
7F33625BC129
2338B4913111
+
# DATA FROM STOYE
CB779C50E1BD
A27D3804C259
@@ -414,16 +474,22 @@ D9A37831DCE5
C5CFE06D9EA3
C0DECE673829
A56C2DF9A26D
+
# DATA FROM HTTPS://PASTEBIN.COM/VBWAST74
68D3F7307C89
+
# SMART RIDER. WESTERN AUSTRALIAN PUBLIC TRANSPORT CARDS
568C9083F71C
+
# BANGKOK METRO KEY
97F5DA640B18
+
# METRO VALENCIA KEY
A8844B0BCA06
+
# HTC EINDHOVEN KEY
857464D3AAD1
+
# VIGIK KEYS
# VARIOUS SOURCES :
# * HTTPS://GITHUB.COM/DUMPDOS/VIGIK
@@ -432,18 +498,24 @@ A8844B0BCA06
# FRENCH VIGIK
# VIGIK1 A
314B49474956
+
# VIGIK1 B
564C505F4D41
BA5B895DA162
+
# VIGIK MYSTERY KEYS MIFARE 1K EV1 (S50)
# 16 A
5C8FF9990DA2
+
# 17 A
75CCB59C9BED
+
# 16 B
D01AFEEB890A
+
# 17 B
4B791BEA7BCC
+
# BTCINO UNDETERMINED SPREAKD 0X01->0X13 KEY
021209197591
2EF720F2AF76
@@ -452,6 +524,7 @@ D01AFEEB890A
4A6352684677
BF1F4424AF76
536653644C65
+
# INTRATONE COGELEC
# DATA FROM HTTP://BOUZDECK.COM/RFID/32-CLONING-A-MIFARE-CLASSIC-1K-TAG.HTML
484558414354
@@ -470,6 +543,7 @@ E64A986A5D94
66D2B7DC39EF
6BC1E1AE547D
22729A9BD40F
+
# DATA FROM HTTPS://DFIR.LU/BLOG/CLONING-A-MIFARE-CLASSIC-1K-TAG.HTML
925B158F796F
FAD63ECB5891
@@ -485,8 +559,10 @@ CC6B3B3CD263
703140FD6D86
157C9A513FA5
E2A5DC8E066F
+
# DATA FROM FORUM, SCHLAGE 9691T FOB
EF1232AB18A0
+
# DATA FROM A OYSTER CARD
374BF468607F
BFC8E353AF63
@@ -517,8 +593,10 @@ A2ABB693CE34
91F93A5564C9
E10623E7A016
B725F9CBF183
+
# DATA FROM FDI TAG
8829DA9DAF76
+
# DATA FROM GITHUB ISSUE
0A7932DC7E65
11428B5BCE06
@@ -543,14 +621,18 @@ D4FE03CE5B09
D4FE03CE5B0A
D4FE03CE5B0F
E241E8AFCBAF
+
# DATA FROM FORUM POST
123F8888F322
050908080008
+
# DATA FROM HOIST
4F9F59C9C875
+
# DATA FROM PASTEBIN
66F3ED00FED7
F7A39753D018
+
# DATA FROM HTTPS://PASTEBIN.COM/Z7PEEZIF
386B4D634A65
666E564F4A44
@@ -582,19 +664,23 @@ F7A39753D018
6F506F493353
31646241686C
77646B633657
+
# DATA FROM TRANSPERT
2031D1E57A3B
53C11F90822A
9189449EA24E
+
# DATA FROM GITHUB
410B9B40B872
2CB1A90071C8
+
# DATA FROM
8697389ACA26
1AB23CD45EF6
013889343891
0000000018DE
16DDCB6B3F24
+
# DATA FROM HTTPS://PASTEBIN.COM/VWDRZW7D
# VINGCARD MIFARE 4K STAFF CARD
EC0A9B1A9E06
@@ -608,6 +694,7 @@ B66AC040203A
2E641D99AD5B
AD4FB33388BF
69FB7B7CD8EE
+
# HOTEL
2A6D9205E7CA
2A2C13CC242A
@@ -615,25 +702,34 @@ AD4FB33388BF
01FA3FC68349
6D44B5AAF464
1717E34A7A8A
+
# RFIDEAS
6B6579737472
+
# HID MIFARE CLASSIC 1K KEY
484944204953
204752454154
+
# HID MIFARE SO
3B7E4FD575AD
11496F97752A
+
# LUXEO/AZTEK CASHLESS VENDING
415A54454B4D
+
# BQT
321958042333
+
# APERIO KEY_A SECTOR 1, 12, 13, 14, 15 DATA START 0 LENGTH 48
160A91D29A9C
+
# GALLAGHER
B7BF0C13066E
+
# PIK COMFORT MOSCOW KEYS (ISBC MIFARE PLUS SE 1K)
009FB42D98ED
002E626E2820
+
# BOSTON, MA, USA TRANSIT - MBTA CHARLIE CARD
# CHARLIE
3060206F5B0A
@@ -670,8 +766,10 @@ D80511FC2AB4
BB467463ACD6
E67C8010502D
FF58BA1B4478
+
# DATA FROM HTTPS://PASTEBIN.COM/KZ8XP4EV
FBF225DC5D58
+
# DATA HTTPS://PASTEBIN.COM/BEM6BDAE
# VINGCARD.TXT
4708111C8604
@@ -688,16 +786,19 @@ FBF225DC5D58
D9BCDE7FC489
0C03A720F208
6018522FAC02
+
# DATA FROM HTTPS://PASTEBIN.COM/4T2YFMGT
# MIFARE TECHNISCHE UNIVERSITÄT GRAZ TUG
D58660D1ACDE
50A11381502C
C01FC822C6E5
0854BF31111E
+
# MORE KEYS:
8A19D40CF2B5
AE8587108640
135B88A94B8B
+
# RUSSIAN TROIKA CARD
08B386463229
0E8F64340BA4
@@ -753,6 +854,7 @@ EAAC88E5DC99
F8493407799D
6B8BD9860763
D3A297DC2698
+
# KEYS FROM MIFARECLASSICTOOL PROJECT
044CE1872BC3
045CECA15535
@@ -808,22 +910,28 @@ FD8705E721B0
00ADA2CD516D
237A4D0D9119
0ED7846C2BC9
+
# HOTEL ADINA
9EBC3EB37130
+
# MOST LIKELY DIVERSED INDIVIDUAL KEYS.
# DATA FROM HTTPS://GITHUB.COM/KORSEHINDI/PROXMARK3/COMMIT/24FDBFA9A1D5C996AAA5C192BC07E4AB28DB4C5C
491CDC863104
A2F63A485632
98631ED2B229
19F1FFE02563
+
# ARGENTINA
563A22C01FC8
43CA22C13091
25094DF2C1BD
+
# OMNITEC.ES HOTEL TIMECARD / MAINTENANCECARD
AFBECD120454
+
# OMNITEC.ES HOTEL EMERGENCYCARD
842146108088
+
# TAPCARD PUBLIC TRANSPORT LA
EA1B88DF0A76
D1991E71E2C5
@@ -857,6 +965,7 @@ B81846F06EDF
C6A76CB2F3B5
E3AD9E9BA5D4
6C9EC046C1A4
+
# ROC HIGHSCHOOL ACCESSCARD
B021669B44BB
B18CDCDE52B7
@@ -888,6 +997,7 @@ AE43F36C1A9A
BE7C4F6C7A9A
5EC7938F140A
82D58AA49CCB
+
# MELONCARD
323334353637
CEE3632EEFF5
@@ -904,6 +1014,7 @@ A7FB4824ACBF
00F0BD116D70
4CFF128FA3EF
10F3BEBC01DF
+
# TRANSPORTES INSULAR LA PALMA
0172066B2F03
0000085F0000
@@ -937,6 +1048,7 @@ B1A862985913
3B0172066B2F
3F1A87298691
F3F0172066B2
+
# TEHRAN EZPAY
38A88AEC1C43
CBD2568BC7C6
@@ -953,10 +1065,12 @@ D3B1C7EA5C53
604AC8D87C7E
8E7B29460F12
BB3D7B11D224
+
# CHACO
B210CFA436D2
B8B1CFA646A8
A9F95891F0A4
+
# KEYS FROM APK APPLICATION "SCAN BADGE"
4A4C474F524D
444156494442
@@ -976,6 +1090,7 @@ A0004A000036
DFE73BE48AC6
B069D0D03D17
000131B93F28
+
# FROM THE DFW AREA, TX, USA
A506370E7C0F
26396F2042E7
@@ -992,6 +1107,7 @@ EF4C5A7AC6FC
B47058139187
8268046CD154
67CC03B7D577
+
# FROM THE HTL MĂ–DLING, NĂ–, AT
A5524645CD91
D964406E67B4
@@ -1000,32 +1116,40 @@ D964406E67B4
C27D999912EA
66A163BA82B4
4C60F4B15BA8
+
# CAFE + CO, AT
35D850D10A24
4B511F4D28DD
E45230E7A9E8
535F47D35E39
FB6C88B7E279
+
# METRO CARD, AT
223C3427108A
+
# UNKNOWN, AT
23D4CDFF8DA3
E6849FCC324B
12FD3A94DF0E
0B83797A9C64
39AD2963D3D1
+
# HOTEL BERLIN CLASSIC ROOM A KEY
34B16CD59FF8
+
# HOTEL BERLIN CLASSIC ROOM B KEY
BB2C0007D022
+
# COINMATIC LAUNDRY SMART CARD
# DATA FROM: HTTPS://PASTEBIN.COM/XZQILTUF
0734BFB93DAB
85A438F72A8A
+
# DATA FROM FORUM, CHINESE HOTEL
58AC17BF3629
B62307B62307
A2A3CCA2A3CC
+
# GRANADA, ES TRANSPORT CARD
000000270000
0F385FFB6529
@@ -1043,6 +1167,7 @@ B385EFA64290
C9739233861F
F3864FCCA693
FC9839273862
+
# VARIOUS HOTEL KEYS
34D3C568B348
91FF18E63887
@@ -1050,6 +1175,7 @@ FC9839273862
354A787087F1
4A306E62E9B6
B9C874AE63D0
+
# DATA FROM OFFICIAL REPO
F00DFEEDD0D0
0BB31DC123E5
@@ -1067,18 +1193,23 @@ B8937130B6BA
D7744A1A0C44
82908B57EF4F
FE04ECFE5577
+
# COMFORT INN HOTEL
4D57414C5648
4D48414C5648
+
# UNKNOWN HOTEL KEY
6D9B485A4845
+
# BOSCH SOLUTION 6000
# FOUND IN TAGINFO APP
# RATB KEY
C1E51C63B8F5
1DB710648A65
+
# E-GO CARD KEY
18F34C92A56E
+
# LIBRARY CARD MFP - SL1
4A832584637D
CA679D6291B0
@@ -1094,6 +1225,7 @@ AADE86B1F9C1
C67BEB41FFBF
B84D52971107
52B0D3F6116E
+
# DATA FROM HTTPS://PASTEBIN.COM/CLSQQ9XN
CA3A24669D45
4087C6A75A96
@@ -1102,10 +1234,12 @@ D73438698EEA
5F31F6FCD3A0
A0974382C4C5
A82045A10949
+
# DATA FROM HTTPS://PASTEBIN.COM/2IV8H93H
# FUNNIVARIUM
# FORUM ANKARA
2602FFFFFFFF
+
# MACERA ADASI
# ANKARA KENTPARK
# INACTIVE
@@ -1113,16 +1247,20 @@ A82045A10949
DFF293979FA7
4D6F62692E45
4118D7EF0902
+
# PETROL OFISI
# POSITIVE CARD
# ODE-GEC
0406080A0C0E
+
# KONYA ELKART
988ACDECDFB0
120D00FFFFFF
+
# BOWLINGO
# SERDIVAN AVYM
4AE23A562A80
+
# KART54
2AFFD6F88B97
A9F3F289B70C
@@ -1131,18 +1269,23 @@ DB6819558A25
B16B2E573235
42EF7BF572AB
274E6101FC5E
+
# CRAZY PARK
# KIZILAY AVM
00DD300F4F10
+
# KARTSISTEM B
FEE2A3FBC5B6
+
# TORU ENT
# TAURUS AVM
005078565703
+
# VING?
0602721E8F06
FC0B50AF8700
F7BA51A9434E
+
# ESKART
# ESKISEHIR TRANSPORT CARD
E902395C1744
@@ -1151,6 +1294,7 @@ E902395C1744
D8BA1AA9ABA0
76939DDD9E97
3BF391815A8D
+
# MUZEKART
# MUSEUM CARD FOR TURKEY
7C87013A648A
@@ -1182,6 +1326,7 @@ D0DDDF2933EC
240F0BB84681
9E7168064993
2F8A867B06B4
+
# BURSAKART
# BURSA TRANSPORT CARD
755D49191A78
@@ -1191,18 +1336,22 @@ DAC7E0CBA8FD
0860318A3A89
1927A45A83D3
B2FE3B2875A6
+
# PLAYLAND
# MALTEPE PARK
ABCC1276FCB0
AABAFFCC7612
+
# LUNASAN
# KOCAELI FAIR
26107E7006A0
+
# GAMEFACTORY
# OZDILEK
17D071403C20
534F4C415249
534F4C303232
+
# NESPRESSO, SMART CARD
# KEY-GEN ALGO, THESE KEYS ARE FOR ONE CARD
FF9A84635BD2
@@ -1281,15 +1430,20 @@ AE76242931F1
124578ABFEDC
ABFEDC124578
4578ABFEDC12
+
# PREMIER INN HOTEL CHAIN
5E594208EF02
AF9E38D36582
+
# NORWEGIAN BUILDING SITE IDENTICATION CARD. (HMS KORT)
10DF4D1859C8
+
# KEY B
B5244E79B0C8
+
# UKRAINE HOTEL
F5C1C4C5DE34
+
# DATA FROM MIFARE CLASSIC TOOL REPO
# ROTTERDAM UNIVERSITY OF APPLIED SCIENCES CAMPUS CARD
BB7923232725
@@ -1314,6 +1468,7 @@ B5ADEFCA46C4
BF3FE47637EC
B290401B0CAD
AD11006B0601
+
# ARMENIAN METRO
E4410EF8ED2D
6A68A7D83E11
@@ -1323,6 +1478,7 @@ D3F3B958B8A3
2196FAD8115B
7C469FE86855
CE99FBC8BD26
+
# KEYS FROM EUROTHERMES GROUP (SWITZERLAND)
D66D91829013
75B691829013
@@ -1338,9 +1494,11 @@ FED791829013
29A791829013
668091829013
00008627C10A
+
# KEYS FROM NSP MANCHESTER UNIVERSITY UK ACCOMODATION STAFF AND STUDENTS
199404281970
199404281998
+
# EASYCARD
310D51E539CA
2CCDA1358323
@@ -1348,6 +1506,7 @@ FED791829013
562E6EF73DB6
F53E9F4114A9
AD38C17DE7D2
+
# SOME KEYS OF HTTPS://W3BSIT3-DNS.COM AND HTTPS://IKEY.RU
# STRELKA EXTENSION
5C83859F2224
@@ -1358,6 +1517,7 @@ C4D3911AD1B3
CAD7D4A6A996
DA898ACBB854
FEA1295774F9
+
# MOSCOW PUBLIC TOILETS CARD
807119F81418
22C8BCD10AAA
@@ -1367,6 +1527,7 @@ DBF9F79AB7A2
34EDE51B4C22
C8BCD10AAABA
BCD10AAABA42
+
# MOSCOW SOCIAL CARD
2F87F74090D1
E53EAEFE478F
@@ -1409,10 +1570,12 @@ F750C0095199
82DA4B93DB1C
9CF46DB5FD46
93EB64ACF43D
+
# KEYS FROM RFIDRESEARCHGROUP PROXMARK3 PROJECT
# HTTPS://GITHUB.COM/RFIDRESEARCHGROUP/PROXMARK3/BLOB/MASTER/CLIENT/DICTIONARIES/MFC_DEFAULT_KEYS.DIC
13B91C226E56
5A7A52D5E20D
+
# IRON LOGIC
A3A26EF4C6B0
2C3FEAAE99FC
@@ -1431,9 +1594,11 @@ DEC0CEB0CE24
413BED2AE45B
D6261A9A4B3F
CB9D507CE56D
+
# MORE KEYS FROM THE PM3 REPO
# KEYS OF ARMENIAN UNDERGROUND TICKET
A0A1A2A8A4A5
+
# https://github.com/RfidResearchGroup/proxmark3/blob/master/client/dictionaries/mfc_keys_bmp_sorted.dic
002DE0301481
004173272D18
@@ -2435,6 +2600,7 @@ EE17C426D25E
EE487A4C806E
EE5931913A8D
EED56840AEBA
+
# https://github.com/RfidResearchGroup/proxmark3/blob/master/client/dictionaries/mfc_keys_icbmp_sorted.dic
00383D96411D
005307DB7853
@@ -3436,6 +3602,7 @@ EE3029556CEB
EE49610E6121
EEB704D69BCA
EED69A391464
+
# https://github.com/RfidResearchGroup/proxmark3/blob/master/client/dictionaries/mfc_keys_mrzd_sorted.dic
010203040506
013940233313
@@ -3494,6 +3661,7 @@ F83466888612
F89C86B2A961
FFFFAE82366C
FFFFD06F83E3
+
# Unknown origin
2DEB57A3EA8F
32C1BB023F87
@@ -3577,27 +3745,26 @@ D27058C6E2C7
E19504C39461
FA1FBB3F0F1F
FF16014FEFC7
-#
+
# Cracked by UberGuidoZ
# https://github.com/UberGuidoZ
-#
# BadgeMaker Leaked
1A1B1C1D1E1F
1665FE2AE945
158B51947A8E
-E167EC67C7FF
-D537320FF9OE
+EL67EC67C7FF
+D53732OFF9OE
5E56BFA9E2C9
F81CED821B63
C81584EF5EDF
9551F8F9259D
-36E1765CE3E8
+36EL765CE3E8
509052C8E42E
776C9B03BE71
-C608E13ADD50
+C608EL3ADD50
BEE8B345B949
-ED0EC56EEFDD
-9716D5241E28
+EDOEC56EEFDD
+9716D524LE28
05D1FC14DC31
3321FB75A356
F22A78E29880
@@ -3611,9 +3778,9 @@ DB32A6811327
8AA8544A2207
8C5819E780A4
7549E90353A2
-2E52ABE0CE95
+2E52ABEOCE95
E46210ED98AB
-61D030C0D7A8
+61DO30COD7A8
18E20102821E
DA59354DFB88
040047C12B75
@@ -3622,6 +3789,7 @@ D10008074A6F
446176696453
6F6674776172
6520446F7665
+
# Apartment keyfobs in USA from Corvette830
E60F8387F0B9
FFD46FF6C5EE
@@ -3630,6 +3798,7 @@ FFD46FF6C5EE
1C5179C4A8A1
16CA203B811B
11AC8C8F3AF2
+
# The Westin Jakarta Indonesia from D4DB0D
# Peppers Hotel Unknown location from D4DB0D
6E0DD4136B0A
@@ -3644,15 +3813,19 @@ FC5AC7678BE3
F09BB8DD142D
B4B3FFEDBE0A
540E0D2D1D08
+
# Schlage 9691T Keyfob
7579B671051A
4F4553746B41
+
# FOOD REPUBLIC
30C1DC9DD040
A9B9C1D0E3F1
+
# iGuard Simple (and reverse) keys
AAAAAAFFFFFF
FFFFFFAAAAAA
+
# Vigik verified by quantum-x
# https://github.com/RfidResearchGroup/proxmark3/pull/1742#issuecomment-1206113976
A00027000099
@@ -3670,19 +3843,20 @@ A00000043D79
A00000000064
A00025000030
A00003000057
-#
+
# BH USA 2013 conference
012279BAD3E5
+
# Vigik ScanBadge App (fr.badgevigik.scanbadge)
# Website https://badge-vigik.fr/ - By Alex`
0000A2B3C86F
-021200c20307
+021200C20307
021209197507
1E34B127AF9C
303041534956
4143532D494E
41454E521985
-43412d627400
+43412D627400
455249524345
456666456666
45B722C63319
@@ -3701,10 +3875,12 @@ A00003000057
9EB7C8A6D4E3
A22AE12C9013
AFC984A3576E
+
# Spackular A/B
# data from http://www.proxmark.org/forum/viewtopic.php?pid=45100#p45100
7CB033257498
1153AABAFF6C
+
# iGuard Simple and Reverse Keys
D537320FF90E
36E1765CE3E8
@@ -3713,10 +3889,13 @@ ED0EC56EEFDD
9716D5241E28
2E52ABE0CE95
61D030C0D7A8
+
# BadgeMaker Leaked from https://github.com/UberGuidoZ
E167EC67C7FF
+
# Schlage 9691T Keyfob from seasnaill Added by VideoMan.
3111A3A303EB
+
# Transport cards
E954024EE754
0CD464CDC100
@@ -3724,17 +3903,13 @@ BC305FE2DA65
CF0EC6ACF2F9
F7A545095C49
6862FD600F78
-#MISC KEYS
-36El765CE3E8
-9716D524lE28
-C608El3ADD50
-El67EC67C7FF
-# keys for transport cards by novacard.ru
72A0C485D3F7
6A530C91F85B
+
# RENFE MADRID (TRAIN) Extracted with detect reader
701AA491A4A5
12BA20088ED3
+
# MISC KEYS FROM MY OLD ACCESS CARDS
F18D91EE3033
0E726E11CFCC
@@ -3784,3 +3959,80 @@ E10F0E7A8DD5
F833E24C3F1C
FA8CA10C7D59
FE98F38F3EE2
+#
+##########################################
+# added by colonelborkmundus
+# "the more, the marriott" mifare project
+#
+
+# 1k - graduate hotel
+C49DAE1C6049
+209A2B910545
+
+# 1k - westin
+8C29F8320617
+5697519A8F02
+7D0A1C277C05
+2058580A941F
+C40964215509
+D44CFC178460
+
+# 1k - marriott
+7B4DFC6D6525
+23C9FDD9A366
+3119A70628EB
+30AAD6A711EF
+1330824CD356
+43012BD9EB87
+035C70558D7B
+9966588CB9A0
+12AB4C37BB8B
+
+# 1k - AC hotels marriott
+8EA8EC3F2320
+7B56B2B38725
+
+# 1k - the ritz-carlton
+30FB20D0EFEF
+D20289CD9E6E
+66A3B064CC4B
+D18296CD9E6E
+
+# 1k - unknown
+722538817225
+
+# 1k - aria resort & casino
+316B8FAA12EF
+A18D9F4E75AF
+
+# 1k - fairfield inn & suites marriott
+7AEB989A5525
+7B3B589A5525
+215E9DED9DDF
+334E91BE3377
+310308EC52EF
+
+# 1k - residence inn marriott
+F72CD208FDF9
+
+# 1k - sheraton
+42FC522DE987
+
+# 1k - millenium hotels
+132F641C948B
+
+# 1k - moxy hotels
+20C166C00ADB
+9EE3896C4530
+
+# 1k - residence inn marriott
+3122AE5341EB
+
+# 1k - americinn
+8AC04C1A4A25
+
+# 1k - the industrialist
+2158E314C3DF
+
+# 1k - waldorf astoria
+011C6CF459E8
\ No newline at end of file
diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv
index a5ce0b489..40f476dae 100644
--- a/firmware/targets/f7/api_symbols.csv
+++ b/firmware/targets/f7/api_symbols.csv
@@ -1,5 +1,5 @@
entry,status,name,type,params
-Version,v,12.12,,
+Version,+,12.4,,
Header,+,applications/services/bt/bt_service/bt.h,,
Header,+,applications/services/cli/cli.h,,
Header,+,applications/services/cli/cli_vcp.h,,
@@ -2150,7 +2150,7 @@ Function,-,posix_memalign,int,"void**, size_t, size_t"
Function,-,pow,double,"double, double"
Function,-,pow10,double,double
Function,-,pow10f,float,float
-Function,-,power_enable_low_battery_level_notification,void,"Power*, _Bool"
+Function,+,power_enable_low_battery_level_notification,void,"Power*, _Bool"
Function,+,power_get_info,void,"Power*, PowerInfo*"
Function,+,power_get_pubsub,FuriPubSub*,Power*
Function,+,power_get_settings_events_pubsub,FuriPubSub*,Power*
@@ -4422,7 +4422,6 @@ Function,+,validator_is_file_callback,_Bool,"const char*, FuriString*, void*"
Function,+,validator_is_file_free,void,ValidatorIsFile*
Function,+,value_index_bool,uint8_t,"const _Bool, const _Bool[], uint8_t"
Function,+,value_index_float,uint8_t,"const float, const float[], uint8_t"
-Function,+,value_index_int32,uint8_t,"const int32_t, const int32_t[], uint8_t"
Function,+,value_index_uint32,uint8_t,"const uint32_t, const uint32_t[], uint8_t"
Function,+,variable_item_get_context,void*,VariableItem*
Function,+,variable_item_get_current_value_index,uint8_t,VariableItem*
diff --git a/lib/nfc/helpers/reader_analyzer.c b/lib/nfc/helpers/reader_analyzer.c
index 45f1a572f..0063b13e7 100644
--- a/lib/nfc/helpers/reader_analyzer.c
+++ b/lib/nfc/helpers/reader_analyzer.c
@@ -163,6 +163,7 @@ void reader_analyzer_stop(ReaderAnalyzer* instance) {
}
if(instance->pcap) {
nfc_debug_pcap_free(instance->pcap);
+ instance->pcap = NULL;
}
}
diff --git a/lib/nfc/protocols/emv.c b/lib/nfc/protocols/emv.c
index e00d09e70..4c4ac856b 100644
--- a/lib/nfc/protocols/emv.c
+++ b/lib/nfc/protocols/emv.c
@@ -142,21 +142,44 @@ static bool emv_decode_response(uint8_t* buff, uint16_t len, EmvApplication* app
success = true;
FURI_LOG_T(TAG, "found EMV_TAG_AFL %x (len=%d)", tag, tlen);
break;
- case EMV_TAG_CARD_NUM: // Track 2 Equivalent Data. 0xD0 delimits PAN from expiry (YYMM)
+ case EMV_TAG_TRACK_1_EQUIV: {
+ char track_1_equiv[80];
+ memcpy(track_1_equiv, &buff[i], tlen);
+ track_1_equiv[tlen] = '\0';
+ success = true;
+ FURI_LOG_T(TAG, "found EMV_TAG_TRACK_1_EQUIV %x : %s", tag, track_1_equiv);
+ break;
+ }
+ case EMV_TAG_TRACK_2_EQUIV: {
+ // 0xD0 delimits PAN from expiry (YYMM)
for(int x = 1; x < tlen; x++) {
if(buff[i + x + 1] > 0xD0) {
memcpy(app->card_number, &buff[i], x + 1);
app->card_number_len = x + 1;
+ app->exp_year = (buff[i + x + 1] << 4) | (buff[i + x + 2] >> 4);
+ app->exp_month = (buff[i + x + 2] << 4) | (buff[i + x + 3] >> 4);
break;
}
}
+
+ // Convert 4-bit to ASCII representation
+ char track_2_equiv[41];
+ uint8_t track_2_equiv_len = 0;
+ for(int x = 0; x < tlen; x++) {
+ char top = (buff[i + x] >> 4) + '0';
+ char bottom = (buff[i + x] & 0x0F) + '0';
+ track_2_equiv[x * 2] = top;
+ track_2_equiv_len++;
+ if(top == '?') break;
+ track_2_equiv[x * 2 + 1] = bottom;
+ track_2_equiv_len++;
+ if(bottom == '?') break;
+ }
+ track_2_equiv[track_2_equiv_len] = '\0';
success = true;
- FURI_LOG_T(
- TAG,
- "found EMV_TAG_CARD_NUM %x (len=%d)",
- EMV_TAG_CARD_NUM,
- app->card_number_len);
+ FURI_LOG_T(TAG, "found EMV_TAG_TRACK_2_EQUIV %x : %s", tag, track_2_equiv);
break;
+ }
case EMV_TAG_PAN:
memcpy(app->card_number, &buff[i], tlen);
app->card_number_len = tlen;
diff --git a/lib/nfc/protocols/emv.h b/lib/nfc/protocols/emv.h
index 0ccf7c3e0..c5b089fdf 100644
--- a/lib/nfc/protocols/emv.h
+++ b/lib/nfc/protocols/emv.h
@@ -11,7 +11,8 @@
#define EMV_TAG_CARD_NAME 0x50
#define EMV_TAG_FCI 0xBF0C
#define EMV_TAG_LOG_CTRL 0x9F4D
-#define EMV_TAG_CARD_NUM 0x57
+#define EMV_TAG_TRACK_1_EQUIV 0x56
+#define EMV_TAG_TRACK_2_EQUIV 0x57
#define EMV_TAG_PAN 0x5A
#define EMV_TAG_AFL 0x94
#define EMV_TAG_EXP_DATE 0x5F24
diff --git a/lib/nfc/protocols/mifare_classic.c b/lib/nfc/protocols/mifare_classic.c
index 5fda122ab..da74a85f9 100644
--- a/lib/nfc/protocols/mifare_classic.c
+++ b/lib/nfc/protocols/mifare_classic.c
@@ -605,6 +605,14 @@ void mf_classic_read_sector(FuriHalNfcTxRxContext* tx_rx, MfClassicData* data, u
if(mf_classic_read_block(tx_rx, &crypto, i, &block_tmp)) {
mf_classic_set_block_read(data, i, &block_tmp);
blocks_read++;
+ } else if(i > start_block) {
+ // Try to re-auth to read block in case prevous block was protected from read
+ furi_hal_nfc_sleep();
+ if(!mf_classic_auth(tx_rx, i, key, MfClassicKeyA, &crypto, false, 0)) break;
+ if(mf_classic_read_block(tx_rx, &crypto, i, &block_tmp)) {
+ mf_classic_set_block_read(data, i, &block_tmp);
+ blocks_read++;
+ }
}
furi_hal_nfc_sleep();
} else {
@@ -618,12 +626,21 @@ void mf_classic_read_sector(FuriHalNfcTxRxContext* tx_rx, MfClassicData* data, u
if(!key_b_found) break;
FURI_LOG_D(TAG, "Try to read blocks with key B");
key = nfc_util_bytes2num(sec_tr->key_b, sizeof(sec_tr->key_b));
+ if(!mf_classic_auth(tx_rx, start_block, key, MfClassicKeyB, &crypto, false, 0)) break;
for(size_t i = start_block; i < start_block + total_blocks; i++) {
if(!mf_classic_is_block_read(data, i)) {
if(!mf_classic_auth(tx_rx, i, key, MfClassicKeyB, &crypto, false, 0)) continue;
if(mf_classic_read_block(tx_rx, &crypto, i, &block_tmp)) {
mf_classic_set_block_read(data, i, &block_tmp);
blocks_read++;
+ } else if(i > start_block) {
+ // Try to re-auth to read block in case prevous block was protected from read
+ furi_hal_nfc_sleep();
+ if(!mf_classic_auth(tx_rx, i, key, MfClassicKeyB, &crypto, false, 0)) break;
+ if(mf_classic_read_block(tx_rx, &crypto, i, &block_tmp)) {
+ mf_classic_set_block_read(data, i, &block_tmp);
+ blocks_read++;
+ }
}
furi_hal_nfc_sleep();
} else {
@@ -676,6 +693,11 @@ static bool mf_classic_read_sector_with_reader(
// Read blocks
for(uint8_t i = 0; i < sector->total_blocks; i++) {
+ if(mf_classic_read_block(tx_rx, crypto, first_block + i, §or->block[i])) continue;
+ if(i == 0) continue;
+ // Try to auth to read next block in case previous is locked
+ furi_hal_nfc_sleep();
+ if(!mf_classic_auth(tx_rx, first_block + i, key, key_type, crypto, false, 0)) continue;
mf_classic_read_block(tx_rx, crypto, first_block + i, §or->block[i]);
}
// Save sector keys in last block
diff --git a/lib/nfc/protocols/mifare_classic.h b/lib/nfc/protocols/mifare_classic.h
index ac5701ecf..f5b73c98b 100644
--- a/lib/nfc/protocols/mifare_classic.h
+++ b/lib/nfc/protocols/mifare_classic.h
@@ -6,6 +6,7 @@
#define MF_CLASSIC_BLOCK_SIZE (16)
#define MF_CLASSIC_TOTAL_BLOCKS_MAX (256)
+#define MF_MINI_TOTAL_SECTORS_NUM (5)
#define MF_CLASSIC_1K_TOTAL_SECTORS_NUM (16)
#define MF_CLASSIC_4K_TOTAL_SECTORS_NUM (40)
#define MF_MINI_TOTAL_SECTORS_NUM (5)
@@ -22,6 +23,7 @@ typedef enum {
MfClassicTypeMini,
MfClassicType1k,
MfClassicType4k,
+ MfClassicTypeMini,
} MfClassicType;
typedef enum {
diff --git a/lib/toolbox/SConscript b/lib/toolbox/SConscript
index da6c1115c..9234f1e80 100644
--- a/lib/toolbox/SConscript
+++ b/lib/toolbox/SConscript
@@ -21,6 +21,7 @@ env.Append(
File("saved_struct.h"),
File("version.h"),
File("float_tools.h"),
+ File("value_index.h"),
File("tar/tar_archive.h"),
File("stream/stream.h"),
File("stream/file_stream.h"),