M module-bluetooth/Bluetooth/BluetoothWorker.cpp => module-bluetooth/Bluetooth/BluetoothWorker.cpp +4 -4
@@ 5,6 5,7 @@
#include "BluetoothWorker.hpp"
#include "BtCommand.hpp"
#include "log/log.hpp"
+#include "interface/BluetoothDriverImpl.hpp"
#include "interface/profiles/A2DP/A2DP.hpp"
#include "interface/profiles/HSP/HSP.hpp"
#include "BtKeysStorage.hpp"
@@ 138,13 139,13 @@ auto BluetoothWorker::run() -> bool
auto BluetoothWorker::handleCommand(QueueHandle_t queue) -> bool
{
- bluetooth::Command command;
- if (xQueueReceive(queue, &command, 0) != pdTRUE) {
+ bluetooth::Command command(bluetooth::Command::Type::None);
+ if (xQueueReceive(queue, static_cast<void *>(&command), 0) != pdTRUE) {
LOG_ERROR("Queue receive failure!");
return false;
}
- switch (command) {
+ switch (command.getType()) {
case bluetooth::Command::PowerOn:
controller->turnOn();
break;
@@ 249,7 250,6 @@ auto BluetoothWorker::handleMessage(uint32_t queueID) -> bool
void BluetoothWorker::setDeviceAddress(bd_addr_t addr)
{
-
currentProfile->setDeviceAddress(addr);
}
M module-bluetooth/Bluetooth/CommandHandler.cpp => module-bluetooth/Bluetooth/CommandHandler.cpp +41 -11
@@ 5,10 5,18 @@
#include <utility>
#include <service-bluetooth/ServiceBluetooth.hpp>
+#include <service-bluetooth/SettingsHolder.hpp>
+
+#include <Service/Service.hpp>
#include "Device.hpp"
#include "BtCommand.hpp"
+extern "C"
+{
+#include <module-bluetooth/lib/btstack/src/btstack_util.h>
+}
+
namespace bluetooth
{
namespace
@@ 22,31 30,35 @@ namespace bluetooth
CommandHandler::CommandHandler(sys::Service *service,
std::shared_ptr<bluetooth::SettingsHolder> settings,
std::shared_ptr<bluetooth::Profile> currentProfile,
- std::shared_ptr<bluetooth::Driver> driver)
+ std::shared_ptr<bluetooth::AbstractDriver> driver)
: service{service}, settings{std::move(settings)}, currentProfile{std::move(currentProfile)}, driver{std::move(
driver)}
{}
Error::Code CommandHandler::handle(Command command)
{
- switch (command) {
- case bluetooth::PowerOn:
+ switch (command.getType()) {
+ case bluetooth::Command::PowerOn:
return Error::Success;
- case bluetooth::StartScan:
+ case bluetooth::Command::StartScan:
return scan();
- case bluetooth::StopScan:
+ case bluetooth::Command::StopScan:
return stopScan();
- case bluetooth::StartPan:
+ case bluetooth::Command::StartPan:
return startPan();
- case bluetooth::VisibilityOn:
+ case bluetooth::Command::Pair:
+ return pair(command.getArgument().value());
+ case bluetooth::Command::VisibilityOn:
return setVisibility(true);
- case bluetooth::VisibilityOff:
+ case bluetooth::Command::VisibilityOff:
return setVisibility(false);
- case bluetooth::ConnectAudio:
+ case bluetooth::Command::ConnectAudio:
return establishAudioConnection();
- case bluetooth::DisconnectAudio:
+ case bluetooth::Command::DisconnectAudio:
return disconnectAudioConnection();
- case bluetooth::PowerOff:
+ case bluetooth::Command::PowerOff:
+ return Error::Success;
+ case bluetooth::Command::None:
return Error::Success;
}
return Error::LibraryError;
@@ 106,4 118,22 @@ namespace bluetooth
currentProfile->disconnect();
return Error::Success;
}
+ Error::Code CommandHandler::pair(CommandArgument arg)
+ {
+ try {
+ auto addrString = std::get<std::string>(arg);
+ bd_addr_t addr;
+ if (sscanf_bd_addr(addrString.c_str(), addr) != 0) {
+ LOG_INFO("Pairing with %s", addrString.c_str());
+ driver->pair(addr);
+ }
+ else {
+ return Error::SystemError;
+ }
+ }
+ catch (const std::bad_variant_access &) {
+ return Error::SystemError;
+ }
+ return Error::Success;
+ }
} // namespace bluetooth
M module-bluetooth/Bluetooth/CommandHandler.hpp => module-bluetooth/Bluetooth/CommandHandler.hpp +44 -15
@@ 7,24 7,52 @@
#include "interface/profiles/Profile.hpp"
#include "interface/BluetoothDriver.hpp"
-#include <service-bluetooth/SettingsHolder.hpp>
-#include <Service/Service.hpp>
-
#include <cstdint>
+namespace sys
+{
+ class Service;
+}
+
namespace bluetooth
{
- enum Command : std::uint8_t
+ class SettingsHolder;
+ using CommandArgument = std::variant<std::string, bool, int>;
+ class Command
{
- StartScan,
- StopScan,
- StartPan,
- VisibilityOn,
- VisibilityOff,
- ConnectAudio,
- DisconnectAudio,
- PowerOn,
- PowerOff,
+ public:
+ enum Type : std::uint8_t
+ {
+ StartScan,
+ StopScan,
+ StartPan,
+ VisibilityOn,
+ VisibilityOff,
+ ConnectAudio,
+ DisconnectAudio,
+ PowerOn,
+ PowerOff,
+ Pair,
+ None,
+ };
+
+ Command(Command::Type type, std::optional<CommandArgument> arg = std::nullopt)
+ : argument(std::move(arg)), type(type)
+ {}
+
+ auto getType() const noexcept -> Command::Type
+ {
+ return type;
+ }
+
+ auto getArgument() const -> std::optional<CommandArgument>
+ {
+ return argument;
+ }
+
+ private:
+ std::optional<CommandArgument> argument;
+ Type type;
};
class AbstractCommandHandler
@@ 41,7 69,7 @@ namespace bluetooth
explicit CommandHandler(sys::Service *service,
std::shared_ptr<bluetooth::SettingsHolder> settings,
std::shared_ptr<bluetooth::Profile> currentProfile,
- std::shared_ptr<bluetooth::Driver> driver);
+ std::shared_ptr<bluetooth::AbstractDriver> driver);
auto handle(Command command) -> Error::Code override;
@@ 52,10 80,11 @@ namespace bluetooth
Error::Code setVisibility(bool visibility);
Error::Code establishAudioConnection();
Error::Code disconnectAudioConnection();
+ Error::Code pair(CommandArgument arg);
sys::Service *service;
std::shared_ptr<bluetooth::SettingsHolder> settings;
std::shared_ptr<bluetooth::Profile> currentProfile;
- std::shared_ptr<Driver> driver;
+ std::shared_ptr<AbstractDriver> driver;
};
} // namespace bluetooth
M module-bluetooth/Bluetooth/WorkerController.cpp => module-bluetooth/Bluetooth/WorkerController.cpp +2 -1
@@ 10,6 10,7 @@
#define BOOST_SML_CFG_DISABLE_MIN_SIZE // GCC10 fix
#include <module-utils/sml/include/boost/sml.hpp>
#include <module-utils/magic_enum/include/magic_enum.hpp>
+#include <stdexcept>
namespace bluetooth
{
@@ 177,7 178,7 @@ namespace bluetooth
void StatefulController::processCommand(Command command)
{
- LOG_INFO("Process command: %s", magic_enum::enum_name(command).data());
+ LOG_INFO("Process command: %s", magic_enum::enum_name(command.getType()).data());
pimpl->sm.process_event(ProcessCommand{command});
}
} // namespace bluetooth
M module-bluetooth/Bluetooth/interface/BluetoothDriver.hpp => module-bluetooth/Bluetooth/interface/BluetoothDriver.hpp +4 -30
@@ 3,9 3,7 @@
#pragma once
-#include <btstack.h>
#include <functional>
-#include "GAP/GAP.hpp"
#include "Error.hpp"
namespace bluetooth
@@ 19,34 17,10 @@ namespace bluetooth
[[nodiscard]] virtual auto init() -> Error::Code = 0;
[[nodiscard]] virtual auto run() -> Error::Code = 0;
[[nodiscard]] virtual auto stop() -> Error::Code = 0;
+ [[nodiscard]] virtual auto scan() -> Error = 0;
+ virtual void stopScan() = 0;
+ virtual void setVisibility(bool visibility) = 0;
+ [[nodiscard]] virtual auto pair(uint8_t *addr, std::uint8_t protectionLevel = 0) -> bool = 0;
virtual void registerErrorCallback(const ErrorCallback &newCallback) = 0;
};
-
- class Driver : public AbstractDriver
- {
- private:
- static hci_transport_config_uart_t config;
- const btstack_run_loop *runLoop;
- btstack_packet_callback_registration_t hci_event_callback_registration;
- std::unique_ptr<bluetooth::GAP> gap;
- static void hci_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
- static void local_version_information_handler(uint8_t *packet);
-#ifdef TARGET_RT1051
- [[maybe_unused]] auto runLoopInitTarget(const btstack_run_loop *runLoop) -> const btstack_uart_block_t *;
-#else
- [[maybe_unused]] auto runLoopInitLinux(const btstack_run_loop *runLoop) -> const btstack_uart_block_t *;
-#endif
-
- public:
- Driver(const btstack_run_loop *runLoop, sys::Service *ownerService);
-
- [[nodiscard]] auto init() -> Error::Code override;
- [[nodiscard]] auto run() -> Error::Code override;
- [[nodiscard]] auto stop() -> Error::Code override;
- void registerErrorCallback(const ErrorCallback &newCallback) override;
- auto scan() -> Error;
- void stopScan();
- void setVisibility(bool visibility);
- auto pair(uint8_t *addr, std::uint8_t protectionLevel = 0) -> bool;
- };
} // namespace bluetooth
R module-bluetooth/Bluetooth/interface/BluetoothDriver.cpp => module-bluetooth/Bluetooth/interface/BluetoothDriverImpl.cpp +1 -1
@@ 1,7 1,7 @@
// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
-#include "BluetoothDriver.hpp"
+#include "BluetoothDriverImpl.hpp"
extern "C"
{
A module-bluetooth/Bluetooth/interface/BluetoothDriverImpl.hpp => module-bluetooth/Bluetooth/interface/BluetoothDriverImpl.hpp +43 -0
@@ 0,0 1,43 @@
+// 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 "BluetoothDriver.hpp"
+
+extern "C"
+{
+#include <btstack.h>
+}
+#include "GAP/GAP.hpp"
+
+namespace bluetooth
+{
+ class Driver : public AbstractDriver
+ {
+ private:
+ static hci_transport_config_uart_t config;
+ const btstack_run_loop *runLoop;
+ btstack_packet_callback_registration_t hci_event_callback_registration;
+ std::unique_ptr<bluetooth::GAP> gap;
+ static void hci_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
+ static void local_version_information_handler(uint8_t *packet);
+#ifdef TARGET_RT1051
+ [[maybe_unused]] auto runLoopInitTarget(const btstack_run_loop *runLoop) -> const btstack_uart_block_t *;
+#else
+ [[maybe_unused]] auto runLoopInitLinux(const btstack_run_loop *runLoop) -> const btstack_uart_block_t *;
+#endif
+
+ public:
+ Driver(const btstack_run_loop *runLoop, sys::Service *ownerService);
+
+ [[nodiscard]] auto init() -> Error::Code override;
+ [[nodiscard]] auto run() -> Error::Code override;
+ [[nodiscard]] auto stop() -> Error::Code override;
+ void registerErrorCallback(const ErrorCallback &newCallback) override;
+ auto scan() -> Error override;
+ void stopScan() override;
+ void setVisibility(bool visibility) override;
+ auto pair(uint8_t *addr, std::uint8_t protectionLevel = 0) -> bool override;
+ };
+} // namespace bluetooth
M module-bluetooth/CMakeLists.txt => module-bluetooth/CMakeLists.txt +1 -1
@@ 9,7 9,7 @@ set(SOURCES
${CMAKE_CURRENT_SOURCE_DIR}/Bluetooth/WorkerController.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Bluetooth/CommandHandler.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Bluetooth/glucode/BluetoothRunLoop.cpp
- ${CMAKE_CURRENT_SOURCE_DIR}/Bluetooth/interface/BluetoothDriver.cpp
+ ${CMAKE_CURRENT_SOURCE_DIR}/Bluetooth/interface/BluetoothDriverImpl.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Bluetooth/BtKeysStorage.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Bluetooth/interface/profiles/GAP/GAP.cpp
${CMAKE_CURRENT_SOURCE_DIR}/Bluetooth/interface/profiles/A2DP/A2DP.cpp
M module-bluetooth/tests/tests-StatefulController.cpp => module-bluetooth/tests/tests-StatefulController.cpp +15 -6
@@ 4,9 4,6 @@
#include <catch2/catch.hpp>
#include "WorkerController.hpp"
-#include "interface/BluetoothDriver.hpp"
-
-#include <iostream>
using namespace bluetooth;
@@ 25,6 22,18 @@ class DriverMock : public AbstractDriver
{
return stopReturnCode;
}
+ Error scan() override
+ {
+ return Error::Success;
+ }
+ void stopScan() override
+ {}
+ void setVisibility(bool visibility) override
+ {}
+ bool pair(uint8_t *addr, std::uint8_t protectionLevel = 0) override
+ {
+ return true;
+ }
void registerErrorCallback(const ErrorCallback &) override
{}
@@ 152,7 161,7 @@ TEST_CASE("Given StatefulController when process command successfully then turne
controller.turnOn();
REQUIRE(controller.isOn());
- controller.processCommand(Command::PowerOn);
+ controller.processCommand(bluetooth::Command(Command::Type::PowerOn));
REQUIRE(controller.isOn());
}
@@ 165,7 174,7 @@ TEST_CASE("Given StatefulController when processing command failed then restarte
controller.turnOn();
REQUIRE(controller.isOn());
- controller.processCommand(Command::PowerOn);
- controller.processCommand(Command::PowerOn);
+ controller.processCommand(bluetooth::Command(Command::Type::PowerOn));
+ controller.processCommand(bluetooth::Command(Command::Type::PowerOn));
REQUIRE(controller.isOn());
}
M module-services/service-bluetooth/ServiceBluetooth.cpp => module-services/service-bluetooth/ServiceBluetooth.cpp +21 -9
@@ 74,16 74,26 @@ sys::ReturnCodes ServiceBluetooth::InitHandler()
enabledFromHarness = true;
LOG_INFO("BT enabled from Harness");
}
- sendWorkerCommand(bluetooth::Command::PowerOn);
+ sendWorkerCommand(bluetooth::Command(bluetooth::Command::Type::PowerOn));
break;
case BluetoothStatus::State::Off:
- sendWorkerCommand(bluetooth::Command::PowerOff);
+ sendWorkerCommand(bluetooth::Command(bluetooth::Command::Type::PowerOff));
enabledFromHarness = false;
break;
default:
break;
}
- sendWorkerCommand(newBtStatus.visibility ? bluetooth::VisibilityOn : bluetooth::VisibilityOff);
+ bluetooth::Command command(newBtStatus.visibility ? bluetooth::Command::Type::VisibilityOn
+ : bluetooth::Command::Type::VisibilityOff);
+ sendWorkerCommand(command);
+ return sys::MessageNone{};
+ });
+
+ connect(typeid(BluetoothPairMessage), [&](sys::Message *msg) {
+ auto pairMsg = static_cast<BluetoothPairMessage *>(msg);
+ auto addr = pairMsg->addr;
+
+ sendWorkerCommand(bluetooth::Command(bluetooth::Command::Type::Pair, addr));
return sys::MessageNone{};
});
@@ 135,10 145,10 @@ sys::MessagePointer ServiceBluetooth::DataReceivedHandler(sys::DataMessage *msg,
case BluetoothMessage::Start:
break;
case BluetoothMessage::Scan:
- sendWorkerCommand(bluetooth::StartScan);
+ sendWorkerCommand(bluetooth::Command(bluetooth::Command::Type::StartScan));
break;
case BluetoothMessage::StopScan:
- sendWorkerCommand(bluetooth::StopScan);
+ sendWorkerCommand(bluetooth::Command(bluetooth::Command::Type::StopScan));
break;
case BluetoothMessage::PAN: {
/// TODO request lwip first...
@@ 151,20 161,22 @@ sys::MessagePointer ServiceBluetooth::DataReceivedHandler(sys::DataMessage *msg,
// else {
/// TODO request PPP
LOG_INFO("Start PAN");
- sendWorkerCommand(bluetooth::StartPan);
+ sendWorkerCommand(bluetooth::Command(bluetooth::Command::Type::StartPan));
// }
} break;
case BluetoothMessage::Visible: {
static bool visibility = true;
- sendWorkerCommand(visibility ? bluetooth::VisibilityOn : bluetooth::VisibilityOff);
+ bluetooth::Command command(visibility ? bluetooth::Command::Type::VisibilityOn
+ : bluetooth::Command::Type::VisibilityOff);
+ sendWorkerCommand(command);
visibility = !visibility;
} break;
case BluetoothMessage::Play:
- sendWorkerCommand(bluetooth::ConnectAudio);
+ sendWorkerCommand(bluetooth::Command(bluetooth::Command::Type::ConnectAudio));
break;
case BluetoothMessage::StopPlayback:
- sendWorkerCommand(bluetooth::DisconnectAudio);
+ sendWorkerCommand(bluetooth::Command(bluetooth::Command::Type::DisconnectAudio));
break;
default:
M module-services/service-bluetooth/service-bluetooth/BluetoothMessage.cpp => module-services/service-bluetooth/service-bluetooth/BluetoothMessage.cpp +4 -0
@@ 7,8 7,12 @@ extern "C"
{
#include <module-bluetooth/lib/btstack/src/btstack_util.h>
}
+#include <utility>
BluetoothAddrMessage::BluetoothAddrMessage(std::string addr) : sys::DataMessage(MessageType::BluetoothAddrResult)
{
sscanf_bd_addr(addr.c_str(), this->addr);
}
+BluetoothPairMessage::BluetoothPairMessage(std::string addr)
+ : sys::DataMessage(MessageType::BluetoothPairResult), addr(std::move(addr))
+{}
M module-services/service-bluetooth/service-bluetooth/BluetoothMessage.hpp => module-services/service-bluetooth/service-bluetooth/BluetoothMessage.hpp +8 -0
@@ 78,6 78,14 @@ class BluetoothAddrMessage : public sys::DataMessage
~BluetoothAddrMessage() override = default;
};
+class BluetoothPairMessage : public sys::DataMessage
+{
+ public:
+ std::string addr;
+ explicit BluetoothPairMessage(std::string addr);
+ ~BluetoothPairMessage() override = default;
+};
+
class BluetoothAudioRegisterMessage : public sys::DataMessage
{
public: