M changelog.md => changelog.md +1 -0
@@ 8,6 8,7 @@
* Add PLL2 clock switching
* Support for asynchronous callbacks on application side.
* APN settings window - empty.
+* Bluetooth settings middleware layer
### Changed
D image/user/db/settings_v2_001.sql => image/user/db/settings_v2_001.sql +0 -43
@@ 1,43 0,0 @@
---
--- Main settings table, for string application persistent data
---
-CREATE TABLE IF NOT EXISTS settings_tab (
- path TEXT NOT NULL UNIQUE PRIMARY KEY,
- value TEXT
-);
-
---
--- Dictionary table, for variables with fixed set of values
---
-CREATE TABLE IF NOT EXISTS dictionary_tab (
- id INTEGER PRIMARY KEY,
- path TEXT NOT NULL,
- value TEXT,
- CONSTRAINT dictionary_unique
- UNIQUE (path, value) ON CONFLICT REPLACE
- );
-
---
--- Table contains information who to inform
--- about changes in values.
---
-CREATE TABLE IF NOT EXISTS notifications_tab (
- id INTEGER PRIMARY KEY,
- path TEXT NOT NULL,
- service TEXT,
- CONSTRAINT notification_unique
- UNIQUE(path, service)
- );
-
-CREATE TABLE IF NOT EXISTS settings_changed_tab(
-
- id INTEGER PRIMARY KEY,
- path TEXT NOT NULL,
- value TEXT,
- CONSTRAINT changed_unique
- UNIQUE(path ) ON CONFLICT REPLACE
-);
-
-CREATE TRIGGER IF NOT EXISTS on_update UPDATE OF value ON settings_tab
-WHEN new.value <> old.value BEGIN INSERT OR REPLACE INTO settings_changed_tab (path, value) VALUES (new.path,new.value); END;
-
M module-apps/CMakeLists.txt => module-apps/CMakeLists.txt +1 -1
@@ 32,7 32,7 @@ set( SOURCES
"widgets/BrightnessBox.cpp"
"widgets/ModesBox.cpp"
"widgets/BarGraph.cpp"
- )
+)
add_library(${PROJECT_NAME} STATIC ${SOURCES} ${BOARD_SOURCES})
M module-apps/application-settings-new/ApplicationSettings.cpp => module-apps/application-settings-new/ApplicationSettings.cpp +24 -1
@@ 33,7 33,11 @@
#include <service-cellular/CellularServiceAPI.hpp>
#include <service-db/Settings.hpp>
#include <module-services/service-bluetooth/service-bluetooth/messages/Status.hpp>
+#include <service-bluetooth/messages/BondedDevices.hpp>
+#include <service-bluetooth/messages/DeviceName.hpp>
+#include <application-settings-new/data/BondedDevicesData.hpp>
#include <service-db/agents/settings/SystemSettings.hpp>
+#include <application-settings-new/data/PhoneNameData.hpp>
namespace app
{
@@ 105,7 109,7 @@ namespace app
}
}
- return std::make_shared<sys::ResponseMessage>();
+ return sys::MessageNone{};
}
// Invoked during initialization
@@ 118,6 122,25 @@ namespace app
return ret;
}
+ connect(typeid(::message::bluetooth::ResponseDeviceName), [&](sys::Message *msg) {
+ auto responseDeviceNameMsg = static_cast<::message::bluetooth::ResponseDeviceName *>(msg);
+ if (gui::window::name::phone_name == getCurrentWindow()->getName()) {
+ auto phoneNameData = std::make_unique<gui::PhoneNameData>(responseDeviceNameMsg->getName());
+ switchWindow(gui::window::name::phone_name, std::move(phoneNameData));
+ }
+ return sys::MessageNone{};
+ });
+
+ connect(typeid(::message::bluetooth::ResponseBondedDevices), [&](sys::Message *msg) {
+ auto responseBondedDevicesMsg = static_cast<::message::bluetooth::ResponseBondedDevices *>(msg);
+ if (gui::window::name::all_devices == getCurrentWindow()->getName()) {
+ auto bondedDevicesData =
+ std::make_unique<gui::BondedDevicesData>(responseBondedDevicesMsg->getDevices());
+ switchWindow(gui::window::name::all_devices, std::move(bondedDevicesData));
+ }
+ return sys::MessageNone{};
+ });
+
createUserInterface();
setActiveWindow(gui::name::window::main_window);
A module-apps/application-settings-new/data/BondedDevicesData.hpp => module-apps/application-settings-new/data/BondedDevicesData.hpp +24 -0
@@ 0,0 1,24 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#pragma once
+
+#include <Device.hpp>
+
+namespace gui
+{
+
+ class BondedDevicesData : public SwitchData
+ {
+ public:
+ explicit BondedDevicesData(std::vector<Devicei> devices) : devices(std::move(devices))
+ {}
+ [[nodiscard]] auto getDevices() const noexcept -> const std::vector<Devicei> &
+ {
+ return devices;
+ }
+
+ private:
+ const std::vector<Devicei> devices;
+ };
+} // namespace gui
A module-apps/application-settings-new/data/PhoneNameData.hpp => module-apps/application-settings-new/data/PhoneNameData.hpp +22 -0
@@ 0,0 1,22 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#pragma once
+#include <string>
+#include <SwitchData.hpp>
+namespace gui
+{
+ class PhoneNameData : public SwitchData
+ {
+ public:
+ explicit PhoneNameData(std::string name) : name(std::move(name))
+ {}
+ [[nodiscard]] auto getName() const -> const std::string &
+ {
+ return name;
+ }
+
+ private:
+ const std::string name;
+ };
+} // namespace gui
M module-apps/application-settings-new/windows/AllDevicesWindow.cpp => module-apps/application-settings-new/windows/AllDevicesWindow.cpp +15 -10
@@ 8,18 8,29 @@
#include "OptionSetting.hpp"
#include "DialogMetadata.hpp"
#include "DialogMetadataMessage.hpp"
+#include <Constants.hpp>
#include <InputEvent.hpp>
#include <i18n/i18n.hpp>
#include <service-bluetooth/BluetoothMessage.hpp>
-
+#include <service-bluetooth/messages/BondedDevices.hpp>
+#include "application-settings-new/data/BondedDevicesData.hpp"
namespace gui
{
AllDevicesWindow::AllDevicesWindow(app::Application *app) : OptionWindow(app, gui::window::name::all_devices)
{
setTitle(utils::localize.get("app_settings_bluetooth_all_devices"));
- addOptions(allDevicesOptionsList());
+ sys::Bus::SendUnicast(
+ std::make_shared<::message::bluetooth::RequestBondedDevices>(), service::name::bluetooth, application);
+ }
+
+ void AllDevicesWindow::onBeforeShow(ShowMode mode, SwitchData *data)
+ {
+ clearOptions();
+ if (const auto newData = dynamic_cast<BondedDevicesData *>(data); newData != nullptr) {
+ addOptions(allDevicesOptionsList(newData->getDevices()));
+ }
}
auto AllDevicesWindow::onInput(const InputEvent &inputEvent) -> bool
@@ 44,17 55,11 @@ namespace gui
return AppWindow::onInput(inputEvent);
}
- auto AllDevicesWindow::allDevicesOptionsList() -> std::list<Option>
+ auto AllDevicesWindow::allDevicesOptionsList(const std::vector<Devicei> &devicesList) -> std::list<Option>
{
std::list<gui::Option> optionsList;
- std::vector<Devicei> devices{Devicei("Paired_device1"),
- Devicei("Paired_device2"),
- Devicei("Paired_device3"),
- Devicei("Paired_device4"),
- Devicei("Paired_device5")};
-
- for (const auto &device : devices) {
+ for (const auto &device : devicesList) {
optionsList.emplace_back(std::make_unique<gui::OptionSettings>(
device.name,
[=](gui::Item &item) {
M module-apps/application-settings-new/windows/AllDevicesWindow.hpp => module-apps/application-settings-new/windows/AllDevicesWindow.hpp +7 -6
@@ 1,21 1,22 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
-
#pragma once
#include "OptionWindow.hpp"
-
+#include <Device.hpp>
namespace gui
{
class AllDevicesWindow : public OptionWindow
{
public:
- AllDevicesWindow(app::Application *app);
- auto onInput(const InputEvent &inputEvent) -> bool override;
+ explicit AllDevicesWindow(app::Application *app);
private:
+ auto allDevicesOptionsList(const std::vector<Devicei> &vector) -> std::list<Option>;
+ void onBeforeShow(ShowMode mode, SwitchData *data) override;
+ auto onInput(const InputEvent &inputEvent) -> bool override;
Image *leftArrowImage = nullptr;
Image *crossImage = nullptr;
- auto allDevicesOptionsList() -> std::list<Option>;
};
-}; // namespace gui
+
+} // namespace gui
M module-apps/application-settings-new/windows/BluetoothWindow.cpp => module-apps/application-settings-new/windows/BluetoothWindow.cpp +2 -2
@@ 110,10 110,10 @@ namespace gui
BluetoothStatus btStatus;
if (isBluetoothSwitchOn) {
- btStatus.state = BluetoothStatus::BluetoothState::On;
+ btStatus.state = BluetoothStatus::State::On;
}
else {
- btStatus.state = BluetoothStatus::BluetoothState::Off;
+ btStatus.state = BluetoothStatus::State::Off;
}
btStatus.visibility = isPhoneVisibilitySwitchOn;
::message::bluetooth::SetStatus setStatus(btStatus);
M module-apps/application-settings-new/windows/BluetoothWindow.hpp => module-apps/application-settings-new/windows/BluetoothWindow.hpp +1 -1
@@ 29,7 29,7 @@ namespace gui
{}
[[nodiscard]] auto getState() const noexcept -> bool
{
- if (status.state == BluetoothStatus::BluetoothState::On) {
+ if (status.state == BluetoothStatus::State::On) {
return true;
}
return false;
M module-apps/application-settings-new/windows/PhoneNameWindow.cpp => module-apps/application-settings-new/windows/PhoneNameWindow.cpp +30 -1
@@ 5,7 5,12 @@
#include "application-settings-new/ApplicationSettings.hpp"
#include "widgets/InputBox.hpp"
+#include <service-bluetooth/Constants.hpp>
+#include <service-bluetooth/messages/DeviceName.hpp>
+#include <service-bluetooth/messages/SetDeviceName.hpp>
+
#include <Utils.hpp>
+#include <application-settings-new/data/PhoneNameData.hpp>
namespace gui
{
@@ 30,12 35,36 @@ namespace gui
bottomBar->setText(BottomBar::Side::CENTER, utils::localize.get(style::strings::common::save));
bottomBar->setText(BottomBar::Side::RIGHT, utils::localize.get(style::strings::common::back));
+ sys::Bus::SendUnicast(
+ std::make_shared<::message::bluetooth::RequestDeviceName>(), service::name::bluetooth, application);
+
setFocusItem(inputField);
}
void PhoneNameWindow::onBeforeShow(ShowMode mode, SwitchData *data)
{
inputField->clear();
- setFocusItem(inputField);
+ if (const auto newData = dynamic_cast<PhoneNameData *>(data); data != nullptr) {
+ inputField->setText(newData->getName());
+ }
+ }
+
+ auto PhoneNameWindow::onInput(const InputEvent &inputEvent) -> bool
+ {
+ if (AppWindow::onInput(inputEvent)) {
+ return true;
+ }
+
+ if (!inputEvent.isShortPress()) {
+ return false;
+ }
+
+ if (inputEvent.is(gui::KeyCode::KEY_ENTER) && !inputField->isEmpty()) {
+ auto result = std::make_shared<::message::bluetooth::SetDeviceName>(inputField->getText());
+ sys::Bus::SendUnicast(std::move(result), service::name::bluetooth, application);
+ return true;
+ }
+
+ return false;
}
} // namespace gui
M module-apps/application-settings-new/windows/PhoneNameWindow.hpp => module-apps/application-settings-new/windows/PhoneNameWindow.hpp +4 -6
@@ 1,10 1,7 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
-
#pragma once
-
#include "AppWindow.hpp"
-
#include <Text.hpp>
namespace gui
@@ 12,11 9,12 @@ namespace gui
class PhoneNameWindow : public AppWindow
{
public:
- PhoneNameWindow(app::Application *app);
- void buildInterface() override;
- void onBeforeShow(ShowMode mode, SwitchData *data) override;
+ explicit PhoneNameWindow(app::Application *app);
private:
+ void buildInterface() override;
+ void onBeforeShow(ShowMode mode, SwitchData *data) override;
+ auto onInput(const InputEvent &inputEvent) -> bool override;
Text *inputField = nullptr;
};
M module-bluetooth/Bluetooth/BluetoothWorker.cpp => module-bluetooth/Bluetooth/BluetoothWorker.cpp +78 -14
@@ 6,11 6,13 @@
#include "log/log.hpp"
#include "interface/profiles/A2DP/A2DP.hpp"
#include "interface/profiles/HSP/HSP.hpp"
+#include "BtKeysStorage.hpp"
extern "C"
{
#include "module-bluetooth/lib/btstack/src/btstack_util.h"
}
#include <btstack_run_loop_freertos.h>
+#include <service-bluetooth/ServiceBluetooth.hpp>
#if DEBUG_BLUETOOTH_HCI_COMS == 1
#define logHciComs(...) LOG_DEBUG(__VA_ARGS__)
@@ 41,15 43,23 @@ const char *c_str(Bt::Error::Code code)
}
return "";
}
+namespace queues
+{
+ constexpr inline auto io = "qBtIO";
+ constexpr inline auto cmd = "qBtCmds";
+
+} // namespace queues
BluetoothWorker::BluetoothWorker(sys::Service *service)
- : Worker(service), service(service), currentProfile(std::make_shared<Bt::HSP>())
+ : Worker(service), service(service), currentProfile(std::make_shared<Bt::HSP>()),
+ settings(static_cast<ServiceBluetooth *>(service)->settingsHolder)
{
init({
- {"qBtIO", sizeof(Bt::Message), 10},
- {"qBtWork", sizeof(Bt::EvtWorker), 10},
+ {queues::io, sizeof(Bt::Message), 10},
+ {queues::cmd, sizeof(Bt::Command), 10},
});
-};
+ static_cast<ServiceBluetooth *>(service)->workerQueue = Worker::getQueueHandleByName(queues::cmd);
+}
BluetoothWorker::~BluetoothWorker()
{
@@ 69,14 79,33 @@ bool BluetoothWorker::run()
is_running = true;
auto el = queues[queueIO_handle];
BlueKitchen::getInstance()->qHandle = el->GetQueueHandle();
+ Bt::KeyStorage::settings = settings;
Bt::initialize_stack();
Bt::register_hw_error_callback();
Bt::GAP::register_scan();
+
std::string name = "PurePhone";
- Bt::set_name(name);
- // set local namne
- Bt::GAP::set_visibility(true);
- // Bt::GAP::
+ auto settingsName = std::get<std::string>(settings->getValue(Bluetooth::Settings::DeviceName));
+ if (settingsName.empty()) {
+ LOG_ERROR("settings name empty!");
+ settings->setValue(Bluetooth::Settings::DeviceName, name);
+ settingsName = name;
+ }
+ Bt::set_name(settingsName);
+ Bt::GAP::set_visibility(
+ std::visit(Bluetooth::BoolVisitor(), settings->getValue(Bluetooth::Settings::Visibility)));
+
+ settings->setValue(Bluetooth::Settings::State, static_cast<int>(BluetoothStatus::State::On));
+ settings->onLinkKeyAdded = [this](std::string addr) {
+ for (auto &device : Bt::GAP::devices) {
+ if (bd_addr_to_str(device.address) == addr) {
+ // found paired device
+ pairedDevices.emplace_back(device);
+ settings->setValue(Bluetooth::Settings::BondedDevices, SettingsSerializer::toString(pairedDevices));
+ }
+ }
+ };
+
Bt::run_stack(&this->bt_worker_task);
return true;
}
@@ 106,13 135,10 @@ void BluetoothWorker::stopScan()
Bt::GAP::stop_scan();
}
-bool BluetoothWorker::toggleVisibility()
+void BluetoothWorker::setVisibility(bool visibility)
{
- static bool visibility = true;
Bt::GAP::set_visibility(visibility);
- visibility = !visibility;
-
- return visibility;
+ settings->setValue(Bluetooth::Settings::Visibility, visibility);
}
bool BluetoothWorker::start_pan()
@@ 124,15 150,53 @@ bool BluetoothWorker::start_pan()
}
return false;
}
+bool BluetoothWorker::handleCommand(QueueHandle_t queue)
+{
+ Bt::Command command;
+ if (xQueueReceive(queue, &command, 0) != pdTRUE) {
+ LOG_ERROR("Queue receive failure!");
+ return false;
+ }
+ switch (command) {
+ case Bt::PowerOn:
+ break;
+ case Bt::StartScan:
+ scan();
+ break;
+ case Bt::StopScan:
+ stopScan();
+ break;
+ case Bt::VisibilityOn:
+ setVisibility(true);
+ break;
+ case Bt::VisibilityOff:
+ setVisibility(false);
+ break;
+ case Bt::ConnectAudio:
+ establishAudioConnection();
+ break;
+ case Bt::DisconnectAudio:
+ disconnectAudioConnection();
+ break;
+ case Bt::PowerOff:
+ break;
+ }
+ return true;
+}
bool BluetoothWorker::handleMessage(uint32_t queueID)
{
-
QueueHandle_t queue = queues[queueID]->GetQueueHandle();
if (queueID == queueService) {
LOG_DEBUG("not interested");
return true;
}
+
+ if (queueID == queueCommands) {
+ handleCommand(queue);
+ return true;
+ }
+
if (queueID != queueIO_handle) {
LOG_ERROR("Wrong queue! %" PRIu32, queueID);
return false;
M module-bluetooth/Bluetooth/BluetoothWorker.hpp => module-bluetooth/Bluetooth/BluetoothWorker.hpp +22 -4
@@ 11,6 11,7 @@
#include <memory>
#include <task.h>
#include <vector>
+#include "service-bluetooth/SettingsHolder.hpp"
struct HCI;
@@ 19,7 20,7 @@ struct HCI;
namespace Bt
{
- enum Message : uint8_t
+ enum Message : std::uint8_t
{
/// asynchronous messages to use on event from irq
EvtSending, /// Bt stack ordered a write transaction and it is pending
@@ 33,6 34,18 @@ namespace Bt
EvtErrorRec, /// there was error o queue receive
};
+ enum Command : std::uint8_t
+ {
+ StartScan,
+ StopScan,
+ VisibilityOn,
+ VisibilityOff,
+ ConnectAudio,
+ DisconnectAudio,
+ PowerOn,
+ PowerOff,
+ };
+
inline const char *MessageCstr(Message what)
{
switch (what) {
@@ 70,8 83,9 @@ class BluetoothWorker : private sys::Worker
queueService = 0,
queueControl = 1,
queueIO_handle, /// bsp support queue
- queue_profiles, /// queue for communication between profile workers,
- /// main bt_worker_task should dispatch these in events
+ // queue_profiles, /// queue for communication between profile workers,
+ // /// main bt_worker_task should dispatch these in events
+ queueCommands,
};
TaskHandle_t bt_worker_task = nullptr;
@@ 91,11 105,13 @@ class BluetoothWorker : private sys::Worker
virtual bool handleMessage(uint32_t queueID);
+ bool handleCommand(QueueHandle_t queue);
+
bool run();
bool scan();
- bool toggleVisibility();
+ void setVisibility(bool visibility);
bool start_pan();
@@ 111,4 127,6 @@ class BluetoothWorker : private sys::Worker
void initAudioBT();
std::shared_ptr<Bt::Profile> currentProfile;
+ std::shared_ptr<Bluetooth::SettingsHolder> settings;
+ std::vector<Devicei> pairedDevices;
};
M module-bluetooth/Bluetooth/BtCommand.hpp => module-bluetooth/Bluetooth/BtCommand.hpp +1 -0
@@ 17,6 17,7 @@ namespace Bt
auto run_stack(TaskHandle_t *handle) -> Error;
namespace GAP
{
+ extern std::vector<Devicei> devices;
/// THIS have to be called prior to Bt system start!
auto register_scan() -> Error;
auto scan() -> Error;
M module-bluetooth/Bluetooth/BtKeysStorage.cpp => module-bluetooth/Bluetooth/BtKeysStorage.cpp +33 -56
@@ 2,59 2,22 @@
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include <algorithm>
-#include <cstdio>
-#include <filesystem>
-#include <purefs/filesystem_paths.hpp>
-#include <gsl/gsl_util>
-
#include "BtKeysStorage.hpp"
-json11::Json Bt::KeyStorage::fileJson = json11::Json();
+json11::Json Bt::KeyStorage::keysJson = json11::Json();
btstack_link_key_db_t Bt::KeyStorage::keyStorage;
json11::Json::array Bt::KeyStorage::keys;
-std::string Bt::KeyStorage::fileContent;
+std::string Bt::KeyStorage::keysEntry;
+std::shared_ptr<Bluetooth::SettingsHolder> Bt::KeyStorage::settings = nullptr;
namespace Bt
{
- namespace
- {
- std::string loadFilesAsString(const std::filesystem::path &fileToLoad)
- {
- using namespace std::string_literals;
- static constexpr auto file_size_limit = 512LU * 1024LU;
- std::error_code ec;
- auto filesize = std::filesystem::file_size(fileToLoad, ec);
- if (ec || filesize > file_size_limit) {
- return ""s;
- }
- std::string contents(filesize, '\0');
- auto fp = fopen(fileToLoad.c_str(), "r");
- if (!fp) {
- return ""s;
- }
- auto cleanup = gsl::finally([fp] { fclose(fp); });
- const auto nitems = std::fread(contents.data(), contents.size(), 1, fp);
- return (nitems == 1) ? contents : ""s;
- }
-
- bool replaceWithString(const std::filesystem::path &fileToModify, const std::string &stringToWrite)
- {
- auto fp = std::fopen(fileToModify.c_str(), "w");
- if (!fp)
- return false;
- auto cleanup = gsl::finally([fp] { fclose(fp); });
- size_t dataWritten = std::fwrite(stringToWrite.data(), stringToWrite.size(), 1, fp);
- return dataWritten == 1;
- }
- } // namespace
-
namespace strings
{
- inline std::string keysFilename = purefs::dir::getUserDiskPath() / "btkeys.json";
- inline std::string keys = "keys";
- inline std::string link_key = "link_key";
- inline std::string bd_addr = "bd_addr";
- inline std::string type = "type";
+ constexpr inline auto keys = "keys";
+ constexpr inline auto link_key = "link_key";
+ constexpr inline auto bd_addr = "bd_addr";
+ constexpr inline auto type = "type";
} // namespace strings
auto KeyStorage::getKeyStorage() -> btstack_link_key_db_t *
@@ 75,28 38,33 @@ namespace Bt
void KeyStorage::openStorage()
{
LOG_INFO("opening storage from API");
- fileContent.clear();
- fileContent = loadFilesAsString(strings::keysFilename);
- if (fileContent.empty()) {
- LOG_WARN("opening empty key file!");
+ if (settings) {
+ keysEntry = std::visit(Bluetooth::StringVisitor(), settings->getValue(Bluetooth::Settings::BtKeys));
+ }
+ else {
+ LOG_ERROR("failed opening settings for BT!");
+ return;
+ }
+ if (keysEntry.empty()) {
+ LOG_WARN("opening empty key entry!");
return;
}
std::string err;
- fileJson = json11::Json::parse(fileContent.c_str(), err);
+ keysJson = json11::Json::parse(keysEntry.c_str(), err);
if (!err.empty()) {
LOG_ERROR("Error while parsing json: %s", err.c_str());
return;
}
- keys = std::move(fileJson[strings::keys].array_items());
+ keys = std::move(keysJson[strings::keys].array_items());
LOG_INFO("Imported keys: %d", static_cast<unsigned int>(keys.size()));
}
void KeyStorage::closeStorage()
{
LOG_INFO("closing storage from API");
- writeToFile();
+ writeSettings();
}
//
auto KeyStorage::getLinkKey(uint8_t *bd_addr, link_key_t link_key, link_key_type_t *type) -> int
@@ 128,7 96,10 @@ namespace Bt
{strings::link_key, std::string(reinterpret_cast<char *>(link_key))},
{strings::type, type}};
keys.emplace_back(keyEntry);
- writeToFile();
+ if (settings->onLinkKeyAdded) {
+ settings->onLinkKeyAdded(bd_addr_to_str(bd_addr));
+ }
+ writeSettings();
LOG_INFO("keys written to the file");
LOG_INFO("Keys in file: %d", (int)keys.size());
}
@@ 146,7 117,7 @@ namespace Bt
if (keysSize != keys.size()) {
LOG_INFO("Key successfully deleted");
}
- writeToFile();
+ writeSettings();
}
//
auto KeyStorage::iterator_init(btstack_link_key_iterator_t *it) -> int
@@ 164,11 135,17 @@ namespace Bt
{}
void KeyStorage::set_local_bd_addr(bd_addr_t bd_addr)
{}
- void KeyStorage::writeToFile()
+ void KeyStorage::writeSettings()
{
json11::Json finalJson = json11::Json::object{{strings::keys, keys}};
- fileContent = finalJson.dump();
- replaceWithString(strings::keysFilename, fileContent);
+ keysEntry = finalJson.dump();
+ if (settings) {
+ settings->setValue(Bluetooth::Settings::BtKeys, keysEntry);
+ }
+ else {
+ LOG_ERROR("failed to open settings to write!");
+ return;
+ }
}
} // namespace Bt
M module-bluetooth/Bluetooth/BtKeysStorage.hpp => module-bluetooth/Bluetooth/BtKeysStorage.hpp +5 -4
@@ 7,7 7,7 @@
#include <btstack_util.h>
#include <json/json11.hpp>
-#include <vfs.hpp>
+#include <service-bluetooth/SettingsHolder.hpp>
namespace Bt
{
@@ 16,6 16,7 @@ namespace Bt
{
public:
static auto getKeyStorage() -> btstack_link_key_db_t *;
+ static std::shared_ptr<Bluetooth::SettingsHolder> settings;
private:
static void openStorage();
@@ 30,11 31,11 @@ namespace Bt
link_key_type_t *type) -> int;
static void iterator_done(btstack_link_key_iterator_t *it);
static void set_local_bd_addr(bd_addr_t bd_addr);
- static void writeToFile();
- static json11::Json fileJson;
+ static void writeSettings();
+ static json11::Json keysJson;
static btstack_link_key_db_t keyStorage;
static json11::Json::array keys;
- static std::string fileContent;
+ static std::string keysEntry;
};
} // namespace Bt
M module-bluetooth/Bluetooth/BtstackWorker.cpp => module-bluetooth/Bluetooth/BtstackWorker.cpp +0 -1
@@ 195,7 195,6 @@ namespace Bt
hci_init(transport, (void *)&config);
hci_set_link_key_db(KeyStorage::getKeyStorage());
-
hci_event_callback_registration.callback = &hci_packet_handler;
hci_add_event_handler(&hci_event_callback_registration);
LOG_DEBUG("BT worker run success");
M module-bluetooth/Bluetooth/interface/profiles/GAP.cpp => module-bluetooth/Bluetooth/interface/profiles/GAP.cpp +23 -20
@@ 9,6 9,7 @@
#include <log/log.hpp>
#include <service-bluetooth/BluetoothMessage.hpp>
#include <vector>
+#include <BtCommand.hpp>
extern "C"
{
@@ 18,8 19,7 @@ extern "C"
btstack_packet_callback_registration_t cb_handler;
-std::vector<Devicei> devices;
-
+std::vector<Devicei> Bt::GAP::devices;
static auto start_scan() -> int;
static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
@@ 44,6 44,7 @@ enum STATE state = INIT;
namespace Bt::GAP
{
+
static sys::Service *ownerService = nullptr;
void setOwnerService(sys::Service *service)
@@ 97,6 98,7 @@ namespace Bt::GAP
}
return false;
}
+
} // namespace Bt::GAP
#define INQUIRY_INTERVAL 5
@@ 109,8 111,8 @@ static auto start_scan() -> int
static auto has_more_remote_name_requests() -> int
{
int i;
- for (i = 0; i < devices.size(); i++) {
- if (devices[i].state == REMOTE_NAME_REQUEST) {
+ for (i = 0; i < Bt::GAP::devices.size(); i++) {
+ if (Bt::GAP::devices[i].state == REMOTE_NAME_REQUEST) {
return 1;
}
}
@@ 120,13 122,14 @@ static auto has_more_remote_name_requests() -> int
static void do_next_remote_name_request()
{
int i;
- for (i = 0; i < devices.size(); i++) {
+ for (i = 0; i < Bt::GAP::devices.size(); i++) {
// remote name request
- if (devices[i].state == REMOTE_NAME_REQUEST) {
- devices[i].state = REMOTE_NAME_INQUIRED;
- LOG_INFO("Get remote name of %s...", bd_addr_to_str(devices[i].address));
- gap_remote_name_request(
- devices[i].address, devices[i].pageScanRepetitionMode, devices[i].clockOffset | 0x8000);
+ if (Bt::GAP::devices[i].state == REMOTE_NAME_REQUEST) {
+ Bt::GAP::devices[i].state = REMOTE_NAME_INQUIRED;
+ LOG_INFO("Get remote name of %s...", bd_addr_to_str(Bt::GAP::devices[i].address));
+ gap_remote_name_request(Bt::GAP::devices[i].address,
+ Bt::GAP::devices[i].pageScanRepetitionMode,
+ Bt::GAP::devices[i].clockOffset | 0x8000);
return;
}
}
@@ 186,7 189,7 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe
case GAP_EVENT_INQUIRY_RESULT: {
gap_event_inquiry_result_get_bd_addr(packet, addr);
- index = getDeviceIndexForAddress(devices, addr);
+ index = getDeviceIndexForAddress(Bt::GAP::devices, addr);
if (index >= 0) {
break; // already in our list
}
@@ 215,36 218,36 @@ static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packe
else {
dev.state = REMOTE_NAME_REQUEST;
}
- devices.push_back(dev);
- auto msg = std::make_shared<BluetoothScanResultMessage>(devices);
+ Bt::GAP::devices.push_back(dev);
+ auto msg = std::make_shared<BluetoothScanResultMessage>(Bt::GAP::devices);
sys::Bus::SendUnicast(msg, "ApplicationSettings", Bt::GAP::ownerService);
sys::Bus::SendUnicast(msg, "ApplicationSettingsNew", Bt::GAP::ownerService);
} break;
case GAP_EVENT_INQUIRY_COMPLETE:
- for (i = 0; i < devices.size(); i++) {
+ for (i = 0; i < Bt::GAP::devices.size(); i++) {
// retry remote name request
- if (devices[i].state == REMOTE_NAME_INQUIRED)
- devices[i].state = REMOTE_NAME_REQUEST;
+ if (Bt::GAP::devices[i].state == REMOTE_NAME_INQUIRED)
+ Bt::GAP::devices[i].state = REMOTE_NAME_REQUEST;
}
continue_remote_names();
break;
case HCI_EVENT_REMOTE_NAME_REQUEST_COMPLETE: {
reverse_bd_addr(&packet[3], addr);
- index = getDeviceIndexForAddress(devices, addr);
+ index = getDeviceIndexForAddress(Bt::GAP::devices, addr);
if (index >= 0) {
if (packet[2] == 0) {
LOG_INFO("Name: '%s'", &packet[9]);
- devices[index].state = REMOTE_NAME_FETCHED;
- devices[index].name = reinterpret_cast<char *>(&packet[9]);
+ Bt::GAP::devices[index].state = REMOTE_NAME_FETCHED;
+ Bt::GAP::devices[index].name = reinterpret_cast<char *>(&packet[9]);
}
else {
LOG_INFO("Failed to get name: page timeout");
}
}
- if (index + 1 == devices.size()) {
+ if (index + 1 == Bt::GAP::devices.size()) {
LOG_INFO("Scanned all");
state = DONE;
gap_inquiry_stop();
M module-services/service-bluetooth/CMakeLists.txt => module-services/service-bluetooth/CMakeLists.txt +1 -0
@@ 5,6 5,7 @@ message( "${PROJECT_NAME} ${CMAKE_CURRENT_LIST_DIR}" )
set(SOURCES
ServiceBluetooth.cpp
service-bluetooth/SettingsHolder.cpp
+ service-bluetooth/SettingsSerializer.cpp
)
add_library(${PROJECT_NAME} STATIC ${SOURCES})
M module-services/service-bluetooth/ServiceBluetooth.cpp => module-services/service-bluetooth/ServiceBluetooth.cpp +62 -21
@@ 15,6 15,7 @@
#include <service-db/Settings.hpp>
#include "service-bluetooth/messages/Status.hpp"
#include "service-bluetooth/messages/SetStatus.hpp"
+#include <service-bluetooth/messages/BondedDevices.hpp>
#include <log/log.hpp>
@@ 24,7 25,7 @@
ServiceBluetooth::ServiceBluetooth() : sys::Service(service::name::bluetooth)
{
auto settings = std::make_unique<settings::Settings>(this);
- settingsHolder = std::make_unique<Bluetooth::SettingsHolder>(std::move(settings));
+ settingsHolder = std::make_shared<Bluetooth::SettingsHolder>(std::move(settings));
LOG_INFO("[ServiceBluetooth] Initializing");
}
@@ 39,8 40,54 @@ sys::ReturnCodes ServiceBluetooth::InitHandler()
{
LOG_ERROR("Bluetooth experimental!");
worker = std::make_unique<BluetoothWorker>(this);
- btStatus.state = BluetoothStatus::BluetoothState::On;
- btStatus.visibility = true;
+
+ connect(message::bluetooth::RequestBondedDevices(), [&](sys::Message *msg) {
+ auto bondedDevicesStr =
+ std::visit(Bluetooth::StringVisitor(), this->settingsHolder->getValue(Bluetooth::Settings::BondedDevices));
+
+ return std::make_shared<message::bluetooth::ResponseBondedDevices>(
+ SettingsSerializer::fromString(bondedDevicesStr));
+ });
+
+ connect(message::bluetooth::RequestStatus(), [&](sys::Message *msg) {
+ BluetoothStatus status;
+
+ auto state = std::visit(Bluetooth::IntVisitor(), settingsHolder->getValue(Bluetooth::Settings::State));
+ auto visibility =
+ std::visit(Bluetooth::BoolVisitor(), settingsHolder->getValue(Bluetooth::Settings::Visibility));
+ status.state = static_cast<BluetoothStatus::State>(state);
+ status.visibility = visibility;
+
+ return std::make_shared<message::bluetooth::ResponseStatus>(status);
+ });
+
+ connect(typeid(message::bluetooth::SetStatus), [&](sys::Message *msg) {
+ auto setStatusMsg = static_cast<message::bluetooth::SetStatus *>(msg);
+ auto btStatus = setStatusMsg->getStatus();
+ worker->setVisibility(btStatus.visibility);
+
+ switch (btStatus.state) {
+ case BluetoothStatus::State::On:
+ worker->run();
+ break;
+ case BluetoothStatus::State::Off:
+ // TODO
+ break;
+ default:
+ break;
+ }
+
+ return std::make_shared<message::bluetooth::ResponseStatus>(btStatus);
+ });
+
+ settingsHolder->onStateChange = [this]() {
+ auto initialState =
+ std::visit(Bluetooth::IntVisitor(), this->settingsHolder->getValue(Bluetooth::Settings::State));
+ if (static_cast<BluetoothStatus::State>(initialState) == BluetoothStatus::State::On) {
+ this->worker->run();
+ }
+ };
+
return sys::ReturnCodes::Success;
}
@@ 52,17 99,6 @@ sys::ReturnCodes ServiceBluetooth::DeinitHandler()
sys::MessagePointer ServiceBluetooth::DataReceivedHandler(sys::DataMessage *msg, sys::ResponseMessage *resp)
{
- // mock response on message::bluetooth::RequestStatus
- if (auto requestStatusMsg = dynamic_cast<message::bluetooth::RequestStatus *>(msg); nullptr != requestStatusMsg) {
- sys::Bus::SendUnicast(std::make_shared<message::bluetooth::ResponseStatus>(btStatus), msg->sender, this);
- }
-
- // temporary solution for handling message::bluetooth::SetStatus
- if (auto setStatusMsg = dynamic_cast<message::bluetooth::SetStatus *>(msg); nullptr != setStatusMsg) {
- btStatus = setStatusMsg->getStatus();
- sys::Bus::SendBroadcast(std::make_shared<message::bluetooth::ResponseStatus>(btStatus), this);
- }
-
try {
switch (static_cast<MessageType>(msg->messageType)) {
case MessageType::BluetoothRequest: {
@@ 81,7 117,7 @@ sys::MessagePointer ServiceBluetooth::DataReceivedHandler(sys::DataMessage *msg,
return std::make_shared<sys::ResponseMessage>(sys::ReturnCodes::Failure);
}
case BluetoothMessage::StopScan:
- worker->stopScan();
+ sendWorkerCommand(Bt::StopScan);
break;
case BluetoothMessage::PAN: {
/// TODO request lwip first...
@@ 97,15 133,17 @@ sys::MessagePointer ServiceBluetooth::DataReceivedHandler(sys::DataMessage *msg,
worker->start_pan();
// }
} break;
- case BluetoothMessage::Visible:
- worker->toggleVisibility();
- break;
+ case BluetoothMessage::Visible: {
+ static bool visibility = true;
+ worker->setVisibility(visibility);
+ visibility = !visibility;
+ } break;
case BluetoothMessage::Play:
- worker->establishAudioConnection();
+ sendWorkerCommand(Bt::ConnectAudio);
break;
case BluetoothMessage::Stop:
- worker->disconnectAudioConnection();
+ sendWorkerCommand(Bt::DisconnectAudio);
break;
default:
@@ 139,4 177,7 @@ sys::ReturnCodes ServiceBluetooth::SwitchPowerModeHandler(const sys::ServicePowe
LOG_ERROR("TODO");
return sys::ReturnCodes::Success;
}
-
+void ServiceBluetooth::sendWorkerCommand(Bt::Command command)
+{
+ xQueueSend(workerQueue, &command, portMAX_DELAY);
+}
M module-services/service-bluetooth/service-bluetooth/BluetoothMessage.hpp => module-services/service-bluetooth/service-bluetooth/BluetoothMessage.hpp +1 -1
@@ 21,7 21,7 @@ extern "C"
struct BluetoothStatus
{
- enum class BluetoothState
+ enum class State
{
On,
Off,
M module-services/service-bluetooth/service-bluetooth/ServiceBluetooth.hpp => module-services/service-bluetooth/service-bluetooth/ServiceBluetooth.hpp +3 -2
@@ 29,9 29,10 @@ class ServiceBluetooth : public sys::Service
sys::ReturnCodes InitHandler() override;
sys::ReturnCodes DeinitHandler() override;
virtual sys::ReturnCodes SwitchPowerModeHandler(const sys::ServicePowerMode mode) override;
+ void sendWorkerCommand(Bt::Command command);
+ QueueHandle_t workerQueue = nullptr;
+ std::shared_ptr<Bluetooth::SettingsHolder> settingsHolder;
private:
std::unique_ptr<BluetoothWorker> worker;
- std::unique_ptr<Bluetooth::SettingsHolder> settingsHolder;
- BluetoothStatus btStatus; // will be replaced with settings storage introduced in [EGD-4579]
};
M module-services/service-bluetooth/service-bluetooth/SettingsHolder.cpp => module-services/service-bluetooth/service-bluetooth/SettingsHolder.cpp +17 -9
@@ 2,14 2,14 @@
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "SettingsHolder.hpp"
-#include <log/log.hpp>
namespace Bluetooth
{
std::map<Settings, std::string> SettingsHolder::settingString{
{Settings::DeviceName, settings::Bluetooth::deviceName},
{Settings::Visibility, settings::Bluetooth::deviceVisibility},
- {Settings::Power, settings::Bluetooth::state},
+ {Settings::State, settings::Bluetooth::state},
{Settings::BondedDevices, settings::Bluetooth::bondedDevices},
+ {Settings::BtKeys, settings::Bluetooth::btKeys},
};
auto SettingsHolder::getValue(const Settings setting) -> SettingEntry
@@ 21,25 21,33 @@ namespace Bluetooth
settingsMap[newSetting] = value;
settingsProvider->setValue(settingString[newSetting], std::visit(StringVisitor(), value));
+ LOG_INFO("setting %s set: %s", settingString[newSetting].c_str(), std::visit(StringVisitor(), value).c_str());
}
SettingsHolder::SettingsHolder(std::unique_ptr<settings::Settings> settingsPtr)
: settingsProvider(std::move(settingsPtr))
{
- settingsProvider->registerValueChange(settings::Bluetooth::state, [this](std::string value) {
- setValue(Settings::Power, value);
- this->settingsProvider->unregisterValueChange(settings::Bluetooth::state);
- });
settingsProvider->registerValueChange(settings::Bluetooth::deviceVisibility, [this](std::string value) {
setValue(Settings::Visibility, value);
- this->settingsProvider->unregisterValueChange(settings::Bluetooth::deviceVisibility);
+ settingsProvider->unregisterValueChange(settings::Bluetooth::deviceVisibility);
});
settingsProvider->registerValueChange(settings::Bluetooth::deviceName, [this](std::string value) {
setValue(Settings::DeviceName, value);
- this->settingsProvider->unregisterValueChange(settings::Bluetooth::deviceName);
+ settingsProvider->unregisterValueChange(settings::Bluetooth::deviceName);
});
settingsProvider->registerValueChange(settings::Bluetooth::bondedDevices, [this](std::string value) {
setValue(Settings::BondedDevices, value);
- this->settingsProvider->unregisterValueChange(settings::Bluetooth::bondedDevices);
+ settingsProvider->unregisterValueChange(settings::Bluetooth::bondedDevices);
+ });
+ settingsProvider->registerValueChange(settings::Bluetooth::btKeys, [this](std::string value) {
+ setValue(Settings::BtKeys, value);
+ settingsProvider->unregisterValueChange(settings::Bluetooth::btKeys);
+ });
+ settingsProvider->registerValueChange(settings::Bluetooth::state, [this](std::string value) {
+ setValue(Settings::State, value);
+ settingsProvider->unregisterValueChange(settings::Bluetooth::state);
+ if (onStateChange) {
+ onStateChange();
+ }
});
}
} // namespace Bluetooth
M module-services/service-bluetooth/service-bluetooth/SettingsHolder.hpp => module-services/service-bluetooth/service-bluetooth/SettingsHolder.hpp +41 -3
@@ 1,12 1,13 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
-
+#pragma once
#include <json/json11.hpp>
#include <string>
#include <variant>
#include <service-db/Settings.hpp>
#include <agents/settings/SystemSettings.hpp>
#include <module-utils/Utils.hpp>
+#include "SettingsSerializer.hpp"
namespace Bluetooth
{
@@ 15,8 16,9 @@ namespace Bluetooth
{
DeviceName,
Visibility,
- Power,
- BondedDevices
+ State,
+ BondedDevices,
+ BtKeys
};
constexpr inline auto trueStr = "true";
@@ 39,12 41,48 @@ namespace Bluetooth
}
};
+ struct IntVisitor
+ {
+ auto operator()(const std::string &input) const -> int
+ {
+ int value;
+ utils::toNumeric(input, value);
+ return value;
+ }
+ auto operator()(bool input) const -> int
+ {
+ return input;
+ }
+ auto operator()(int input) const -> int
+ {
+ return input;
+ }
+ };
+
+ struct BoolVisitor
+ {
+ auto operator()(const std::string &input) const -> bool
+ {
+ return input == trueStr;
+ }
+ auto operator()(bool input) const -> bool
+ {
+ return input;
+ }
+ auto operator()(int input) const -> bool
+ {
+ return input != 0;
+ }
+ };
+
class SettingsHolder
{
public:
explicit SettingsHolder(std::unique_ptr<settings::Settings> settingsPtr);
auto getValue(const Settings setting) -> SettingEntry;
void setValue(const Settings &newSetting, const SettingEntry &value);
+ std::function<void()> onStateChange;
+ std::function<void(std::string addr)> onLinkKeyAdded;
private:
static std::map<Settings, std::string> settingString;
A module-services/service-bluetooth/service-bluetooth/SettingsSerializer.cpp => module-services/service-bluetooth/service-bluetooth/SettingsSerializer.cpp +47 -0
@@ 0,0 1,47 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#include "SettingsSerializer.hpp"
+#include "btstack_util.h"
+#include <log/log.hpp>
+
+namespace strings
+{
+ constexpr inline auto addr = "addr";
+ constexpr inline auto name = "name";
+ constexpr inline auto devices = "devices";
+} // namespace strings
+
+auto SettingsSerializer::toString(const std::vector<Devicei> &devices) -> std::string
+{
+ json11::Json::array devicesJson;
+ for (auto &device : devices) {
+ auto deviceEntry =
+ json11::Json::object{{strings::addr, bd_addr_to_str(device.address)}, {strings::name, device.name}};
+ devicesJson.emplace_back(deviceEntry);
+ }
+ json11::Json finalJson = json11::Json::object{{strings::devices, devicesJson}};
+
+ return finalJson.dump();
+}
+auto SettingsSerializer::fromString(const std::string &jsonStr) -> std::vector<Devicei>
+{
+ json11::Json devicesJson;
+ std::string err;
+ devicesJson = json11::Json::parse(jsonStr.c_str(), err);
+ if (!err.empty()) {
+ LOG_ERROR("Failed parsing device string!");
+ return std::vector<Devicei>();
+ }
+ json11::Json::array devicesArray;
+ devicesArray = std::move(devicesJson[strings::devices].array_items());
+
+ std::vector<Devicei> devicesVector;
+ for (auto &device : devicesArray) {
+ Devicei temp;
+ sscanf_bd_addr(device[strings::addr].string_value().c_str(), temp.address);
+ temp.name = device[strings::name].string_value();
+ devicesVector.emplace_back(temp);
+ }
+ return devicesVector;
+}
A module-services/service-bluetooth/service-bluetooth/SettingsSerializer.hpp => module-services/service-bluetooth/service-bluetooth/SettingsSerializer.hpp +14 -0
@@ 0,0 1,14 @@
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
+
+#pragma once
+
+#include <json/json11.hpp>
+#include <Device.hpp>
+
+class SettingsSerializer
+{
+ public:
+ static auto toString(const std::vector<Devicei> &devices) -> std::string;
+ static auto fromString(const std::string &jsonStr) -> std::vector<Devicei>;
+};
M module-services/service-db/agents/settings/SystemSettings.hpp => module-services/service-db/agents/settings/SystemSettings.hpp +1 -0
@@ 21,6 21,7 @@ namespace settings
constexpr inline auto deviceVisibility = "bt_device_visibility";
constexpr inline auto deviceName = "bt_device_name";
constexpr inline auto bondedDevices = "bt_bonded_devices";
+ constexpr inline auto btKeys = "bt_keys";
} // namespace Bluetooth
namespace Cellular
M module-services/service-desktop/endpoints/calllog/CalllogHelper.cpp => module-services/service-desktop/endpoints/calllog/CalllogHelper.cpp +0 -1
@@ 143,7 143,6 @@ auto CalllogHelper::deleteDBEntry(Context &context) -> sys::ReturnCodes
}
},
context);
-
query->setQueryListener(std::move(listener));
DBServiceAPI::GetQuery(ownerServicePtr, db::Interface::Name::Calllog, std::move(query));
return sys::ReturnCodes::Success;
M module-utils/log/Logger.hpp => module-utils/log/Logger.hpp +1 -0
@@ 8,6 8,7 @@
#include "log.hpp"
#include <map>
#include <mutex.hpp>
+#include <string>
namespace Log
{