mirror of
https://github.com/DarkFlippers/unleashed-firmware.git
synced 2025-12-13 13:09:49 +04:00
Compare commits
1 Commits
unlshd-080
...
subghz_pro
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fc6adcbeb1 |
149
.ci_files/anims_ofw.txt
Normal file
149
.ci_files/anims_ofw.txt
Normal file
@@ -0,0 +1,149 @@
|
||||
Filetype: Flipper Animation Manifest
|
||||
Version: 1
|
||||
|
||||
Name: L1_Waves_128x50
|
||||
Min butthurt: 0
|
||||
Max butthurt: 5
|
||||
Min level: 1
|
||||
Max level: 3
|
||||
Weight: 3
|
||||
|
||||
Name: L1_Laptop_128x51
|
||||
Min butthurt: 0
|
||||
Max butthurt: 7
|
||||
Min level: 1
|
||||
Max level: 1
|
||||
Weight: 3
|
||||
|
||||
Name: L1_Sleep_128x64
|
||||
Min butthurt: 0
|
||||
Max butthurt: 10
|
||||
Min level: 1
|
||||
Max level: 3
|
||||
Weight: 3
|
||||
|
||||
Name: L1_Recording_128x51
|
||||
Min butthurt: 0
|
||||
Max butthurt: 8
|
||||
Min level: 1
|
||||
Max level: 1
|
||||
Weight: 3
|
||||
|
||||
Name: L1_Furippa1_128x64
|
||||
Min butthurt: 0
|
||||
Max butthurt: 6
|
||||
Min level: 1
|
||||
Max level: 1
|
||||
Weight: 3
|
||||
|
||||
Name: L1_Happy_holidays_128x64
|
||||
Min butthurt: 0
|
||||
Max butthurt: 14
|
||||
Min level: 1
|
||||
Max level: 3
|
||||
Weight: 4
|
||||
|
||||
Name: L1_Read_books_128x64
|
||||
Min butthurt: 0
|
||||
Max butthurt: 8
|
||||
Min level: 1
|
||||
Max level: 1
|
||||
Weight: 3
|
||||
|
||||
Name: L1_Cry_128x64
|
||||
Min butthurt: 8
|
||||
Max butthurt: 13
|
||||
Min level: 1
|
||||
Max level: 3
|
||||
Weight: 3
|
||||
|
||||
Name: L1_Boxing_128x64
|
||||
Min butthurt: 10
|
||||
Max butthurt: 13
|
||||
Min level: 1
|
||||
Max level: 3
|
||||
Weight: 3
|
||||
|
||||
Name: L1_Mad_fist_128x64
|
||||
Min butthurt: 9
|
||||
Max butthurt: 13
|
||||
Min level: 1
|
||||
Max level: 3
|
||||
Weight: 3
|
||||
|
||||
Name: L1_Mods_128x64
|
||||
Min butthurt: 0
|
||||
Max butthurt: 9
|
||||
Min level: 1
|
||||
Max level: 3
|
||||
Weight: 4
|
||||
|
||||
Name: L1_Painting_128x64
|
||||
Min butthurt: 0
|
||||
Max butthurt: 7
|
||||
Min level: 1
|
||||
Max level: 3
|
||||
Weight: 3
|
||||
|
||||
Name: L1_Leaving_sad_128x64
|
||||
Min butthurt: 14
|
||||
Max butthurt: 14
|
||||
Min level: 1
|
||||
Max level: 3
|
||||
Weight: 3
|
||||
|
||||
Name: L2_Wake_up_128x64
|
||||
Min butthurt: 0
|
||||
Max butthurt: 12
|
||||
Min level: 2
|
||||
Max level: 3
|
||||
Weight: 4
|
||||
|
||||
Name: L2_Furippa2_128x64
|
||||
Min butthurt: 0
|
||||
Max butthurt: 6
|
||||
Min level: 2
|
||||
Max level: 2
|
||||
Weight: 3
|
||||
|
||||
Name: L2_Hacking_pc_128x64
|
||||
Min butthurt: 0
|
||||
Max butthurt: 8
|
||||
Min level: 2
|
||||
Max level: 2
|
||||
Weight: 3
|
||||
|
||||
Name: L2_Soldering_128x64
|
||||
Min butthurt: 0
|
||||
Max butthurt: 10
|
||||
Min level: 2
|
||||
Max level: 2
|
||||
Weight: 3
|
||||
|
||||
Name: L3_Furippa3_128x64
|
||||
Min butthurt: 0
|
||||
Max butthurt: 6
|
||||
Min level: 3
|
||||
Max level: 3
|
||||
Weight: 3
|
||||
|
||||
Name: L3_Hijack_radio_128x64
|
||||
Min butthurt: 0
|
||||
Max butthurt: 8
|
||||
Min level: 3
|
||||
Max level: 3
|
||||
Weight: 3
|
||||
|
||||
Name: L3_Lab_research_128x54
|
||||
Min butthurt: 0
|
||||
Max butthurt: 10
|
||||
Min level: 3
|
||||
Max level: 3
|
||||
Weight: 3
|
||||
|
||||
Name: L1_Sleigh_ride_128x64
|
||||
Min butthurt: 0
|
||||
Max butthurt: 14
|
||||
Min level: 1
|
||||
Max level: 3
|
||||
Weight: 4
|
||||
@@ -1,16 +0,0 @@
|
||||
## New Unleashed FW Dev Build
|
||||
|
||||
**Build** - (buildnum)
|
||||
**Commit** - [(commitsha)](https://github.com/DarkFlippers/unleashed-firmware/commit/(commitsha))
|
||||
### Sponsor our project -> [Patreon](https://patreon.com/mmxdev) or [Boosty](https://boosty.to/mmxdev)
|
||||
How to [install firmware](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/HowToInstall.md)?
|
||||
|
||||
### Install FW via Web Updater:
|
||||
[Default](https://lab.flipper.net/?url=https://unleashedflip.com/fw/dev/flipper-z-f7-update-(buildnum).tgz&channel=dev-cfw&version=(buildnum)) > ` `
|
||||
[Extra apps](https://lab.flipper.net/?url=https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-(buildnum)e.tgz&channel=dev-cfw&version=(buildnum)e) > `e`
|
||||
[No apps](https://lab.flipper.net/?url=https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-(buildnum)c.tgz&channel=dev-cfw&version=(buildnum)c) > `c`
|
||||
[RGB patch - only for hardware mod!](https://lab.flipper.net/?url=https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-(buildnum)r.tgz&channel=dev-cfw&version=(buildnum)r) > `r`
|
||||
What ` `, `e`, `c`, `r` means? -> [versions info](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/CHANGELOG.md#what-n-r-e---c-means-what-i-need-to-download-if-i-dont-want-to-use-web-updater)
|
||||
### Direct tgz download links:
|
||||
[Default](https://unleashedflip.com/fw/dev/flipper-z-f7-update-(buildnum).tgz) > ` ` - [Extra apps](https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-(buildnum)e.tgz) > `e` - [No apps](https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-(buildnum)c.tgz) > `c` - [RGB patch - only for hardware mod!](https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-(buildnum)r.tgz) > `r`
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
**New Unleashed FW Dev Build**
|
||||
|
||||
**Build** - (buildnum)
|
||||
**Commit** - [(commitsha)](https://github.com/DarkFlippers/unleashed-firmware/commit/(commitsha))
|
||||
**Sponsor our project** -> [Patreon](https://patreon.com/mmxdev) or [Boosty](https://boosty.to/mmxdev)
|
||||
|
||||
How to [install firmware](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/HowToInstall.md)?
|
||||
|
||||
**Install FW via Web Updater:**
|
||||
[Default](https://lab.flipper.net/?url=https://unleashedflip.com/fw/dev/flipper-z-f7-update-(buildnum).tgz&channel=dev-cfw&version=(buildnum)) > ` `
|
||||
[Extra apps](https://lab.flipper.net/?url=https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-(buildnum)e.tgz&channel=dev-cfw&version=(buildnum)e) > `e`
|
||||
[No apps](https://lab.flipper.net/?url=https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-(buildnum)c.tgz&channel=dev-cfw&version=(buildnum)c) > `c`
|
||||
[RGB patch - only for hardware mod!](https://lab.flipper.net/?url=https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-(buildnum)r.tgz&channel=dev-cfw&version=(buildnum)r) > `r`
|
||||
|
||||
What ` `, `e`, `c`, `r` means? -> [versions info](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/CHANGELOG.md#what-n-r-e---c-means-what-i-need-to-download-if-i-dont-want-to-use-web-updater)
|
||||
|
||||
**Direct tgz download links:**
|
||||
[Default](https://unleashedflip.com/fw/dev/flipper-z-f7-update-(buildnum).tgz) > ` `
|
||||
[Extra apps](https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-(buildnum)e.tgz) > `e`
|
||||
[No apps](https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-(buildnum)c.tgz) > `c`
|
||||
[RGB patch - only for hardware mod!](https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-(buildnum)r.tgz) > `r`
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
FROM ubuntu:hirsute
|
||||
|
||||
RUN apt-get update \
|
||||
&& DEBIAN_FRONTEND=noninteractive apt-get install --no-install-recommends -y \
|
||||
ca-certificates \
|
||||
git \
|
||||
wget \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
|
||||
|
||||
COPY entrypoint.sh /
|
||||
|
||||
ENTRYPOINT ["/entrypoint.sh"]
|
||||
@@ -1,10 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
if [ -z "$1" ]; then
|
||||
bash
|
||||
else
|
||||
echo "Running $1"
|
||||
set -ex
|
||||
bash -c "$1"
|
||||
fi
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
## New Unleashed firmware released!
|
||||
|
||||
**Version:** (releasever)
|
||||
**Github:** [Release](https://github.com/DarkFlippers/unleashed-firmware/releases/tag/(releasever))
|
||||
### Sponsor our project -> [Patreon](https://patreon.com/mmxdev) or [Boosty](https://boosty.to/mmxdev)
|
||||
How to [install firmware](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/HowToInstall.md)?
|
||||
|
||||
### Install FW via Web Updater:
|
||||
[Default](https://lab.flipper.net/?url=https://unleashedflip.com/fw/(releasever)/flipper-z-f7-update-(releasever).tgz&channel=release-cfw&version=(releasever)) > ` `
|
||||
[Extra apps](https://lab.flipper.net/?url=https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-(releasever)e.tgz&channel=release-cfw&version=(releasever)e) > `e`
|
||||
[No apps](https://lab.flipper.net/?url=https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-(releasever)c.tgz&channel=release-cfw&version=(releasever)c) > `c`
|
||||
[RGB patch - only for hardware mod!](https://lab.flipper.net/?url=https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-(releasever)r.tgz&channel=release-cfw&version=(releasever)r) > `r`
|
||||
What ` `, `e`, `c`, `r` means? -> [versions info](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/CHANGELOG.md#what-n-r-e---c-means-what-i-need-to-download-if-i-dont-want-to-use-web-updater)
|
||||
### Direct tgz download links:
|
||||
[Default](https://unleashedflip.com/fw/(releasever)/flipper-z-f7-update-(releasever).tgz) > ` ` - [Extra apps](https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-(releasever)e.tgz) > `e` - [No apps](https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-(releasever)c.tgz) > `c` - [RGB patch - only for hardware mod!](https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-(releasever)r.tgz) > `r`
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
**New Unleashed firmware released**
|
||||
|
||||
**Version:** (releasever)
|
||||
**Github:** [Release](https://github.com/DarkFlippers/unleashed-firmware/releases/tag/(releasever))
|
||||
**Sponsor our project** -> [Patreon](https://patreon.com/mmxdev) or [Boosty](https://boosty.to/mmxdev)
|
||||
|
||||
How to [install firmware](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/HowToInstall.md)?
|
||||
|
||||
**Install FW via Web Updater:**
|
||||
[Default](https://lab.flipper.net/?url=https://unleashedflip.com/fw/(releasever)/flipper-z-f7-update-(releasever).tgz&channel=release-cfw&version=(releasever)) > ` `
|
||||
[Extra apps](https://lab.flipper.net/?url=https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-(releasever)e.tgz&channel=release-cfw&version=(releasever)e) > `e`
|
||||
[No apps](https://lab.flipper.net/?url=https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-(releasever)c.tgz&channel=release-cfw&version=(releasever)c) > `c`
|
||||
[RGB patch - only for hardware mod!](https://lab.flipper.net/?url=https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-(releasever)r.tgz&channel=release-cfw&version=(releasever)r) > `r`
|
||||
|
||||
What ` `, `e`, `c`, `r` means? -> [versions info](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/CHANGELOG.md#what-n-r-e---c-means-what-i-need-to-download-if-i-dont-want-to-use-web-updater)
|
||||
|
||||
**Direct tgz download links:**
|
||||
[Default](https://unleashedflip.com/fw/(releasever)/flipper-z-f7-update-(releasever).tgz) > ` `
|
||||
[Extra apps](https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-(releasever)e.tgz) > `e`
|
||||
[No apps](https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-(releasever)c.tgz) > `c`
|
||||
[RGB patch - only for hardware mod!](https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-(releasever)r.tgz) > `r`
|
||||
|
||||
@@ -1,675 +0,0 @@
|
||||
diff --git a/applications/services/notification/notification_app.c b/applications/services/notification/notification_app.c
|
||||
index 35d2fe6..1af97e2 100644
|
||||
--- a/applications/services/notification/notification_app.c
|
||||
+++ b/applications/services/notification/notification_app.c
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "notification.h"
|
||||
#include "notification_messages.h"
|
||||
#include "notification_app.h"
|
||||
+#include "applications/settings/notification_settings/rgb_backlight.h"
|
||||
|
||||
#define TAG "NotificationSrv"
|
||||
|
||||
@@ -616,6 +617,7 @@ int32_t notification_srv(void* p) {
|
||||
break;
|
||||
case SaveSettingsMessage:
|
||||
notification_save_settings(app);
|
||||
+ rgb_backlight_save_settings();
|
||||
break;
|
||||
case LoadSettingsMessage:
|
||||
notification_load_settings(app);
|
||||
diff --git a/applications/settings/notification_settings/notification_settings_app.c b/applications/settings/notification_settings/notification_settings_app.c
|
||||
index 2462b32..8e045ce 100644
|
||||
--- a/applications/settings/notification_settings/notification_settings_app.c
|
||||
+++ b/applications/settings/notification_settings/notification_settings_app.c
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <gui/modules/variable_item_list.h>
|
||||
#include <gui/view_dispatcher.h>
|
||||
#include <lib/toolbox/value_index.h>
|
||||
+#include <applications/settings/notification_settings/rgb_backlight.h>
|
||||
|
||||
#define MAX_NOTIFICATION_SETTINGS 4
|
||||
|
||||
@@ -13,6 +14,8 @@ typedef struct {
|
||||
VariableItemList* variable_item_list;
|
||||
} NotificationAppSettings;
|
||||
|
||||
+static VariableItem* temp_item;
|
||||
+
|
||||
static const NotificationSequence sequence_note_c = {
|
||||
&message_note_c5,
|
||||
&message_delay_100,
|
||||
@@ -168,6 +171,59 @@ static void vibro_changed(VariableItem* item) {
|
||||
notification_message(app->notification, &sequence_single_vibro);
|
||||
}
|
||||
|
||||
+// Set RGB backlight color
|
||||
+static void color_changed(VariableItem* item) {
|
||||
+ NotificationAppSettings* app = variable_item_get_context(item);
|
||||
+ uint8_t index = variable_item_get_current_value_index(item);
|
||||
+ rgb_backlight_set_color(index);
|
||||
+ variable_item_set_current_value_text(item, rgb_backlight_get_color_text(index));
|
||||
+ 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) {
|
||||
UNUSED(context);
|
||||
return VIEW_NONE;
|
||||
@@ -192,8 +248,40 @@ static NotificationAppSettings* alloc_settings(void) {
|
||||
variable_item_set_current_value_index(item, value_index);
|
||||
variable_item_set_current_value_text(item, contrast_text[value_index]);
|
||||
|
||||
+ // RGB Colors
|
||||
+ item = variable_item_list_add(
|
||||
+ app->variable_item_list, "LCD Color", rgb_backlight_get_color_count(), color_changed, app);
|
||||
+ value_index = rgb_backlight_get_settings()->display_color_index;
|
||||
+ variable_item_set_current_value_index(item, 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(
|
||||
+ 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);
|
||||
value_index = value_index_float(
|
||||
app->notification->settings.display_brightness, backlight_value, BACKLIGHT_COUNT);
|
||||
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
|
||||
new file mode 100644
|
||||
index 0000000..4edd775
|
||||
--- /dev/null
|
||||
+++ b/applications/settings/notification_settings/rgb_backlight.c
|
||||
@@ -0,0 +1,217 @@
|
||||
+/*
|
||||
+ RGB backlight FlipperZero driver
|
||||
+ Copyright (C) 2022-2023 Victor Nikitchuk (https://github.com/quen0n)
|
||||
+
|
||||
+ This program is free software: you can redistribute it and/or modify
|
||||
+ it under the terms of the GNU General Public License as published by
|
||||
+ the Free Software Foundation, either version 3 of the License, or
|
||||
+ (at your option) any later version.
|
||||
+
|
||||
+ This program is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
+ GNU General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU General Public License
|
||||
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
+*/
|
||||
+
|
||||
+#include "rgb_backlight.h"
|
||||
+#include <furi_hal.h>
|
||||
+#include <storage/storage.h>
|
||||
+
|
||||
+#define RGB_BACKLIGHT_SETTINGS_VERSION 6
|
||||
+#define RGB_BACKLIGHT_SETTINGS_FILE_NAME ".rgb_backlight.settings"
|
||||
+#define RGB_BACKLIGHT_SETTINGS_PATH INT_PATH(RGB_BACKLIGHT_SETTINGS_FILE_NAME)
|
||||
+
|
||||
+#define COLOR_COUNT (sizeof(colors) / sizeof(RGBBacklightColor))
|
||||
+
|
||||
+#define TAG "RGB Backlight"
|
||||
+
|
||||
+static RGBBacklightSettings rgb_settings = {
|
||||
+ .version = RGB_BACKLIGHT_SETTINGS_VERSION,
|
||||
+ .display_color_index = 0,
|
||||
+ .custom_r = 254,
|
||||
+ .custom_g = 254,
|
||||
+ .custom_b = 254,
|
||||
+ .settings_is_loaded = false};
|
||||
+
|
||||
+static const RGBBacklightColor colors[] = {
|
||||
+ {"Orange", 255, 60, 0},
|
||||
+ {"Yellow", 255, 144, 0},
|
||||
+ {"Spring", 167, 255, 0},
|
||||
+ {"Lime", 0, 255, 0},
|
||||
+ {"Aqua", 0, 255, 127},
|
||||
+ {"Cyan", 0, 210, 210},
|
||||
+ {"Azure", 0, 127, 255},
|
||||
+ {"Blue", 0, 0, 255},
|
||||
+ {"Purple", 127, 0, 255},
|
||||
+ {"Magenta", 210, 0, 210},
|
||||
+ {"Pink", 255, 0, 127},
|
||||
+ {"Red", 255, 0, 0},
|
||||
+ {"White", 254, 210, 200},
|
||||
+ {"Custom", 0, 0, 0},
|
||||
+};
|
||||
+
|
||||
+uint8_t rgb_backlight_get_color_count(void) {
|
||||
+ return COLOR_COUNT;
|
||||
+}
|
||||
+
|
||||
+const char* rgb_backlight_get_color_text(uint8_t index) {
|
||||
+ return colors[index].name;
|
||||
+}
|
||||
+
|
||||
+void rgb_backlight_load_settings(void) {
|
||||
+ // Do not load settings if we are in other boot modes than normal
|
||||
+ if(furi_hal_rtc_get_boot_mode() != FuriHalRtcBootModeNormal) {
|
||||
+ rgb_settings.settings_is_loaded = true;
|
||||
+ 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;
|
||||
+ File* file = storage_file_alloc(furi_record_open(RECORD_STORAGE));
|
||||
+ const size_t settings_size = sizeof(RGBBacklightSettings);
|
||||
+
|
||||
+ FURI_LOG_D(TAG, "loading settings from \"%s\"", RGB_BACKLIGHT_SETTINGS_PATH);
|
||||
+ bool fs_result =
|
||||
+ storage_file_open(file, RGB_BACKLIGHT_SETTINGS_PATH, FSAM_READ, FSOM_OPEN_EXISTING);
|
||||
+
|
||||
+ if(fs_result) {
|
||||
+ uint16_t bytes_count = storage_file_read(file, &settings, settings_size);
|
||||
+
|
||||
+ if(bytes_count != settings_size) {
|
||||
+ fs_result = false;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if(fs_result) {
|
||||
+ FURI_LOG_D(TAG, "load success");
|
||||
+ if(settings.version != RGB_BACKLIGHT_SETTINGS_VERSION) {
|
||||
+ FURI_LOG_E(
|
||||
+ TAG,
|
||||
+ "version(%d != %d) mismatch",
|
||||
+ settings.version,
|
||||
+ RGB_BACKLIGHT_SETTINGS_VERSION);
|
||||
+ } else {
|
||||
+ memcpy(&rgb_settings, &settings, settings_size);
|
||||
+ }
|
||||
+ } else {
|
||||
+ FURI_LOG_E(TAG, "load failed, %s", storage_file_get_error_desc(file));
|
||||
+ }
|
||||
+
|
||||
+ storage_file_close(file);
|
||||
+ storage_file_free(file);
|
||||
+ furi_record_close(RECORD_STORAGE);
|
||||
+ rgb_settings.settings_is_loaded = true;
|
||||
+}
|
||||
+
|
||||
+void rgb_backlight_save_settings(void) {
|
||||
+ RGBBacklightSettings settings;
|
||||
+ File* file = storage_file_alloc(furi_record_open(RECORD_STORAGE));
|
||||
+ const size_t settings_size = sizeof(RGBBacklightSettings);
|
||||
+
|
||||
+ FURI_LOG_D(TAG, "saving settings to \"%s\"", RGB_BACKLIGHT_SETTINGS_PATH);
|
||||
+
|
||||
+ memcpy(&settings, &rgb_settings, settings_size);
|
||||
+
|
||||
+ bool fs_result =
|
||||
+ storage_file_open(file, RGB_BACKLIGHT_SETTINGS_PATH, FSAM_WRITE, FSOM_CREATE_ALWAYS);
|
||||
+
|
||||
+ if(fs_result) {
|
||||
+ uint16_t bytes_count = storage_file_write(file, &settings, settings_size);
|
||||
+
|
||||
+ if(bytes_count != settings_size) {
|
||||
+ fs_result = false;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if(fs_result) {
|
||||
+ FURI_LOG_D(TAG, "save success");
|
||||
+ } else {
|
||||
+ FURI_LOG_E(TAG, "save failed, %s", storage_file_get_error_desc(file));
|
||||
+ }
|
||||
+
|
||||
+ storage_file_close(file);
|
||||
+ storage_file_free(file);
|
||||
+ furi_record_close(RECORD_STORAGE);
|
||||
+}
|
||||
+
|
||||
+RGBBacklightSettings* rgb_backlight_get_settings(void) {
|
||||
+ if(!rgb_settings.settings_is_loaded) {
|
||||
+ rgb_backlight_load_settings();
|
||||
+ }
|
||||
+ return &rgb_settings;
|
||||
+}
|
||||
+
|
||||
+void rgb_backlight_set_color(uint8_t color_index) {
|
||||
+ if(color_index > (rgb_backlight_get_color_count() - 1)) color_index = 0;
|
||||
+ rgb_settings.display_color_index = color_index;
|
||||
+}
|
||||
+
|
||||
+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) {
|
||||
+ rgb_backlight_load_settings();
|
||||
+ }
|
||||
+
|
||||
+ if(!bypass) {
|
||||
+ 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) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ last_brightness = brightness;
|
||||
+ last_color_index = rgb_settings.display_color_index;
|
||||
+ }
|
||||
+
|
||||
+ for(uint8_t i = 0; i < SK6805_get_led_count(); i++) {
|
||||
+ if(rgb_settings.display_color_index == 13) {
|
||||
+ uint8_t r = rgb_settings.custom_r * (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);
|
||||
+ } 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();
|
||||
+}
|
||||
diff --git a/applications/settings/notification_settings/rgb_backlight.h b/applications/settings/notification_settings/rgb_backlight.h
|
||||
new file mode 100644
|
||||
index 0000000..f215ed3
|
||||
--- /dev/null
|
||||
+++ b/applications/settings/notification_settings/rgb_backlight.h
|
||||
@@ -0,0 +1,91 @@
|
||||
+/*
|
||||
+ RGB backlight FlipperZero driver
|
||||
+ Copyright (C) 2022-2023 Victor Nikitchuk (https://github.com/quen0n)
|
||||
+
|
||||
+ This program is free software: you can redistribute it and/or modify
|
||||
+ it under the terms of the GNU General Public License as published by
|
||||
+ the Free Software Foundation, either version 3 of the License, or
|
||||
+ (at your option) any later version.
|
||||
+
|
||||
+ This program is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
+ GNU General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU General Public License
|
||||
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
+*/
|
||||
+
|
||||
+#include <furi.h>
|
||||
+#include "SK6805.h"
|
||||
+
|
||||
+typedef struct {
|
||||
+ char* name;
|
||||
+ uint8_t red;
|
||||
+ uint8_t green;
|
||||
+ uint8_t blue;
|
||||
+} RGBBacklightColor;
|
||||
+
|
||||
+typedef struct {
|
||||
+ uint8_t version;
|
||||
+ uint8_t display_color_index;
|
||||
+ uint8_t custom_r;
|
||||
+ uint8_t custom_g;
|
||||
+ uint8_t custom_b;
|
||||
+ bool settings_is_loaded;
|
||||
+} RGBBacklightSettings;
|
||||
+
|
||||
+/**
|
||||
+ * @brief Получить текущие настройки RGB-подсветки
|
||||
+ *
|
||||
+ * @return Указатель на структуру настроек
|
||||
+ */
|
||||
+RGBBacklightSettings* rgb_backlight_get_settings(void);
|
||||
+
|
||||
+/**
|
||||
+ * @brief Загрузить настройки подсветки с SD-карты
|
||||
+ */
|
||||
+void rgb_backlight_load_settings(void);
|
||||
+
|
||||
+/**
|
||||
+ * @brief Сохранить текущие настройки RGB-подсветки
|
||||
+ */
|
||||
+void rgb_backlight_save_settings(void);
|
||||
+
|
||||
+/**
|
||||
+ * @brief Применить текущие настройки RGB-подсветки
|
||||
+ *
|
||||
+ * @param brightness Яркость свечения (0-255)
|
||||
+ * @param bypass Применить настройки принудительно
|
||||
+ */
|
||||
+void rgb_backlight_update(uint8_t brightness, bool bypass);
|
||||
+
|
||||
+/**
|
||||
+ * @brief Установить цвет RGB-подсветки
|
||||
+ *
|
||||
+ * @param color_index Индекс цвета (0 - rgb_backlight_get_color_count())
|
||||
+ */
|
||||
+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 Получить количество доступных цветов
|
||||
+ *
|
||||
+ * @return Число доступных вариантов цвета
|
||||
+ */
|
||||
+uint8_t rgb_backlight_get_color_count(void);
|
||||
+
|
||||
+/**
|
||||
+ * @brief Получить текстовое название цвета
|
||||
+ *
|
||||
+ * @param index Индекс из доступных вариантов цвета
|
||||
+ * @return Указатель на строку с названием цвета
|
||||
+ */
|
||||
+const char* rgb_backlight_get_color_text(uint8_t index);
|
||||
diff --git a/lib/drivers/SK6805.c b/lib/drivers/SK6805.c
|
||||
new file mode 100644
|
||||
index 0000000..b89f82a
|
||||
--- /dev/null
|
||||
+++ b/lib/drivers/SK6805.c
|
||||
@@ -0,0 +1,101 @@
|
||||
+/*
|
||||
+ SK6805 FlipperZero driver
|
||||
+ Copyright (C) 2022-2023 Victor Nikitchuk (https://github.com/quen0n)
|
||||
+
|
||||
+ This program is free software: you can redistribute it and/or modify
|
||||
+ it under the terms of the GNU General Public License as published by
|
||||
+ the Free Software Foundation, either version 3 of the License, or
|
||||
+ (at your option) any later version.
|
||||
+
|
||||
+ This program is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
+ GNU General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU General Public License
|
||||
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
+*/
|
||||
+
|
||||
+#include "SK6805.h"
|
||||
+#include <furi_hal.h>
|
||||
+
|
||||
+/* Настройки */
|
||||
+#define SK6805_LED_COUNT 3 //Количество светодиодов на плате подсветки
|
||||
+#define SK6805_LED_PIN &led_pin //Порт подключения светодиодов
|
||||
+
|
||||
+#ifdef FURI_DEBUG
|
||||
+#define DEBUG_PIN &gpio_ext_pa7
|
||||
+#define DEBUG_INIT() \
|
||||
+ furi_hal_gpio_init(DEBUG_PIN, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh)
|
||||
+#define DEBUG_SET_HIGH() furi_hal_gpio_write(DEBUG_PIN, true)
|
||||
+#define DEBUG_SET_LOW() furi_hal_gpio_write(DEBUG_PIN, false)
|
||||
+#else
|
||||
+#define DEBUG_INIT()
|
||||
+#define DEBUG_SET_HIGH()
|
||||
+#define DEBUG_SET_LOW()
|
||||
+#endif
|
||||
+
|
||||
+static const GpioPin led_pin = {.port = GPIOA, .pin = LL_GPIO_PIN_8};
|
||||
+static uint8_t led_buffer[SK6805_LED_COUNT][3];
|
||||
+
|
||||
+void SK6805_init(void) {
|
||||
+ DEBUG_INIT();
|
||||
+ furi_hal_gpio_write(SK6805_LED_PIN, false);
|
||||
+ furi_hal_gpio_init(SK6805_LED_PIN, GpioModeOutputPushPull, GpioPullNo, GpioSpeedVeryHigh);
|
||||
+}
|
||||
+
|
||||
+uint8_t SK6805_get_led_count(void) {
|
||||
+ return (const uint8_t)SK6805_LED_COUNT;
|
||||
+}
|
||||
+void SK6805_set_led_color(uint8_t led_index, uint8_t r, uint8_t g, uint8_t b) {
|
||||
+ furi_check(led_index < SK6805_LED_COUNT);
|
||||
+
|
||||
+ led_buffer[led_index][0] = g;
|
||||
+ led_buffer[led_index][1] = r;
|
||||
+ led_buffer[led_index][2] = b;
|
||||
+}
|
||||
+
|
||||
+void SK6805_update(void) {
|
||||
+ SK6805_init();
|
||||
+ FURI_CRITICAL_ENTER();
|
||||
+ uint32_t end;
|
||||
+ /* Последовательная отправка цветов светодиодов */
|
||||
+ for(uint8_t lednumber = 0; lednumber < SK6805_LED_COUNT; lednumber++) {
|
||||
+ //Последовательная отправка цветов светодиода
|
||||
+ for(uint8_t color = 0; color < 3; color++) {
|
||||
+ //Последовательная отправка битов цвета
|
||||
+ uint8_t i = 0b10000000;
|
||||
+ while(i != 0) {
|
||||
+ if(led_buffer[lednumber][color] & (i)) {
|
||||
+ furi_hal_gpio_write(SK6805_LED_PIN, true);
|
||||
+ DEBUG_SET_HIGH();
|
||||
+ end = DWT->CYCCNT + 30;
|
||||
+ //T1H 600 us (615 us)
|
||||
+ while(DWT->CYCCNT < end) {
|
||||
+ }
|
||||
+ furi_hal_gpio_write(SK6805_LED_PIN, false);
|
||||
+ DEBUG_SET_LOW();
|
||||
+ end = DWT->CYCCNT + 26;
|
||||
+ //T1L 600 us (587 us)
|
||||
+ while(DWT->CYCCNT < end) {
|
||||
+ }
|
||||
+ } else {
|
||||
+ furi_hal_gpio_write(SK6805_LED_PIN, true);
|
||||
+ DEBUG_SET_HIGH();
|
||||
+ end = DWT->CYCCNT + 11;
|
||||
+ //T0H 300 ns (312 ns)
|
||||
+ while(DWT->CYCCNT < end) {
|
||||
+ }
|
||||
+ furi_hal_gpio_write(SK6805_LED_PIN, false);
|
||||
+ DEBUG_SET_LOW();
|
||||
+ end = DWT->CYCCNT + 43;
|
||||
+ //T0L 900 ns (890 ns)
|
||||
+ while(DWT->CYCCNT < end) {
|
||||
+ }
|
||||
+ }
|
||||
+ i >>= 1;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ FURI_CRITICAL_EXIT();
|
||||
+}
|
||||
diff --git a/lib/drivers/SK6805.h b/lib/drivers/SK6805.h
|
||||
new file mode 100644
|
||||
index 0000000..c97054f
|
||||
--- /dev/null
|
||||
+++ b/lib/drivers/SK6805.h
|
||||
@@ -0,0 +1,51 @@
|
||||
+/*
|
||||
+ SK6805 FlipperZero driver
|
||||
+ Copyright (C) 2022-2023 Victor Nikitchuk (https://github.com/quen0n)
|
||||
+
|
||||
+ This program is free software: you can redistribute it and/or modify
|
||||
+ it under the terms of the GNU General Public License as published by
|
||||
+ the Free Software Foundation, either version 3 of the License, or
|
||||
+ (at your option) any later version.
|
||||
+
|
||||
+ This program is distributed in the hope that it will be useful,
|
||||
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
+ GNU General Public License for more details.
|
||||
+
|
||||
+ You should have received a copy of the GNU General Public License
|
||||
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
+*/
|
||||
+
|
||||
+#ifndef SK6805_H_
|
||||
+#define SK6805_H_
|
||||
+
|
||||
+#include <furi.h>
|
||||
+
|
||||
+/**
|
||||
+ * @brief Инициализация линии управления подсветкой
|
||||
+ */
|
||||
+void SK6805_init(void);
|
||||
+
|
||||
+/**
|
||||
+ * @brief Получить количество светодиодов в подсветке
|
||||
+ *
|
||||
+ * @return Количество светодиодов
|
||||
+ */
|
||||
+uint8_t SK6805_get_led_count(void);
|
||||
+
|
||||
+/**
|
||||
+ * @brief Установить цвет свечения светодиода
|
||||
+ *
|
||||
+ * @param led_index номер светодиода (от 0 до SK6805_get_led_count())
|
||||
+ * @param r значение красного (0-255)
|
||||
+ * @param g значение зелёного (0-255)
|
||||
+ * @param b значение синего (0-255)
|
||||
+ */
|
||||
+void SK6805_set_led_color(uint8_t led_index, uint8_t r, uint8_t g, uint8_t b);
|
||||
+
|
||||
+/**
|
||||
+ * @brief Обновление состояния подсветки дисплея
|
||||
+ */
|
||||
+void SK6805_update(void);
|
||||
+
|
||||
+#endif /* SK6805_H_ */
|
||||
diff --git a/targets/f7/furi_hal/furi_hal_light.c b/targets/f7/furi_hal/furi_hal_light.c
|
||||
index 621478d..ef15153 100644
|
||||
--- a/targets/f7/furi_hal/furi_hal_light.c
|
||||
+++ b/targets/f7/furi_hal/furi_hal_light.c
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <furi_hal_light.h>
|
||||
#include <lp5562.h>
|
||||
#include <stdint.h>
|
||||
+#include <applications/settings/notification_settings/rgb_backlight.h>
|
||||
|
||||
#define LED_CURRENT_RED (50u)
|
||||
#define LED_CURRENT_GREEN (50u)
|
||||
@@ -31,22 +32,21 @@ void furi_hal_light_init(void) {
|
||||
}
|
||||
|
||||
void furi_hal_light_set(Light light, uint8_t value) {
|
||||
- furi_hal_i2c_acquire(&furi_hal_i2c_handle_power);
|
||||
- if(light & LightRed) {
|
||||
- lp5562_set_channel_value(&furi_hal_i2c_handle_power, LP5562ChannelRed, value);
|
||||
- }
|
||||
- if(light & LightGreen) {
|
||||
- lp5562_set_channel_value(&furi_hal_i2c_handle_power, LP5562ChannelGreen, value);
|
||||
- }
|
||||
- if(light & LightBlue) {
|
||||
- lp5562_set_channel_value(&furi_hal_i2c_handle_power, LP5562ChannelBlue, value);
|
||||
- }
|
||||
if(light & LightBacklight) {
|
||||
- uint8_t prev = lp5562_get_channel_value(&furi_hal_i2c_handle_power, LP5562ChannelWhite);
|
||||
- lp5562_execute_ramp(
|
||||
- &furi_hal_i2c_handle_power, LP5562Engine1, LP5562ChannelWhite, prev, value, 100);
|
||||
+ rgb_backlight_update(value, false);
|
||||
+ } else {
|
||||
+ furi_hal_i2c_acquire(&furi_hal_i2c_handle_power);
|
||||
+ if(light & LightRed) {
|
||||
+ lp5562_set_channel_value(&furi_hal_i2c_handle_power, LP5562ChannelRed, value);
|
||||
+ }
|
||||
+ if(light & LightGreen) {
|
||||
+ lp5562_set_channel_value(&furi_hal_i2c_handle_power, LP5562ChannelGreen, value);
|
||||
+ }
|
||||
+ if(light & LightBlue) {
|
||||
+ lp5562_set_channel_value(&furi_hal_i2c_handle_power, LP5562ChannelBlue, value);
|
||||
+ }
|
||||
+ furi_hal_i2c_release(&furi_hal_i2c_handle_power);
|
||||
}
|
||||
- furi_hal_i2c_release(&furi_hal_i2c_handle_power);
|
||||
}
|
||||
|
||||
void furi_hal_light_blink_start(Light light, uint8_t brightness, uint16_t on_time, uint16_t period) {
|
||||
125
.clang-format
125
.clang-format
@@ -3,55 +3,22 @@ Language: Cpp
|
||||
AccessModifierOffset: -4
|
||||
AlignAfterOpenBracket: AlwaysBreak
|
||||
AlignArrayOfStructures: None
|
||||
AlignConsecutiveAssignments:
|
||||
Enabled: false
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCompound: false
|
||||
AlignFunctionPointers: false
|
||||
PadOperators: true
|
||||
AlignConsecutiveBitFields:
|
||||
Enabled: true
|
||||
AcrossEmptyLines: true
|
||||
AcrossComments: true
|
||||
AlignCompound: false
|
||||
AlignFunctionPointers: false
|
||||
PadOperators: true
|
||||
AlignConsecutiveDeclarations:
|
||||
Enabled: false
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCompound: false
|
||||
AlignFunctionPointers: false
|
||||
PadOperators: true
|
||||
AlignConsecutiveMacros:
|
||||
Enabled: true
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: true
|
||||
AlignCompound: true
|
||||
AlignFunctionPointers: false
|
||||
PadOperators: true
|
||||
AlignConsecutiveShortCaseStatements:
|
||||
Enabled: false
|
||||
AcrossEmptyLines: false
|
||||
AcrossComments: false
|
||||
AlignCaseColons: false
|
||||
AlignConsecutiveMacros: None
|
||||
AlignConsecutiveAssignments: None
|
||||
AlignConsecutiveBitFields: None
|
||||
AlignConsecutiveDeclarations: None
|
||||
AlignEscapedNewlines: Left
|
||||
AlignOperands: Align
|
||||
AlignTrailingComments:
|
||||
Kind: Never
|
||||
OverEmptyLines: 0
|
||||
AlignTrailingComments: false
|
||||
AllowAllArgumentsOnNextLine: true
|
||||
AllowAllParametersOfDeclarationOnNextLine: false
|
||||
AllowBreakBeforeNoexceptSpecifier: Never
|
||||
AllowShortEnumsOnASingleLine: true
|
||||
AllowShortBlocksOnASingleLine: Never
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
AllowShortCompoundRequirementOnASingleLine: true
|
||||
AllowShortEnumsOnASingleLine: false
|
||||
AllowShortFunctionsOnASingleLine: None
|
||||
AllowShortIfStatementsOnASingleLine: WithoutElse
|
||||
AllowShortLambdasOnASingleLine: All
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AllowShortIfStatementsOnASingleLine: WithoutElse
|
||||
AllowShortLoopsOnASingleLine: true
|
||||
AlwaysBreakAfterDefinitionReturnType: None
|
||||
AlwaysBreakAfterReturnType: None
|
||||
AlwaysBreakBeforeMultilineStrings: false
|
||||
@@ -60,18 +27,17 @@ AttributeMacros:
|
||||
- __capability
|
||||
BinPackArguments: false
|
||||
BinPackParameters: false
|
||||
BitFieldColonSpacing: Both
|
||||
BraceWrapping:
|
||||
AfterCaseLabel: false
|
||||
AfterClass: false
|
||||
AfterControlStatement: Never
|
||||
AfterEnum: false
|
||||
AfterExternBlock: false
|
||||
AfterFunction: false
|
||||
AfterNamespace: false
|
||||
AfterObjCDeclaration: false
|
||||
AfterStruct: false
|
||||
AfterUnion: false
|
||||
AfterExternBlock: false
|
||||
BeforeCatch: false
|
||||
BeforeElse: false
|
||||
BeforeLambdaBody: false
|
||||
@@ -80,35 +46,38 @@ BraceWrapping:
|
||||
SplitEmptyFunction: true
|
||||
SplitEmptyRecord: true
|
||||
SplitEmptyNamespace: true
|
||||
BreakAdjacentStringLiterals: true
|
||||
BreakAfterAttributes: Leave
|
||||
BreakAfterJavaFieldAnnotations: false
|
||||
BreakArrays: true
|
||||
BreakBeforeBinaryOperators: None
|
||||
BreakBeforeConceptDeclarations: Always
|
||||
BreakBeforeConceptDeclarations: true
|
||||
BreakBeforeBraces: Attach
|
||||
BreakBeforeInlineASMColon: OnlyMultiline
|
||||
BreakBeforeTernaryOperators: false
|
||||
BreakConstructorInitializers: BeforeComma
|
||||
BreakBeforeInheritanceComma: false
|
||||
BreakInheritanceList: BeforeColon
|
||||
BreakBeforeTernaryOperators: false
|
||||
BreakConstructorInitializersBeforeComma: false
|
||||
BreakConstructorInitializers: BeforeComma
|
||||
BreakAfterJavaFieldAnnotations: false
|
||||
BreakStringLiterals: false
|
||||
ColumnLimit: 99
|
||||
CommentPragmas: '^ IWYU pragma:'
|
||||
QualifierAlignment: Leave
|
||||
CompactNamespaces: false
|
||||
ConstructorInitializerIndentWidth: 4
|
||||
ContinuationIndentWidth: 4
|
||||
Cpp11BracedListStyle: true
|
||||
DeriveLineEnding: true
|
||||
DerivePointerAlignment: false
|
||||
DisableFormat: false
|
||||
EmptyLineAfterAccessModifier: Never
|
||||
EmptyLineBeforeAccessModifier: LogicalBlock
|
||||
ExperimentalAutoDetectBinPacking: false
|
||||
PackConstructorInitializers: BinPack
|
||||
BasedOnStyle: ''
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
||||
AllowAllConstructorInitializersOnNextLine: true
|
||||
FixNamespaceComments: false
|
||||
ForEachMacros:
|
||||
- foreach
|
||||
- Q_FOREACH
|
||||
- BOOST_FOREACH
|
||||
- M_EACH
|
||||
IfMacros:
|
||||
- KJ_IF_MAYBE
|
||||
IncludeBlocks: Preserve
|
||||
@@ -128,30 +97,19 @@ IncludeCategories:
|
||||
IncludeIsMainRegex: '(Test)?$'
|
||||
IncludeIsMainSourceRegex: ''
|
||||
IndentAccessModifiers: false
|
||||
IndentCaseBlocks: false
|
||||
IndentCaseLabels: false
|
||||
IndentExternBlock: AfterExternBlock
|
||||
IndentCaseBlocks: false
|
||||
IndentGotoLabels: true
|
||||
IndentPPDirectives: None
|
||||
IndentRequiresClause: false
|
||||
IndentExternBlock: AfterExternBlock
|
||||
IndentRequires: false
|
||||
IndentWidth: 4
|
||||
IndentWrappedFunctionNames: true
|
||||
InsertBraces: false
|
||||
InsertNewlineAtEOF: true
|
||||
InsertTrailingCommas: None
|
||||
IntegerLiteralSeparator:
|
||||
Binary: 0
|
||||
BinaryMinDigits: 0
|
||||
Decimal: 0
|
||||
DecimalMinDigits: 0
|
||||
Hex: 0
|
||||
HexMinDigits: 0
|
||||
JavaScriptQuotes: Leave
|
||||
JavaScriptWrapImports: true
|
||||
KeepEmptyLinesAtTheStartOfBlocks: false
|
||||
KeepEmptyLinesAtEOF: false
|
||||
LambdaBodyIndentation: Signature
|
||||
LineEnding: DeriveLF
|
||||
MacroBlockBegin: ''
|
||||
MacroBlockEnd: ''
|
||||
MaxEmptyLinesToKeep: 1
|
||||
@@ -161,44 +119,34 @@ ObjCBlockIndentWidth: 4
|
||||
ObjCBreakBeforeNestedBlockParam: true
|
||||
ObjCSpaceAfterProperty: true
|
||||
ObjCSpaceBeforeProtocolList: true
|
||||
PackConstructorInitializers: BinPack
|
||||
PenaltyBreakAssignment: 10
|
||||
PenaltyBreakBeforeFirstCallParameter: 30
|
||||
PenaltyBreakComment: 10
|
||||
PenaltyBreakFirstLessLess: 0
|
||||
PenaltyBreakOpenParenthesis: 0
|
||||
PenaltyBreakScopeResolution: 500
|
||||
PenaltyBreakString: 10
|
||||
PenaltyBreakTemplateDeclaration: 10
|
||||
PenaltyExcessCharacter: 100
|
||||
PenaltyIndentedWhitespace: 0
|
||||
PenaltyReturnTypeOnItsOwnLine: 60
|
||||
PenaltyIndentedWhitespace: 0
|
||||
PointerAlignment: Left
|
||||
PPIndentWidth: -1
|
||||
QualifierAlignment: Leave
|
||||
ReferenceAlignment: Pointer
|
||||
ReflowComments: false
|
||||
RemoveBracesLLVM: false
|
||||
RemoveParentheses: Leave
|
||||
RemoveSemicolon: true
|
||||
RequiresClausePosition: OwnLine
|
||||
RequiresExpressionIndentation: OuterScope
|
||||
SeparateDefinitionBlocks: Leave
|
||||
ShortNamespaceLines: 1
|
||||
SkipMacroDefinitionBody: false
|
||||
SortIncludes: Never
|
||||
SortJavaStaticImport: Before
|
||||
SortUsingDeclarations: Never
|
||||
SortUsingDeclarations: false
|
||||
SpaceAfterCStyleCast: false
|
||||
SpaceAfterLogicalNot: false
|
||||
SpaceAfterTemplateKeyword: true
|
||||
SpaceAroundPointerQualifiers: Default
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
SpaceBeforeCaseColon: false
|
||||
SpaceBeforeCpp11BracedList: false
|
||||
SpaceBeforeCtorInitializerColon: true
|
||||
SpaceBeforeInheritanceColon: true
|
||||
SpaceBeforeJsonColon: false
|
||||
SpaceBeforeParens: Never
|
||||
SpaceBeforeParensOptions:
|
||||
AfterControlStatements: false
|
||||
@@ -207,35 +155,32 @@ SpaceBeforeParensOptions:
|
||||
AfterFunctionDeclarationName: false
|
||||
AfterIfMacros: false
|
||||
AfterOverloadedOperator: false
|
||||
AfterPlacementOperator: true
|
||||
AfterRequiresInClause: false
|
||||
AfterRequiresInExpression: false
|
||||
BeforeNonEmptyParentheses: false
|
||||
SpaceAroundPointerQualifiers: Default
|
||||
SpaceBeforeRangeBasedForLoopColon: true
|
||||
SpaceBeforeSquareBrackets: false
|
||||
SpaceInEmptyBlock: false
|
||||
SpaceInEmptyParentheses: false
|
||||
SpacesBeforeTrailingComments: 1
|
||||
SpacesInAngles: Never
|
||||
SpacesInConditionalStatement: false
|
||||
SpacesInContainerLiterals: false
|
||||
SpacesInCStyleCastParentheses: false
|
||||
SpacesInLineCommentPrefix:
|
||||
Minimum: 1
|
||||
Maximum: -1
|
||||
SpacesInParens: Never
|
||||
SpacesInParensOptions:
|
||||
InCStyleCasts: false
|
||||
InConditionalStatements: false
|
||||
InEmptyParentheses: false
|
||||
Other: false
|
||||
SpacesInParentheses: false
|
||||
SpacesInSquareBrackets: false
|
||||
Standard: c++20
|
||||
SpaceBeforeSquareBrackets: false
|
||||
BitFieldColonSpacing: Both
|
||||
Standard: c++03
|
||||
StatementAttributeLikeMacros:
|
||||
- Q_EMIT
|
||||
StatementMacros:
|
||||
- Q_UNUSED
|
||||
- QT_REQUIRE_VERSION
|
||||
TabWidth: 4
|
||||
UseCRLF: false
|
||||
UseTab: Never
|
||||
VerilogBreakBetweenInstancePorts: true
|
||||
WhitespaceSensitiveMacros:
|
||||
- STRINGIZE
|
||||
- PP_STRINGIZE
|
||||
|
||||
17
.clangd
17
.clangd
@@ -1,17 +0,0 @@
|
||||
CompileFlags:
|
||||
Add:
|
||||
- -Wno-unknown-warning-option
|
||||
- -Wno-format
|
||||
Remove:
|
||||
- -mword-relocations
|
||||
|
||||
Diagnostics:
|
||||
ClangTidy:
|
||||
FastCheckFilter: None
|
||||
|
||||
---
|
||||
|
||||
If:
|
||||
PathMatch: .*\.h
|
||||
Diagnostics:
|
||||
UnusedIncludes: None
|
||||
405
.drone.yml
405
.drone.yml
@@ -11,53 +11,27 @@ steps:
|
||||
image: alpine/git
|
||||
commands:
|
||||
- git submodule sync
|
||||
- git -c protocol.version=2 submodule update --init --force --recursive --jobs 4
|
||||
- git -c protocol.version=2 submodule update --init --force --recursive
|
||||
- git submodule foreach git config --local gc.auto 0
|
||||
- git log -1 --format='%H'
|
||||
|
||||
- name: "Build clean"
|
||||
image: hfdj/fztools
|
||||
pull: never
|
||||
commands:
|
||||
- export DIST_SUFFIX=${DRONE_TAG}c
|
||||
- export WORKFLOW_BRANCH_OR_TAG=release-cfw
|
||||
- export FORCE_NO_DIRTY=yes
|
||||
- export FBT_GIT_SUBMODULE_SHALLOW=1
|
||||
- rm -rf applications/main/clock_app/resources/apps/
|
||||
- rm -rf build/
|
||||
- rm -rf dist/
|
||||
- rm -rf .sconsign.dblite
|
||||
- ./fbt COMPACT=1 DEBUG=0 updater_package
|
||||
- mkdir artifacts-clean
|
||||
- mv dist/f7-C/* artifacts-clean/
|
||||
- ls -laS artifacts-clean
|
||||
- ls -laS artifacts-clean/f7-update-${DRONE_TAG}c
|
||||
environment:
|
||||
FBT_TOOLS_CUSTOM_LINK:
|
||||
from_secret: fbt_link
|
||||
|
||||
- name: "Build default"
|
||||
- name: "Build firmware"
|
||||
image: hfdj/fztools
|
||||
pull: never
|
||||
commands:
|
||||
- export DIST_SUFFIX=${DRONE_TAG}
|
||||
- export WORKFLOW_BRANCH_OR_TAG=release-cfw
|
||||
- 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
|
||||
- tar zxf all-the-apps-base.tgz
|
||||
- mkdir -p applications/main/clock_app/resources/apps
|
||||
- mkdir -p applications/main/clock_app/resources/apps_data
|
||||
- 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 all-the-apps-base.tgz
|
||||
- rm -f build/f7-firmware-C/toolbox/version.*
|
||||
- ./fbt COMPACT=1 DEBUG=0 updater_package
|
||||
- mkdir artifacts-default
|
||||
- mv dist/f7-C/* artifacts-default/
|
||||
- ls -laS artifacts-default
|
||||
- ls -laS artifacts-default/f7-update-${DRONE_TAG}
|
||||
- sed -i 's/(version)/'${DRONE_TAG}'/g' CHANGELOG.md
|
||||
- echo '# [Install via Web Updater](https://lab.flipper.net/?url=https://unleashedflip.com/fw/${DRONE_TAG}/flipper-z-f7-update-'${DRONE_TAG}'.tgz&channel=release-cfw&version='${DRONE_TAG}')' >> CHANGELOG.md
|
||||
- echo '' >> CHANGELOG.md
|
||||
- echo '### [Version without custom animations - Install via Web Updater](https://lab.flipper.net/?url=https://unleashedflip.com/fw_no_anim/flipper-z-f7-update-'${DRONE_TAG}'n.tgz&channel=release-cfw&version='${DRONE_TAG}'n)' >> CHANGELOG.md
|
||||
- echo '' >> CHANGELOG.md
|
||||
- echo '### [Version with extra apps - Install via Web Updater](https://lab.flipper.net/?url=https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-'${DRONE_TAG}'e.tgz&channel=release-cfw&version='${DRONE_TAG}'e)' >> CHANGELOG.md
|
||||
environment:
|
||||
FBT_TOOLS_CUSTOM_LINK:
|
||||
from_secret: fbt_link
|
||||
@@ -66,15 +40,12 @@ steps:
|
||||
image: hfdj/fztools
|
||||
pull: never
|
||||
commands:
|
||||
- wget https://github.com/xMasterX/all-the-plugins/releases/latest/download/all-the-apps-extra.tgz
|
||||
- tar zxf all-the-apps-extra.tgz
|
||||
- mkdir -p applications/main/clock_app/resources/apps
|
||||
- cp -R extra_pack_build/artifacts-extra/* applications/main/clock_app/resources/apps/
|
||||
- rm -rf extra_pack_build
|
||||
- git clone https://github.com/xMasterX/unleashed-extra-pack.git
|
||||
- cp -R unleashed-extra-pack/apps/* assets/resources/apps/
|
||||
- rm -rf unleashed-extra-pack
|
||||
- export DIST_SUFFIX=${DRONE_TAG}e
|
||||
- export WORKFLOW_BRANCH_OR_TAG=release-cfw
|
||||
- export FORCE_NO_DIRTY=yes
|
||||
- export FBT_GIT_SUBMODULE_SHALLOW=1
|
||||
- rm -f build/f7-firmware-C/toolbox/version.*
|
||||
- ./fbt COMPACT=1 DEBUG=0 updater_package
|
||||
- mkdir artifacts-extra-apps
|
||||
@@ -85,53 +56,41 @@ steps:
|
||||
FBT_TOOLS_CUSTOM_LINK:
|
||||
from_secret: fbt_link
|
||||
|
||||
- name: "Build with RGB patch"
|
||||
- name: "Build with ofw anims"
|
||||
image: hfdj/fztools
|
||||
pull: never
|
||||
commands:
|
||||
- git apply .ci_files/rgb.patch
|
||||
- export DIST_SUFFIX=${DRONE_TAG}r
|
||||
- export WORKFLOW_BRANCH_OR_TAG=release-cfw-rgb
|
||||
- rm -f assets/dolphin/external/manifest.txt
|
||||
- cp .ci_files/anims_ofw.txt assets/dolphin/external/manifest.txt
|
||||
- rm -rf assets/resources/apps/
|
||||
- export DIST_SUFFIX=${DRONE_TAG}n
|
||||
- export WORKFLOW_BRANCH_OR_TAG=no-custom-anims
|
||||
- export FORCE_NO_DIRTY=yes
|
||||
- export FBT_GIT_SUBMODULE_SHALLOW=1
|
||||
- rm -f build/f7-firmware-C/toolbox/version.*
|
||||
- ./fbt COMPACT=1 DEBUG=0 updater_package
|
||||
- mkdir artifacts-rgb-patch
|
||||
- mv dist/f7-C/* artifacts-rgb-patch/
|
||||
- ls -laS artifacts-rgb-patch
|
||||
- ls -laS artifacts-rgb-patch/f7-update-${DRONE_TAG}r
|
||||
- sed -i 's/(version)/'${DRONE_TAG}'/g' CHANGELOG.md
|
||||
- echo '# Install FW via Web Updater:' >> CHANGELOG.md
|
||||
- echo '### [Default](https://lab.flipper.net/?url=https://unleashedflip.com/fw/${DRONE_TAG}/flipper-z-f7-update-'${DRONE_TAG}'.tgz&channel=release-cfw&version='${DRONE_TAG}') > ` `' >> CHANGELOG.md
|
||||
- echo '' >> CHANGELOG.md
|
||||
- echo '### [Extra apps](https://lab.flipper.net/?url=https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-'${DRONE_TAG}'e.tgz&channel=release-cfw&version='${DRONE_TAG}'e) > `e`' >> CHANGELOG.md
|
||||
- echo '' >> CHANGELOG.md
|
||||
- echo '### [No apps](https://lab.flipper.net/?url=https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-'${DRONE_TAG}'c.tgz&channel=release-cfw&version='${DRONE_TAG}'c) > `c`' >> CHANGELOG.md
|
||||
- echo '' >> CHANGELOG.md
|
||||
- echo '### [RGB patch - only for hardware mod!](https://lab.flipper.net/?url=https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-'${DRONE_TAG}'r.tgz&channel=release-cfw&version='${DRONE_TAG}'r) > `r`' >> CHANGELOG.md
|
||||
- mkdir artifacts-ofw-anims
|
||||
- mv dist/f7-C/* artifacts-ofw-anims/
|
||||
- ls -laS artifacts-ofw-anims
|
||||
- ls -laS artifacts-ofw-anims/f7-update-${DRONE_TAG}n
|
||||
environment:
|
||||
FBT_TOOLS_CUSTOM_LINK:
|
||||
from_secret: fbt_link
|
||||
|
||||
- name: "Bundle self-update packages"
|
||||
image: joshkeegan/zip
|
||||
image: kramos/alpine-zip
|
||||
commands:
|
||||
- cp artifacts-extra-apps/flipper-z-f7-update-${DRONE_TAG}e.tgz .
|
||||
- cp artifacts-rgb-patch/flipper-z-f7-update-${DRONE_TAG}r.tgz .
|
||||
- cp artifacts-clean/flipper-z-f7-update-${DRONE_TAG}c.tgz .
|
||||
- cp artifacts-ofw-anims/flipper-z-f7-update-${DRONE_TAG}n.tgz .
|
||||
- cp artifacts-default/flipper-z-f7-update-${DRONE_TAG}.tgz .
|
||||
- zip -r artifacts-extra-apps/flipper-z-f7-update-${DRONE_TAG}e.zip artifacts-extra-apps/f7-update-${DRONE_TAG}e
|
||||
- zip -r artifacts-rgb-patch/flipper-z-f7-update-${DRONE_TAG}r.zip artifacts-rgb-patch/f7-update-${DRONE_TAG}r
|
||||
- zip -r artifacts-clean/flipper-z-f7-update-${DRONE_TAG}c.zip artifacts-clean/f7-update-${DRONE_TAG}c
|
||||
- zip -r artifacts-ofw-anims/flipper-z-f7-update-${DRONE_TAG}n.zip artifacts-ofw-anims/f7-update-${DRONE_TAG}n
|
||||
- zip -r artifacts-default/flipper-z-f7-update-${DRONE_TAG}.zip artifacts-default/f7-update-${DRONE_TAG}
|
||||
- tar czpf artifacts-default/flipper-z-any-scripts-${DRONE_TAG}.tgz scripts
|
||||
- tar czpf artifacts-default/flipper-z-any-scripts-${DRONE_TAG}.tgz scripts debug
|
||||
- rm -rf artifacts-extra-apps/f7-update-${DRONE_TAG}
|
||||
- rm -rf artifacts-rgb-patch/f7-update-${DRONE_TAG}
|
||||
- rm -rf artifacts-clean/f7-update-${DRONE_TAG}
|
||||
- rm -rf artifacts-ofw-anims/f7-update-${DRONE_TAG}
|
||||
- rm -rf artifacts-default/f7-update-${DRONE_TAG}
|
||||
- ls -laS artifacts-extra-apps
|
||||
- ls -laS artifacts-rgb-patch
|
||||
- ls -laS artifacts-clean
|
||||
- ls -laS artifacts-ofw-anims
|
||||
- ls -laS artifacts-default
|
||||
- mv artifacts-default/ ${DRONE_TAG}
|
||||
- ls -laS ${DRONE_TAG}
|
||||
@@ -157,6 +116,21 @@ steps:
|
||||
- ${DRONE_TAG}/*.dfu
|
||||
- ${DRONE_TAG}/*.bin
|
||||
|
||||
- name: "Upload no-anims to updates srv"
|
||||
image: appleboy/drone-scp:linux-amd64
|
||||
settings:
|
||||
host:
|
||||
from_secret: dep_host
|
||||
username:
|
||||
from_secret: dep_user
|
||||
password:
|
||||
from_secret: dep_passwd
|
||||
port:
|
||||
from_secret: dep_port
|
||||
target:
|
||||
from_secret: dep_target_noanim
|
||||
source: flipper-z-f7-update-${DRONE_TAG}n.tgz
|
||||
|
||||
- name: "Upload extra apps version to updates srv"
|
||||
image: appleboy/drone-scp:linux-amd64
|
||||
settings:
|
||||
@@ -172,36 +146,6 @@ steps:
|
||||
from_secret: dep_target_extra
|
||||
source: flipper-z-f7-update-${DRONE_TAG}e.tgz
|
||||
|
||||
- name: "Upload rgb patch version to updates srv"
|
||||
image: appleboy/drone-scp:linux-amd64
|
||||
settings:
|
||||
host:
|
||||
from_secret: dep_host
|
||||
username:
|
||||
from_secret: dep_user
|
||||
password:
|
||||
from_secret: dep_passwd
|
||||
port:
|
||||
from_secret: dep_port
|
||||
target:
|
||||
from_secret: dep_target_extra
|
||||
source: flipper-z-f7-update-${DRONE_TAG}r.tgz
|
||||
|
||||
- name: "Upload clean version to updates srv"
|
||||
image: appleboy/drone-scp:linux-amd64
|
||||
settings:
|
||||
host:
|
||||
from_secret: dep_host
|
||||
username:
|
||||
from_secret: dep_user
|
||||
password:
|
||||
from_secret: dep_passwd
|
||||
port:
|
||||
from_secret: dep_port
|
||||
target:
|
||||
from_secret: dep_target_extra
|
||||
source: flipper-z-f7-update-${DRONE_TAG}c.tgz
|
||||
|
||||
- name: "Do Github release"
|
||||
image: ddplugins/github-release
|
||||
pull: never
|
||||
@@ -214,9 +158,8 @@ steps:
|
||||
files:
|
||||
- ${DRONE_TAG}/*.tgz
|
||||
- ${DRONE_TAG}/*.zip
|
||||
- artifacts-ofw-anims/*.tgz
|
||||
- artifacts-extra-apps/*.tgz
|
||||
- artifacts-rgb-patch/*.tgz
|
||||
- artifacts-clean/*.tgz
|
||||
title: ${DRONE_TAG}
|
||||
note: CHANGELOG.md
|
||||
checksum:
|
||||
@@ -235,6 +178,39 @@ steps:
|
||||
commands:
|
||||
- curl -X POST -F 'key='$UPD_KEY'' $UPD_URL
|
||||
|
||||
- name: "Send files to telegram"
|
||||
image: appleboy/drone-telegram
|
||||
settings:
|
||||
token:
|
||||
from_secret: tgtoken
|
||||
to:
|
||||
from_secret: tgid
|
||||
format: markdown
|
||||
message: "New Unleashed firmware released!
|
||||
|
||||
|
||||
Version: {{build.tag}}
|
||||
|
||||
|
||||
[-Github - Changelog-](https://github.com/DarkFlippers/unleashed-firmware/releases/tag/${DRONE_TAG})
|
||||
|
||||
|
||||
[-How to install firmware-](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/HowToInstall.md)
|
||||
|
||||
|
||||
[-Download latest extra apps pack-](https://download-directory.github.io/?url=https://github.com/xMasterX/unleashed-extra-pack/tree/main/apps)
|
||||
|
||||
|
||||
[-Install FW via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw/${DRONE_TAG}/flipper-z-f7-update-${DRONE_TAG}.tgz&channel=release-cfw&version=${DRONE_TAG})
|
||||
|
||||
|
||||
[-Version without custom animations - Install FW via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw_no_anim/flipper-z-f7-update-${DRONE_TAG}n.tgz&channel=release-cfw&version=${DRONE_TAG}n)
|
||||
|
||||
|
||||
[-Version with extra apps - Install FW via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-${DRONE_TAG}e.tgz&channel=release-cfw&version=${DRONE_TAG}e)"
|
||||
document:
|
||||
- ${DRONE_TAG}/flipper-z-f7-update-${DRONE_TAG}.tgz
|
||||
|
||||
- name: "Send discord notification"
|
||||
image: hfdj/fztools
|
||||
pull: never
|
||||
@@ -242,54 +218,9 @@ steps:
|
||||
DISCORD_WEBHOOK:
|
||||
from_secret: dis_release_webhook
|
||||
commands:
|
||||
- wget "https://raw.githubusercontent.com/fieu/discord.sh/2253303efc0e7211ac2777d2535054cbb872f1e0/discord.sh"
|
||||
- wget "https://raw.githubusercontent.com/fieu/discord.sh/e1dc1a7595efad2cad8f072f0b3531c470f5b7c8/discord.sh"
|
||||
- chmod +x ./discord.sh
|
||||
- sed -n '/## Main changes/,/## Other changes/p' CHANGELOG.md | sed -e 's/## Main changes//' -e 's/## Other changes//' > changelogcut.txt
|
||||
- head -c 1544 changelogcut.txt > changelogcutfin.txt
|
||||
- truncate -s -1 changelogcutfin.txt
|
||||
- tail -c +2 changelogcutfin.txt > changelogready.txt
|
||||
- rm -f changelogcut.txt
|
||||
- rm -f changelogcutfin.txt
|
||||
- echo '' >> changelogready.txt
|
||||
- echo '## [Read full changelog](https://github.com/DarkFlippers/unleashed-firmware/releases/tag/'${DRONE_TAG}')' >> changelogready.txt
|
||||
- sed -i 's/(releasever)/'${DRONE_TAG}'/g' .ci_files/release_msg_discord.txt
|
||||
- sed -i 's/(releasever)/'${DRONE_TAG}'/g' .ci_files/release_msg_telegram.txt
|
||||
- cp .ci_files/release_msg_telegram.txt tg_release_message.tpl
|
||||
- ./discord.sh --title "Main changes" --description "$(jq -Rs . <changelogready.txt | cut -c 2- | rev | cut -c 2- | rev)" --timestamp --text "$(jq -Rs . <.ci_files/release_msg_discord.txt | cut -c 2- | rev | cut -c 2- | rev)"
|
||||
|
||||
- name: "Send notification to telegram"
|
||||
image: appleboy/drone-telegram
|
||||
settings:
|
||||
token:
|
||||
from_secret: tgtoken
|
||||
to:
|
||||
from_secret: tgid
|
||||
format: markdown
|
||||
message_file: tg_release_message.tpl
|
||||
|
||||
- name: "Send default build to telegram"
|
||||
image: appleboy/drone-telegram
|
||||
settings:
|
||||
token:
|
||||
from_secret: tgtoken
|
||||
to:
|
||||
from_secret: tgid
|
||||
format: markdown
|
||||
message: "Default build:"
|
||||
document:
|
||||
- ${DRONE_TAG}/flipper-z-f7-update-${DRONE_TAG}.tgz
|
||||
|
||||
- name: "Send clean build to telegram"
|
||||
image: appleboy/drone-telegram
|
||||
settings:
|
||||
token:
|
||||
from_secret: tgtoken
|
||||
to:
|
||||
from_secret: tgid
|
||||
format: markdown
|
||||
message: "Build with only main apps:"
|
||||
document:
|
||||
- flipper-z-f7-update-${DRONE_TAG}c.tgz
|
||||
- ./discord.sh --text 'New Unleashed firmware released!\n\nVersion - '${DRONE_TAG}'\n\n[[Github - Changelog]](https://github.com/DarkFlippers/unleashed-firmware/releases/tag/'${DRONE_TAG}')\n\n[-How to install firmware-](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/HowToInstall.md)\n\n[-Download latest extra apps pack-](https://download-directory.github.io/?url=https://github.com/xMasterX/unleashed-extra-pack/tree/main/apps)\n\n[-Install FW via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw/'${DRONE_TAG}'/flipper-z-f7-update-'${DRONE_TAG}'.tgz&channel=release-cfw&version='${DRONE_TAG}')\n\n[-Version without custom animations - Install FW via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw_no_anim/flipper-z-f7-update-'${DRONE_TAG}'n.tgz&channel=release-cfw&version='${DRONE_TAG}'n)\n\n[-Version with extra apps - Install FW via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-'${DRONE_TAG}'e.tgz&channel=release-cfw&version='${DRONE_TAG}'e)'
|
||||
|
||||
- name: "Send extra pack build to telegram"
|
||||
image: appleboy/drone-telegram
|
||||
@@ -299,7 +230,7 @@ steps:
|
||||
to:
|
||||
from_secret: tgid
|
||||
format: markdown
|
||||
message: "Build with extra apps:"
|
||||
message: "Build with extra apps pack:"
|
||||
document:
|
||||
- flipper-z-f7-update-${DRONE_TAG}e.tgz
|
||||
|
||||
@@ -308,7 +239,7 @@ trigger:
|
||||
- tag
|
||||
|
||||
node:
|
||||
typ: dev2
|
||||
typ: haupt
|
||||
|
||||
---
|
||||
kind: pipeline
|
||||
@@ -324,49 +255,16 @@ steps:
|
||||
image: alpine/git
|
||||
commands:
|
||||
- git submodule sync
|
||||
- git -c protocol.version=2 submodule update --init --force --recursive --jobs 4
|
||||
- git -c protocol.version=2 submodule update --init --force --recursive
|
||||
- git submodule foreach git config --local gc.auto 0
|
||||
- git log -1 --format='%H'
|
||||
|
||||
- name: "Build dev clean"
|
||||
image: hfdj/fztools
|
||||
pull: never
|
||||
commands:
|
||||
- export DIST_SUFFIX=${DRONE_BUILD_NUMBER}c
|
||||
- export WORKFLOW_BRANCH_OR_TAG=dev-cfw
|
||||
- export FORCE_NO_DIRTY=yes
|
||||
- export FBT_GIT_SUBMODULE_SHALLOW=1
|
||||
- rm -rf applications/main/clock_app/resources/apps/
|
||||
- rm -rf build/
|
||||
- rm -rf dist/
|
||||
- rm -rf .sconsign.dblite
|
||||
- ./fbt COMPACT=1 DEBUG=0 updater_package
|
||||
- mkdir artifacts-clean
|
||||
- mv dist/f7-C/* artifacts-clean/
|
||||
- ls -laS artifacts-clean
|
||||
- ls -laS artifacts-clean/f7-update-${DRONE_BUILD_NUMBER}c
|
||||
environment:
|
||||
FBT_TOOLS_CUSTOM_LINK:
|
||||
from_secret: fbt_link
|
||||
|
||||
|
||||
- name: "Build dev default"
|
||||
- name: "Build dev FW"
|
||||
image: hfdj/fztools
|
||||
pull: never
|
||||
commands:
|
||||
- export DIST_SUFFIX=${DRONE_BUILD_NUMBER}
|
||||
- export WORKFLOW_BRANCH_OR_TAG=dev-cfw
|
||||
- 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
|
||||
- tar zxf all-the-apps-base.tgz
|
||||
- mkdir -p applications/main/clock_app/resources/apps
|
||||
- mkdir -p applications/main/clock_app/resources/apps_data
|
||||
- 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 all-the-apps-base.tgz
|
||||
- rm -f build/f7-firmware-C/toolbox/version.*
|
||||
- ./fbt COMPACT=1 DEBUG=0 updater_package
|
||||
- mkdir artifacts-default
|
||||
- mv dist/f7-C/* artifacts-default/
|
||||
@@ -380,15 +278,12 @@ steps:
|
||||
image: hfdj/fztools
|
||||
pull: never
|
||||
commands:
|
||||
- wget https://github.com/xMasterX/all-the-plugins/releases/latest/download/all-the-apps-extra.tgz
|
||||
- tar zxf all-the-apps-extra.tgz
|
||||
- mkdir -p applications/main/clock_app/resources/apps
|
||||
- cp -R extra_pack_build/artifacts-extra/* applications/main/clock_app/resources/apps/
|
||||
- rm -rf extra_pack_build
|
||||
- git clone https://github.com/xMasterX/unleashed-extra-pack.git
|
||||
- cp -R unleashed-extra-pack/apps/* assets/resources/apps/
|
||||
- rm -rf unleashed-extra-pack
|
||||
- export DIST_SUFFIX=${DRONE_BUILD_NUMBER}e
|
||||
- export WORKFLOW_BRANCH_OR_TAG=dev-cfw
|
||||
- export FORCE_NO_DIRTY=yes
|
||||
- export FBT_GIT_SUBMODULE_SHALLOW=1
|
||||
- rm -f build/f7-firmware-C/toolbox/version.*
|
||||
- ./fbt COMPACT=1 DEBUG=0 updater_package
|
||||
- mkdir artifacts-extra-apps
|
||||
@@ -399,31 +294,10 @@ steps:
|
||||
FBT_TOOLS_CUSTOM_LINK:
|
||||
from_secret: fbt_link
|
||||
|
||||
- name: "Build dev with rgb patch"
|
||||
image: hfdj/fztools
|
||||
pull: never
|
||||
commands:
|
||||
- git apply .ci_files/rgb.patch
|
||||
- export DIST_SUFFIX=${DRONE_BUILD_NUMBER}r
|
||||
- export WORKFLOW_BRANCH_OR_TAG=dev-cfw-rgb
|
||||
- export FORCE_NO_DIRTY=yes
|
||||
- export FBT_GIT_SUBMODULE_SHALLOW=1
|
||||
- rm -f build/f7-firmware-C/toolbox/version.*
|
||||
- ./fbt COMPACT=1 DEBUG=0 updater_package
|
||||
- mkdir artifacts-rgb-patch
|
||||
- mv dist/f7-C/* artifacts-rgb-patch/
|
||||
- ls -laS artifacts-rgb-patch
|
||||
- ls -laS artifacts-rgb-patch/f7-update-${DRONE_BUILD_NUMBER}r
|
||||
environment:
|
||||
FBT_TOOLS_CUSTOM_LINK:
|
||||
from_secret: fbt_link
|
||||
|
||||
- name: "Bundle self-update packages"
|
||||
image: joshkeegan/zip
|
||||
image: kramos/alpine-zip
|
||||
commands:
|
||||
- cp artifacts-extra-apps/flipper-z-f7-update-${DRONE_BUILD_NUMBER}e.tgz .
|
||||
- cp artifacts-rgb-patch/flipper-z-f7-update-${DRONE_BUILD_NUMBER}r.tgz .
|
||||
- cp artifacts-clean/flipper-z-f7-update-${DRONE_BUILD_NUMBER}c.tgz .
|
||||
- cp artifacts-default/flipper-z-f7-update-${DRONE_BUILD_NUMBER}.tgz .
|
||||
- rm -rf artifacts-default/f7-update-${DRONE_BUILD_NUMBER}
|
||||
- ls -laS artifacts-default
|
||||
@@ -481,36 +355,6 @@ steps:
|
||||
from_secret: dep_target_extra
|
||||
source: flipper-z-f7-update-${DRONE_BUILD_NUMBER}e.tgz
|
||||
|
||||
- name: "Upload rgb patch version to updates srv"
|
||||
image: appleboy/drone-scp:linux-amd64
|
||||
settings:
|
||||
host:
|
||||
from_secret: dep_host
|
||||
username:
|
||||
from_secret: dep_user
|
||||
password:
|
||||
from_secret: dep_passwd
|
||||
port:
|
||||
from_secret: dep_port
|
||||
target:
|
||||
from_secret: dep_target_extra
|
||||
source: flipper-z-f7-update-${DRONE_BUILD_NUMBER}r.tgz
|
||||
|
||||
- name: "Upload clean version to updates srv"
|
||||
image: appleboy/drone-scp:linux-amd64
|
||||
settings:
|
||||
host:
|
||||
from_secret: dep_host
|
||||
username:
|
||||
from_secret: dep_user
|
||||
password:
|
||||
from_secret: dep_passwd
|
||||
port:
|
||||
from_secret: dep_port
|
||||
target:
|
||||
from_secret: dep_target_extra
|
||||
source: flipper-z-f7-update-${DRONE_BUILD_NUMBER}c.tgz
|
||||
|
||||
- name: "Trigger update server reindex"
|
||||
image: hfdj/fztools
|
||||
pull: never
|
||||
@@ -522,31 +366,7 @@ steps:
|
||||
commands:
|
||||
- curl -X POST -F 'key='$UPD_KEY'' $UPD_URL
|
||||
|
||||
- name: "Send discord notification"
|
||||
image: hfdj/fztools
|
||||
pull: never
|
||||
environment:
|
||||
DISCORD_WEBHOOK:
|
||||
from_secret: dis_dev_webhook
|
||||
commands:
|
||||
- wget "https://raw.githubusercontent.com/fieu/discord.sh/2253303efc0e7211ac2777d2535054cbb872f1e0/discord.sh"
|
||||
- chmod +x ./discord.sh
|
||||
- sed -n '/## Main changes/,/## Other changes/p' CHANGELOG.md | sed -e 's/## Main changes//' -e 's/## Other changes//' > changelogcut.txt
|
||||
- head -c 1544 changelogcut.txt > changelogcutfin.txt
|
||||
- truncate -s -1 changelogcutfin.txt
|
||||
- tail -c +2 changelogcutfin.txt > changelogready.txt
|
||||
- rm -f changelogcut.txt
|
||||
- rm -f changelogcutfin.txt
|
||||
- echo '' >> changelogready.txt
|
||||
- echo '## [Read full changelog](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/CHANGELOG.md)' >> changelogready.txt
|
||||
- sed -i 's/(buildnum)/'${DRONE_BUILD_NUMBER}'/g' .ci_files/devbuild_msg_discord.txt
|
||||
- sed -i 's/(commitsha)/'${DRONE_COMMIT_SHA}'/g' .ci_files/devbuild_msg_discord.txt
|
||||
- sed -i 's/(buildnum)/'${DRONE_BUILD_NUMBER}'/g' .ci_files/devbuild_msg_telegram.txt
|
||||
- sed -i 's/(commitsha)/'${DRONE_COMMIT_SHA}'/g' .ci_files/devbuild_msg_telegram.txt
|
||||
- cp .ci_files/devbuild_msg_telegram.txt tg_dev_message.tpl
|
||||
- ./discord.sh --title "Changelog" --description "$(jq -Rs . <changelogready.txt | cut -c 2- | rev | cut -c 2- | rev)" --timestamp --text "$(jq -Rs . <.ci_files/devbuild_msg_discord.txt | cut -c 2- | rev | cut -c 2- | rev)"
|
||||
|
||||
- name: "Send message to telegram"
|
||||
- name: "Send files to telegram"
|
||||
image: appleboy/drone-telegram
|
||||
settings:
|
||||
token:
|
||||
@@ -554,32 +374,24 @@ steps:
|
||||
to:
|
||||
from_secret: tgid_dev
|
||||
format: markdown
|
||||
message_file: tg_dev_message.tpl
|
||||
message: "Unleashed firmware dev build successful!
|
||||
|
||||
- name: "Send default build to telegram"
|
||||
image: appleboy/drone-telegram
|
||||
settings:
|
||||
token:
|
||||
from_secret: tgtoken
|
||||
to:
|
||||
from_secret: tgid_dev
|
||||
format: markdown
|
||||
message: "Default Build:"
|
||||
|
||||
Build: {{build.number}}
|
||||
|
||||
SHA: {{commit.sha}}
|
||||
|
||||
|
||||
Commit: {{commit.message}}
|
||||
|
||||
|
||||
[-Version with extra apps - Install via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-${DRONE_BUILD_NUMBER}e.tgz&channel=dev-cfw&version=${DRONE_BUILD_NUMBER}e)
|
||||
|
||||
|
||||
[-Install via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw/dev/flipper-z-f7-update-${DRONE_BUILD_NUMBER}.tgz&channel=dev-cfw&version=${DRONE_BUILD_NUMBER})"
|
||||
document:
|
||||
- dev/flipper-z-f7-update-${DRONE_BUILD_NUMBER}.tgz
|
||||
|
||||
- name: "Send clean build to telegram"
|
||||
image: appleboy/drone-telegram
|
||||
settings:
|
||||
token:
|
||||
from_secret: tgtoken
|
||||
to:
|
||||
from_secret: tgid_dev
|
||||
format: markdown
|
||||
message: "Clean (Main apps only) Build:"
|
||||
document:
|
||||
- flipper-z-f7-update-${DRONE_BUILD_NUMBER}c.tgz
|
||||
|
||||
- name: "Send extra pack build to telegram"
|
||||
image: appleboy/drone-telegram
|
||||
settings:
|
||||
@@ -588,10 +400,21 @@ steps:
|
||||
to:
|
||||
from_secret: tgid_dev
|
||||
format: markdown
|
||||
message: "Build with extra apps:"
|
||||
message: "Build with extra apps pack:"
|
||||
document:
|
||||
- flipper-z-f7-update-${DRONE_BUILD_NUMBER}e.tgz
|
||||
|
||||
- name: "Send discord notification"
|
||||
image: hfdj/fztools
|
||||
pull: never
|
||||
environment:
|
||||
DISCORD_WEBHOOK:
|
||||
from_secret: dis_dev_webhook
|
||||
commands:
|
||||
- wget "https://raw.githubusercontent.com/fieu/discord.sh/e1dc1a7595efad2cad8f072f0b3531c470f5b7c8/discord.sh"
|
||||
- chmod +x ./discord.sh
|
||||
- ./discord.sh --text 'Unleashed firmware dev build successful!\n\nBuild - '${DRONE_BUILD_NUMBER}'\n\nSHA - '${DRONE_COMMIT_SHA}'\n\n[-Version with extra apps - Install via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw_extra_apps/flipper-z-f7-update-'${DRONE_BUILD_NUMBER}'e.tgz&channel=dev-cfw&version='${DRONE_BUILD_NUMBER}'e)\n\n[-Install via Web Updater-](https://lab.flipper.net/?url=https://unleashedflip.com/fw/dev/flipper-z-f7-update-'${DRONE_BUILD_NUMBER}'.tgz&channel=dev-cfw&version='${DRONE_BUILD_NUMBER}')'
|
||||
|
||||
trigger:
|
||||
branch:
|
||||
- dev
|
||||
@@ -599,4 +422,4 @@ trigger:
|
||||
- push
|
||||
|
||||
node:
|
||||
typ: dev2
|
||||
typ: haupt
|
||||
|
||||
@@ -8,3 +8,6 @@ charset = utf-8
|
||||
[*.{cpp,h,c,py,sh}]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
|
||||
[{Makefile,*.mk}]
|
||||
indent_size = tab
|
||||
|
||||
2
.github/CODEOWNERS
vendored
2
.github/CODEOWNERS
vendored
@@ -2,4 +2,4 @@
|
||||
* @xMasterX
|
||||
|
||||
# Assets
|
||||
/assets/resources/infrared/assets/ @amec0e @Leptopt1los @xMasterX
|
||||
/assets/resources/infrared/ @xMasterX @amec0e
|
||||
2
.github/FUNDING.yml
vendored
2
.github/FUNDING.yml
vendored
@@ -1,4 +1,4 @@
|
||||
patreon: mmxdev
|
||||
ko_fi: masterx
|
||||
custom:
|
||||
[
|
||||
"https://boosty.to/mmxdev",
|
||||
|
||||
114
.github/workflows/codeql.yml
vendored
114
.github/workflows/codeql.yml
vendored
@@ -1,114 +0,0 @@
|
||||
# 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
|
||||
33
.gitignore
vendored
33
.gitignore
vendored
@@ -1,8 +1,6 @@
|
||||
*~
|
||||
*.swp
|
||||
*.swo
|
||||
*.gdb_history
|
||||
*.old
|
||||
|
||||
|
||||
# LSP
|
||||
@@ -12,9 +10,6 @@ compile_commands.json
|
||||
# JetBrains IDEs
|
||||
.idea/
|
||||
|
||||
# Sublime Text
|
||||
.sublime-project.sublime-workspace
|
||||
|
||||
# Python VirtEnvironments
|
||||
.env
|
||||
.venv
|
||||
@@ -33,28 +28,28 @@ bindings/
|
||||
.mxproject
|
||||
Brewfile.lock.json
|
||||
|
||||
# Visual Studio Code
|
||||
.vscode/
|
||||
|
||||
# Kate
|
||||
.kateproject
|
||||
.kateconfig
|
||||
|
||||
# legendary cmake's
|
||||
build
|
||||
CMakeLists.txt
|
||||
|
||||
# bundle output
|
||||
dist
|
||||
|
||||
# kde
|
||||
.directory
|
||||
null.d
|
||||
|
||||
# SCons
|
||||
.sconsign.dblite
|
||||
|
||||
|
||||
# bundle output
|
||||
/dist
|
||||
/artifacts-default
|
||||
/artifacts-ofw-anims
|
||||
/artifacts-rgb-patch
|
||||
/artifacts-extra-apps
|
||||
/artifacts-clean
|
||||
|
||||
# SCons build dir
|
||||
/build
|
||||
build/
|
||||
|
||||
# Toolchain
|
||||
/toolchain
|
||||
@@ -65,11 +60,5 @@ openocd.log
|
||||
# PVS Studio temporary files
|
||||
.PVS-Studio/
|
||||
PVS-Studio.log
|
||||
*.PVS-Studio.*
|
||||
|
||||
.gdbinit
|
||||
|
||||
/fbt_options_local.py
|
||||
|
||||
# JS packages
|
||||
node_modules/
|
||||
|
||||
32
.gitmodules
vendored
32
.gitmodules
vendored
@@ -1,13 +1,18 @@
|
||||
[submodule "lib/mlib"]
|
||||
path = lib/mlib
|
||||
url = https://github.com/P-p-H-d/mlib.git
|
||||
[submodule "lib/STM32CubeWB"]
|
||||
path = lib/STM32CubeWB
|
||||
url = https://github.com/Flipper-Zero/STM32CubeWB.git
|
||||
[submodule "lib/littlefs"]
|
||||
path = lib/littlefs
|
||||
url = https://github.com/littlefs-project/littlefs.git
|
||||
[submodule "lib/nanopb"]
|
||||
path = lib/nanopb
|
||||
url = https://github.com/nanopb/nanopb.git
|
||||
[submodule "assets/protobuf"]
|
||||
path = assets/protobuf
|
||||
url = https://github.com/flipperdevices/flipperzero-protobuf.git
|
||||
shallow = false
|
||||
[submodule "lib/libusb_stm32"]
|
||||
path = lib/libusb_stm32
|
||||
url = https://github.com/flipperdevices/libusb_stm32.git
|
||||
@@ -20,19 +25,12 @@
|
||||
[submodule "lib/mbedtls"]
|
||||
path = lib/mbedtls
|
||||
url = https://github.com/Mbed-TLS/mbedtls.git
|
||||
[submodule "lib/heatshrink"]
|
||||
path = lib/heatshrink
|
||||
url = https://github.com/flipperdevices/heatshrink.git
|
||||
[submodule "lib/st_cmsis_device_wb"]
|
||||
path = lib/stm32wb_cmsis
|
||||
url = https://github.com/STMicroelectronics/cmsis_device_wb
|
||||
[submodule "lib/stm32wbxx_hal_driver"]
|
||||
path = lib/stm32wb_hal
|
||||
url = https://github.com/STMicroelectronics/stm32wbxx_hal_driver
|
||||
[submodule "lib/stm32wb_copro"]
|
||||
path = lib/stm32wb_copro
|
||||
url = https://github.com/flipperdevices/stm32wb_copro.git
|
||||
[submodule "subghz_remote"]
|
||||
path = applications/main/subghz_remote
|
||||
url = https://github.com/DarkFlippers/SubGHz_Remote.git
|
||||
branch = ufw_main_app
|
||||
[submodule "lib/cxxheaderparser"]
|
||||
path = lib/cxxheaderparser
|
||||
url = https://github.com/robotpy/cxxheaderparser.git
|
||||
[submodule "applications/plugins/subbrute"]
|
||||
path = applications/plugins/subbrute
|
||||
url = https://github.com/derskythe/flipperzero-subbrute.git
|
||||
[submodule "applications/plugins/dap_link/lib/free-dap"]
|
||||
path = applications/plugins/dap_link/lib/free-dap
|
||||
url = https://github.com/ataradov/free-dap.git
|
||||
|
||||
12
.pvsconfig
12
.pvsconfig
@@ -1,14 +1,12 @@
|
||||
# MLib macros we can't do much about.
|
||||
//-V:M_LET:1048,1044
|
||||
//-V:M_EACH:1048,1044
|
||||
//-V:ARRAY_DEF:760,747,568,776,729,712,654,1103
|
||||
//-V:LIST_DEF:760,747,568,712,729,654,776,1103
|
||||
//-V:LIST_DUAL_PUSH_DEF:524,760,774
|
||||
//-V:ARRAY_DEF:760,747,568,776,729,712,654
|
||||
//-V:LIST_DEF:760,747,568,712,729,654,776
|
||||
//-V:BPTREE_DEF2:779,1086,557,773,512
|
||||
//-V:DICT_DEF2:779,524,776,760,1044,1001,729,590,568,747,685,1103
|
||||
//-V:DICT_DEF2:779,524,776,760,1044,1001,729,590,568,747,685
|
||||
//-V:ALGO_DEF:1048,747,1044
|
||||
//-V:TUPLE_DEF2:524,590,1001,760
|
||||
//-V:DEQUE_DEF:658,747,760
|
||||
|
||||
# Non-severe malloc/null pointer deref warnings
|
||||
//-V::522:2,3
|
||||
@@ -44,5 +42,5 @@
|
||||
# Model-related warnings
|
||||
//-V:with_view_model:1044,1048
|
||||
|
||||
# Examples
|
||||
//V_EXCLUDE_PATH applications/examples/
|
||||
# Functions that always return the same error code
|
||||
//-V:picopass_device_decrypt:1048
|
||||
|
||||
@@ -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/mbedtls -e lib/microtar -e lib/mlib -e lib/stm32wb_cmsis -e lib/stm32wb_copro -e lib/stm32wb_hal -e lib/u8g2 -e lib/nanopb -e lib/mjs -e */arm-none-eabi/*
|
||||
--ignore-ccache -C gccarm --rules-config .pvsconfig -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/STM32CubeWB -e lib/u8g2 -e lib/nanopb -e */arm-none-eabi/* -e applications/plugins/dap_link/lib/free-dap
|
||||
|
||||
23
.sublime-project
vendored
23
.sublime-project
vendored
@@ -1,23 +0,0 @@
|
||||
{
|
||||
"folders":
|
||||
[
|
||||
{
|
||||
"path": ".",
|
||||
}
|
||||
],
|
||||
"settings": {
|
||||
"LSP": {
|
||||
"clangd": {
|
||||
"enabled": true,
|
||||
"initializationOptions": {
|
||||
// Set `"binary": "custom",` option in LSP-clangd config to use toolchain clangd
|
||||
"custom_command": ["toolchain/current/bin/clangd"],
|
||||
"clangd.compile-commands-dir": "build/latest",
|
||||
"clangd.header-insertion": "never",
|
||||
"clangd.query-driver": "**/arm-none-eabi-*",
|
||||
"clangd.clang-tidy": true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
7
.vscode/.gitignore
vendored
7
.vscode/.gitignore
vendored
@@ -1,3 +1,4 @@
|
||||
*
|
||||
!example/
|
||||
!ReadMe.md
|
||||
./c_cpp_properties.json
|
||||
./launch.json
|
||||
./settings.json
|
||||
./tasks.json
|
||||
|
||||
2
.vscode/ReadMe.md
vendored
2
.vscode/ReadMe.md
vendored
@@ -1,4 +1,4 @@
|
||||
# Visual Studio Code workspace for Flipper Zero {#vscode}
|
||||
# Visual Studio Code workspace for Flipper Zero
|
||||
|
||||
## Setup
|
||||
|
||||
|
||||
32
.vscode/example/c_cpp_properties.json
vendored
Normal file
32
.vscode/example/c_cpp_properties.json
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Win32",
|
||||
"compilerPath": "${workspaceFolder}/toolchain/x86_64-windows/bin/arm-none-eabi-gcc.exe",
|
||||
"intelliSenseMode": "gcc-arm",
|
||||
"compileCommands": "${workspaceFolder}/build/latest/compile_commands.json",
|
||||
"configurationProvider": "ms-vscode.cpptools",
|
||||
"cStandard": "gnu17",
|
||||
"cppStandard": "c++17"
|
||||
},
|
||||
{
|
||||
"name": "Linux",
|
||||
"compilerPath": "${workspaceFolder}/toolchain/x86_64-linux/bin/arm-none-eabi-gcc",
|
||||
"intelliSenseMode": "gcc-arm",
|
||||
"compileCommands": "${workspaceFolder}/build/latest/compile_commands.json",
|
||||
"configurationProvider": "ms-vscode.cpptools",
|
||||
"cStandard": "gnu17",
|
||||
"cppStandard": "c++17"
|
||||
},
|
||||
{
|
||||
"name": "Mac",
|
||||
"compilerPath": "${workspaceFolder}/toolchain/x86_64-darwin/bin/arm-none-eabi-gcc",
|
||||
"intelliSenseMode": "gcc-arm",
|
||||
"compileCommands": "${workspaceFolder}/build/latest/compile_commands.json",
|
||||
"configurationProvider": "ms-vscode.cpptools",
|
||||
"cStandard": "gnu17",
|
||||
"cppStandard": "c++17"
|
||||
}
|
||||
],
|
||||
"version": 4
|
||||
}
|
||||
20
.vscode/example/clangd/extensions.json
vendored
20
.vscode/example/clangd/extensions.json
vendored
@@ -1,20 +0,0 @@
|
||||
{
|
||||
// See https://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations.
|
||||
// Extension identifier format: ${publisher}.${name}. Example: vscode.csharp
|
||||
// List of extensions which should be recommended for users of this workspace.
|
||||
"recommendations": [
|
||||
"ms-python.black-formatter",
|
||||
"llvm-vs-code-extensions.vscode-clangd",
|
||||
"amiralizadeh9480.cpp-helper",
|
||||
"marus25.cortex-debug",
|
||||
"zxh404.vscode-proto3",
|
||||
"augustocdias.tasks-shell-input",
|
||||
"rioj7.command-variable"
|
||||
],
|
||||
// List of extensions recommended by VS Code that should not be recommended for users of this workspace.
|
||||
"unwantedRecommendations": [
|
||||
"twxs.cmake",
|
||||
"ms-vscode.cpptools",
|
||||
"ms-vscode.cmake-tools"
|
||||
]
|
||||
}
|
||||
29
.vscode/example/cpptools/c_cpp_properties.json
vendored
29
.vscode/example/cpptools/c_cpp_properties.json
vendored
@@ -1,29 +0,0 @@
|
||||
{
|
||||
"configurations": [
|
||||
{
|
||||
"name": "Win32",
|
||||
"compilerPath": "${workspaceFolder}/toolchain/current/bin/arm-none-eabi-gcc.exe",
|
||||
"intelliSenseMode": "gcc-arm",
|
||||
"compileCommands": "${workspaceFolder}/build/latest/compile_commands.json",
|
||||
"cStandard": "gnu23",
|
||||
"cppStandard": "c++20"
|
||||
},
|
||||
{
|
||||
"name": "Linux",
|
||||
"compilerPath": "${workspaceFolder}/toolchain/current/bin/arm-none-eabi-gcc",
|
||||
"intelliSenseMode": "gcc-arm",
|
||||
"compileCommands": "${workspaceFolder}/build/latest/compile_commands.json",
|
||||
"cStandard": "gnu23",
|
||||
"cppStandard": "c++20"
|
||||
},
|
||||
{
|
||||
"name": "Mac",
|
||||
"compilerPath": "${workspaceFolder}/toolchain/current/bin/arm-none-eabi-gcc",
|
||||
"intelliSenseMode": "gcc-arm",
|
||||
"compileCommands": "${workspaceFolder}/build/latest/compile_commands.json",
|
||||
"cStandard": "gnu23",
|
||||
"cppStandard": "c++20"
|
||||
}
|
||||
],
|
||||
"version": 4
|
||||
}
|
||||
20
.vscode/example/cpptools/extensions.json
vendored
20
.vscode/example/cpptools/extensions.json
vendored
@@ -1,20 +0,0 @@
|
||||
{
|
||||
// See https://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations.
|
||||
// Extension identifier format: ${publisher}.${name}. Example: vscode.csharp
|
||||
// List of extensions which should be recommended for users of this workspace.
|
||||
"recommendations": [
|
||||
"ms-python.black-formatter",
|
||||
"ms-vscode.cpptools",
|
||||
"amiralizadeh9480.cpp-helper",
|
||||
"marus25.cortex-debug",
|
||||
"zxh404.vscode-proto3",
|
||||
"augustocdias.tasks-shell-input",
|
||||
"rioj7.command-variable"
|
||||
],
|
||||
// List of extensions recommended by VS Code that should not be recommended for users of this workspace.
|
||||
"unwantedRecommendations": [
|
||||
"llvm-vs-code-extensions.vscode-clangd",
|
||||
"twxs.cmake",
|
||||
"ms-vscode.cmake-tools"
|
||||
]
|
||||
}
|
||||
46
.vscode/example/launch.json
vendored
46
.vscode/example/launch.json
vendored
@@ -11,10 +11,10 @@
|
||||
"args": {
|
||||
"useSingleResult": true,
|
||||
"env": {
|
||||
"PATH": "${workspaceFolder}${command:extension.commandvariable.envListSep}${env:PATH}"
|
||||
"PATH": "${workspaceFolder};${env:PATH}"
|
||||
},
|
||||
"command": "fbt -s get_blackmagic",
|
||||
"description": "Get Blackmagic device"
|
||||
"command": "./fbt get_blackmagic",
|
||||
"description": "Get Blackmagic device",
|
||||
}
|
||||
}
|
||||
],
|
||||
@@ -27,21 +27,20 @@
|
||||
"type": "cortex-debug",
|
||||
"servertype": "openocd",
|
||||
"device": "stlink",
|
||||
"svdFile": "./scripts/debug/STM32WB55_CM4.svd",
|
||||
"svdFile": "./debug/STM32WB55_CM4.svd",
|
||||
// If you're debugging early in the boot process, before OS scheduler is running,
|
||||
// you have to comment out the following line.
|
||||
"rtos": "FreeRTOS",
|
||||
"configFiles": [
|
||||
"interface/stlink.cfg",
|
||||
"./scripts/debug/stm32wbx.cfg",
|
||||
"./debug/stm32wbx.cfg",
|
||||
],
|
||||
"postAttachCommands": [
|
||||
"source scripts/debug/flipperversion.py",
|
||||
"fw-version",
|
||||
// "compare-sections",
|
||||
"source scripts/debug/flipperapps.py",
|
||||
"source debug/flipperapps.py",
|
||||
"fap-set-debug-elf-root build/latest/.extapps",
|
||||
// "source scripts/debug/FreeRTOS/FreeRTOS.py",
|
||||
// "source debug/FreeRTOS/FreeRTOS.py",
|
||||
// "svd_load debug/STM32WB55_CM4.svd"
|
||||
]
|
||||
// "showDevDebugOutput": "raw",
|
||||
},
|
||||
@@ -53,16 +52,14 @@
|
||||
"type": "cortex-debug",
|
||||
"servertype": "external",
|
||||
"gdbTarget": "${input:BLACKMAGIC}",
|
||||
"svdFile": "./scripts/debug/STM32WB55_CM4.svd",
|
||||
"svdFile": "./debug/STM32WB55_CM4.svd",
|
||||
"rtos": "FreeRTOS",
|
||||
"postAttachCommands": [
|
||||
"monitor swdp_scan",
|
||||
"attach 1",
|
||||
"set confirm off",
|
||||
"set mem inaccessible-by-default off",
|
||||
"source scripts/debug/flipperversion.py",
|
||||
"fw-version",
|
||||
"source scripts/debug/flipperapps.py",
|
||||
"source debug/flipperapps.py",
|
||||
"fap-set-debug-elf-root build/latest/.extapps",
|
||||
// "compare-sections",
|
||||
]
|
||||
@@ -77,12 +74,10 @@
|
||||
"servertype": "jlink",
|
||||
"interface": "swd",
|
||||
"device": "STM32WB55RG",
|
||||
"svdFile": "./scripts/debug/STM32WB55_CM4.svd",
|
||||
"svdFile": "./debug/STM32WB55_CM4.svd",
|
||||
"rtos": "FreeRTOS",
|
||||
"postAttachCommands": [
|
||||
"source scripts/debug/flipperversion.py",
|
||||
"fw-version",
|
||||
"source scripts/debug/flipperapps.py",
|
||||
"source debug/flipperapps.py",
|
||||
"fap-set-debug-elf-root build/latest/.extapps",
|
||||
]
|
||||
// "showDevDebugOutput": "raw",
|
||||
@@ -95,20 +90,27 @@
|
||||
"type": "cortex-debug",
|
||||
"servertype": "openocd",
|
||||
"device": "cmsis-dap",
|
||||
"svdFile": "./scripts/debug/STM32WB55_CM4.svd",
|
||||
"svdFile": "./debug/STM32WB55_CM4.svd",
|
||||
"rtos": "FreeRTOS",
|
||||
"configFiles": [
|
||||
"interface/cmsis-dap.cfg",
|
||||
"./scripts/debug/stm32wbx.cfg",
|
||||
"./debug/stm32wbx.cfg",
|
||||
],
|
||||
"postAttachCommands": [
|
||||
"source scripts/debug/flipperversion.py",
|
||||
"fw-version",
|
||||
"source scripts/debug/flipperapps.py",
|
||||
"source debug/flipperapps.py",
|
||||
"fap-set-debug-elf-root build/latest/.extapps",
|
||||
],
|
||||
// "showDevDebugOutput": "raw",
|
||||
},
|
||||
{
|
||||
"name": "fbt debug",
|
||||
"type": "python",
|
||||
"request": "launch",
|
||||
"program": "./lib/scons/scripts/scons.py",
|
||||
"args": [
|
||||
"plugin_dist"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "python debug",
|
||||
"type": "python",
|
||||
|
||||
25
.vscode/example/settings.json
vendored
Normal file
25
.vscode/example/settings.json
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"C_Cpp.default.cStandard": "gnu17",
|
||||
"C_Cpp.default.cppStandard": "c++17",
|
||||
"python.formatting.provider": "black",
|
||||
"workbench.tree.indent": 12,
|
||||
"cortex-debug.enableTelemetry": false,
|
||||
"cortex-debug.variableUseNaturalFormat": true,
|
||||
"cortex-debug.showRTOS": true,
|
||||
"cortex-debug.armToolchainPath.windows": "${workspaceFolder}/toolchain/x86_64-windows/bin",
|
||||
"cortex-debug.armToolchainPath.linux": "${workspaceFolder}/toolchain/x86_64-linux/bin",
|
||||
"cortex-debug.armToolchainPath.osx": "${workspaceFolder}/toolchain/x86_64-darwin/bin",
|
||||
"cortex-debug.openocdPath.windows": "${workspaceFolder}/toolchain/x86_64-windows/openocd/bin/openocd.exe",
|
||||
"cortex-debug.openocdPath.linux": "${workspaceFolder}/toolchain/x86_64-linux/openocd/bin/openocd",
|
||||
"cortex-debug.openocdPath.osx": "${workspaceFolder}/toolchain/x86_64-darwin/openocd/bin/openocd",
|
||||
"cortex-debug.gdbPath.windows": "${workspaceFolder}/toolchain/x86_64-windows/bin/arm-none-eabi-gdb-py.bat",
|
||||
"cortex-debug.gdbPath.linux": "${workspaceFolder}/toolchain/x86_64-linux/bin/arm-none-eabi-gdb-py",
|
||||
"cortex-debug.gdbPath.osx": "${workspaceFolder}/toolchain/x86_64-darwin/bin/arm-none-eabi-gdb-py",
|
||||
"editor.formatOnSave": true,
|
||||
"files.associations": {
|
||||
"*.scons": "python",
|
||||
"SConscript": "python",
|
||||
"SConstruct": "python",
|
||||
"*.fam": "python",
|
||||
}
|
||||
}
|
||||
22
.vscode/example/settings.json.tmpl
vendored
22
.vscode/example/settings.json.tmpl
vendored
@@ -1,22 +0,0 @@
|
||||
{
|
||||
"workbench.tree.indent": 12,
|
||||
"cortex-debug.enableTelemetry": false,
|
||||
"cortex-debug.variableUseNaturalFormat": true,
|
||||
"cortex-debug.armToolchainPath": "${workspaceFolder}/toolchain/current/bin",
|
||||
"cortex-debug.openocdPath": "${workspaceFolder}/toolchain/current/bin/openocd",
|
||||
"cortex-debug.gdbPath": "${workspaceFolder}/toolchain/current/bin/arm-none-eabi-gdb-py3",
|
||||
"editor.formatOnSave": true,
|
||||
"files.associations": {
|
||||
"*.scons": "python",
|
||||
"SConscript": "python",
|
||||
"SConstruct": "python",
|
||||
"*.fam": "python"
|
||||
},
|
||||
"clangd.path": "${workspaceFolder}/toolchain/current/bin/clangd@FBT_PLATFORM_EXECUTABLE_EXT@",
|
||||
"clangd.arguments": [
|
||||
"--query-driver=**/arm-none-eabi-*",
|
||||
"--compile-commands-dir=${workspaceFolder}/build/latest",
|
||||
"--clang-tidy",
|
||||
"--header-insertion=never"
|
||||
]
|
||||
}
|
||||
102
.vscode/example/tasks.json
vendored
102
.vscode/example/tasks.json
vendored
@@ -4,41 +4,41 @@
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"label": "[Release] Build Firmware",
|
||||
"label": "[Release] Build",
|
||||
"group": "build",
|
||||
"type": "shell",
|
||||
"command": "./fbt COMPACT=1 DEBUG=0"
|
||||
},
|
||||
{
|
||||
"label": "[Debug] Build Firmware",
|
||||
"label": "[Debug] Build",
|
||||
"group": "build",
|
||||
"type": "shell",
|
||||
"command": "./fbt"
|
||||
},
|
||||
{
|
||||
"label": "[FBT] Format",
|
||||
"group": "build",
|
||||
"type": "shell",
|
||||
"command": "./fbt format"
|
||||
},
|
||||
{
|
||||
"label": "[FBT] Clear",
|
||||
"group": "build",
|
||||
"type": "shell",
|
||||
"command": "./fbt -c"
|
||||
},
|
||||
{
|
||||
"label": "[Release] Flash (SWD)",
|
||||
"label": "[Release] Flash (ST-Link)",
|
||||
"group": "build",
|
||||
"type": "shell",
|
||||
"command": "./fbt COMPACT=1 DEBUG=0 FORCE=1 flash"
|
||||
},
|
||||
{
|
||||
"label": "[Debug] Flash (SWD)",
|
||||
"label": "[Debug] Flash (ST-Link)",
|
||||
"group": "build",
|
||||
"type": "shell",
|
||||
"command": "./fbt FORCE=1 flash"
|
||||
},
|
||||
{
|
||||
"label": "[Release] Flash (blackmagic)",
|
||||
"group": "build",
|
||||
"type": "shell",
|
||||
"command": "./fbt COMPACT=1 DEBUG=0 FORCE=1 flash_blackmagic"
|
||||
},
|
||||
{
|
||||
"label": "[Debug] Flash (blackmagic)",
|
||||
"group": "build",
|
||||
"type": "shell",
|
||||
"command": "./fbt FORCE=1 flash_blackmagic"
|
||||
},
|
||||
{
|
||||
"label": "[Release] Flash (JLink)",
|
||||
"group": "build",
|
||||
@@ -75,29 +75,23 @@
|
||||
"type": "shell",
|
||||
"command": "./fbt updater_all"
|
||||
},
|
||||
{
|
||||
"label": "[Release] Flash (USB, w/o resources)",
|
||||
"group": "build",
|
||||
"type": "shell",
|
||||
"command": "./fbt COMPACT=1 DEBUG=0 FORCE=1 flash_usb"
|
||||
},
|
||||
{
|
||||
"label": "[Debug] Flash (USB, w/o resources)",
|
||||
"group": "build",
|
||||
"type": "shell",
|
||||
"command": "./fbt FORCE=1 flash_usb"
|
||||
},
|
||||
{
|
||||
"label": "[Release] Flash (USB, w/o resources)",
|
||||
"group": "build",
|
||||
"type": "shell",
|
||||
"command": "./fbt COMPACT=1 DEBUG=0 FORCE=1 flash_usb"
|
||||
},
|
||||
{
|
||||
"label": "[Debug:unit_tests] Flash (USB)",
|
||||
"group": "build",
|
||||
"type": "shell",
|
||||
"command": "./fbt FIRMWARE_APP_SET=unit_tests FORCE=1 flash_usb_full"
|
||||
},
|
||||
{
|
||||
"label": "[Release] Flash (USB, with resources)",
|
||||
"group": "build",
|
||||
"type": "shell",
|
||||
"command": "./fbt COMPACT=1 DEBUG=0 FORCE=1 flash_usb_full"
|
||||
"command": "./fbt FIRMWARE_APP_SET=unit_tests FORCE=1 flash_usb"
|
||||
},
|
||||
{
|
||||
"label": "[Debug] Flash (USB, with resources)",
|
||||
@@ -105,18 +99,18 @@
|
||||
"type": "shell",
|
||||
"command": "./fbt FORCE=1 flash_usb_full"
|
||||
},
|
||||
{
|
||||
"label": "[Release] Flash (USB, with resources)",
|
||||
"group": "build",
|
||||
"type": "shell",
|
||||
"command": "./fbt COMPACT=1 DEBUG=0 FORCE=1 flash_usb_full"
|
||||
},
|
||||
{
|
||||
"label": "[Debug] Create PVS-Studio report",
|
||||
"group": "build",
|
||||
"type": "shell",
|
||||
"command": "./fbt firmware_pvs"
|
||||
},
|
||||
{
|
||||
"label": "[Release] Build FAPs",
|
||||
"group": "build",
|
||||
"type": "shell",
|
||||
"command": "./fbt COMPACT=1 DEBUG=0 fap_dist"
|
||||
},
|
||||
{
|
||||
"label": "[Debug] Build FAPs",
|
||||
"group": "build",
|
||||
@@ -124,28 +118,22 @@
|
||||
"command": "./fbt fap_dist"
|
||||
},
|
||||
{
|
||||
"label": "[Release] Build App",
|
||||
"label": "[Release] Build FAPs",
|
||||
"group": "build",
|
||||
"type": "shell",
|
||||
"command": "./fbt COMPACT=1 DEBUG=0 build APPSRC=${relativeFileDirname}"
|
||||
},
|
||||
{
|
||||
"label": "[Debug] Build App",
|
||||
"group": "build",
|
||||
"type": "shell",
|
||||
"command": "./fbt build APPSRC=${relativeFileDirname}"
|
||||
},
|
||||
{
|
||||
"label": "[Release] Launch App on Flipper",
|
||||
"group": "build",
|
||||
"type": "shell",
|
||||
"command": "./fbt COMPACT=1 DEBUG=0 launch APPSRC=${relativeFileDirname}"
|
||||
"command": "./fbt COMPACT=1 DEBUG=0 fap_dist"
|
||||
},
|
||||
{
|
||||
"label": "[Debug] Launch App on Flipper",
|
||||
"group": "build",
|
||||
"type": "shell",
|
||||
"command": "./fbt launch APPSRC=${relativeFileDirname}"
|
||||
"command": "./fbt launch_app APPSRC=${relativeFileDirname}"
|
||||
},
|
||||
{
|
||||
"label": "[Release] Launch App on Flipper",
|
||||
"group": "build",
|
||||
"type": "shell",
|
||||
"command": "./fbt COMPACT=1 DEBUG=0 launch_app APPSRC=${relativeFileDirname}"
|
||||
},
|
||||
{
|
||||
"label": "[Debug] Launch App on Flipper with Serial Console",
|
||||
@@ -156,18 +144,18 @@
|
||||
"Serial Console"
|
||||
]
|
||||
},
|
||||
{
|
||||
"label": "[Release] Build and upload all FAPs to Flipper over USB",
|
||||
"group": "build",
|
||||
"type": "shell",
|
||||
"command": "./fbt COMPACT=1 DEBUG=0 fap_deploy"
|
||||
},
|
||||
{
|
||||
"label": "[Debug] Build and upload all FAPs to Flipper over USB",
|
||||
"group": "build",
|
||||
"type": "shell",
|
||||
"command": "./fbt fap_deploy"
|
||||
},
|
||||
{
|
||||
"label": "[Release] Build and upload all FAPs to Flipper over USB",
|
||||
"group": "build",
|
||||
"type": "shell",
|
||||
"command": "./fbt COMPACT=1 DEBUG=0 fap_deploy"
|
||||
},
|
||||
{
|
||||
// Press Ctrl+] to quit
|
||||
"label": "Serial Console",
|
||||
@@ -192,4 +180,4 @@
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
18
.vscode/extensions.json
vendored
Normal file
18
.vscode/extensions.json
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
// See https://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations.
|
||||
// Extension identifier format: ${publisher}.${name}. Example: vscode.csharp
|
||||
// List of extensions which should be recommended for users of this workspace.
|
||||
"recommendations": [
|
||||
"ms-python.black-formatter",
|
||||
"ms-vscode.cpptools",
|
||||
"amiralizadeh9480.cpp-helper",
|
||||
"marus25.cortex-debug",
|
||||
"zxh404.vscode-proto3",
|
||||
"augustocdias.tasks-shell-input"
|
||||
],
|
||||
// List of extensions recommended by VS Code that should not be recommended for users of this workspace.
|
||||
"unwantedRecommendations": [
|
||||
"twxs.cmake",
|
||||
"ms-vscode.cmake-tools"
|
||||
]
|
||||
}
|
||||
7
Brewfile
Normal file
7
Brewfile
Normal file
@@ -0,0 +1,7 @@
|
||||
cask "brew-cask/gcc-arm-embedded.rb"
|
||||
brew "protobuf"
|
||||
brew "gdb"
|
||||
brew "open-ocd"
|
||||
brew "clang-format"
|
||||
brew "dfu-util"
|
||||
brew "protobuf-c"
|
||||
101
CHANGELOG.md
101
CHANGELOG.md
@@ -1,87 +1,44 @@
|
||||
## Main changes
|
||||
- Current API: 79.3
|
||||
* SubGHz: Jolly Motors support (with add manually) (Thanks @pkooiman !)
|
||||
* Power: Auto Power Off Timer (by @Dmitry422 with some fixes by @xMasterX)
|
||||
* OFW: **Fix lost BadBLE keystrokes**
|
||||
* OFW: **Add the ability to send a signal once via RPC**
|
||||
* OFW PR 4070: Infrared: increase max carrier limit (by @skotopes)
|
||||
* OFW PR 4025: Increase system stack's reserved memory size (Fix USB UART Bridge Crash) (by @Astrrra)
|
||||
* OFW: merged gsurkov/vcp_break_support branch for usb uart bridge (WIP!!!)
|
||||
* Apps: **Check out more Apps updates and fixes by following** [this link](https://github.com/xMasterX/all-the-plugins/commits/dev)
|
||||
## Other changes
|
||||
* Power & Desktop: Add input events sub check & use event system for auto power off
|
||||
* OFW: Rename FuriHalDebuging.md to FuriHalDebugging.md
|
||||
* OFW: nfc: Fix MIFARE Plus detection
|
||||
* OFW: u2f: Fix leaking message digest contexts
|
||||
* OFW: nfc: Fix MFUL PWD_AUTH command creation
|
||||
* OFW: Bump cross-spawn in /applications/system/js_app/packages/create-fz-app
|
||||
* OFW: **Pipe** (new api funcs)
|
||||
* OFW: Fix invalid path errors while deploying SDK by enforcing toolchain to use UTF-8 on initial SDK Extraction
|
||||
* OFW: **Added flipper_format_write_empty_line(...)**
|
||||
* OFW: Fix skylander ID reading
|
||||
* OFW: Work around incorrect serial port handling by the OS
|
||||
* OFW: Add winter animations
|
||||
* OFW: FBT: Don't lint JS packages
|
||||
* OFW: **Loader: Fix BusFault in handling of OOM** (was already included in previous UL release)
|
||||
* OFW: **NFC Fix ISO15693 stucking in wrong mode.**
|
||||
* OFW: Update `infrared_test.c` reference
|
||||
* OFW: **FuriThread stdin**
|
||||
* OFW: NFC: Plantain parser Last payment amount fix
|
||||
* OFW: NFC clipper: BART station ids for San Lorenzo, Bay Fair
|
||||
* OFW: Fix typo for mf_classic_key_cahce_get_next_key() function
|
||||
<br><br>
|
||||
#### Known NFC post-refactor regressions list:
|
||||
- Mifare Mini clones reading is broken (original mini working fine) (OFW)
|
||||
- NFC CLI was removed with refactoring (OFW) (will be back soon)
|
||||
### New changes
|
||||
* SubGHz: **Nice ON2E (Nice One)** support (by @assasinfil | PR #335)
|
||||
* SubGHz: Remove 467.75 From freq analyzer since it has too much noise (Frequency is still can be used, just excluded from FA to avoid false detections)
|
||||
* Archive and FileBrowser: **Fixed more navigation issues** (by @Willy-JL | PR #334)
|
||||
* Plugins -> SubGHz Bruteforcer: Fix Linear Delta 3 repeats (now its more stable and we will be sure signal is received correctly)
|
||||
* Plugins: Updated TOTP (Authenticator) [(by akopachov)](https://github.com/akopachov/flipper-zero_authenticator)
|
||||
* OFW: **Fix Cyfral & Metakom emulation (My temp fix removed and proper fix from OFW applied)**
|
||||
* OFW: BadUSB: disable CDC mode, USB mode switch fix
|
||||
* OFW: Updater visual fixes
|
||||
|
||||
----
|
||||
#### [🎲 Download latest extra apps pack](https://download-directory.github.io/?url=https://github.com/xMasterX/unleashed-extra-pack/tree/main/apps)
|
||||
|
||||
[-> How to install firmware](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/HowToInstall.md)
|
||||
|
||||
[-> Download qFlipper (official link)](https://flipperzero.one/update)
|
||||
|
||||
## Please support development of the project
|
||||
|Service|Remark|QR Code|Link/Wallet|
|
||||
|-|-|-|-|
|
||||
|**Patreon**||<div align="center"><a href="https://github.com/user-attachments/assets/a88a90a5-28c3-40b4-864a-0c0b79494a42"><img src="https://github.com/user-attachments/assets/da3a864d-d1c7-42cc-8a86-6fcaf26663ec" alt="QR image"/></a></div>|https://patreon.com/mmxdev|
|
||||
|**Boosty**|patreon alternative|<div align="center"><a href="https://github.com/user-attachments/assets/893c0760-f738-42c1-acaa-916019a7bdf8"><img src="https://github.com/user-attachments/assets/da3a864d-d1c7-42cc-8a86-6fcaf26663ec" alt="QR image"/></a></div>|https://boosty.to/mmxdev|
|
||||
|cloudtips|only RU payments accepted|<div align="center"><a href="https://github.com/user-attachments/assets/5de31d6a-ef24-4d30-bd8e-c06af815332a"><img src="https://github.com/user-attachments/assets/da3a864d-d1c7-42cc-8a86-6fcaf26663ec" alt="QR image"/></a></div>|https://pay.cloudtips.ru/p/7b3e9d65|
|
||||
|YooMoney|only RU payments accepted|<div align="center"><a href="https://github.com/user-attachments/assets/33454f79-074b-4349-b453-f94fdadc3c68"><img src="https://github.com/user-attachments/assets/da3a864d-d1c7-42cc-8a86-6fcaf26663ec" alt="QR image"/></a></div>|https://yoomoney.ru/fundraise/XA49mgQLPA0.221209|
|
||||
|USDT|(TRC20)|<div align="center"><a href="https://github.com/user-attachments/assets/0500498d-18ed-412d-a1a4-8a66d0b6f057"><img src="https://github.com/user-attachments/assets/da3a864d-d1c7-42cc-8a86-6fcaf26663ec" alt="QR image"/></a></div>|`TSXcitMSnWXUFqiUfEXrTVpVewXy2cYhrs`|
|
||||
|ETH|(BSC/ERC20-Tokens)|<div align="center"><a href="https://github.com/user-attachments/assets/0f323e98-c524-4f41-abb2-f4f1cec83ab6"><img src="https://github.com/user-attachments/assets/da3a864d-d1c7-42cc-8a86-6fcaf26663ec" alt="QR image"/></a></div>|`0xFebF1bBc8229418FF2408C07AF6Afa49152fEc6a`|
|
||||
|BTC||<div align="center"><a href="https://github.com/user-attachments/assets/5a904d45-947e-4b92-9f0f-7fbaaa7b37f8"><img src="https://github.com/user-attachments/assets/da3a864d-d1c7-42cc-8a86-6fcaf26663ec" alt="QR image"/></a></div>|`bc1q0np836jk9jwr4dd7p6qv66d04vamtqkxrecck9`|
|
||||
|SOL|(Solana/Tokens)|<div align="center"><a href="https://github.com/user-attachments/assets/ab33c5e0-dd59-497b-9c91-ceb89c36b34d"><img src="https://github.com/user-attachments/assets/da3a864d-d1c7-42cc-8a86-6fcaf26663ec" alt="QR image"/></a></div>|`DSgwouAEgu8iP5yr7EHHDqMNYWZxAqXWsTEeqCAXGLj8`|
|
||||
|DOGE||<div align="center"><a href="https://github.com/user-attachments/assets/2937edd0-5c85-4465-a444-14d4edb481c0"><img src="https://github.com/user-attachments/assets/da3a864d-d1c7-42cc-8a86-6fcaf26663ec" alt="QR image"/></a></div>|`D6R6gYgBn5LwTNmPyvAQR6bZ9EtGgFCpvv`|
|
||||
|LTC||<div align="center"><a href="https://github.com/user-attachments/assets/441985fe-f028-4400-83c1-c215760c1e74"><img src="https://github.com/user-attachments/assets/da3a864d-d1c7-42cc-8a86-6fcaf26663ec" alt="QR image"/></a></div>|`ltc1q3ex4ejkl0xpx3znwrmth4lyuadr5qgv8tmq8z9`|
|
||||
|BCH||<div align="center"><a href="https://github.com/user-attachments/assets/7f365976-19a3-4777-b17e-4bfba5f69eff"><img src="https://github.com/user-attachments/assets/da3a864d-d1c7-42cc-8a86-6fcaf26663ec" alt="QR image"/></a></div>|`qquxfyzntuqufy2dx0hrfr4sndp0tucvky4sw8qyu3`|
|
||||
|XMR|(Monero)|<div align="center"><a href="https://github.com/user-attachments/assets/96186c06-61e7-4b4d-b716-6eaf1779bfd8"><img src="https://github.com/user-attachments/assets/da3a864d-d1c7-42cc-8a86-6fcaf26663ec" alt="QR image"/></a></div>|`41xUz92suUu1u5Mu4qkrcs52gtfpu9rnZRdBpCJ244KRHf6xXSvVFevdf2cnjS7RAeYr5hn9MsEfxKoFDRSctFjG5fv1Mhn`|
|
||||
|TON||<div align="center"><a href="https://github.com/user-attachments/assets/92a57e57-7462-42b7-a342-6f22c6e600c1"><img src="https://github.com/user-attachments/assets/da3a864d-d1c7-42cc-8a86-6fcaf26663ec" alt="QR image"/></a></div>|`UQCOqcnYkvzOZUV_9bPE_8oTbOrOF03MnF-VcJyjisTZmsxa`|
|
||||
* Boosty: https://boosty.to/mmxdev
|
||||
* Ko-Fi: https://ko-fi.com/masterx
|
||||
* cloudtips (only RU payments accepted): https://pay.cloudtips.ru/p/7b3e9d65
|
||||
* YooMoney (only RU payments accepted): https://yoomoney.ru/fundraise/XA49mgQLPA0.221209
|
||||
* USDT(TRC20): `TSXcitMSnWXUFqiUfEXrTVpVewXy2cYhrs`
|
||||
* BCH: `qquxfyzntuqufy2dx0hrfr4sndp0tucvky4sw8qyu3`
|
||||
* ETH/BSC/ERC20-Tokens: `darkflippers.eth` (or `0xFebF1bBc8229418FF2408C07AF6Afa49152fEc6a`)
|
||||
* BTC: `bc1q0np836jk9jwr4dd7p6qv66d04vamtqkxrecck9`
|
||||
* DOGE: `D6R6gYgBn5LwTNmPyvAQR6bZ9EtGgFCpvv`
|
||||
* LTC: `ltc1q3ex4ejkl0xpx3znwrmth4lyuadr5qgv8tmq8z9`
|
||||
* XMR (Monero): `41xUz92suUu1u5Mu4qkrcs52gtfpu9rnZRdBpCJ244KRHf6xXSvVFevdf2cnjS7RAeYr5hn9MsEfxKoFDRSctFjG5fv1Mhn`
|
||||
* TON: `EQCOqcnYkvzOZUV_9bPE_8oTbOrOF03MnF-VcJyjisTZmpGf`
|
||||
|
||||
#### Thanks to our sponsors who supported project in the past and special thanks to sponsors who supports us on regular basis:
|
||||
@mishamyte, ClaraCrazy, Pathfinder [Count Zero cDc], callmezimbra, Quen0n, MERRON, grvpvl (lvpvrg), art_col, ThurstonWaffles, Moneron, UterGrooll, LUCFER, Northpirate, zloepuzo, T.Rat, Alexey B., ionelife, ...
|
||||
### Thanks to our sponsors:
|
||||
callmezimbra, Quen0n, MERRON, grvpvl (lvpvrg), art_col, ThurstonWaffles, Moneron, UterGrooll, LUCFER, Northpirate, zloepuzo, T.Rat, Alexey B., ionelife, ...
|
||||
and all other great people who supported our project and me (xMasterX), thanks to you all!
|
||||
|
||||
**Note: To avoid issues with .dfu, prefer installing using .tgz with qFlipper, web updater or by self update package, all needed assets will be installed**
|
||||
|
||||
## **Recommended update option - Web Updater**
|
||||
**Recommended option - Web Updater**
|
||||
|
||||
### What `r`, `e`, ` `, `c` means? What I need to download if I don't want to use Web updater?
|
||||
What build I should download and what this name means - `flipper-z-f7-update-(version)(r / e / c).tgz` ? <br>
|
||||
`flipper-z` = for Flipper Zero device<br>
|
||||
`f7` = Hardware version - same for all flipper zero devices<br>
|
||||
`update` = Update package, contains updater, all assets (plugins, IR libs, etc.), and firmware itself<br>
|
||||
`(version)` = Firmware version<br>
|
||||
| Designation | [Base Apps](https://github.com/xMasterX/all-the-plugins#default-pack) | [Extra Apps](https://github.com/xMasterX/all-the-plugins#extra-pack) | ⚠️RGB mode* |
|
||||
|-----|:---:|:---:|:---:|
|
||||
| ` ` | ✅ | | |
|
||||
| `c` | | | |
|
||||
| `e` | ✅ | ✅ | |
|
||||
| `r` | ✅ | ✅ | ⚠️ |
|
||||
|
||||
⚠️This is [hardware mod](https://github.com/quen0n/flipperzero-firmware-rgb#readme), works only on modded flippers! do not install on non modded device!
|
||||
|
||||
Firmware Self-update package (update from microSD) - `flipper-z-f7-update-(version).tgz` for mobile app / qFlipper / web<br>
|
||||
Archive of `scripts` folder (contains scripts for FW/plugins development) - `flipper-z-any-scripts-(version).tgz`<br>
|
||||
SDK files for plugins development and uFBT - `flipper-z-f7-sdk-(version).zip`
|
||||
What means `n` or `e` in - `flipper-z-f7-update-(version)(n / e).tgz` ? - `n` means this build comes without our custom animations, only official flipper animations,
|
||||
`e` means build has extra apps pack preinstalled
|
||||
|
||||
Self-update package (update from microSD) - `flipper-z-f7-update-(version).zip` or download `.tgz` for mobile app / qFlipper
|
||||
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ Almost everything in flipper firmware is built around this concept.
|
||||
# C coding style
|
||||
|
||||
- Tab is 4 spaces
|
||||
- Use `./fbt format` to reformat source code and check style guide before commit
|
||||
- Use `fbt format` to reformat source code and check style guide before commit
|
||||
|
||||
## Naming
|
||||
|
||||
|
||||
326
ReadMe.md
326
ReadMe.md
@@ -1,247 +1,228 @@
|
||||
<h3 align="center">
|
||||
<a href="https://github.com/DarkFlippers/unleashed-firmware">
|
||||
<img src="https://user-images.githubusercontent.com/10697207/186202043-26947e28-b1cc-459a-8f20-ffcc7fc0c71c.png" align="center" alt="Unleashed Firmware Logo" border="0">
|
||||
<img src="https://user-images.githubusercontent.com/10697207/186202043-26947e28-b1cc-459a-8f20-ffcc7fc0c71c.png" align="center" alt="fzCUSTOM" border="0">
|
||||
</a>
|
||||
</h3>
|
||||
<div align="center" id="badges">
|
||||
<a href="https://discord.unleashedflip.com">
|
||||
<img src="https://img.shields.io/discord/937479784148115456?style=flat-square&logo=discord&label=Discord&color=%237289DA&link=https%3A%2F%2Fdiscord.unleashedflip.com%2F" alt="Discord server"/>
|
||||
</a>
|
||||
<a href="https://t.me/flipperzero_unofficial">
|
||||
<img src="https://img.shields.io/endpoint?label=EN%20Channel&style=flat-square&url=https%3A%2F%2Fmogyo.ro%2Fquart-apis%2Ftgmembercount%3Fchat_id%3Dflipperzero_unofficial" alt="EN TG channel"/>
|
||||
</a>
|
||||
<a href="https://t.me/flipperzero_unofficial_ru">
|
||||
<img src="https://img.shields.io/endpoint?label=RU%20Channel&style=flat-square&url=https%3A%2F%2Fmogyo.ro%2Fquart-apis%2Ftgmembercount%3Fchat_id%3Dflipperzero_unofficial_ru" alt="RU TG channel"/>
|
||||
</a>
|
||||
<a href="https://t.me/flipperzero_unofficial_ua">
|
||||
<img src="https://img.shields.io/endpoint?label=UA%20Channel&style=flat-square&url=https%3A%2F%2Fmogyo.ro%2Fquart-apis%2Ftgmembercount%3Fchat_id%3Dflipperzero_unofficial_ua" alt="UA TG channel"/>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
### Welcome to the Flipper Zero Unleashed Firmware repo!
|
||||
|
||||
#### **This firmware is a fork from original (OFW) firmware** [flipperdevices/flipperzero-firmware](https://github.com/flipperdevices/flipperzero-firmware)
|
||||
**This firmware is a fork from** [flipperdevices/flipperzero-firmware](https://github.com/flipperdevices/flipperzero-firmware)
|
||||
|
||||
<br>
|
||||
|
||||
### Most stable custom firmware focused on new features and improvements of original firmware components, keeping compatibility with original firmware API and Apps
|
||||
Our goal is to make all features possible on this device without any limitations!
|
||||
|
||||
Please help us implement emulation for all Sub-GHz dynamic (rolling code) protocols!
|
||||
|
||||
<br>
|
||||
|
||||
##### This software is for experimental purposes only and is not meant for any illegal activity/purposes. <br> We do not condone illegal activity and strongly encourage keeping transmissions to legal/valid uses allowed by law. <br> Also, this software is made without any support from Flipper Devices and is in no way related to the official team.
|
||||
|
||||
### This software is for experimental purposes only and is not meant for any illegal activity/purposes. <br> We do not condone illegal activity and strongly encourage keeping transmissions to legal/valid uses allowed by law. <br> Also, this software is made without any support from Flipper Devices and is in no way related to the official devs.
|
||||
|
||||
<br>
|
||||
Our Discord Community:
|
||||
<br>
|
||||
<a href="https://discord.unleashedflip.com"><img src="https://discordapp.com/api/guilds/937479784148115456/widget.png?style=banner4" alt="Unofficial Discord Community" target="_blank"></a>
|
||||
|
||||
## 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)
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
|
||||
## Our official domains
|
||||
- https://flipperunleashed.com/ -> our main web page
|
||||
- https://unleashedflip.com/ -> update server, direct .tgz update links for web updater or direct download
|
||||
|
||||
## Dev builds (unstable) (built automatically from dev branch)
|
||||
## Dev builds
|
||||
- https://dev.unleashedflip.com/
|
||||
- https://t.me/kotnehleb
|
||||
|
||||
## Releases in Telegram
|
||||
- https://t.me/unleashed_fw
|
||||
|
||||
# What's changed
|
||||
- **Sub-GHz** *lib & hal*
|
||||
- Regional TX restrictions removed
|
||||
- Extra Sub-GHz frequencies added
|
||||
- Frequency range can be extended in settings file (Warning: It can damage Flipper's hardware)
|
||||
- Many rolling code [protocols](https://github.com/DarkFlippers/unleashed-firmware#current-modified-and-new-sub-ghz-protocols-list) now have the ability to save & send captured signals
|
||||
- FAAC SLH (Spa) & BFT Mitto (keeloq secure with seed) manual creation
|
||||
- External CC1101 module support [(by quen0n)](https://github.com/DarkFlippers/unleashed-firmware/pull/307)
|
||||
- **Sub-GHz** *Main App*
|
||||
- Save last used settings [(by derskythe)](https://github.com/DarkFlippers/unleashed-firmware/pull/77)
|
||||
- New frequency analyzer [(by ClusterM)](https://github.com/DarkFlippers/unleashed-firmware/pull/43)
|
||||
- Press OK in frequency analyzer to use detected frequency in Read modes [(by derskythe)](https://github.com/DarkFlippers/unleashed-firmware/pull/77)
|
||||
- Long press OK button in Sub-GHz Frequency analyzer to switch to Read menu [(by derskythe)](https://github.com/DarkFlippers/unleashed-firmware/pull/79)
|
||||
- New option to use timestamps + protocol name when you saving file, instead of random name or timestamp only - Enable in `Radio Settings -> Protocol Names = ON`
|
||||
- Read mode UI improvements (shows time when signal was received) (by @wosk)
|
||||
- External CC1101 module support (Hardware SPI used)
|
||||
- External CC1101 module amplifier control (or LED control) support (enabled by default)
|
||||
- **Hold right in received signal list to delete selected signal**
|
||||
- **Custom buttons for Keeloq / Alutech AT4N / Nice Flor S / Somfy Telis / Security+ 2.0 / CAME Atomo** - now you can use arrow buttons to send signal with different button code
|
||||
- `Add manually` menu extended with new protocols
|
||||
- FAAC SLH, BFT Mitto / Somfy Telis / Nice Flor S / CAME Atomo, etc.. manual creation with programming new remote into receiver (use button 0xF for BFT Mitto, 0x8 (Prog) on Somfy Telis, (right arrow button for other protocols))
|
||||
- Debug mode counter increase settings (+1 -> +5, +10, default: +1)
|
||||
- Debug PIN output settings for protocol development
|
||||
|
||||
- **Sub-GHz apps** *by unleashed team*
|
||||
- Sub-GHz Bruteforce - static code brute-force plugin |
|
||||
- Time delay (between signals) setting (hold Up in main screen(says Up to Save)) + configure repeats in protocols list by pressing right button on selected protocol
|
||||
- Load your own file and select bytes you want to bruteforce or use preconfigured options in protocols list
|
||||
- Sub-GHz Remote - remote control for 5 sub-ghz files | bind one file for each button
|
||||
- use the built-in constructor or make config file by following this [instruction](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/SubGHzRemotePlugin.md)
|
||||
- **Infrared**
|
||||
- Recompiled IR TV Universal Remote for ALL buttons
|
||||
- Universal remotes for Projectors, Fans, A/Cs and Audio(soundbars, etc.) -> Also always updated and verified by our team
|
||||
- Infrared -> `RCA` Protocol
|
||||
- Infrared -> External IR modules support (with autodetect by OFW)
|
||||
- **NFC/RFID/iButton**
|
||||
* LFRFID and iButton Fuzzer plugins
|
||||
* Add DEZ 8 display form for EM4100 (by @korden32)
|
||||
* Extra Mifare Classic keys in system dict
|
||||
* EMV Protocol + Public data parser (by @Leptopt1los and @wosk)
|
||||
* NFC `Add manually` -> Mifare Classic with custom UID
|
||||
* NFC parsers: Umarsh, Zolotaya Korona, Kazan, Metromoney, Moscow Social Card, Troika (reworked) and [many others](https://github.com/DarkFlippers/unleashed-firmware/tree/dev/applications/main/nfc/plugins/supported_cards) (by @Leptopt1los and @assasinfil)
|
||||
- **Quality of life & other features**
|
||||
- Customizable Flipper name **Update! Now can be changed in Settings->Desktop** (by @xMasterX and @Willy-JL)
|
||||
- Text Input UI element -> Cursor feature (by @Willy-JL)
|
||||
- Byte Input Mini editor -> **Press UP** multiple times until the nibble editor appears (by @gid9798)
|
||||
- Clock on Desktop -> `Settings -> Desktop -> Show Clock` (by @gid9798)
|
||||
- Battery percentage display with different styles `Settings -> Desktop -> Battery View`
|
||||
- More games in Dummy Mode -> click or hold any of arrow buttons
|
||||
- Lock device with pin(or regular lock if pin not set) by holding UP button on main screen [(by an4tur0r)](https://github.com/DarkFlippers/unleashed-firmware/pull/107)
|
||||
- **BadKB** plugin [(by Willy-JL, ClaraCrazy, XFW contributors)](https://github.com/Flipper-XFW/Xtreme-Firmware/tree/dev/applications/main/bad_kb) - (See in Applications->Tools) - (aka BadUSB via Bluetooth)
|
||||
- BadUSB -> Keyboard layouts [(by rien > dummy-decoy)](https://github.com/dummy-decoy/flipperzero-firmware/tree/dummy_decoy/bad_usb_keyboard_layout)
|
||||
- Custom community plugins and games added + all known working apps can be downloaded in extra pack in every release
|
||||
- Other small fixes and changes throughout
|
||||
- See other changes in readme below
|
||||
* Sub-GHz regional TX restrictions removed
|
||||
* Sub-GHz frequency range can be extended in settings file (Warning: It can damage Flipper's hardware)
|
||||
* Many rolling code protocols now have the ability to save & send captured signals
|
||||
* FAAC SLH (Spa) & BFT Mitto (secure with seed) manual creation
|
||||
* Sub-GHz static code brute-force plugin
|
||||
* LFRFID Fuzzer plugin
|
||||
* Custom community plugins and games added + all known working apps can be downloaded in extra pack in every release
|
||||
* Extra Sub-GHz frequencies + extra Mifare Classic keys
|
||||
* Picopass/iClass plugin included in releases
|
||||
* Recompiled IR TV Universal Remote for ALL buttons
|
||||
* Universal remote for Projectors, Fans, A/Cs and Audio(soundbars, etc.)
|
||||
* BadUSB keyboard layouts
|
||||
* Customizable Flipper name
|
||||
* Sub-GHz -> Press OK in frequency analyzer to use detected frequency in Read modes
|
||||
* Sub-GHz -> Long press OK button in Sub-GHz Frequency analyzer to switch to Read menu
|
||||
* Sub-GHz -> External CC1101 module support
|
||||
* Other small fixes and changes throughout
|
||||
* See other changes in changelog and in readme below
|
||||
|
||||
Also check the [changelog in releases](https://github.com/DarkFlippers/unleashed-firmware/releases) for latest updates!
|
||||
Also check the changelog in releases for latest updates!
|
||||
|
||||
### Current modified and new Sub-GHz protocols list:
|
||||
Thanks to Official team (to their SubGHz Developer, Skorp) for implementing support (decoder + encoder / or decode only) for these protocols in OFW.
|
||||
Thanks to Official team (to thier SubGHz Developer, Skorp) for implementing decoders for these protocols.
|
||||
|
||||
Keeloq [Not ALL systems supported for decode or emulation!] - [Supported manufacturers list](https://pastes.io/raw/unuj9bhe4m)
|
||||
Encoders/sending made by Eng1n33r & @xMasterX:
|
||||
|
||||
Decoders/Encoders or emulation (+ programming mode) support made by @xMasterX:
|
||||
- Marantec24 (static 24 bit) with add manually support
|
||||
- GangQi (static 34 bit) with button parsing and add manually support (thanks to @mishamyte for captures and testing, thanks @Skorpionm for help)
|
||||
- Hollarm (static 42 bit) with button parsing and add manually support (thanks to @mishamyte for captures, thanks @Skorpionm for help)
|
||||
- Hay21 (dynamic 21 bit) with button parsing
|
||||
- Nero Radio 57bit (+ 56bit support)
|
||||
- CAME 12bit/24bit encoder fixes (Fixes are now merged in OFW)
|
||||
- Keeloq: Dea Mio, Genius Bravo, GSN, HCS101, AN-Motors, JCM Tech, MHouse, Nice Smilo, DTM Neo, FAAC RC,XT, Mutancode, Normstahl, Beninca + Allmatic, Stilmatic, CAME Space, Aprimatic (model TR and similar), Centurion Nova (thanks Carlos !), Hormann EcoStar, Novoferm, Sommer, Monarch (thanks @ashphx !)
|
||||
|
||||
Protocols support made by Skorp (original implementation) and @xMasterX (current version):
|
||||
- CAME Atomo -> Update! check out new [instructions](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/SubGHzRemoteProg.md)
|
||||
- Nice Flor S -> How to create new remote - [instructions](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/SubGHzRemoteProg.md)
|
||||
- FAAC SLH (Spa) -> Update!!! (Programming mode!) Check out new [instructions](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/SubGHzRemoteProg.md)
|
||||
- Keeloq: BFT Mitto -> Update! Check out new [instructions](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/SubGHzRemoteProg.md)
|
||||
- Star Line
|
||||
- Keeloq [Not ALL systems supported for decode or emulation yet!] - [Supported manufacturers list](https://0bin.net/paste/VwR2lNJY#WH9vnPgvcp7w6zVKucFCuNREKAcOij8KsJ6vqLfMn3b)
|
||||
- Keeloq: HCS101
|
||||
- Keeloq: AN-Motors
|
||||
- Keeloq: JCM Tech
|
||||
- Keeloq: MHouse
|
||||
- Keeloq: Nice Smilo
|
||||
- Keeloq: DTM Neo
|
||||
- Keeloq: FAAC RC,XT
|
||||
- Keeloq: Mutancode
|
||||
- Keeloq: Normstahl
|
||||
- CAME Atomo
|
||||
- Nice Flor S
|
||||
- FAAC SLH (Spa) [External seed calculation required (For info contact me in Discord: Nano#8998)]
|
||||
- BFT Mitto [External seed calculation required (For info contact me in Discord: Nano#8998)]
|
||||
- Security+ v1 & v2
|
||||
- Star Line
|
||||
|
||||
Encoders made by @assasinfil and @xMasterX:
|
||||
- Somfy Telis -> How to create new remote - [instructions](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/SubGHzRemoteProg.md)
|
||||
Encoders made by @assasinfil & @xMasterX:
|
||||
- Somfy Telis
|
||||
- Somfy Keytis
|
||||
- KingGates Stylo 4k
|
||||
- Alutech AT-4N -> How to create new remote - [instructions](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/SubGHzRemoteProg.md)
|
||||
- Nice ON2E (Nice One) -> How to create new remote - [instructions](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/SubGHzRemoteProg.md)
|
||||
- Alutech AT-4N
|
||||
- Nice ON2E (Nice One)
|
||||
|
||||
## Please support development of the project
|
||||
The majority of this project is developed and maintained by me, @xMasterX.
|
||||
I'm unemployed because of the war, and the only income I receive is from your donations.
|
||||
Our team is small and the guys are working on this project as much as they can solely based on the enthusiasm they have for this project and the community.
|
||||
- @Leptopt1los - NFC, RFID, Plugins, and many other things
|
||||
- @gid9798 - SubGHz, Plugins, many other things - currently offline :(
|
||||
- @assasinfil - SubGHz protocols, NFC parsers
|
||||
- @assasinfil - SubGHz
|
||||
- @Svaarich - UI design and animations
|
||||
- @amec0e - Infrared assets
|
||||
- @Amec0e - Infrared assets
|
||||
- Community moderators in Telegram, Discord, and Reddit
|
||||
- And of course our GitHub community. Your PRs are a very important part of this firmware and open-source development.
|
||||
|
||||
The amount of work done on this project is huge and we need your support, no matter how large or small. Even if you just say, "Thank you Unleashed firmware developers!" somewhere. Doing so will help us continue our work and will help drive us to make the firmware better every time.
|
||||
Also, regarding our releases, every build has and always will be free and open-source. There will be no paywall releases or closed-source apps within the firmware. As long as I am working on this project it will never happen.
|
||||
You can support us by using links or addresses below:
|
||||
|Service|Remark|QR Code|Link/Wallet|
|
||||
|-|-|-|-|
|
||||
|**Patreon**||<div align="center"><a href="https://github.com/user-attachments/assets/a88a90a5-28c3-40b4-864a-0c0b79494a42"><img src="https://github.com/user-attachments/assets/da3a864d-d1c7-42cc-8a86-6fcaf26663ec" alt="QR image"/></a></div>|https://patreon.com/mmxdev|
|
||||
|**Boosty**|patreon alternative|<div align="center"><a href="https://github.com/user-attachments/assets/893c0760-f738-42c1-acaa-916019a7bdf8"><img src="https://github.com/user-attachments/assets/da3a864d-d1c7-42cc-8a86-6fcaf26663ec" alt="QR image"/></a></div>|https://boosty.to/mmxdev|
|
||||
|cloudtips|only RU payments accepted|<div align="center"><a href="https://github.com/user-attachments/assets/5de31d6a-ef24-4d30-bd8e-c06af815332a"><img src="https://github.com/user-attachments/assets/da3a864d-d1c7-42cc-8a86-6fcaf26663ec" alt="QR image"/></a></div>|https://pay.cloudtips.ru/p/7b3e9d65|
|
||||
|YooMoney|only RU payments accepted|<div align="center"><a href="https://github.com/user-attachments/assets/33454f79-074b-4349-b453-f94fdadc3c68"><img src="https://github.com/user-attachments/assets/da3a864d-d1c7-42cc-8a86-6fcaf26663ec" alt="QR image"/></a></div>|https://yoomoney.ru/fundraise/XA49mgQLPA0.221209|
|
||||
|USDT|(TRC20)|<div align="center"><a href="https://github.com/user-attachments/assets/0500498d-18ed-412d-a1a4-8a66d0b6f057"><img src="https://github.com/user-attachments/assets/da3a864d-d1c7-42cc-8a86-6fcaf26663ec" alt="QR image"/></a></div>|`TSXcitMSnWXUFqiUfEXrTVpVewXy2cYhrs`|
|
||||
|ETH|(BSC/ERC20-Tokens)|<div align="center"><a href="https://github.com/user-attachments/assets/0f323e98-c524-4f41-abb2-f4f1cec83ab6"><img src="https://github.com/user-attachments/assets/da3a864d-d1c7-42cc-8a86-6fcaf26663ec" alt="QR image"/></a></div>|`0xFebF1bBc8229418FF2408C07AF6Afa49152fEc6a`|
|
||||
|BTC||<div align="center"><a href="https://github.com/user-attachments/assets/5a904d45-947e-4b92-9f0f-7fbaaa7b37f8"><img src="https://github.com/user-attachments/assets/da3a864d-d1c7-42cc-8a86-6fcaf26663ec" alt="QR image"/></a></div>|`bc1q0np836jk9jwr4dd7p6qv66d04vamtqkxrecck9`|
|
||||
|SOL|(Solana/Tokens)|<div align="center"><a href="https://github.com/user-attachments/assets/ab33c5e0-dd59-497b-9c91-ceb89c36b34d"><img src="https://github.com/user-attachments/assets/da3a864d-d1c7-42cc-8a86-6fcaf26663ec" alt="QR image"/></a></div>|`DSgwouAEgu8iP5yr7EHHDqMNYWZxAqXWsTEeqCAXGLj8`|
|
||||
|DOGE||<div align="center"><a href="https://github.com/user-attachments/assets/2937edd0-5c85-4465-a444-14d4edb481c0"><img src="https://github.com/user-attachments/assets/da3a864d-d1c7-42cc-8a86-6fcaf26663ec" alt="QR image"/></a></div>|`D6R6gYgBn5LwTNmPyvAQR6bZ9EtGgFCpvv`|
|
||||
|LTC||<div align="center"><a href="https://github.com/user-attachments/assets/441985fe-f028-4400-83c1-c215760c1e74"><img src="https://github.com/user-attachments/assets/da3a864d-d1c7-42cc-8a86-6fcaf26663ec" alt="QR image"/></a></div>|`ltc1q3ex4ejkl0xpx3znwrmth4lyuadr5qgv8tmq8z9`|
|
||||
|BCH||<div align="center"><a href="https://github.com/user-attachments/assets/7f365976-19a3-4777-b17e-4bfba5f69eff"><img src="https://github.com/user-attachments/assets/da3a864d-d1c7-42cc-8a86-6fcaf26663ec" alt="QR image"/></a></div>|`qquxfyzntuqufy2dx0hrfr4sndp0tucvky4sw8qyu3`|
|
||||
|XMR|(Monero)|<div align="center"><a href="https://github.com/user-attachments/assets/96186c06-61e7-4b4d-b716-6eaf1779bfd8"><img src="https://github.com/user-attachments/assets/da3a864d-d1c7-42cc-8a86-6fcaf26663ec" alt="QR image"/></a></div>|`41xUz92suUu1u5Mu4qkrcs52gtfpu9rnZRdBpCJ244KRHf6xXSvVFevdf2cnjS7RAeYr5hn9MsEfxKoFDRSctFjG5fv1Mhn`|
|
||||
|TON||<div align="center"><a href="https://github.com/user-attachments/assets/92a57e57-7462-42b7-a342-6f22c6e600c1"><img src="https://github.com/user-attachments/assets/da3a864d-d1c7-42cc-8a86-6fcaf26663ec" alt="QR image"/></a></div>|`UQCOqcnYkvzOZUV_9bPE_8oTbOrOF03MnF-VcJyjisTZmsxa`|
|
||||
* Boosty: https://boosty.to/mmxdev
|
||||
* Ko-Fi: https://ko-fi.com/masterx
|
||||
* cloudtips (only RU payments accepted): https://pay.cloudtips.ru/p/7b3e9d65
|
||||
* YooMoney (only RU payments accepted): https://yoomoney.ru/fundraise/XA49mgQLPA0.221209
|
||||
* USDT(TRC20): `TSXcitMSnWXUFqiUfEXrTVpVewXy2cYhrs`
|
||||
* BCH: `qquxfyzntuqufy2dx0hrfr4sndp0tucvky4sw8qyu3`
|
||||
* ETH/BSC/ERC20-Tokens: `darkflippers.eth` (or `0xFebF1bBc8229418FF2408C07AF6Afa49152fEc6a`)
|
||||
* BTC: `bc1q0np836jk9jwr4dd7p6qv66d04vamtqkxrecck9`
|
||||
* DOGE: `D6R6gYgBn5LwTNmPyvAQR6bZ9EtGgFCpvv`
|
||||
* LTC: `ltc1q3ex4ejkl0xpx3znwrmth4lyuadr5qgv8tmq8z9`
|
||||
* XMR (Monero): `41xUz92suUu1u5Mu4qkrcs52gtfpu9rnZRdBpCJ244KRHf6xXSvVFevdf2cnjS7RAeYr5hn9MsEfxKoFDRSctFjG5fv1Mhn`
|
||||
* TON: `EQCOqcnYkvzOZUV_9bPE_8oTbOrOF03MnF-VcJyjisTZmpGf`
|
||||
|
||||
## Community apps included
|
||||
### Community apps included:
|
||||
|
||||
### [🎲 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 *(Default)* pack](https://github.com/xMasterX/all-the-plugins/tree/dev#default-pack)
|
||||
- **RFID Fuzzer** [(by Ganapati & @xMasterX)](https://github.com/DarkFlippers/unleashed-firmware/pull/54) & New protocols by @mvanzanten
|
||||
- **Sub-GHz bruteforcer** [(by @derskythe & xMasterX)](https://github.com/derskythe/flipperzero-subbrute) [(original by Ganapati & xMasterX)](https://github.com/DarkFlippers/unleashed-firmware/pull/57)
|
||||
- **Sub-GHz playlist** [(by darmiel)](https://github.com/DarkFlippers/unleashed-firmware/pull/62)
|
||||
- ESP8266 Deauther plugin [(by SequoiaSan)](https://github.com/SequoiaSan/FlipperZero-Wifi-ESP8266-Deauther-Module)
|
||||
- WiFi Scanner plugin [(by SequoiaSan)](https://github.com/SequoiaSan/FlipperZero-WiFi-Scanner_Module)
|
||||
- MultiConverter plugin [(by theisolinearchip)](https://github.com/theisolinearchip/flipperzero_stuff)
|
||||
- USB Keyboard plugin [(by huuck)](https://github.com/huuck/FlipperZeroUSBKeyboard)
|
||||
- WAV Player [(OFW: DrZlo13)](https://github.com/flipperdevices/flipperzero-firmware/tree/zlo/wav-player) - Fixed and improved by [LTVA1](https://github.com/LTVA1/wav_player)
|
||||
- Barcode generator plugin [(original by McAzzaMan)](https://github.com/McAzzaMan/flipperzero-firmware/tree/UPC-A_Barcode_Generator/applications/barcode_generator) - [EAN-8 and refactoring](https://github.com/DarkFlippers/unleashed-firmware/pull/154) by @msvsergey
|
||||
- GPIO: Sentry Safe plugin [(by H4ckd4ddy)](https://github.com/H4ckd4ddy/flipperzero-sentry-safe-plugin)
|
||||
- ESP32: WiFi Marauder companion plugin [(by 0xchocolate)](https://github.com/0xchocolate/flipperzero-firmware-with-wifi-marauder-companion)
|
||||
- NRF24: Sniffer & MouseJacker (with changes) [(by mothball187)](https://github.com/mothball187/flipperzero-nrf24/tree/main/mousejacker)
|
||||
- Simple Clock (timer by GMMan) [(original by CompaqDisc)](https://gist.github.com/CompaqDisc/4e329c501bd03c1e801849b81f48ea61)
|
||||
- **Sub-GHz Remote** (UniversalRF Remix) [(by @darmiel & @xMasterX)](https://github.com/darmiel/flipper-playlist/tree/feat/unirf-protocols) (original by @ESurge)
|
||||
- Spectrum Analyzer (with changes) [(by jolcese)](https://github.com/jolcese/flipperzero-firmware/tree/spectrum/applications/spectrum_analyzer) - [Ultra Narrow mode & scan channels non-consecutively](https://github.com/theY4Kman/flipperzero-firmware/commits?author=theY4Kman)
|
||||
- Metronome [(by panki27)](https://github.com/panki27/Metronome)
|
||||
- DTMF Dolphin [(by litui)](https://github.com/litui/dtmf_dolphin)
|
||||
- **TOTP (Authenticator)** [(by akopachov)](https://github.com/akopachov/flipper-zero_authenticator)
|
||||
- GPS [(by ezod)](https://github.com/ezod/flipperzero-gps) works with module `NMEA 0183` via UART (13TX, 14RX, GND pins on Flipper)
|
||||
- i2c Tools [(by NaejEL)](https://github.com/NaejEL/flipperzero-i2ctools) - C0 -> SCL / C1 -> SDA / GND -> GND | 3v3 logic levels only!
|
||||
- HC-SR04 Distance sensor - Ported and modified by @xMasterX [(original by Sanqui)](https://github.com/Sanqui/flipperzero-firmware/tree/hc_sr04) - How to connect -> (5V -> VCC) / (GND -> GND) / (13|TX -> Trig) / (14|RX -> Echo)
|
||||
- Morse Code [(by wh00hw)](https://github.com/wh00hw/MorseCodeFAP)
|
||||
- **Unitemp - Temperature sensors reader** (DHT11/22, DS18B20, BMP280, HTU21x and more) [(by quen0n)](https://github.com/quen0n/unitemp-flipperzero)
|
||||
- BH1750 - Lightmeter [(by oleksiikutuzov)](https://github.com/oleksiikutuzov/flipperzero-lightmeter)
|
||||
- **iButton Fuzzer** [(by xMasterX)](https://github.com/xMasterX/ibutton-fuzzer)
|
||||
- HEX Viewer [(by QtRoS)](https://github.com/QtRoS/flipper-zero-hex-viewer)
|
||||
- POCSAG Pager [(by xMasterX & Shmuma)](https://github.com/xMasterX/flipper-pager)
|
||||
- Text Viewer [(by kowalski7cc & kyhwana)](https://github.com/kowalski7cc/flipper-zero-text-viewer/tree/refactor-text-app)
|
||||
- **UART Terminal** [(by cool4uma)](https://github.com/cool4uma/UART_Terminal/tree/main)
|
||||
- **ProtoView** [(by antirez)](https://github.com/antirez/protoview)
|
||||
|
||||
See full list and sources here: [xMasterX/all-the-plugins](https://github.com/xMasterX/all-the-plugins/tree/dev)
|
||||
Games:
|
||||
- DOOM (fixed) [(by p4nic4ttack)](https://github.com/p4nic4ttack/doom-flipper-zero/)
|
||||
- Zombiez [(Reworked By DevMilanIan)](https://github.com/RogueMaster/flipperzero-firmware-wPlugins/pull/240) [(Original By Dooskington)](https://github.com/Dooskington/flipperzero-zombiez)
|
||||
- Flappy Bird [(by DroomOne)](https://github.com/DroomOne/flipperzero-firmware/tree/dev/applications/flappy_bird)
|
||||
- Arkanoid (refactored by xMasterX) [(by gotnull)](https://github.com/gotnull/flipperzero-firmware-wPlugins)
|
||||
- Tic Tac Toe (refactored by xMasterX) [(by gotnull)](https://github.com/gotnull/flipperzero-firmware-wPlugins)
|
||||
- Tetris (with fixes) [(by jeffplang)](https://github.com/jeffplang/flipperzero-firmware/tree/tetris_game/applications/tetris_game)
|
||||
- Minesweeper [(by panki27)](https://github.com/panki27/minesweeper)
|
||||
- Heap Defence (aka Stack Attack) - Ported to latest firmware by @xMasterX - [(original by wquinoa & Vedmein)](https://github.com/Vedmein/flipperzero-firmware/tree/hd/svisto-perdelki)
|
||||
- Game15 [(by x27)](https://github.com/x27/flipperzero-game15)
|
||||
- Solitaire [(by teeebor)](https://github.com/teeebor/flipper_games)
|
||||
- BlackJack [(by teeebor)](https://github.com/teeebor/flipper_games)
|
||||
- 2048 game [(by eugene-kirzhanov)](https://github.com/eugene-kirzhanov/flipper-zero-2048-game)
|
||||
|
||||
### Official Flipper Zero Apps Catalog [web version](https://lab.flipper.net/apps) or mobile app
|
||||
### Other changes
|
||||
|
||||
- BadUSB -> Keyboard layouts [(by rien > dummy-decoy)](https://github.com/dummy-decoy/flipperzero-firmware/tree/dummy_decoy/bad_usb_keyboard_layout)
|
||||
- Sub-GHz -> External CC1101 module support - [(by quen0n)](https://github.com/DarkFlippers/unleashed-firmware/pull/307)
|
||||
- Sub-GHz -> New frequency analyzer - [(by ClusterM)](https://github.com/DarkFlippers/unleashed-firmware/pull/43)
|
||||
- Sub-GHz -> Save last used frequency [(by derskythe)](https://github.com/DarkFlippers/unleashed-firmware/pull/77)
|
||||
- Sub-GHz -> Press OK in frequency analyzer to use detected frequency in Read modes [(by derskythe)](https://github.com/DarkFlippers/unleashed-firmware/pull/77)
|
||||
- Sub-GHz -> Long press OK button in Sub-GHz Frequency analyzer to switch to Read menu [(by derskythe)](https://github.com/DarkFlippers/unleashed-firmware/pull/79)
|
||||
- Lock device with pin(or regular lock if pin not set) by holding UP button on main screen [(by an4tur0r)](https://github.com/DarkFlippers/unleashed-firmware/pull/107)
|
||||
|
||||
# Instructions
|
||||
## First look at official docs [docs.flipper.net](https://docs.flipper.net/)
|
||||
## [How to install](/documentation/HowToInstall.md) - [versions info](/CHANGELOG.md#recommended-update-option---web-updater): `r`,` `,`e`...
|
||||
## Firmware & Development
|
||||
## [- How to install firmware](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/HowToInstall.md)
|
||||
|
||||
### - **Developer Documentation** - [developer.flipper.net](https://developer.flipper.net/flipperzero/doxygen)
|
||||
## [- How to build firmware](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/HowToBuild.md)
|
||||
|
||||
### - **[How to build](/documentation/HowToBuild.md#how-to-build-by-yourself) | [Project-structure](#project-structure)**
|
||||
## [- How to connect external CC1101 module](https://github.com/quen0n/flipperzero-ext-cc1101)
|
||||
|
||||
### - **CLion IDE** - How to setup workspace for flipper firmware development [by Savely Krasovsky](https://krasovs.ky/2022/11/01/flipper-zero-clion.html)
|
||||
## [- BadUSB: how to add new keyboard layouts](https://github.com/dummy-decoy/flipperzero_badusb_kl)
|
||||
|
||||
### - **"Hello world!"** - plugin tutorial [English<sub> by DroomOne</sub> ](https://github.com/DroomOne/Flipper-Plugin-Tutorial) | [Russian<sub> by Pavel Yakovlev</sub>](https://yakovlev.me/hello-flipper-zero/)
|
||||
## [- How to change Flipper name](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/CustomFlipperName.md)
|
||||
|
||||
### - [How to write your own app](https://flipper.atmanos.com/docs/overview/intro). Docs by atmanos **⚠️outdated API**
|
||||
### **Plugins**
|
||||
|
||||
## Firmware & main Apps feature
|
||||
## [- 🎲 Download Extra plugins for Unleashed](https://github.com/xMasterX/unleashed-extra-pack)
|
||||
|
||||
### - System: [How to change Flipper name](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/CustomFlipperName.md)
|
||||
## [- Configure Sub-GHz Remote App](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/SubGHzRemotePlugin.md)
|
||||
|
||||
### - BadUSB: [How to add new keyboard layouts](https://github.com/dummy-decoy/flipperzero_badusb_kl)
|
||||
## [- TOTP (Authenticator) config description](https://github.com/akopachov/flipper-zero_authenticator/blob/master/docs/conf-file_description.md)
|
||||
|
||||
### - Infrared: [How to make captures to add them into Universal IR remotes](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/InfraredCaptures.md)
|
||||
## [- Barcode Generator](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/BarcodeGenerator.md)
|
||||
|
||||
## **Sub-GHz**
|
||||
## [- Multi Converter](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/MultiConverter.md)
|
||||
|
||||
### - [How to use Flipper as new remote (Nice FlorS, BFT Mitto, Somfy Telis, Aprimatic, AN-Motors, etc..)](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/SubGHzRemoteProg.md)
|
||||
## [- WAV Player sample files & how to convert](https://github.com/UberGuidoZ/Flipper/tree/main/Wav_Player#readme)
|
||||
|
||||
### - External Radio: [How to connect CC1101 module](https://github.com/quen0n/flipperzero-ext-cc1101)
|
||||
## [- Sub-GHz playlist generator script](https://github.com/darmiel/flipper-scripts/blob/main/playlist/playlist_creator_by_chunk.py)
|
||||
|
||||
### - Transmission is blocked? [How to extend Sub-GHz frequency range](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/DangerousSettings.md)
|
||||
### **Plugins that works with external hardware**
|
||||
|
||||
### - [How to add extra Sub-GHz frequencies](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/SubGHzSettings.md)
|
||||
## [- How to use: Unitemp - Temperature sensors reader](https://github.com/quen0n/unitemp-flipperzero#readme)
|
||||
|
||||
### - [~~Configure Sub-GHz Remote App~~](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/SubGHzRemotePlugin.md) Not recommended, please use embedded configurator
|
||||
## [- How to use: [NMEA] GPS](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/applications/plugins/gps_nmea_uart/README.md)
|
||||
|
||||
## **Plugins**
|
||||
## [- How to use: i2c Tools](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/applications/plugins/flipper_i2ctools/README.md)
|
||||
|
||||
### - TOTP (Authenticator): [config description](https://github.com/akopachov/flipper-zero_authenticator/blob/master/docs/conf-file_description.md)
|
||||
## [- How to use: [NRF24] plugins](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/NRF24.md)
|
||||
|
||||
### - Barcode Generator: [How to use](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/BarcodeGenerator.md)
|
||||
## [- How to use: [WiFi] Scanner](https://github.com/SequoiaSan/FlipperZero-WiFi-Scanner_Module#readme)
|
||||
|
||||
### - Multi Converter: [How to use](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/MultiConverter.md)
|
||||
## [- How to use: [ESP8266] Deauther](https://github.com/SequoiaSan/FlipperZero-Wifi-ESP8266-Deauther-Module#readme)
|
||||
|
||||
### - WAV Player: [sample files & how to convert](https://github.com/UberGuidoZ/Flipper/tree/main/Wav_Player#readme)
|
||||
## [- How to use: [ESP32] WiFi Marauder](https://github.com/UberGuidoZ/Flipper/tree/main/Wifi_DevBoard)
|
||||
|
||||
### - Sub-GHz playlist: [generator script](https://github.com/darmiel/flipper-scripts/blob/main/playlist/playlist_creator_by_chunk.py)
|
||||
## [- [WiFi] Scanner - Web Flasher for module firmware](https://sequoiasan.github.io/FlipperZero-WiFi-Scanner_Module/)
|
||||
|
||||
## **Plugins that works with external hardware** [GPIO]
|
||||
## [- [ESP8266] Deauther - Web Flasher for module firmware](https://sequoiasan.github.io/FlipperZero-Wifi-ESP8266-Deauther-Module/)
|
||||
|
||||
### - Unitemp - Temperature sensors reader: [How to use & supported sensors](https://github.com/quen0n/unitemp-flipperzero#readme)
|
||||
## [- Windows: How to Upload .bin to ESP32/ESP8266](https://github.com/SequoiaSan/Guide-How-To-Upload-bin-to-ESP8266-ESP32)
|
||||
|
||||
### - [NMEA] GPS: [How to use](https://github.com/xMasterX/all-the-plugins/blob/dev/base_pack/gps_nmea_uart/README.md)
|
||||
## [- How to use: [GPIO] SentrySafe plugin](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/SentrySafe.md)
|
||||
|
||||
### - i2c Tools [How to use](https://github.com/xMasterX/all-the-plugins/blob/dev/base_pack/flipper_i2ctools/README.md)
|
||||
### **Sub-GHz**
|
||||
|
||||
### - [NRF24] plugins: [How to use](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/NRF24.md)
|
||||
## [- Transmission is blocked? - How to extend Sub-GHz frequency range](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/DangerousSettings.md)
|
||||
|
||||
|
||||
### - [WiFi] Scanner: [How to use](https://github.com/SequoiaSan/FlipperZero-WiFi-Scanner_Module#readme) | [Web Flasher](https://sequoiasan.github.io/FlipperZero-WiFi-Scanner_Module/)
|
||||
|
||||
### - [ESP8266] Deauther: [How to use](https://github.com/SequoiaSan/FlipperZero-Wifi-ESP8266-Deauther-Module#readme) | [Web Flasher](https://sequoiasan.github.io/FlipperZero-Wifi-ESP8266-Deauther-Module/)
|
||||
|
||||
### - [ESP32] WiFi Marauder: [How to use](https://github.com/UberGuidoZ/Flipper/tree/main/Wifi_DevBoard)<sub> docs by UberGuidoZ</sub> | [Marauder repo](https://github.com/justcallmekoko/ESP32Marauder)
|
||||
|
||||
### - [ESP32-CAM] Camera Suite: [How to use](https://github.com/CodyTolene/Flipper-Zero-Camera-Suite)
|
||||
|
||||
### - How to Upload `.bin` to ESP32/ESP8266: [Windows](https://github.com/SequoiaSan/Guide-How-To-Upload-bin-to-ESP8266-ESP32) | [FAP "ESP flasher"](https://github.com/0xchocolate/flipperzero-esp-flasher)
|
||||
|
||||
### - [GPIO] SentrySafe plugin: [How to use](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/SentrySafe.md)
|
||||
## [- How to add extra Sub-GHz frequencies](https://github.com/DarkFlippers/unleashed-firmware/blob/dev/documentation/SubGHzSettings.md)
|
||||
|
||||
<br>
|
||||
<br>
|
||||
@@ -249,16 +230,19 @@ See full list and sources here: [xMasterX/all-the-plugins](https://github.com/xM
|
||||
# Where I can find IR, Sub-GHz, ... files, DBs, and other stuff?
|
||||
## [UberGuidoZ Playground - Large collection of files - Github](https://github.com/UberGuidoZ/Flipper)
|
||||
## [Awesome Flipper Zero - Github](https://github.com/djsime1/awesome-flipperzero)
|
||||
## [CAME-12bit, NICE-12bit, Linear-10bit, PT-2240 - Sub-GHz fixed code bruteforce](https://github.com/tobiabocchi/flipperzero-bruteforce)
|
||||
## [SMC5326, UNILARM - Sub-GHz fixed code bruteforce](https://github.com/Hong5489/flipperzero-gate-bruteforce)
|
||||
|
||||
<br>
|
||||
<br>
|
||||
|
||||
# Links
|
||||
|
||||
* Official Docs: [docs.flipper.net](https://docs.flipper.net/)
|
||||
* Official Forum: [forum.flipperzero.one](https://forum.flipperzero.one/)
|
||||
* Unofficial Discord: [discord.unleashedflip.com](https://discord.unleashedflip.com)
|
||||
* Docs by atmanos / How to write your own app (outdated API): [https://flipper.atmanos.com/docs/overview/intro](https://flipper.atmanos.com/docs/overview/intro)
|
||||
|
||||
* Update! Developer Documentation [developer.flipper.net](https://developer.flipper.net/flipperzero/doxygen)
|
||||
* Official Docs: [http://docs.flipperzero.one](http://docs.flipperzero.one)
|
||||
* Official Forum: [forum.flipperzero.one](https://forum.flipperzero.one/)
|
||||
|
||||
# Project structure
|
||||
|
||||
|
||||
265
SConstruct
265
SConstruct
@@ -7,7 +7,7 @@
|
||||
# construction of certain targets behind command-line options.
|
||||
|
||||
import os
|
||||
from fbt.util import open_browser_action
|
||||
from fbt.util import path_as_posix
|
||||
|
||||
DefaultEnvironment(tools=[])
|
||||
|
||||
@@ -42,8 +42,6 @@ distenv = coreenv.Clone(
|
||||
"openocd",
|
||||
"blackmagic",
|
||||
"jflash",
|
||||
"doxygen",
|
||||
"textfile",
|
||||
],
|
||||
ENV=os.environ,
|
||||
UPDATE_BUNDLE_DIR="dist/${DIST_DIR}/f${TARGET_HW}-update-${DIST_SUFFIX}",
|
||||
@@ -67,24 +65,21 @@ if GetOption("fullenv") or any(
|
||||
|
||||
# Target for self-update package
|
||||
dist_basic_arguments = [
|
||||
"${ARGS}",
|
||||
"--bundlever",
|
||||
"${UPDATE_VERSION_STRING}",
|
||||
'"${UPDATE_VERSION_STRING}"',
|
||||
]
|
||||
dist_radio_arguments = [
|
||||
"--radio",
|
||||
"${ROOT_DIR.abspath}/${COPRO_STACK_BIN_DIR}/${COPRO_STACK_BIN}",
|
||||
'"${ROOT_DIR.abspath}/${COPRO_STACK_BIN_DIR}/${COPRO_STACK_BIN}"',
|
||||
"--radiotype",
|
||||
"${COPRO_STACK_TYPE}",
|
||||
"${COPRO_DISCLAIMER}",
|
||||
"--obdata",
|
||||
"${ROOT_DIR.abspath}/${COPRO_OB_DATA}",
|
||||
"--stackversion",
|
||||
"${COPRO_CUBE_VERSION}",
|
||||
'"${ROOT_DIR.abspath}/${COPRO_OB_DATA}"',
|
||||
]
|
||||
dist_resource_arguments = [
|
||||
"-r",
|
||||
firmware_env.subst("${RESOURCES_ROOT}"),
|
||||
'"${ROOT_DIR.abspath}/assets/resources"',
|
||||
]
|
||||
dist_splash_arguments = (
|
||||
[
|
||||
@@ -97,7 +92,7 @@ if GetOption("fullenv") or any(
|
||||
|
||||
selfupdate_dist = distenv.DistCommand(
|
||||
"updater_package",
|
||||
(distenv["DIST_DEPENDS"], firmware_env["FW_RESOURCES_MANIFEST"]),
|
||||
(distenv["DIST_DEPENDS"], firmware_env["FW_RESOURCES"]),
|
||||
DIST_EXTRA=[
|
||||
*dist_basic_arguments,
|
||||
*dist_radio_arguments,
|
||||
@@ -130,8 +125,7 @@ if GetOption("fullenv") or any(
|
||||
|
||||
# Installation over USB & CLI
|
||||
usb_update_package = distenv.AddUsbFlashTarget(
|
||||
"#build/usbinstall.flag",
|
||||
(firmware_env["FW_RESOURCES_MANIFEST"], selfupdate_dist),
|
||||
"#build/usbinstall.flag", (firmware_env["FW_RESOURCES"], selfupdate_dist)
|
||||
)
|
||||
distenv.Alias("flash_usb_full", usb_update_package)
|
||||
|
||||
@@ -145,52 +139,42 @@ if GetOption("fullenv") or any(
|
||||
basic_dist = distenv.DistCommand("fw_dist", distenv["DIST_DEPENDS"])
|
||||
distenv.Default(basic_dist)
|
||||
|
||||
dist_dir_name = distenv.GetProjectDirName()
|
||||
dist_dir = distenv.Dir(f"#/dist/{dist_dir_name}")
|
||||
external_apps_artifacts = firmware_env["FW_EXTAPPS"]
|
||||
external_app_list = external_apps_artifacts.application_map.values()
|
||||
|
||||
dist_dir = distenv.GetProjetDirName()
|
||||
fap_dist = [
|
||||
distenv.Install(
|
||||
dist_dir.Dir("debug_elf"),
|
||||
list(app_artifact.debug for app_artifact in external_app_list),
|
||||
distenv.Dir(f"#/dist/{dist_dir}/apps/debug_elf"),
|
||||
list(
|
||||
app_artifact.debug
|
||||
for app_artifact in firmware_env["FW_EXTAPPS"].applications.values()
|
||||
),
|
||||
),
|
||||
*(
|
||||
distenv.Install(
|
||||
dist_dir.File(dist_entry[1]).dir,
|
||||
app_artifact.compact,
|
||||
f"#/dist/{dist_dir}/apps/{app_artifact.app.fap_category}",
|
||||
app_artifact.compact[0],
|
||||
)
|
||||
for app_artifact in external_app_list
|
||||
for dist_entry in app_artifact.dist_entries
|
||||
for app_artifact in firmware_env["FW_EXTAPPS"].applications.values()
|
||||
),
|
||||
]
|
||||
Depends(
|
||||
fap_dist,
|
||||
list(app_artifact.validator for app_artifact in external_app_list),
|
||||
list(
|
||||
app_artifact.validator
|
||||
for app_artifact in firmware_env["FW_EXTAPPS"].applications.values()
|
||||
),
|
||||
)
|
||||
Alias("fap_dist", fap_dist)
|
||||
# distenv.Default(fap_dist)
|
||||
|
||||
distenv.Depends(firmware_env["FW_RESOURCES"], firmware_env["FW_EXTAPPS"].resources_dist)
|
||||
|
||||
# Copy all faps to device
|
||||
|
||||
fap_deploy = distenv.PhonyTarget(
|
||||
"fap_deploy",
|
||||
Action(
|
||||
[
|
||||
[
|
||||
"${PYTHON3}",
|
||||
"${FBT_SCRIPT_DIR}/storage.py",
|
||||
"-p",
|
||||
"${FLIP_PORT}",
|
||||
"send",
|
||||
"${SOURCE}",
|
||||
"/ext/apps",
|
||||
"${ARGS}",
|
||||
]
|
||||
]
|
||||
),
|
||||
source=firmware_env.Dir(("${RESOURCES_ROOT}/apps")),
|
||||
"${PYTHON3} ${ROOT_DIR}/scripts/storage.py send ${SOURCE} /ext/apps",
|
||||
source=Dir("#/assets/resources/apps"),
|
||||
)
|
||||
Depends(fap_deploy, firmware_env["FW_RESOURCES_MANIFEST"])
|
||||
|
||||
|
||||
# Target for bundling core2 package for qFlipper
|
||||
@@ -201,17 +185,29 @@ copro_dist = distenv.CoproBuilder(
|
||||
distenv.AlwaysBuild(copro_dist)
|
||||
distenv.Alias("copro_dist", copro_dist)
|
||||
|
||||
|
||||
firmware_flash = distenv.AddFwFlashTarget(firmware_env)
|
||||
firmware_flash = distenv.AddOpenOCDFlashTarget(firmware_env)
|
||||
distenv.Alias("flash", firmware_flash)
|
||||
|
||||
# To be implemented in fwflash.py
|
||||
firmware_jflash = distenv.AddJFlashTarget(firmware_env)
|
||||
distenv.Alias("jflash", firmware_jflash)
|
||||
|
||||
distenv.PhonyTarget(
|
||||
firmware_bm_flash = distenv.PhonyTarget(
|
||||
"flash_blackmagic",
|
||||
"$GDB $GDBOPTS $SOURCES $GDBFLASH",
|
||||
source=firmware_env["FW_ELF"],
|
||||
GDBOPTS="${GDBOPTS_BASE} ${GDBOPTS_BLACKMAGIC}",
|
||||
GDBREMOTE="${BLACKMAGIC_ADDR}",
|
||||
GDBFLASH=[
|
||||
"-ex",
|
||||
"load",
|
||||
"-ex",
|
||||
"quit",
|
||||
],
|
||||
)
|
||||
|
||||
gdb_backtrace_all_threads = distenv.PhonyTarget(
|
||||
"gdb_trace_all",
|
||||
[["${GDB}", "${GDBOPTS}", "${SOURCES}", "${GDBFLASH}"]],
|
||||
"$GDB $GDBOPTS $SOURCES $GDBFLASH",
|
||||
source=firmware_env["FW_ELF"],
|
||||
GDBOPTS="${GDBOPTS_BASE}",
|
||||
GDBREMOTE="${OPENOCD_GDB_PIPE}",
|
||||
@@ -230,122 +226,72 @@ firmware_debug = distenv.PhonyTarget(
|
||||
source=firmware_env["FW_ELF"],
|
||||
GDBOPTS="${GDBOPTS_BASE}",
|
||||
GDBREMOTE="${OPENOCD_GDB_PIPE}",
|
||||
FBT_FAP_DEBUG_ELF_ROOT=firmware_env["FBT_FAP_DEBUG_ELF_ROOT"],
|
||||
FBT_FAP_DEBUG_ELF_ROOT=path_as_posix(firmware_env.subst("$FBT_FAP_DEBUG_ELF_ROOT")),
|
||||
)
|
||||
distenv.Depends(firmware_debug, firmware_flash)
|
||||
|
||||
firmware_blackmagic = distenv.PhonyTarget(
|
||||
distenv.PhonyTarget(
|
||||
"blackmagic",
|
||||
"${GDBPYCOM}",
|
||||
source=firmware_env["FW_ELF"],
|
||||
GDBOPTS="${GDBOPTS_BASE} ${GDBOPTS_BLACKMAGIC}",
|
||||
GDBREMOTE="${BLACKMAGIC_ADDR}",
|
||||
FBT_FAP_DEBUG_ELF_ROOT=firmware_env["FBT_FAP_DEBUG_ELF_ROOT"],
|
||||
FBT_FAP_DEBUG_ELF_ROOT=path_as_posix(firmware_env.subst("$FBT_FAP_DEBUG_ELF_ROOT")),
|
||||
)
|
||||
distenv.Depends(firmware_blackmagic, firmware_flash)
|
||||
|
||||
# Debug alien elf
|
||||
debug_other_opts = [
|
||||
"-ex",
|
||||
"source ${FBT_DEBUG_DIR}/PyCortexMDebug/PyCortexMDebug.py",
|
||||
# "-ex",
|
||||
# "source ${FBT_DEBUG_DIR}/FreeRTOS/FreeRTOS.py",
|
||||
"-ex",
|
||||
"source ${FBT_DEBUG_DIR}/flipperversion.py",
|
||||
"-ex",
|
||||
"fw-version",
|
||||
]
|
||||
|
||||
distenv.PhonyTarget(
|
||||
"debug_other",
|
||||
"${GDBPYCOM}",
|
||||
GDBOPTS="${GDBOPTS_BASE}",
|
||||
GDBREMOTE="${OPENOCD_GDB_PIPE}",
|
||||
GDBPYOPTS=debug_other_opts,
|
||||
GDBPYOPTS='-ex "source ${FBT_DEBUG_DIR}/PyCortexMDebug/PyCortexMDebug.py" ',
|
||||
)
|
||||
|
||||
distenv.PhonyTarget(
|
||||
"debug_other_blackmagic",
|
||||
"${GDBPYCOM}",
|
||||
GDBOPTS="${GDBOPTS_BASE} ${GDBOPTS_BLACKMAGIC}",
|
||||
GDBREMOTE="${BLACKMAGIC_ADDR}",
|
||||
GDBPYOPTS=debug_other_opts,
|
||||
GDBOPTS="${GDBOPTS_BASE} ${GDBOPTS_BLACKMAGIC}",
|
||||
GDBREMOTE="$${BLACKMAGIC_ADDR}",
|
||||
)
|
||||
|
||||
|
||||
# Just start OpenOCD
|
||||
distenv.PhonyTarget(
|
||||
"openocd",
|
||||
[["${OPENOCDCOM}", "${ARGS}"]],
|
||||
"${OPENOCDCOM}",
|
||||
)
|
||||
|
||||
# Linter
|
||||
distenv.PhonyTarget(
|
||||
"lint",
|
||||
[
|
||||
[
|
||||
"${PYTHON3}",
|
||||
"${FBT_SCRIPT_DIR}/lint.py",
|
||||
"check",
|
||||
"${LINT_SOURCES}",
|
||||
"${ARGS}",
|
||||
]
|
||||
],
|
||||
"${PYTHON3} ${FBT_SCRIPT_DIR}/lint.py check ${LINT_SOURCES}",
|
||||
LINT_SOURCES=[n.srcnode() for n in firmware_env["LINT_SOURCES"]],
|
||||
)
|
||||
|
||||
distenv.PhonyTarget(
|
||||
"format",
|
||||
[
|
||||
[
|
||||
"${PYTHON3}",
|
||||
"${FBT_SCRIPT_DIR}/lint.py",
|
||||
"format",
|
||||
"${LINT_SOURCES}",
|
||||
"${ARGS}",
|
||||
]
|
||||
],
|
||||
"${PYTHON3} ${FBT_SCRIPT_DIR}/lint.py format ${LINT_SOURCES}",
|
||||
LINT_SOURCES=[n.srcnode() for n in firmware_env["LINT_SOURCES"]],
|
||||
)
|
||||
|
||||
# PY_LINT_SOURCES contains recursively-built modules' SConscript files
|
||||
# PY_LINT_SOURCES contains recursively-built modules' SConscript files + application manifests
|
||||
# Here we add additional Python files residing in repo root
|
||||
firmware_env.Append(
|
||||
PY_LINT_SOURCES=[
|
||||
# Py code folders
|
||||
"site_scons",
|
||||
"scripts",
|
||||
"applications",
|
||||
"applications_user",
|
||||
"assets",
|
||||
"targets",
|
||||
# Extra files
|
||||
"SConstruct",
|
||||
"firmware.scons",
|
||||
"fbt_options.py",
|
||||
],
|
||||
IMG_LINT_SOURCES=[
|
||||
# Image assets
|
||||
"applications",
|
||||
"assets",
|
||||
],
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
black_commandline = [
|
||||
[
|
||||
"@${PYTHON3}",
|
||||
"-m",
|
||||
"black",
|
||||
"${PY_BLACK_ARGS}",
|
||||
"${PY_LINT_SOURCES}",
|
||||
"${ARGS}",
|
||||
]
|
||||
]
|
||||
black_base_args = [
|
||||
"--include",
|
||||
'"(\\.scons|\\.py|SConscript|SConstruct|\\.fam)$"',
|
||||
]
|
||||
black_commandline = "@${PYTHON3} -m black ${PY_BLACK_ARGS} ${PY_LINT_SOURCES}"
|
||||
black_base_args = ["--include", '"\\.scons|\\.py|SConscript|SConstruct"']
|
||||
|
||||
distenv.PhonyTarget(
|
||||
"lint_py",
|
||||
@@ -365,64 +311,8 @@ distenv.PhonyTarget(
|
||||
PY_LINT_SOURCES=firmware_env["PY_LINT_SOURCES"],
|
||||
)
|
||||
|
||||
# Image assets linting
|
||||
distenv.PhonyTarget(
|
||||
"lint_img",
|
||||
[
|
||||
[
|
||||
"${PYTHON3}",
|
||||
"${FBT_SCRIPT_DIR}/imglint.py",
|
||||
"check",
|
||||
"${IMG_LINT_SOURCES}",
|
||||
"${ARGS}",
|
||||
]
|
||||
],
|
||||
IMG_LINT_SOURCES=firmware_env["IMG_LINT_SOURCES"],
|
||||
)
|
||||
|
||||
distenv.PhonyTarget(
|
||||
"format_img",
|
||||
[
|
||||
[
|
||||
"${PYTHON3}",
|
||||
"${FBT_SCRIPT_DIR}/imglint.py",
|
||||
"format",
|
||||
"${IMG_LINT_SOURCES}",
|
||||
"${ARGS}",
|
||||
]
|
||||
],
|
||||
IMG_LINT_SOURCES=firmware_env["IMG_LINT_SOURCES"],
|
||||
)
|
||||
|
||||
distenv.Alias("lint_all", ["lint", "lint_py", "lint_img"])
|
||||
distenv.Alias("format_all", ["format", "format_py", "format_img"])
|
||||
|
||||
|
||||
# Start Flipper CLI via PySerial's miniterm
|
||||
distenv.PhonyTarget(
|
||||
"cli",
|
||||
[
|
||||
[
|
||||
"${PYTHON3}",
|
||||
"${FBT_SCRIPT_DIR}/serial_cli.py",
|
||||
"-p",
|
||||
"${FLIP_PORT}",
|
||||
"${ARGS}",
|
||||
]
|
||||
],
|
||||
)
|
||||
|
||||
# Update WiFi devboard firmware with release channel
|
||||
distenv.PhonyTarget(
|
||||
"devboard_flash",
|
||||
[
|
||||
[
|
||||
"${PYTHON3}",
|
||||
"${FBT_SCRIPT_DIR}/wifi_board.py",
|
||||
"${ARGS}",
|
||||
]
|
||||
],
|
||||
)
|
||||
distenv.PhonyTarget("cli", "${PYTHON3} ${FBT_SCRIPT_DIR}/serial_cli.py")
|
||||
|
||||
|
||||
# Find blackmagic probe
|
||||
@@ -436,50 +326,13 @@ distenv.PhonyTarget(
|
||||
distenv.PhonyTarget(
|
||||
"get_stlink",
|
||||
distenv.Action(
|
||||
lambda **_: distenv.GetDevices(),
|
||||
lambda **kw: distenv.GetDevices(),
|
||||
None,
|
||||
),
|
||||
)
|
||||
|
||||
# Prepare vscode environment
|
||||
vscode_dist = distenv.Install(
|
||||
"#.vscode",
|
||||
[
|
||||
distenv.Glob("#.vscode/example/*.json", exclude="*.tmpl"),
|
||||
distenv.Glob("#.vscode/example/${LANG_SERVER}/*.json"),
|
||||
],
|
||||
)
|
||||
for template_file in distenv.Glob("#.vscode/example/*.tmpl"):
|
||||
vscode_dist.append(
|
||||
distenv.Substfile(
|
||||
distenv.Dir("#.vscode").File(template_file.name.replace(".tmpl", "")),
|
||||
template_file,
|
||||
SUBST_DICT={
|
||||
"@FBT_PLATFORM_EXECUTABLE_EXT@": ".exe" if os.name == "nt" else ""
|
||||
},
|
||||
)
|
||||
)
|
||||
vscode_dist = distenv.Install("#.vscode", distenv.Glob("#.vscode/example/*"))
|
||||
distenv.Precious(vscode_dist)
|
||||
distenv.NoClean(vscode_dist)
|
||||
distenv.Alias("vscode_dist", (vscode_dist, firmware_env["FW_CDB"]))
|
||||
|
||||
# Configure shell with build tools
|
||||
distenv.PhonyTarget(
|
||||
"env",
|
||||
"@echo $( ${FBT_SCRIPT_DIR.abspath}/toolchain/fbtenv.sh $)",
|
||||
)
|
||||
|
||||
doxy_build = distenv.DoxyBuild(
|
||||
"documentation/doxygen/build/html/index.html",
|
||||
"documentation/doxygen/Doxyfile-awesome.cfg",
|
||||
doxy_env_variables={
|
||||
"DOXY_SRC_ROOT": Dir(".").abspath,
|
||||
"DOXY_BUILD_DIR": Dir("documentation/doxygen/build").abspath,
|
||||
"DOXY_CONFIG_DIR": "documentation/doxygen",
|
||||
},
|
||||
)
|
||||
distenv.Alias("doxygen", doxy_build)
|
||||
distenv.AlwaysBuild(doxy_build)
|
||||
|
||||
# Open generated documentation in browser
|
||||
distenv.PhonyTarget("doxy", open_browser_action, source=doxy_build)
|
||||
distenv.Alias("vscode_dist", vscode_dist)
|
||||
|
||||
@@ -26,6 +26,7 @@ Applications for main Flipper menu.
|
||||
|
||||
- `archive` - Archive and file manager
|
||||
- `bad_usb` - Bad USB application
|
||||
- `fap_loader` - External applications loader
|
||||
- `gpio` - GPIO application: includes USART bridge and GPIO control
|
||||
- `ibutton` - iButton application, onewire keys and more
|
||||
- `infrared` - Infrared application, controls your IR devices
|
||||
@@ -35,11 +36,22 @@ Applications for main Flipper menu.
|
||||
- `u2f` - U2F Application
|
||||
|
||||
|
||||
## plugins
|
||||
|
||||
Extra apps for Plugins & App Loader menus.
|
||||
|
||||
- `bt_hid_app` - BT Remote controller
|
||||
- `music_player` - Music player app (demo)
|
||||
- `picopass` - Picopass tool
|
||||
- `snake_game` - Snake game application
|
||||
|
||||
|
||||
## services
|
||||
|
||||
Background services providing system APIs to applications.
|
||||
|
||||
- `applications.h` - Firmware application list header
|
||||
|
||||
- `bt` - BLE service and application
|
||||
- `cli` - Console service and API
|
||||
- `crypto` - Crypto cli tools
|
||||
@@ -71,10 +83,7 @@ Small applications providing configuration for basic firmware and its services.
|
||||
|
||||
## system
|
||||
|
||||
Utility apps not visible in other menus, plus few external apps pre-packaged with the firmware.
|
||||
Utility apps not visible in other menus.
|
||||
|
||||
- `hid_app` - BLE & USB HID remote
|
||||
- `js_app` - JS engine runner
|
||||
- `snake_game` - Snake game
|
||||
- `storage_move_to_sd` - Data migration tool for internal storage
|
||||
- `updater` - Update service & application
|
||||
|
||||
@@ -34,16 +34,12 @@ void AccessorApp::run(void) {
|
||||
AccessorApp::AccessorApp()
|
||||
: text_store{0} {
|
||||
notification = static_cast<NotificationApp*>(furi_record_open(RECORD_NOTIFICATION));
|
||||
expansion = static_cast<Expansion*>(furi_record_open(RECORD_EXPANSION));
|
||||
onewire_host = onewire_host_alloc(&gpio_ibutton);
|
||||
expansion_disable(expansion);
|
||||
onewire_host = onewire_host_alloc(&ibutton_gpio);
|
||||
furi_hal_power_enable_otg();
|
||||
}
|
||||
|
||||
AccessorApp::~AccessorApp() {
|
||||
furi_hal_power_disable_otg();
|
||||
expansion_enable(expansion);
|
||||
furi_record_close(RECORD_EXPANSION);
|
||||
furi_record_close(RECORD_NOTIFICATION);
|
||||
onewire_host_free(onewire_host);
|
||||
}
|
||||
|
||||
@@ -6,35 +6,34 @@
|
||||
#include "helpers/wiegand.h"
|
||||
#include <one_wire/one_wire_host.h>
|
||||
#include <notification/notification_messages.h>
|
||||
#include <expansion/expansion.h>
|
||||
|
||||
class AccessorApp {
|
||||
public:
|
||||
void run(void);
|
||||
|
||||
AccessorApp(void);
|
||||
~AccessorApp(void);
|
||||
AccessorApp();
|
||||
~AccessorApp();
|
||||
|
||||
enum class Scene : uint8_t {
|
||||
Exit,
|
||||
Start,
|
||||
};
|
||||
|
||||
AccessorAppViewManager* get_view_manager(void);
|
||||
AccessorAppViewManager* get_view_manager();
|
||||
void switch_to_next_scene(Scene index);
|
||||
void search_and_switch_to_previous_scene(std::initializer_list<Scene> scenes_list);
|
||||
bool switch_to_previous_scene(uint8_t count = 1);
|
||||
Scene get_previous_scene(void);
|
||||
Scene get_previous_scene();
|
||||
|
||||
void notify_green_blink(void);
|
||||
void notify_success(void);
|
||||
void notify_green_blink();
|
||||
void notify_success();
|
||||
|
||||
char* get_text_store(void);
|
||||
uint8_t get_text_store_size(void);
|
||||
char* get_text_store();
|
||||
uint8_t get_text_store_size();
|
||||
void set_text_store(const char* text...);
|
||||
|
||||
WIEGAND* get_wiegand(void);
|
||||
OneWireHost* get_one_wire(void);
|
||||
WIEGAND* get_wiegand();
|
||||
OneWireHost* get_one_wire();
|
||||
|
||||
private:
|
||||
std::list<Scene> previous_scenes_list = {Scene::Exit};
|
||||
@@ -52,5 +51,4 @@ private:
|
||||
OneWireHost* onewire_host;
|
||||
|
||||
NotificationApp* notification;
|
||||
Expansion* expansion;
|
||||
};
|
||||
|
||||
@@ -1,53 +1,49 @@
|
||||
#include "accessor_view_manager.h"
|
||||
#include "accessor_event.h"
|
||||
#include "callback_connector.h"
|
||||
#include <callback-connector.h>
|
||||
|
||||
AccessorAppViewManager::AccessorAppViewManager() {
|
||||
event_queue = furi_message_queue_alloc(10, sizeof(AccessorEvent));
|
||||
|
||||
view_holder = view_holder_alloc();
|
||||
auto callback =
|
||||
cbc::obtain_connector(this, &AccessorAppViewManager::view_holder_back_callback);
|
||||
view_dispatcher = view_dispatcher_alloc();
|
||||
auto callback = cbc::obtain_connector(this, &AccessorAppViewManager::previous_view_callback);
|
||||
|
||||
// allocate views
|
||||
submenu = submenu_alloc();
|
||||
popup = popup_alloc();
|
||||
add_view(ViewType::Submenu, submenu_get_view(submenu));
|
||||
|
||||
// set back callback
|
||||
view_holder_set_back_callback(view_holder, callback, NULL);
|
||||
popup = popup_alloc();
|
||||
add_view(ViewType::Popup, popup_get_view(popup));
|
||||
|
||||
gui = static_cast<Gui*>(furi_record_open(RECORD_GUI));
|
||||
view_holder_attach_to_gui(view_holder, gui);
|
||||
view_dispatcher_attach_to_gui(view_dispatcher, gui, ViewDispatcherTypeFullscreen);
|
||||
|
||||
// set previous view callback for all views
|
||||
view_set_previous_callback(submenu_get_view(submenu), callback);
|
||||
view_set_previous_callback(popup_get_view(popup), callback);
|
||||
}
|
||||
|
||||
AccessorAppViewManager::~AccessorAppViewManager() {
|
||||
// remove current view
|
||||
view_holder_set_view(view_holder, NULL);
|
||||
// remove views
|
||||
view_dispatcher_remove_view(
|
||||
view_dispatcher, static_cast<uint32_t>(AccessorAppViewManager::ViewType::Submenu));
|
||||
view_dispatcher_remove_view(
|
||||
view_dispatcher, static_cast<uint32_t>(AccessorAppViewManager::ViewType::Popup));
|
||||
|
||||
// free view modules
|
||||
furi_record_close(RECORD_GUI);
|
||||
submenu_free(submenu);
|
||||
popup_free(popup);
|
||||
// free view holder
|
||||
view_holder_free(view_holder);
|
||||
|
||||
// free dispatcher
|
||||
view_dispatcher_free(view_dispatcher);
|
||||
|
||||
// free event queue
|
||||
furi_message_queue_free(event_queue);
|
||||
}
|
||||
|
||||
void AccessorAppViewManager::switch_to(ViewType type) {
|
||||
View* view;
|
||||
|
||||
switch(type) {
|
||||
case ViewType::Submenu:
|
||||
view = submenu_get_view(submenu);
|
||||
break;
|
||||
case ViewType::Popup:
|
||||
view = popup_get_view(popup);
|
||||
break;
|
||||
default:
|
||||
furi_crash();
|
||||
}
|
||||
|
||||
view_holder_set_view(view_holder, view);
|
||||
view_dispatcher_switch_to_view(view_dispatcher, static_cast<uint32_t>(type));
|
||||
}
|
||||
|
||||
Submenu* AccessorAppViewManager::get_submenu() {
|
||||
@@ -69,10 +65,16 @@ void AccessorAppViewManager::send_event(AccessorEvent* event) {
|
||||
furi_check(result == FuriStatusOk);
|
||||
}
|
||||
|
||||
void AccessorAppViewManager::view_holder_back_callback(void*) {
|
||||
uint32_t AccessorAppViewManager::previous_view_callback(void*) {
|
||||
if(event_queue != NULL) {
|
||||
AccessorEvent event;
|
||||
event.type = AccessorEvent::Type::Back;
|
||||
send_event(&event);
|
||||
}
|
||||
|
||||
return VIEW_IGNORE;
|
||||
}
|
||||
|
||||
void AccessorAppViewManager::add_view(ViewType view_type, View* view) {
|
||||
view_dispatcher_add_view(view_dispatcher, static_cast<uint32_t>(view_type), view);
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
#include <furi.h>
|
||||
#include <gui/view_holder.h>
|
||||
#include <gui/view_dispatcher.h>
|
||||
#include <gui/modules/submenu.h>
|
||||
#include <gui/modules/popup.h>
|
||||
#include "accessor_event.h"
|
||||
@@ -10,26 +10,28 @@ public:
|
||||
enum class ViewType : uint8_t {
|
||||
Submenu,
|
||||
Popup,
|
||||
Tune,
|
||||
};
|
||||
|
||||
FuriMessageQueue* event_queue;
|
||||
|
||||
AccessorAppViewManager(void);
|
||||
~AccessorAppViewManager(void);
|
||||
AccessorAppViewManager();
|
||||
~AccessorAppViewManager();
|
||||
|
||||
void switch_to(ViewType type);
|
||||
|
||||
void receive_event(AccessorEvent* event);
|
||||
void send_event(AccessorEvent* event);
|
||||
|
||||
Submenu* get_submenu(void);
|
||||
Popup* get_popup(void);
|
||||
Submenu* get_submenu();
|
||||
Popup* get_popup();
|
||||
|
||||
private:
|
||||
ViewDispatcher* view_dispatcher;
|
||||
Gui* gui;
|
||||
ViewHolder* view_holder;
|
||||
|
||||
void view_holder_back_callback(void* context);
|
||||
uint32_t previous_view_callback(void* context);
|
||||
void add_view(ViewType view_type, View* view);
|
||||
|
||||
// view elements
|
||||
Submenu* submenu;
|
||||
|
||||
@@ -4,6 +4,7 @@ App(
|
||||
apptype=FlipperAppType.DEBUG,
|
||||
targets=["f7"],
|
||||
entry_point="accessor_app",
|
||||
cdefines=["APP_ACCESSOR"],
|
||||
requires=["gui"],
|
||||
stack_size=4 * 1024,
|
||||
order=40,
|
||||
|
||||
@@ -1,106 +0,0 @@
|
||||
#ifndef CALLBACKCONNECTOR_H
|
||||
#define CALLBACKCONNECTOR_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include <functional>
|
||||
namespace cbc {
|
||||
namespace Details {
|
||||
|
||||
template <std::size_t Tag, typename T, typename Ret, typename... Args>
|
||||
class FuncMemberWrapper {
|
||||
public:
|
||||
FuncMemberWrapper() = delete;
|
||||
using member_fun_t = Ret (T::*)(Args...);
|
||||
using const_member_fun_t = Ret (T::*)(Args...) const;
|
||||
static auto instantiate(T* t, member_fun_t ptr) {
|
||||
obj = t;
|
||||
member = ptr;
|
||||
return MetaCall;
|
||||
}
|
||||
|
||||
static auto instantiate(T* t, const_member_fun_t ptr) {
|
||||
obj = t;
|
||||
const_member = ptr;
|
||||
return ConstMetaCall;
|
||||
}
|
||||
|
||||
private:
|
||||
static auto MetaCall(Args... args) {
|
||||
return (*obj.*member)(args...);
|
||||
}
|
||||
static auto ConstMetaCall(Args... args) {
|
||||
return (*obj.*const_member)(args...);
|
||||
}
|
||||
static T* obj;
|
||||
static member_fun_t member;
|
||||
static const_member_fun_t const_member;
|
||||
};
|
||||
template <std::size_t Tag, typename T, typename Ret, typename... Args>
|
||||
T* FuncMemberWrapper<Tag, T, Ret, Args...>::obj{};
|
||||
|
||||
template <std::size_t Tag, typename T, typename Ret, typename... Args>
|
||||
typename FuncMemberWrapper<Tag, T, Ret, Args...>::member_fun_t
|
||||
FuncMemberWrapper<Tag, T, Ret, Args...>::member{};
|
||||
|
||||
template <std::size_t Tag, typename T, typename Ret, typename... Args>
|
||||
typename FuncMemberWrapper<Tag, T, Ret, Args...>::const_member_fun_t
|
||||
FuncMemberWrapper<Tag, T, Ret, Args...>::const_member{};
|
||||
|
||||
template <typename Functor, typename Ret, typename... Args>
|
||||
struct FunctorWrapper {
|
||||
public:
|
||||
static std::function<Ret(Args...)> functor;
|
||||
static auto instatiate(Functor fn) {
|
||||
functor = std::move(fn);
|
||||
return MetaCall;
|
||||
}
|
||||
|
||||
private:
|
||||
static auto MetaCall(Args... args) {
|
||||
return functor(args...);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Functor, typename Ret, typename... Args>
|
||||
std::function<Ret(Args...)> FunctorWrapper<Functor, Ret, Args...>::functor;
|
||||
|
||||
template <typename Functor, typename Ret, typename T, typename... Args>
|
||||
auto deducer(Functor obj, Ret (T::*)(Args...) const) {
|
||||
return FunctorWrapper<Functor, Ret, Args...>::instatiate(std::move(obj));
|
||||
}
|
||||
|
||||
template <typename Functor, typename Ret, typename T, typename... Args>
|
||||
auto deducer(Functor obj, Ret (T::*)(Args...)) {
|
||||
return FunctorWrapper<Functor, Ret, Args...>::instatiate(std::move(obj));
|
||||
}
|
||||
|
||||
template <std::size_t tag, typename T, typename Ret, typename... Args>
|
||||
auto const_instantiate(T* t, Ret (T::*ptr)(Args...) const) {
|
||||
return FuncMemberWrapper<tag, T, Ret, Args...>::instantiate(t, ptr);
|
||||
}
|
||||
|
||||
template <std::size_t tag, typename T, typename Func>
|
||||
auto const_instantiate(T* t, Func ptr) {
|
||||
return const_instantiate(t, ptr);
|
||||
}
|
||||
|
||||
} //end of Details scope
|
||||
|
||||
template <std::size_t tag = 0, typename T, typename Ret, typename... Args>
|
||||
auto obtain_connector(T* t, Ret (T::*ptr)(Args...)) {
|
||||
return Details::FuncMemberWrapper<tag, T, Ret, Args...>::instantiate(t, ptr);
|
||||
}
|
||||
|
||||
template <std::size_t tag = 0, typename T, typename Ret, typename... Args>
|
||||
auto obtain_connector(T* t, Ret (T::*ptr)(Args...) const) {
|
||||
return Details::FuncMemberWrapper<tag, T, Ret, Args...>::instantiate(t, ptr);
|
||||
}
|
||||
|
||||
template <typename Functor>
|
||||
auto obtain_connector(Functor functor) {
|
||||
return Details::deducer(std::move(functor), &Functor::operator());
|
||||
}
|
||||
} //end of cbc scope
|
||||
|
||||
#endif // __cplusplus
|
||||
#endif // CALLBACKCONNECTOR_H
|
||||
@@ -2,12 +2,12 @@
|
||||
#include <furi.h>
|
||||
#include <furi_hal.h>
|
||||
|
||||
unsigned long WIEGAND::_cardTempHigh = 0;
|
||||
unsigned long WIEGAND::_cardTemp = 0;
|
||||
unsigned long WIEGAND::_lastWiegand = 0;
|
||||
volatile unsigned long WIEGAND::_cardTempHigh = 0;
|
||||
volatile unsigned long WIEGAND::_cardTemp = 0;
|
||||
volatile unsigned long WIEGAND::_lastWiegand = 0;
|
||||
unsigned long WIEGAND::_code = 0;
|
||||
unsigned long WIEGAND::_codeHigh = 0;
|
||||
int WIEGAND::_bitCount = 0;
|
||||
volatile int WIEGAND::_bitCount = 0;
|
||||
int WIEGAND::_wiegandType = 0;
|
||||
|
||||
constexpr uint32_t clocks_in_ms = 64 * 1000;
|
||||
@@ -98,7 +98,10 @@ void WIEGAND::ReadD1() {
|
||||
_lastWiegand = DWT->CYCCNT; // Keep track of last wiegand bit received
|
||||
}
|
||||
|
||||
unsigned long WIEGAND::GetCardId(unsigned long* codehigh, unsigned long* codelow, char bitlength) {
|
||||
unsigned long WIEGAND::GetCardId(
|
||||
volatile unsigned long* codehigh,
|
||||
volatile unsigned long* codelow,
|
||||
char bitlength) {
|
||||
if(bitlength == 26) // EM tag
|
||||
return (*codelow & 0x1FFFFFE) >> 1;
|
||||
|
||||
@@ -171,7 +174,7 @@ bool WIEGAND::DoWiegandConversion() {
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO FL-3490: Handle validation failure case!
|
||||
// TODO: Handle validation failure case!
|
||||
} else if(4 == _bitCount) {
|
||||
// 4-bit Wiegand codes have no data integrity check so we just
|
||||
// read the LOW nibble.
|
||||
|
||||
@@ -2,26 +2,28 @@
|
||||
|
||||
class WIEGAND {
|
||||
public:
|
||||
WIEGAND(void);
|
||||
void begin(void);
|
||||
void end(void);
|
||||
bool available(void);
|
||||
unsigned long getCode(void);
|
||||
unsigned long getCodeHigh(void);
|
||||
int getWiegandType(void);
|
||||
WIEGAND();
|
||||
void begin();
|
||||
void end();
|
||||
bool available();
|
||||
unsigned long getCode();
|
||||
unsigned long getCodeHigh();
|
||||
int getWiegandType();
|
||||
|
||||
static void ReadD0(void);
|
||||
static void ReadD1(void);
|
||||
static void ReadD0();
|
||||
static void ReadD1();
|
||||
|
||||
private:
|
||||
static bool DoWiegandConversion(void);
|
||||
static unsigned long
|
||||
GetCardId(unsigned long* codehigh, unsigned long* codelow, char bitlength);
|
||||
static bool DoWiegandConversion();
|
||||
static unsigned long GetCardId(
|
||||
volatile unsigned long* codehigh,
|
||||
volatile unsigned long* codelow,
|
||||
char bitlength);
|
||||
|
||||
static unsigned long _cardTempHigh;
|
||||
static unsigned long _cardTemp;
|
||||
static unsigned long _lastWiegand;
|
||||
static int _bitCount;
|
||||
static volatile unsigned long _cardTempHigh;
|
||||
static volatile unsigned long _cardTemp;
|
||||
static volatile unsigned long _lastWiegand;
|
||||
static volatile int _bitCount;
|
||||
static int _wiegandType;
|
||||
static unsigned long _code;
|
||||
static unsigned long _codeHigh;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include "../accessor_app.h"
|
||||
#include "../accessor_view_manager.h"
|
||||
#include "../accessor_event.h"
|
||||
#include <callback-connector.h>
|
||||
#include "accessor_scene_start.h"
|
||||
|
||||
void AccessorSceneStart::on_enter(AccessorApp* app) {
|
||||
|
||||
@@ -7,11 +7,10 @@ App(
|
||||
"vibro_test",
|
||||
"keypad_test",
|
||||
"usb_test",
|
||||
"usb_mouse",
|
||||
"uart_echo",
|
||||
"USB_Mouse",
|
||||
"UART_Echo",
|
||||
"display_test",
|
||||
"text_box_test",
|
||||
"file_browser_test",
|
||||
"speaker_debug",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -3,6 +3,7 @@ App(
|
||||
name="Battery Test",
|
||||
apptype=FlipperAppType.DEBUG,
|
||||
entry_point="battery_test_app",
|
||||
cdefines=["APP_BATTERY_TEST"],
|
||||
requires=[
|
||||
"gui",
|
||||
"power",
|
||||
|
||||
@@ -12,8 +12,7 @@ void battery_test_dialog_callback(DialogExResult result, void* context) {
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t battery_test_exit_confirm_view(void* context) {
|
||||
UNUSED(context);
|
||||
uint32_t battery_test_exit_confirm_view() {
|
||||
return BatteryTestAppViewExitDialog;
|
||||
}
|
||||
|
||||
@@ -32,7 +31,7 @@ static void battery_test_battery_info_update_model(void* context) {
|
||||
notification_message(app->notifications, &sequence_display_backlight_on);
|
||||
}
|
||||
|
||||
BatteryTestApp* battery_test_alloc(void) {
|
||||
BatteryTestApp* battery_test_alloc() {
|
||||
BatteryTestApp* app = malloc(sizeof(BatteryTestApp));
|
||||
|
||||
// Records
|
||||
@@ -42,6 +41,7 @@ BatteryTestApp* battery_test_alloc(void) {
|
||||
|
||||
// View dispatcher
|
||||
app->view_dispatcher = view_dispatcher_alloc();
|
||||
view_dispatcher_enable_queue(app->view_dispatcher);
|
||||
view_dispatcher_set_event_callback_context(app->view_dispatcher, app);
|
||||
view_dispatcher_set_tick_event_callback(
|
||||
app->view_dispatcher, battery_test_battery_info_update_model, 500);
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#include <gui/elements.h>
|
||||
#include <assets_icons.h>
|
||||
|
||||
#define LOW_CHARGE_THRESHOLD 10
|
||||
#define LOW_CHARGE_THRESHOLD 10
|
||||
#define HIGH_DRAIN_CURRENT_THRESHOLD 100
|
||||
|
||||
struct BatteryInfo {
|
||||
@@ -17,7 +17,7 @@ static void draw_stat(Canvas* canvas, int x, int y, const Icon* icon, char* val)
|
||||
canvas_draw_box(canvas, x - 4, y + 16, 24, 6);
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
canvas_draw_str_aligned(canvas, x + 8, y + 22, AlignCenter, AlignBottom, val);
|
||||
}
|
||||
};
|
||||
|
||||
static void draw_battery(Canvas* canvas, BatteryInfoModel* data, int x, int y) {
|
||||
char emote[20] = {};
|
||||
@@ -68,7 +68,7 @@ static void draw_battery(Canvas* canvas, BatteryInfoModel* data, int x, int y) {
|
||||
drain_current > HIGH_DRAIN_CURRENT_THRESHOLD ? "mA!" : "mA");
|
||||
} else if(drain_current != 0) {
|
||||
snprintf(header, 20, "...");
|
||||
} else if(data->charging_voltage < 4.2f) {
|
||||
} else if(data->charging_voltage < 4.2) {
|
||||
// Non-default battery charging limit, mention it
|
||||
snprintf(emote, sizeof(emote), "Charged!");
|
||||
snprintf(header, sizeof(header), "Limited to");
|
||||
@@ -85,7 +85,7 @@ static void draw_battery(Canvas* canvas, BatteryInfoModel* data, int x, int y) {
|
||||
canvas_draw_str_aligned(canvas, 92, y + 3, AlignCenter, AlignCenter, emote);
|
||||
canvas_draw_str_aligned(canvas, 92, y + 15, AlignCenter, AlignCenter, header);
|
||||
canvas_draw_str_aligned(canvas, 92, y + 27, AlignCenter, AlignCenter, value);
|
||||
}
|
||||
};
|
||||
|
||||
static void battery_info_draw_callback(Canvas* canvas, void* context) {
|
||||
furi_assert(context);
|
||||
@@ -116,7 +116,7 @@ static void battery_info_draw_callback(Canvas* canvas, void* context) {
|
||||
draw_stat(canvas, 104, 42, &I_Health_16x16, health);
|
||||
}
|
||||
|
||||
BatteryInfo* battery_info_alloc(void) {
|
||||
BatteryInfo* battery_info_alloc() {
|
||||
BatteryInfo* battery_info = malloc(sizeof(BatteryInfo));
|
||||
battery_info->view = view_alloc();
|
||||
view_set_context(battery_info->view, battery_info);
|
||||
|
||||
@@ -14,7 +14,7 @@ typedef struct {
|
||||
uint8_t health;
|
||||
} BatteryInfoModel;
|
||||
|
||||
BatteryInfo* battery_info_alloc(void);
|
||||
BatteryInfo* battery_info_alloc();
|
||||
|
||||
void battery_info_free(BatteryInfo* battery_info);
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ App(
|
||||
name="Blink Test",
|
||||
apptype=FlipperAppType.DEBUG,
|
||||
entry_point="blink_test_app",
|
||||
cdefines=["APP_BLINK"],
|
||||
requires=["gui"],
|
||||
stack_size=1 * 1024,
|
||||
order=10,
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#include <core/common_defines.h>
|
||||
#include <furi.h>
|
||||
#include <furi_hal.h>
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ uint32_t bt_debug_start_view(void* context) {
|
||||
return BtDebugAppViewSubmenu;
|
||||
}
|
||||
|
||||
BtDebugApp* bt_debug_app_alloc(void) {
|
||||
BtDebugApp* bt_debug_app_alloc() {
|
||||
BtDebugApp* app = malloc(sizeof(BtDebugApp));
|
||||
|
||||
// Gui
|
||||
@@ -36,6 +36,7 @@ BtDebugApp* bt_debug_app_alloc(void) {
|
||||
|
||||
// View dispatcher
|
||||
app->view_dispatcher = view_dispatcher_alloc();
|
||||
view_dispatcher_enable_queue(app->view_dispatcher);
|
||||
view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen);
|
||||
|
||||
// Views
|
||||
|
||||
@@ -129,7 +129,7 @@ static void bt_test_carrier_timer_callback(void* context) {
|
||||
}
|
||||
}
|
||||
|
||||
BtCarrierTest* bt_carrier_test_alloc(void) {
|
||||
BtCarrierTest* bt_carrier_test_alloc() {
|
||||
BtCarrierTest* bt_carrier_test = malloc(sizeof(BtCarrierTest));
|
||||
bt_carrier_test->bt_test = bt_test_alloc();
|
||||
bt_test_set_context(bt_carrier_test->bt_test, bt_carrier_test);
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
typedef struct BtCarrierTest BtCarrierTest;
|
||||
|
||||
BtCarrierTest* bt_carrier_test_alloc(void);
|
||||
BtCarrierTest* bt_carrier_test_alloc();
|
||||
|
||||
void bt_carrier_test_free(BtCarrierTest* bt_carrier_test);
|
||||
|
||||
|
||||
@@ -97,7 +97,7 @@ static void bt_test_packet_timer_callback(void* context) {
|
||||
}
|
||||
}
|
||||
|
||||
BtPacketTest* bt_packet_test_alloc(void) {
|
||||
BtPacketTest* bt_packet_test_alloc() {
|
||||
BtPacketTest* bt_packet_test = malloc(sizeof(BtPacketTest));
|
||||
bt_packet_test->bt_test = bt_test_alloc();
|
||||
bt_test_set_context(bt_packet_test->bt_test, bt_packet_test);
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
typedef struct BtPacketTest BtPacketTest;
|
||||
|
||||
BtPacketTest* bt_packet_test_alloc(void);
|
||||
BtPacketTest* bt_packet_test_alloc();
|
||||
|
||||
void bt_packet_test_free(BtPacketTest* bt_packet_test);
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ typedef struct {
|
||||
} BtTestModel;
|
||||
|
||||
#define BT_TEST_START_MESSAGE "Ok - Start"
|
||||
#define BT_TEST_STOP_MESSAGE "Ok - Stop"
|
||||
#define BT_TEST_STOP_MESSAGE "Ok - Stop"
|
||||
|
||||
static void bt_test_process_up(BtTest* bt_test);
|
||||
static void bt_test_process_down(BtTest* bt_test);
|
||||
@@ -305,7 +305,7 @@ void bt_test_process_back(BtTest* bt_test) {
|
||||
}
|
||||
}
|
||||
|
||||
BtTest* bt_test_alloc(void) {
|
||||
BtTest* bt_test_alloc() {
|
||||
BtTest* bt_test = malloc(sizeof(BtTest));
|
||||
bt_test->view = view_alloc();
|
||||
view_set_context(bt_test->view, bt_test);
|
||||
@@ -384,7 +384,8 @@ BtTestParam* bt_test_param_add(
|
||||
|
||||
void bt_test_set_rssi(BtTest* bt_test, float rssi) {
|
||||
furi_assert(bt_test);
|
||||
with_view_model(bt_test->view, BtTestModel * model, { model->rssi = rssi; }, true);
|
||||
with_view_model(
|
||||
bt_test->view, BtTestModel * model, { model->rssi = rssi; }, true);
|
||||
}
|
||||
|
||||
void bt_test_set_packets_tx(BtTest* bt_test, uint32_t packets_num) {
|
||||
|
||||
@@ -12,7 +12,7 @@ typedef void (*BtTestBackCallback)(void* context);
|
||||
typedef struct BtTestParam BtTestParam;
|
||||
typedef void (*BtTestParamChangeCallback)(BtTestParam* param);
|
||||
|
||||
BtTest* bt_test_alloc(void);
|
||||
BtTest* bt_test_alloc();
|
||||
|
||||
void bt_test_free(BtTest* bt_test);
|
||||
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
App(
|
||||
appid="ccid_test",
|
||||
name="CCID Debug",
|
||||
apptype=FlipperAppType.DEBUG,
|
||||
entry_point="ccid_test_app",
|
||||
requires=[
|
||||
"gui",
|
||||
],
|
||||
provides=[
|
||||
"ccid_test",
|
||||
],
|
||||
stack_size=1 * 1024,
|
||||
order=120,
|
||||
fap_category="Debug",
|
||||
)
|
||||
@@ -1,150 +0,0 @@
|
||||
#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/iso7816_handler.h"
|
||||
#include "iso7816/iso7816_t0_apdu.h"
|
||||
#include "iso7816/iso7816_atr.h"
|
||||
#include "iso7816/iso7816_response.h"
|
||||
|
||||
#include "ccid_test_app_commands.h"
|
||||
|
||||
typedef enum {
|
||||
EventTypeInput,
|
||||
} EventType;
|
||||
|
||||
typedef struct {
|
||||
Gui* gui;
|
||||
ViewPort* view_port;
|
||||
FuriMessageQueue* event_queue;
|
||||
FuriHalUsbCcidConfig ccid_cfg;
|
||||
Iso7816Handler* iso7816_handler;
|
||||
} CcidTestApp;
|
||||
|
||||
typedef struct {
|
||||
union {
|
||||
InputEvent input;
|
||||
};
|
||||
EventType type;
|
||||
} CcidTestAppEvent;
|
||||
|
||||
typedef enum {
|
||||
CcidTestSubmenuIndexInsertSmartcard,
|
||||
CcidTestSubmenuIndexRemoveSmartcard,
|
||||
CcidTestSubmenuIndexInsertSmartcardReader
|
||||
} SubmenuIndex;
|
||||
|
||||
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(void) {
|
||||
CcidTestApp* app = malloc(sizeof(CcidTestApp));
|
||||
|
||||
//setup CCID USB
|
||||
// On linux: set VID PID using: /usr/lib/pcsc/drivers/ifd-ccid.bundle/Contents/Info.plist
|
||||
app->ccid_cfg.vid = 0x076B;
|
||||
app->ccid_cfg.pid = 0x3A21;
|
||||
|
||||
app->iso7816_handler = iso7816_handler_alloc();
|
||||
app->iso7816_handler->iso7816_answer_to_reset = iso7816_answer_to_reset;
|
||||
app->iso7816_handler->iso7816_process_command = iso7816_process_command;
|
||||
|
||||
// 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));
|
||||
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;
|
||||
|
||||
iso7816_handler_free(app->iso7816_handler);
|
||||
|
||||
// Free rest
|
||||
free(app);
|
||||
}
|
||||
|
||||
int32_t ccid_test_app(void* p) {
|
||||
UNUSED(p);
|
||||
|
||||
//setup view
|
||||
CcidTestApp* app = ccid_test_app_alloc();
|
||||
|
||||
FuriHalUsbInterface* usb_mode_prev = furi_hal_usb_get_config();
|
||||
furi_hal_usb_unlock();
|
||||
|
||||
furi_check(furi_hal_usb_set_config(&usb_ccid, &app->ccid_cfg) == true);
|
||||
iso7816_handler_set_usb_ccid_callbacks();
|
||||
furi_hal_usb_ccid_insert_smartcard();
|
||||
|
||||
//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
|
||||
iso7816_handler_reset_usb_ccid_callbacks();
|
||||
furi_hal_usb_set_config(usb_mode_prev, NULL);
|
||||
|
||||
//teardown view
|
||||
ccid_test_app_free(app);
|
||||
return 0;
|
||||
}
|
||||
@@ -1,123 +0,0 @@
|
||||
#include "iso7816/iso7816_t0_apdu.h"
|
||||
#include "iso7816/iso7816_response.h"
|
||||
|
||||
//Instruction 1: returns an OK response unconditionally
|
||||
//APDU example: 0x01:0x01:0x00:0x00
|
||||
//response: SW1=0x90, SW2=0x00
|
||||
void handle_instruction_01(ISO7816_Response_APDU* response_apdu) {
|
||||
response_apdu->DataLen = 0;
|
||||
iso7816_set_response(response_apdu, ISO7816_RESPONSE_OK);
|
||||
}
|
||||
|
||||
//Instruction 2: expect command with no body, replies wit with a body with two bytes
|
||||
//APDU example: 0x01:0x02:0x00:0x00:0x02
|
||||
//response: 'bc' (0x62, 0x63) SW1=0x90, SW2=0x00
|
||||
void handle_instruction_02(
|
||||
uint8_t p1,
|
||||
uint8_t p2,
|
||||
uint16_t lc,
|
||||
uint16_t le,
|
||||
ISO7816_Response_APDU* response_apdu) {
|
||||
if(p1 == 0 && p2 == 0 && lc == 0 && le >= 2) {
|
||||
response_apdu->Data[0] = 0x62;
|
||||
response_apdu->Data[1] = 0x63;
|
||||
|
||||
response_apdu->DataLen = 2;
|
||||
|
||||
iso7816_set_response(response_apdu, ISO7816_RESPONSE_OK);
|
||||
} else if(p1 != 0 || p2 != 0) {
|
||||
iso7816_set_response(response_apdu, ISO7816_RESPONSE_WRONG_PARAMETERS_P1_P2);
|
||||
} else {
|
||||
iso7816_set_response(response_apdu, ISO7816_RESPONSE_WRONG_LENGTH);
|
||||
}
|
||||
}
|
||||
|
||||
//Instruction 3: sends a command with a body with two bytes, receives a response with no bytes
|
||||
//APDU example: 0x01:0x03:0x00:0x00:0x02:CA:FE
|
||||
//response SW1=0x90, SW2=0x00
|
||||
void handle_instruction_03(
|
||||
uint8_t p1,
|
||||
uint8_t p2,
|
||||
uint16_t lc,
|
||||
ISO7816_Response_APDU* response_apdu) {
|
||||
if(p1 == 0 && p2 == 0 && lc == 2) {
|
||||
response_apdu->DataLen = 0;
|
||||
iso7816_set_response(response_apdu, ISO7816_RESPONSE_OK);
|
||||
} else if(p1 != 0 || p2 != 0) {
|
||||
iso7816_set_response(response_apdu, ISO7816_RESPONSE_WRONG_PARAMETERS_P1_P2);
|
||||
} else {
|
||||
iso7816_set_response(response_apdu, ISO7816_RESPONSE_WRONG_LENGTH);
|
||||
}
|
||||
}
|
||||
|
||||
//instruction 4: sends a command with a body with 'n' bytes, receives a response with 'n' bytes
|
||||
//APDU example: 0x01:0x04:0x00:0x00:0x04:0x01:0x02:0x03:0x04:0x04
|
||||
//receives (0x01, 0x02, 0x03, 0x04) SW1=0x90, SW2=0x00
|
||||
void handle_instruction_04(
|
||||
uint8_t p1,
|
||||
uint8_t p2,
|
||||
uint16_t lc,
|
||||
uint16_t le,
|
||||
const uint8_t* command_apdu_data_buffer,
|
||||
ISO7816_Response_APDU* response_apdu) {
|
||||
if(p1 == 0 && p2 == 0 && lc > 0 && le > 0 && le >= lc) {
|
||||
for(uint16_t i = 0; i < lc; i++) {
|
||||
response_apdu->Data[i] = command_apdu_data_buffer[i];
|
||||
}
|
||||
|
||||
response_apdu->DataLen = lc;
|
||||
|
||||
iso7816_set_response(response_apdu, ISO7816_RESPONSE_OK);
|
||||
} else if(p1 != 0 || p2 != 0) {
|
||||
iso7816_set_response(response_apdu, ISO7816_RESPONSE_WRONG_PARAMETERS_P1_P2);
|
||||
} else {
|
||||
iso7816_set_response(response_apdu, ISO7816_RESPONSE_WRONG_LENGTH);
|
||||
}
|
||||
}
|
||||
|
||||
void iso7816_answer_to_reset(Iso7816Atr* atr) {
|
||||
//minimum valid ATR: https://smartcard-atr.apdu.fr/parse?ATR=3B+00
|
||||
atr->TS = 0x3B;
|
||||
atr->T0 = 0x00;
|
||||
}
|
||||
|
||||
void iso7816_process_command(
|
||||
const ISO7816_Command_APDU* command_apdu,
|
||||
ISO7816_Response_APDU* response_apdu) {
|
||||
//example 1: sends a command with no body, receives a response with no body
|
||||
//sends APDU 0x01:0x01:0x00:0x00
|
||||
//receives SW1=0x90, SW2=0x00
|
||||
|
||||
if(command_apdu->CLA == 0x01) {
|
||||
switch(command_apdu->INS) {
|
||||
case 0x01:
|
||||
handle_instruction_01(response_apdu);
|
||||
break;
|
||||
case 0x02:
|
||||
handle_instruction_02(
|
||||
command_apdu->P1,
|
||||
command_apdu->P2,
|
||||
command_apdu->Lc,
|
||||
command_apdu->Le,
|
||||
response_apdu);
|
||||
break;
|
||||
case 0x03:
|
||||
handle_instruction_03(
|
||||
command_apdu->P1, command_apdu->P2, command_apdu->Lc, response_apdu);
|
||||
break;
|
||||
case 0x04:
|
||||
handle_instruction_04(
|
||||
command_apdu->P1,
|
||||
command_apdu->P2,
|
||||
command_apdu->Lc,
|
||||
command_apdu->Le,
|
||||
command_apdu->Data,
|
||||
response_apdu);
|
||||
break;
|
||||
default:
|
||||
iso7816_set_response(response_apdu, ISO7816_RESPONSE_INSTRUCTION_NOT_SUPPORTED);
|
||||
}
|
||||
} else {
|
||||
iso7816_set_response(response_apdu, ISO7816_RESPONSE_CLASS_NOT_SUPPORTED);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
#include "iso7816/iso7816_t0_apdu.h"
|
||||
|
||||
void iso7816_answer_to_reset(Iso7816Atr* atr);
|
||||
|
||||
void iso7816_process_command(
|
||||
const ISO7816_Command_APDU* command_apdu,
|
||||
ISO7816_Response_APDU* response_apdu);
|
||||
@@ -1,119 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# pylint: disable=missing-module-docstring, too-many-arguments, consider-using-f-string, missing-function-docstring
|
||||
from smartcard.System import readers
|
||||
|
||||
|
||||
def test_apdu(connection, test_name, apdu, expected_sw1, expected_sw2, expected_data):
|
||||
print("Running test: [%s]" % test_name)
|
||||
data, sw1, sw2 = connection.transmit(apdu)
|
||||
|
||||
failed = []
|
||||
|
||||
if sw1 != expected_sw1:
|
||||
failed.append("SW1: Expected %x, actual %x" % (expected_sw1, sw1))
|
||||
|
||||
if sw2 != expected_sw2:
|
||||
failed.append("SW2: Expected %x, actual %x" % (expected_sw2, sw2))
|
||||
|
||||
if len(data) != len(expected_data):
|
||||
failed.append(
|
||||
"Data: Sizes differ: Expected %x, actual %x"
|
||||
% (len(expected_data), len(data))
|
||||
)
|
||||
print(data)
|
||||
elif len(data) > 0:
|
||||
data_matches = True
|
||||
for i, _ in enumerate(data):
|
||||
if data[i] != expected_data[i]:
|
||||
data_matches = False
|
||||
|
||||
if not data_matches:
|
||||
failed.append("Data: Expected %s, actual %s" % (expected_data, data))
|
||||
|
||||
if len(failed) > 0:
|
||||
print("Test failed: ")
|
||||
for failure in failed:
|
||||
print("- %s" % failure)
|
||||
else:
|
||||
print("Test passed!")
|
||||
|
||||
|
||||
def main():
|
||||
r = readers()
|
||||
print("Found following smartcard readers: ")
|
||||
|
||||
for i, sc in enumerate(r):
|
||||
print("[%d] %s" % (i, sc))
|
||||
|
||||
print("Select the smartcard reader you want to run tests against:")
|
||||
|
||||
reader_index = int(input())
|
||||
|
||||
if reader_index < len(r):
|
||||
connection = r[reader_index].createConnection()
|
||||
|
||||
connection.connect()
|
||||
|
||||
test_apdu(
|
||||
connection,
|
||||
"INS 0x01: No Lc, no Data, No Le. Expect no data in return",
|
||||
[0x01, 0x01, 0x00, 0x00],
|
||||
0x90,
|
||||
0x00,
|
||||
[],
|
||||
)
|
||||
|
||||
test_apdu(
|
||||
connection,
|
||||
"INS 0x02: No Lc, no Data, Le=2. Expect 2 byte data in return",
|
||||
[0x01, 0x02, 0x00, 0x00, 0x02],
|
||||
0x90,
|
||||
0x00,
|
||||
[0x62, 0x63],
|
||||
)
|
||||
|
||||
test_apdu(
|
||||
connection,
|
||||
"INS 0x03: Lc=2, data=[0xCA, 0xFE], No Le. Expect no data in return",
|
||||
[0x01, 0x03, 0x00, 0x00, 0x02, 0xCA, 0xFE],
|
||||
0x90,
|
||||
0x00,
|
||||
[],
|
||||
)
|
||||
|
||||
test_apdu(
|
||||
connection,
|
||||
"INS 0x04: Lc=2, data=[0xCA, 0xFE], Le=2. Expect 1 byte data in return",
|
||||
[0x01, 0x04, 0x00, 0x00, 0x02, 0xCA, 0xFE, 0x02],
|
||||
0x90,
|
||||
0x00,
|
||||
[0xCA, 0xFE],
|
||||
)
|
||||
|
||||
small_apdu = list(range(0, 0x0F))
|
||||
|
||||
test_apdu(
|
||||
connection,
|
||||
"INS 0x04: Lc=0x0F, data=small_apdu, Le=0x0F. Expect 14 bytes data in return",
|
||||
[0x01, 0x04, 0x00, 0x00, 0x0F] + small_apdu + [0x0F],
|
||||
0x90,
|
||||
0x00,
|
||||
small_apdu,
|
||||
)
|
||||
|
||||
upper_bound = 0xF0
|
||||
max_apdu = list(range(0, upper_bound))
|
||||
|
||||
test_apdu(
|
||||
connection,
|
||||
"INS 0x04: Lc=0x%x, data=max_apdu, Le=0x%x. Expect 0x%x bytes data in return"
|
||||
% (upper_bound, upper_bound, upper_bound),
|
||||
[0x01, 0x04, 0x00, 0x00, upper_bound] + max_apdu + [upper_bound],
|
||||
0x90,
|
||||
0x00,
|
||||
max_apdu,
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -1,2 +0,0 @@
|
||||
pyscard
|
||||
# or sudo apt install python3-pyscard
|
||||
@@ -1,6 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
typedef struct {
|
||||
uint8_t TS;
|
||||
uint8_t T0;
|
||||
} Iso7816Atr;
|
||||
@@ -1,96 +0,0 @@
|
||||
// transforms low level calls such as XFRCallback or ICC Power on to a structured one
|
||||
// an application can register these calls and listen for the callbacks defined in Iso7816Callbacks
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <furi.h>
|
||||
#include <furi_hal.h>
|
||||
|
||||
#include "iso7816_handler.h"
|
||||
|
||||
#include "iso7816_t0_apdu.h"
|
||||
#include "iso7816_atr.h"
|
||||
#include "iso7816_response.h"
|
||||
|
||||
static Iso7816Handler* iso7816_handler;
|
||||
static CcidCallbacks* ccid_callbacks;
|
||||
static uint8_t* command_apdu_buffer;
|
||||
static uint8_t* response_apdu_buffer;
|
||||
|
||||
void iso7816_icc_power_on_callback(uint8_t* atr_data, uint32_t* atr_data_len, void* context) {
|
||||
furi_check(context);
|
||||
|
||||
Iso7816Handler* handler = (Iso7816Handler*)context;
|
||||
|
||||
Iso7816Atr iso7816_atr;
|
||||
handler->iso7816_answer_to_reset(&iso7816_atr);
|
||||
|
||||
furi_assert(iso7816_atr.T0 == 0x00);
|
||||
|
||||
uint8_t atr_buffer[2] = {iso7816_atr.TS, iso7816_atr.T0};
|
||||
|
||||
*atr_data_len = 2;
|
||||
|
||||
memcpy(atr_data, atr_buffer, sizeof(uint8_t) * (*atr_data_len));
|
||||
}
|
||||
|
||||
//dataBlock points to the buffer
|
||||
//dataBlockLen tells reader how nany bytes should be read
|
||||
void iso7816_xfr_datablock_callback(
|
||||
const uint8_t* pc_to_reader_datablock,
|
||||
uint32_t pc_to_reader_datablock_len,
|
||||
uint8_t* reader_to_pc_datablock,
|
||||
uint32_t* reader_to_pc_datablock_len,
|
||||
void* context) {
|
||||
furi_check(context);
|
||||
|
||||
Iso7816Handler* handler = (Iso7816Handler*)context;
|
||||
|
||||
ISO7816_Response_APDU* response_apdu = (ISO7816_Response_APDU*)response_apdu_buffer;
|
||||
ISO7816_Command_APDU* command_apdu = (ISO7816_Command_APDU*)command_apdu_buffer;
|
||||
|
||||
uint8_t result = iso7816_read_command_apdu(
|
||||
command_apdu, pc_to_reader_datablock, pc_to_reader_datablock_len, CCID_SHORT_APDU_SIZE);
|
||||
|
||||
if(result == ISO7816_READ_COMMAND_APDU_OK) {
|
||||
handler->iso7816_process_command(command_apdu, response_apdu);
|
||||
|
||||
furi_assert(response_apdu->DataLen < CCID_SHORT_APDU_SIZE);
|
||||
} else if(result == ISO7816_READ_COMMAND_APDU_ERROR_WRONG_LE) {
|
||||
iso7816_set_response(response_apdu, ISO7816_RESPONSE_WRONG_LE);
|
||||
} else if(result == ISO7816_READ_COMMAND_APDU_ERROR_WRONG_LENGTH) {
|
||||
iso7816_set_response(response_apdu, ISO7816_RESPONSE_WRONG_LENGTH);
|
||||
}
|
||||
|
||||
iso7816_write_response_apdu(response_apdu, reader_to_pc_datablock, reader_to_pc_datablock_len);
|
||||
}
|
||||
|
||||
Iso7816Handler* iso7816_handler_alloc() {
|
||||
iso7816_handler = malloc(sizeof(Iso7816Handler));
|
||||
|
||||
command_apdu_buffer = malloc(sizeof(ISO7816_Command_APDU) + CCID_SHORT_APDU_SIZE);
|
||||
response_apdu_buffer = malloc(sizeof(ISO7816_Response_APDU) + CCID_SHORT_APDU_SIZE);
|
||||
|
||||
ccid_callbacks = malloc(sizeof(CcidCallbacks));
|
||||
ccid_callbacks->icc_power_on_callback = iso7816_icc_power_on_callback;
|
||||
ccid_callbacks->xfr_datablock_callback = iso7816_xfr_datablock_callback;
|
||||
|
||||
return iso7816_handler;
|
||||
}
|
||||
|
||||
void iso7816_handler_set_usb_ccid_callbacks() {
|
||||
furi_hal_usb_ccid_set_callbacks(ccid_callbacks, iso7816_handler);
|
||||
}
|
||||
|
||||
void iso7816_handler_reset_usb_ccid_callbacks() {
|
||||
furi_hal_usb_ccid_set_callbacks(NULL, NULL);
|
||||
}
|
||||
|
||||
void iso7816_handler_free(Iso7816Handler* handler) {
|
||||
free(ccid_callbacks);
|
||||
|
||||
free(command_apdu_buffer);
|
||||
free(response_apdu_buffer);
|
||||
|
||||
free(handler);
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include "iso7816_atr.h"
|
||||
#include "iso7816_t0_apdu.h"
|
||||
|
||||
typedef struct {
|
||||
void (*iso7816_answer_to_reset)(Iso7816Atr* atr);
|
||||
void (*iso7816_process_command)(
|
||||
const ISO7816_Command_APDU* command,
|
||||
ISO7816_Response_APDU* response);
|
||||
} Iso7816Handler;
|
||||
|
||||
Iso7816Handler* iso7816_handler_alloc();
|
||||
|
||||
void iso7816_handler_free(Iso7816Handler* handler);
|
||||
void iso7816_handler_set_usb_ccid_callbacks();
|
||||
void iso7816_handler_reset_usb_ccid_callbacks();
|
||||
@@ -1,8 +0,0 @@
|
||||
#include <stdint.h>
|
||||
#include "iso7816_t0_apdu.h"
|
||||
#include "iso7816_response.h"
|
||||
|
||||
void iso7816_set_response(ISO7816_Response_APDU* responseAPDU, uint16_t responseCode) {
|
||||
responseAPDU->SW1 = (responseCode >> (8 * 1)) & 0xff;
|
||||
responseAPDU->SW2 = (responseCode >> (8 * 0)) & 0xff;
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#define ISO7816_RESPONSE_OK 0x9000
|
||||
|
||||
#define ISO7816_RESPONSE_WRONG_LENGTH 0x6700
|
||||
#define ISO7816_RESPONSE_WRONG_PARAMETERS_P1_P2 0x6A00
|
||||
#define ISO7816_RESPONSE_WRONG_LE 0x6C00
|
||||
#define ISO7816_RESPONSE_INSTRUCTION_NOT_SUPPORTED 0x6D00
|
||||
#define ISO7816_RESPONSE_CLASS_NOT_SUPPORTED 0x6E00
|
||||
#define ISO7816_RESPONSE_INTERNAL_EXCEPTION 0x6F00
|
||||
|
||||
void iso7816_set_response(ISO7816_Response_APDU* responseAPDU, uint16_t responseCode);
|
||||
@@ -1,84 +0,0 @@
|
||||
/* Implements rudimentary iso7816-3 support for APDU (T=0) */
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include "iso7816_t0_apdu.h"
|
||||
|
||||
//reads pc_to_reader_datablock_len with pc_to_reader_datablock_len size, translate it into a ISO7816_Command_APDU type
|
||||
//extra data will be pointed to commandDataBuffer
|
||||
uint8_t iso7816_read_command_apdu(
|
||||
ISO7816_Command_APDU* command,
|
||||
const uint8_t* pc_to_reader_datablock,
|
||||
uint32_t pc_to_reader_datablock_len,
|
||||
uint32_t max_apdu_size) {
|
||||
command->CLA = pc_to_reader_datablock[0];
|
||||
command->INS = pc_to_reader_datablock[1];
|
||||
command->P1 = pc_to_reader_datablock[2];
|
||||
command->P2 = pc_to_reader_datablock[3];
|
||||
|
||||
if(pc_to_reader_datablock_len == 4) {
|
||||
command->Lc = 0;
|
||||
command->Le = 0;
|
||||
command->LePresent = false;
|
||||
|
||||
return ISO7816_READ_COMMAND_APDU_OK;
|
||||
} else if(pc_to_reader_datablock_len == 5) {
|
||||
//short le
|
||||
|
||||
command->Lc = 0;
|
||||
command->Le = pc_to_reader_datablock[4];
|
||||
command->LePresent = true;
|
||||
|
||||
return ISO7816_READ_COMMAND_APDU_OK;
|
||||
} else if(pc_to_reader_datablock_len > 5 && pc_to_reader_datablock[4] != 0x00) {
|
||||
//short lc
|
||||
|
||||
command->Lc = pc_to_reader_datablock[4];
|
||||
if(command->Lc > 0 && command->Lc < max_apdu_size) { //-V560
|
||||
memcpy(command->Data, &pc_to_reader_datablock[5], command->Lc);
|
||||
|
||||
//does it have a short le too?
|
||||
if(pc_to_reader_datablock_len == (uint32_t)(command->Lc + 5)) {
|
||||
command->Le = 0;
|
||||
command->LePresent = false;
|
||||
return ISO7816_READ_COMMAND_APDU_OK;
|
||||
} else if(pc_to_reader_datablock_len == (uint32_t)(command->Lc + 6)) {
|
||||
command->Le = pc_to_reader_datablock[pc_to_reader_datablock_len - 1];
|
||||
command->LePresent = true;
|
||||
|
||||
return ISO7816_READ_COMMAND_APDU_OK;
|
||||
} else {
|
||||
return ISO7816_READ_COMMAND_APDU_ERROR_WRONG_LENGTH;
|
||||
}
|
||||
} else {
|
||||
return ISO7816_READ_COMMAND_APDU_ERROR_WRONG_LENGTH;
|
||||
}
|
||||
} else {
|
||||
return ISO7816_READ_COMMAND_APDU_ERROR_WRONG_LENGTH;
|
||||
}
|
||||
}
|
||||
|
||||
//data buffer contains the whole APU response (response + trailer (SW1+SW2))
|
||||
void iso7816_write_response_apdu(
|
||||
const ISO7816_Response_APDU* response,
|
||||
uint8_t* reader_to_pc_datablock,
|
||||
uint32_t* reader_to_pc_datablock_len) {
|
||||
uint32_t responseDataBufferIndex = 0;
|
||||
|
||||
//response body
|
||||
if(response->DataLen > 0) {
|
||||
while(responseDataBufferIndex < response->DataLen) {
|
||||
reader_to_pc_datablock[responseDataBufferIndex] =
|
||||
response->Data[responseDataBufferIndex];
|
||||
responseDataBufferIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
//trailer
|
||||
reader_to_pc_datablock[responseDataBufferIndex] = response->SW1;
|
||||
responseDataBufferIndex++;
|
||||
|
||||
reader_to_pc_datablock[responseDataBufferIndex] = response->SW2;
|
||||
responseDataBufferIndex++;
|
||||
|
||||
*reader_to_pc_datablock_len = responseDataBufferIndex;
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include "iso7816_atr.h"
|
||||
#include "core/common_defines.h"
|
||||
|
||||
#define ISO7816_READ_COMMAND_APDU_OK 0
|
||||
#define ISO7816_READ_COMMAND_APDU_ERROR_WRONG_LE 1
|
||||
#define ISO7816_READ_COMMAND_APDU_ERROR_WRONG_LENGTH 2
|
||||
|
||||
typedef struct {
|
||||
//header
|
||||
uint8_t CLA;
|
||||
uint8_t INS;
|
||||
uint8_t P1;
|
||||
uint8_t P2;
|
||||
|
||||
//body
|
||||
uint16_t Lc; //data length
|
||||
uint16_t Le; //maximum response data length expected by client
|
||||
|
||||
//Le can have value of 0x00, which actually meand 0x100 = 256
|
||||
bool LePresent;
|
||||
uint8_t Data[0];
|
||||
} FURI_PACKED ISO7816_Command_APDU;
|
||||
|
||||
typedef struct {
|
||||
uint8_t SW1;
|
||||
uint8_t SW2;
|
||||
uint16_t DataLen;
|
||||
uint8_t Data[0];
|
||||
} FURI_PACKED ISO7816_Response_APDU;
|
||||
|
||||
uint8_t iso7816_read_command_apdu(
|
||||
ISO7816_Command_APDU* command,
|
||||
const uint8_t* pc_to_reader_datablock,
|
||||
uint32_t pc_to_reader_datablock_len,
|
||||
uint32_t max_apdu_size);
|
||||
void iso7816_write_response_apdu(
|
||||
const ISO7816_Response_APDU* response,
|
||||
uint8_t* reader_to_pc_datablock,
|
||||
uint32_t* reader_to_pc_datablock_len);
|
||||
@@ -1,9 +0,0 @@
|
||||
App(
|
||||
appid="crash_test",
|
||||
name="Crash Test",
|
||||
apptype=FlipperAppType.DEBUG,
|
||||
entry_point="crash_test_app",
|
||||
requires=["gui"],
|
||||
stack_size=1 * 1024,
|
||||
fap_category="Debug",
|
||||
)
|
||||
@@ -1,127 +0,0 @@
|
||||
#include <furi_hal.h>
|
||||
#include <furi.h>
|
||||
|
||||
#include <gui/gui.h>
|
||||
#include <gui/view_dispatcher.h>
|
||||
#include <gui/modules/submenu.h>
|
||||
|
||||
#define TAG "CrashTest"
|
||||
|
||||
typedef struct {
|
||||
Gui* gui;
|
||||
ViewDispatcher* view_dispatcher;
|
||||
Submenu* submenu;
|
||||
} CrashTest;
|
||||
|
||||
typedef enum {
|
||||
CrashTestViewSubmenu,
|
||||
} CrashTestView;
|
||||
|
||||
typedef enum {
|
||||
CrashTestSubmenuCheck,
|
||||
CrashTestSubmenuCheckMessage,
|
||||
CrashTestSubmenuAssert,
|
||||
CrashTestSubmenuAssertMessage,
|
||||
CrashTestSubmenuCrash,
|
||||
CrashTestSubmenuHalt,
|
||||
} CrashTestSubmenu;
|
||||
|
||||
static void crash_test_submenu_callback(void* context, uint32_t index) {
|
||||
CrashTest* instance = (CrashTest*)context;
|
||||
UNUSED(instance);
|
||||
|
||||
switch(index) {
|
||||
case CrashTestSubmenuCheck:
|
||||
furi_check(false);
|
||||
break;
|
||||
case CrashTestSubmenuCheckMessage:
|
||||
furi_check(false, "Crash test: furi_check with message");
|
||||
break;
|
||||
case CrashTestSubmenuAssert:
|
||||
furi_assert(false);
|
||||
break;
|
||||
case CrashTestSubmenuAssertMessage:
|
||||
furi_assert(false, "Crash test: furi_assert with message");
|
||||
break;
|
||||
case CrashTestSubmenuCrash:
|
||||
furi_crash("Crash test: furi_crash");
|
||||
break;
|
||||
case CrashTestSubmenuHalt:
|
||||
furi_halt("Crash test: furi_halt");
|
||||
break;
|
||||
default:
|
||||
furi_crash();
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t crash_test_exit_callback(void* context) {
|
||||
UNUSED(context);
|
||||
return VIEW_NONE;
|
||||
}
|
||||
|
||||
CrashTest* crash_test_alloc(void) {
|
||||
CrashTest* instance = malloc(sizeof(CrashTest));
|
||||
|
||||
View* view = NULL;
|
||||
|
||||
instance->gui = furi_record_open(RECORD_GUI);
|
||||
instance->view_dispatcher = view_dispatcher_alloc();
|
||||
view_dispatcher_attach_to_gui(
|
||||
instance->view_dispatcher, instance->gui, ViewDispatcherTypeFullscreen);
|
||||
|
||||
// Menu
|
||||
instance->submenu = submenu_alloc();
|
||||
view = submenu_get_view(instance->submenu);
|
||||
view_set_previous_callback(view, crash_test_exit_callback);
|
||||
view_dispatcher_add_view(instance->view_dispatcher, CrashTestViewSubmenu, view);
|
||||
submenu_add_item(
|
||||
instance->submenu, "Check", CrashTestSubmenuCheck, crash_test_submenu_callback, instance);
|
||||
submenu_add_item(
|
||||
instance->submenu,
|
||||
"Check with message",
|
||||
CrashTestSubmenuCheckMessage,
|
||||
crash_test_submenu_callback,
|
||||
instance);
|
||||
submenu_add_item(
|
||||
instance->submenu, "Assert", CrashTestSubmenuAssert, crash_test_submenu_callback, instance);
|
||||
submenu_add_item(
|
||||
instance->submenu,
|
||||
"Assert with message",
|
||||
CrashTestSubmenuAssertMessage,
|
||||
crash_test_submenu_callback,
|
||||
instance);
|
||||
submenu_add_item(
|
||||
instance->submenu, "Crash", CrashTestSubmenuCrash, crash_test_submenu_callback, instance);
|
||||
submenu_add_item(
|
||||
instance->submenu, "Halt", CrashTestSubmenuHalt, crash_test_submenu_callback, instance);
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
void crash_test_free(CrashTest* instance) {
|
||||
view_dispatcher_remove_view(instance->view_dispatcher, CrashTestViewSubmenu);
|
||||
submenu_free(instance->submenu);
|
||||
|
||||
view_dispatcher_free(instance->view_dispatcher);
|
||||
furi_record_close(RECORD_GUI);
|
||||
|
||||
free(instance);
|
||||
}
|
||||
|
||||
int32_t crash_test_run(CrashTest* instance) {
|
||||
view_dispatcher_switch_to_view(instance->view_dispatcher, CrashTestViewSubmenu);
|
||||
view_dispatcher_run(instance->view_dispatcher);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t crash_test_app(void* p) {
|
||||
UNUSED(p);
|
||||
|
||||
CrashTest* instance = crash_test_alloc();
|
||||
|
||||
int32_t ret = crash_test_run(instance);
|
||||
|
||||
crash_test_free(instance);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
#include <furi.h>
|
||||
#include <gui/gui.h>
|
||||
#include <gui/canvas_i.h>
|
||||
#include <input/input.h>
|
||||
|
||||
#define BUFFER_SIZE (32U)
|
||||
@@ -25,7 +26,7 @@ static void gui_input_events_callback(const void* value, void* ctx) {
|
||||
}
|
||||
}
|
||||
|
||||
static DirectDraw* direct_draw_alloc(void) {
|
||||
static DirectDraw* direct_draw_alloc() {
|
||||
DirectDraw* instance = malloc(sizeof(DirectDraw));
|
||||
|
||||
instance->input = furi_record_open(RECORD_INPUT_EVENTS);
|
||||
@@ -41,11 +42,10 @@ static DirectDraw* direct_draw_alloc(void) {
|
||||
static void direct_draw_free(DirectDraw* instance) {
|
||||
furi_pubsub_unsubscribe(instance->input, instance->input_subscription);
|
||||
|
||||
instance->canvas = NULL;
|
||||
gui_direct_draw_release(instance->gui);
|
||||
furi_record_close(RECORD_GUI);
|
||||
furi_record_close(RECORD_INPUT_EVENTS);
|
||||
|
||||
free(instance);
|
||||
}
|
||||
|
||||
static void direct_draw_block(Canvas* canvas, uint32_t size, uint32_t counter) {
|
||||
@@ -71,7 +71,7 @@ static void direct_draw_run(DirectDraw* instance) {
|
||||
size_t counter = 0;
|
||||
float fps = 0;
|
||||
|
||||
furi_thread_set_current_priority(FuriThreadPriorityIdle);
|
||||
vTaskPrioritySet(furi_thread_get_current_id(), FuriThreadPriorityIdle);
|
||||
|
||||
do {
|
||||
size_t elapsed = DWT->CYCCNT - start;
|
||||
|
||||
@@ -3,8 +3,9 @@ App(
|
||||
name="Display Test",
|
||||
apptype=FlipperAppType.DEBUG,
|
||||
entry_point="display_test_app",
|
||||
cdefines=["APP_DISPLAY_TEST"],
|
||||
requires=["gui"],
|
||||
fap_libs=["u8g2"],
|
||||
fap_libs=["misc"],
|
||||
stack_size=1 * 1024,
|
||||
order=120,
|
||||
fap_category="Debug",
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#include "display_test.h"
|
||||
|
||||
#include <furi_hal.h>
|
||||
#include <furi.h>
|
||||
|
||||
@@ -119,13 +121,14 @@ static void display_config_set_contrast(VariableItem* item) {
|
||||
display_test_reload_config(instance);
|
||||
}
|
||||
|
||||
DisplayTest* display_test_alloc(void) {
|
||||
DisplayTest* display_test_alloc() {
|
||||
DisplayTest* instance = malloc(sizeof(DisplayTest));
|
||||
|
||||
View* view = NULL;
|
||||
|
||||
instance->gui = furi_record_open(RECORD_GUI);
|
||||
instance->view_dispatcher = view_dispatcher_alloc();
|
||||
view_dispatcher_enable_queue(instance->view_dispatcher);
|
||||
view_dispatcher_attach_to_gui(
|
||||
instance->view_dispatcher, instance->gui, ViewDispatcherTypeFullscreen);
|
||||
|
||||
|
||||
@@ -150,10 +150,11 @@ static void view_display_test_exit(void* context) {
|
||||
|
||||
static void view_display_test_timer_callback(void* context) {
|
||||
ViewDisplayTest* instance = context;
|
||||
with_view_model(instance->view, ViewDisplayTestModel * model, { model->counter++; }, true);
|
||||
with_view_model(
|
||||
instance->view, ViewDisplayTestModel * model, { model->counter++; }, true);
|
||||
}
|
||||
|
||||
ViewDisplayTest* view_display_test_alloc(void) {
|
||||
ViewDisplayTest* view_display_test_alloc() {
|
||||
ViewDisplayTest* instance = malloc(sizeof(ViewDisplayTest));
|
||||
|
||||
instance->view = view_alloc();
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
typedef struct ViewDisplayTest ViewDisplayTest;
|
||||
|
||||
ViewDisplayTest* view_display_test_alloc(void);
|
||||
ViewDisplayTest* view_display_test_alloc();
|
||||
|
||||
void view_display_test_free(ViewDisplayTest* instance);
|
||||
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
App(
|
||||
appid="event_loop_blink_test",
|
||||
name="Event Loop Blink Test",
|
||||
apptype=FlipperAppType.DEBUG,
|
||||
entry_point="event_loop_blink_test_app",
|
||||
requires=["input"],
|
||||
stack_size=1 * 1024,
|
||||
order=20,
|
||||
fap_category="Debug",
|
||||
)
|
||||
@@ -1,168 +0,0 @@
|
||||
#include <furi.h>
|
||||
#include <furi_hal_resources.h>
|
||||
|
||||
#include <gui/gui.h>
|
||||
#include <gui/elements.h>
|
||||
#include <gui/view_port.h>
|
||||
|
||||
#include <input/input.h>
|
||||
|
||||
#define TAG "EventLoopBlinkTest"
|
||||
|
||||
#define TIMER_COUNT (6U)
|
||||
|
||||
typedef struct {
|
||||
FuriEventLoop* event_loop;
|
||||
FuriMessageQueue* input_queue;
|
||||
FuriEventLoopTimer* timers[TIMER_COUNT];
|
||||
} EventLoopBlinkTestApp;
|
||||
|
||||
static const GpioPin* blink_gpio_pins[] = {
|
||||
&gpio_ext_pa7,
|
||||
&gpio_ext_pa6,
|
||||
&gpio_ext_pa4,
|
||||
&gpio_ext_pb3,
|
||||
&gpio_ext_pb2,
|
||||
&gpio_ext_pc3,
|
||||
};
|
||||
|
||||
static_assert(COUNT_OF(blink_gpio_pins) == TIMER_COUNT);
|
||||
|
||||
static const uint32_t timer_intervals[] = {
|
||||
25,
|
||||
50,
|
||||
100,
|
||||
200,
|
||||
400,
|
||||
800,
|
||||
};
|
||||
|
||||
static_assert(COUNT_OF(timer_intervals) == TIMER_COUNT);
|
||||
|
||||
static void blink_gpio_init(void) {
|
||||
for(size_t i = 0; i < TIMER_COUNT; ++i) {
|
||||
furi_hal_gpio_init_simple(blink_gpio_pins[i], GpioModeOutputPushPull);
|
||||
furi_hal_gpio_write(blink_gpio_pins[i], false);
|
||||
}
|
||||
|
||||
furi_hal_gpio_init_simple(&gpio_ext_pc0, GpioModeOutputPushPull);
|
||||
furi_hal_gpio_write(&gpio_ext_pc0, false);
|
||||
}
|
||||
|
||||
static void blink_gpio_deinit(void) {
|
||||
for(size_t i = 0; i < TIMER_COUNT; ++i) {
|
||||
furi_hal_gpio_write(blink_gpio_pins[i], false);
|
||||
furi_hal_gpio_init_simple(blink_gpio_pins[i], GpioModeAnalog);
|
||||
}
|
||||
|
||||
furi_hal_gpio_write(&gpio_ext_pc0, false);
|
||||
furi_hal_gpio_init_simple(&gpio_ext_pc0, GpioModeAnalog);
|
||||
}
|
||||
|
||||
static void view_port_draw_callback(Canvas* canvas, void* context) {
|
||||
UNUSED(context);
|
||||
canvas_clear(canvas);
|
||||
elements_text_box(
|
||||
canvas,
|
||||
0,
|
||||
0,
|
||||
canvas_width(canvas),
|
||||
canvas_height(canvas),
|
||||
AlignCenter,
|
||||
AlignCenter,
|
||||
"\e#Event Loop Timers Test\e#\n"
|
||||
"Press buttons\n"
|
||||
"to enable or disable timers\n"
|
||||
"\e#Exit\e# = long press \e#Back\e#",
|
||||
false);
|
||||
}
|
||||
|
||||
static void view_port_input_callback(InputEvent* input_event, void* context) {
|
||||
EventLoopBlinkTestApp* app = context;
|
||||
furi_message_queue_put(app->input_queue, input_event, 0);
|
||||
}
|
||||
|
||||
static void input_queue_callback(FuriEventLoopObject* object, void* context) {
|
||||
FuriMessageQueue* queue = object;
|
||||
EventLoopBlinkTestApp* app = context;
|
||||
|
||||
InputEvent event;
|
||||
FuriStatus status = furi_message_queue_get(queue, &event, 0);
|
||||
furi_assert(status == FuriStatusOk);
|
||||
|
||||
if(event.type == InputTypeShort) {
|
||||
const size_t timer_idx = event.key;
|
||||
furi_assert(timer_idx < TIMER_COUNT);
|
||||
|
||||
FuriEventLoopTimer* timer = app->timers[timer_idx];
|
||||
|
||||
if(furi_event_loop_timer_is_running(timer)) {
|
||||
furi_event_loop_timer_stop(timer);
|
||||
} else {
|
||||
furi_event_loop_timer_restart(timer);
|
||||
}
|
||||
|
||||
} else if(event.type == InputTypeLong) {
|
||||
if(event.key == InputKeyBack) {
|
||||
furi_event_loop_stop(app->event_loop);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void blink_timer_callback(void* context) {
|
||||
const GpioPin* gpio = blink_gpio_pins[(size_t)context];
|
||||
furi_hal_gpio_write(gpio, !furi_hal_gpio_read(gpio));
|
||||
}
|
||||
|
||||
static void event_loop_tick_callback(void* context) {
|
||||
UNUSED(context);
|
||||
furi_hal_gpio_write(&gpio_ext_pc0, !furi_hal_gpio_read(&gpio_ext_pc0));
|
||||
}
|
||||
|
||||
int32_t event_loop_blink_test_app(void* arg) {
|
||||
UNUSED(arg);
|
||||
|
||||
blink_gpio_init();
|
||||
|
||||
EventLoopBlinkTestApp app;
|
||||
|
||||
app.event_loop = furi_event_loop_alloc();
|
||||
app.input_queue = furi_message_queue_alloc(3, sizeof(InputEvent));
|
||||
|
||||
for(size_t i = 0; i < TIMER_COUNT; ++i) {
|
||||
app.timers[i] = furi_event_loop_timer_alloc(
|
||||
app.event_loop, blink_timer_callback, FuriEventLoopTimerTypePeriodic, (void*)i);
|
||||
furi_event_loop_timer_start(app.timers[i], timer_intervals[i]);
|
||||
}
|
||||
|
||||
ViewPort* view_port = view_port_alloc();
|
||||
view_port_draw_callback_set(view_port, view_port_draw_callback, &app);
|
||||
view_port_input_callback_set(view_port, view_port_input_callback, &app);
|
||||
|
||||
Gui* gui = furi_record_open(RECORD_GUI);
|
||||
gui_add_view_port(gui, view_port, GuiLayerFullscreen);
|
||||
|
||||
furi_event_loop_tick_set(app.event_loop, 500, event_loop_tick_callback, &app);
|
||||
furi_event_loop_subscribe_message_queue(
|
||||
app.event_loop, app.input_queue, FuriEventLoopEventIn, input_queue_callback, &app);
|
||||
|
||||
furi_event_loop_run(app.event_loop);
|
||||
|
||||
gui_remove_view_port(gui, view_port);
|
||||
view_port_free(view_port);
|
||||
|
||||
furi_record_close(RECORD_GUI);
|
||||
|
||||
furi_event_loop_unsubscribe(app.event_loop, app.input_queue);
|
||||
furi_message_queue_free(app.input_queue);
|
||||
|
||||
for(size_t i = 0; i < TIMER_COUNT; ++i) {
|
||||
furi_event_loop_timer_free(app.timers[i]);
|
||||
}
|
||||
|
||||
furi_event_loop_free(app.event_loop);
|
||||
|
||||
blink_gpio_deinit();
|
||||
|
||||
return 0;
|
||||
}
|
||||
9
applications/debug/example_custom_font/application.fam
Normal file
9
applications/debug/example_custom_font/application.fam
Normal file
@@ -0,0 +1,9 @@
|
||||
App(
|
||||
appid="example_custom_font",
|
||||
name="Example: custom font",
|
||||
apptype=FlipperAppType.DEBUG,
|
||||
entry_point="example_custom_font_main",
|
||||
requires=["gui"],
|
||||
stack_size=1 * 1024,
|
||||
fap_category="Debug",
|
||||
)
|
||||
98
applications/debug/example_custom_font/example_custom_font.c
Normal file
98
applications/debug/example_custom_font/example_custom_font.c
Normal file
@@ -0,0 +1,98 @@
|
||||
#include <furi.h>
|
||||
#include <furi_hal.h>
|
||||
|
||||
#include <gui/gui.h>
|
||||
#include <input/input.h>
|
||||
|
||||
//This arrays contains the font itself. You can use any u8g2 font you want
|
||||
|
||||
/*
|
||||
Fontname: -Raccoon-Fixed4x6-Medium-R-Normal--6-60-75-75-P-40-ISO10646-1
|
||||
Copyright:
|
||||
Glyphs: 95/203
|
||||
BBX Build Mode: 0
|
||||
*/
|
||||
const uint8_t u8g2_font_tom_thumb_4x6_tr[725] =
|
||||
"_\0\2\2\2\3\3\4\4\3\6\0\377\5\377\5\0\0\352\1\330\2\270 \5\340\315\0!\6\265\310"
|
||||
"\254\0\42\6\213\313$\25#\10\227\310\244\241\206\12$\10\227\310\215\70b\2%\10\227\310d\324F\1"
|
||||
"&\10\227\310(\65R\22'\5\251\313\10(\6\266\310\251\62)\10\226\310\304\224\24\0*\6\217\312\244"
|
||||
"\16+\7\217\311\245\225\0,\6\212\310)\0-\5\207\312\14.\5\245\310\4/\7\227\310Ve\4\60"
|
||||
"\7\227\310-k\1\61\6\226\310\255\6\62\10\227\310h\220\312\1\63\11\227\310h\220\62X\0\64\10\227"
|
||||
"\310$\65b\1\65\10\227\310\214\250\301\2\66\10\227\310\315\221F\0\67\10\227\310\314TF\0\70\10\227"
|
||||
"\310\214\64\324\10\71\10\227\310\214\64\342\2:\6\255\311\244\0;\7\222\310e\240\0<\10\227\310\246\32"
|
||||
"d\20=\6\217\311l\60>\11\227\310d\220A*\1\77\10\227\310\314\224a\2@\10\227\310UC\3"
|
||||
"\1A\10\227\310UC\251\0B\10\227\310\250\264\322\2C\7\227\310\315\32\10D\10\227\310\250d-\0"
|
||||
"E\10\227\310\214\70\342\0F\10\227\310\214\70b\4G\10\227\310\315\221\222\0H\10\227\310$\65\224\12"
|
||||
"I\7\227\310\254X\15J\7\227\310\226\252\2K\10\227\310$\265\222\12L\7\227\310\304\346\0M\10\227"
|
||||
"\310\244\61\224\12N\10\227\310\244q\250\0O\7\227\310UV\5P\10\227\310\250\264b\4Q\10\227\310"
|
||||
"Uj$\1R\10\227\310\250\64V\1S\10\227\310m\220\301\2T\7\227\310\254\330\2U\7\227\310$"
|
||||
"W\22V\10\227\310$\253L\0W\10\227\310$\65\206\12X\10\227\310$\325R\1Y\10\227\310$U"
|
||||
"V\0Z\7\227\310\314T\16[\7\227\310\214X\16\134\10\217\311d\220A\0]\7\227\310\314r\4^"
|
||||
"\5\213\313\65_\5\207\310\14`\6\212\313\304\0a\7\223\310\310\65\2b\10\227\310D\225\324\2c\7"
|
||||
"\223\310\315\14\4d\10\227\310\246\245\222\0e\6\223\310\235\2f\10\227\310\246\264b\2g\10\227\307\35"
|
||||
"\61%\0h\10\227\310D\225\254\0i\6\265\310\244\1j\10\233\307f\30U\5k\10\227\310\304\264T"
|
||||
"\1l\7\227\310\310\326\0m\7\223\310<R\0n\7\223\310\250d\5o\7\223\310U\252\2p\10\227"
|
||||
"\307\250\244V\4q\10\227\307-\225d\0r\6\223\310\315\22s\10\223\310\215\70\22\0t\10\227\310\245"
|
||||
"\25\243\0u\7\223\310$+\11v\10\223\310$\65R\2w\7\223\310\244q\4x\7\223\310\244\62\25"
|
||||
"y\11\227\307$\225dJ\0z\7\223\310\254\221\6{\10\227\310\251\32D\1|\6\265\310(\1}\11"
|
||||
"\227\310\310\14RR\0~\6\213\313\215\4\0\0\0\4\377\377\0";
|
||||
|
||||
// Screen is 128x64 px
|
||||
static void app_draw_callback(Canvas* canvas, void* ctx) {
|
||||
UNUSED(ctx);
|
||||
|
||||
canvas_clear(canvas);
|
||||
|
||||
canvas_set_custom_u8g2_font(canvas, u8g2_font_tom_thumb_4x6_tr);
|
||||
|
||||
canvas_draw_str(canvas, 0, 6, "This is a tiny custom font");
|
||||
canvas_draw_str(canvas, 0, 12, "012345.?! ,:;\"\'@#$%");
|
||||
}
|
||||
|
||||
static void app_input_callback(InputEvent* input_event, void* ctx) {
|
||||
furi_assert(ctx);
|
||||
|
||||
FuriMessageQueue* event_queue = ctx;
|
||||
furi_message_queue_put(event_queue, input_event, FuriWaitForever);
|
||||
}
|
||||
|
||||
int32_t example_custom_font_main(void* p) {
|
||||
UNUSED(p);
|
||||
FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(InputEvent));
|
||||
|
||||
// Configure view port
|
||||
ViewPort* view_port = view_port_alloc();
|
||||
view_port_draw_callback_set(view_port, app_draw_callback, view_port);
|
||||
view_port_input_callback_set(view_port, app_input_callback, event_queue);
|
||||
|
||||
// Register view port in GUI
|
||||
Gui* gui = furi_record_open(RECORD_GUI);
|
||||
gui_add_view_port(gui, view_port, GuiLayerFullscreen);
|
||||
|
||||
InputEvent event;
|
||||
|
||||
bool running = true;
|
||||
|
||||
while(running) {
|
||||
if(furi_message_queue_get(event_queue, &event, 100) == FuriStatusOk) {
|
||||
if((event.type == InputTypePress) || (event.type == InputTypeRepeat)) {
|
||||
switch(event.key) {
|
||||
case InputKeyBack:
|
||||
running = false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
view_port_enabled_set(view_port, false);
|
||||
gui_remove_view_port(gui, view_port);
|
||||
view_port_free(view_port);
|
||||
furi_message_queue_free(event_queue);
|
||||
|
||||
furi_record_close(RECORD_GUI);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
App(
|
||||
appid="expansion_test",
|
||||
name="Expansion Module Test",
|
||||
apptype=FlipperAppType.DEBUG,
|
||||
entry_point="expansion_test_app",
|
||||
requires=["expansion_start"],
|
||||
fap_libs=["assets"],
|
||||
stack_size=1 * 1024,
|
||||
order=20,
|
||||
fap_category="Debug",
|
||||
fap_file_assets="assets",
|
||||
)
|
||||
@@ -1,9 +0,0 @@
|
||||
"Did you ever hear the tragedy of Darth Plagueis the Wise?"
|
||||
"No."
|
||||
"I thought not. It's not a story the Jedi would tell you. It's a Sith legend. Darth Plagueis... was a Dark Lord of the Sith so powerful and so wise, he could use the Force to influence the midi-chlorians... to create... life. He had such a knowledge of the dark side, he could even keep the ones he cared about... from dying."
|
||||
"He could actually... save people from death?"
|
||||
"The dark side of the Force is a pathway to many abilities... some consider to be unnatural."
|
||||
"Wh– What happened to him?"
|
||||
"He became so powerful, the only thing he was afraid of was... losing his power. Which eventually, of course, he did. Unfortunately, he taught his apprentice everything he knew. Then his apprentice killed him in his sleep. It's ironic. He could save others from death, but not himself."
|
||||
"Is it possible to learn this power?"
|
||||
"Not from a Jedi."
|
||||
@@ -1,508 +0,0 @@
|
||||
/**
|
||||
* @file expansion_test.c
|
||||
* @brief Expansion module support testing application.
|
||||
*
|
||||
* Before running, connect pins using the following scheme:
|
||||
* 13 -> 16 (USART TX to LPUART RX)
|
||||
* 14 -> 15 (USART RX to LPUART TX)
|
||||
*
|
||||
* Optional: Connect an LED with an appropriate series resistor
|
||||
* between pins 1 and 8. It will always be on if the device is
|
||||
* connected to USB power, so unplug it before running the app.
|
||||
*
|
||||
* What this application does:
|
||||
*
|
||||
* - Enables module support and emulates the module on a single device
|
||||
* (hence the above connection),
|
||||
* - Connects to the expansion module service, sets baud rate,
|
||||
* - Enables OTG (5V) on GPIO via plain expansion protocol,
|
||||
* - Waits 5 cycles of idle loop (1 second),
|
||||
* - Starts the RPC session,
|
||||
* - Disables OTG (5V) on GPIO via RPC messages,
|
||||
* - Waits 5 cycles of idle loop (1 second),
|
||||
* - Creates a directory at `/ext/ExpansionTest` and writes a file
|
||||
* named `test.txt` under it,
|
||||
* - Plays an audiovisual alert (sound and blinking display),
|
||||
* - Enables OTG (5V) on GPIO via RPC messages,
|
||||
* - Waits 5 cycles of idle loop (1 second),
|
||||
* - Stops the RPC session,
|
||||
* - Disables OTG (5V) on GPIO via plain expansion protocol,
|
||||
* - Exits (plays a sound if any of the above steps failed).
|
||||
*/
|
||||
#include <furi.h>
|
||||
|
||||
#include <furi_hal_resources.h>
|
||||
|
||||
#include <furi_hal_serial.h>
|
||||
#include <furi_hal_serial_control.h>
|
||||
|
||||
#include <pb.h>
|
||||
#include <pb_decode.h>
|
||||
#include <pb_encode.h>
|
||||
|
||||
#include <flipper.pb.h>
|
||||
|
||||
#include <storage/storage.h>
|
||||
#include <expansion/expansion.h>
|
||||
#include <notification/notification_messages.h>
|
||||
#include <expansion/expansion_protocol.h>
|
||||
|
||||
#define TAG "ExpansionTest"
|
||||
|
||||
#define TEST_DIR_PATH EXT_PATH(TAG)
|
||||
#define TEST_FILE_NAME "test.txt"
|
||||
#define TEST_FILE_PATH EXT_PATH(TAG "/" TEST_FILE_NAME)
|
||||
|
||||
#define HOST_SERIAL_ID (FuriHalSerialIdLpuart)
|
||||
#define MODULE_SERIAL_ID (FuriHalSerialIdUsart)
|
||||
|
||||
#define RECEIVE_BUFFER_SIZE (sizeof(ExpansionFrame) + sizeof(ExpansionFrameChecksum))
|
||||
|
||||
typedef enum {
|
||||
ExpansionTestAppFlagData = 1U << 0,
|
||||
ExpansionTestAppFlagExit = 1U << 1,
|
||||
} ExpansionTestAppFlag;
|
||||
|
||||
#define EXPANSION_TEST_APP_ALL_FLAGS (ExpansionTestAppFlagData | ExpansionTestAppFlagExit)
|
||||
|
||||
typedef struct {
|
||||
FuriThreadId thread_id;
|
||||
Expansion* expansion;
|
||||
FuriHalSerialHandle* handle;
|
||||
FuriStreamBuffer* buf;
|
||||
ExpansionFrame frame;
|
||||
PB_Main msg;
|
||||
Storage* storage;
|
||||
} ExpansionTestApp;
|
||||
|
||||
static void expansion_test_app_serial_rx_callback(
|
||||
FuriHalSerialHandle* handle,
|
||||
FuriHalSerialRxEvent event,
|
||||
void* context) {
|
||||
furi_assert(handle);
|
||||
furi_assert(context);
|
||||
ExpansionTestApp* app = context;
|
||||
|
||||
if(event == FuriHalSerialRxEventData) {
|
||||
const uint8_t data = furi_hal_serial_async_rx(handle);
|
||||
furi_stream_buffer_send(app->buf, &data, sizeof(data), 0);
|
||||
furi_thread_flags_set(app->thread_id, ExpansionTestAppFlagData);
|
||||
}
|
||||
}
|
||||
|
||||
static ExpansionTestApp* expansion_test_app_alloc(void) {
|
||||
ExpansionTestApp* instance = malloc(sizeof(ExpansionTestApp));
|
||||
instance->buf = furi_stream_buffer_alloc(RECEIVE_BUFFER_SIZE, 1);
|
||||
return instance;
|
||||
}
|
||||
|
||||
static void expansion_test_app_free(ExpansionTestApp* instance) {
|
||||
furi_stream_buffer_free(instance->buf);
|
||||
free(instance);
|
||||
}
|
||||
|
||||
static void expansion_test_app_start(ExpansionTestApp* instance) {
|
||||
instance->thread_id = furi_thread_get_current_id();
|
||||
instance->expansion = furi_record_open(RECORD_EXPANSION);
|
||||
instance->handle = furi_hal_serial_control_acquire(MODULE_SERIAL_ID);
|
||||
furi_check(instance->handle);
|
||||
// Configure the serial port
|
||||
furi_hal_serial_init(instance->handle, EXPANSION_PROTOCOL_DEFAULT_BAUD_RATE);
|
||||
// Start waiting for the initial pulse
|
||||
expansion_set_listen_serial(instance->expansion, HOST_SERIAL_ID);
|
||||
|
||||
furi_hal_serial_async_rx_start(
|
||||
instance->handle, expansion_test_app_serial_rx_callback, instance, false);
|
||||
}
|
||||
|
||||
static void expansion_test_app_stop(ExpansionTestApp* instance) {
|
||||
// Disable expansion module support
|
||||
expansion_disable(instance->expansion);
|
||||
// Give back the module handle
|
||||
furi_hal_serial_control_release(instance->handle);
|
||||
// Restore expansion user settings
|
||||
expansion_enable(instance->expansion);
|
||||
furi_record_close(RECORD_EXPANSION);
|
||||
}
|
||||
|
||||
static inline bool expansion_test_app_is_success_response(const ExpansionFrame* response) {
|
||||
return response->header.type == ExpansionFrameTypeStatus &&
|
||||
response->content.status.error == ExpansionFrameErrorNone;
|
||||
}
|
||||
|
||||
static inline bool expansion_test_app_is_success_rpc_message(const PB_Main* message) {
|
||||
return (message->command_status == PB_CommandStatus_OK ||
|
||||
message->command_status == PB_CommandStatus_ERROR_STORAGE_EXIST) &&
|
||||
(message->which_content == PB_Main_empty_tag);
|
||||
}
|
||||
|
||||
static size_t expansion_test_app_receive_callback(uint8_t* data, size_t data_size, void* context) {
|
||||
ExpansionTestApp* instance = context;
|
||||
|
||||
size_t received_size = 0;
|
||||
|
||||
while(true) {
|
||||
received_size += furi_stream_buffer_receive(
|
||||
instance->buf, data + received_size, data_size - received_size, 0);
|
||||
if(received_size == data_size) break;
|
||||
|
||||
const uint32_t flags = furi_thread_flags_wait(
|
||||
EXPANSION_TEST_APP_ALL_FLAGS, FuriFlagWaitAny, EXPANSION_PROTOCOL_TIMEOUT_MS);
|
||||
|
||||
// Exit on any error
|
||||
if(flags & FuriFlagError) break;
|
||||
}
|
||||
|
||||
return received_size;
|
||||
}
|
||||
|
||||
static size_t
|
||||
expansion_test_app_send_callback(const uint8_t* data, size_t data_size, void* context) {
|
||||
ExpansionTestApp* instance = context;
|
||||
|
||||
furi_hal_serial_tx(instance->handle, data, data_size);
|
||||
furi_hal_serial_tx_wait_complete(instance->handle);
|
||||
|
||||
return data_size;
|
||||
}
|
||||
|
||||
static bool expansion_test_app_receive_frame(ExpansionTestApp* instance, ExpansionFrame* frame) {
|
||||
return expansion_protocol_decode(frame, expansion_test_app_receive_callback, instance) ==
|
||||
ExpansionProtocolStatusOk;
|
||||
}
|
||||
|
||||
static bool
|
||||
expansion_test_app_send_status_response(ExpansionTestApp* instance, ExpansionFrameError error) {
|
||||
ExpansionFrame frame = {
|
||||
.header.type = ExpansionFrameTypeStatus,
|
||||
.content.status.error = error,
|
||||
};
|
||||
return expansion_protocol_encode(&frame, expansion_test_app_send_callback, instance) ==
|
||||
ExpansionProtocolStatusOk;
|
||||
}
|
||||
|
||||
static bool expansion_test_app_send_heartbeat(ExpansionTestApp* instance) {
|
||||
ExpansionFrame frame = {
|
||||
.header.type = ExpansionFrameTypeHeartbeat,
|
||||
.content.heartbeat = {},
|
||||
};
|
||||
return expansion_protocol_encode(&frame, expansion_test_app_send_callback, instance) ==
|
||||
ExpansionProtocolStatusOk;
|
||||
}
|
||||
|
||||
static bool
|
||||
expansion_test_app_send_baud_rate_request(ExpansionTestApp* instance, uint32_t baud_rate) {
|
||||
ExpansionFrame frame = {
|
||||
.header.type = ExpansionFrameTypeBaudRate,
|
||||
.content.baud_rate.baud = baud_rate,
|
||||
};
|
||||
return expansion_protocol_encode(&frame, expansion_test_app_send_callback, instance) ==
|
||||
ExpansionProtocolStatusOk;
|
||||
}
|
||||
|
||||
static bool expansion_test_app_send_control_request(
|
||||
ExpansionTestApp* instance,
|
||||
ExpansionFrameControlCommand command) {
|
||||
ExpansionFrame frame = {
|
||||
.header.type = ExpansionFrameTypeControl,
|
||||
.content.control.command = command,
|
||||
};
|
||||
return expansion_protocol_encode(&frame, expansion_test_app_send_callback, instance) ==
|
||||
ExpansionProtocolStatusOk;
|
||||
}
|
||||
|
||||
static bool expansion_test_app_send_data_request(
|
||||
ExpansionTestApp* instance,
|
||||
const uint8_t* data,
|
||||
size_t data_size) {
|
||||
furi_assert(data_size <= EXPANSION_PROTOCOL_MAX_DATA_SIZE);
|
||||
|
||||
ExpansionFrame frame = {
|
||||
.header.type = ExpansionFrameTypeData,
|
||||
.content.data.size = data_size,
|
||||
};
|
||||
|
||||
memcpy(frame.content.data.bytes, data, data_size);
|
||||
return expansion_protocol_encode(&frame, expansion_test_app_send_callback, instance) ==
|
||||
ExpansionProtocolStatusOk;
|
||||
}
|
||||
|
||||
static bool expansion_test_app_rpc_encode_callback(
|
||||
pb_ostream_t* stream,
|
||||
const pb_byte_t* data,
|
||||
size_t data_size) {
|
||||
ExpansionTestApp* instance = stream->state;
|
||||
|
||||
size_t size_sent = 0;
|
||||
|
||||
while(size_sent < data_size) {
|
||||
const size_t current_size = MIN(data_size - size_sent, EXPANSION_PROTOCOL_MAX_DATA_SIZE);
|
||||
if(!expansion_test_app_send_data_request(instance, data + size_sent, current_size)) break;
|
||||
if(!expansion_test_app_receive_frame(instance, &instance->frame)) break;
|
||||
if(!expansion_test_app_is_success_response(&instance->frame)) break;
|
||||
size_sent += current_size;
|
||||
}
|
||||
|
||||
return size_sent == data_size;
|
||||
}
|
||||
|
||||
static bool expansion_test_app_send_rpc_request(ExpansionTestApp* instance, PB_Main* message) {
|
||||
pb_ostream_t stream = {
|
||||
.callback = expansion_test_app_rpc_encode_callback,
|
||||
.state = instance,
|
||||
.max_size = SIZE_MAX,
|
||||
.bytes_written = 0,
|
||||
.errmsg = NULL,
|
||||
};
|
||||
|
||||
const bool success = pb_encode_ex(&stream, &PB_Main_msg, message, PB_ENCODE_DELIMITED);
|
||||
pb_release(&PB_Main_msg, message);
|
||||
return success;
|
||||
}
|
||||
|
||||
static bool expansion_test_app_receive_rpc_request(ExpansionTestApp* instance, PB_Main* message) {
|
||||
bool success = false;
|
||||
|
||||
do {
|
||||
if(!expansion_test_app_receive_frame(instance, &instance->frame)) break;
|
||||
if(!expansion_test_app_send_status_response(instance, ExpansionFrameErrorNone)) break;
|
||||
if(instance->frame.header.type != ExpansionFrameTypeData) break;
|
||||
pb_istream_t stream = pb_istream_from_buffer(
|
||||
instance->frame.content.data.bytes, instance->frame.content.data.size);
|
||||
if(!pb_decode_ex(&stream, &PB_Main_msg, message, PB_DECODE_DELIMITED)) break;
|
||||
success = true;
|
||||
} while(false);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
static bool expansion_test_app_send_presence(ExpansionTestApp* instance) {
|
||||
// Send pulses to emulate module insertion
|
||||
const uint8_t init = 0xAA;
|
||||
furi_hal_serial_tx(instance->handle, &init, sizeof(init));
|
||||
furi_hal_serial_tx_wait_complete(instance->handle);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool expansion_test_app_wait_ready(ExpansionTestApp* instance) {
|
||||
bool success = false;
|
||||
|
||||
do {
|
||||
if(!expansion_test_app_receive_frame(instance, &instance->frame)) break;
|
||||
if(instance->frame.header.type != ExpansionFrameTypeHeartbeat) break;
|
||||
success = true;
|
||||
} while(false);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
static bool expansion_test_app_handshake(ExpansionTestApp* instance) {
|
||||
bool success = false;
|
||||
|
||||
do {
|
||||
if(!expansion_test_app_send_baud_rate_request(instance, 230400)) break;
|
||||
if(!expansion_test_app_receive_frame(instance, &instance->frame)) break;
|
||||
if(!expansion_test_app_is_success_response(&instance->frame)) break;
|
||||
furi_hal_serial_set_br(instance->handle, 230400);
|
||||
furi_delay_ms(EXPANSION_PROTOCOL_BAUD_CHANGE_DT_MS);
|
||||
success = true;
|
||||
} while(false);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
static bool expansion_test_app_enable_otg(ExpansionTestApp* instance, bool enable) {
|
||||
bool success = false;
|
||||
|
||||
do {
|
||||
const ExpansionFrameControlCommand command = enable ?
|
||||
ExpansionFrameControlCommandEnableOtg :
|
||||
ExpansionFrameControlCommandDisableOtg;
|
||||
if(!expansion_test_app_send_control_request(instance, command)) break;
|
||||
if(!expansion_test_app_receive_frame(instance, &instance->frame)) break;
|
||||
if(!expansion_test_app_is_success_response(&instance->frame)) break;
|
||||
success = true;
|
||||
} while(false);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
static bool expansion_test_app_start_rpc(ExpansionTestApp* instance) {
|
||||
bool success = false;
|
||||
|
||||
do {
|
||||
if(!expansion_test_app_send_control_request(instance, ExpansionFrameControlCommandStartRpc))
|
||||
break;
|
||||
if(!expansion_test_app_receive_frame(instance, &instance->frame)) break;
|
||||
if(!expansion_test_app_is_success_response(&instance->frame)) break;
|
||||
success = true;
|
||||
} while(false);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
static bool expansion_test_app_rpc_mkdir(ExpansionTestApp* instance) {
|
||||
bool success = false;
|
||||
|
||||
instance->msg.command_id++;
|
||||
instance->msg.command_status = PB_CommandStatus_OK;
|
||||
instance->msg.which_content = PB_Main_storage_mkdir_request_tag;
|
||||
instance->msg.has_next = false;
|
||||
instance->msg.content.storage_mkdir_request.path = TEST_DIR_PATH;
|
||||
|
||||
do {
|
||||
if(!expansion_test_app_send_rpc_request(instance, &instance->msg)) break;
|
||||
if(!expansion_test_app_receive_rpc_request(instance, &instance->msg)) break;
|
||||
if(!expansion_test_app_is_success_rpc_message(&instance->msg)) break;
|
||||
success = true;
|
||||
} while(false);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
static bool expansion_test_app_rpc_write(ExpansionTestApp* instance) {
|
||||
bool success = false;
|
||||
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
File* file = storage_file_alloc(storage);
|
||||
|
||||
do {
|
||||
if(!storage_file_open(file, APP_ASSETS_PATH(TEST_FILE_NAME), FSAM_READ, FSOM_OPEN_EXISTING))
|
||||
break;
|
||||
|
||||
const uint64_t file_size = storage_file_size(file);
|
||||
|
||||
instance->msg.command_id++;
|
||||
instance->msg.command_status = PB_CommandStatus_OK;
|
||||
instance->msg.which_content = PB_Main_storage_write_request_tag;
|
||||
instance->msg.has_next = false;
|
||||
instance->msg.content.storage_write_request.path = TEST_FILE_PATH;
|
||||
instance->msg.content.storage_write_request.has_file = true;
|
||||
instance->msg.content.storage_write_request.file.data =
|
||||
malloc(PB_BYTES_ARRAY_T_ALLOCSIZE(file_size));
|
||||
instance->msg.content.storage_write_request.file.data->size = file_size;
|
||||
|
||||
const size_t bytes_read = storage_file_read(
|
||||
file, instance->msg.content.storage_write_request.file.data->bytes, file_size);
|
||||
|
||||
if(bytes_read != file_size) {
|
||||
pb_release(&PB_Main_msg, &instance->msg);
|
||||
break;
|
||||
}
|
||||
|
||||
if(!expansion_test_app_send_rpc_request(instance, &instance->msg)) break;
|
||||
if(!expansion_test_app_receive_rpc_request(instance, &instance->msg)) break;
|
||||
if(!expansion_test_app_is_success_rpc_message(&instance->msg)) break;
|
||||
success = true;
|
||||
} while(false);
|
||||
|
||||
storage_file_free(file);
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
static bool expansion_test_app_rpc_alert(ExpansionTestApp* instance) {
|
||||
bool success = false;
|
||||
|
||||
instance->msg.command_id++;
|
||||
instance->msg.command_status = PB_CommandStatus_OK;
|
||||
instance->msg.which_content = PB_Main_system_play_audiovisual_alert_request_tag;
|
||||
instance->msg.has_next = false;
|
||||
|
||||
do {
|
||||
if(!expansion_test_app_send_rpc_request(instance, &instance->msg)) break;
|
||||
if(!expansion_test_app_receive_rpc_request(instance, &instance->msg)) break;
|
||||
if(instance->msg.which_content != PB_Main_empty_tag) break;
|
||||
if(instance->msg.command_status != PB_CommandStatus_OK) break;
|
||||
success = true;
|
||||
} while(false);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
static bool expansion_test_app_rpc_enable_otg(ExpansionTestApp* instance, bool enable) {
|
||||
bool success = false;
|
||||
|
||||
instance->msg.command_id++;
|
||||
instance->msg.command_status = PB_CommandStatus_OK;
|
||||
instance->msg.which_content = PB_Main_gpio_set_otg_mode_tag;
|
||||
instance->msg.content.gpio_set_otg_mode.mode = enable ? PB_Gpio_GpioOtgMode_ON :
|
||||
PB_Gpio_GpioOtgMode_OFF;
|
||||
instance->msg.has_next = false;
|
||||
|
||||
do {
|
||||
if(!expansion_test_app_send_rpc_request(instance, &instance->msg)) break;
|
||||
if(!expansion_test_app_receive_rpc_request(instance, &instance->msg)) break;
|
||||
if(instance->msg.which_content != PB_Main_empty_tag) break;
|
||||
if(instance->msg.command_status != PB_CommandStatus_OK) break;
|
||||
success = true;
|
||||
} while(false);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
static bool expansion_test_app_idle(ExpansionTestApp* instance, uint32_t num_cycles) {
|
||||
uint32_t num_cycles_done;
|
||||
for(num_cycles_done = 0; num_cycles_done < num_cycles; ++num_cycles_done) {
|
||||
if(!expansion_test_app_send_heartbeat(instance)) break;
|
||||
if(!expansion_test_app_receive_frame(instance, &instance->frame)) break;
|
||||
if(instance->frame.header.type != ExpansionFrameTypeHeartbeat) break;
|
||||
furi_delay_ms(EXPANSION_PROTOCOL_TIMEOUT_MS - 50);
|
||||
}
|
||||
|
||||
return num_cycles_done == num_cycles;
|
||||
}
|
||||
|
||||
static bool expansion_test_app_stop_rpc(ExpansionTestApp* instance) {
|
||||
bool success = false;
|
||||
|
||||
do {
|
||||
if(!expansion_test_app_send_control_request(instance, ExpansionFrameControlCommandStopRpc))
|
||||
break;
|
||||
if(!expansion_test_app_receive_frame(instance, &instance->frame)) break;
|
||||
if(!expansion_test_app_is_success_response(&instance->frame)) break;
|
||||
success = true;
|
||||
} while(false);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
int32_t expansion_test_app(void* p) {
|
||||
UNUSED(p);
|
||||
|
||||
ExpansionTestApp* instance = expansion_test_app_alloc();
|
||||
expansion_test_app_start(instance);
|
||||
|
||||
bool success = false;
|
||||
|
||||
do {
|
||||
if(!expansion_test_app_send_presence(instance)) break;
|
||||
if(!expansion_test_app_wait_ready(instance)) break;
|
||||
if(!expansion_test_app_handshake(instance)) break;
|
||||
if(!expansion_test_app_enable_otg(instance, true)) break;
|
||||
if(!expansion_test_app_idle(instance, 5)) break;
|
||||
if(!expansion_test_app_start_rpc(instance)) break;
|
||||
if(!expansion_test_app_rpc_enable_otg(instance, false)) break;
|
||||
if(!expansion_test_app_idle(instance, 5)) break;
|
||||
if(!expansion_test_app_rpc_mkdir(instance)) break;
|
||||
if(!expansion_test_app_rpc_write(instance)) break;
|
||||
if(!expansion_test_app_rpc_alert(instance)) break;
|
||||
if(!expansion_test_app_rpc_enable_otg(instance, true)) break;
|
||||
if(!expansion_test_app_idle(instance, 5)) break;
|
||||
if(!expansion_test_app_stop_rpc(instance)) break;
|
||||
if(!expansion_test_app_enable_otg(instance, false)) break;
|
||||
success = true;
|
||||
} while(false);
|
||||
|
||||
expansion_test_app_stop(instance);
|
||||
expansion_test_app_free(instance);
|
||||
|
||||
if(!success) {
|
||||
NotificationApp* notification = furi_record_open(RECORD_NOTIFICATION);
|
||||
notification_message(notification, &sequence_error);
|
||||
furi_record_close(RECORD_NOTIFICATION);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -3,6 +3,7 @@ App(
|
||||
name="File Browser Test",
|
||||
apptype=FlipperAppType.DEBUG,
|
||||
entry_point="file_browser_app",
|
||||
cdefines=["APP_FILE_BROWSER_TEST"],
|
||||
requires=["gui"],
|
||||
stack_size=2 * 1024,
|
||||
order=150,
|
||||
|
||||
@@ -33,6 +33,8 @@ FileBrowserApp* file_browser_app_alloc(char* arg) {
|
||||
app->dialogs = furi_record_open(RECORD_DIALOGS);
|
||||
|
||||
app->view_dispatcher = view_dispatcher_alloc();
|
||||
view_dispatcher_enable_queue(app->view_dispatcher);
|
||||
|
||||
app->scene_manager = scene_manager_alloc(&file_browser_scene_handlers, app);
|
||||
|
||||
view_dispatcher_set_event_callback_context(app->view_dispatcher, app);
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 96 B After Width: | Height: | Size: 576 B |
@@ -2,7 +2,7 @@
|
||||
#include <furi.h>
|
||||
|
||||
#define DEFAULT_PATH "/"
|
||||
#define EXTENSION "*"
|
||||
#define EXTENSION "*"
|
||||
|
||||
bool file_browser_scene_browser_on_event(void* context, SceneManagerEvent event) {
|
||||
UNUSED(context);
|
||||
|
||||
@@ -19,7 +19,7 @@ bool file_browser_scene_start_on_event(void* context, SceneManagerEvent event) {
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
furi_string_set(app->file_path, EXT_PATH("badusb/demo_windows.txt"));
|
||||
furi_string_set(app->file_path, ANY_PATH("badusb/demo_windows.txt"));
|
||||
scene_manager_next_scene(app->scene_manager, FileBrowserSceneBrowser);
|
||||
consumed = true;
|
||||
} else if(event.type == SceneManagerEventTypeTick) {
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
App(
|
||||
appid="infrared_test",
|
||||
name="Infrared Test",
|
||||
apptype=FlipperAppType.DEBUG,
|
||||
entry_point="infrared_test_app",
|
||||
fap_category="Debug",
|
||||
targets=["f7"],
|
||||
)
|
||||
@@ -1,61 +0,0 @@
|
||||
#include <furi.h>
|
||||
#include <furi_hal_infrared.h>
|
||||
|
||||
#define TAG "InfraredTest"
|
||||
|
||||
#define CARRIER_FREQ_HZ (38000UL)
|
||||
#define CARRIER_DUTY (0.33f)
|
||||
|
||||
#define BURST_DURATION_US (600UL)
|
||||
#define BURST_COUNT (50UL)
|
||||
|
||||
typedef struct {
|
||||
bool level;
|
||||
uint32_t count;
|
||||
} InfraredTestApp;
|
||||
|
||||
static FuriHalInfraredTxGetDataState
|
||||
infrared_test_app_tx_data_callback(void* context, uint32_t* duration, bool* level) {
|
||||
furi_assert(context);
|
||||
furi_assert(duration);
|
||||
furi_assert(level);
|
||||
|
||||
InfraredTestApp* app = context;
|
||||
|
||||
*duration = BURST_DURATION_US;
|
||||
*level = app->level;
|
||||
|
||||
app->level = !app->level;
|
||||
app->count += 1;
|
||||
|
||||
if(app->count < BURST_COUNT * 2) {
|
||||
return FuriHalInfraredTxGetDataStateOk;
|
||||
} else {
|
||||
return FuriHalInfraredTxGetDataStateLastDone;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t infrared_test_app(void* arg) {
|
||||
UNUSED(arg);
|
||||
|
||||
InfraredTestApp app = {
|
||||
.level = true,
|
||||
};
|
||||
|
||||
FURI_LOG_I(TAG, "Starting test signal on PA7");
|
||||
|
||||
furi_hal_infrared_set_tx_output(FuriHalInfraredTxPinExtPA7);
|
||||
furi_hal_infrared_async_tx_set_data_isr_callback(infrared_test_app_tx_data_callback, &app);
|
||||
furi_hal_infrared_async_tx_start(CARRIER_FREQ_HZ, CARRIER_DUTY);
|
||||
furi_hal_infrared_async_tx_wait_termination();
|
||||
furi_hal_infrared_set_tx_output(FuriHalInfraredTxPinInternal);
|
||||
|
||||
FURI_LOG_I(TAG, "Test signal end");
|
||||
FURI_LOG_I(
|
||||
TAG,
|
||||
"The measured signal should be %luus +-%.1fus",
|
||||
(app.count - 1) * BURST_DURATION_US,
|
||||
(double)1000000.0 / CARRIER_FREQ_HZ);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -3,6 +3,7 @@ App(
|
||||
name="Keypad Test",
|
||||
apptype=FlipperAppType.DEBUG,
|
||||
entry_point="keypad_test_app",
|
||||
cdefines=["APP_KEYPAD_TEST"],
|
||||
requires=["gui"],
|
||||
stack_size=1 * 1024,
|
||||
order=30,
|
||||
|
||||
@@ -11,7 +11,6 @@ typedef struct {
|
||||
uint16_t left;
|
||||
uint16_t right;
|
||||
uint16_t ok;
|
||||
FuriMutex* mutex;
|
||||
} KeypadTestState;
|
||||
|
||||
static void keypad_test_reset_state(KeypadTestState* state) {
|
||||
@@ -23,8 +22,7 @@ static void keypad_test_reset_state(KeypadTestState* state) {
|
||||
}
|
||||
|
||||
static void keypad_test_render_callback(Canvas* canvas, void* ctx) {
|
||||
KeypadTestState* state = ctx;
|
||||
furi_mutex_acquire(state->mutex, FuriWaitForever);
|
||||
KeypadTestState* state = (KeypadTestState*)acquire_mutex((ValueMutex*)ctx, 25);
|
||||
canvas_clear(canvas);
|
||||
char strings[5][20];
|
||||
|
||||
@@ -53,7 +51,7 @@ static void keypad_test_render_callback(Canvas* canvas, void* ctx) {
|
||||
|
||||
canvas_draw_str(canvas, 10, 63, "[back] - reset, hold to exit");
|
||||
|
||||
furi_mutex_release(state->mutex);
|
||||
release_mutex((ValueMutex*)ctx, state);
|
||||
}
|
||||
|
||||
static void keypad_test_input_callback(InputEvent* input_event, void* ctx) {
|
||||
@@ -64,12 +62,19 @@ static void keypad_test_input_callback(InputEvent* input_event, void* ctx) {
|
||||
int32_t keypad_test_app(void* p) {
|
||||
UNUSED(p);
|
||||
FuriMessageQueue* event_queue = furi_message_queue_alloc(32, sizeof(InputEvent));
|
||||
KeypadTestState state = {{false, false, false, false, false}, 0, 0, 0, 0, 0, NULL};
|
||||
state.mutex = furi_mutex_alloc(FuriMutexTypeNormal);
|
||||
furi_check(event_queue);
|
||||
|
||||
KeypadTestState _state = {{false, false, false, false, false}, 0, 0, 0, 0, 0};
|
||||
|
||||
ValueMutex state_mutex;
|
||||
if(!init_mutex(&state_mutex, &_state, sizeof(KeypadTestState))) {
|
||||
FURI_LOG_E(TAG, "cannot create mutex");
|
||||
return 0;
|
||||
}
|
||||
|
||||
ViewPort* view_port = view_port_alloc();
|
||||
|
||||
view_port_draw_callback_set(view_port, keypad_test_render_callback, &state);
|
||||
view_port_draw_callback_set(view_port, keypad_test_render_callback, &state_mutex);
|
||||
view_port_input_callback_set(view_port, keypad_test_input_callback, event_queue);
|
||||
|
||||
// Open GUI and register view_port
|
||||
@@ -78,7 +83,7 @@ int32_t keypad_test_app(void* p) {
|
||||
|
||||
InputEvent event;
|
||||
while(furi_message_queue_get(event_queue, &event, FuriWaitForever) == FuriStatusOk) {
|
||||
furi_mutex_acquire(state.mutex, FuriWaitForever);
|
||||
KeypadTestState* state = (KeypadTestState*)acquire_mutex_block(&state_mutex);
|
||||
FURI_LOG_I(
|
||||
TAG,
|
||||
"key: %s type: %s",
|
||||
@@ -87,54 +92,54 @@ int32_t keypad_test_app(void* p) {
|
||||
|
||||
if(event.key == InputKeyRight) {
|
||||
if(event.type == InputTypePress) {
|
||||
state.press[0] = true;
|
||||
state->press[0] = true;
|
||||
} else if(event.type == InputTypeRelease) {
|
||||
state.press[0] = false;
|
||||
state->press[0] = false;
|
||||
} else if(event.type == InputTypeShort) {
|
||||
++state.right;
|
||||
++state->right;
|
||||
}
|
||||
} else if(event.key == InputKeyLeft) {
|
||||
if(event.type == InputTypePress) {
|
||||
state.press[1] = true;
|
||||
state->press[1] = true;
|
||||
} else if(event.type == InputTypeRelease) {
|
||||
state.press[1] = false;
|
||||
state->press[1] = false;
|
||||
} else if(event.type == InputTypeShort) {
|
||||
++state.left;
|
||||
++state->left;
|
||||
}
|
||||
} else if(event.key == InputKeyUp) {
|
||||
if(event.type == InputTypePress) {
|
||||
state.press[2] = true;
|
||||
state->press[2] = true;
|
||||
} else if(event.type == InputTypeRelease) {
|
||||
state.press[2] = false;
|
||||
state->press[2] = false;
|
||||
} else if(event.type == InputTypeShort) {
|
||||
++state.up;
|
||||
++state->up;
|
||||
}
|
||||
} else if(event.key == InputKeyDown) {
|
||||
if(event.type == InputTypePress) {
|
||||
state.press[3] = true;
|
||||
state->press[3] = true;
|
||||
} else if(event.type == InputTypeRelease) {
|
||||
state.press[3] = false;
|
||||
state->press[3] = false;
|
||||
} else if(event.type == InputTypeShort) {
|
||||
++state.down;
|
||||
++state->down;
|
||||
}
|
||||
} else if(event.key == InputKeyOk) {
|
||||
if(event.type == InputTypePress) {
|
||||
state.press[4] = true;
|
||||
state->press[4] = true;
|
||||
} else if(event.type == InputTypeRelease) {
|
||||
state.press[4] = false;
|
||||
state->press[4] = false;
|
||||
} else if(event.type == InputTypeShort) {
|
||||
++state.ok;
|
||||
++state->ok;
|
||||
}
|
||||
} else if(event.key == InputKeyBack) {
|
||||
if(event.type == InputTypeLong) {
|
||||
furi_mutex_release(state.mutex);
|
||||
release_mutex(&state_mutex, state);
|
||||
break;
|
||||
} else if(event.type == InputTypeShort) {
|
||||
keypad_test_reset_state(&state);
|
||||
keypad_test_reset_state(state);
|
||||
}
|
||||
}
|
||||
|
||||
furi_mutex_release(state.mutex);
|
||||
release_mutex(&state_mutex, state);
|
||||
view_port_update(view_port);
|
||||
}
|
||||
|
||||
@@ -142,7 +147,7 @@ int32_t keypad_test_app(void* p) {
|
||||
gui_remove_view_port(gui, view_port);
|
||||
view_port_free(view_port);
|
||||
furi_message_queue_free(event_queue);
|
||||
furi_mutex_free(state.mutex);
|
||||
delete_mutex(&state_mutex);
|
||||
|
||||
furi_record_close(RECORD_GUI);
|
||||
|
||||
|
||||
@@ -12,11 +12,12 @@ static bool lfrfid_debug_back_event_callback(void* context) {
|
||||
return scene_manager_handle_back_event(app->scene_manager);
|
||||
}
|
||||
|
||||
static LfRfidDebug* lfrfid_debug_alloc(void) {
|
||||
static LfRfidDebug* lfrfid_debug_alloc() {
|
||||
LfRfidDebug* app = malloc(sizeof(LfRfidDebug));
|
||||
|
||||
app->view_dispatcher = view_dispatcher_alloc();
|
||||
app->scene_manager = scene_manager_alloc(&lfrfid_debug_scene_handlers, app);
|
||||
view_dispatcher_enable_queue(app->view_dispatcher);
|
||||
view_dispatcher_set_event_callback_context(app->view_dispatcher, app);
|
||||
view_dispatcher_set_custom_event_callback(
|
||||
app->view_dispatcher, lfrfid_debug_custom_event_callback);
|
||||
@@ -77,4 +78,4 @@ int32_t lfrfid_debug_app(void* p) {
|
||||
lfrfid_debug_free(app);
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -6,11 +6,6 @@ static void comparator_trigger_callback(bool level, void* comp_ctx) {
|
||||
furi_hal_gpio_write(&gpio_ext_pa7, !level);
|
||||
}
|
||||
|
||||
void lfrfid_debug_view_tune_callback(void* context) {
|
||||
LfRfidDebug* app = context;
|
||||
view_dispatcher_send_custom_event(app->view_dispatcher, 0xBA);
|
||||
}
|
||||
|
||||
void lfrfid_debug_scene_tune_on_enter(void* context) {
|
||||
LfRfidDebug* app = context;
|
||||
|
||||
@@ -19,9 +14,9 @@ void lfrfid_debug_scene_tune_on_enter(void* context) {
|
||||
furi_hal_rfid_comp_set_callback(comparator_trigger_callback, app);
|
||||
furi_hal_rfid_comp_start();
|
||||
|
||||
furi_hal_rfid_tim_read_start(125000, 0.5);
|
||||
|
||||
lfrfid_debug_view_tune_set_callback(app->tune_view, lfrfid_debug_view_tune_callback, app);
|
||||
furi_hal_rfid_pins_read();
|
||||
furi_hal_rfid_tim_read(125000, 0.5);
|
||||
furi_hal_rfid_tim_read_start();
|
||||
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidDebugViewTune);
|
||||
}
|
||||
@@ -48,5 +43,6 @@ void lfrfid_debug_scene_tune_on_exit(void* context) {
|
||||
|
||||
furi_hal_gpio_init_simple(&gpio_ext_pa7, GpioModeAnalog);
|
||||
furi_hal_rfid_tim_read_stop();
|
||||
furi_hal_rfid_tim_reset();
|
||||
furi_hal_rfid_pins_reset();
|
||||
}
|
||||
|
||||
@@ -13,8 +13,6 @@ typedef struct {
|
||||
uint32_t ARR;
|
||||
uint32_t CCR;
|
||||
int pos;
|
||||
void (*update_callback)(void* context);
|
||||
void* update_context;
|
||||
} LfRfidTuneViewModel;
|
||||
|
||||
static void lfrfid_debug_view_tune_draw_callback(Canvas* canvas, void* _model) {
|
||||
@@ -34,8 +32,8 @@ static void lfrfid_debug_view_tune_draw_callback(Canvas* canvas, void* _model) {
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
|
||||
char buffer[TEMP_STR_LEN + 1];
|
||||
double freq = ((double)SystemCoreClock / (model->ARR + 1));
|
||||
double duty = (double)((model->CCR + 1) * 100) / (model->ARR + 1);
|
||||
double freq = ((float)SystemCoreClock / ((float)model->ARR + 1));
|
||||
double duty = ((float)model->CCR + 1) / ((float)model->ARR + 1) * 100.0f;
|
||||
snprintf(
|
||||
buffer,
|
||||
TEMP_STR_LEN,
|
||||
@@ -153,29 +151,29 @@ static bool lfrfid_debug_view_tune_input_callback(InputEvent* event, void* conte
|
||||
consumed = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if(event->key == InputKeyLeft || event->key == InputKeyRight) {
|
||||
with_view_model(
|
||||
tune_view->view,
|
||||
LfRfidTuneViewModel * model,
|
||||
{
|
||||
if(model->update_callback) {
|
||||
model->update_callback(model->update_context);
|
||||
}
|
||||
},
|
||||
false);
|
||||
}
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
LfRfidTuneView* lfrfid_debug_view_tune_alloc(void) {
|
||||
LfRfidTuneView* lfrfid_debug_view_tune_alloc() {
|
||||
LfRfidTuneView* tune_view = malloc(sizeof(LfRfidTuneView));
|
||||
tune_view->view = view_alloc();
|
||||
view_set_context(tune_view->view, tune_view);
|
||||
view_allocate_model(tune_view->view, ViewModelTypeLocking, sizeof(LfRfidTuneViewModel));
|
||||
lfrfid_debug_view_tune_clean(tune_view);
|
||||
|
||||
with_view_model(
|
||||
tune_view->view,
|
||||
LfRfidTuneViewModel * model,
|
||||
{
|
||||
model->dirty = true;
|
||||
model->fine = false;
|
||||
model->ARR = 511;
|
||||
model->CCR = 255;
|
||||
model->pos = 0;
|
||||
},
|
||||
true);
|
||||
|
||||
view_set_draw_callback(tune_view->view, lfrfid_debug_view_tune_draw_callback);
|
||||
view_set_input_callback(tune_view->view, lfrfid_debug_view_tune_input_callback);
|
||||
|
||||
@@ -201,8 +199,6 @@ void lfrfid_debug_view_tune_clean(LfRfidTuneView* tune_view) {
|
||||
model->ARR = 511;
|
||||
model->CCR = 255;
|
||||
model->pos = 0;
|
||||
model->update_callback = NULL;
|
||||
model->update_context = NULL;
|
||||
},
|
||||
true);
|
||||
}
|
||||
@@ -223,28 +219,16 @@ bool lfrfid_debug_view_tune_is_dirty(LfRfidTuneView* tune_view) {
|
||||
|
||||
uint32_t lfrfid_debug_view_tune_get_arr(LfRfidTuneView* tune_view) {
|
||||
uint32_t result = false;
|
||||
with_view_model(tune_view->view, LfRfidTuneViewModel * model, { result = model->ARR; }, false);
|
||||
with_view_model(
|
||||
tune_view->view, LfRfidTuneViewModel * model, { result = model->ARR; }, false);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
uint32_t lfrfid_debug_view_tune_get_ccr(LfRfidTuneView* tune_view) {
|
||||
uint32_t result = false;
|
||||
with_view_model(tune_view->view, LfRfidTuneViewModel * model, { result = model->CCR; }, false);
|
||||
with_view_model(
|
||||
tune_view->view, LfRfidTuneViewModel * model, { result = model->CCR; }, false);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void lfrfid_debug_view_tune_set_callback(
|
||||
LfRfidTuneView* tune_view,
|
||||
void (*callback)(void* context),
|
||||
void* context) {
|
||||
with_view_model(
|
||||
tune_view->view,
|
||||
LfRfidTuneViewModel * model,
|
||||
{
|
||||
model->update_callback = callback;
|
||||
model->update_context = context;
|
||||
},
|
||||
false);
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user