mirror of
https://github.com/DarkFlippers/unleashed-firmware.git
synced 2025-12-12 20:49:49 +04:00
Compare commits
171 Commits
readme_upd
...
nfcrefacto
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
18377185c7 | ||
|
|
ef09dcf8f8 | ||
|
|
bee1a6c18a | ||
|
|
b958bfd5c9 | ||
|
|
49dcf81743 | ||
|
|
16ffa2bf75 | ||
|
|
32e2cbe60a | ||
|
|
a7e6eb7fe4 | ||
|
|
33ed5ea1f2 | ||
|
|
c8c191c0a4 | ||
|
|
78af3214c3 | ||
|
|
e244bedd64 | ||
|
|
ebe95a92d1 | ||
|
|
5921eb3d27 | ||
|
|
9ed23799eb | ||
|
|
19f524ec43 | ||
|
|
085c90af40 | ||
|
|
0d94abf856 | ||
|
|
0131eb3aa2 | ||
|
|
bee48f483c | ||
|
|
47cc05dab4 | ||
|
|
aa06328516 | ||
|
|
7bd3bd7ea4 | ||
|
|
bf8984a225 | ||
|
|
bbe68d6ffc | ||
|
|
9af81ce8d0 | ||
|
|
c8180747db | ||
|
|
917410a0a8 | ||
|
|
176fb21f5f | ||
|
|
593b5fc098 | ||
|
|
0fe93fcfa4 | ||
|
|
cfaf745523 | ||
|
|
3d872cf37a | ||
|
|
844e0f10e5 | ||
|
|
92969ecc1f | ||
|
|
3bbb326c9c | ||
|
|
d92b0a82cc | ||
|
|
ac5abdbb1d | ||
|
|
2958e5cef3 | ||
|
|
35c903494c | ||
|
|
1b6295b2bf | ||
|
|
b93a06354f | ||
|
|
2d9090b2de | ||
|
|
e5b079f4ce | ||
|
|
1e5223c6ab | ||
|
|
29a1865ec3 | ||
|
|
8b8174b1b4 | ||
|
|
53245986ab | ||
|
|
b44bc718be | ||
|
|
8e3378b7b9 | ||
|
|
9e90948fc3 | ||
|
|
b87a8ca329 | ||
|
|
e664159188 | ||
|
|
9d6352e92f | ||
|
|
f45a5dff43 | ||
|
|
130fa43ad6 | ||
|
|
76e5a1c087 | ||
|
|
38792f2c93 | ||
|
|
4308a5e377 | ||
|
|
65a56cdb4a | ||
|
|
fbded1e4ee | ||
|
|
4ae9a02efa | ||
|
|
2c3b5ca43d | ||
|
|
b51b8eb843 | ||
|
|
40552e6837 | ||
|
|
9960328d3e | ||
|
|
3ac6aef6cf | ||
|
|
700cee3766 | ||
|
|
c1363a18cc | ||
|
|
016abe3273 | ||
|
|
5bf5826c88 | ||
|
|
62a4c0dd03 | ||
|
|
d47e5ca520 | ||
|
|
699078d5a5 | ||
|
|
8ebfda6b8c | ||
|
|
e7ea821650 | ||
|
|
0c2c74ae21 | ||
|
|
9898a5d0dd | ||
|
|
09f86f24fd | ||
|
|
57aa5e1620 | ||
|
|
ef01355297 | ||
|
|
14c0572368 | ||
|
|
50aaacd30d | ||
|
|
2f44fd6cac | ||
|
|
c924693a84 | ||
|
|
e739aeeb10 | ||
|
|
5031540a8f | ||
|
|
fc1ec55a40 | ||
|
|
a6bb9698ef | ||
|
|
63d7d46bd3 | ||
|
|
e1030e7999 | ||
|
|
8d1a4a5c69 | ||
|
|
cc5607d66f | ||
|
|
8666cdc5ef | ||
|
|
286dbfaf0b | ||
|
|
bf8357ee52 | ||
|
|
b98631c633 | ||
|
|
1891d54baf | ||
|
|
b80dfbe0c5 | ||
|
|
a73a83f04d | ||
|
|
3fbb9f24f8 | ||
|
|
a089aeb2bd | ||
|
|
182c8defb1 | ||
|
|
f46018b204 | ||
|
|
f7f9250e55 | ||
|
|
70b8823eb8 | ||
|
|
8f5ea2be83 | ||
|
|
abe0e34ace | ||
|
|
1f485be6e8 | ||
|
|
4368ff4294 | ||
|
|
338fc3afea | ||
|
|
fdc39f8473 | ||
|
|
931f4464c2 | ||
|
|
5901720681 | ||
|
|
e68ee9b47c | ||
|
|
ee24e4eb48 | ||
|
|
25af13e998 | ||
|
|
ac892f3d03 | ||
|
|
4d3a3070e4 | ||
|
|
6a2adf69e6 | ||
|
|
19ca956e7c | ||
|
|
1530c2b4f1 | ||
|
|
f0f2a6c11f | ||
|
|
8bfa9898e3 | ||
|
|
953a747b1a | ||
|
|
8835ef3598 | ||
|
|
cbc5d61ab7 | ||
|
|
e8210cd94d | ||
|
|
b6ff400587 | ||
|
|
91813831c6 | ||
|
|
c657eb8a40 | ||
|
|
091210c003 | ||
|
|
d4cad7b8c6 | ||
|
|
5949d7be1c | ||
|
|
ac3bd337a1 | ||
|
|
f09d364e95 | ||
|
|
7f474ed9c6 | ||
|
|
04c914d945 | ||
|
|
93ae4db35a | ||
|
|
2db719f35c | ||
|
|
e36b87ddd9 | ||
|
|
1c360ae110 | ||
|
|
44140caa2d | ||
|
|
15894235a9 | ||
|
|
fae8d91880 | ||
|
|
78446bab07 | ||
|
|
84e94e728c | ||
|
|
b2042fd044 | ||
|
|
67a681f8b8 | ||
|
|
eb2607f308 | ||
|
|
9f6fc6fe79 | ||
|
|
77d6c41914 | ||
|
|
4705812d24 | ||
|
|
1c0276a0be | ||
|
|
abc4110198 | ||
|
|
99ba1b6a24 | ||
|
|
1fec80a533 | ||
|
|
53fffffd1b | ||
|
|
dfd5233760 | ||
|
|
7b4d66f0f4 | ||
|
|
c3d2a1f243 | ||
|
|
3491844d41 | ||
|
|
9ef1a4dfaa | ||
|
|
f53246d40b | ||
|
|
d1f1635dd2 | ||
|
|
e7c52828ea | ||
|
|
fea15bedd4 | ||
|
|
5bbee02704 | ||
|
|
8c44dfb6af | ||
|
|
540862fbf2 | ||
|
|
500ca0758a |
@@ -168,3 +168,10 @@ Max butthurt: 13
|
|||||||
Min level: 1
|
Min level: 1
|
||||||
Max level: 3
|
Max level: 3
|
||||||
Weight: 4
|
Weight: 4
|
||||||
|
|
||||||
|
Name: L2_Coding_in_the_shell_128x64
|
||||||
|
Min butthurt: 0
|
||||||
|
Max butthurt: 12
|
||||||
|
Min level: 2
|
||||||
|
Max level: 3
|
||||||
|
Weight: 4
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
diff --git a/applications/services/notification/notification_app.c b/applications/services/notification/notification_app.c
|
diff --git a/applications/services/notification/notification_app.c b/applications/services/notification/notification_app.c
|
||||||
index 2f947fe..03c4c76 100644
|
index 5769ced..c5d3088 100644
|
||||||
--- a/applications/services/notification/notification_app.c
|
--- a/applications/services/notification/notification_app.c
|
||||||
+++ b/applications/services/notification/notification_app.c
|
+++ b/applications/services/notification/notification_app.c
|
||||||
@@ -9,6 +9,7 @@
|
@@ -9,6 +9,7 @@
|
||||||
@@ -10,7 +10,7 @@ index 2f947fe..03c4c76 100644
|
|||||||
|
|
||||||
#define TAG "NotificationSrv"
|
#define TAG "NotificationSrv"
|
||||||
|
|
||||||
@@ -579,6 +580,7 @@ int32_t notification_srv(void* p) {
|
@@ -589,6 +590,7 @@ int32_t notification_srv(void* p) {
|
||||||
break;
|
break;
|
||||||
case SaveSettingsMessage:
|
case SaveSettingsMessage:
|
||||||
notification_save_settings(app);
|
notification_save_settings(app);
|
||||||
@@ -19,7 +19,7 @@ index 2f947fe..03c4c76 100644
|
|||||||
}
|
}
|
||||||
|
|
||||||
diff --git a/applications/settings/notification_settings/notification_settings_app.c b/applications/settings/notification_settings/notification_settings_app.c
|
diff --git a/applications/settings/notification_settings/notification_settings_app.c b/applications/settings/notification_settings/notification_settings_app.c
|
||||||
index 565d4f1..bae9299 100644
|
index 1955012..19d953d 100644
|
||||||
--- a/applications/settings/notification_settings/notification_settings_app.c
|
--- a/applications/settings/notification_settings/notification_settings_app.c
|
||||||
+++ b/applications/settings/notification_settings/notification_settings_app.c
|
+++ b/applications/settings/notification_settings/notification_settings_app.c
|
||||||
@@ -3,6 +3,7 @@
|
@@ -3,6 +3,7 @@
|
||||||
@@ -30,10 +30,20 @@ index 565d4f1..bae9299 100644
|
|||||||
|
|
||||||
#define MAX_NOTIFICATION_SETTINGS 4
|
#define MAX_NOTIFICATION_SETTINGS 4
|
||||||
|
|
||||||
@@ -162,6 +163,14 @@ static void vibro_changed(VariableItem* item) {
|
@@ -20,6 +21,8 @@ static const NotificationSequence sequence_note_c = {
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
+static VariableItem* temp_item;
|
||||||
|
+
|
||||||
|
#define CONTRAST_COUNT 11
|
||||||
|
const char* const contrast_text[CONTRAST_COUNT] = {
|
||||||
|
"-5",
|
||||||
|
@@ -156,6 +159,59 @@ static void vibro_changed(VariableItem* item) {
|
||||||
notification_message(app->notification, &sequence_single_vibro);
|
notification_message(app->notification, &sequence_single_vibro);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
+// Set RGB backlight color
|
||||||
+static void color_changed(VariableItem* item) {
|
+static void color_changed(VariableItem* item) {
|
||||||
+ NotificationAppSettings* app = variable_item_get_context(item);
|
+ NotificationAppSettings* app = variable_item_get_context(item);
|
||||||
+ uint8_t index = variable_item_get_current_value_index(item);
|
+ uint8_t index = variable_item_get_current_value_index(item);
|
||||||
@@ -41,31 +51,102 @@ index 565d4f1..bae9299 100644
|
|||||||
+ variable_item_set_current_value_text(item, rgb_backlight_get_color_text(index));
|
+ variable_item_set_current_value_text(item, rgb_backlight_get_color_text(index));
|
||||||
+ notification_message(app->notification, &sequence_display_backlight_on);
|
+ notification_message(app->notification, &sequence_display_backlight_on);
|
||||||
+}
|
+}
|
||||||
|
+
|
||||||
|
+// TODO: refactor and fix this
|
||||||
|
+static void color_set_custom_red(VariableItem* item) {
|
||||||
|
+ NotificationAppSettings* app = variable_item_get_context(item);
|
||||||
|
+ uint8_t index = variable_item_get_current_value_index(item);
|
||||||
|
+ rgb_backlight_set_custom_color(index, 0);
|
||||||
|
+ char valtext[4] = {};
|
||||||
|
+ snprintf(valtext, sizeof(valtext), "%d", index);
|
||||||
|
+ variable_item_set_current_value_text(item, valtext);
|
||||||
|
+ rgb_backlight_set_color(13);
|
||||||
|
+ rgb_backlight_update(app->notification->settings.display_brightness * 0xFF, true);
|
||||||
|
+ // Set to custom color explicitly
|
||||||
|
+ variable_item_set_current_value_index(temp_item, 13);
|
||||||
|
+ variable_item_set_current_value_text(temp_item, rgb_backlight_get_color_text(13));
|
||||||
|
+ notification_message(app->notification, &sequence_display_backlight_on);
|
||||||
|
+}
|
||||||
|
+static void color_set_custom_green(VariableItem* item) {
|
||||||
|
+ NotificationAppSettings* app = variable_item_get_context(item);
|
||||||
|
+ uint8_t index = variable_item_get_current_value_index(item);
|
||||||
|
+ rgb_backlight_set_custom_color(index, 1);
|
||||||
|
+ char valtext[4] = {};
|
||||||
|
+ snprintf(valtext, sizeof(valtext), "%d", index);
|
||||||
|
+ variable_item_set_current_value_text(item, valtext);
|
||||||
|
+ rgb_backlight_set_color(13);
|
||||||
|
+ rgb_backlight_update(app->notification->settings.display_brightness * 0xFF, true);
|
||||||
|
+ // Set to custom color explicitly
|
||||||
|
+ variable_item_set_current_value_index(temp_item, 13);
|
||||||
|
+ variable_item_set_current_value_text(temp_item, rgb_backlight_get_color_text(13));
|
||||||
|
+ notification_message(app->notification, &sequence_display_backlight_on);
|
||||||
|
+}
|
||||||
|
+static void color_set_custom_blue(VariableItem* item) {
|
||||||
|
+ NotificationAppSettings* app = variable_item_get_context(item);
|
||||||
|
+ uint8_t index = variable_item_get_current_value_index(item);
|
||||||
|
+ rgb_backlight_set_custom_color(index, 2);
|
||||||
|
+ char valtext[4] = {};
|
||||||
|
+ snprintf(valtext, sizeof(valtext), "%d", index);
|
||||||
|
+ variable_item_set_current_value_text(item, valtext);
|
||||||
|
+ rgb_backlight_set_color(13);
|
||||||
|
+ rgb_backlight_update(app->notification->settings.display_brightness * 0xFF, true);
|
||||||
|
+ // Set to custom color explicitly
|
||||||
|
+ variable_item_set_current_value_index(temp_item, 13);
|
||||||
|
+ variable_item_set_current_value_text(temp_item, rgb_backlight_get_color_text(13));
|
||||||
|
+ notification_message(app->notification, &sequence_display_backlight_on);
|
||||||
|
+}
|
||||||
+
|
+
|
||||||
static uint32_t notification_app_settings_exit(void* context) {
|
static uint32_t notification_app_settings_exit(void* context) {
|
||||||
UNUSED(context);
|
UNUSED(context);
|
||||||
return VIEW_NONE;
|
return VIEW_NONE;
|
||||||
@@ -187,7 +196,13 @@ static NotificationAppSettings* alloc_settings() {
|
@@ -180,8 +236,40 @@ static NotificationAppSettings* alloc_settings() {
|
||||||
|
variable_item_set_current_value_index(item, value_index);
|
||||||
variable_item_set_current_value_text(item, contrast_text[value_index]);
|
variable_item_set_current_value_text(item, contrast_text[value_index]);
|
||||||
|
|
||||||
item = variable_item_list_add(
|
+ // RGB Colors
|
||||||
- app->variable_item_list, "LCD Backlight", BACKLIGHT_COUNT, backlight_changed, app);
|
+ item = variable_item_list_add(
|
||||||
+ app->variable_item_list, "LCD Color", rgb_backlight_get_color_count(), color_changed, app);
|
+ app->variable_item_list, "LCD Color", rgb_backlight_get_color_count(), color_changed, app);
|
||||||
+ value_index = rgb_backlight_get_settings()->display_color_index;
|
+ value_index = rgb_backlight_get_settings()->display_color_index;
|
||||||
+ variable_item_set_current_value_index(item, value_index);
|
+ variable_item_set_current_value_index(item, value_index);
|
||||||
+ variable_item_set_current_value_text(item, rgb_backlight_get_color_text(value_index));
|
+ variable_item_set_current_value_text(item, rgb_backlight_get_color_text(value_index));
|
||||||
|
+ temp_item = item;
|
||||||
|
+
|
||||||
|
+ // Custom Color - REFACTOR THIS
|
||||||
|
+ item = variable_item_list_add(
|
||||||
|
+ app->variable_item_list, "Custom Red", 255, color_set_custom_red, app);
|
||||||
|
+ value_index = rgb_backlight_get_settings()->custom_r;
|
||||||
|
+ variable_item_set_current_value_index(item, value_index);
|
||||||
|
+ char valtext[4] = {};
|
||||||
|
+ snprintf(valtext, sizeof(valtext), "%d", value_index);
|
||||||
|
+ variable_item_set_current_value_text(item, valtext);
|
||||||
+
|
+
|
||||||
+ item = variable_item_list_add(
|
+ item = variable_item_list_add(
|
||||||
|
+ app->variable_item_list, "Custom Green", 255, color_set_custom_green, app);
|
||||||
|
+ value_index = rgb_backlight_get_settings()->custom_g;
|
||||||
|
+ variable_item_set_current_value_index(item, value_index);
|
||||||
|
+ snprintf(valtext, sizeof(valtext), "%d", value_index);
|
||||||
|
+ variable_item_set_current_value_text(item, valtext);
|
||||||
|
+
|
||||||
|
+ item = variable_item_list_add(
|
||||||
|
+ app->variable_item_list, "Custom Blue", 255, color_set_custom_blue, app);
|
||||||
|
+ value_index = rgb_backlight_get_settings()->custom_b;
|
||||||
|
+ variable_item_set_current_value_index(item, value_index);
|
||||||
|
+ snprintf(valtext, sizeof(valtext), "%d", value_index);
|
||||||
|
+ variable_item_set_current_value_text(item, valtext);
|
||||||
|
+ // End of RGB
|
||||||
|
+
|
||||||
|
item = variable_item_list_add(
|
||||||
|
- app->variable_item_list, "LCD Backlight", BACKLIGHT_COUNT, backlight_changed, app);
|
||||||
+ app->variable_item_list, "LCD Brightness", BACKLIGHT_COUNT, backlight_changed, app);
|
+ app->variable_item_list, "LCD Brightness", BACKLIGHT_COUNT, backlight_changed, app);
|
||||||
value_index = value_index_float(
|
value_index = value_index_float(
|
||||||
app->notification->settings.display_brightness, backlight_value, BACKLIGHT_COUNT);
|
app->notification->settings.display_brightness, backlight_value, BACKLIGHT_COUNT);
|
||||||
variable_item_set_current_value_index(item, value_index);
|
variable_item_set_current_value_index(item, value_index);
|
||||||
diff --git a/applications/settings/notification_settings/rgb_backlight.c b/applications/settings/notification_settings/rgb_backlight.c
|
diff --git a/applications/settings/notification_settings/rgb_backlight.c b/applications/settings/notification_settings/rgb_backlight.c
|
||||||
new file mode 100644
|
new file mode 100644
|
||||||
index 0000000..269b544
|
index 0000000..98f0d3a
|
||||||
--- /dev/null
|
--- /dev/null
|
||||||
+++ b/applications/settings/notification_settings/rgb_backlight.c
|
+++ b/applications/settings/notification_settings/rgb_backlight.c
|
||||||
@@ -0,0 +1,171 @@
|
@@ -0,0 +1,217 @@
|
||||||
+/*
|
+/*
|
||||||
+ RGB backlight FlipperZero driver
|
+ RGB backlight FlipperZero driver
|
||||||
+ Copyright (C) 2022-2023 Victor Nikitchuk (https://github.com/quen0n)
|
+ Copyright (C) 2022-2023 Victor Nikitchuk (https://github.com/quen0n)
|
||||||
@@ -88,9 +169,9 @@ index 0000000..269b544
|
|||||||
+#include <furi_hal.h>
|
+#include <furi_hal.h>
|
||||||
+#include <storage/storage.h>
|
+#include <storage/storage.h>
|
||||||
+
|
+
|
||||||
+#define RGB_BACKLIGHT_SETTINGS_VERSION 5
|
+#define RGB_BACKLIGHT_SETTINGS_VERSION 6
|
||||||
+#define RGB_BACKLIGHT_SETTINGS_FILE_NAME ".rgb_backlight.settings"
|
+#define RGB_BACKLIGHT_SETTINGS_FILE_NAME ".rgb_backlight.settings"
|
||||||
+#define RGB_BACKLIGHT_SETTINGS_PATH EXT_PATH(RGB_BACKLIGHT_SETTINGS_FILE_NAME)
|
+#define RGB_BACKLIGHT_SETTINGS_PATH INT_PATH(RGB_BACKLIGHT_SETTINGS_FILE_NAME)
|
||||||
+
|
+
|
||||||
+#define COLOR_COUNT (sizeof(colors) / sizeof(RGBBacklightColor))
|
+#define COLOR_COUNT (sizeof(colors) / sizeof(RGBBacklightColor))
|
||||||
+
|
+
|
||||||
@@ -99,11 +180,14 @@ index 0000000..269b544
|
|||||||
+static RGBBacklightSettings rgb_settings = {
|
+static RGBBacklightSettings rgb_settings = {
|
||||||
+ .version = RGB_BACKLIGHT_SETTINGS_VERSION,
|
+ .version = RGB_BACKLIGHT_SETTINGS_VERSION,
|
||||||
+ .display_color_index = 0,
|
+ .display_color_index = 0,
|
||||||
|
+ .custom_r = 254,
|
||||||
|
+ .custom_g = 254,
|
||||||
|
+ .custom_b = 254,
|
||||||
+ .settings_is_loaded = false};
|
+ .settings_is_loaded = false};
|
||||||
+
|
+
|
||||||
+static const RGBBacklightColor colors[] = {
|
+static const RGBBacklightColor colors[] = {
|
||||||
+ {"Orange", 255, 60, 0},
|
+ {"Orange", 255, 60, 0},
|
||||||
+ {"Yellow", 255, 150, 0},
|
+ {"Yellow", 255, 144, 0},
|
||||||
+ {"Spring", 167, 255, 0},
|
+ {"Spring", 167, 255, 0},
|
||||||
+ {"Lime", 0, 255, 0},
|
+ {"Lime", 0, 255, 0},
|
||||||
+ {"Aqua", 0, 255, 127},
|
+ {"Aqua", 0, 255, 127},
|
||||||
@@ -114,7 +198,8 @@ index 0000000..269b544
|
|||||||
+ {"Magenta", 210, 0, 210},
|
+ {"Magenta", 210, 0, 210},
|
||||||
+ {"Pink", 255, 0, 127},
|
+ {"Pink", 255, 0, 127},
|
||||||
+ {"Red", 255, 0, 0},
|
+ {"Red", 255, 0, 0},
|
||||||
+ {"White", 150, 150, 110},
|
+ {"White", 254, 210, 200},
|
||||||
|
+ {"Custom", 0, 0, 0},
|
||||||
+};
|
+};
|
||||||
+
|
+
|
||||||
+uint8_t rgb_backlight_get_color_count(void) {
|
+uint8_t rgb_backlight_get_color_count(void) {
|
||||||
@@ -126,18 +211,28 @@ index 0000000..269b544
|
|||||||
+}
|
+}
|
||||||
+
|
+
|
||||||
+void rgb_backlight_load_settings(void) {
|
+void rgb_backlight_load_settings(void) {
|
||||||
+ //Не загружать данные из внутренней памяти при загрузке в режиме DFU
|
+ // Do not load settings if we are in other boot modes than normal
|
||||||
+ FuriHalRtcBootMode bm = furi_hal_rtc_get_boot_mode();
|
+ if(furi_hal_rtc_get_boot_mode() != FuriHalRtcBootModeNormal) {
|
||||||
+ if(bm == FuriHalRtcBootModeDfu) {
|
|
||||||
+ rgb_settings.settings_is_loaded = true;
|
+ rgb_settings.settings_is_loaded = true;
|
||||||
+ return;
|
+ return;
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
|
+ // Wait for all required services to start and create their records
|
||||||
|
+ uint8_t timeout = 0;
|
||||||
|
+ while(!furi_record_exists(RECORD_STORAGE)) {
|
||||||
|
+ timeout++;
|
||||||
|
+ if(timeout > 150) {
|
||||||
|
+ rgb_settings.settings_is_loaded = true;
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+ furi_delay_ms(5);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
+ RGBBacklightSettings settings;
|
+ RGBBacklightSettings settings;
|
||||||
+ File* file = storage_file_alloc(furi_record_open(RECORD_STORAGE));
|
+ File* file = storage_file_alloc(furi_record_open(RECORD_STORAGE));
|
||||||
+ const size_t settings_size = sizeof(RGBBacklightSettings);
|
+ const size_t settings_size = sizeof(RGBBacklightSettings);
|
||||||
+
|
+
|
||||||
+ FURI_LOG_I(TAG, "loading settings from \"%s\"", RGB_BACKLIGHT_SETTINGS_PATH);
|
+ FURI_LOG_D(TAG, "loading settings from \"%s\"", RGB_BACKLIGHT_SETTINGS_PATH);
|
||||||
+ bool fs_result =
|
+ bool fs_result =
|
||||||
+ storage_file_open(file, RGB_BACKLIGHT_SETTINGS_PATH, FSAM_READ, FSOM_OPEN_EXISTING);
|
+ storage_file_open(file, RGB_BACKLIGHT_SETTINGS_PATH, FSAM_READ, FSOM_OPEN_EXISTING);
|
||||||
+
|
+
|
||||||
@@ -150,7 +245,7 @@ index 0000000..269b544
|
|||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
+ if(fs_result) {
|
+ if(fs_result) {
|
||||||
+ FURI_LOG_I(TAG, "load success");
|
+ FURI_LOG_D(TAG, "load success");
|
||||||
+ if(settings.version != RGB_BACKLIGHT_SETTINGS_VERSION) {
|
+ if(settings.version != RGB_BACKLIGHT_SETTINGS_VERSION) {
|
||||||
+ FURI_LOG_E(
|
+ FURI_LOG_E(
|
||||||
+ TAG,
|
+ TAG,
|
||||||
@@ -175,7 +270,7 @@ index 0000000..269b544
|
|||||||
+ File* file = storage_file_alloc(furi_record_open(RECORD_STORAGE));
|
+ File* file = storage_file_alloc(furi_record_open(RECORD_STORAGE));
|
||||||
+ const size_t settings_size = sizeof(RGBBacklightSettings);
|
+ const size_t settings_size = sizeof(RGBBacklightSettings);
|
||||||
+
|
+
|
||||||
+ FURI_LOG_I(TAG, "saving settings to \"%s\"", RGB_BACKLIGHT_SETTINGS_PATH);
|
+ FURI_LOG_D(TAG, "saving settings to \"%s\"", RGB_BACKLIGHT_SETTINGS_PATH);
|
||||||
+
|
+
|
||||||
+ memcpy(&settings, &rgb_settings, settings_size);
|
+ memcpy(&settings, &rgb_settings, settings_size);
|
||||||
+
|
+
|
||||||
@@ -191,7 +286,7 @@ index 0000000..269b544
|
|||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
+ if(fs_result) {
|
+ if(fs_result) {
|
||||||
+ FURI_LOG_I(TAG, "save success");
|
+ FURI_LOG_D(TAG, "save success");
|
||||||
+ } else {
|
+ } else {
|
||||||
+ FURI_LOG_E(TAG, "save failed, %s", storage_file_get_error_desc(file));
|
+ FURI_LOG_E(TAG, "save failed, %s", storage_file_get_error_desc(file));
|
||||||
+ }
|
+ }
|
||||||
@@ -213,36 +308,68 @@ index 0000000..269b544
|
|||||||
+ rgb_settings.display_color_index = color_index;
|
+ rgb_settings.display_color_index = color_index;
|
||||||
+}
|
+}
|
||||||
+
|
+
|
||||||
+void rgb_backlight_update(uint8_t brightness) {
|
+void rgb_backlight_set_custom_color(uint8_t color, uint8_t index) {
|
||||||
|
+ if(index > 2) return;
|
||||||
|
+ if(index == 0) {
|
||||||
|
+ rgb_settings.custom_r = color;
|
||||||
|
+ } else if(index == 1) {
|
||||||
|
+ rgb_settings.custom_g = color;
|
||||||
|
+ } else if(index == 2) {
|
||||||
|
+ rgb_settings.custom_b = color;
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void rgb_backlight_update(uint8_t brightness, bool bypass) {
|
||||||
+ if(!rgb_settings.settings_is_loaded) {
|
+ if(!rgb_settings.settings_is_loaded) {
|
||||||
+ rgb_backlight_load_settings();
|
+ rgb_backlight_load_settings();
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
+ static uint8_t last_color_index = 255;
|
+ if(!bypass) {
|
||||||
+ static uint8_t last_brightness = 123;
|
+ static uint8_t last_color_index = 255;
|
||||||
|
+ static uint8_t last_brightness = 123;
|
||||||
+
|
+
|
||||||
+ if(last_brightness == brightness && last_color_index == rgb_settings.display_color_index)
|
+ if(last_brightness == brightness && last_color_index == rgb_settings.display_color_index) {
|
||||||
+ return;
|
+ return;
|
||||||
|
+ }
|
||||||
+
|
+
|
||||||
+ last_brightness = brightness;
|
+ last_brightness = brightness;
|
||||||
+ last_color_index = rgb_settings.display_color_index;
|
+ last_color_index = rgb_settings.display_color_index;
|
||||||
|
+ }
|
||||||
+
|
+
|
||||||
+ for(uint8_t i = 0; i < SK6805_get_led_count(); i++) {
|
+ for(uint8_t i = 0; i < SK6805_get_led_count(); i++) {
|
||||||
+ uint8_t r = colors[rgb_settings.display_color_index].red * (brightness / 255.0f);
|
+ if(rgb_settings.display_color_index == 13) {
|
||||||
+ uint8_t g = colors[rgb_settings.display_color_index].green * (brightness / 255.0f);
|
+ uint8_t r = rgb_settings.custom_r * (brightness / 255.0f);
|
||||||
+ uint8_t b = colors[rgb_settings.display_color_index].blue * (brightness / 255.0f);
|
+ uint8_t g = rgb_settings.custom_g * (brightness / 255.0f);
|
||||||
|
+ uint8_t b = rgb_settings.custom_b * (brightness / 255.0f);
|
||||||
+
|
+
|
||||||
+ SK6805_set_led_color(i, r, g, b);
|
+ SK6805_set_led_color(i, r, g, b);
|
||||||
|
+ } else {
|
||||||
|
+ if((colors[rgb_settings.display_color_index].red == 0) &&
|
||||||
|
+ (colors[rgb_settings.display_color_index].green == 0) &&
|
||||||
|
+ (colors[rgb_settings.display_color_index].blue == 0)) {
|
||||||
|
+ uint8_t r = colors[0].red * (brightness / 255.0f);
|
||||||
|
+ uint8_t g = colors[0].green * (brightness / 255.0f);
|
||||||
|
+ uint8_t b = colors[0].blue * (brightness / 255.0f);
|
||||||
|
+
|
||||||
|
+ SK6805_set_led_color(i, r, g, b);
|
||||||
|
+ } else {
|
||||||
|
+ uint8_t r = colors[rgb_settings.display_color_index].red * (brightness / 255.0f);
|
||||||
|
+ uint8_t g = colors[rgb_settings.display_color_index].green * (brightness / 255.0f);
|
||||||
|
+ uint8_t b = colors[rgb_settings.display_color_index].blue * (brightness / 255.0f);
|
||||||
|
+
|
||||||
|
+ SK6805_set_led_color(i, r, g, b);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
+ SK6805_update();
|
+ SK6805_update();
|
||||||
+}
|
+}
|
||||||
diff --git a/applications/settings/notification_settings/rgb_backlight.h b/applications/settings/notification_settings/rgb_backlight.h
|
diff --git a/applications/settings/notification_settings/rgb_backlight.h b/applications/settings/notification_settings/rgb_backlight.h
|
||||||
new file mode 100644
|
new file mode 100644
|
||||||
index 0000000..b63d223
|
index 0000000..68dacda
|
||||||
--- /dev/null
|
--- /dev/null
|
||||||
+++ b/applications/settings/notification_settings/rgb_backlight.h
|
+++ b/applications/settings/notification_settings/rgb_backlight.h
|
||||||
@@ -0,0 +1,79 @@
|
@@ -0,0 +1,91 @@
|
||||||
+/*
|
+/*
|
||||||
+ RGB backlight FlipperZero driver
|
+ RGB backlight FlipperZero driver
|
||||||
+ Copyright (C) 2022-2023 Victor Nikitchuk (https://github.com/quen0n)
|
+ Copyright (C) 2022-2023 Victor Nikitchuk (https://github.com/quen0n)
|
||||||
@@ -274,6 +401,9 @@ index 0000000..b63d223
|
|||||||
+typedef struct {
|
+typedef struct {
|
||||||
+ uint8_t version;
|
+ uint8_t version;
|
||||||
+ uint8_t display_color_index;
|
+ uint8_t display_color_index;
|
||||||
|
+ uint8_t custom_r;
|
||||||
|
+ uint8_t custom_g;
|
||||||
|
+ uint8_t custom_b;
|
||||||
+ bool settings_is_loaded;
|
+ bool settings_is_loaded;
|
||||||
+} RGBBacklightSettings;
|
+} RGBBacklightSettings;
|
||||||
+
|
+
|
||||||
@@ -298,8 +428,9 @@ index 0000000..b63d223
|
|||||||
+ * @brief Применить текущие настройки RGB-подсветки
|
+ * @brief Применить текущие настройки RGB-подсветки
|
||||||
+ *
|
+ *
|
||||||
+ * @param brightness Яркость свечения (0-255)
|
+ * @param brightness Яркость свечения (0-255)
|
||||||
|
+ * @param bypass Применить настройки принудительно
|
||||||
+ */
|
+ */
|
||||||
+void rgb_backlight_update(uint8_t brightness);
|
+void rgb_backlight_update(uint8_t brightness, bool bypass);
|
||||||
+
|
+
|
||||||
+/**
|
+/**
|
||||||
+ * @brief Установить цвет RGB-подсветки
|
+ * @brief Установить цвет RGB-подсветки
|
||||||
@@ -309,6 +440,14 @@ index 0000000..b63d223
|
|||||||
+void rgb_backlight_set_color(uint8_t color_index);
|
+void rgb_backlight_set_color(uint8_t color_index);
|
||||||
+
|
+
|
||||||
+/**
|
+/**
|
||||||
|
+ * @brief Set custom color values by index - 0=R 1=G 2=B
|
||||||
|
+ *
|
||||||
|
+ * @param color - color value (0-255)
|
||||||
|
+ * @param index - color index (0-2) 0=R 1=G 2=B
|
||||||
|
+ */
|
||||||
|
+void rgb_backlight_set_custom_color(uint8_t color, uint8_t index);
|
||||||
|
+
|
||||||
|
+/**
|
||||||
+ * @brief Получить количество доступных цветов
|
+ * @brief Получить количество доступных цветов
|
||||||
+ *
|
+ *
|
||||||
+ * @return Число доступных вариантов цвета
|
+ * @return Число доступных вариантов цвета
|
||||||
@@ -324,7 +463,7 @@ index 0000000..b63d223
|
|||||||
+const char* rgb_backlight_get_color_text(uint8_t index);
|
+const char* rgb_backlight_get_color_text(uint8_t index);
|
||||||
\ No newline at end of file
|
\ No newline at end of file
|
||||||
diff --git a/firmware/targets/f7/furi_hal/furi_hal_light.c b/firmware/targets/f7/furi_hal/furi_hal_light.c
|
diff --git a/firmware/targets/f7/furi_hal/furi_hal_light.c b/firmware/targets/f7/furi_hal/furi_hal_light.c
|
||||||
index 83e1603..cad5b86 100644
|
index 83e1603..45798ca 100644
|
||||||
--- a/firmware/targets/f7/furi_hal/furi_hal_light.c
|
--- a/firmware/targets/f7/furi_hal/furi_hal_light.c
|
||||||
+++ b/firmware/targets/f7/furi_hal/furi_hal_light.c
|
+++ b/firmware/targets/f7/furi_hal/furi_hal_light.c
|
||||||
@@ -3,6 +3,7 @@
|
@@ -3,6 +3,7 @@
|
||||||
@@ -353,7 +492,7 @@ index 83e1603..cad5b86 100644
|
|||||||
- uint8_t prev = lp5562_get_channel_value(&furi_hal_i2c_handle_power, LP5562ChannelWhite);
|
- uint8_t prev = lp5562_get_channel_value(&furi_hal_i2c_handle_power, LP5562ChannelWhite);
|
||||||
- lp5562_execute_ramp(
|
- lp5562_execute_ramp(
|
||||||
- &furi_hal_i2c_handle_power, LP5562Engine1, LP5562ChannelWhite, prev, value, 100);
|
- &furi_hal_i2c_handle_power, LP5562Engine1, LP5562ChannelWhite, prev, value, 100);
|
||||||
+ rgb_backlight_update(value);
|
+ rgb_backlight_update(value, false);
|
||||||
+ } else {
|
+ } else {
|
||||||
+ furi_hal_i2c_acquire(&furi_hal_i2c_handle_power);
|
+ furi_hal_i2c_acquire(&furi_hal_i2c_handle_power);
|
||||||
+ if(light & LightRed) {
|
+ if(light & LightRed) {
|
||||||
|
|||||||
28
.drone.yml
28
.drone.yml
@@ -22,7 +22,8 @@ steps:
|
|||||||
- export DIST_SUFFIX=${DRONE_TAG}c
|
- export DIST_SUFFIX=${DRONE_TAG}c
|
||||||
- export WORKFLOW_BRANCH_OR_TAG=release-cfw
|
- export WORKFLOW_BRANCH_OR_TAG=release-cfw
|
||||||
- export FORCE_NO_DIRTY=yes
|
- export FORCE_NO_DIRTY=yes
|
||||||
- rm -rf assets/resources/apps/
|
- export FBT_GIT_SUBMODULE_SHALLOW=1
|
||||||
|
- rm -rf applications/main/clock_app/resources/apps/
|
||||||
- rm -rf build/
|
- rm -rf build/
|
||||||
- rm -rf dist/
|
- rm -rf dist/
|
||||||
- rm -rf .sconsign.dblite
|
- rm -rf .sconsign.dblite
|
||||||
@@ -42,9 +43,11 @@ steps:
|
|||||||
- export DIST_SUFFIX=${DRONE_TAG}
|
- export DIST_SUFFIX=${DRONE_TAG}
|
||||||
- export WORKFLOW_BRANCH_OR_TAG=release-cfw
|
- export WORKFLOW_BRANCH_OR_TAG=release-cfw
|
||||||
- export FORCE_NO_DIRTY=yes
|
- export FORCE_NO_DIRTY=yes
|
||||||
|
- export FBT_GIT_SUBMODULE_SHALLOW=1
|
||||||
- wget https://github.com/xMasterX/all-the-plugins/releases/latest/download/all-the-apps-base.tgz
|
- wget https://github.com/xMasterX/all-the-plugins/releases/latest/download/all-the-apps-base.tgz
|
||||||
- tar zxvf all-the-apps-base.tgz
|
- tar zxvf all-the-apps-base.tgz
|
||||||
- cp -R base_pack_build/artifacts-base/* assets/resources/apps/
|
- cp -R base_pack_build/artifacts-base/* applications/main/clock_app/resources/apps/
|
||||||
|
- cp -R base_pack_build/apps_data/* applications/main/clock_app/resources/apps_data/
|
||||||
- rm -rf base_pack_build
|
- rm -rf base_pack_build
|
||||||
- rm -rf all-the-apps-base.tgz
|
- rm -rf all-the-apps-base.tgz
|
||||||
- rm -f build/f7-firmware-C/toolbox/version.*
|
- rm -f build/f7-firmware-C/toolbox/version.*
|
||||||
@@ -63,11 +66,12 @@ steps:
|
|||||||
commands:
|
commands:
|
||||||
- wget https://github.com/xMasterX/all-the-plugins/releases/latest/download/all-the-apps-extra.tgz
|
- wget https://github.com/xMasterX/all-the-plugins/releases/latest/download/all-the-apps-extra.tgz
|
||||||
- tar zxvf all-the-apps-extra.tgz
|
- tar zxvf all-the-apps-extra.tgz
|
||||||
- cp -R extra_pack_build/artifacts-extra/* assets/resources/apps/
|
- cp -R extra_pack_build/artifacts-extra/* applications/main/clock_app/resources/apps/
|
||||||
- rm -rf extra_pack_build
|
- rm -rf extra_pack_build
|
||||||
- export DIST_SUFFIX=${DRONE_TAG}e
|
- export DIST_SUFFIX=${DRONE_TAG}e
|
||||||
- export WORKFLOW_BRANCH_OR_TAG=release-cfw
|
- export WORKFLOW_BRANCH_OR_TAG=release-cfw
|
||||||
- export FORCE_NO_DIRTY=yes
|
- export FORCE_NO_DIRTY=yes
|
||||||
|
- export FBT_GIT_SUBMODULE_SHALLOW=1
|
||||||
- rm -f build/f7-firmware-C/toolbox/version.*
|
- rm -f build/f7-firmware-C/toolbox/version.*
|
||||||
- ./fbt COMPACT=1 DEBUG=0 updater_package
|
- ./fbt COMPACT=1 DEBUG=0 updater_package
|
||||||
- mkdir artifacts-extra-apps
|
- mkdir artifacts-extra-apps
|
||||||
@@ -86,6 +90,7 @@ steps:
|
|||||||
- export DIST_SUFFIX=${DRONE_TAG}r
|
- export DIST_SUFFIX=${DRONE_TAG}r
|
||||||
- export WORKFLOW_BRANCH_OR_TAG=release-cfw-rgb
|
- export WORKFLOW_BRANCH_OR_TAG=release-cfw-rgb
|
||||||
- export FORCE_NO_DIRTY=yes
|
- export FORCE_NO_DIRTY=yes
|
||||||
|
- export FBT_GIT_SUBMODULE_SHALLOW=1
|
||||||
- rm -f build/f7-firmware-C/toolbox/version.*
|
- rm -f build/f7-firmware-C/toolbox/version.*
|
||||||
- ./fbt COMPACT=1 DEBUG=0 updater_package
|
- ./fbt COMPACT=1 DEBUG=0 updater_package
|
||||||
- mkdir artifacts-rgb-patch
|
- mkdir artifacts-rgb-patch
|
||||||
@@ -104,15 +109,17 @@ steps:
|
|||||||
- git checkout -- .
|
- git checkout -- .
|
||||||
- rm -f assets/dolphin/external/manifest.txt
|
- rm -f assets/dolphin/external/manifest.txt
|
||||||
- cp .ci_files/anims_ofw.txt assets/dolphin/external/manifest.txt
|
- cp .ci_files/anims_ofw.txt assets/dolphin/external/manifest.txt
|
||||||
- rm -rf assets/resources/apps/
|
- rm -rf applications/main/clock_app/resources/apps/
|
||||||
- export DIST_SUFFIX=${DRONE_TAG}n
|
- export DIST_SUFFIX=${DRONE_TAG}n
|
||||||
- export WORKFLOW_BRANCH_OR_TAG=no-custom-anims
|
- export WORKFLOW_BRANCH_OR_TAG=no-custom-anims
|
||||||
- export FORCE_NO_DIRTY=yes
|
- export FORCE_NO_DIRTY=yes
|
||||||
|
- export FBT_GIT_SUBMODULE_SHALLOW=1
|
||||||
- rm -f build/f7-firmware-C/toolbox/version.*
|
- rm -f build/f7-firmware-C/toolbox/version.*
|
||||||
- ./fbt COMPACT=1 DEBUG=0 updater_package
|
- ./fbt COMPACT=1 DEBUG=0 updater_package
|
||||||
- wget https://github.com/xMasterX/all-the-plugins/releases/latest/download/all-the-apps-base.tgz
|
- wget https://github.com/xMasterX/all-the-plugins/releases/latest/download/all-the-apps-base.tgz
|
||||||
- tar zxvf all-the-apps-base.tgz
|
- tar zxvf all-the-apps-base.tgz
|
||||||
- cp -R base_pack_build/artifacts-base/* assets/resources/apps/
|
- cp -R base_pack_build/artifacts-base/* applications/main/clock_app/resources/apps/
|
||||||
|
- cp -R base_pack_build/apps_data/* applications/main/clock_app/resources/apps_data/
|
||||||
- rm -rf base_pack_build
|
- rm -rf base_pack_build
|
||||||
- rm -rf all-the-apps-base.tgz
|
- rm -rf all-the-apps-base.tgz
|
||||||
- rm -f build/f7-firmware-C/toolbox/version.*
|
- rm -f build/f7-firmware-C/toolbox/version.*
|
||||||
@@ -389,7 +396,8 @@ steps:
|
|||||||
- export DIST_SUFFIX=${DRONE_BUILD_NUMBER}c
|
- export DIST_SUFFIX=${DRONE_BUILD_NUMBER}c
|
||||||
- export WORKFLOW_BRANCH_OR_TAG=dev-cfw
|
- export WORKFLOW_BRANCH_OR_TAG=dev-cfw
|
||||||
- export FORCE_NO_DIRTY=yes
|
- export FORCE_NO_DIRTY=yes
|
||||||
- rm -rf assets/resources/apps/
|
- export FBT_GIT_SUBMODULE_SHALLOW=1
|
||||||
|
- rm -rf applications/main/clock_app/resources/apps/
|
||||||
- rm -rf build/
|
- rm -rf build/
|
||||||
- rm -rf dist/
|
- rm -rf dist/
|
||||||
- rm -rf .sconsign.dblite
|
- rm -rf .sconsign.dblite
|
||||||
@@ -410,9 +418,11 @@ steps:
|
|||||||
- export DIST_SUFFIX=${DRONE_BUILD_NUMBER}
|
- export DIST_SUFFIX=${DRONE_BUILD_NUMBER}
|
||||||
- export WORKFLOW_BRANCH_OR_TAG=dev-cfw
|
- export WORKFLOW_BRANCH_OR_TAG=dev-cfw
|
||||||
- export FORCE_NO_DIRTY=yes
|
- export FORCE_NO_DIRTY=yes
|
||||||
|
- export FBT_GIT_SUBMODULE_SHALLOW=1
|
||||||
- wget https://github.com/xMasterX/all-the-plugins/releases/latest/download/all-the-apps-base.tgz
|
- wget https://github.com/xMasterX/all-the-plugins/releases/latest/download/all-the-apps-base.tgz
|
||||||
- tar zxvf all-the-apps-base.tgz
|
- tar zxvf all-the-apps-base.tgz
|
||||||
- cp -R base_pack_build/artifacts-base/* assets/resources/apps/
|
- cp -R base_pack_build/artifacts-base/* applications/main/clock_app/resources/apps/
|
||||||
|
- cp -R base_pack_build/apps_data/* applications/main/clock_app/resources/apps_data/
|
||||||
- rm -rf base_pack_build
|
- rm -rf base_pack_build
|
||||||
- rm -rf all-the-apps-base.tgz
|
- rm -rf all-the-apps-base.tgz
|
||||||
- rm -f build/f7-firmware-C/toolbox/version.*
|
- rm -f build/f7-firmware-C/toolbox/version.*
|
||||||
@@ -431,11 +441,12 @@ steps:
|
|||||||
commands:
|
commands:
|
||||||
- wget https://github.com/xMasterX/all-the-plugins/releases/latest/download/all-the-apps-extra.tgz
|
- wget https://github.com/xMasterX/all-the-plugins/releases/latest/download/all-the-apps-extra.tgz
|
||||||
- tar zxvf all-the-apps-extra.tgz
|
- tar zxvf all-the-apps-extra.tgz
|
||||||
- cp -R extra_pack_build/artifacts-extra/* assets/resources/apps/
|
- cp -R extra_pack_build/artifacts-extra/* applications/main/clock_app/resources/apps/
|
||||||
- rm -rf extra_pack_build
|
- rm -rf extra_pack_build
|
||||||
- export DIST_SUFFIX=${DRONE_BUILD_NUMBER}e
|
- export DIST_SUFFIX=${DRONE_BUILD_NUMBER}e
|
||||||
- export WORKFLOW_BRANCH_OR_TAG=dev-cfw
|
- export WORKFLOW_BRANCH_OR_TAG=dev-cfw
|
||||||
- export FORCE_NO_DIRTY=yes
|
- export FORCE_NO_DIRTY=yes
|
||||||
|
- export FBT_GIT_SUBMODULE_SHALLOW=1
|
||||||
- rm -f build/f7-firmware-C/toolbox/version.*
|
- rm -f build/f7-firmware-C/toolbox/version.*
|
||||||
- ./fbt COMPACT=1 DEBUG=0 updater_package
|
- ./fbt COMPACT=1 DEBUG=0 updater_package
|
||||||
- mkdir artifacts-extra-apps
|
- mkdir artifacts-extra-apps
|
||||||
@@ -454,6 +465,7 @@ steps:
|
|||||||
- export DIST_SUFFIX=${DRONE_BUILD_NUMBER}r
|
- export DIST_SUFFIX=${DRONE_BUILD_NUMBER}r
|
||||||
- export WORKFLOW_BRANCH_OR_TAG=dev-cfw-rgb
|
- export WORKFLOW_BRANCH_OR_TAG=dev-cfw-rgb
|
||||||
- export FORCE_NO_DIRTY=yes
|
- export FORCE_NO_DIRTY=yes
|
||||||
|
- export FBT_GIT_SUBMODULE_SHALLOW=1
|
||||||
- rm -f build/f7-firmware-C/toolbox/version.*
|
- rm -f build/f7-firmware-C/toolbox/version.*
|
||||||
- ./fbt COMPACT=1 DEBUG=0 updater_package
|
- ./fbt COMPACT=1 DEBUG=0 updater_package
|
||||||
- mkdir artifacts-rgb-patch
|
- mkdir artifacts-rgb-patch
|
||||||
|
|||||||
114
.github/workflows/codeql.yml
vendored
Normal file
114
.github/workflows/codeql.yml
vendored
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
# For most projects, this workflow file will not need changing; you simply need
|
||||||
|
# to commit it to your repository.
|
||||||
|
#
|
||||||
|
# You may wish to alter this file to override the set of languages analyzed,
|
||||||
|
# or to provide custom queries or build logic.
|
||||||
|
#
|
||||||
|
# ******** NOTE ********
|
||||||
|
# We have attempted to detect the languages in your repository. Please check
|
||||||
|
# the `language` matrix defined below to confirm you have the correct set of
|
||||||
|
# supported CodeQL languages.
|
||||||
|
#
|
||||||
|
name: "CodeQL"
|
||||||
|
run-name: "CodeQL Analyze ${{ github.ref_name }} by @${{ github.ACTOR }}"
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: ["dev"]
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
analyze:
|
||||||
|
name: Analyze
|
||||||
|
# Runner size impacts CodeQL analysis time. To learn more, please see:
|
||||||
|
# - https://gh.io/recommended-hardware-resources-for-running-codeql
|
||||||
|
# - https://gh.io/supported-runners-and-hardware-resources
|
||||||
|
# - https://gh.io/using-larger-runners
|
||||||
|
# Consider using larger runners for possible analysis time improvements.
|
||||||
|
runs-on: [ "ubuntu-latest" ]
|
||||||
|
timeout-minutes: 60
|
||||||
|
permissions:
|
||||||
|
actions: read
|
||||||
|
contents: read
|
||||||
|
security-events: write
|
||||||
|
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
language: ["cpp"]
|
||||||
|
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby', 'swift' ]
|
||||||
|
# Use only 'java' to analyze code written in Java, Kotlin or both
|
||||||
|
# Use only 'javascript' to analyze code written in JavaScript, TypeScript or both
|
||||||
|
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
|
||||||
|
env:
|
||||||
|
PATH_SARIF_DIR: ".github/results.sarif"
|
||||||
|
PATH_SARIF_FILE: ".github/results.sarif/${{ matrix.language }}.sarif"
|
||||||
|
FBT_NO_SYNC: 0
|
||||||
|
DIST_SUFFIX: "codeql"
|
||||||
|
WORKFLOW_BRANCH_OR_TAG: release-cfw
|
||||||
|
LANG_CATEGORY: "/language:${{matrix.language}}"
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout Firmware Files
|
||||||
|
uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
clean: "true"
|
||||||
|
submodules: "true"
|
||||||
|
fetch-depth: "0"
|
||||||
|
|
||||||
|
# Initializes the CodeQL tools for scanning.
|
||||||
|
- name: Initialize CodeQL
|
||||||
|
uses: github/codeql-action/init@v2
|
||||||
|
with:
|
||||||
|
languages: ${{ matrix.language }}
|
||||||
|
setup-python-dependencies: true
|
||||||
|
|
||||||
|
- name: Resolve CodeQL Build Env
|
||||||
|
uses: github/codeql-action/resolve-environment@v2
|
||||||
|
with:
|
||||||
|
language: ${{ matrix.language }}
|
||||||
|
#debug: true
|
||||||
|
|
||||||
|
- name: Build Firmware
|
||||||
|
shell: bash
|
||||||
|
if: ${{ success() }}
|
||||||
|
run: |
|
||||||
|
./fbt COMPACT=1 DEBUG=0 FBT_NO_SYNC=${{ env.FBT_NO_SYNC }}
|
||||||
|
|
||||||
|
- name: Perform CodeQL Analysis
|
||||||
|
uses: github/codeql-action/analyze@v2
|
||||||
|
if: ${{ success() }}
|
||||||
|
with:
|
||||||
|
threads: 4
|
||||||
|
category: "${{ env.LANG_CATEGORY }}"
|
||||||
|
output: "${{ env.PATH_SARIF_DIR }}"
|
||||||
|
upload-database: false
|
||||||
|
upload: "failure-only" # disable the upload here - we will upload in a different action
|
||||||
|
|
||||||
|
- name: Filter dirs for SARIF
|
||||||
|
uses: advanced-security/filter-sarif@v1
|
||||||
|
if: ${{ success() }}
|
||||||
|
with:
|
||||||
|
# filter out all test files unless they contain a sql-injection vulnerability
|
||||||
|
patterns: |
|
||||||
|
-build/**
|
||||||
|
-dist/**
|
||||||
|
-toolchain/**
|
||||||
|
-lib/**
|
||||||
|
input: "${{ env.PATH_SARIF_FILE }}"
|
||||||
|
output: "${{ env.PATH_SARIF_FILE }}"
|
||||||
|
|
||||||
|
- name: Upload CodeQL SARIF
|
||||||
|
uses: github/codeql-action/upload-sarif@v2
|
||||||
|
if: ${{ success() }}
|
||||||
|
with:
|
||||||
|
category: "${{ env.LANG_CATEGORY }}"
|
||||||
|
sarif_file: "${{ env.PATH_SARIF_FILE }}"
|
||||||
|
|
||||||
|
# optional: for debugging the uploaded sarif
|
||||||
|
# - name: Upload loc as a Build Artifact
|
||||||
|
# uses: actions/upload-artifact@v3
|
||||||
|
# with:
|
||||||
|
# name: sarif-results
|
||||||
|
# path: sarif-results
|
||||||
|
# retention-days: 1
|
||||||
@@ -1 +1 @@
|
|||||||
--ignore-ccache -C gccarm --rules-config .pvsconfig -e lib/cmsis_core -e lib/fatfs -e lib/fnv1a-hash -e lib/FreeRTOS-Kernel -e lib/heatshrink -e lib/libusb_stm32 -e lib/littlefs -e lib/mbedtls -e lib/micro-ecc -e lib/microtar -e lib/mlib -e lib/qrcode -e lib/ST25RFAL002 -e lib/stm32wb_cmsis -e lib/stm32wb_copro -e lib/stm32wb_hal -e lib/u8g2 -e lib/nanopb -e */arm-none-eabi/*
|
--ignore-ccache -C gccarm --rules-config .pvsconfig -e lib/cmsis_core -e lib/fatfs -e lib/fnv1a-hash -e lib/FreeRTOS-Kernel -e lib/heatshrink -e lib/libusb_stm32 -e lib/littlefs -e lib/mbedtls -e lib/micro-ecc -e lib/microtar -e lib/mlib -e lib/qrcode -e lib/stm32wb_cmsis -e lib/stm32wb_copro -e lib/stm32wb_hal -e lib/u8g2 -e lib/nanopb -e */arm-none-eabi/*
|
||||||
|
|||||||
46
CHANGELOG.md
46
CHANGELOG.md
@@ -1,41 +1,13 @@
|
|||||||
## New changes
|
## New changes
|
||||||
* **Apple BLE Spam app** (by @Willy-JL | Plus research from ECTO-1A, xMasterX and techryptic) -> (app can be found in builds ` `, `e`, `n`, `r`)
|
* SubGHz: Add 4 more systems to Add Manually (untested!)
|
||||||
* SubGHz: **FAAC SLH - Programming mode** (by @xMasterX & @Eng1n33r (full research and PoC by @Skorpionm)| PR #585) -> [How to use](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/SubGHzRemoteProg.md)
|
* SubGHz: Add Manually fixes
|
||||||
* SubGHz: FAAC SLH -> Add manually new options
|
* SubGHz: Added NiceFlor-S to ignore options, removed colons. (by @G2Dolphin | PR #620)
|
||||||
* SubGHz: Fix 0xFFFF counter value being skipped
|
* Misc code cleanup
|
||||||
* SubGHz: Fix path reset on save name scene exit
|
* RGB: Fix white color on reboot, move settings, add custom color option
|
||||||
* SubGHz: Various fixes
|
* **BLE Spam app** updated to latest version (Android, Windows support) (by @Willy-JL) -> (app can be found in builds ` `, `e`, `n`, `r`)
|
||||||
* SubGHz Remote: Fix Sub-GHz Remote folder name (by @OperKH | PR #583)
|
* OFW: Fix double arrows and add proper indication
|
||||||
* SubGHz Remote: submodule (by @gid9798 | PR #592)
|
* OFW: SubGHz: add manually fix 12-bits is 0xFFF (or 0xFF0) CAME/NICE 12-bit
|
||||||
* Infrared: Updated universal assets (by @amec0e | PR #594)
|
* OFW: Fix various crashes if debug libraries used
|
||||||
* Infrared: Remake custom universal remotes to use new design (New icons by @Svaarich)
|
|
||||||
* UI: Keyboard ok to toggle select all in cursor mode (by @Willy-JL)
|
|
||||||
* CI/CD: Fixed regular builds having `c` in version name in the device info while not being actual `c` build
|
|
||||||
* Docs: New FAAC SLH instructions
|
|
||||||
* Docs: Readme & Changelog fixes (by @gid9798 | PR #586)
|
|
||||||
* OFW: iButton: Return to the file selection if file is corrupted
|
|
||||||
* OFW: Account for the "-" in line carry-over
|
|
||||||
* OFW: github: workflow improvements
|
|
||||||
* OFW: Storage: force mount
|
|
||||||
* OFW: Add File Naming setting for more detailed naming -> **Breaking API change, API 35.x -> API 36.x** - **Update your apps!**
|
|
||||||
* OFW: Disconnect from BLE on protobuf error
|
|
||||||
* OFW: Add support for Mifare Classic 4k SAK 0x38 ATQA 0x02, 0x04, 0x08
|
|
||||||
* OFW: Undo some TODO
|
|
||||||
* OFW: Check the filetype of the update manifest
|
|
||||||
* OFW: StorageListRequest: size filter
|
|
||||||
* OFW: SubGhz: heap overflow text error
|
|
||||||
* OFW: nfc: add rfal wrong state error handling
|
|
||||||
* OFW: Rfid: fix crash on broken key launch from archive (fix was already done in UL in similar way)
|
|
||||||
* OFW: AC OFF button
|
|
||||||
* OFW: New IR universal remote graphics
|
|
||||||
* OFW: Intelligent probing with warnings for fwflash.py
|
|
||||||
* OFW: FuriHal: explicitly pull display pins at early init stage, move PUPD config to early stage
|
|
||||||
* OFW: Fix display last symbol in multiline text
|
|
||||||
* OFW: Properly reset the NFC device data
|
|
||||||
* OFW: fbt: various improvements and bug fixes
|
|
||||||
* OFW: Littlefs updated to v2.7.0
|
|
||||||
* OFW: loader: restored support for debug apps
|
|
||||||
* OFW: Removed explicit dependency on scons for external scripting
|
|
||||||
|
|
||||||
----
|
----
|
||||||
|
|
||||||
|
|||||||
@@ -33,6 +33,9 @@
|
|||||||
|
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
|
## FAQ (frequently asked questions)
|
||||||
|
[Follow this link to find answers to most asked questions](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/FAQ.md)
|
||||||
|
|
||||||
## Dev builds (unstable)
|
## Dev builds (unstable)
|
||||||
- https://dev.unleashedflip.com/
|
- https://dev.unleashedflip.com/
|
||||||
- https://t.me/kotnehleb
|
- https://t.me/kotnehleb
|
||||||
@@ -166,13 +169,13 @@ You can support us by using links or addresses below:
|
|||||||
### [🎲 Download Extra plugins for Unleashed](https://github.com/xMasterX/all-the-plugins/releases/latest)
|
### [🎲 Download Extra plugins for Unleashed](https://github.com/xMasterX/all-the-plugins/releases/latest)
|
||||||
### [List of Extra pack](https://github.com/xMasterX/all-the-plugins/tree/dev#extra-pack) | [List of Base *(Deafult)* pack](https://github.com/xMasterX/all-the-plugins/tree/dev#default-pack)
|
### [List of Extra pack](https://github.com/xMasterX/all-the-plugins/tree/dev#extra-pack) | [List of Base *(Deafult)* pack](https://github.com/xMasterX/all-the-plugins/tree/dev#default-pack)
|
||||||
|
|
||||||
See full list and sources here: [xMasterX/all-the-plugin](https://github.com/xMasterX/all-the-plugins/tree/dev)
|
See full list and sources here: [xMasterX/all-the-plugins](https://github.com/xMasterX/all-the-plugins/tree/dev)
|
||||||
|
|
||||||
### Official Flipper Zero Apps Catalog [web version](https://lab.flipper.net/apps) or mobile app
|
### Official Flipper Zero Apps Catalog [web version](https://lab.flipper.net/apps) or mobile app
|
||||||
|
|
||||||
# Instructions
|
# Instructions
|
||||||
## First lock official docs [docs.flipper.net](https://docs.flipper.net/)
|
## First lock official docs [docs.flipper.net](https://docs.flipper.net/)
|
||||||
## [How to install](/documentation/HowToInstall.md) - [versions info](/CHANGELOG.md#what-n-r-e--c-means-what-i-need-to-download-if-i-dont-want-to-use-web-updater): `n`,` `,`e`...
|
## [How to install](/documentation/HowToInstall.md) - [versions info](/CHANGELOG.md#recommended-update-option---web-updater): `n`,` `,`e`...
|
||||||
## Firmware & Development
|
## Firmware & Development
|
||||||
|
|
||||||
### - **[How to build](/documentation/HowToBuild.md#how-to-build-by-yourself) | [Project-structure](#project-structure)**
|
### - **[How to build](/documentation/HowToBuild.md#how-to-build-by-yourself) | [Project-structure](#project-structure)**
|
||||||
|
|||||||
37
SConstruct
37
SConstruct
@@ -67,20 +67,22 @@ if GetOption("fullenv") or any(
|
|||||||
# Target for self-update package
|
# Target for self-update package
|
||||||
dist_basic_arguments = [
|
dist_basic_arguments = [
|
||||||
"--bundlever",
|
"--bundlever",
|
||||||
'"${UPDATE_VERSION_STRING}"',
|
"${UPDATE_VERSION_STRING}",
|
||||||
]
|
]
|
||||||
dist_radio_arguments = [
|
dist_radio_arguments = [
|
||||||
"--radio",
|
"--radio",
|
||||||
'"${ROOT_DIR.abspath}/${COPRO_STACK_BIN_DIR}/${COPRO_STACK_BIN}"',
|
"${ROOT_DIR.abspath}/${COPRO_STACK_BIN_DIR}/${COPRO_STACK_BIN}",
|
||||||
"--radiotype",
|
"--radiotype",
|
||||||
"${COPRO_STACK_TYPE}",
|
"${COPRO_STACK_TYPE}",
|
||||||
"${COPRO_DISCLAIMER}",
|
"${COPRO_DISCLAIMER}",
|
||||||
"--obdata",
|
"--obdata",
|
||||||
'"${ROOT_DIR.abspath}/${COPRO_OB_DATA}"',
|
"${ROOT_DIR.abspath}/${COPRO_OB_DATA}",
|
||||||
|
"--stackversion",
|
||||||
|
"${COPRO_CUBE_VERSION}",
|
||||||
]
|
]
|
||||||
dist_resource_arguments = [
|
dist_resource_arguments = [
|
||||||
"-r",
|
"-r",
|
||||||
'"${ROOT_DIR.abspath}/assets/resources"',
|
firmware_env.subst("${RESOURCES_ROOT}"),
|
||||||
]
|
]
|
||||||
dist_splash_arguments = (
|
dist_splash_arguments = (
|
||||||
[
|
[
|
||||||
@@ -93,7 +95,7 @@ if GetOption("fullenv") or any(
|
|||||||
|
|
||||||
selfupdate_dist = distenv.DistCommand(
|
selfupdate_dist = distenv.DistCommand(
|
||||||
"updater_package",
|
"updater_package",
|
||||||
(distenv["DIST_DEPENDS"], firmware_env["FW_RESOURCES"]),
|
(distenv["DIST_DEPENDS"], firmware_env["FW_RESOURCES_MANIFEST"]),
|
||||||
DIST_EXTRA=[
|
DIST_EXTRA=[
|
||||||
*dist_basic_arguments,
|
*dist_basic_arguments,
|
||||||
*dist_radio_arguments,
|
*dist_radio_arguments,
|
||||||
@@ -126,7 +128,8 @@ if GetOption("fullenv") or any(
|
|||||||
|
|
||||||
# Installation over USB & CLI
|
# Installation over USB & CLI
|
||||||
usb_update_package = distenv.AddUsbFlashTarget(
|
usb_update_package = distenv.AddUsbFlashTarget(
|
||||||
"#build/usbinstall.flag", (firmware_env["FW_RESOURCES"], selfupdate_dist)
|
"#build/usbinstall.flag",
|
||||||
|
(firmware_env["FW_RESOURCES_MANIFEST"], selfupdate_dist),
|
||||||
)
|
)
|
||||||
distenv.Alias("flash_usb_full", usb_update_package)
|
distenv.Alias("flash_usb_full", usb_update_package)
|
||||||
|
|
||||||
@@ -164,17 +167,25 @@ Depends(
|
|||||||
list(app_artifact.validator for app_artifact in external_app_list),
|
list(app_artifact.validator for app_artifact in external_app_list),
|
||||||
)
|
)
|
||||||
Alias("fap_dist", fap_dist)
|
Alias("fap_dist", fap_dist)
|
||||||
# distenv.Default(fap_dist)
|
|
||||||
|
|
||||||
distenv.Depends(firmware_env["FW_RESOURCES"], external_apps_artifacts.resources_dist)
|
|
||||||
|
|
||||||
# Copy all faps to device
|
# Copy all faps to device
|
||||||
|
|
||||||
fap_deploy = distenv.PhonyTarget(
|
fap_deploy = distenv.PhonyTarget(
|
||||||
"fap_deploy",
|
"fap_deploy",
|
||||||
"${PYTHON3} ${FBT_SCRIPT_DIR}/storage.py -p ${FLIP_PORT} send ${SOURCE} /ext/apps",
|
[
|
||||||
source=Dir("#/assets/resources/apps"),
|
[
|
||||||
|
"${PYTHON3}",
|
||||||
|
"${FBT_SCRIPT_DIR}/storage.py",
|
||||||
|
"-p",
|
||||||
|
"${FLIP_PORT}",
|
||||||
|
"send",
|
||||||
|
"${SOURCE}",
|
||||||
|
"/ext/apps",
|
||||||
|
]
|
||||||
|
],
|
||||||
|
source=firmware_env.Dir(("${RESOURCES_ROOT}/apps")),
|
||||||
)
|
)
|
||||||
|
Depends(fap_deploy, firmware_env["FW_RESOURCES_MANIFEST"])
|
||||||
|
|
||||||
|
|
||||||
# Target for bundling core2 package for qFlipper
|
# Target for bundling core2 package for qFlipper
|
||||||
@@ -312,9 +323,7 @@ distenv.PhonyTarget(
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Start Flipper CLI via PySerial's miniterm
|
# Start Flipper CLI via PySerial's miniterm
|
||||||
distenv.PhonyTarget(
|
distenv.PhonyTarget("cli", "${PYTHON3} ${FBT_SCRIPT_DIR}/serial_cli.py -p ${FLIP_PORT}")
|
||||||
"cli", "${PYTHON3} ${FBT_SCRIPT_DIR}/serial_cli.py -p ${FLIP_PORT}"
|
|
||||||
)
|
|
||||||
|
|
||||||
# Update WiFi devboard firmware
|
# Update WiFi devboard firmware
|
||||||
distenv.PhonyTarget("devboard_flash", "${PYTHON3} ${FBT_SCRIPT_DIR}/wifi_board.py")
|
distenv.PhonyTarget("devboard_flash", "${PYTHON3} ${FBT_SCRIPT_DIR}/wifi_board.py")
|
||||||
|
|||||||
16
applications/debug/ccid_test/application.fam
Normal file
16
applications/debug/ccid_test/application.fam
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
App(
|
||||||
|
appid="ccid_test",
|
||||||
|
name="CCID Debug",
|
||||||
|
apptype=FlipperAppType.DEBUG,
|
||||||
|
entry_point="ccid_test_app",
|
||||||
|
cdefines=["CCID_TEST"],
|
||||||
|
requires=[
|
||||||
|
"gui",
|
||||||
|
],
|
||||||
|
provides=[
|
||||||
|
"ccid_test",
|
||||||
|
],
|
||||||
|
stack_size=1 * 1024,
|
||||||
|
order=120,
|
||||||
|
fap_category="Debug",
|
||||||
|
)
|
||||||
169
applications/debug/ccid_test/ccid_test_app.c
Normal file
169
applications/debug/ccid_test/ccid_test_app.c
Normal file
@@ -0,0 +1,169 @@
|
|||||||
|
#include <stdint.h>
|
||||||
|
#include <furi.h>
|
||||||
|
#include <furi_hal.h>
|
||||||
|
|
||||||
|
#include <gui/view.h>
|
||||||
|
#include <gui/view_dispatcher.h>
|
||||||
|
#include <gui/modules/submenu.h>
|
||||||
|
#include <gui/gui.h>
|
||||||
|
|
||||||
|
#include "iso7816_t0_apdu.h"
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
EventTypeInput,
|
||||||
|
} EventType;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
Gui* gui;
|
||||||
|
ViewPort* view_port;
|
||||||
|
FuriMessageQueue* event_queue;
|
||||||
|
FuriHalUsbCcidConfig ccid_cfg;
|
||||||
|
} CcidTestApp;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
union {
|
||||||
|
InputEvent input;
|
||||||
|
};
|
||||||
|
EventType type;
|
||||||
|
} CcidTestAppEvent;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
CcidTestSubmenuIndexInsertSmartcard,
|
||||||
|
CcidTestSubmenuIndexRemoveSmartcard,
|
||||||
|
CcidTestSubmenuIndexInsertSmartcardReader
|
||||||
|
} SubmenuIndex;
|
||||||
|
|
||||||
|
void icc_power_on_callback(uint8_t* atrBuffer, uint32_t* atrlen, void* context) {
|
||||||
|
UNUSED(context);
|
||||||
|
|
||||||
|
iso7816_answer_to_reset(atrBuffer, atrlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
//dataBlock points to the buffer
|
||||||
|
//dataBlockLen tells reader how nany bytes should be read
|
||||||
|
void xfr_datablock_callback(
|
||||||
|
const uint8_t* dataBlock,
|
||||||
|
uint32_t dataBlockLen,
|
||||||
|
uint8_t* responseDataBlock,
|
||||||
|
uint32_t* responseDataBlockLen,
|
||||||
|
void* context) {
|
||||||
|
UNUSED(context);
|
||||||
|
|
||||||
|
struct ISO7816_Command_APDU commandAPDU;
|
||||||
|
iso7816_read_command_apdu(&commandAPDU, dataBlock, dataBlockLen);
|
||||||
|
|
||||||
|
struct ISO7816_Response_APDU responseAPDU;
|
||||||
|
//class not supported
|
||||||
|
responseAPDU.SW1 = 0x6E;
|
||||||
|
responseAPDU.SW2 = 0x00;
|
||||||
|
|
||||||
|
iso7816_write_response_apdu(&responseAPDU, responseDataBlock, responseDataBlockLen);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const CcidCallbacks ccid_cb = {
|
||||||
|
icc_power_on_callback,
|
||||||
|
xfr_datablock_callback,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void ccid_test_app_render_callback(Canvas* canvas, void* ctx) {
|
||||||
|
UNUSED(ctx);
|
||||||
|
canvas_clear(canvas);
|
||||||
|
|
||||||
|
canvas_set_font(canvas, FontPrimary);
|
||||||
|
canvas_draw_str(canvas, 0, 10, "CCID Test App");
|
||||||
|
|
||||||
|
canvas_set_font(canvas, FontSecondary);
|
||||||
|
canvas_draw_str(canvas, 0, 63, "Hold [back] to exit");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ccid_test_app_input_callback(InputEvent* input_event, void* ctx) {
|
||||||
|
FuriMessageQueue* event_queue = ctx;
|
||||||
|
|
||||||
|
CcidTestAppEvent event;
|
||||||
|
event.type = EventTypeInput;
|
||||||
|
event.input = *input_event;
|
||||||
|
furi_message_queue_put(event_queue, &event, FuriWaitForever);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t ccid_test_exit(void* context) {
|
||||||
|
UNUSED(context);
|
||||||
|
return VIEW_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
CcidTestApp* ccid_test_app_alloc() {
|
||||||
|
CcidTestApp* app = malloc(sizeof(CcidTestApp));
|
||||||
|
|
||||||
|
// Gui
|
||||||
|
app->gui = furi_record_open(RECORD_GUI);
|
||||||
|
|
||||||
|
//viewport
|
||||||
|
app->view_port = view_port_alloc();
|
||||||
|
gui_add_view_port(app->gui, app->view_port, GuiLayerFullscreen);
|
||||||
|
view_port_draw_callback_set(app->view_port, ccid_test_app_render_callback, NULL);
|
||||||
|
|
||||||
|
//message queue
|
||||||
|
app->event_queue = furi_message_queue_alloc(8, sizeof(CcidTestAppEvent));
|
||||||
|
furi_check(app->event_queue);
|
||||||
|
view_port_input_callback_set(app->view_port, ccid_test_app_input_callback, app->event_queue);
|
||||||
|
|
||||||
|
return app;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ccid_test_app_free(CcidTestApp* app) {
|
||||||
|
furi_assert(app);
|
||||||
|
|
||||||
|
//message queue
|
||||||
|
furi_message_queue_free(app->event_queue);
|
||||||
|
|
||||||
|
//view port
|
||||||
|
gui_remove_view_port(app->gui, app->view_port);
|
||||||
|
view_port_free(app->view_port);
|
||||||
|
|
||||||
|
// Close gui record
|
||||||
|
furi_record_close(RECORD_GUI);
|
||||||
|
app->gui = NULL;
|
||||||
|
|
||||||
|
// Free rest
|
||||||
|
free(app);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t ccid_test_app(void* p) {
|
||||||
|
UNUSED(p);
|
||||||
|
|
||||||
|
//setup view
|
||||||
|
CcidTestApp* app = ccid_test_app_alloc();
|
||||||
|
|
||||||
|
//setup CCID USB
|
||||||
|
// On linux: set VID PID using: /usr/lib/pcsc/drivers/ifd-ccid.bundle/Contents/Info.plist
|
||||||
|
app->ccid_cfg.vid = 0x1234;
|
||||||
|
app->ccid_cfg.pid = 0x5678;
|
||||||
|
|
||||||
|
FuriHalUsbInterface* usb_mode_prev = furi_hal_usb_get_config();
|
||||||
|
furi_hal_usb_unlock();
|
||||||
|
furi_hal_ccid_set_callbacks((CcidCallbacks*)&ccid_cb);
|
||||||
|
furi_check(furi_hal_usb_set_config(&usb_ccid, &app->ccid_cfg) == true);
|
||||||
|
|
||||||
|
//handle button events
|
||||||
|
CcidTestAppEvent event;
|
||||||
|
while(1) {
|
||||||
|
FuriStatus event_status =
|
||||||
|
furi_message_queue_get(app->event_queue, &event, FuriWaitForever);
|
||||||
|
|
||||||
|
if(event_status == FuriStatusOk) {
|
||||||
|
if(event.type == EventTypeInput) {
|
||||||
|
if(event.input.type == InputTypeLong && event.input.key == InputKeyBack) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
view_port_update(app->view_port);
|
||||||
|
}
|
||||||
|
|
||||||
|
//tear down USB
|
||||||
|
furi_hal_usb_set_config(usb_mode_prev, NULL);
|
||||||
|
furi_hal_ccid_set_callbacks(NULL);
|
||||||
|
|
||||||
|
//teardown view
|
||||||
|
ccid_test_app_free(app);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
37
applications/debug/ccid_test/iso7816_t0_apdu.c
Normal file
37
applications/debug/ccid_test/iso7816_t0_apdu.c
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
/* Implements rudimentary iso7816-3 support for APDU (T=0) */
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <furi.h>
|
||||||
|
#include "iso7816_t0_apdu.h"
|
||||||
|
|
||||||
|
void iso7816_answer_to_reset(uint8_t* dataBuffer, uint32_t* atrlen) {
|
||||||
|
//minimum valid ATR: https://smartcard-atr.apdu.fr/parse?ATR=3B+00
|
||||||
|
uint8_t AtrBuffer[2] = {
|
||||||
|
0x3B, //TS (direct convention)
|
||||||
|
0x00 // T0 (Y(1): b0000, K: 0 (historical bytes))
|
||||||
|
};
|
||||||
|
*atrlen = 2;
|
||||||
|
|
||||||
|
memcpy(dataBuffer, AtrBuffer, sizeof(uint8_t) * (*atrlen));
|
||||||
|
}
|
||||||
|
|
||||||
|
void iso7816_read_command_apdu(
|
||||||
|
struct ISO7816_Command_APDU* command,
|
||||||
|
const uint8_t* dataBuffer,
|
||||||
|
uint32_t dataLen) {
|
||||||
|
UNUSED(dataLen);
|
||||||
|
command->CLA = dataBuffer[0];
|
||||||
|
command->INS = dataBuffer[1];
|
||||||
|
command->P1 = dataBuffer[2];
|
||||||
|
command->P2 = dataBuffer[3];
|
||||||
|
command->Lc = dataBuffer[4];
|
||||||
|
}
|
||||||
|
|
||||||
|
void iso7816_write_response_apdu(
|
||||||
|
const struct ISO7816_Response_APDU* response,
|
||||||
|
uint8_t* dataBuffer,
|
||||||
|
uint32_t* dataLen) {
|
||||||
|
dataBuffer[0] = response->SW1;
|
||||||
|
dataBuffer[1] = response->SW2;
|
||||||
|
*dataLen = 2;
|
||||||
|
}
|
||||||
32
applications/debug/ccid_test/iso7816_t0_apdu.h
Normal file
32
applications/debug/ccid_test/iso7816_t0_apdu.h
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
#ifndef _ISO7816_T0_APDU_H_
|
||||||
|
#define _ISO7816_T0_APDU_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
struct ISO7816_Command_APDU {
|
||||||
|
//header
|
||||||
|
uint8_t CLA;
|
||||||
|
uint8_t INS;
|
||||||
|
uint8_t P1;
|
||||||
|
uint8_t P2;
|
||||||
|
|
||||||
|
//body
|
||||||
|
uint8_t Lc;
|
||||||
|
uint8_t Le;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
struct ISO7816_Response_APDU {
|
||||||
|
uint8_t SW1;
|
||||||
|
uint8_t SW2;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
void iso7816_answer_to_reset(uint8_t* atrBuffer, uint32_t* atrlen);
|
||||||
|
void iso7816_read_command_apdu(
|
||||||
|
struct ISO7816_Command_APDU* command,
|
||||||
|
const uint8_t* dataBuffer,
|
||||||
|
uint32_t dataLen);
|
||||||
|
void iso7816_write_response_apdu(
|
||||||
|
const struct ISO7816_Response_APDU* response,
|
||||||
|
uint8_t* dataBuffer,
|
||||||
|
uint32_t* dataLen);
|
||||||
|
#endif //_ISO7816_T0_APDU_H_
|
||||||
@@ -71,7 +71,7 @@ static void direct_draw_run(DirectDraw* instance) {
|
|||||||
size_t counter = 0;
|
size_t counter = 0;
|
||||||
float fps = 0;
|
float fps = 0;
|
||||||
|
|
||||||
vTaskPrioritySet(furi_thread_get_current_id(), FuriThreadPriorityIdle);
|
furi_thread_set_current_priority(FuriThreadPriorityIdle);
|
||||||
|
|
||||||
do {
|
do {
|
||||||
size_t elapsed = DWT->CYCCNT - start;
|
size_t elapsed = DWT->CYCCNT - start;
|
||||||
|
|||||||
@@ -21,22 +21,51 @@ static void rpc_debug_app_tick_event_callback(void* context) {
|
|||||||
scene_manager_handle_tick_event(app->scene_manager);
|
scene_manager_handle_tick_event(app->scene_manager);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void rpc_debug_app_rpc_command_callback(RpcAppSystemEvent event, void* context) {
|
static void
|
||||||
|
rpc_debug_app_format_hex(const uint8_t* data, size_t data_size, char* buf, size_t buf_size) {
|
||||||
|
if(data == NULL || data_size == 0) {
|
||||||
|
strncpy(buf, "<Data empty>", buf_size);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const size_t byte_width = 3;
|
||||||
|
const size_t line_width = 7;
|
||||||
|
|
||||||
|
data_size = MIN(data_size, buf_size / (byte_width + 1));
|
||||||
|
|
||||||
|
for(size_t i = 0; i < data_size; ++i) {
|
||||||
|
char* p = buf + (i * byte_width);
|
||||||
|
char sep = !((i + 1) % line_width) ? '\n' : ' ';
|
||||||
|
snprintf(p, byte_width + 1, "%02X%c", data[i], sep);
|
||||||
|
}
|
||||||
|
|
||||||
|
buf[buf_size - 1] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rpc_debug_app_rpc_command_callback(const RpcAppSystemEvent* event, void* context) {
|
||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
RpcDebugApp* app = context;
|
RpcDebugApp* app = context;
|
||||||
furi_assert(app->rpc);
|
furi_assert(app->rpc);
|
||||||
|
|
||||||
if(event == RpcAppEventSessionClose) {
|
if(event->type == RpcAppEventTypeSessionClose) {
|
||||||
scene_manager_stop(app->scene_manager);
|
scene_manager_stop(app->scene_manager);
|
||||||
view_dispatcher_stop(app->view_dispatcher);
|
view_dispatcher_stop(app->view_dispatcher);
|
||||||
rpc_system_app_set_callback(app->rpc, NULL, NULL);
|
rpc_system_app_set_callback(app->rpc, NULL, NULL);
|
||||||
app->rpc = NULL;
|
app->rpc = NULL;
|
||||||
} else if(event == RpcAppEventAppExit) {
|
} else if(event->type == RpcAppEventTypeAppExit) {
|
||||||
scene_manager_stop(app->scene_manager);
|
scene_manager_stop(app->scene_manager);
|
||||||
view_dispatcher_stop(app->view_dispatcher);
|
view_dispatcher_stop(app->view_dispatcher);
|
||||||
rpc_system_app_confirm(app->rpc, RpcAppEventAppExit, true);
|
rpc_system_app_confirm(app->rpc, true);
|
||||||
|
} else if(event->type == RpcAppEventTypeDataExchange) {
|
||||||
|
furi_assert(event->data.type == RpcAppSystemEventDataTypeBytes);
|
||||||
|
|
||||||
|
rpc_debug_app_format_hex(
|
||||||
|
event->data.bytes.ptr, event->data.bytes.size, app->text_store, TEXT_STORE_SIZE);
|
||||||
|
|
||||||
|
view_dispatcher_send_custom_event(
|
||||||
|
app->view_dispatcher, RpcDebugAppCustomEventRpcDataExchange);
|
||||||
} else {
|
} else {
|
||||||
rpc_system_app_confirm(app->rpc, event, false);
|
rpc_system_app_confirm(app->rpc, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,40 +1,5 @@
|
|||||||
#include "../rpc_debug_app.h"
|
#include "../rpc_debug_app.h"
|
||||||
|
|
||||||
static void rpc_debug_app_scene_start_format_hex(
|
|
||||||
const uint8_t* data,
|
|
||||||
size_t data_size,
|
|
||||||
char* buf,
|
|
||||||
size_t buf_size) {
|
|
||||||
furi_assert(data);
|
|
||||||
furi_assert(buf);
|
|
||||||
|
|
||||||
const size_t byte_width = 3;
|
|
||||||
const size_t line_width = 7;
|
|
||||||
|
|
||||||
data_size = MIN(data_size, buf_size / (byte_width + 1));
|
|
||||||
|
|
||||||
for(size_t i = 0; i < data_size; ++i) {
|
|
||||||
char* p = buf + (i * byte_width);
|
|
||||||
char sep = !((i + 1) % line_width) ? '\n' : ' ';
|
|
||||||
snprintf(p, byte_width + 1, "%02X%c", data[i], sep);
|
|
||||||
}
|
|
||||||
|
|
||||||
buf[buf_size - 1] = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
static void rpc_debug_app_scene_receive_data_exchange_callback(
|
|
||||||
const uint8_t* data,
|
|
||||||
size_t data_size,
|
|
||||||
void* context) {
|
|
||||||
RpcDebugApp* app = context;
|
|
||||||
if(data) {
|
|
||||||
rpc_debug_app_scene_start_format_hex(data, data_size, app->text_store, TEXT_STORE_SIZE);
|
|
||||||
} else {
|
|
||||||
strncpy(app->text_store, "<Data empty>", TEXT_STORE_SIZE);
|
|
||||||
}
|
|
||||||
view_dispatcher_send_custom_event(app->view_dispatcher, RpcDebugAppCustomEventRpcDataExchange);
|
|
||||||
}
|
|
||||||
|
|
||||||
void rpc_debug_app_scene_receive_data_exchange_on_enter(void* context) {
|
void rpc_debug_app_scene_receive_data_exchange_on_enter(void* context) {
|
||||||
RpcDebugApp* app = context;
|
RpcDebugApp* app = context;
|
||||||
strncpy(app->text_store, "Received data will appear here...", TEXT_STORE_SIZE);
|
strncpy(app->text_store, "Received data will appear here...", TEXT_STORE_SIZE);
|
||||||
@@ -42,8 +7,6 @@ void rpc_debug_app_scene_receive_data_exchange_on_enter(void* context) {
|
|||||||
text_box_set_text(app->text_box, app->text_store);
|
text_box_set_text(app->text_box, app->text_store);
|
||||||
text_box_set_font(app->text_box, TextBoxFontHex);
|
text_box_set_font(app->text_box, TextBoxFontHex);
|
||||||
|
|
||||||
rpc_system_app_set_data_exchange_callback(
|
|
||||||
app->rpc, rpc_debug_app_scene_receive_data_exchange_callback, app);
|
|
||||||
view_dispatcher_switch_to_view(app->view_dispatcher, RpcDebugAppViewTextBox);
|
view_dispatcher_switch_to_view(app->view_dispatcher, RpcDebugAppViewTextBox);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,6 +16,7 @@ bool rpc_debug_app_scene_receive_data_exchange_on_event(void* context, SceneMana
|
|||||||
|
|
||||||
if(event.type == SceneManagerEventTypeCustom) {
|
if(event.type == SceneManagerEventTypeCustom) {
|
||||||
if(event.event == RpcDebugAppCustomEventRpcDataExchange) {
|
if(event.event == RpcDebugAppCustomEventRpcDataExchange) {
|
||||||
|
rpc_system_app_confirm(app->rpc, true);
|
||||||
notification_message(app->notifications, &sequence_blink_cyan_100);
|
notification_message(app->notifications, &sequence_blink_cyan_100);
|
||||||
notification_message(app->notifications, &sequence_display_backlight_on);
|
notification_message(app->notifications, &sequence_display_backlight_on);
|
||||||
text_box_set_text(app->text_box, app->text_store);
|
text_box_set_text(app->text_box, app->text_store);
|
||||||
@@ -66,5 +30,4 @@ bool rpc_debug_app_scene_receive_data_exchange_on_event(void* context, SceneMana
|
|||||||
void rpc_debug_app_scene_receive_data_exchange_on_exit(void* context) {
|
void rpc_debug_app_scene_receive_data_exchange_on_exit(void* context) {
|
||||||
RpcDebugApp* app = context;
|
RpcDebugApp* app = context;
|
||||||
text_box_reset(app->text_box);
|
text_box_reset(app->text_box);
|
||||||
rpc_system_app_set_data_exchange_callback(app->rpc, NULL, NULL);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ App(
|
|||||||
cdefines=["APP_UNIT_TESTS"],
|
cdefines=["APP_UNIT_TESTS"],
|
||||||
requires=["system_settings"],
|
requires=["system_settings"],
|
||||||
provides=["delay_test"],
|
provides=["delay_test"],
|
||||||
|
resources="resources",
|
||||||
order=100,
|
order=100,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ void bt_test_alloc() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void bt_test_free() {
|
void bt_test_free() {
|
||||||
furi_assert(bt_test);
|
furi_check(bt_test);
|
||||||
free(bt_test->nvm_ram_buff_ref);
|
free(bt_test->nvm_ram_buff_ref);
|
||||||
free(bt_test->nvm_ram_buff_dut);
|
free(bt_test->nvm_ram_buff_dut);
|
||||||
bt_keys_storage_free(bt_test->bt_keys_storage);
|
bt_keys_storage_free(bt_test->bt_keys_storage);
|
||||||
@@ -89,7 +89,7 @@ static void bt_test_keys_remove_test_file() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
MU_TEST(bt_test_keys_storage_serial_profile) {
|
MU_TEST(bt_test_keys_storage_serial_profile) {
|
||||||
furi_assert(bt_test);
|
furi_check(bt_test);
|
||||||
|
|
||||||
bt_test_keys_remove_test_file();
|
bt_test_keys_remove_test_file();
|
||||||
bt_test_keys_storage_profile();
|
bt_test_keys_storage_profile();
|
||||||
|
|||||||
@@ -5,6 +5,11 @@
|
|||||||
#include "../minunit.h"
|
#include "../minunit.h"
|
||||||
|
|
||||||
#define DATA_SIZE 4
|
#define DATA_SIZE 4
|
||||||
|
#define EEPROM_ADDRESS 0b10101000
|
||||||
|
#define EEPROM_ADDRESS_HIGH (EEPROM_ADDRESS | 0b10)
|
||||||
|
#define EEPROM_SIZE 512
|
||||||
|
#define EEPROM_PAGE_SIZE 16
|
||||||
|
#define EEPROM_WRITE_DELAY_MS 6
|
||||||
|
|
||||||
static void furi_hal_i2c_int_setup() {
|
static void furi_hal_i2c_int_setup() {
|
||||||
furi_hal_i2c_acquire(&furi_hal_i2c_handle_power);
|
furi_hal_i2c_acquire(&furi_hal_i2c_handle_power);
|
||||||
@@ -14,6 +19,14 @@ static void furi_hal_i2c_int_teardown() {
|
|||||||
furi_hal_i2c_release(&furi_hal_i2c_handle_power);
|
furi_hal_i2c_release(&furi_hal_i2c_handle_power);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void furi_hal_i2c_ext_setup() {
|
||||||
|
furi_hal_i2c_acquire(&furi_hal_i2c_handle_external);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void furi_hal_i2c_ext_teardown() {
|
||||||
|
furi_hal_i2c_release(&furi_hal_i2c_handle_external);
|
||||||
|
}
|
||||||
|
|
||||||
MU_TEST(furi_hal_i2c_int_1b) {
|
MU_TEST(furi_hal_i2c_int_1b) {
|
||||||
bool ret = false;
|
bool ret = false;
|
||||||
uint8_t data_one = 0;
|
uint8_t data_one = 0;
|
||||||
@@ -103,14 +116,116 @@ MU_TEST(furi_hal_i2c_int_1b_fail) {
|
|||||||
mu_assert(data_one != 0, "9 invalid data");
|
mu_assert(data_one != 0, "9 invalid data");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MU_TEST(furi_hal_i2c_int_ext_3b) {
|
||||||
|
bool ret = false;
|
||||||
|
uint8_t data_many[DATA_SIZE] = {0};
|
||||||
|
|
||||||
|
// 3 byte: read
|
||||||
|
data_many[0] = LP5562_CHANNEL_BLUE_CURRENT_REGISTER;
|
||||||
|
ret = furi_hal_i2c_tx_ext(
|
||||||
|
&furi_hal_i2c_handle_power,
|
||||||
|
LP5562_ADDRESS,
|
||||||
|
false,
|
||||||
|
data_many,
|
||||||
|
1,
|
||||||
|
FuriHalI2cBeginStart,
|
||||||
|
FuriHalI2cEndAwaitRestart,
|
||||||
|
LP5562_I2C_TIMEOUT);
|
||||||
|
mu_assert(ret, "3 tx failed");
|
||||||
|
|
||||||
|
// Send a RESTART condition, then read the 3 bytes one after the other
|
||||||
|
ret = furi_hal_i2c_rx_ext(
|
||||||
|
&furi_hal_i2c_handle_power,
|
||||||
|
LP5562_ADDRESS,
|
||||||
|
false,
|
||||||
|
data_many + 1,
|
||||||
|
1,
|
||||||
|
FuriHalI2cBeginRestart,
|
||||||
|
FuriHalI2cEndPause,
|
||||||
|
LP5562_I2C_TIMEOUT);
|
||||||
|
mu_assert(ret, "4 rx failed");
|
||||||
|
mu_assert(data_many[1] != 0, "4 invalid data");
|
||||||
|
ret = furi_hal_i2c_rx_ext(
|
||||||
|
&furi_hal_i2c_handle_power,
|
||||||
|
LP5562_ADDRESS,
|
||||||
|
false,
|
||||||
|
data_many + 2,
|
||||||
|
1,
|
||||||
|
FuriHalI2cBeginResume,
|
||||||
|
FuriHalI2cEndPause,
|
||||||
|
LP5562_I2C_TIMEOUT);
|
||||||
|
mu_assert(ret, "5 rx failed");
|
||||||
|
mu_assert(data_many[2] != 0, "5 invalid data");
|
||||||
|
ret = furi_hal_i2c_rx_ext(
|
||||||
|
&furi_hal_i2c_handle_power,
|
||||||
|
LP5562_ADDRESS,
|
||||||
|
false,
|
||||||
|
data_many + 3,
|
||||||
|
1,
|
||||||
|
FuriHalI2cBeginResume,
|
||||||
|
FuriHalI2cEndStop,
|
||||||
|
LP5562_I2C_TIMEOUT);
|
||||||
|
mu_assert(ret, "6 rx failed");
|
||||||
|
mu_assert(data_many[3] != 0, "6 invalid data");
|
||||||
|
}
|
||||||
|
|
||||||
|
MU_TEST(furi_hal_i2c_ext_eeprom) {
|
||||||
|
if(!furi_hal_i2c_is_device_ready(&furi_hal_i2c_handle_external, EEPROM_ADDRESS, 100)) {
|
||||||
|
printf("no device connected, skipping\r\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ret = false;
|
||||||
|
uint8_t buffer[EEPROM_SIZE] = {0};
|
||||||
|
|
||||||
|
for(size_t page = 0; page < (EEPROM_SIZE / EEPROM_PAGE_SIZE); ++page) {
|
||||||
|
// Fill page buffer
|
||||||
|
for(size_t page_byte = 0; page_byte < EEPROM_PAGE_SIZE; ++page_byte) {
|
||||||
|
// Each byte is its position in the EEPROM modulo 256
|
||||||
|
uint8_t byte = ((page * EEPROM_PAGE_SIZE) + page_byte) % 256;
|
||||||
|
|
||||||
|
buffer[page_byte] = byte;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t address = (page < 16) ? EEPROM_ADDRESS : EEPROM_ADDRESS_HIGH;
|
||||||
|
|
||||||
|
ret = furi_hal_i2c_write_mem(
|
||||||
|
&furi_hal_i2c_handle_external,
|
||||||
|
address,
|
||||||
|
page * EEPROM_PAGE_SIZE,
|
||||||
|
buffer,
|
||||||
|
EEPROM_PAGE_SIZE,
|
||||||
|
20);
|
||||||
|
|
||||||
|
mu_assert(ret, "EEPROM write failed");
|
||||||
|
furi_delay_ms(EEPROM_WRITE_DELAY_MS);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = furi_hal_i2c_read_mem(
|
||||||
|
&furi_hal_i2c_handle_external, EEPROM_ADDRESS, 0, buffer, EEPROM_SIZE, 100);
|
||||||
|
|
||||||
|
mu_assert(ret, "EEPROM read failed");
|
||||||
|
|
||||||
|
for(size_t pos = 0; pos < EEPROM_SIZE; ++pos) {
|
||||||
|
mu_assert_int_eq(pos % 256, buffer[pos]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
MU_TEST_SUITE(furi_hal_i2c_int_suite) {
|
MU_TEST_SUITE(furi_hal_i2c_int_suite) {
|
||||||
MU_SUITE_CONFIGURE(&furi_hal_i2c_int_setup, &furi_hal_i2c_int_teardown);
|
MU_SUITE_CONFIGURE(&furi_hal_i2c_int_setup, &furi_hal_i2c_int_teardown);
|
||||||
MU_RUN_TEST(furi_hal_i2c_int_1b);
|
MU_RUN_TEST(furi_hal_i2c_int_1b);
|
||||||
MU_RUN_TEST(furi_hal_i2c_int_3b);
|
MU_RUN_TEST(furi_hal_i2c_int_3b);
|
||||||
|
MU_RUN_TEST(furi_hal_i2c_int_ext_3b);
|
||||||
MU_RUN_TEST(furi_hal_i2c_int_1b_fail);
|
MU_RUN_TEST(furi_hal_i2c_int_1b_fail);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MU_TEST_SUITE(furi_hal_i2c_ext_suite) {
|
||||||
|
MU_SUITE_CONFIGURE(&furi_hal_i2c_ext_setup, &furi_hal_i2c_ext_teardown);
|
||||||
|
MU_RUN_TEST(furi_hal_i2c_ext_eeprom);
|
||||||
|
}
|
||||||
|
|
||||||
int run_minunit_test_furi_hal() {
|
int run_minunit_test_furi_hal() {
|
||||||
MU_RUN_SUITE(furi_hal_i2c_int_suite);
|
MU_RUN_SUITE(furi_hal_i2c_int_suite);
|
||||||
|
MU_RUN_SUITE(furi_hal_i2c_ext_suite);
|
||||||
return MU_EXIT_CODE;
|
return MU_EXIT_CODE;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ static void infrared_test_alloc() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void infrared_test_free() {
|
static void infrared_test_free() {
|
||||||
furi_assert(test);
|
furi_check(test);
|
||||||
infrared_free_decoder(test->decoder_handler);
|
infrared_free_decoder(test->decoder_handler);
|
||||||
infrared_free_encoder(test->encoder_handler);
|
infrared_free_encoder(test->encoder_handler);
|
||||||
flipper_format_free(test->ff);
|
flipper_format_free(test->ff);
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ MU_TEST(manifest_iteration_test) {
|
|||||||
ResourceManifestReader* manifest_reader = resource_manifest_reader_alloc(storage);
|
ResourceManifestReader* manifest_reader = resource_manifest_reader_alloc(storage);
|
||||||
do {
|
do {
|
||||||
// Open manifest file
|
// Open manifest file
|
||||||
if(!resource_manifest_reader_open(manifest_reader, EXT_PATH("unit_tests/Manifest"))) {
|
if(!resource_manifest_reader_open(manifest_reader, EXT_PATH("unit_tests/Manifest_test"))) {
|
||||||
result = false;
|
result = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
458
applications/debug/unit_tests/nfc/nfc_transport.c
Normal file
458
applications/debug/unit_tests/nfc/nfc_transport.c
Normal file
@@ -0,0 +1,458 @@
|
|||||||
|
#ifdef FW_CFG_unit_tests
|
||||||
|
|
||||||
|
#include <lib/nfc/nfc.h>
|
||||||
|
#include <lib/nfc/helpers/iso14443_crc.h>
|
||||||
|
#include <lib/nfc/protocols/iso14443_3a/iso14443_3a.h>
|
||||||
|
|
||||||
|
#include <furi/furi.h>
|
||||||
|
|
||||||
|
#define NFC_MAX_BUFFER_SIZE (256)
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
NfcTransportLogLevelWarning,
|
||||||
|
NfcTransportLogLevelInfo,
|
||||||
|
} NfcTransportLogLevel;
|
||||||
|
|
||||||
|
FuriMessageQueue* poller_queue = NULL;
|
||||||
|
FuriMessageQueue* listener_queue = NULL;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
NfcMessageTypeTx,
|
||||||
|
NfcMessageTypeTimeout,
|
||||||
|
NfcMessageTypeAbort,
|
||||||
|
} NfcMessageType;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint16_t data_bits;
|
||||||
|
uint8_t data[NFC_MAX_BUFFER_SIZE];
|
||||||
|
} NfcMessageData;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
NfcMessageType type;
|
||||||
|
NfcMessageData data;
|
||||||
|
} NfcMessage;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
NfcStateIdle,
|
||||||
|
NfcStateReady,
|
||||||
|
NfcStateReset,
|
||||||
|
} NfcState;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
Iso14443_3aColResStatusIdle,
|
||||||
|
Iso14443_3aColResStatusInProgress,
|
||||||
|
Iso14443_3aColResStatusDone,
|
||||||
|
} Iso14443_3aColResStatus;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
Iso14443_3aSensResp sens_resp;
|
||||||
|
Iso14443_3aSddResp sdd_resp[2];
|
||||||
|
Iso14443_3aSelResp sel_resp[2];
|
||||||
|
} Iso14443_3aColResData;
|
||||||
|
|
||||||
|
struct Nfc {
|
||||||
|
NfcState state;
|
||||||
|
|
||||||
|
Iso14443_3aColResStatus col_res_status;
|
||||||
|
Iso14443_3aColResData col_res_data;
|
||||||
|
|
||||||
|
NfcEventCallback callback;
|
||||||
|
void* context;
|
||||||
|
|
||||||
|
NfcMode mode;
|
||||||
|
|
||||||
|
FuriThread* worker_thread;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void nfc_test_print(
|
||||||
|
NfcTransportLogLevel log_level,
|
||||||
|
const char* message,
|
||||||
|
uint8_t* buffer,
|
||||||
|
uint16_t bits) {
|
||||||
|
FuriString* str = furi_string_alloc();
|
||||||
|
size_t bytes = (bits + 7) / 8;
|
||||||
|
|
||||||
|
for(size_t i = 0; i < bytes; i++) {
|
||||||
|
furi_string_cat_printf(str, " %02X", buffer[i]);
|
||||||
|
}
|
||||||
|
if(log_level == NfcTransportLogLevelWarning) {
|
||||||
|
FURI_LOG_W(message, "%s", furi_string_get_cstr(str));
|
||||||
|
} else {
|
||||||
|
FURI_LOG_I(message, "%s", furi_string_get_cstr(str));
|
||||||
|
}
|
||||||
|
|
||||||
|
furi_string_free(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void nfc_prepare_col_res_data(
|
||||||
|
Nfc* instance,
|
||||||
|
uint8_t* uid,
|
||||||
|
uint8_t uid_len,
|
||||||
|
uint8_t* atqa,
|
||||||
|
uint8_t sak) {
|
||||||
|
memcpy(instance->col_res_data.sens_resp.sens_resp, atqa, 2);
|
||||||
|
|
||||||
|
if(uid_len == 7) {
|
||||||
|
instance->col_res_data.sdd_resp[0].nfcid[0] = 0x88;
|
||||||
|
memcpy(&instance->col_res_data.sdd_resp[0].nfcid[1], uid, 3);
|
||||||
|
uint8_t bss = 0;
|
||||||
|
for(size_t i = 0; i < 4; i++) {
|
||||||
|
bss ^= instance->col_res_data.sdd_resp[0].nfcid[i];
|
||||||
|
}
|
||||||
|
instance->col_res_data.sdd_resp[0].bss = bss;
|
||||||
|
instance->col_res_data.sel_resp[0].sak = 0x04;
|
||||||
|
|
||||||
|
memcpy(instance->col_res_data.sdd_resp[1].nfcid, &uid[3], 4);
|
||||||
|
bss = 0;
|
||||||
|
for(size_t i = 0; i < 4; i++) {
|
||||||
|
bss ^= instance->col_res_data.sdd_resp[1].nfcid[i];
|
||||||
|
}
|
||||||
|
instance->col_res_data.sdd_resp[1].bss = bss;
|
||||||
|
instance->col_res_data.sel_resp[1].sak = sak;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
furi_crash("Not supporting not 7 bytes");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Nfc* nfc_alloc() {
|
||||||
|
Nfc* instance = malloc(sizeof(Nfc));
|
||||||
|
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nfc_free(Nfc* instance) {
|
||||||
|
furi_check(instance);
|
||||||
|
|
||||||
|
free(instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
void nfc_config(Nfc* instance, NfcMode mode, NfcTech tech) {
|
||||||
|
UNUSED(instance);
|
||||||
|
UNUSED(tech);
|
||||||
|
|
||||||
|
instance->mode = mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nfc_set_fdt_poll_fc(Nfc* instance, uint32_t fdt_poll_fc) {
|
||||||
|
UNUSED(instance);
|
||||||
|
UNUSED(fdt_poll_fc);
|
||||||
|
}
|
||||||
|
|
||||||
|
void nfc_set_fdt_listen_fc(Nfc* instance, uint32_t fdt_listen_fc) {
|
||||||
|
UNUSED(instance);
|
||||||
|
UNUSED(fdt_listen_fc);
|
||||||
|
}
|
||||||
|
|
||||||
|
void nfc_set_mask_receive_time_fc(Nfc* instance, uint32_t mask_rx_time_fc) {
|
||||||
|
UNUSED(instance);
|
||||||
|
UNUSED(mask_rx_time_fc);
|
||||||
|
}
|
||||||
|
|
||||||
|
void nfc_set_fdt_poll_poll_us(Nfc* instance, uint32_t fdt_poll_poll_us) {
|
||||||
|
UNUSED(instance);
|
||||||
|
UNUSED(fdt_poll_poll_us);
|
||||||
|
}
|
||||||
|
|
||||||
|
void nfc_set_guard_time_us(Nfc* instance, uint32_t guard_time_us) {
|
||||||
|
UNUSED(instance);
|
||||||
|
UNUSED(guard_time_us);
|
||||||
|
}
|
||||||
|
|
||||||
|
NfcError nfc_iso14443a_listener_set_col_res_data(
|
||||||
|
Nfc* instance,
|
||||||
|
uint8_t* uid,
|
||||||
|
uint8_t uid_len,
|
||||||
|
uint8_t* atqa,
|
||||||
|
uint8_t sak) {
|
||||||
|
furi_check(instance);
|
||||||
|
furi_check(uid);
|
||||||
|
furi_check(atqa);
|
||||||
|
|
||||||
|
nfc_prepare_col_res_data(instance, uid, uid_len, atqa, sak);
|
||||||
|
|
||||||
|
return NfcErrorNone;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t nfc_worker_poller(void* context) {
|
||||||
|
Nfc* instance = context;
|
||||||
|
furi_check(instance->callback);
|
||||||
|
|
||||||
|
instance->state = NfcStateReady;
|
||||||
|
NfcCommand command = NfcCommandContinue;
|
||||||
|
NfcEvent event = {};
|
||||||
|
|
||||||
|
while(true) {
|
||||||
|
event.type = NfcEventTypePollerReady;
|
||||||
|
command = instance->callback(event, instance->context);
|
||||||
|
if(command == NfcCommandStop) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
instance->state = NfcStateIdle;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void nfc_worker_listener_pass_col_res(Nfc* instance, uint8_t* rx_data, uint16_t rx_bits) {
|
||||||
|
furi_check(instance->col_res_status != Iso14443_3aColResStatusDone);
|
||||||
|
BitBuffer* tx_buffer = bit_buffer_alloc(NFC_MAX_BUFFER_SIZE);
|
||||||
|
|
||||||
|
bool processed = false;
|
||||||
|
|
||||||
|
if((rx_bits == 7) && (rx_data[0] == 0x52)) {
|
||||||
|
instance->col_res_status = Iso14443_3aColResStatusInProgress;
|
||||||
|
bit_buffer_copy_bytes(
|
||||||
|
tx_buffer,
|
||||||
|
instance->col_res_data.sens_resp.sens_resp,
|
||||||
|
sizeof(instance->col_res_data.sens_resp.sens_resp));
|
||||||
|
nfc_listener_tx(instance, tx_buffer);
|
||||||
|
processed = true;
|
||||||
|
} else if(rx_bits == 2 * 8) {
|
||||||
|
if((rx_data[0] == 0x93) && (rx_data[1] == 0x20)) {
|
||||||
|
bit_buffer_copy_bytes(
|
||||||
|
tx_buffer,
|
||||||
|
(const uint8_t*)&instance->col_res_data.sdd_resp[0],
|
||||||
|
sizeof(Iso14443_3aSddResp));
|
||||||
|
nfc_listener_tx(instance, tx_buffer);
|
||||||
|
processed = true;
|
||||||
|
} else if((rx_data[0] == 0x95) && (rx_data[1] == 0x20)) {
|
||||||
|
bit_buffer_copy_bytes(
|
||||||
|
tx_buffer,
|
||||||
|
(const uint8_t*)&instance->col_res_data.sdd_resp[1],
|
||||||
|
sizeof(Iso14443_3aSddResp));
|
||||||
|
nfc_listener_tx(instance, tx_buffer);
|
||||||
|
processed = true;
|
||||||
|
}
|
||||||
|
} else if(rx_bits == 9 * 8) {
|
||||||
|
if((rx_data[0] == 0x93) && (rx_data[1] == 0x70)) {
|
||||||
|
bit_buffer_set_size_bytes(tx_buffer, 1);
|
||||||
|
bit_buffer_set_byte(tx_buffer, 0, instance->col_res_data.sel_resp[0].sak);
|
||||||
|
iso14443_crc_append(Iso14443CrcTypeA, tx_buffer);
|
||||||
|
nfc_listener_tx(instance, tx_buffer);
|
||||||
|
processed = true;
|
||||||
|
} else if((rx_data[0] == 0x95) && (rx_data[1] == 0x70)) {
|
||||||
|
bit_buffer_set_size_bytes(tx_buffer, 1);
|
||||||
|
bit_buffer_set_byte(tx_buffer, 0, instance->col_res_data.sel_resp[1].sak);
|
||||||
|
iso14443_crc_append(Iso14443CrcTypeA, tx_buffer);
|
||||||
|
nfc_listener_tx(instance, tx_buffer);
|
||||||
|
instance->col_res_status = Iso14443_3aColResStatusDone;
|
||||||
|
NfcEvent event = {.type = NfcEventTypeListenerActivated};
|
||||||
|
instance->callback(event, instance->context);
|
||||||
|
|
||||||
|
processed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!processed) {
|
||||||
|
NfcMessage message = {.type = NfcMessageTypeTimeout};
|
||||||
|
furi_message_queue_put(poller_queue, &message, FuriWaitForever);
|
||||||
|
}
|
||||||
|
|
||||||
|
bit_buffer_free(tx_buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t nfc_worker_listener(void* context) {
|
||||||
|
Nfc* instance = context;
|
||||||
|
furi_check(instance->callback);
|
||||||
|
|
||||||
|
NfcMessage message = {};
|
||||||
|
|
||||||
|
NfcEventData event_data = {};
|
||||||
|
event_data.buffer = bit_buffer_alloc(NFC_MAX_BUFFER_SIZE);
|
||||||
|
NfcEvent nfc_event = {.data = event_data};
|
||||||
|
|
||||||
|
while(true) {
|
||||||
|
furi_message_queue_get(listener_queue, &message, FuriWaitForever);
|
||||||
|
bit_buffer_copy_bits(event_data.buffer, message.data.data, message.data.data_bits);
|
||||||
|
if((message.data.data[0] == 0x52) && (message.data.data_bits == 7)) {
|
||||||
|
instance->col_res_status = Iso14443_3aColResStatusIdle;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(message.type == NfcMessageTypeAbort) {
|
||||||
|
break;
|
||||||
|
} else if(message.type == NfcMessageTypeTx) {
|
||||||
|
nfc_test_print(
|
||||||
|
NfcTransportLogLevelInfo, "RDR", message.data.data, message.data.data_bits);
|
||||||
|
if(instance->col_res_status != Iso14443_3aColResStatusDone) {
|
||||||
|
nfc_worker_listener_pass_col_res(
|
||||||
|
instance, message.data.data, message.data.data_bits);
|
||||||
|
} else {
|
||||||
|
instance->state = NfcStateReady;
|
||||||
|
nfc_event.type = NfcEventTypeRxEnd;
|
||||||
|
instance->callback(nfc_event, instance->context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
instance->state = NfcStateIdle;
|
||||||
|
instance->col_res_status = Iso14443_3aColResStatusIdle;
|
||||||
|
memset(&instance->col_res_data, 0, sizeof(instance->col_res_data));
|
||||||
|
bit_buffer_free(nfc_event.data.buffer);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nfc_start(Nfc* instance, NfcEventCallback callback, void* context) {
|
||||||
|
furi_check(instance);
|
||||||
|
furi_check(instance->worker_thread == NULL);
|
||||||
|
|
||||||
|
if(instance->mode == NfcModeListener) {
|
||||||
|
furi_check(listener_queue == NULL);
|
||||||
|
// Check that poller didn't start
|
||||||
|
furi_check(poller_queue == NULL);
|
||||||
|
} else {
|
||||||
|
furi_check(poller_queue == NULL);
|
||||||
|
// Check that poller is started after listener
|
||||||
|
furi_check(listener_queue);
|
||||||
|
}
|
||||||
|
|
||||||
|
instance->callback = callback;
|
||||||
|
instance->context = context;
|
||||||
|
|
||||||
|
if(instance->mode == NfcModeListener) {
|
||||||
|
listener_queue = furi_message_queue_alloc(4, sizeof(NfcMessage));
|
||||||
|
} else {
|
||||||
|
poller_queue = furi_message_queue_alloc(4, sizeof(NfcMessage));
|
||||||
|
}
|
||||||
|
|
||||||
|
instance->worker_thread = furi_thread_alloc();
|
||||||
|
furi_thread_set_context(instance->worker_thread, instance);
|
||||||
|
furi_thread_set_priority(instance->worker_thread, FuriThreadPriorityHigh);
|
||||||
|
furi_thread_set_stack_size(instance->worker_thread, 8 * 1024);
|
||||||
|
|
||||||
|
if(instance->mode == NfcModeListener) {
|
||||||
|
furi_thread_set_name(instance->worker_thread, "NfcWorkerListener");
|
||||||
|
furi_thread_set_callback(instance->worker_thread, nfc_worker_listener);
|
||||||
|
} else {
|
||||||
|
furi_thread_set_name(instance->worker_thread, "NfcWorkerPoller");
|
||||||
|
furi_thread_set_callback(instance->worker_thread, nfc_worker_poller);
|
||||||
|
}
|
||||||
|
|
||||||
|
furi_thread_start(instance->worker_thread);
|
||||||
|
}
|
||||||
|
|
||||||
|
void nfc_stop(Nfc* instance) {
|
||||||
|
furi_check(instance);
|
||||||
|
furi_check(instance->worker_thread);
|
||||||
|
|
||||||
|
if(instance->mode == NfcModeListener) {
|
||||||
|
NfcMessage message = {.type = NfcMessageTypeAbort};
|
||||||
|
furi_message_queue_put(listener_queue, &message, FuriWaitForever);
|
||||||
|
furi_thread_join(instance->worker_thread);
|
||||||
|
|
||||||
|
furi_message_queue_free(listener_queue);
|
||||||
|
listener_queue = NULL;
|
||||||
|
|
||||||
|
furi_thread_free(instance->worker_thread);
|
||||||
|
instance->worker_thread = NULL;
|
||||||
|
} else {
|
||||||
|
furi_thread_join(instance->worker_thread);
|
||||||
|
|
||||||
|
furi_message_queue_free(poller_queue);
|
||||||
|
poller_queue = NULL;
|
||||||
|
|
||||||
|
furi_thread_free(instance->worker_thread);
|
||||||
|
instance->worker_thread = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called from worker thread
|
||||||
|
|
||||||
|
NfcError nfc_listener_tx(Nfc* instance, const BitBuffer* tx_buffer) {
|
||||||
|
furi_check(instance);
|
||||||
|
furi_check(poller_queue);
|
||||||
|
furi_check(listener_queue);
|
||||||
|
furi_check(tx_buffer);
|
||||||
|
|
||||||
|
NfcMessage message = {};
|
||||||
|
message.type = NfcMessageTypeTx;
|
||||||
|
message.data.data_bits = bit_buffer_get_size(tx_buffer);
|
||||||
|
bit_buffer_write_bytes(tx_buffer, message.data.data, bit_buffer_get_size_bytes(tx_buffer));
|
||||||
|
|
||||||
|
furi_message_queue_put(poller_queue, &message, FuriWaitForever);
|
||||||
|
|
||||||
|
return NfcErrorNone;
|
||||||
|
}
|
||||||
|
|
||||||
|
NfcError nfc_iso14443a_listener_tx_custom_parity(Nfc* instance, const BitBuffer* tx_buffer) {
|
||||||
|
return nfc_listener_tx(instance, tx_buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
NfcError
|
||||||
|
nfc_poller_trx(Nfc* instance, const BitBuffer* tx_buffer, BitBuffer* rx_buffer, uint32_t fwt) {
|
||||||
|
furi_check(instance);
|
||||||
|
furi_check(tx_buffer);
|
||||||
|
furi_check(rx_buffer);
|
||||||
|
furi_check(poller_queue);
|
||||||
|
furi_check(listener_queue);
|
||||||
|
UNUSED(fwt);
|
||||||
|
|
||||||
|
NfcError error = NfcErrorNone;
|
||||||
|
|
||||||
|
NfcMessage message = {};
|
||||||
|
message.type = NfcMessageTypeTx;
|
||||||
|
message.data.data_bits = bit_buffer_get_size(tx_buffer);
|
||||||
|
bit_buffer_write_bytes(tx_buffer, message.data.data, bit_buffer_get_size_bytes(tx_buffer));
|
||||||
|
// Tx
|
||||||
|
furi_check(furi_message_queue_put(listener_queue, &message, FuriWaitForever) == FuriStatusOk);
|
||||||
|
// Rx
|
||||||
|
FuriStatus status = furi_message_queue_get(poller_queue, &message, 50);
|
||||||
|
|
||||||
|
if(status == FuriStatusErrorTimeout) {
|
||||||
|
error = NfcErrorTimeout;
|
||||||
|
} else if(message.type == NfcMessageTypeTx) {
|
||||||
|
bit_buffer_copy_bits(rx_buffer, message.data.data, message.data.data_bits);
|
||||||
|
nfc_test_print(
|
||||||
|
NfcTransportLogLevelWarning, "TAG", message.data.data, message.data.data_bits);
|
||||||
|
} else if(message.type == NfcMessageTypeTimeout) {
|
||||||
|
error = NfcErrorTimeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
NfcError nfc_iso14443a_poller_trx_custom_parity(
|
||||||
|
Nfc* instance,
|
||||||
|
const BitBuffer* tx_buffer,
|
||||||
|
BitBuffer* rx_buffer,
|
||||||
|
uint32_t fwt) {
|
||||||
|
return nfc_poller_trx(instance, tx_buffer, rx_buffer, fwt);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Technology specific API
|
||||||
|
|
||||||
|
NfcError nfc_iso14443a_poller_trx_short_frame(
|
||||||
|
Nfc* instance,
|
||||||
|
NfcIso14443aShortFrame frame,
|
||||||
|
BitBuffer* rx_buffer,
|
||||||
|
uint32_t fwt) {
|
||||||
|
UNUSED(frame);
|
||||||
|
|
||||||
|
BitBuffer* tx_buffer = bit_buffer_alloc(32);
|
||||||
|
bit_buffer_set_size(tx_buffer, 7);
|
||||||
|
bit_buffer_set_byte(tx_buffer, 0, 0x52);
|
||||||
|
|
||||||
|
NfcError error = nfc_poller_trx(instance, tx_buffer, rx_buffer, fwt);
|
||||||
|
|
||||||
|
bit_buffer_free(tx_buffer);
|
||||||
|
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
NfcError nfc_iso14443a_poller_trx_sdd_frame(
|
||||||
|
Nfc* instance,
|
||||||
|
const BitBuffer* tx_buffer,
|
||||||
|
BitBuffer* rx_buffer,
|
||||||
|
uint32_t fwt) {
|
||||||
|
return nfc_poller_trx(instance, tx_buffer, rx_buffer, fwt);
|
||||||
|
}
|
||||||
|
|
||||||
|
NfcError nfc_iso15693_listener_tx_sof(Nfc* instance) {
|
||||||
|
UNUSED(instance);
|
||||||
|
|
||||||
|
return NfcErrorNone;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
Filetype: Flipper NFC device
|
||||||
|
Version: 3
|
||||||
|
# Nfc device type can be UID, Mifare Ultralight, Mifare Classic
|
||||||
|
Device type: NTAG213
|
||||||
|
# UID, ATQA and SAK are common for all formats
|
||||||
|
UID: 04 AC 6B 72 BA 6C 80
|
||||||
|
ATQA: 00 44
|
||||||
|
SAK: 00
|
||||||
|
# Mifare Ultralight specific data
|
||||||
|
Data format version: 1
|
||||||
|
Signature: 2D AE BC AF 84 B8 85 87 C2 FB FE 76 13 58 86 72 8E 1D 3C B5 DA 24 23 44 E5 63 4D 4C 82 FB D7 18
|
||||||
|
Mifare version: 00 04 04 02 01 00 0F 03
|
||||||
|
Counter 0: 0
|
||||||
|
Tearing 0: 00
|
||||||
|
Counter 1: 0
|
||||||
|
Tearing 1: 00
|
||||||
|
Counter 2: 0
|
||||||
|
Tearing 2: 00
|
||||||
|
Pages total: 45
|
||||||
|
Pages read: 45
|
||||||
|
Page 0: 04 AC 6B 4B
|
||||||
|
Page 1: 72 BA 6C 80
|
||||||
|
Page 2: 24 48 00 00
|
||||||
|
Page 3: E1 10 12 00
|
||||||
|
Page 4: 00 00 41 50
|
||||||
|
Page 5: 00 00 31 31
|
||||||
|
Page 6: 00 20 09 28
|
||||||
|
Page 7: 00 03 31 59
|
||||||
|
Page 8: 91 DF D3 00
|
||||||
|
Page 9: 00 00 00 00
|
||||||
|
Page 10: 00 00 00 00
|
||||||
|
Page 11: 00 00 00 00
|
||||||
|
Page 12: 00 00 00 00
|
||||||
|
Page 13: 00 00 00 00
|
||||||
|
Page 14: 00 00 00 00
|
||||||
|
Page 15: 00 00 00 00
|
||||||
|
Page 16: 00 00 00 00
|
||||||
|
Page 17: 00 00 00 00
|
||||||
|
Page 18: 00 00 00 00
|
||||||
|
Page 19: 00 00 00 00
|
||||||
|
Page 20: 00 00 00 00
|
||||||
|
Page 21: 00 00 00 00
|
||||||
|
Page 22: 00 00 00 00
|
||||||
|
Page 23: 00 00 00 00
|
||||||
|
Page 24: 00 00 00 00
|
||||||
|
Page 25: 00 00 00 00
|
||||||
|
Page 26: 00 00 00 00
|
||||||
|
Page 27: 00 00 00 00
|
||||||
|
Page 28: 00 00 00 00
|
||||||
|
Page 29: 00 00 00 00
|
||||||
|
Page 30: 00 00 00 00
|
||||||
|
Page 31: 00 00 00 00
|
||||||
|
Page 32: 00 00 00 00
|
||||||
|
Page 33: 00 00 00 00
|
||||||
|
Page 34: 00 00 00 00
|
||||||
|
Page 35: 00 00 00 00
|
||||||
|
Page 36: 00 00 00 00
|
||||||
|
Page 37: 00 00 00 00
|
||||||
|
Page 38: 00 00 00 00
|
||||||
|
Page 39: 00 00 00 00
|
||||||
|
Page 40: 00 00 00 BD
|
||||||
|
Page 41: 04 00 00 04
|
||||||
|
Page 42: C0 05 00 00
|
||||||
|
Page 43: 95 3F 52 FF
|
||||||
|
Page 44: 00 00 00 00
|
||||||
|
Failed authentication attempts: 0
|
||||||
@@ -0,0 +1,156 @@
|
|||||||
|
Filetype: Flipper NFC device
|
||||||
|
Version: 3
|
||||||
|
# Nfc device type can be UID, Mifare Ultralight, Mifare Classic
|
||||||
|
Device type: NTAG215
|
||||||
|
# UID, ATQA and SAK are common for all formats
|
||||||
|
UID: 04 51 5C FA 6F 73 81
|
||||||
|
ATQA: 00 44
|
||||||
|
SAK: 00
|
||||||
|
# Mifare Ultralight specific data
|
||||||
|
Data format version: 1
|
||||||
|
Signature: 42 21 E4 6C 79 6A 81 5E EA 0D 93 6D 85 EE 4B 0C 2A 00 D5 77 F1 C5 67 F3 63 75 F8 EB 86 48 5E 6B
|
||||||
|
Mifare version: 00 04 04 02 01 00 11 03
|
||||||
|
Counter 0: 0
|
||||||
|
Tearing 0: 00
|
||||||
|
Counter 1: 0
|
||||||
|
Tearing 1: 00
|
||||||
|
Counter 2: 00
|
||||||
|
Tearing 2: 00
|
||||||
|
Pages total: 135
|
||||||
|
Pages read: 135
|
||||||
|
Page 0: 04 51 5C 81
|
||||||
|
Page 1: FA 6F 73 81
|
||||||
|
Page 2: 67 48 0F E0
|
||||||
|
Page 3: F1 10 FF EE
|
||||||
|
Page 4: A5 00 00 00
|
||||||
|
Page 5: 90 42 74 71
|
||||||
|
Page 6: FD 8F 50 61
|
||||||
|
Page 7: C5 65 1B 54
|
||||||
|
Page 8: EF 68 D0 8E
|
||||||
|
Page 9: 3D 35 DB 83
|
||||||
|
Page 10: D3 00 29 F6
|
||||||
|
Page 11: 42 2A A5 5C
|
||||||
|
Page 12: F1 69 0A FC
|
||||||
|
Page 13: B6 44 E9 6B
|
||||||
|
Page 14: 77 41 88 81
|
||||||
|
Page 15: 86 31 CB AD
|
||||||
|
Page 16: B1 DE F1 AB
|
||||||
|
Page 17: DF 96 C2 C5
|
||||||
|
Page 18: C1 26 99 96
|
||||||
|
Page 19: 85 AF 9F 0E
|
||||||
|
Page 20: 58 FE ED DC
|
||||||
|
Page 21: 0A 0A 00 01
|
||||||
|
Page 22: 03 C1 05 02
|
||||||
|
Page 23: 38 39 34 33
|
||||||
|
Page 24: 49 2D 4E 5C
|
||||||
|
Page 25: 5B 21 0F 44
|
||||||
|
Page 26: 3F 3F 76 69
|
||||||
|
Page 27: B4 72 D8 38
|
||||||
|
Page 28: A0 35 53 51
|
||||||
|
Page 29: 53 EB A6 7C
|
||||||
|
Page 30: 3E 8B 97 C0
|
||||||
|
Page 31: 00 7A 45 13
|
||||||
|
Page 32: 3A 8B D4 0F
|
||||||
|
Page 33: 31 C2 32 CC
|
||||||
|
Page 34: B4 24 A6 1B
|
||||||
|
Page 35: D3 F5 4A 1F
|
||||||
|
Page 36: CD 8F 1D 64
|
||||||
|
Page 37: 01 F4 DF C2
|
||||||
|
Page 38: 11 16 C2 C5
|
||||||
|
Page 39: 30 6D 49 AF
|
||||||
|
Page 40: 10 D4 7C 3C
|
||||||
|
Page 41: 6E 36 4E 08
|
||||||
|
Page 42: 95 76 BC 84
|
||||||
|
Page 43: 35 50 DD F0
|
||||||
|
Page 44: 21 0F EE D9
|
||||||
|
Page 45: 85 19 54 5F
|
||||||
|
Page 46: 3E A9 04 20
|
||||||
|
Page 47: 1B 97 E4 39
|
||||||
|
Page 48: FF 0A 45 F6
|
||||||
|
Page 49: 13 D4 3E DD
|
||||||
|
Page 50: 97 42 FC 67
|
||||||
|
Page 51: 6A AC 78 96
|
||||||
|
Page 52: D1 DA 25 23
|
||||||
|
Page 53: BF 4D B3 76
|
||||||
|
Page 54: F1 21 ED 15
|
||||||
|
Page 55: BD 55 11 C4
|
||||||
|
Page 56: 4E 8C E9 23
|
||||||
|
Page 57: C0 C4 6D 5A
|
||||||
|
Page 58: 58 25 FF 95
|
||||||
|
Page 59: 3C 2B 7A 57
|
||||||
|
Page 60: 66 BE A0 61
|
||||||
|
Page 61: BC FC 4A 31
|
||||||
|
Page 62: 4D AC EE 81
|
||||||
|
Page 63: BE 1A 86 04
|
||||||
|
Page 64: F6 D7 5E B3
|
||||||
|
Page 65: E7 A8 A2 86
|
||||||
|
Page 66: E9 40 AB 47
|
||||||
|
Page 67: C8 36 E4 3E
|
||||||
|
Page 68: A7 4D D3 EA
|
||||||
|
Page 69: 83 9A 64 F7
|
||||||
|
Page 70: 96 6B 5D BF
|
||||||
|
Page 71: 4E A2 A6 0F
|
||||||
|
Page 72: BD 3D BE 7C
|
||||||
|
Page 73: 22 0C 68 51
|
||||||
|
Page 74: 0F 9A B8 AE
|
||||||
|
Page 75: 38 2C C4 CD
|
||||||
|
Page 76: 53 D8 DD 18
|
||||||
|
Page 77: A6 5D 35 87
|
||||||
|
Page 78: C9 6D 99 59
|
||||||
|
Page 79: 61 9F B6 DC
|
||||||
|
Page 80: E6 22 0F 99
|
||||||
|
Page 81: 39 82 79 60
|
||||||
|
Page 82: 58 2E BE F7
|
||||||
|
Page 83: EF F7 95 62
|
||||||
|
Page 84: D5 06 1B 58
|
||||||
|
Page 85: 65 05 A9 08
|
||||||
|
Page 86: 75 ED 5D 90
|
||||||
|
Page 87: 5A E1 7E C9
|
||||||
|
Page 88: 35 D6 29 BB
|
||||||
|
Page 89: D0 67 6C F9
|
||||||
|
Page 90: A0 FF 0B 93
|
||||||
|
Page 91: 22 EA A3 3F
|
||||||
|
Page 92: E2 BD BD 58
|
||||||
|
Page 93: BE 93 D9 94
|
||||||
|
Page 94: 41 CC 7E 40
|
||||||
|
Page 95: E6 8C 5A 43
|
||||||
|
Page 96: 65 C1 24 94
|
||||||
|
Page 97: B9 97 61 13
|
||||||
|
Page 98: AD 74 FF 21
|
||||||
|
Page 99: 0F EC F6 03
|
||||||
|
Page 100: 89 5D 89 E5
|
||||||
|
Page 101: 8D 11 F8 D7
|
||||||
|
Page 102: 33 43 79 2E
|
||||||
|
Page 103: 23 E5 29 B5
|
||||||
|
Page 104: 53 98 13 FF
|
||||||
|
Page 105: E8 79 8B 33
|
||||||
|
Page 106: 45 6C 34 38
|
||||||
|
Page 107: 3B 69 28 D7
|
||||||
|
Page 108: D2 80 B0 2F
|
||||||
|
Page 109: D0 18 D5 DD
|
||||||
|
Page 110: 6C 2D D9 97
|
||||||
|
Page 111: CA 78 B4 A2
|
||||||
|
Page 112: B7 3E B8 79
|
||||||
|
Page 113: A2 BE 54 E4
|
||||||
|
Page 114: C8 28 0C 4A
|
||||||
|
Page 115: 81 E7 EC 1C
|
||||||
|
Page 116: 39 93 6F 70
|
||||||
|
Page 117: 75 77 5C FC
|
||||||
|
Page 118: 66 58 0C 1C
|
||||||
|
Page 119: 9F 70 2E C8
|
||||||
|
Page 120: 52 4A 52 BD
|
||||||
|
Page 121: 56 D5 6A 15
|
||||||
|
Page 122: 54 1B 33 90
|
||||||
|
Page 123: 44 11 C1 07
|
||||||
|
Page 124: 11 5C BA 80
|
||||||
|
Page 125: 10 14 20 9A
|
||||||
|
Page 126: 4A D8 E6 36
|
||||||
|
Page 127: DA B8 59 E5
|
||||||
|
Page 128: 5E 48 95 DA
|
||||||
|
Page 129: 96 6A 26 85
|
||||||
|
Page 130: 01 00 0F BD
|
||||||
|
Page 131: 00 00 00 04
|
||||||
|
Page 132: 5F 00 00 00
|
||||||
|
Page 133: 00 00 00 00
|
||||||
|
Page 134: 00 00 00 00
|
||||||
|
Failed authentication attempts: 0
|
||||||
@@ -0,0 +1,252 @@
|
|||||||
|
Filetype: Flipper NFC device
|
||||||
|
Version: 2
|
||||||
|
# Nfc device type can be UID, Mifare Ultralight, Mifare Classic, Bank card
|
||||||
|
Device type: NTAG216
|
||||||
|
# UID, ATQA and SAK are common for all formats
|
||||||
|
UID: 04 D9 65 0A 32 5E 80
|
||||||
|
ATQA: 44 00
|
||||||
|
SAK: 00
|
||||||
|
# Mifare Ultralight specific data
|
||||||
|
Data format version: 1
|
||||||
|
Signature: 48 2A F2 01 0F F2 F5 A7 9A D5 79 6E CB 14 54 48 98 D1 57 5D 8A 23 A9 B0 E8 20 02 3E CD C8 16 DB
|
||||||
|
Mifare version: 00 04 04 02 01 00 13 03
|
||||||
|
Counter 0: 0
|
||||||
|
Tearing 0: 00
|
||||||
|
Counter 1: 0
|
||||||
|
Tearing 1: 00
|
||||||
|
Counter 2: 0
|
||||||
|
Tearing 2: 00
|
||||||
|
Pages total: 231
|
||||||
|
Pages read: 231
|
||||||
|
Page 0: 04 D9 65 30
|
||||||
|
Page 1: 0A 32 5E 80
|
||||||
|
Page 2: E6 48 00 00
|
||||||
|
Page 3: E1 10 6D 00
|
||||||
|
Page 4: 03 37 D1 01
|
||||||
|
Page 5: 33 55 04 6D
|
||||||
|
Page 6: 2E 79 6F 75
|
||||||
|
Page 7: 74 75 62 65
|
||||||
|
Page 8: 2E 63 6F 6D
|
||||||
|
Page 9: 2F 77 61 74
|
||||||
|
Page 10: 63 68 3F 76
|
||||||
|
Page 11: 3D 62 78 71
|
||||||
|
Page 12: 4C 73 72 6C
|
||||||
|
Page 13: 61 6B 4B 38
|
||||||
|
Page 14: 26 66 65 61
|
||||||
|
Page 15: 74 75 72 65
|
||||||
|
Page 16: 3D 79 6F 75
|
||||||
|
Page 17: 74 75 2E 62
|
||||||
|
Page 18: 65 FE 00 00
|
||||||
|
Page 19: 00 00 00 00
|
||||||
|
Page 20: 00 00 00 00
|
||||||
|
Page 21: 00 00 00 00
|
||||||
|
Page 22: 00 00 00 00
|
||||||
|
Page 23: 00 00 00 00
|
||||||
|
Page 24: 00 00 00 00
|
||||||
|
Page 25: 00 00 00 00
|
||||||
|
Page 26: 00 00 00 00
|
||||||
|
Page 27: 00 00 00 00
|
||||||
|
Page 28: 00 00 00 00
|
||||||
|
Page 29: 00 00 00 00
|
||||||
|
Page 30: 00 00 00 00
|
||||||
|
Page 31: 00 00 00 00
|
||||||
|
Page 32: 00 00 00 00
|
||||||
|
Page 33: 00 00 00 00
|
||||||
|
Page 34: 00 00 00 00
|
||||||
|
Page 35: 00 00 00 00
|
||||||
|
Page 36: 00 00 00 00
|
||||||
|
Page 37: 00 00 00 00
|
||||||
|
Page 38: 00 00 00 00
|
||||||
|
Page 39: 00 00 00 00
|
||||||
|
Page 40: 00 00 00 00
|
||||||
|
Page 41: 00 00 00 00
|
||||||
|
Page 42: 00 00 00 00
|
||||||
|
Page 43: 00 00 00 00
|
||||||
|
Page 44: 00 00 00 00
|
||||||
|
Page 45: 00 00 00 00
|
||||||
|
Page 46: 00 00 00 00
|
||||||
|
Page 47: 00 00 00 00
|
||||||
|
Page 48: 00 00 00 00
|
||||||
|
Page 49: 00 00 00 00
|
||||||
|
Page 50: 00 00 00 00
|
||||||
|
Page 51: 00 00 00 00
|
||||||
|
Page 52: 00 00 00 00
|
||||||
|
Page 53: 00 00 00 00
|
||||||
|
Page 54: 00 00 00 00
|
||||||
|
Page 55: 00 00 00 00
|
||||||
|
Page 56: 00 00 00 00
|
||||||
|
Page 57: 00 00 00 00
|
||||||
|
Page 58: 00 00 00 00
|
||||||
|
Page 59: 00 00 00 00
|
||||||
|
Page 60: 00 00 00 00
|
||||||
|
Page 61: 00 00 00 00
|
||||||
|
Page 62: 00 00 00 00
|
||||||
|
Page 63: 00 00 00 00
|
||||||
|
Page 64: 00 00 00 00
|
||||||
|
Page 65: 00 00 00 00
|
||||||
|
Page 66: 00 00 00 00
|
||||||
|
Page 67: 00 00 00 00
|
||||||
|
Page 68: 00 00 00 00
|
||||||
|
Page 69: 00 00 00 00
|
||||||
|
Page 70: 00 00 00 00
|
||||||
|
Page 71: 00 00 00 00
|
||||||
|
Page 72: 00 00 00 00
|
||||||
|
Page 73: 00 00 00 00
|
||||||
|
Page 74: 00 00 00 00
|
||||||
|
Page 75: 00 00 00 00
|
||||||
|
Page 76: 00 00 00 00
|
||||||
|
Page 77: 00 00 00 00
|
||||||
|
Page 78: 00 00 00 00
|
||||||
|
Page 79: 00 00 00 00
|
||||||
|
Page 80: 00 00 00 00
|
||||||
|
Page 81: 00 00 00 00
|
||||||
|
Page 82: 00 00 00 00
|
||||||
|
Page 83: 00 00 00 00
|
||||||
|
Page 84: 00 00 00 00
|
||||||
|
Page 85: 00 00 00 00
|
||||||
|
Page 86: 00 00 00 00
|
||||||
|
Page 87: 00 00 00 00
|
||||||
|
Page 88: 00 00 00 00
|
||||||
|
Page 89: 00 00 00 00
|
||||||
|
Page 90: 00 00 00 00
|
||||||
|
Page 91: 00 00 00 00
|
||||||
|
Page 92: 00 00 00 00
|
||||||
|
Page 93: 00 00 00 00
|
||||||
|
Page 94: 00 00 00 00
|
||||||
|
Page 95: 00 00 00 00
|
||||||
|
Page 96: 00 00 00 00
|
||||||
|
Page 97: 00 00 00 00
|
||||||
|
Page 98: 00 00 00 00
|
||||||
|
Page 99: 00 00 00 00
|
||||||
|
Page 100: 00 00 00 00
|
||||||
|
Page 101: 00 00 00 00
|
||||||
|
Page 102: 00 00 00 00
|
||||||
|
Page 103: 00 00 00 00
|
||||||
|
Page 104: 00 00 00 00
|
||||||
|
Page 105: 00 00 00 00
|
||||||
|
Page 106: 00 00 00 00
|
||||||
|
Page 107: 00 00 00 00
|
||||||
|
Page 108: 00 00 00 00
|
||||||
|
Page 109: 00 00 00 00
|
||||||
|
Page 110: 00 00 00 00
|
||||||
|
Page 111: 00 00 00 00
|
||||||
|
Page 112: 00 00 00 00
|
||||||
|
Page 113: 00 00 00 00
|
||||||
|
Page 114: 00 00 00 00
|
||||||
|
Page 115: 00 00 00 00
|
||||||
|
Page 116: 00 00 00 00
|
||||||
|
Page 117: 00 00 00 00
|
||||||
|
Page 118: 00 00 00 00
|
||||||
|
Page 119: 00 00 00 00
|
||||||
|
Page 120: 00 00 00 00
|
||||||
|
Page 121: 00 00 00 00
|
||||||
|
Page 122: 00 00 00 00
|
||||||
|
Page 123: 00 00 00 00
|
||||||
|
Page 124: 00 00 00 00
|
||||||
|
Page 125: 00 00 00 00
|
||||||
|
Page 126: 00 00 00 00
|
||||||
|
Page 127: 00 00 00 00
|
||||||
|
Page 128: 00 00 00 00
|
||||||
|
Page 129: 00 00 00 00
|
||||||
|
Page 130: 00 00 00 00
|
||||||
|
Page 131: 00 00 00 00
|
||||||
|
Page 132: 00 00 00 00
|
||||||
|
Page 133: 00 00 00 00
|
||||||
|
Page 134: 00 00 00 00
|
||||||
|
Page 135: 00 00 00 00
|
||||||
|
Page 136: 00 00 00 00
|
||||||
|
Page 137: 00 00 00 00
|
||||||
|
Page 138: 00 00 00 00
|
||||||
|
Page 139: 00 00 00 00
|
||||||
|
Page 140: 00 00 00 00
|
||||||
|
Page 141: 00 00 00 00
|
||||||
|
Page 142: 00 00 00 00
|
||||||
|
Page 143: 00 00 00 00
|
||||||
|
Page 144: 00 00 00 00
|
||||||
|
Page 145: 00 00 00 00
|
||||||
|
Page 146: 00 00 00 00
|
||||||
|
Page 147: 00 00 00 00
|
||||||
|
Page 148: 00 00 00 00
|
||||||
|
Page 149: 00 00 00 00
|
||||||
|
Page 150: 00 00 00 00
|
||||||
|
Page 151: 00 00 00 00
|
||||||
|
Page 152: 00 00 00 00
|
||||||
|
Page 153: 00 00 00 00
|
||||||
|
Page 154: 00 00 00 00
|
||||||
|
Page 155: 00 00 00 00
|
||||||
|
Page 156: 00 00 00 00
|
||||||
|
Page 157: 00 00 00 00
|
||||||
|
Page 158: 00 00 00 00
|
||||||
|
Page 159: 00 00 00 00
|
||||||
|
Page 160: 00 00 00 00
|
||||||
|
Page 161: 00 00 00 00
|
||||||
|
Page 162: 00 00 00 00
|
||||||
|
Page 163: 00 00 00 00
|
||||||
|
Page 164: 00 00 00 00
|
||||||
|
Page 165: 00 00 00 00
|
||||||
|
Page 166: 00 00 00 00
|
||||||
|
Page 167: 00 00 00 00
|
||||||
|
Page 168: 00 00 00 00
|
||||||
|
Page 169: 00 00 00 00
|
||||||
|
Page 170: 00 00 00 00
|
||||||
|
Page 171: 00 00 00 00
|
||||||
|
Page 172: 00 00 00 00
|
||||||
|
Page 173: 00 00 00 00
|
||||||
|
Page 174: 00 00 00 00
|
||||||
|
Page 175: 00 00 00 00
|
||||||
|
Page 176: 00 00 00 00
|
||||||
|
Page 177: 00 00 00 00
|
||||||
|
Page 178: 00 00 00 00
|
||||||
|
Page 179: 00 00 00 00
|
||||||
|
Page 180: 00 00 00 00
|
||||||
|
Page 181: 00 00 00 00
|
||||||
|
Page 182: 00 00 00 00
|
||||||
|
Page 183: 00 00 00 00
|
||||||
|
Page 184: 00 00 00 00
|
||||||
|
Page 185: 00 00 00 00
|
||||||
|
Page 186: 00 00 00 00
|
||||||
|
Page 187: 00 00 00 00
|
||||||
|
Page 188: 00 00 00 00
|
||||||
|
Page 189: 00 00 00 00
|
||||||
|
Page 190: 00 00 00 00
|
||||||
|
Page 191: 00 00 00 00
|
||||||
|
Page 192: 00 00 00 00
|
||||||
|
Page 193: 00 00 00 00
|
||||||
|
Page 194: 00 00 00 00
|
||||||
|
Page 195: 00 00 00 00
|
||||||
|
Page 196: 00 00 00 00
|
||||||
|
Page 197: 00 00 00 00
|
||||||
|
Page 198: 00 00 00 00
|
||||||
|
Page 199: 00 00 00 00
|
||||||
|
Page 200: 00 00 00 00
|
||||||
|
Page 201: 00 00 00 00
|
||||||
|
Page 202: 00 00 00 00
|
||||||
|
Page 203: 00 00 00 00
|
||||||
|
Page 204: 00 00 00 00
|
||||||
|
Page 205: 00 00 00 00
|
||||||
|
Page 206: 00 00 00 00
|
||||||
|
Page 207: 00 00 00 00
|
||||||
|
Page 208: 00 00 00 00
|
||||||
|
Page 209: 00 00 00 00
|
||||||
|
Page 210: 00 00 00 00
|
||||||
|
Page 211: 00 00 00 00
|
||||||
|
Page 212: 00 00 00 00
|
||||||
|
Page 213: 00 00 00 00
|
||||||
|
Page 214: 00 00 00 00
|
||||||
|
Page 215: 00 00 00 00
|
||||||
|
Page 216: 00 00 00 00
|
||||||
|
Page 217: 00 00 00 00
|
||||||
|
Page 218: 00 00 00 00
|
||||||
|
Page 219: 00 00 00 00
|
||||||
|
Page 220: 00 00 00 00
|
||||||
|
Page 221: 00 00 00 00
|
||||||
|
Page 222: 00 00 00 00
|
||||||
|
Page 223: 00 00 00 00
|
||||||
|
Page 224: 00 00 00 00
|
||||||
|
Page 225: 00 00 00 00
|
||||||
|
Page 226: 00 00 00 BD
|
||||||
|
Page 227: 04 00 00 FF
|
||||||
|
Page 228: 00 05 00 00
|
||||||
|
Page 229: 00 00 00 00
|
||||||
|
Page 230: 00 00 00 00
|
||||||
|
Failed authentication attempts: 0
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
Filetype: Flipper NFC device
|
||||||
|
Version: 3
|
||||||
|
# Nfc device type can be UID, Mifare Ultralight, Mifare Classic
|
||||||
|
Device type: Mifare Ultralight 11
|
||||||
|
# UID, ATQA and SAK are common for all formats
|
||||||
|
UID: 04 15 74 F2 B0 5E 81
|
||||||
|
ATQA: 00 44
|
||||||
|
SAK: 00
|
||||||
|
# Mifare Ultralight specific data
|
||||||
|
Data format version: 1
|
||||||
|
Signature: A4 37 7D E5 8C 2F 88 D8 04 60 41 6E 3A C8 CD DB 19 94 26 12 C5 D0 12 B0 EB 88 05 72 89 F2 A5 61
|
||||||
|
Mifare version: 00 04 03 01 01 00 0B 03
|
||||||
|
Counter 0: 0
|
||||||
|
Tearing 0: BD
|
||||||
|
Counter 1: 0
|
||||||
|
Tearing 1: BD
|
||||||
|
Counter 2: 0
|
||||||
|
Tearing 2: BD
|
||||||
|
Pages total: 20
|
||||||
|
Pages read: 20
|
||||||
|
Page 0: 04 15 74 ED
|
||||||
|
Page 1: F2 B0 5E 81
|
||||||
|
Page 2: 9D 48 F8 FF
|
||||||
|
Page 3: C1 31 3E 3F
|
||||||
|
Page 4: B0 00 F0 02
|
||||||
|
Page 5: 2F B3 45 A0
|
||||||
|
Page 6: D4 9C 02 F2
|
||||||
|
Page 7: 4A B1 ED FF
|
||||||
|
Page 8: C8 01 00 02
|
||||||
|
Page 9: 4F B3 46 70
|
||||||
|
Page 10: EE F6 60 B0
|
||||||
|
Page 11: B6 C6 12 1B
|
||||||
|
Page 12: B9 1E 49 C3
|
||||||
|
Page 13: 49 DF 7A 57
|
||||||
|
Page 14: 08 52 2A 11
|
||||||
|
Page 15: 28 0A 28 59
|
||||||
|
Page 16: 00 00 00 FF
|
||||||
|
Page 17: 00 05 00 00
|
||||||
|
Page 18: FF FF FF FF
|
||||||
|
Page 19: 00 00 00 00
|
||||||
|
Failed authentication attempts: 0
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
Filetype: Flipper NFC device
|
||||||
|
Version: 3
|
||||||
|
# Nfc device type can be UID, Mifare Ultralight, Mifare Classic
|
||||||
|
Device type: Mifare Ultralight 21
|
||||||
|
# UID, ATQA and SAK are common for all formats
|
||||||
|
UID: 34 BF AB B1 AE 73 D6
|
||||||
|
ATQA: 00 44
|
||||||
|
SAK: 00
|
||||||
|
# Mifare Ultralight specific data
|
||||||
|
Data format version: 1
|
||||||
|
Signature: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
|
||||||
|
Mifare version: 00 34 21 01 01 00 0E 03
|
||||||
|
Counter 0: 0
|
||||||
|
Tearing 0: 00
|
||||||
|
Counter 1: 0
|
||||||
|
Tearing 1: 00
|
||||||
|
Counter 2: 0
|
||||||
|
Tearing 2: 00
|
||||||
|
Pages total: 41
|
||||||
|
Pages read: 41
|
||||||
|
Page 0: 34 BF AB A8
|
||||||
|
Page 1: B1 AE 73 D6
|
||||||
|
Page 2: BA 00 70 08
|
||||||
|
Page 3: FF FF FF FC
|
||||||
|
Page 4: 45 D9 BB A0
|
||||||
|
Page 5: 5D 9D FA 00
|
||||||
|
Page 6: 80 70 38 40
|
||||||
|
Page 7: 12 30 02 00
|
||||||
|
Page 8: 00 00 00 00
|
||||||
|
Page 9: 00 00 00 00
|
||||||
|
Page 10: AC A1 0D E4
|
||||||
|
Page 11: 80 70 38 40
|
||||||
|
Page 12: 00 57 A0 01
|
||||||
|
Page 13: 00 08 C1 40
|
||||||
|
Page 14: 00 00 00 00
|
||||||
|
Page 15: AC A1 0D E4
|
||||||
|
Page 16: 00 00 00 00
|
||||||
|
Page 17: 00 00 00 00
|
||||||
|
Page 18: 00 00 00 00
|
||||||
|
Page 19: 00 00 00 00
|
||||||
|
Page 20: 00 00 00 00
|
||||||
|
Page 21: 00 00 00 00
|
||||||
|
Page 22: 00 00 00 00
|
||||||
|
Page 23: 00 00 00 00
|
||||||
|
Page 24: 00 00 00 00
|
||||||
|
Page 25: 00 00 00 00
|
||||||
|
Page 26: 00 00 00 00
|
||||||
|
Page 27: 00 00 00 00
|
||||||
|
Page 28: 00 00 00 00
|
||||||
|
Page 29: 00 00 00 00
|
||||||
|
Page 30: 00 00 00 00
|
||||||
|
Page 31: 00 00 00 00
|
||||||
|
Page 32: 00 00 00 00
|
||||||
|
Page 33: 00 00 00 00
|
||||||
|
Page 34: 00 00 00 00
|
||||||
|
Page 35: 00 00 00 00
|
||||||
|
Page 36: 00 00 00 BD
|
||||||
|
Page 37: 00 00 00 FF
|
||||||
|
Page 38: 00 05 00 00
|
||||||
|
Page 39: FF FF FF FF
|
||||||
|
Page 40: 00 00 00 00
|
||||||
|
Failed authentication attempts: 0
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user