Added Adult toy controller external app (#2840)

This commit is contained in:
Pezsma 2025-10-23 13:09:48 +02:00 committed by GitHub
parent 60a5222058
commit 81afec9ea4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 752 additions and 2 deletions

View file

@ -415,6 +415,44 @@ static constexpr Bitmap bitmap_icon_adsb{
{16, 16},
bitmap_icon_adsb_data};
static constexpr uint8_t bitmap_icon_adulttoys_data[] = {
0x00,
0x00,
0x30,
0x0C,
0x78,
0x1E,
0x7C,
0x3E,
0xFE,
0x7F,
0xFE,
0x7F,
0xFE,
0x7F,
0xFE,
0x7F,
0xFC,
0x3F,
0xFC,
0x3F,
0xF8,
0x1F,
0xF0,
0x0F,
0xE0,
0x07,
0xC0,
0x03,
0x80,
0x01,
0x00,
0x00,
};
static constexpr Bitmap bitmap_icon_adulttoys{
{16, 16},
bitmap_icon_adulttoys_data};
static constexpr uint8_t bitmap_icon_ais_data[] = {
0x00,
0x01,

View file

@ -0,0 +1,85 @@
/*
* Copyright (C) 2025 Pezsma
*
* This file is part of PortaPack.
*
* 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 2, 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; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#include "ui.hpp"
#include "ui_adult_toys_controller.hpp"
#include "ui_navigation.hpp"
#include "external_app.hpp"
namespace ui::external_app::adult_toys_controller {
void initialize_app(::ui::NavigationView& nav) {
nav.push<AdultToysView>();
}
} // namespace ui::external_app::adult_toys_controller
extern "C" {
__attribute__((section(".external_app.app_adult_toys_controller.application_information"), used)) application_information_t _application_information_adult_toys_controller = {
/*.memory_location = */ (uint8_t*)0x00000000,
/*.externalAppEntry = */ ui::external_app::adult_toys_controller::initialize_app,
/*.header_version = */ CURRENT_HEADER_VERSION,
/*.app_version = */ VERSION_MD5,
/*.app_name = */ "Adult Toys",
/*.bitmap_data = */ {
0x00,
0x00,
0x30,
0x0C,
0x78,
0x1E,
0x7C,
0x3E,
0xFE,
0x7F,
0xFE,
0x7F,
0xFE,
0x7F,
0xFE,
0x7F,
0xFC,
0x3F,
0xFC,
0x3F,
0xF8,
0x1F,
0xF0,
0x0F,
0xE0,
0x07,
0xC0,
0x03,
0x80,
0x01,
0x00,
0x00,
},
/*.icon_color = */ ui::Color::yellow().v,
/*.menu_location = */ app_location_t::TX,
/*.desired_menu_position = */ -1,
/*.m4_app_tag = portapack::spi_flash::image_tag_btle_tx */ {'P', 'B', 'T', 'T'},
/*.m4_app_offset = */ 0x00000000, // will be filled at compile time
};
}

View file

@ -0,0 +1,373 @@
#include "ui_adult_toys_controller.hpp"
#include "ui_modemsetup.hpp"
#include "modems.hpp"
#include "audio.hpp"
#include "baseband_api.hpp"
#include "string_format.hpp"
#include "portapack_persistent_memory.hpp"
#include "ui_navigation.hpp"
using namespace portapack;
using namespace modems;
using namespace ui;
namespace ui::external_app::adult_toys_controller {
void AdultToysView::focus() {
button_on.focus();
}
AdultToysView::AdultToysView(NavigationView& nav)
: nav_{nav} {
add_children({
&button_on,
&btn_adult,
&btn_child,
&btn_mode_decrease,
&btn_mode_increase,
&btn_pcknum_inc,
&btn_pcknum_dec,
&chk_mode_rnd,
&chk_mode_play,
&chk_mode_stop,
&chk_mode_ncnt,
&chk_mode_infinite,
&field_frequency,
&txt_selected_mode,
&options_target,
&labels,
&message_num,
&tx_view,
&screen_message_1,
&screen_message_2,
&screen_message_3,
&screen_message_4,
&screen_message_5,
&screen_message_6,
&screen_message_7,
&screen_message_8,
&screen_message_9,
&screen_message_10,
});
btn_adult.on_select = [this](Button&) {
start_screen = true;
hidden_program(!start_screen);
};
btn_child.on_select = [this](Button&) {
nav_.pop();
};
button_on.on_select = [this](Button&) {
if (play_running || stop_running) {
if (button_onstate) {
button_onstate = false;
stop();
button_on.set_text(LanguageHelper::currentMessages[LANG_START]);
} else {
button_onstate = true;
printCurrentModes();
start();
button_on.set_text(LanguageHelper::currentMessages[LANG_STOP]);
}
} // if play_running || stop_running
};
btn_mode_decrease.on_select = [this](Button&) {
if (toy_packet > 0) {
toy_packet--;
printCurrentModes();
}
};
btn_mode_increase.on_select = [this](Button&) {
if (stop_running || play_running) {
if (play_running && (toy_packet < max_plays - 1)) {
toy_packet++;
} else {
if (stop_running && toy_packet < max_stops - 1) {
toy_packet++;
}
}
printCurrentModes();
}
};
btn_pcknum_inc.on_select = [this](Button&) {
if (!button_onstate) {
chk_mode_ncnt.set_value(true);
if (n_message_set < n_message_max) {
n_message_set++;
} else {
n_message_set = 0;
}
message_num.set_value(n_message_set);
n_message_current = n_message_set;
}
};
btn_pcknum_dec.on_select = [this](Button&) {
if (!button_onstate) {
chk_mode_ncnt.set_value(true);
if (n_message_set > 0) {
n_message_set--;
} else {
n_message_set = n_message_max;
}
message_num.set_value(n_message_set);
n_message_current = n_message_set;
}
};
message_num.on_change = [this](int32_t v) {
if (!button_onstate) {
chk_mode_ncnt.set_value(true);
n_message_set = static_cast<uint16_t>(v);
n_message_current = n_message_set;
} else {
if (!button_onstate) message_num.set_value(n_message_current);
}
};
chk_mode_rnd.on_select = [this](Checkbox&, bool v) {
random_running = v;
};
chk_mode_play.on_select = [this](Checkbox&, bool v) {
play_running = v;
if (play_running && stop_running) {
toy_packet = 0;
stop_running = false;
chk_mode_stop.set_value(stop_running);
}
if (play_running) printCurrentModes();
};
chk_mode_stop.on_select = [this](Checkbox&, bool v) {
stop_running = v;
if (play_running && stop_running) {
toy_packet = 0;
play_running = false;
chk_mode_play.set_value(play_running);
}
if (stop_running) printCurrentModes();
};
chk_mode_ncnt.on_select = [this](Checkbox&, bool v) {
n_message_running = v;
if (n_message_running && inf_message_running) {
inf_message_running = false;
chk_mode_infinite.set_value(inf_message_running);
}
};
chk_mode_infinite.on_select = [this](Checkbox&, bool v) {
inf_message_running = v;
if (n_message_running && inf_message_running) {
n_message_running = false;
chk_mode_ncnt.set_value(n_message_running);
}
};
options_target.on_change = [this](size_t, int32_t i) {
target = (uint8_t)i;
};
chk_mode_infinite.set_value(true);
chk_mode_play.set_value(true);
}
void AdultToysView::hidden_program(bool hide) {
options_target.hidden(hide);
labels.hidden(hide);
button_on.hidden(hide);
btn_mode_decrease.hidden(hide);
btn_mode_increase.hidden(hide);
btn_pcknum_inc.hidden(hide);
btn_pcknum_dec.hidden(hide);
chk_mode_rnd.hidden(hide);
chk_mode_play.hidden(hide);
chk_mode_stop.hidden(hide);
chk_mode_ncnt.hidden(hide);
chk_mode_infinite.hidden(hide);
field_frequency.hidden(hide);
txt_selected_mode.hidden(hide);
message_num.hidden(hide);
tx_view.hidden(hide);
btn_adult.hidden(!hide);
btn_child.hidden(!hide);
screen_message_1.hidden(!hide);
screen_message_2.hidden(!hide);
screen_message_3.hidden(!hide);
screen_message_4.hidden(!hide);
screen_message_5.hidden(!hide);
screen_message_6.hidden(!hide);
screen_message_7.hidden(!hide);
screen_message_8.hidden(!hide);
screen_message_9.hidden(!hide);
screen_message_10.hidden(!hide);
set_dirty();
if (hide)
btn_child.focus();
else
button_on.focus();
}
void AdultToysView::on_show() {
hidden_program(!start_screen);
}
void AdultToysView::createPacket(bool regenerate) {
if (regenerate) randomizeMac();
randomChn();
if (target == 1 || 1) { // now only lovespouse supported, in the future, need to separee them
uint32_t mode = play_running ? plays[toy_packet].value : stops[toy_packet].value;
const uint8_t size = 22;
uint8_t packet[size];
uint8_t i = 0;
// 1. AD Flags
packet[i++] = 2;
packet[i++] = 0x01;
packet[i++] = 0x1A;
// 2. Manufacturer Specific
packet[i++] = 14;
packet[i++] = 0xFF;
packet[i++] = 0xFF;
packet[i++] = 0x00;
packet[i++] = 0x6D;
packet[i++] = 0xB6;
packet[i++] = 0x43;
packet[i++] = 0xCE;
packet[i++] = 0x97;
packet[i++] = 0xFE;
packet[i++] = 0x42;
packet[i++] = 0x7C;
packet[i++] = (mode >> 0x10) & 0xFF;
packet[i++] = (mode >> 0x8) & 0xFF;
packet[i++] = (mode >> 0x0) & 0xFF;
// 3. Service UUID List
packet[i++] = 3;
packet[i++] = 0x03;
packet[i++] = 0x8F;
packet[i++] = 0xAE;
std::string res = to_string_hex_array(packet, i);
memset(advertisementData, 0, sizeof(advertisementData));
std::copy(res.begin(), res.end(), advertisementData);
}
}
AdultToysView::~AdultToysView() {
stop();
}
void AdultToysView::stop() {
transmitter_model.disable();
baseband::shutdown();
}
void AdultToysView::start() {
baseband::run_image(portapack::spi_flash::image_tag_btle_tx);
transmitter_model.enable();
on_tx_progress(true);
}
void AdultToysView::reset() {
stop();
start();
}
uint8_t AdultToysView::randomize(uint8_t max) {
return static_cast<uint8_t>(rand() % max);
}
void AdultToysView::printCurrentModes() {
uint8_t max_val = play_running ? max_plays : max_stops;
auto name = play_running ? plays[toy_packet].name : stops[toy_packet].name;
std::string current = to_string_dec_uint(toy_packet + 1);
std::string max_val_str = to_string_dec_uint(max_val);
std::string result_str = current;
result_str += "/";
result_str += max_val_str;
result_str += " ";
result_str += name;
txt_selected_mode.set(result_str.c_str());
}
uint64_t AdultToysView::get_freq_by_channel_number(uint8_t channel_number) {
uint64_t freq_hz;
switch (channel_number) {
case 37:
freq_hz = 2'402'000'000ull;
break;
case 38:
freq_hz = 2'426'000'000ull;
break;
case 39:
freq_hz = 2'480'000'000ull;
break;
case 0 ... 10:
freq_hz = 2'404'000'000ull + channel_number * 2'000'000ull;
break;
case 11 ... 36:
freq_hz = 2'428'000'000ull + (channel_number - 11) * 2'000'000ull;
break;
default:
freq_hz = UINT64_MAX;
}
return freq_hz;
}
void AdultToysView::randomizeMac() {
const char hexDigits[] = "0123456789ABCDEF";
// Generate 12 random hexadecimal characters
for (int i = 0; i < 12; ++i) {
int randomIndex = rand() % 16;
mac[i] = hexDigits[randomIndex];
}
mac[12] = '\0'; // Null-terminate the string
}
void AdultToysView::randomChn() {
channel_number = 37 + std::rand() % (39 - 37 + 1);
field_frequency.set_value(get_freq_by_channel_number(channel_number));
}
void AdultToysView::on_tx_progress(const bool done) {
if (!done) return;
if (!button_onstate) return;
bool regenerate = (counter++ % 600) == 0;
if (random_running && regenerate) {
toy_packet = randomize(play_running ? max_plays : max_stops);
}
createPacket(regenerate);
printCurrentModes();
if (n_message_running) {
if (n_message_current > 0) {
n_message_current--;
message_num.set_value(n_message_current);
} else {
stop();
message_num.set_value(n_message_set);
button_on.set_text(LanguageHelper::currentMessages[LANG_START]);
button_onstate = false;
n_message_current = n_message_set;
return;
}
} // if n_message
baseband::set_btletx(channel_number, mac, advertisementData, pduType);
}
} // namespace ui::external_app::adult_toys_controller

View file

@ -0,0 +1,245 @@
/*
* Copyright (C) 2025 Pezsma
*
* This file is part of PortaPack.
*
* 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 2, 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; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
// Code from https://github.com/Next-Flip/Momentum-Apps/blob/89d493daa1ea0cb86906fa0042c41dd4edc22a6a/ble_spam/protocols/lovespouse.c#L93
// Thanks for the work of the original creators!
#ifndef __UI_ADULT_TOYS_H__
#define __UI_ADULT_TOYS_H__
#include "ui.hpp"
#include "ui_language.hpp"
#include "ui_navigation.hpp"
#include "ui_transmitter.hpp"
#include "ui_freq_field.hpp"
#include "ui_record_view.hpp"
#include "app_settings.hpp"
#include "radio_state.hpp"
#include "log_file.hpp"
#include "utility.hpp"
using namespace ui;
namespace ui::external_app::adult_toys_controller {
enum PKT_TYPE {
PKT_TYPE_INVALID_TYPE,
PKT_TYPE_RAW,
PKT_TYPE_DISCOVERY,
PKT_TYPE_IBEACON,
PKT_TYPE_ADV_IND,
PKT_TYPE_ADV_DIRECT_IND,
PKT_TYPE_ADV_NONCONN_IND,
PKT_TYPE_ADV_SCAN_IND,
PKT_TYPE_SCAN_REQ,
PKT_TYPE_SCAN_RSP,
PKT_TYPE_CONNECT_REQ,
PKT_TYPE_LL_DATA,
PKT_TYPE_LL_CONNECTION_UPDATE_REQ,
PKT_TYPE_LL_CHANNEL_MAP_REQ,
PKT_TYPE_LL_TERMINATE_IND,
PKT_TYPE_LL_ENC_REQ,
PKT_TYPE_LL_ENC_RSP,
PKT_TYPE_LL_START_ENC_REQ,
PKT_TYPE_LL_START_ENC_RSP,
PKT_TYPE_LL_UNKNOWN_RSP,
PKT_TYPE_LL_FEATURE_REQ,
PKT_TYPE_LL_FEATURE_RSP,
PKT_TYPE_LL_PAUSE_ENC_REQ,
PKT_TYPE_LL_PAUSE_ENC_RSP,
PKT_TYPE_LL_VERSION_IND,
PKT_TYPE_LL_REJECT_IND,
PKT_TYPE_NUM_PKT_TYPE
};
class AdultToysView : public ui::View {
public:
AdultToysView(NavigationView& nav);
~AdultToysView();
void focus() override;
void on_show() override;
std::string title() const override {
return "Adult Toys";
};
struct LovespouseMode {
uint32_t value;
std::string name;
};
private:
NavigationView& nav_;
TxRadioState radio_state_{
2'402'000'000 /* frequency */,
4'000'000 /* bandwidth */,
4'000'000 /* sampling rate */
};
TxFrequencyField field_frequency{
{UI_POS_X(0), UI_POS_Y(0)},
nav_};
TransmitterView2 tx_view{
{UI_POS_X(11), UI_POS_Y(0)},
/*short_ui*/ true};
app_settings::SettingsManager settings_{
"Adult Toys", app_settings::Mode::TX};
OptionsField options_target{
{UI_POS_X(6), UI_POS_Y(1)},
11,
{{"LoveSpouse", 1}}};
Button btn_adult{{UI_POS_X(0), UI_POS_Y_BOTTOM(4), UI_POS_WIDTH(10), UI_POS_HEIGHT(3)}, "adult"};
Button btn_child{{UI_POS_X_RIGHT(10), UI_POS_Y_BOTTOM(4), UI_POS_WIDTH(10), UI_POS_HEIGHT(3)}, "child"};
Button button_on{
{UI_POS_X(0), UI_POS_Y(3), UI_POS_WIDTH(12), UI_POS_HEIGHT(2)},
LanguageHelper::currentMessages[LANG_START]};
Button btn_mode_decrease{
{UI_POS_X(0), UI_POS_Y(13), UI_POS_WIDTH(3), UI_POS_HEIGHT(2)},
"<-"};
Button btn_mode_increase{
{UI_POS_X_RIGHT(3), UI_POS_Y(13), UI_POS_WIDTH(3), UI_POS_HEIGHT(2)},
"->"};
Text txt_selected_mode{{UI_POS_X_CENTER(22), UI_POS_Y(13.5), UI_POS_WIDTH(22), UI_POS_HEIGHT(1)}, ""};
Button btn_pcknum_inc{
{UI_POS_X(7), UI_POS_Y(9), UI_POS_WIDTH(2), UI_POS_HEIGHT(1.5)},
"+"};
Button btn_pcknum_dec{
{UI_POS_X(0), UI_POS_Y(9), UI_POS_WIDTH(2), UI_POS_HEIGHT(1.5)},
"-"};
NumberField message_num{{UI_POS_X(3), UI_POS_Y(9.2)}, 3, {0, 999}, 1, ' ', true};
Checkbox chk_mode_rnd{{UI_POS_X_RIGHT(15), UI_POS_Y(3)}, 12, "Random Msg.", false};
Checkbox chk_mode_play{{UI_POS_X_RIGHT(15), UI_POS_Y(5)}, 10, "Play Mode", false};
Checkbox chk_mode_stop{{UI_POS_X_RIGHT(15), UI_POS_Y(7)}, 10, "Stop Mode", false};
Checkbox chk_mode_ncnt{{UI_POS_X_RIGHT(15), UI_POS_Y(9)}, 7, "N Msg.", false};
Checkbox chk_mode_infinite{{UI_POS_X_RIGHT(15), UI_POS_Y(11)}, 10, "Inf. Msg.", false};
Text screen_message_1{{0, 0, UI_POS_MAXWIDTH, UI_POS_HEIGHT(1)}, "The application is intended"};
Text screen_message_2{{0, 25, UI_POS_MAXWIDTH, UI_POS_HEIGHT(1)}, "for controlling Love Spouse"};
Text screen_message_3{{0, 50, UI_POS_MAXWIDTH, UI_POS_HEIGHT(1)}, "auxiliary tools/devices."};
Text screen_message_4{{0, 75, UI_POS_MAXWIDTH, UI_POS_HEIGHT(1)}, "It is only for use by adults."};
Text screen_message_5{{0, 100, UI_POS_MAXWIDTH, UI_POS_HEIGHT(1)}, "Are you an adult?"};
Text screen_message_6{{0, 140, UI_POS_MAXWIDTH, UI_POS_HEIGHT(1)}, "To use the application, "};
Text screen_message_7{{0, 165, UI_POS_MAXWIDTH, UI_POS_HEIGHT(1)}, "I assume full responsibility"};
Text screen_message_8{{0, 190, UI_POS_MAXWIDTH, UI_POS_HEIGHT(1)}, "for the \"I do not assume"};
Text screen_message_9{{0, 215, UI_POS_MAXWIDTH, UI_POS_HEIGHT(1)}, "responsibility\"."};
Text screen_message_10{{UI_POS_X_RIGHT(16), 230, UI_POS_WIDTH(16), UI_POS_HEIGHT(1)}, "(The developer)"};
Labels labels{
{{UI_POS_X(0), UI_POS_Y(1)}, "Type:", Theme::getInstance()->fg_light->foreground}};
bool button_onstate{false};
bool play_running{false};
bool stop_running{false};
bool random_running{false};
bool n_message_running{false};
bool inf_message_running{false};
bool start_screen{false};
uint8_t target = 1; // lovespouse
char mac[13] = "010203040506";
uint8_t channel_number = 37;
char advertisementData[63] = {"03032CFE06162CFED5A59E020AB4\0"};
PKT_TYPE pduType = {PKT_TYPE_DISCOVERY};
uint8_t toy_packet = 0;
uint16_t n_message_max = 999;
uint16_t n_message_set = 0;
uint16_t n_message_current = 0;
static const size_t max_plays = 27;
static const size_t max_stops = 3;
uint16_t counter = 599;
void createPacket(bool regenerate);
void start();
void stop();
void reset();
void printCurrentModes();
void on_tx_progress(const bool done);
void hidden_program(bool hide);
void randomizeMac();
void randomChn();
uint8_t randomize(uint8_t max);
uint64_t get_freq_by_channel_number(uint8_t channel_number);
MessageHandlerRegistration message_handler_tx_progress{
Message::ID::TXProgress,
[this](const Message* const p) {
const auto message = *reinterpret_cast<const TXProgressMessage*>(p);
this->on_tx_progress(message.done);
}};
LovespouseMode plays[max_plays] = {
{0xE49C6C, "Classic 1"},
{0xE7075E, "Classic 2"},
{0xE68E4F, "Classic 3"},
{0xE1313B, "Classic 4"},
{0xE0B82A, "Classic 5"},
{0xE32318, "Classic 6"},
{0xE2AA09, "Classic 7"},
{0xED5DF1, "Classic 8"},
{0xECD4E0, "Classic 9"},
{0xD41F5D, "Independent 1-1"},
{0xD7846F, "Independent 1-2"},
{0xD60D7E, "Independent 1-3"},
{0xD1B20A, "Independent 1-4"},
{0xD0B31B, "Independent 1-5"},
{0xD3A029, "Independent 1-6"},
{0xD22938, "Independent 1-7"},
{0xDDDEC0, "Independent 1-8"},
{0xDC57D1, "Independent 1-9"},
{0xA4982E, "Independent 2-1"},
{0xA7031C, "Independent 2-2"},
{0xA68A0D, "Independent 2-3"},
{0xA13579, "Independent 2-4"},
{0xA0BC68, "Independent 2-5"},
{0xA3275A, "Independent 2-6"},
{0xA2AE4B, "Independent 2-7"},
{0xAD59B3, "Independent 2-8"},
{0xACD0A2, "Independent 2-9"},
};
LovespouseMode stops[max_stops] = {
{0xE5157D, "Classic Stop"},
{0xD5964C, "Independent 1 Stop"},
{0xA5113F, "Independent 2 Stop"},
};
};
}; // namespace ui::external_app::adult_toys_controller
#endif // ui_adult_toys_controller_hpp

View file

@ -258,6 +258,10 @@ set(EXTCPPSRC
#morse_practice
external/morse_practice/main.cpp
external/morse_practice/ui_morse_practice.cpp
#adult_toys_controller
external/adult_toys_controller/main.cpp
external/adult_toys_controller/ui_adult_toys_controller.cpp
)
set(EXTAPPLIST
@ -323,4 +327,5 @@ set(EXTAPPLIST
game2048
bht_tx
morse_practice
adult_toys_controller
)

View file

@ -85,7 +85,7 @@ MEMORY
ram_external_app_game2048 (rwx) : org = 0xADEC0000, len = 32k
ram_external_app_bht_tx (rwx) : org = 0xADED0000, len = 32k
ram_external_app_morse_practice (rwx) : org = 0xADEE0000, len = 32k
ram_external_app_adult_toys_controller (rwx) : org = 0xADEF0000, len = 32k
}
@ -465,6 +465,11 @@ SECTIONS
*(*ui*external_app*morse_practice*);
} > ram_external_app_morse_practice
.external_app_adult_toys_controller : ALIGN(4) SUBALIGN(4)
{
KEEP(*(.external_app.app_adult_toys_controller.application_information));
*(*ui*external_app*adult_toys_controller*);
} > ram_external_app_adult_toys_controller
}

View file

@ -34,7 +34,6 @@ void initialize_app(NavigationView& nav) {
extern "C" {
// Az alkalmazás információ C-linkage-ként, hogy a firmware hívhassa
__attribute__((section(".external_app.app_morse_practice.application_information"), used))
application_information_t _application_information_morse_practice = {
/*.memory_location = */ (uint8_t*)0x00000000,

Binary file not shown.

After

Width:  |  Height:  |  Size: 215 B