M module-apps/application-settings/ApplicationSettings.cpp => module-apps/application-settings/ApplicationSettings.cpp +3 -2
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include <application-settings/ApplicationSettings.hpp>
@@ 251,7 251,8 @@ namespace app
auto connectResultMsg = static_cast<::message::bluetooth::ConnectResult *>(msg);
auto device = connectResultMsg->getDevice();
- if (connectResultMsg->isSucceed()) {
+ using message::bluetooth::ConnectResult;
+ if (connectResultMsg->getResult() == ConnectResult::Result::Success) {
return sys::MessageNone{};
}
M module-bluetooth/Bluetooth/AbstractController.hpp => module-bluetooth/Bluetooth/AbstractController.hpp +7 -10
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
@@ 18,14 18,13 @@ namespace bluetooth::event
struct ShutDown;
struct Pair;
struct Unpair;
- struct StartRinging;
- struct StopRinging;
- struct StartRouting;
struct StartStream;
struct StopStream;
struct CallAnswered;
struct CallTerminated;
- struct CallStarted;
+ struct CallMissed;
+ struct OutgoingCallStarted;
+ struct IncomingCallStarted;
struct IncomingCallNumber;
struct SignalStrengthData;
struct OperatorNameData;
@@ 35,7 34,6 @@ namespace bluetooth::event
namespace bluetooth
{
-
class AbstractController
{
public:
@@ 54,14 52,13 @@ namespace bluetooth
virtual void handle(const bluetooth::event::ShutDown &evt) = 0;
virtual void handle(const bluetooth::event::Pair &evt) = 0;
virtual void handle(const bluetooth::event::Unpair &evt) = 0;
- virtual void handle(const bluetooth::event::StartRinging &evt) = 0;
- virtual void handle(const bluetooth::event::StopRinging &evt) = 0;
- virtual void handle(const bluetooth::event::StartRouting &evt) = 0;
virtual void handle(const bluetooth::event::StartStream &evt) = 0;
virtual void handle(const bluetooth::event::StopStream &evt) = 0;
virtual void handle(const bluetooth::event::CallAnswered &evt) = 0;
virtual void handle(const bluetooth::event::CallTerminated &evt) = 0;
- virtual void handle(const bluetooth::event::CallStarted &evt) = 0;
+ virtual void handle(const bluetooth::event::CallMissed &evt) = 0;
+ virtual void handle(const bluetooth::event::OutgoingCallStarted &evt) = 0;
+ virtual void handle(const bluetooth::event::IncomingCallStarted &evt) = 0;
virtual void handle(const bluetooth::event::IncomingCallNumber &evt) = 0;
virtual void handle(const bluetooth::event::SignalStrengthData &evt) = 0;
virtual void handle(const bluetooth::event::OperatorNameData &evt) = 0;
M module-bluetooth/Bluetooth/BluetoothStateMachine.hpp => module-bluetooth/Bluetooth/BluetoothStateMachine.hpp +53 -53
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
@@ 43,7 43,7 @@ namespace bluetooth
throw std::runtime_error("shouldn't happen");
}
// printf("driver: 0x%X %d\n", driver.get(), int(driver.use_count()));
- if (const auto status = driver->init(); status != Error::Success) {
+ if (const auto status = driver->init(); status != Result::Code::Success) {
throw InitializationError{"Unable to initialize a bluetooth driver."};
}
}
@@ 75,7 75,7 @@ namespace bluetooth
{
void operator()(DeviceRegistrationFunction registerDevice, InitializationState &data)
{
- if (const auto status = registerDevice(); status != Error::Success) {
+ if (const auto status = registerDevice(); status != Result::Code::Success) {
throw InitializationError{"Unable to initialize bluetooth"};
}
data.isInitDone = true;
@@ 86,7 86,7 @@ namespace bluetooth
{
void operator()(std::shared_ptr<AbstractDriver> driver)
{
- if (const auto status = driver->run(); status != Error::Success) {
+ if (const auto status = driver->run(); status != Result::Code::Success) {
throw InitializationError{"Unable to run the bluetooth driver"};
}
}
@@ 187,63 187,63 @@ namespace bluetooth
} constexpr HandleUnsetVisibility;
- struct StartRinging
+ struct IncomingCallStarted
{
void operator()(std::shared_ptr<bluetooth::BaseProfileManager> profileManager)
{
- profileManager->startRinging();
+ profileManager->incomingCallStarted();
}
- } constexpr StartRinging;
+ } constexpr IncomingCallStarted;
- struct StopRinging
+ struct IncomingCallNumber
{
- void operator()(std::shared_ptr<bluetooth::BaseProfileManager> profileManager)
+ void operator()(std::shared_ptr<bluetooth::BaseProfileManager> profileManager,
+ bluetooth::event::IncomingCallNumber evt)
{
- profileManager->stopRinging();
+ profileManager->setIncomingCallNumber(evt.number);
}
- } constexpr StopRinging;
+ } constexpr IncomingCallNumber;
- struct InitializeCall
+ struct OutgoingCallStarted
{
- void operator()(std::shared_ptr<bluetooth::BaseProfileManager> profileManager)
+ void operator()(std::shared_ptr<bluetooth::BaseProfileManager> profileManager,
+ bluetooth::event::OutgoingCallStarted evt)
{
- profileManager->initializeCall();
+ profileManager->outgoingCallStarted(evt.number);
}
- } constexpr InitializeCall;
+ } constexpr OutgoingCallStarted;
- struct CallAnswered
+ struct IncomingCallAnswered
{
void operator()(std::shared_ptr<bluetooth::BaseProfileManager> profileManager)
{
- profileManager->callAnswered();
+ profileManager->incomingCallAnswered();
}
- } constexpr CallAnswered;
+ } constexpr IncomingCallAnswered;
- struct TerminateCall
+ struct OutgoingCallAnswered
{
void operator()(std::shared_ptr<bluetooth::BaseProfileManager> profileManager)
{
- profileManager->terminateCall();
+ profileManager->outgoingCallAnswered();
}
- } constexpr TerminateCall;
+ } constexpr OutgoingCallAnswered;
- struct CallStarted
+ struct CallTerminated
{
- void operator()(std::shared_ptr<bluetooth::BaseProfileManager> profileManager,
- bluetooth::event::CallStarted evt)
+ void operator()(std::shared_ptr<bluetooth::BaseProfileManager> profileManager)
{
- profileManager->callStarted(evt.number);
+ profileManager->callTerminated();
}
- } constexpr CallStarted;
+ } constexpr CallTerminated;
- struct IncomingCall
+ struct CallMissed
{
- void operator()(std::shared_ptr<bluetooth::BaseProfileManager> profileManager,
- bluetooth::event::IncomingCallNumber evt)
+ void operator()(std::shared_ptr<bluetooth::BaseProfileManager> profileManager)
{
- profileManager->setIncomingCallNumber(evt.number);
+ profileManager->callMissed();
}
- } constexpr IncomingCall;
+ } constexpr CallMissed;
struct SignalStrength
{
@@ 314,26 314,24 @@ namespace bluetooth
{
using namespace sml;
// clang-format off
- return make_transition_table(
- *"CallSetup"_s + sml::event<bluetooth::event::StartRinging> / StartRinging = "CallRinging"_s,
- "CallSetup"_s + sml::event<bluetooth::event::StartRouting> / InitializeCall = "CallInitiated"_s,
- "CallSetup"_s + sml::event<bluetooth::event::CallStarted> / CallStarted = "CallInitiated"_s,
- "CallSetup"_s + sml::event<bluetooth::event::IncomingCallNumber> / (StartRinging, IncomingCall) = "CallRinging"_s,
-
- "CallRinging"_s + sml::event<bluetooth::event::StopRinging> / StopRinging = "CallDropped"_s,
- "CallRinging"_s + sml::event<bluetooth::event::CallAnswered> / CallAnswered = "CallInProgress"_s,
- "CallRinging"_s + sml::event<bluetooth::event::CallTerminated> / TerminateCall = "CallDropped"_s,
+ return make_transition_table(
+ *"CallSetup"_s + sml::event<bluetooth::event::IncomingCallStarted> / IncomingCallStarted = "CallRinging"_s,
+ "CallSetup"_s + sml::event<bluetooth::event::IncomingCallNumber> / (IncomingCallStarted, IncomingCallNumber) = "CallRinging"_s,
+ "CallSetup"_s + sml::event<bluetooth::event::OutgoingCallStarted> / OutgoingCallStarted = "CallInitiated"_s,
- "CallInitiated"_s + sml::event<bluetooth::event::CallAnswered> / CallAnswered = "CallInProgress"_s,
- "CallInitiated"_s + sml::event<bluetooth::event::StopRinging> / StopRinging = "CallDropped"_s,
- "CallInitiated"_s + sml::event<bluetooth::event::CallTerminated> / TerminateCall = "CallDropped"_s,
- "CallInitiated"_s + sml::event<bluetooth::event::IncomingCallNumber> / IncomingCall= "CallInitiated"_s,
+ "CallRinging"_s + sml::event<bluetooth::event::IncomingCallNumber> / IncomingCallNumber = "CallRinging"_s,
+ "CallRinging"_s + sml::event<bluetooth::event::CallAnswered> / IncomingCallAnswered = "CallInProgress"_s,
+ "CallRinging"_s + sml::event<bluetooth::event::CallTerminated> / CallTerminated = "CallEnded"_s,
+ "CallRinging"_s + sml::event<bluetooth::event::CallMissed> / CallMissed = "CallEnded"_s,
- "CallInProgress"_s + sml::event<bluetooth::event::CallTerminated> / TerminateCall = "CallDropped"_s,
+ "CallInitiated"_s + sml::event<bluetooth::event::CallAnswered> / OutgoingCallAnswered = "CallInProgress"_s,
+ "CallInitiated"_s + sml::event<bluetooth::event::CallTerminated> / CallTerminated = "CallEnded"_s,
- "CallDropped"_s = X
+ "CallInProgress"_s + sml::event<bluetooth::event::CallTerminated> / CallTerminated = "CallEnded"_s,
- );
+ "CallEnded"_s = X
+ );
+ // clang-format on
}
};
@@ 342,7 340,10 @@ namespace bluetooth
{
auto operator()() const
{
- auto forwardEvent = [](const auto &ev, auto &sm, auto &deps, auto &subs){sm.process_event(ev,deps,subs);};
+ const auto forwardEvent = [](const auto &ev, auto &sm, auto &deps, auto &subs) {
+ sm.process_event(ev, deps, subs);
+ };
+
using namespace sml;
// clang-format off
return make_transition_table(
@@ 364,13 365,12 @@ namespace bluetooth
state<Idle> + sml::event<bluetooth::event::StartStream>/ StartAudio = state<Idle>,
state<Idle> + sml::event<bluetooth::event::StopStream>/ StopAudio = state<Idle>,
- state<Idle> + sml::event<bluetooth::event::StartRouting> / forwardEvent= state<Call>,
- state<Idle> + sml::event<bluetooth::event::IncomingCallNumber> / forwardEvent = state<Call>,
- state<Idle> + sml::event<bluetooth::event::CallStarted> / forwardEvent= state<Call>,
+ state<Idle> + sml::event<bluetooth::event::IncomingCallStarted> / forwardEvent = state<Call>,
+ state<Idle> + sml::event<bluetooth::event::IncomingCallNumber> / forwardEvent = state<Call>,
+ state<Idle> + sml::event<bluetooth::event::OutgoingCallStarted> / forwardEvent = state<Call>,
state<Call> = state<Idle> // this one is needed to go out from Call substate properly!
-
- );
+ );
// clang-format on
}
};
M module-bluetooth/Bluetooth/BluetoothWorker.cpp => module-bluetooth/Bluetooth/BluetoothWorker.cpp +3 -3
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include <service-bluetooth/ServiceBluetooth.hpp>
@@ 36,7 36,7 @@ namespace queues
namespace
{
- constexpr auto BluetoothWorkerStackDepth = 4096U;
+ constexpr auto BluetoothWorkerStackDepth = 1024 * 4;
class DeviceRegistration
{
@@ 61,7 61,7 @@ namespace
bluetooth::set_name(settingsName);
settings->onLinkKeyAdded = onLinkKeyAdded;
- return bluetooth::Error::Success;
+ return bluetooth::Result::Code::Success;
}
private:
M module-bluetooth/Bluetooth/BtCommand.hpp => module-bluetooth/Bluetooth/BtCommand.hpp +3 -4
@@ 1,13 1,12 @@
-// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
-#include "Error.hpp"
-
+#include "Result.hpp"
#include <string>
namespace bluetooth
{
- auto set_name(std::string &name) -> Error;
+ auto set_name(std::string &name) -> Result;
} // namespace bluetooth
M module-bluetooth/Bluetooth/CommandHandler.cpp => module-bluetooth/Bluetooth/CommandHandler.cpp +23 -23
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "CommandHandler.hpp"
@@ 23,7 23,7 @@ namespace bluetooth
{
namespace
{
- [[nodiscard]] auto toString(bluetooth::Error::Code code) -> std::string
+ [[nodiscard]] auto toString(bluetooth::Result::Code code) -> std::string
{
return utils::enumToString(code);
}
@@ 39,72 39,72 @@ namespace bluetooth
this->driver->registerPowerOnCallback([profilePtr = this->profileManager]() { profilePtr->init(); });
}
- Error::Code CommandHandler::scan()
+ Result::Code CommandHandler::scan()
{
- if (const auto ret = driver->scan(); ret.err != bluetooth::Error::Success) {
- LOG_ERROR("Cant start scan!: %s %" PRIu32 "", toString(ret.err).c_str(), ret.lib_code);
- return ret.err;
+ if (const auto ret = driver->scan(); ret.result != bluetooth::Result::Code::Success) {
+ LOG_ERROR("Can't start scan!: %s %d", toString(ret.result).c_str(), ret.libraryResult);
+ return ret.result;
}
LOG_INFO("Scan started!");
// open new scan window
- return Error::Success;
+ return Result::Code::Success;
}
- Error::Code CommandHandler::stopScan()
+ Result::Code CommandHandler::stopScan()
{
LOG_INFO("Stopping scan!");
driver->stopScan();
- return Error::Success;
+ return Result::Code::Success;
}
- Error::Code CommandHandler::setVisibility(bool visibility)
+ Result::Code CommandHandler::setVisibility(bool visibility)
{
driver->setVisibility(visibility);
settings->setValue(bluetooth::Settings::Visibility, static_cast<int>(visibility));
- return Error::Success;
+ return Result::Code::Success;
}
- Error::Code CommandHandler::connect(const DataVariant &data)
+ Result::Code CommandHandler::connect(const DataVariant &data)
{
auto device = std::get<Devicei>(data);
LOG_INFO("Connecting device");
profileManager->connect(device);
- return Error::Success;
+ return Result::Code::Success;
}
- Error::Code CommandHandler::disconnect()
+ Result::Code CommandHandler::disconnect()
{
LOG_INFO("Disconnecting device");
profileManager->disconnect();
- return Error::Success;
+ return Result::Code::Success;
}
- Error::Code CommandHandler::pair(const DataVariant &data)
+
+ Result::Code CommandHandler::pair(const DataVariant &data)
{
auto device = std::get<Devicei>(data);
LOG_INFO("Pairing...");
- auto errorCode = Error::Code::Success;
+ auto errorCode = Result::Code::Success;
driver->pair(device);
LOG_INFO("Pairing result: %s", magic_enum::enum_name(errorCode).data());
return errorCode;
}
- Error::Code CommandHandler::unpair(const DataVariant &data)
+
+ Result::Code CommandHandler::unpair(const DataVariant &data)
{
auto device = std::get<Devicei>(data);
LOG_INFO("Unpairing...");
- const auto errorCode = Error::Code::Success;
+ const auto errorCode = Result::Code::Success;
driver->unpair(device);
LOG_INFO("Unpairing result: %s", magic_enum::enum_name(errorCode).data());
return errorCode;
}
- Error::Code CommandHandler::availableDevices()
+ Result::Code CommandHandler::availableDevices()
{
auto msg = std::make_shared<message::bluetooth::ResponseVisibleDevices>(bluetooth::GAP::getDevicesList());
static_cast<ServiceBluetooth *>(service)->bus.sendUnicast(std::move(msg), service::name::service_desktop);
-
- return Error::Success;
+ return Result::Code::Success;
}
-
} // namespace bluetooth
M module-bluetooth/Bluetooth/CommandHandler.hpp => module-bluetooth/Bluetooth/CommandHandler.hpp +18 -18
@@ 1,9 1,9 @@
-// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
-#include "Error.hpp"
+#include "Result.hpp"
#include "interface/profiles/ProfileManager.hpp"
#include "interface/BluetoothDriver.hpp"
@@ 27,14 27,14 @@ namespace bluetooth
public:
virtual ~AbstractCommandHandler() noexcept = default;
- virtual Error::Code scan() = 0;
- virtual Error::Code stopScan() = 0;
- virtual Error::Code setVisibility(bool visibility) = 0;
- virtual Error::Code connect(const DataVariant &data) = 0;
- virtual Error::Code disconnect() = 0;
- virtual Error::Code pair(const DataVariant &data) = 0;
- virtual Error::Code unpair(const DataVariant &data) = 0;
- virtual Error::Code availableDevices() = 0;
+ virtual Result::Code scan() = 0;
+ virtual Result::Code stopScan() = 0;
+ virtual Result::Code setVisibility(bool visibility) = 0;
+ virtual Result::Code connect(const DataVariant &data) = 0;
+ virtual Result::Code disconnect() = 0;
+ virtual Result::Code pair(const DataVariant &data) = 0;
+ virtual Result::Code unpair(const DataVariant &data) = 0;
+ virtual Result::Code availableDevices() = 0;
};
class CommandHandler : public AbstractCommandHandler
@@ 45,14 45,14 @@ namespace bluetooth
std::shared_ptr<bluetooth::BaseProfileManager> profileManager,
std::shared_ptr<bluetooth::AbstractDriver> driver);
- Error::Code scan() override;
- Error::Code stopScan() override;
- Error::Code setVisibility(bool visibility) override;
- Error::Code connect(const DataVariant &data) override;
- Error::Code disconnect() override;
- Error::Code pair(const DataVariant &data) override;
- Error::Code unpair(const DataVariant &data) override;
- Error::Code availableDevices() override;
+ Result::Code scan() override;
+ Result::Code stopScan() override;
+ Result::Code setVisibility(bool visibility) override;
+ Result::Code connect(const DataVariant &data) override;
+ Result::Code disconnect() override;
+ Result::Code pair(const DataVariant &data) override;
+ Result::Code unpair(const DataVariant &data) override;
+ Result::Code availableDevices() override;
private:
sys::Service *service;
R module-bluetooth/Bluetooth/Error.hpp => module-bluetooth/Bluetooth/Result.hpp +10 -11
@@ 1,28 1,27 @@
-// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
#include <cstdint>
-#include <variant>
-#include <optional>
namespace bluetooth
{
-
- struct Error
+ struct Result
{
- enum Code
+ enum class Code
{
Success,
NotReady,
SystemError,
LibraryError,
- } err = Success;
- uint32_t lib_code = 0;
- Error(enum Code err = Success, int lib_code = Success) : err(err)
+ };
+
+ Code result;
+ int libraryResult;
+
+ explicit Result(Code result = Code::Success, int libraryResult = 0)
+ : result(result), libraryResult(libraryResult)
{}
};
-
} // namespace bluetooth
-const char *c_str(bluetooth::Error::Code code);
M module-bluetooth/Bluetooth/WorkerController.cpp => module-bluetooth/Bluetooth/WorkerController.cpp +31 -12
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "BluetoothStateMachine.hpp"
@@ 42,98 42,117 @@ namespace bluetooth
{
pimpl->sm.process_event(evt);
};
+
void StatefulController::handle(const bluetooth::event::StopScan &evt)
{
pimpl->sm.process_event(evt);
};
+
void StatefulController::handle(const bluetooth::event::GetDevicesAvailable &evt)
{
pimpl->sm.process_event(evt);
};
+
void StatefulController::handle(const bluetooth::event::VisibilityOn &evt)
{
pimpl->sm.process_event(evt);
};
+
void StatefulController::handle(const bluetooth::event::VisibilityOff &evt)
{
pimpl->sm.process_event(evt);
};
+
void StatefulController::handle(const bluetooth::event::Connect &evt)
{
pimpl->sm.process_event(evt);
};
+
void StatefulController::handle(const bluetooth::event::Disconnect &evt)
{
pimpl->sm.process_event(evt);
};
+
void StatefulController::handle(const bluetooth::event::PowerOn &evt)
{
pimpl->sm.process_event(evt);
};
+
void StatefulController::handle(const bluetooth::event::PowerOff &evt)
{
pimpl->sm.process_event(evt);
};
+
void StatefulController::handle(const bluetooth::event::ShutDown &evt)
{
pimpl->sm.process_event(evt);
};
+
void StatefulController::handle(const bluetooth::event::Pair &evt)
{
pimpl->sm.process_event(evt);
};
+
void StatefulController::handle(const bluetooth::event::Unpair &evt)
{
pimpl->sm.process_event(evt);
};
- void StatefulController::handle(const bluetooth::event::StartRinging &evt)
- {
- pimpl->sm.process_event(evt);
- };
- void StatefulController::handle(const bluetooth::event::StopRinging &evt)
+
+ void StatefulController::handle(const bluetooth::event::StartStream &evt)
{
pimpl->sm.process_event(evt);
};
- void StatefulController::handle(const bluetooth::event::StartRouting &evt)
+
+ void StatefulController::handle(const bluetooth::event::StopStream &evt)
{
pimpl->sm.process_event(evt);
};
- void StatefulController::handle(const bluetooth::event::StartStream &evt)
+
+ void StatefulController::handle(const bluetooth::event::CallAnswered &evt)
{
pimpl->sm.process_event(evt);
};
- void StatefulController::handle(const bluetooth::event::StopStream &evt)
+
+ void StatefulController::handle(const bluetooth::event::CallTerminated &evt)
{
pimpl->sm.process_event(evt);
};
- void StatefulController::handle(const bluetooth::event::CallAnswered &evt)
+
+ void StatefulController::handle(const bluetooth::event::CallMissed &evt)
{
pimpl->sm.process_event(evt);
};
- void StatefulController::handle(const bluetooth::event::CallTerminated &evt)
+
+ void StatefulController::handle(const bluetooth::event::OutgoingCallStarted &evt)
{
pimpl->sm.process_event(evt);
};
- void StatefulController::handle(const bluetooth::event::CallStarted &evt)
+
+ void StatefulController::handle(const bluetooth::event::IncomingCallStarted &evt)
{
pimpl->sm.process_event(evt);
};
+
void StatefulController::handle(const bluetooth::event::IncomingCallNumber &evt)
{
pimpl->sm.process_event(evt);
};
+
void StatefulController::handle(const bluetooth::event::SignalStrengthData &evt)
{
pimpl->sm.process_event(evt);
};
+
void StatefulController::handle(const bluetooth::event::OperatorNameData &evt)
{
pimpl->sm.process_event(evt);
};
+
void StatefulController::handle(const bluetooth::event::BatteryLevelData &evt)
{
pimpl->sm.process_event(evt);
};
+
void StatefulController::handle(const bluetooth::event::NetworkStatusData &evt)
{
pimpl->sm.process_event(evt);
M module-bluetooth/Bluetooth/WorkerController.hpp => module-bluetooth/Bluetooth/WorkerController.hpp +5 -6
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
@@ 13,7 13,7 @@
namespace bluetooth
{
- using DeviceRegistrationFunction = std::function<Error::Code()>;
+ using DeviceRegistrationFunction = std::function<Result::Code()>;
class StatefulController : public AbstractController
{
@@ 45,14 45,13 @@ namespace bluetooth
void handle(const bluetooth::event::ShutDown &evt) override;
void handle(const bluetooth::event::Pair &evt) override;
void handle(const bluetooth::event::Unpair &evt) override;
- void handle(const bluetooth::event::StartRinging &evt) override;
- void handle(const bluetooth::event::StopRinging &evt) override;
- void handle(const bluetooth::event::StartRouting &evt) override;
void handle(const bluetooth::event::StartStream &evt) override;
void handle(const bluetooth::event::StopStream &evt) override;
void handle(const bluetooth::event::CallAnswered &evt) override;
void handle(const bluetooth::event::CallTerminated &evt) override;
- void handle(const bluetooth::event::CallStarted &evt) override;
+ void handle(const bluetooth::event::CallMissed &evt) override;
+ void handle(const bluetooth::event::OutgoingCallStarted &evt) override;
+ void handle(const bluetooth::event::IncomingCallStarted &evt) override;
void handle(const bluetooth::event::IncomingCallNumber &evt) override;
void handle(const bluetooth::event::SignalStrengthData &evt) override;
void handle(const bluetooth::event::OperatorNameData &evt) override;
M module-bluetooth/Bluetooth/command/event/Events.hpp => module-bluetooth/Bluetooth/command/event/Events.hpp +82 -68
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
@@ 13,7 13,7 @@ namespace bluetooth::event
{
struct Base
{
- virtual void dispatch(bluetooth::AbstractController *controler) const = 0;
+ virtual void dispatch(bluetooth::AbstractController *controller) const = 0;
virtual ~Base() = default;
protected:
@@ 22,210 22,224 @@ namespace bluetooth::event
struct StartScan : public Base
{
- void dispatch(bluetooth::AbstractController *controler) const override
+ void dispatch(bluetooth::AbstractController *controller) const override
{
- controler->handle(*this);
+ controller->handle(*this);
}
};
struct StopScan : public Base
{
- void dispatch(bluetooth::AbstractController *controler) const override
+ void dispatch(bluetooth::AbstractController *controller) const override
{
- controler->handle(*this);
+ controller->handle(*this);
}
};
+
struct GetDevicesAvailable : public Base
{
- void dispatch(bluetooth::AbstractController *controler) const override
+ void dispatch(bluetooth::AbstractController *controller) const override
{
- controler->handle(*this);
+ controller->handle(*this);
}
};
+
struct VisibilityOn : public Base
{
- void dispatch(bluetooth::AbstractController *controler) const override
+ void dispatch(bluetooth::AbstractController *controller) const override
{
- controler->handle(*this);
+ controller->handle(*this);
}
};
+
struct VisibilityOff : public Base
{
- void dispatch(bluetooth::AbstractController *controler) const override
+ void dispatch(bluetooth::AbstractController *controller) const override
{
- controler->handle(*this);
+ controller->handle(*this);
}
};
+
struct Connect : public Base
{
explicit Connect(const Devicei &dev) : device(dev)
{}
const Devicei device;
- void dispatch(bluetooth::AbstractController *controler) const override
+ void dispatch(bluetooth::AbstractController *controller) const override
{
- controler->handle(*this);
+ controller->handle(*this);
}
};
+
struct Disconnect : public Base
{
- void dispatch(bluetooth::AbstractController *controler) const override
+ void dispatch(bluetooth::AbstractController *controller) const override
{
- controler->handle(*this);
+ controller->handle(*this);
}
};
+
struct PowerOn : public Base
{
- void dispatch(bluetooth::AbstractController *controler) const override
+ void dispatch(bluetooth::AbstractController *controller) const override
{
- controler->handle(*this);
+ controller->handle(*this);
}
};
+
struct PowerOff : public Base
{
- void dispatch(bluetooth::AbstractController *controler) const override
+ void dispatch(bluetooth::AbstractController *controller) const override
{
- controler->handle(*this);
+ controller->handle(*this);
}
};
+
struct ShutDown : public Base
{
- void dispatch(bluetooth::AbstractController *controler) const override
+ void dispatch(bluetooth::AbstractController *controller) const override
{
- controler->handle(*this);
+ controller->handle(*this);
}
};
+
struct Pair : public Base
{
- Pair(const Devicei &device) : device(device)
+ explicit Pair(const Devicei &device) : device(device)
{}
const Devicei device;
- void dispatch(bluetooth::AbstractController *controler) const override
+ void dispatch(bluetooth::AbstractController *controller) const override
{
- controler->handle(*this);
+ controller->handle(*this);
}
};
+
struct Unpair : public Base
{
explicit Unpair(const Devicei &device) : device(device)
{}
const Devicei device;
- void dispatch(bluetooth::AbstractController *controler) const override
+ void dispatch(bluetooth::AbstractController *controller) const override
{
- controler->handle(*this);
+ controller->handle(*this);
}
};
- struct StartRinging : public Base
- {
- void dispatch(bluetooth::AbstractController *controler) const override
- {
- controler->handle(*this);
- }
- };
- struct StopRinging : public Base
+ struct StartStream : public Base
{
- void dispatch(bluetooth::AbstractController *controler) const override
+ void dispatch(bluetooth::AbstractController *controller) const override
{
- controler->handle(*this);
+ controller->handle(*this);
}
};
- struct StartRouting : public Base
+
+ struct StopStream : public Base
{
- void dispatch(bluetooth::AbstractController *controler) const override
+ void dispatch(bluetooth::AbstractController *controller) const override
{
- controler->handle(*this);
+ controller->handle(*this);
}
};
- struct StartStream : public Base
+
+ struct CallAnswered : public Base
{
- void dispatch(bluetooth::AbstractController *controler) const override
+ void dispatch(bluetooth::AbstractController *controller) const override
{
- controler->handle(*this);
+ controller->handle(*this);
}
};
- struct StopStream : public Base
+
+ struct CallTerminated : public Base
{
- void dispatch(bluetooth::AbstractController *controler) const override
+ void dispatch(bluetooth::AbstractController *controller) const override
{
- controler->handle(*this);
+ controller->handle(*this);
}
};
- struct CallAnswered : public Base
+
+ struct CallMissed : public Base
{
- void dispatch(bluetooth::AbstractController *controler) const override
+ void dispatch(bluetooth::AbstractController *controller) const override
{
- controler->handle(*this);
+ controller->handle(*this);
}
};
- struct CallTerminated : public Base
+
+ struct OutgoingCallStarted : public Base
{
- void dispatch(bluetooth::AbstractController *controler) const override
+ explicit OutgoingCallStarted(const utils::PhoneNumber &number) : number(number)
+ {}
+ const utils::PhoneNumber number;
+ void dispatch(bluetooth::AbstractController *controller) const override
{
- controler->handle(*this);
+ controller->handle(*this);
}
};
- struct CallStarted : public Base
+
+ struct IncomingCallStarted : public Base
{
- explicit CallStarted(const utils::PhoneNumber &number) : number(number)
- {}
- const utils::PhoneNumber number;
- void dispatch(bluetooth::AbstractController *controler) const override
+ void dispatch(bluetooth::AbstractController *controller) const override
{
- controler->handle(*this);
+ controller->handle(*this);
}
};
+
struct IncomingCallNumber : public Base
{
explicit IncomingCallNumber(utils::PhoneNumber::View &number) : number(number)
{}
const utils::PhoneNumber::View number;
- void dispatch(bluetooth::AbstractController *controler) const override
+ void dispatch(bluetooth::AbstractController *controller) const override
{
- controler->handle(*this);
+ controller->handle(*this);
}
};
+
struct SignalStrengthData : public Base
{
explicit SignalStrengthData(const Store::SignalStrength &strength) : strength(strength)
{}
Store::SignalStrength strength;
- void dispatch(bluetooth::AbstractController *controler) const override
+ void dispatch(bluetooth::AbstractController *controller) const override
{
- controler->handle(*this);
+ controller->handle(*this);
}
};
+
struct OperatorNameData : public Base
{
explicit OperatorNameData(const std::string &name) : name(name)
{}
const std::string name;
- void dispatch(bluetooth::AbstractController *controler) const override
+ void dispatch(bluetooth::AbstractController *controller) const override
{
- controler->handle(*this);
+ controller->handle(*this);
}
};
+
struct BatteryLevelData : public Base
{
explicit BatteryLevelData(unsigned int level) : level(level)
{}
const unsigned int level;
- void dispatch(bluetooth::AbstractController *controler) const override
+ void dispatch(bluetooth::AbstractController *controller) const override
{
- controler->handle(*this);
+ controller->handle(*this);
}
};
+
struct NetworkStatusData : public Base
{
explicit NetworkStatusData(Store::Network::Status status) : status(status)
{}
const Store::Network::Status status;
- void dispatch(bluetooth::AbstractController *controler) const override
+ void dispatch(bluetooth::AbstractController *controller) const override
{
- controler->handle(*this);
+ controller->handle(*this);
}
};
} // namespace bluetooth::event
M module-bluetooth/Bluetooth/interface/BluetoothDriver.hpp => module-bluetooth/Bluetooth/interface/BluetoothDriver.hpp +6 -6
@@ 1,11 1,11 @@
-// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
#include <functional>
#include "Device.hpp"
-#include "Error.hpp"
+#include "Result.hpp"
namespace bluetooth
{
@@ 17,10 17,10 @@ namespace bluetooth
virtual ~AbstractDriver() noexcept = default;
using ErrorCallback = std::function<void(uint8_t)>;
- [[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;
+ [[nodiscard]] virtual auto init() -> Result::Code = 0;
+ [[nodiscard]] virtual auto run() -> Result::Code = 0;
+ [[nodiscard]] virtual auto stop() -> Result::Code = 0;
+ [[nodiscard]] virtual auto scan() -> Result = 0;
virtual void stopScan() = 0;
virtual void setVisibility(bool visibility) = 0;
virtual void pair(Devicei device, std::uint8_t protectionLevel = 0) = 0;
M module-bluetooth/Bluetooth/interface/BluetoothDriverImpl.cpp => module-bluetooth/Bluetooth/interface/BluetoothDriverImpl.cpp +9 -9
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "BluetoothDriverImpl.hpp"
@@ 60,7 60,7 @@ namespace bluetooth
: runLoop{runLoop}, gap{std::make_unique<bluetooth::GAP>(ownerService)}
{}
- auto Driver::init() -> Error::Code
+ auto Driver::init() -> Result::Code
{
btstack_memory_init();
config = {
@@ 88,7 88,7 @@ namespace bluetooth
gap_set_class_of_device(0x64020C);
LOG_DEBUG("BT worker run success");
- return Error::Success;
+ return Result::Code::Success;
}
void Driver::hci_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size)
@@ 167,16 167,16 @@ namespace bluetooth
break;
}
}
- auto Driver::run() -> Error::Code
+ auto Driver::run() -> Result::Code
{
auto ret = hci_power_control(HCI_POWER_ON);
if (ret != 0) {
LOG_ERROR("HCI power on failed, can't start Bluetooth!");
- return Error::LibraryError;
+ return Result::Code::LibraryError;
}
LOG_INFO("HCI turned on - run BtStack loop\n");
btstack_run_loop_execute();
- return Error::Success;
+ return Result::Code::Success;
}
void Driver::registerErrorCallback(const ErrorCallback &newCallback)
@@ 196,7 196,7 @@ namespace bluetooth
powerOnCallback = newCallback;
}
- auto Driver::stop() -> Error::Code
+ auto Driver::stop() -> Result::Code
{
auto ret = hci_power_control(HCI_POWER_OFF);
if (ret != 0) {
@@ 204,9 204,9 @@ namespace bluetooth
}
bluetooth::KeyStorage::settings->setValue(bluetooth::Settings::State,
static_cast<int>(BluetoothStatus::State::Off));
- return ret != 0 ? Error::LibraryError : Error::Success;
+ return ret != 0 ? Result::Code::LibraryError : Result::Code::Success;
}
- auto Driver::scan() -> Error
+ auto Driver::scan() -> Result
{
return gap->scan();
}
M module-bluetooth/Bluetooth/interface/BluetoothDriverImpl.hpp => module-bluetooth/Bluetooth/interface/BluetoothDriverImpl.hpp +6 -6
@@ 1,9 1,10 @@
-// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
#include "BluetoothDriver.hpp"
+#include "GAP/GAP.hpp"
extern "C"
{
@@ 11,7 12,6 @@ extern "C"
#include <hci_transport.h>
#include <hci_transport_h4.h>
}
-#include "GAP/GAP.hpp"
namespace bluetooth
{
@@ 35,13 35,13 @@ namespace bluetooth
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;
+ [[nodiscard]] auto init() -> Result::Code override;
+ [[nodiscard]] auto run() -> Result::Code override;
+ [[nodiscard]] auto stop() -> Result::Code override;
void registerErrorCallback(const ErrorCallback &newCallback) override;
void registerPowerOnCallback(const PowerOnCallback &newCallback) override;
- auto scan() -> Error override;
+ auto scan() -> Result override;
void stopScan() override;
void setVisibility(bool visibility) override;
void pair(Devicei device, std::uint8_t protectionLevel = 0) override;
M module-bluetooth/Bluetooth/interface/profiles/A2DP/A2DP.cpp => module-bluetooth/Bluetooth/interface/profiles/A2DP/A2DP.cpp +177 -175
@@ 1,16 1,12 @@
// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
-//
-// Created by bartek on 14.09.2020.
-//
-
#include "A2DP.hpp"
#include "A2DPImpl.hpp"
#include "AVDTP.hpp"
#include "AVRCP.hpp"
#include <Bluetooth/Device.hpp>
-#include <Bluetooth/Error.hpp>
+#include <Bluetooth/Result.hpp>
#include <log/log.hpp>
#include <Audio/AudioCommon.hpp>
#include <service-audio/AudioMessage.hpp>
@@ 26,6 22,8 @@ extern "C"
#include <btstack_defines.h>
}
+#define ARRAY_LENGTH(x) (sizeof(x) / sizeof((x)[0]))
+
namespace bluetooth
{
A2DP::A2DP() : pimpl(std::make_unique<A2DPImpl>(A2DPImpl()))
@@ 53,8 51,9 @@ namespace bluetooth
A2DP &A2DP::operator=(A2DP &&other) noexcept
{
- if (&other == this)
+ if (&other == this) {
return *this;
+ }
pimpl = std::move(other.pimpl);
other.pimpl = nullptr;
@@ 62,7 61,7 @@ namespace bluetooth
return *this;
}
- auto A2DP::init() -> Error::Code
+ auto A2DP::init() -> Result::Code
{
return pimpl->init();
}
@@ 72,7 71,7 @@ namespace bluetooth
pimpl->setDevice(device);
}
- void A2DP::setOwnerService(const sys::Service *service)
+ void A2DP::setOwnerService(sys::Service *service)
{
pimpl->setOwnerService(service);
}
@@ 102,119 101,116 @@ namespace bluetooth
pimpl->setAudioDevice(std::move(audioDevice));
}
- const sys::Service *A2DP::A2DPImpl::ownerService;
- QueueHandle_t A2DP::A2DPImpl::sourceQueue = nullptr;
- QueueHandle_t A2DP::A2DPImpl::sinkQueue = nullptr;
- DeviceMetadata_t A2DP::A2DPImpl::metadata;
- btstack_packet_callback_registration_t A2DP::A2DPImpl::hciEventCallbackRegistration;
- std::array<std::uint8_t, A2DP::A2DPImpl::SDP_BUFFER_LENGTH> A2DP::A2DPImpl::sdpSourceServiceBuffer;
- std::array<std::uint8_t, A2DP::A2DPImpl::MEDIA_CAP_SIZE> A2DP::A2DPImpl::mediaSbcCodecCapabilities = {
+ std::uint8_t A2DP::A2DPImpl::sdpSourceServiceBuffer[sourceServiceBufferSize];
+ std::uint8_t A2DP::A2DPImpl::mediaSbcCodecCapabilities[] = {
(AVDTP_SBC_44100 << 4) | AVDTP_SBC_STEREO,
0xFF, //(AVDTP_SBC_BLOCK_LENGTH_16 << 4) | (AVDTP_SBC_SUBBANDS_8 << 2) | AVDTP_SBC_ALLOCATION_METHOD_LOUDNESS,
2,
53};
+
std::shared_ptr<BluetoothAudioDevice> A2DP::A2DPImpl::audioDevice;
+ sys::Service *A2DP::A2DPImpl::ownerService = nullptr;
+ Devicei A2DP::A2DPImpl::device;
+
+ btstack_packet_callback_registration_t A2DP::A2DPImpl::hciEventCallbackRegistration;
+
+ QueueHandle_t A2DP::A2DPImpl::sourceQueue = nullptr;
bool A2DP::A2DPImpl::isConnected = false;
- Devicei A2DP::A2DPImpl::device;
- /* LISTING_START(MainConfiguration): Setup Audio Source and AVRCP Target services */
- auto A2DP::A2DPImpl::init() -> Error::Code
+ auto A2DP::A2DPImpl::init() -> Result::Code
{
// request role change on reconnecting headset to always use them in slave mode
hci_set_master_slave_policy(0);
Profile::initL2cap();
- // Initialize A2DP Source.
+
a2dp_source_init();
a2dp_source_register_packet_handler(&sourcePacketHandler);
// Create stream endpoint.
- avdtp_stream_endpoint_t *local_stream_endpoint =
- a2dp_source_create_stream_endpoint(AVDTP_AUDIO,
- AVDTP_CODEC_SBC,
- mediaSbcCodecCapabilities.data(),
- mediaSbcCodecCapabilities.size(),
- AVDTP::sbcCodecConfiguration.data(),
- AVDTP::sbcCodecConfiguration.size());
+ const auto local_stream_endpoint = a2dp_source_create_stream_endpoint(AVDTP_AUDIO,
+ AVDTP_CODEC_SBC,
+ mediaSbcCodecCapabilities,
+ ARRAY_LENGTH(mediaSbcCodecCapabilities),
+ AVDTP::sbcCodecConfiguration.data(),
+ AVDTP::sbcCodecConfiguration.size());
if (local_stream_endpoint == nullptr) {
LOG_INFO("A2DP Source: not enough memory to create local stream endpoint");
- return bluetooth::Error::SystemError;
+ return Result::Code::SystemError;
}
AVRCP::mediaTracker.local_seid = avdtp_local_seid(local_stream_endpoint);
avdtp_source_register_delay_reporting_category(AVRCP::mediaTracker.local_seid);
- AVRCP::init(const_cast<sys::Service *>(ownerService));
+ AVRCP::init(ownerService);
- // Initialize SDP
Profile::initSdp();
- // Create A2DP Source service record and register it with SDP.
- sdpSourceServiceBuffer.fill(0);
+ std::memset(sdpSourceServiceBuffer, 0, sizeof(sdpSourceServiceBuffer));
+
a2dp_source_create_sdp_record(
- sdpSourceServiceBuffer.data(), a2dpSdpRecordHandle, AVDTP_SOURCE_FEATURE_MASK_PLAYER, nullptr, nullptr);
- if (const auto status = sdp_register_service(sdpSourceServiceBuffer.data()); status != ERROR_CODE_SUCCESS) {
- LOG_ERROR("Can't register service. Status %x", status);
+ sdpSourceServiceBuffer, a2dpSdpRecordHandle, AVDTP_SOURCE_FEATURE_MASK_PLAYER, nullptr, nullptr);
+ if (const auto status = sdp_register_service(sdpSourceServiceBuffer); status != ERROR_CODE_SUCCESS) {
+ LOG_ERROR("Can't register service, status 0x%02X", status);
}
- // Create AVRCP target service record and register it with SDP.
- AVRCP::sdpTargetServiceBuffer.fill(0);
+ std::memset(AVRCP::sdpTargetServiceBuffer, 0, sizeof(AVRCP::sdpTargetServiceBuffer));
+
std::uint16_t supportedFeatures = AVRCP_FEATURE_MASK_CATEGORY_PLAYER_OR_RECORDER;
#ifdef AVRCP_BROWSING_ENABLED
supported_features |= AVRCP_FEATURE_MASK_BROWSING;
#endif
avrcp_target_create_sdp_record(
- AVRCP::sdpTargetServiceBuffer.data(), avrcpServiceSdpRecordHandle, supportedFeatures, nullptr, nullptr);
- if (const auto status = sdp_register_service(AVRCP::sdpTargetServiceBuffer.data());
- status != ERROR_CODE_SUCCESS) {
- LOG_ERROR("Can't register service. Status %x", status);
+ AVRCP::sdpTargetServiceBuffer, avrcpServiceSdpRecordHandle, supportedFeatures, nullptr, nullptr);
+ if (const auto status = sdp_register_service(AVRCP::sdpTargetServiceBuffer); status != ERROR_CODE_SUCCESS) {
+ LOG_ERROR("Can't register service, status 0x%02X", status);
}
- // setup AVRCP Controller
- AVRCP::sdpControllerServiceBuffer.fill(0);
- std::uint16_t controllerSupportedFeatures = AVRCP_FEATURE_MASK_CATEGORY_MONITOR_OR_AMPLIFIER;
- avrcp_controller_create_sdp_record(AVRCP::sdpControllerServiceBuffer.data(),
+ std::memset(AVRCP::sdpControllerServiceBuffer, 0, sizeof(AVRCP::sdpControllerServiceBuffer));
+
+ const std::uint16_t controllerSupportedFeatures = AVRCP_FEATURE_MASK_CATEGORY_MONITOR_OR_AMPLIFIER;
+
+ avrcp_controller_create_sdp_record(AVRCP::sdpControllerServiceBuffer,
avrcpControllerSdpRecordHandle,
controllerSupportedFeatures,
nullptr,
nullptr);
- if (const auto status = sdp_register_service(AVRCP::sdpControllerServiceBuffer.data());
- status != ERROR_CODE_SUCCESS) {
+ if (const auto status = sdp_register_service(AVRCP::sdpControllerServiceBuffer); status != ERROR_CODE_SUCCESS) {
LOG_ERROR("Can't register service. Status %x", status);
}
- // Register for HCI events.
hciEventCallbackRegistration.callback = &hciPacketHandler;
hci_add_event_handler(&hciEventCallbackRegistration);
- LOG_INFO("Init done!");
-
- return bluetooth::Error::Success;
+ LOG_INFO("A2DP initialized!");
+ return Result::Code::Success;
}
void A2DP::A2DPImpl::sendMediaPacket()
{
- int numBytesInFrame = btstack_sbc_encoder_sbc_buffer_length();
- int bytesInStorage = AVRCP::mediaTracker.sbc_storage_count;
- std::uint8_t numFrames = bytesInStorage / numBytesInFrame;
+ const auto numBytesInFrame = btstack_sbc_encoder_sbc_buffer_length();
+ const auto bytesInStorage = AVRCP::mediaTracker.sbc_storage_count;
+ const std::uint8_t numFrames = bytesInStorage / numBytesInFrame;
+
a2dp_source_stream_send_media_payload(AVRCP::mediaTracker.a2dp_cid,
AVRCP::mediaTracker.local_seid,
AVRCP::mediaTracker.sbc_storage,
bytesInStorage,
numFrames,
0);
+
AVRCP::mediaTracker.sbc_storage_count = 0;
AVRCP::mediaTracker.sbc_ready_to_send = 0;
}
void A2DP::A2DPImpl::audioTimeoutHandler(btstack_timer_source_t *timer)
{
- auto *context = static_cast<MediaContext *>(btstack_run_loop_get_timer_context(timer));
- btstack_run_loop_set_timer(&context->audio_timer, AUDIO_TIMEOUT_MS);
+ const auto context = static_cast<MediaContext *>(btstack_run_loop_get_timer_context(timer));
+ btstack_run_loop_set_timer(&context->audio_timer, audioTimeoutMs);
btstack_run_loop_add_timer(&context->audio_timer);
- std::uint32_t now = btstack_run_loop_get_time_ms();
+ const auto now = btstack_run_loop_get_time_ms();
- std::uint32_t updatePeriodMs = AUDIO_TIMEOUT_MS;
+ std::uint32_t updatePeriodMs = audioTimeoutMs;
if (context->time_audio_data_sent_in_ms > 0) {
updatePeriodMs = now - context->time_audio_data_sent_in_ms;
}
@@ 229,7 225,7 @@ namespace bluetooth
context->time_audio_data_sent_in_ms = now;
context->samples_ready += numSamples;
- if (context->sbc_ready_to_send != 0u) {
+ if (context->sbc_ready_to_send != 0) {
return;
}
@@ 238,31 234,31 @@ namespace bluetooth
}
if ((context->sbc_storage_count + btstack_sbc_encoder_sbc_buffer_length()) > context->max_media_payload_size) {
- // schedule sending
- context->sbc_ready_to_send = 1;
+ context->sbc_ready_to_send = 1; // schedule sending
a2dp_source_stream_endpoint_request_can_send_now(context->a2dp_cid, context->local_seid);
}
}
void A2DP::A2DPImpl::startTimer(MediaContext *context)
{
- LOG_DEBUG("Timer start");
+ LOG_DEBUG("A2DP timer start");
context->max_media_payload_size =
btstack_min(a2dp_max_media_payload_size(context->a2dp_cid, context->local_seid), SBC_STORAGE_SIZE);
context->sbc_storage_count = 0;
context->sbc_ready_to_send = 0;
context->streaming = 1;
+
btstack_run_loop_remove_timer(&context->audio_timer);
btstack_run_loop_set_timer_handler(&context->audio_timer, audioTimeoutHandler);
btstack_run_loop_set_timer_context(&context->audio_timer, context);
- btstack_run_loop_set_timer(&context->audio_timer, A2DP::A2DPImpl::AUDIO_TIMEOUT_MS);
+ btstack_run_loop_set_timer(&context->audio_timer, audioTimeoutMs);
btstack_run_loop_add_timer(&context->audio_timer);
}
void A2DP::A2DPImpl::stopTimer(MediaContext *context)
{
- LOG_DEBUG("Timer stop");
+ LOG_DEBUG("A2DP timer stop");
context->time_audio_data_sent_in_ms = 0;
context->acc_num_missed_samples = 0;
@@ 270,18 266,15 @@ namespace bluetooth
context->streaming = 1;
context->sbc_storage_count = 0;
context->sbc_ready_to_send = 0;
+
btstack_run_loop_remove_timer(&context->audio_timer);
}
- void A2DP::A2DPImpl::hciPacketHandler(uint8_t packetType,
+ void A2DP::A2DPImpl::hciPacketHandler([[maybe_unused]] uint8_t packetType,
[[maybe_unused]] uint16_t channel,
[[maybe_unused]] uint8_t *packet,
[[maybe_unused]] uint16_t size)
- {
- if (packetType != HCI_EVENT_PACKET) {
- return;
- }
- }
+ {}
void A2DP::A2DPImpl::sourcePacketHandler(uint8_t packetType,
[[maybe_unused]] uint16_t channel,
@@ 296,6 289,7 @@ namespace bluetooth
if (packetType != HCI_EVENT_PACKET) {
return;
}
+
if (hci_event_packet_get_type(packet) != HCI_EVENT_A2DP_META) {
return;
}
@@ 307,38 301,41 @@ namespace bluetooth
status = a2dp_subevent_signaling_connection_established_get_status(packet);
if (status != ERROR_CODE_SUCCESS) {
- LOG_INFO("A2DP Source: Connection failed, status 0x%02x, cid 0x%02x, a2dp_cid 0x%02x ",
+ LOG_INFO("Connection failed, status 0x%02X, cid 0x%02X, a2dp_cid 0x%02X",
status,
cid,
AVRCP::mediaTracker.a2dp_cid);
AVRCP::mediaTracker.a2dp_cid = 0;
-
- auto &busProxy = const_cast<sys::Service *>(ownerService)->bus;
- busProxy.sendUnicast(std::make_shared<message::bluetooth::ConnectResult>(device, false),
- service::name::bluetooth);
+ ownerService->bus.sendUnicast(std::make_shared<message::bluetooth::ConnectResult>(
+ device, message::bluetooth::ConnectResult::Result::Failure),
+ service::name::bluetooth);
break;
}
+
AVRCP::mediaTracker.a2dp_cid = cid;
AVRCP::mediaTracker.volume = 64;
- LOG_INFO("A2DP Source: Connected, a2dp cid 0x%02x, local seid %d",
+ LOG_INFO("Connected, a2dp_cid 0x%02X, local seid 0x%02X",
AVRCP::mediaTracker.a2dp_cid,
AVRCP::mediaTracker.local_seid);
- isConnected = true;
- auto &busProxy = const_cast<sys::Service *>(ownerService)->bus;
device.deviceState = DeviceState::ConnectedAudio;
- // handle proper device matching when connection was initiated by remote device
+ isConnected = true;
+
+ /* Handle proper device matching when connection was initiated by remote device */
a2dp_subevent_signaling_connection_established_get_bd_addr(packet, device.address);
- busProxy.sendUnicast(std::make_shared<message::bluetooth::ConnectResult>(device, true),
- service::name::bluetooth);
+ ownerService->bus.sendUnicast(std::make_shared<message::bluetooth::ConnectResult>(
+ device, message::bluetooth::ConnectResult::Result::Success),
+ service::name::bluetooth);
break;
}
+
case A2DP_SUBEVENT_SIGNALING_MEDIA_CODEC_SBC_CONFIGURATION: {
cid = avdtp_subevent_signaling_media_codec_sbc_configuration_get_avdtp_cid(packet);
if (cid != AVRCP::mediaTracker.a2dp_cid) {
return;
}
+
AVRCP::mediaTracker.remote_seid =
a2dp_subevent_signaling_media_codec_sbc_configuration_get_remote_seid(packet);
@@ 355,31 352,35 @@ namespace bluetooth
a2dp_subevent_signaling_media_codec_sbc_configuration_get_min_bitpool_value(packet);
AVDTP::sbcConfig.maxBitpoolValue =
a2dp_subevent_signaling_media_codec_sbc_configuration_get_max_bitpool_value(packet);
- LOG_INFO("A2DP Source: Received SBC codec configuration, sampling frequency %u, a2dp_cid 0x%02x, local "
- "seid 0x%02x, remote seid 0x%02x",
+
+ LOG_INFO("Received SBC codec configuration, sampling frequency %uHz, a2dp_cid 0x%02X, local seid 0x%02X, "
+ "remote seid 0x%02X",
AVDTP::sbcConfig.samplingFrequency,
cid,
AVRCP::mediaTracker.local_seid,
AVRCP::mediaTracker.remote_seid);
// Adapt Bluetooth spec definition to SBC Encoder expected input
- auto allocation_method =
+ const auto allocation_method =
a2dp_subevent_signaling_media_codec_sbc_configuration_get_allocation_method(packet);
AVDTP::sbcConfig.allocationMethod = static_cast<btstack_sbc_allocation_method_t>(allocation_method - 1);
- auto channel_mode = static_cast<avdtp_channel_mode_t>(
- a2dp_subevent_signaling_media_codec_sbc_configuration_get_channel_mode(packet));
-
AVDTP::sbcConfig.numChannels = 2;
+
+ const auto channel_mode = static_cast<avdtp_channel_mode_t>(
+ a2dp_subevent_signaling_media_codec_sbc_configuration_get_channel_mode(packet));
switch (channel_mode) {
case AVDTP_CHANNEL_MODE_JOINT_STEREO:
AVDTP::sbcConfig.channelMode = SBC_CHANNEL_MODE_JOINT_STEREO;
break;
+
case AVDTP_CHANNEL_MODE_STEREO:
AVDTP::sbcConfig.channelMode = SBC_CHANNEL_MODE_STEREO;
break;
+
case AVDTP_CHANNEL_MODE_DUAL_CHANNEL:
AVDTP::sbcConfig.channelMode = SBC_CHANNEL_MODE_DUAL_CHANNEL;
break;
+
case AVDTP_CHANNEL_MODE_MONO:
AVDTP::sbcConfig.channelMode = SBC_CHANNEL_MODE_MONO;
break;
@@ 394,165 395,165 @@ namespace bluetooth
AVDTP::sbcConfig.samplingFrequency,
AVDTP::sbcConfig.maxBitpoolValue,
AVDTP::sbcConfig.channelMode);
+ } break;
- metadata = DeviceMetadata_t{
- .sampleRate = static_cast<unsigned int>(AVDTP::sbcConfig.samplingFrequency),
- .channels = static_cast<unsigned short>(AVDTP::sbcConfig.numChannels),
- .samplesPerFrame = static_cast<unsigned int>(btstack_sbc_encoder_num_audio_frames()),
- };
-
- break;
- }
-
- case A2DP_SUBEVENT_SIGNALING_DELAY_REPORTING_CAPABILITY:
- LOG_INFO("A2DP Source: remote supports delay report, remote seid %d",
+ case A2DP_SUBEVENT_SIGNALING_DELAY_REPORTING_CAPABILITY: {
+ LOG_INFO("Remote supports delay report, remote seid 0x%02X",
avdtp_subevent_signaling_delay_reporting_capability_get_remote_seid(packet));
- break;
- case A2DP_SUBEVENT_SIGNALING_CAPABILITIES_DONE:
- LOG_INFO("A2DP Source: All capabilities reported, remote seid %d",
+ } break;
+
+ case A2DP_SUBEVENT_SIGNALING_CAPABILITIES_DONE: {
+ LOG_INFO("All capabilities reported, remote seid 0x%02X",
avdtp_subevent_signaling_capabilities_done_get_remote_seid(packet));
- break;
+ } break;
- case A2DP_SUBEVENT_SIGNALING_DELAY_REPORT:
- LOG_INFO("A2DP Source: Received delay report of %d.%0d ms, local seid %d",
+ case A2DP_SUBEVENT_SIGNALING_DELAY_REPORT: {
+ LOG_INFO("Received delay report of %d.%0d ms, local seid 0x%02X",
avdtp_subevent_signaling_delay_report_get_delay_100us(packet) / 10,
avdtp_subevent_signaling_delay_report_get_delay_100us(packet) % 10,
avdtp_subevent_signaling_delay_report_get_local_seid(packet));
- break;
+ } break;
- case A2DP_SUBEVENT_STREAM_ESTABLISHED:
+ case A2DP_SUBEVENT_STREAM_ESTABLISHED: {
a2dp_subevent_stream_established_get_bd_addr(packet, address);
status = a2dp_subevent_stream_established_get_status(packet);
- if (status != 0u) {
- LOG_INFO("A2DP Source: Stream failed, status 0x%02x", status);
+ if (status != ERROR_CODE_SUCCESS) {
+ LOG_INFO("Stream failed, status 0x%02X", status);
break;
}
local_seid = a2dp_subevent_stream_established_get_local_seid(packet);
cid = a2dp_subevent_stream_established_get_a2dp_cid(packet);
- LOG_INFO("A2DP_SUBEVENT_STREAM_ESTABLISHED: a2dp_cid [expected 0x%02x, received 0x%02x], local_seid %d "
- "(expected %d), remote_seid %d (expected %d)",
+
+ LOG_INFO("A2DP_SUBEVENT_STREAM_ESTABLISHED: a2dp_cid [expected 0x%02X, received 0x%02X], local_seid "
+ "[expected 0x%02X, received 0x%02X], remote_seid [expected 0x%02X, received 0x%02X]",
AVRCP::mediaTracker.a2dp_cid,
cid,
- local_seid,
AVRCP::mediaTracker.local_seid,
+ local_seid,
a2dp_subevent_stream_established_get_remote_seid(packet),
AVRCP::mediaTracker.remote_seid);
if (local_seid != AVRCP::mediaTracker.local_seid) {
- LOG_INFO("A2DP Source: Stream failed, wrong local seid %d, expected %d",
+ LOG_INFO("Stream failed, wrong local seid 0x%02X, expected 0x%02X",
local_seid,
AVRCP::mediaTracker.local_seid);
break;
}
- LOG_INFO("A2DP Source: Stream established, a2dp cid 0x%02x, local seid %d, remote seid %d",
+
+ LOG_INFO("Stream established, a2dp_cid 0x%02X, local seid 0x%02X, remote seid 0x%02X",
AVRCP::mediaTracker.a2dp_cid,
AVRCP::mediaTracker.local_seid,
a2dp_subevent_stream_established_get_remote_seid(packet));
- sourceQueue = xQueueCreate(5, sizeof(AudioData_t));
- if (sourceQueue != nullptr) {
- sendAudioEvent(audio::EventType::BluetoothA2DPDeviceState, audio::Event::DeviceState::Connected);
- }
- else {
- LOG_ERROR("failed to create queue!");
+ sourceQueue = xQueueCreate(sourceQueueLength, sizeof(AudioData_t));
+ if (sourceQueue == nullptr) {
+ LOG_ERROR("Failed to create sourceQueue!");
+ break;
}
- break;
+ sendAudioEvent(audio::EventType::BluetoothA2DPDeviceState, audio::Event::DeviceState::Connected);
+ } break;
- case A2DP_SUBEVENT_STREAM_RECONFIGURED:
- status = a2dp_subevent_stream_reconfigured_get_status(packet);
+ case A2DP_SUBEVENT_STREAM_RECONFIGURED: {
local_seid = a2dp_subevent_stream_reconfigured_get_local_seid(packet);
cid = a2dp_subevent_stream_reconfigured_get_a2dp_cid(packet);
+ status = a2dp_subevent_stream_reconfigured_get_status(packet);
- LOG_INFO("A2DP Source: Reconfigured: a2dp_cid [expected 0x%02x, received 0x%02x], local_seid [expected %d, "
- "received %d]",
+ LOG_INFO("Reconfigured, a2dp_cid [expected 0x%02X, received 0x%02X], local_seid [expected 0x%02X, received "
+ "0x%02X], status 0x%02X",
AVRCP::mediaTracker.a2dp_cid,
cid,
AVRCP::mediaTracker.local_seid,
- local_seid);
- LOG_INFO("Status 0x%02x", status);
- break;
+ local_seid,
+ status);
+ } break;
- case A2DP_SUBEVENT_STREAM_STARTED:
+ case A2DP_SUBEVENT_STREAM_STARTED: {
local_seid = a2dp_subevent_stream_started_get_local_seid(packet);
cid = a2dp_subevent_stream_started_get_a2dp_cid(packet);
AVRCP::playInfo.status = AVRCP_PLAYBACK_STATUS_PLAYING;
- if (AVRCP::mediaTracker.avrcp_cid != 0u) {
+ if (AVRCP::mediaTracker.avrcp_cid != 0) {
avrcp_target_set_playback_status(AVRCP::mediaTracker.avrcp_cid, AVRCP::playInfo.status);
}
startTimer(&AVRCP::mediaTracker);
- LOG_INFO(
- "A2DP Source: Stream started: a2dp_cid [expected 0x%02x, received 0x%02x], local_seid [expected %d, "
- "received %d]",
- AVRCP::mediaTracker.a2dp_cid,
- cid,
- AVRCP::mediaTracker.local_seid,
- local_seid);
- break;
- case A2DP_SUBEVENT_STREAMING_CAN_SEND_MEDIA_PACKET_NOW:
- local_seid = a2dp_subevent_streaming_can_send_media_packet_now_get_local_seid(packet);
- cid = a2dp_subevent_signaling_media_codec_sbc_configuration_get_a2dp_cid(packet);
+ LOG_INFO("Stream started: a2dp_cid [expected 0x%02X, received 0x%02X], local_seid [expected 0x%02X, "
+ "received 0x%02X]",
+ AVRCP::mediaTracker.a2dp_cid,
+ cid,
+ AVRCP::mediaTracker.local_seid,
+ local_seid);
+ } break;
+
+ case A2DP_SUBEVENT_STREAMING_CAN_SEND_MEDIA_PACKET_NOW: {
sendMediaPacket();
- break;
+ } break;
- case A2DP_SUBEVENT_STREAM_SUSPENDED:
+ case A2DP_SUBEVENT_STREAM_SUSPENDED: {
local_seid = a2dp_subevent_stream_suspended_get_local_seid(packet);
cid = a2dp_subevent_stream_suspended_get_a2dp_cid(packet);
AVRCP::playInfo.status = AVRCP_PLAYBACK_STATUS_PAUSED;
- if (AVRCP::mediaTracker.avrcp_cid != 0u) {
+ if (AVRCP::mediaTracker.avrcp_cid != 0) {
avrcp_target_set_playback_status(AVRCP::mediaTracker.avrcp_cid, AVRCP::playInfo.status);
}
- LOG_INFO(
- "A2DP Source: Stream paused: a2dp_cid [expected 0x%02x, received 0x%02x], local_seid [expected %d, "
- "received %d]",
- AVRCP::mediaTracker.a2dp_cid,
- cid,
- AVRCP::mediaTracker.local_seid,
- local_seid);
+
+ LOG_INFO("Stream paused: a2dp_cid [expected 0x%02X, received 0x%02X], local_seid [expected 0x%02X, "
+ "received 0x%02X]",
+ AVRCP::mediaTracker.a2dp_cid,
+ cid,
+ AVRCP::mediaTracker.local_seid,
+ local_seid);
stopTimer(&AVRCP::mediaTracker);
- break;
+ } break;
case A2DP_SUBEVENT_STREAM_RELEASED: {
- AVRCP::playInfo.status = AVRCP_PLAYBACK_STATUS_STOPPED;
cid = a2dp_subevent_stream_released_get_a2dp_cid(packet);
local_seid = a2dp_subevent_stream_released_get_local_seid(packet);
- LOG_INFO(
- "A2DP Source: Stream released: a2dp_cid [expected 0x%02x, received 0x%02x], local_seid [expected %d, "
- "received %d]",
- AVRCP::mediaTracker.a2dp_cid,
- cid,
- AVRCP::mediaTracker.local_seid,
- local_seid);
+
+ AVRCP::playInfo.status = AVRCP_PLAYBACK_STATUS_STOPPED;
+
+ LOG_INFO("Stream released: a2dp_cid [expected 0x%02X, received 0x%02X], local_seid [expected 0x%02X, "
+ "received 0x%02X]",
+ AVRCP::mediaTracker.a2dp_cid,
+ cid,
+ AVRCP::mediaTracker.local_seid,
+ local_seid);
+
sendAudioEvent(audio::EventType::BluetoothA2DPDeviceState, audio::Event::DeviceState::Disconnected);
+
if (cid == AVRCP::mediaTracker.a2dp_cid) {
AVRCP::mediaTracker.stream_opened = 0;
- LOG_INFO("A2DP Source: Stream released");
+ LOG_INFO("Stream released");
}
- if (AVRCP::mediaTracker.avrcp_cid != 0u) {
+ if (AVRCP::mediaTracker.avrcp_cid != 0) {
avrcp_target_set_playback_status(AVRCP::mediaTracker.avrcp_cid, AVRCP_PLAYBACK_STATUS_STOPPED);
}
- auto &busProxy = const_cast<sys::Service *>(ownerService)->bus;
- busProxy.sendUnicast(std::make_shared<message::bluetooth::DisconnectResult>(device),
- service::name::bluetooth);
+
+ ownerService->bus.sendUnicast(std::make_shared<message::bluetooth::DisconnectResult>(device),
+ service::name::bluetooth);
+
stopTimer(&AVRCP::mediaTracker);
break;
}
- case A2DP_SUBEVENT_SIGNALING_CONNECTION_RELEASED:
+ case A2DP_SUBEVENT_SIGNALING_CONNECTION_RELEASED: {
cid = a2dp_subevent_signaling_connection_released_get_a2dp_cid(packet);
+
if (cid == AVRCP::mediaTracker.a2dp_cid) {
AVRCP::mediaTracker.avrcp_cid = 0;
AVRCP::mediaTracker.a2dp_cid = 0;
- LOG_INFO("A2DP Source: Signaling released");
+ LOG_INFO("Signaling connection released");
}
+
isConnected = false;
- break;
+ } break;
+
default:
+ LOG_DEBUG("Event not handled: 0x%02X", hci_event_a2dp_meta_get_subevent_code(packet));
break;
}
}
@@ 562,6 563,7 @@ namespace bluetooth
if (isConnected) {
disconnect();
}
+
LOG_INFO("Connecting A2DP profile");
a2dp_source_establish_stream(device.address, &AVRCP::mediaTracker.a2dp_cid);
}
@@ 570,8 572,8 @@ namespace bluetooth
{
LOG_INFO("Disconnecting A2DP profile");
a2dp_source_disconnect(AVRCP::mediaTracker.a2dp_cid);
- auto &busProxy = const_cast<sys::Service *>(ownerService)->bus;
- busProxy.sendUnicast(std::make_shared<message::bluetooth::DisconnectResult>(device), service::name::bluetooth);
+ ownerService->bus.sendUnicast(std::make_shared<message::bluetooth::DisconnectResult>(device),
+ service::name::bluetooth);
}
void A2DP::A2DPImpl::setDevice(const Devicei &dev)
@@ 580,7 582,7 @@ namespace bluetooth
LOG_INFO("Device set!");
}
- void A2DP::A2DPImpl::setOwnerService(const sys::Service *service)
+ void A2DP::A2DPImpl::setOwnerService(sys::Service *service)
{
ownerService = service;
}
@@ 589,9 591,9 @@ namespace bluetooth
{
auto evt = std::make_shared<audio::Event>(event, state);
auto msg = std::make_shared<AudioEventRequest>(std::move(evt));
- auto &busProxy = const_cast<sys::Service *>(ownerService)->bus;
- busProxy.sendUnicast(std::move(msg), service::name::evt_manager);
+ ownerService->bus.sendUnicast(std::move(msg), service::name::evt_manager);
}
+
void A2DP::A2DPImpl::start()
{
if (!isConnected) {
@@ 600,6 602,7 @@ namespace bluetooth
AVRCP::mediaTracker.stream_opened = 1;
a2dp_source_start_stream(AVRCP::mediaTracker.a2dp_cid, AVRCP::mediaTracker.local_seid);
}
+
void A2DP::A2DPImpl::stop()
{
AVRCP::mediaTracker.stream_opened = 1;
@@ 610,15 613,14 @@ namespace bluetooth
{
A2DP::A2DPImpl::audioDevice = std::move(newAudioDevice);
}
+
void A2DP::A2DPImpl::deInit()
{
- LOG_DEBUG("Deinitializing A2DP profile");
-
sdp_unregister_service(a2dpSdpRecordHandle);
sdp_unregister_service(avrcpControllerSdpRecordHandle);
sdp_unregister_service(avrcpServiceSdpRecordHandle);
-
audioDevice.reset();
- }
+ LOG_DEBUG("A2DP deinitialized!");
+ }
} // namespace bluetooth
M module-bluetooth/Bluetooth/interface/profiles/A2DP/A2DP.hpp => module-bluetooth/Bluetooth/interface/profiles/A2DP/A2DP.hpp +3 -3
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
@@ 22,9 22,9 @@ namespace bluetooth
A2DP(A2DP &&other) noexcept;
auto operator=(A2DP &&other) noexcept -> A2DP &;
- auto init() -> Error::Code override;
+ auto init() -> Result::Code override;
void setDevice(const Devicei &device) override;
- void setOwnerService(const sys::Service *service) override;
+ void setOwnerService(sys::Service *service) override;
void connect() override;
void disconnect() override;
M module-bluetooth/Bluetooth/interface/profiles/A2DP/A2DPImpl.hpp => module-bluetooth/Bluetooth/interface/profiles/A2DP/A2DPImpl.hpp +39 -35
@@ 1,16 1,15 @@
-// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
+
#include "A2DP.hpp"
#include <Bluetooth/Device.hpp>
-#include <Bluetooth/Error.hpp>
+#include <Bluetooth/Result.hpp>
#include <log/log.hpp>
#include <Audio/AudioCommon.hpp>
#include <audio/BluetoothAudioDevice.hpp>
-
#include "MediaContext.hpp"
-
#include <memory>
extern "C"
@@ 24,45 23,50 @@ namespace bluetooth
class AVRCP;
class A2DP::A2DPImpl
{
+ public:
+ auto init() -> Result::Code;
+ void deInit();
+ void connect();
+ void disconnect();
+ void start();
+ void stop();
+ void setDevice(const Devicei &dev);
+ void setOwnerService(sys::Service *service);
+ void setAudioDevice(std::shared_ptr<bluetooth::BluetoothAudioDevice> audioDevice);
- static constexpr int NUM_CHANNELS = 2;
- static constexpr int BYTES_PER_AUDIO_SAMPLE = (2 * NUM_CHANNELS);
- static constexpr int AUDIO_TIMEOUT_MS = 10;
- static constexpr int TABLE_SIZE_441HZ = 100;
- static constexpr int SDP_BUFFER_LENGTH = 150;
- static constexpr int MEDIA_CAP_SIZE = 4;
-
- static std::array<uint8_t, SDP_BUFFER_LENGTH> sdpSourceServiceBuffer;
- static btstack_packet_callback_registration_t hciEventCallbackRegistration;
- static std::array<uint8_t, MEDIA_CAP_SIZE> mediaSbcCodecCapabilities;
- static const sys::Service *ownerService;
- static QueueHandle_t sourceQueue;
- static QueueHandle_t sinkQueue;
- static DeviceMetadata_t metadata;
-
+ private:
static void startTimer(MediaContext *context);
static void stopTimer(MediaContext *context);
static void audioTimeoutHandler(btstack_timer_source_t *timer);
- static void sourcePacketHandler(uint8_t packetType, uint16_t channel, uint8_t *packet, uint16_t size);
- static void hciPacketHandler(uint8_t packetType, uint16_t channel, uint8_t *packet, uint16_t size);
+ static void sourcePacketHandler(std::uint8_t packetType,
+ std::uint16_t channel,
+ std::uint8_t *packet,
+ std::uint16_t size);
+ static void hciPacketHandler(std::uint8_t packetType,
+ std::uint16_t channel,
+ std::uint8_t *packet,
+ std::uint16_t size);
static void sendMediaPacket();
static void sendAudioEvent(audio::EventType event, audio::Event::DeviceState state);
- static bool isConnected;
+
+ static constexpr std::uint32_t a2dpSdpRecordHandle = 0x10001;
+ static constexpr std::uint32_t avrcpServiceSdpRecordHandle = 0x10002;
+ static constexpr std::uint32_t avrcpControllerSdpRecordHandle = 0x10003;
+ static constexpr auto sourceServiceBufferSize = 150;
+ static constexpr auto sourceQueueLength = 5;
+ static constexpr int audioTimeoutMs = 10;
+
+ static std::uint8_t sdpSourceServiceBuffer[sourceServiceBufferSize];
+ static std::uint8_t mediaSbcCodecCapabilities[];
+
static std::shared_ptr<BluetoothAudioDevice> audioDevice;
+ static sys::Service *ownerService;
static Devicei device;
- static constexpr uint32_t a2dpSdpRecordHandle = 0x10001;
- static constexpr uint32_t avrcpServiceSdpRecordHandle = 0x10002;
- static constexpr uint32_t avrcpControllerSdpRecordHandle = 0x10003;
- public:
- auto init() -> Error::Code;
- void deInit();
- void connect();
- void disconnect();
- void start();
- void stop();
- void setDevice(const Devicei &dev);
- void setOwnerService(const sys::Service *service);
- void setAudioDevice(std::shared_ptr<bluetooth::BluetoothAudioDevice> audioDevice);
+ static btstack_packet_callback_registration_t hciEventCallbackRegistration;
+
+ static QueueHandle_t sourceQueue;
+
+ static bool isConnected;
};
} // namespace bluetooth
M module-bluetooth/Bluetooth/interface/profiles/A2DP/AVDTP.cpp => module-bluetooth/Bluetooth/interface/profiles/A2DP/AVDTP.cpp +2 -2
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "AVDTP.hpp"
@@ 6,8 6,8 @@
namespace bluetooth
{
AVDTP::SbcConfiguration AVDTP::sbcConfig;
+ std::array<std::uint8_t, AVDTP::sbcCodecConfigurationSize> AVDTP::sbcCodecConfiguration;
btstack_sbc_encoder_state_t AVDTP::sbcEncoderState;
- std::array<uint8_t, 4> AVDTP::sbcCodecConfiguration;
int AVDTP::sampleRate = AVDTP::defaultSampleRate;
void AVDTP::dumpSbcConfiguration()
M module-bluetooth/Bluetooth/interface/profiles/A2DP/AVDTP.hpp => module-bluetooth/Bluetooth/interface/profiles/A2DP/AVDTP.hpp +10 -7
@@ 1,25 1,25 @@
-// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
#include "A2DPImpl.hpp"
+
extern "C"
{
#include <btstack.h>
#include <btstack_defines.h>
#include <classic/avdtp.h>
}
+
namespace bluetooth
{
-
class AVDTP
{
public:
struct SbcConfiguration
{
int reconfigure;
-
int numChannels;
int samplingFrequency;
int blockLength;
@@ 29,12 29,15 @@ namespace bluetooth
btstack_sbc_channel_mode_t channelMode;
btstack_sbc_allocation_method_t allocationMethod;
};
+
+ static void dumpSbcConfiguration();
+
+ static constexpr int defaultSampleRate = 44100;
+ static constexpr auto sbcCodecConfigurationSize = 4;
+
static SbcConfiguration sbcConfig;
+ static std::array<std::uint8_t, sbcCodecConfigurationSize> sbcCodecConfiguration;
static btstack_sbc_encoder_state_t sbcEncoderState;
- static std::array<uint8_t, 4> sbcCodecConfiguration;
- static constexpr int defaultSampleRate = 44100;
static int sampleRate;
-
- static void dumpSbcConfiguration();
};
} // namespace bluetooth
M module-bluetooth/Bluetooth/interface/profiles/A2DP/AVRCP.cpp => module-bluetooth/Bluetooth/interface/profiles/A2DP/AVRCP.cpp +74 -74
@@ 10,35 10,38 @@
namespace bluetooth
{
+ std::uint8_t AVRCP::sdpTargetServiceBuffer[targetServiceBufferSize];
+ std::uint8_t AVRCP::sdpControllerServiceBuffer[controllerServiceBufferSize];
+
+ sys::Service *AVRCP::ownerService = nullptr;
+
AVRCP::PlaybackStatusInfo AVRCP::playInfo;
- int AVRCP::currentTrackIndex;
MediaContext AVRCP::mediaTracker;
- std::array<std::uint8_t, AVRCP::SDP_BUFFER_LENGTH> AVRCP::sdpTargetServiceBuffer;
- std::array<std::uint8_t, AVRCP::SDP_BUFFER_LENGTH> AVRCP::sdpControllerServiceBuffer;
- sys::Service *AVRCP::ownerService = nullptr;
- void AVRCP::packetHandler(uint8_t packetType,
- [[maybe_unused]] uint16_t channel,
- uint8_t *packet,
- [[maybe_unused]] uint16_t size)
+ void AVRCP::packetHandler(std::uint8_t packetType,
+ [[maybe_unused]] std::uint16_t channel,
+ std::uint8_t *packet,
+ [[maybe_unused]] std::uint16_t size)
{
bd_addr_t event_addr;
std::uint16_t local_cid;
- std::uint8_t status = ERROR_CODE_SUCCESS;
if (packetType != HCI_EVENT_PACKET || hci_event_packet_get_type(packet) != HCI_EVENT_AVRCP_META) {
return;
}
const auto subevent_code = hci_event_avrcp_meta_get_subevent_code(packet);
+
switch (subevent_code) {
- case AVRCP_SUBEVENT_CONNECTION_ESTABLISHED:
+ case AVRCP_SUBEVENT_CONNECTION_ESTABLISHED: {
local_cid = avrcp_subevent_connection_established_get_avrcp_cid(packet);
- status = avrcp_subevent_connection_established_get_status(packet);
+ const auto status = avrcp_subevent_connection_established_get_status(packet);
+
if (status != ERROR_CODE_SUCCESS) {
- LOG_INFO("AVRCP: Connection failed, local cid 0x%02x, status 0x%02x", local_cid, status);
- return;
+ LOG_ERROR("Connection failed, local cid 0x%02X, status 0x%02X", local_cid, status);
+ break;
}
+
AVRCP::mediaTracker.avrcp_cid = local_cid;
avrcp_subevent_connection_established_get_bd_addr(packet, event_addr);
@@ 50,135 53,133 @@ namespace bluetooth
avrcp_controller_enable_notification(AVRCP::mediaTracker.avrcp_cid,
AVRCP_NOTIFICATION_EVENT_VOLUME_CHANGED);
- avrcp_target_set_now_playing_info(
- AVRCP::mediaTracker.avrcp_cid, nullptr, sizeof(AVRCP::tracks) / sizeof(avrcp_track_t));
avrcp_target_set_unit_info(AVRCP::mediaTracker.avrcp_cid, AVRCP_SUBUNIT_TYPE_AUDIO, AVRCP::companyId);
avrcp_target_set_subunit_info(AVRCP::mediaTracker.avrcp_cid,
AVRCP_SUBUNIT_TYPE_AUDIO,
static_cast<const std::uint8_t *>(AVRCP::subunitInfo),
sizeof(AVRCP::subunitInfo));
-
avrcp_target_set_playback_status(AVRCP::mediaTracker.avrcp_cid, AVRCP::playInfo.status);
- return;
+ } break;
- case AVRCP_SUBEVENT_CONNECTION_RELEASED:
- LOG_INFO("AVRCP Target: Disconnected, avrcp_cid 0x%02x",
- avrcp_subevent_connection_released_get_avrcp_cid(packet));
+ case AVRCP_SUBEVENT_CONNECTION_RELEASED: {
+ LOG_INFO("Disconnected, avrcp_cid 0x%02X", avrcp_subevent_connection_released_get_avrcp_cid(packet));
AVRCP::mediaTracker.avrcp_cid = 0;
- return;
+ } break;
+
default:
+ LOG_DEBUG("Event not handled: 0x%02X", subevent_code);
break;
}
-
- if (status != ERROR_CODE_SUCCESS) {
- LOG_INFO("Responding to event 0x%02x failed with status 0x%02x", subevent_code, status);
- }
}
- void AVRCP::targetPacketHandler(uint8_t packetType,
- [[maybe_unused]] uint16_t channel,
- uint8_t *packet,
- [[maybe_unused]] uint16_t size)
+ void AVRCP::targetPacketHandler(std::uint8_t packetType,
+ [[maybe_unused]] std::uint16_t channel,
+ std::uint8_t *packet,
+ [[maybe_unused]] std::uint16_t size)
{
- std::uint8_t status = ERROR_CODE_SUCCESS;
-
if (packetType != HCI_EVENT_PACKET || hci_event_packet_get_type(packet) != HCI_EVENT_AVRCP_META) {
return;
}
const auto subevent_code = hci_event_avrcp_meta_get_subevent_code(packet);
+
switch (subevent_code) {
- case AVRCP_SUBEVENT_PLAY_STATUS_QUERY:
- status = avrcp_target_play_status(AVRCP::mediaTracker.avrcp_cid,
- AVRCP::playInfo.song_length_ms,
- AVRCP::playInfo.song_position_ms,
- AVRCP::playInfo.status);
- break;
+ case AVRCP_SUBEVENT_PLAY_STATUS_QUERY: {
+ const auto status = avrcp_target_play_status(AVRCP::mediaTracker.avrcp_cid,
+ AVRCP::playInfo.song_length_ms,
+ AVRCP::playInfo.song_position_ms,
+ AVRCP::playInfo.status);
+ if (status != ERROR_CODE_SUCCESS) {
+ LOG_ERROR("Play status query failed, status: 0x%02X", status);
+ }
+ } break;
+
case AVRCP_SUBEVENT_OPERATION: {
const auto operation_id =
static_cast<avrcp_operation_id_t>(avrcp_subevent_operation_get_operation_id(packet));
+
switch (operation_id) {
case AVRCP_OPERATION_ID_PLAY: {
- LOG_INFO("AVRCP Target: PLAY");
- auto &busProxy = AVRCP::ownerService->bus;
- busProxy.sendUnicast(std::make_shared<message::bluetooth::AudioStart>(), service::name::audio);
- return;
+ LOG_INFO("AVRCP operation: PLAY");
+ ownerService->bus.sendUnicast(std::make_shared<message::bluetooth::AudioStart>(), service::name::audio);
} break;
+
case AVRCP_OPERATION_ID_PAUSE: {
- LOG_INFO("AVRCP Target: PAUSE");
- auto &busProxy = AVRCP::ownerService->bus;
- busProxy.sendUnicast(std::make_shared<message::bluetooth::AudioPause>(), service::name::audio);
- return;
+ LOG_INFO("AVRCP operation: PAUSE");
+ ownerService->bus.sendUnicast(std::make_shared<message::bluetooth::AudioPause>(), service::name::audio);
} break;
- case AVRCP_OPERATION_ID_STOP:
- LOG_INFO("AVRCP Target: STOP");
- status = a2dp_source_disconnect(AVRCP::mediaTracker.a2dp_cid);
- break;
+
+ case AVRCP_OPERATION_ID_STOP: {
+ LOG_INFO("AVRCP operation: STOP");
+ const auto status = a2dp_source_disconnect(AVRCP::mediaTracker.a2dp_cid);
+ if (status != ERROR_CODE_SUCCESS) {
+ LOG_ERROR("Stop request failed, status: 0x%02X", status);
+ }
+ } break;
+
default:
- LOG_INFO("AVRCP Target: operation 0x%2x is not handled", operation_id);
- return;
+ LOG_INFO("Operation not handled: 0x%02X ", operation_id);
+ break;
}
- break;
}
default:
+ LOG_DEBUG("Event not handled: 0x%02X", subevent_code);
break;
}
-
- if (status != ERROR_CODE_SUCCESS) {
- LOG_INFO("Responding to event 0x%02x failed with status 0x%02x", subevent_code, status);
- }
}
- void AVRCP::controllerPacketHandler(uint8_t packetType,
- [[maybe_unused]] uint16_t channel,
- uint8_t *packet,
- [[maybe_unused]] uint16_t size)
+ void AVRCP::controllerPacketHandler(std::uint8_t packetType,
+ [[maybe_unused]] std::uint16_t channel,
+ std::uint8_t *packet,
+ [[maybe_unused]] std::uint16_t size)
{
if (packetType != HCI_EVENT_PACKET || hci_event_packet_get_type(packet) != HCI_EVENT_AVRCP_META) {
return;
}
- if (AVRCP::mediaTracker.avrcp_cid == 0u) {
+ if (AVRCP::mediaTracker.avrcp_cid == 0) {
return;
}
const auto subevent_code = hci_event_avrcp_meta_get_subevent_code(packet);
+
switch (subevent_code) {
- /* BT device requested volume change */
- case AVRCP_SUBEVENT_NOTIFICATION_VOLUME_CHANGED: {
+ case AVRCP_SUBEVENT_NOTIFICATION_VOLUME_CHANGED: { // BT device requested volume change
const auto volume = avrcp_subevent_notification_volume_changed_get_absolute_volume(packet);
- auto &busProxy = AVRCP::ownerService->bus;
- busProxy.sendUnicast(std::make_shared<message::bluetooth::A2DPVolume>(volume), service::name::bluetooth);
+ ownerService->bus.sendUnicast(std::make_shared<message::bluetooth::A2DPVolume>(volume),
+ service::name::bluetooth);
LOG_INFO("AVRCP Controller: BT device volume changed to %u%% (%u)",
AVRCP::controllerVolumeToPercent(volume),
volume);
} break;
- case AVRCP_SUBEVENT_NOTIFICATION_EVENT_BATT_STATUS_CHANGED:
- // see avrcp_battery_status_t
+ case AVRCP_SUBEVENT_NOTIFICATION_EVENT_BATT_STATUS_CHANGED: { // see avrcp_battery_status_t
LOG_INFO("AVRCP Controller: Notification Battery Status %d",
avrcp_subevent_notification_event_batt_status_changed_get_battery_status(packet));
- break;
- case AVRCP_SUBEVENT_NOTIFICATION_STATE:
+ } break;
+
+ case AVRCP_SUBEVENT_NOTIFICATION_STATE: {
LOG_INFO("AVRCP Controller: Notification %s - %s",
avrcp_event2str(avrcp_subevent_notification_state_get_event_id(packet)),
avrcp_subevent_notification_state_get_enabled(packet) != 0 ? "enabled" : "disabled");
- break;
+ } break;
+
default:
break;
}
}
+
void AVRCP::init(sys::Service *service)
{
AVRCP::ownerService = service;
- // Initialize AVRCP Service.
+
avrcp_init();
avrcp_register_packet_handler(&packetHandler);
- // Initialize AVRCP Target.
+
avrcp_target_init();
avrcp_target_register_packet_handler(&targetPacketHandler);
- // Initialize AVRCP Controller
+
avrcp_controller_init();
avrcp_controller_register_packet_handler(&controllerPacketHandler);
}
@@ 192,5 193,4 @@ namespace bluetooth
{
return volume * 100 / AVRCP::maxVolumeValue;
}
-
} // namespace bluetooth
M module-bluetooth/Bluetooth/interface/profiles/A2DP/AVRCP.hpp => module-bluetooth/Bluetooth/interface/profiles/A2DP/AVRCP.hpp +29 -17
@@ 1,8 1,10 @@
-// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
+
#include "A2DPImpl.hpp"
+
extern "C"
{
#include "classic/avrcp.h"
@@ 25,30 27,40 @@ namespace bluetooth
static std::uint16_t controllerVolumeToPercent(std::uint16_t volume);
public:
- static constexpr uint8_t subunitInfo[] = {0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,
- 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7};
- static constexpr uint32_t companyId = 0x112233;
- static constexpr int SDP_BUFFER_LENGTH = 200;
struct PlaybackStatusInfo
{
- uint8_t track_id[8];
- uint32_t song_length_ms;
+ std::uint8_t track_id[8];
+ std::uint32_t song_length_ms;
avrcp_playback_status_t status = AVRCP_PLAYBACK_STATUS_STOPPED;
- uint32_t song_position_ms; // 0xFFFFFFFF if not supported
+ std::uint32_t song_position_ms; // 0xFFFFFFFF if not supported
};
- static std::array<std::uint8_t, SDP_BUFFER_LENGTH> sdpTargetServiceBuffer;
- static std::array<std::uint8_t, SDP_BUFFER_LENGTH> sdpControllerServiceBuffer;
+ static void packetHandler(std::uint8_t packetType,
+ std::uint16_t channel,
+ std::uint8_t *packet,
+ std::uint16_t size);
+ static void targetPacketHandler(std::uint8_t packetType,
+ std::uint16_t channel,
+ std::uint8_t *packet,
+ std::uint16_t size);
+ static void controllerPacketHandler(std::uint8_t packetType,
+ std::uint16_t channel,
+ std::uint8_t *packet,
+ std::uint16_t size);
+ static void init(sys::Service *service);
+
+ static constexpr std::uint8_t subunitInfo[] = {0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3,
+ 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7};
+ static constexpr std::uint32_t companyId = 0x112233;
+ static constexpr auto targetServiceBufferSize = 200;
+ static constexpr auto controllerServiceBufferSize = 200;
+
+ static std::uint8_t sdpTargetServiceBuffer[targetServiceBufferSize];
+ static std::uint8_t sdpControllerServiceBuffer[controllerServiceBufferSize];
+
static sys::Service *ownerService;
- static avrcp_track_t tracks[3];
- static int currentTrackIndex;
static PlaybackStatusInfo playInfo;
static MediaContext mediaTracker;
-
- static void packetHandler(uint8_t packetType, uint16_t channel, uint8_t *packet, uint16_t size);
- static void targetPacketHandler(uint8_t packetType, uint16_t channel, uint8_t *packet, uint16_t size);
- static void controllerPacketHandler(uint8_t packetType, uint16_t channel, uint8_t *packet, uint16_t size);
- static void init(sys::Service *service);
};
} // namespace bluetooth
M module-bluetooth/Bluetooth/interface/profiles/BtCommand.cpp => module-bluetooth/Bluetooth/interface/profiles/BtCommand.cpp +3 -5
@@ 1,10 1,8 @@
-// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "BtCommand.hpp"
-
#include <array>
-#include <cstdint>
extern "C"
{
@@ 15,13 13,13 @@ namespace bluetooth
{
// Set local name with a template Bluetooth address, that will be automatically
// replaced with a actual address once it is available, i.e. when BTstack boots
- Error set_name(std::string &name)
+ Result set_name(std::string &name)
{
// name has to have storage
constexpr std::uint32_t size = 64;
static std::array<char, size> lname;
snprintf(lname.data(), size, "%s", name.c_str());
gap_set_local_name(lname.data());
- return Error();
+ return Result();
}
} // namespace bluetooth
M module-bluetooth/Bluetooth/interface/profiles/GAP/GAP.cpp => module-bluetooth/Bluetooth/interface/profiles/GAP/GAP.cpp +7 -7
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "GAP.hpp"
@@ 42,17 42,17 @@ namespace bluetooth
return *dev;
};
- auto GAP::registerScan() -> Error
+ auto GAP::registerScan() -> Result
{
LOG_INFO("GAP register scan!");
/// -> this have to be called prior to power on!
hci_set_inquiry_mode(INQUIRY_MODE_RSSI_AND_EIR);
cb_handler.callback = &packetHandler;
hci_add_event_handler(&cb_handler);
- return Error();
+ return Result();
}
- auto GAP::scan() -> Error
+ auto GAP::scan() -> Result
{
if (hci_get_state() == HCI_STATE_WORKING) {
if (gap::state == gap::state::scan_on) {
@@ 61,14 61,14 @@ namespace bluetooth
devices().clear();
if (auto ret = startScan(); ret != 0) {
LOG_ERROR("Start scan error!: 0x%02X - %s", ret, error_cstr(ret));
- return Error(Error::LibraryError, ret);
+ return Result(Result::Code::LibraryError, ret);
}
gap::state = gap::state::scan_on;
}
else {
- return Error(Error::NotReady);
+ return Result(Result::Code::NotReady);
}
- return Error();
+ return Result();
}
void GAP::stopScan()
M module-bluetooth/Bluetooth/interface/profiles/GAP/GAP.hpp => module-bluetooth/Bluetooth/interface/profiles/GAP/GAP.hpp +8 -6
@@ 1,15 1,18 @@
-// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
+
#include <vector>
#include <Bluetooth/Device.hpp>
-#include <Bluetooth/Error.hpp>
+#include <Bluetooth/Result.hpp>
#include <Service/Service.hpp>
+
extern "C"
{
#include "btstack_defines.h"
}
+
namespace bluetooth
{
namespace stack
@@ 47,12 50,11 @@ namespace bluetooth
static void processDedicatedBondingCompleted(std::uint8_t *packet, bd_addr_t &addr);
static void processSimplePairingCompleted(std::uint8_t *packet, bd_addr_t &addr);
static void initStateHandler(std::uint8_t eventType, std::uint8_t *packet);
- static auto getDeviceIndexForAddress(const std::vector<Devicei> &devs, const bd_addr_t addr) -> int;
public:
/// THIS have to be called prior to Bt system start!
- static auto registerScan() -> Error;
- auto scan() -> Error;
+ static auto registerScan() -> Result;
+ auto scan() -> Result;
void stopScan();
void setVisibility(bool visibility);
void pair(Devicei device, std::uint8_t protectionLevel = 0);
@@ 60,7 62,7 @@ namespace bluetooth
static auto getDevicesList() -> std::vector<Devicei>;
static void respondPinCode(const std::string &pin, Devicei d);
static void finishCodeComparison(bool accepted, Devicei d);
- static Devicei currentlyProccesedDevice;
+ static Devicei currentlyProcessedDevice;
explicit GAP(sys::Service *owner);
};
} // namespace bluetooth
M module-bluetooth/Bluetooth/interface/profiles/HFP/HFP.cpp => module-bluetooth/Bluetooth/interface/profiles/HFP/HFP.cpp +253 -226
@@ 4,7 4,7 @@
#include "HFPImpl.hpp"
#include "HFP.hpp"
-#include <Bluetooth/Error.hpp>
+#include <Bluetooth/Result.hpp>
#include <log/log.hpp>
#include <service-evtmgr/Constants.hpp>
#include <service-audio/AudioMessage.hpp>
@@ 16,11 16,12 @@
#include <BluetoothWorker.hpp>
#include "SCO/ScoUtils.hpp"
+#define ARRAY_LENGTH(x) (sizeof(x) / sizeof((x)[0]))
+
extern "C"
{
#include "btstack.h"
#include "btstack_run_loop_freertos.h"
-#include "btstack_stdin.h"
#include <btstack_defines.h>
}
@@ 41,7 42,7 @@ namespace bluetooth
return *this;
}
- auto HFP::init() -> Error::Code
+ auto HFP::init() -> Result::Code
{
return pimpl->init();
}
@@ 51,9 52,8 @@ namespace bluetooth
pimpl->setDevice(device);
}
- void HFP::setOwnerService(const sys::Service *service)
+ void HFP::setOwnerService(sys::Service *service)
{
- ownerService = service;
pimpl->setOwnerService(service);
}
@@ 66,68 66,71 @@ namespace bluetooth
{
pimpl->disconnect();
}
- auto HFP::startRinging() const noexcept -> Error::Code
+
+ auto HFP::incomingCallStarted() const noexcept -> Result::Code
{
- pimpl->startRinging();
- return Error::Success;
+ return pimpl->incomingCallStarted();
}
- auto HFP::stopRinging() const noexcept -> Error::Code
+
+ auto HFP::outgoingCallStarted(const std::string &number) const noexcept -> Result::Code
{
- pimpl->stopRinging();
- return Error::Success;
+ return pimpl->outgoingCallStarted(number);
}
- auto HFP::initializeCall() const noexcept -> Error::Code
+
+ auto HFP::incomingCallAnswered() const noexcept -> Result::Code
{
- pimpl->initializeCall();
- return Error::Success;
+ return pimpl->incomingCallAnswered();
}
- auto HFP::terminateCall() const noexcept -> Error::Code
+
+ auto HFP::outgoingCallAnswered() const noexcept -> Result::Code
{
- pimpl->terminateCall();
- return Error::Success;
+ return pimpl->outgoingCallAnswered();
}
- void HFP::setAudioDevice(std::shared_ptr<bluetooth::BluetoothAudioDevice> audioDevice)
+
+ auto HFP::setIncomingCallNumber(const std::string &num) const noexcept -> Result::Code
{
- pimpl->setAudioDevice(audioDevice);
+ return pimpl->setIncomingCallNumber(num);
}
- auto HFP::callActive() const noexcept -> Error::Code
+
+ auto HFP::callTerminated() const noexcept -> Result::Code
{
- return pimpl->callActive();
+ return pimpl->callTerminated();
}
- auto HFP::setIncomingCallNumber(const std::string &num) const noexcept -> Error::Code
+
+ auto HFP::callMissed() const noexcept -> Result::Code
{
- LOG_SENSITIVE(LOGDEBUG, "Setting number: %s", num.c_str());
- return pimpl->setIncomingCallNumber(num);
+ return pimpl->callMissed();
}
- auto HFP::setSignalStrength(int bars) const noexcept -> Error::Code
+
+ void HFP::setAudioDevice(std::shared_ptr<bluetooth::BluetoothAudioDevice> audioDevice)
+ {
+ pimpl->setAudioDevice(audioDevice);
+ }
+
+ auto HFP::setSignalStrength(int bars) const noexcept -> Result::Code
{
- LOG_DEBUG("Setting RSSI bars: %d/4", bars);
return pimpl->setSignalStrength(bars);
}
- auto HFP::setOperatorName(const std::string_view &name) const noexcept -> Error::Code
+
+ auto HFP::setOperatorName(const std::string_view &name) const noexcept -> Result::Code
{
- LOG_DEBUG("Setting operator name: %s", name.data());
return pimpl->setOperatorName(name);
}
- auto HFP::setBatteryLevel(const BatteryLevel &level) const noexcept -> Error::Code
+
+ auto HFP::setBatteryLevel(const BatteryLevel &level) const noexcept -> Result::Code
{
- LOG_DEBUG("Setting battery level: %d", level.getBatteryLevel());
return pimpl->setBatteryLevel(level);
}
- auto HFP::setNetworkRegistrationStatus(bool registered) const noexcept -> Error::Code
+
+ auto HFP::setNetworkRegistrationStatus(bool registered) const noexcept -> Result::Code
{
- LOG_DEBUG("Setting network registration status: %s", registered ? "online" : "offline");
return pimpl->setNetworkRegistrationStatus(registered);
}
- auto HFP::setRoamingStatus(bool enabled) const noexcept -> Error::Code
+
+ auto HFP::setRoamingStatus(bool enabled) const noexcept -> Result::Code
{
- LOG_DEBUG("Setting roaming status: %s", enabled ? "enabled" : "disabled");
return pimpl->setRoamingStatus(enabled);
}
- auto HFP::callStarted(const std::string &num) const noexcept -> Error::Code
- {
- return pimpl->callStarted(num);
- }
HFP::~HFP()
{
@@ 137,19 140,23 @@ namespace bluetooth
hci_con_handle_t HFP::HFPImpl::scoHandle = HCI_CON_HANDLE_INVALID;
hci_con_handle_t HFP::HFPImpl::aclHandle = HCI_CON_HANDLE_INVALID;
- std::array<uint8_t, serviceBufferLength> HFP::HFPImpl::serviceBuffer;
+
+ std::uint8_t HFP::HFPImpl::serviceBuffer[serviceBufferSize];
+
std::unique_ptr<SCO> HFP::HFPImpl::sco;
- std::unique_ptr<CellularInterface> HFP::HFPImpl::cellularInterface = nullptr;
- std::unique_ptr<AudioInterface> HFP::HFPImpl::audioInterface = nullptr;
- const sys::Service *HFP::HFPImpl::ownerService;
- const std::string_view HFP::HFPImpl::agServiceName = "Mudita Pure HFP";
SCOCodec HFP::HFPImpl::codec = SCOCodec::CVSD;
std::shared_ptr<CVSDAudioDevice> HFP::HFPImpl::audioDevice;
- int HFP::HFPImpl::memory_1_enabled = 1;
- btstack_packet_callback_registration_t HFP::HFPImpl::hci_event_callback_registration;
- int HFP::HFPImpl::ag_indicators_nr = 7;
- hfp_ag_indicator_t HFP::HFPImpl::ag_indicators[] = {
+ std::unique_ptr<CellularInterface> HFP::HFPImpl::cellularInterface;
+ std::unique_ptr<AudioInterface> HFP::HFPImpl::audioInterface;
+
+ sys::Service *HFP::HFPImpl::ownerService;
+ Devicei HFP::HFPImpl::device;
+
+ const char *HFP::HFPImpl::agServiceName = "Mudita Pure HFP";
+ btstack_packet_callback_registration_t HFP::HFPImpl::hciEventCallbackRegistration;
+
+ hfp_ag_indicator_t HFP::HFPImpl::agIndicators[] = {
// index, name, min range, max range, status, mandatory, enabled, status changed
{1, "service", 0, 1, 1, 0, 0, 0},
{2, "call", 0, 1, 0, 1, 1, 0},
@@ 158,17 165,15 @@ namespace bluetooth
{5, "signal", 0, 4, 5, 0, 1, 0},
{6, "roam", 0, 1, 0, 0, 1, 0},
{7, "callheld", 0, 2, 0, 1, 1, 0}};
- int HFP::HFPImpl::call_hold_services_nr = 5;
- const char *HFP::HFPImpl::call_hold_services[] = {"1", "1x", "2", "2x", "3"};
- int HFP::HFPImpl::hf_indicators_nr = 2;
- hfp_generic_status_indicator_t HFP::HFPImpl::hf_indicators[] = {
- {1, 1},
- {2, 1},
+
+ const char *HFP::HFPImpl::callHoldServices[] = {"1", "1x", "2", "2x", "3"};
+
+ hfp_generic_status_indicator_t HFP::HFPImpl::hfIndicators[] = {
+ {1, 1}, // Enhanced safety indicator
+ {2, 1}, // Remaining level of battery indicator
};
- Devicei HFP::HFPImpl::device;
- CallStatus HFP::HFPImpl::currentCallStatus = CallStatus::Unknown;
- void HFP::HFPImpl::dump_supported_codecs(void)
+ void HFP::HFPImpl::logSupportedCodecs()
{
LOG_DEBUG("Supported codecs: ");
@@ 184,7 189,7 @@ namespace bluetooth
LOG_DEBUG("mSBC");
}
else {
- LOG_WARN("mSBC codec disabled because eSCO not supported by local controller.");
+ LOG_WARN("mSBC codec disabled because eSCO not supported by local controller");
}
break;
@@ 193,15 198,18 @@ namespace bluetooth
break;
}
}
+
void HFP::HFPImpl::sendAudioEvent(audio::EventType event, audio::Event::DeviceState state)
{
auto evt = std::make_shared<audio::Event>(event, state);
auto msg = std::make_shared<AudioEventRequest>(std::move(evt));
- auto &busProxy = const_cast<sys::Service *>(ownerService)->bus;
- busProxy.sendUnicast(std::move(msg), service::name::evt_manager);
+ ownerService->bus.sendUnicast(std::move(msg), service::name::evt_manager);
}
- void HFP::HFPImpl::packetHandler(uint8_t packetType, uint16_t channel, uint8_t *event, uint16_t eventSize)
+ void HFP::HFPImpl::packetHandler(std::uint8_t packetType,
+ [[maybe_unused]] std::uint16_t channel,
+ std::uint8_t *event,
+ std::uint16_t eventSize)
{
switch (packetType) {
case HCI_SCO_DATA_PACKET:
@@ 212,7 220,6 @@ namespace bluetooth
audioDevice->receiveCVSD(audio::AbstractStream::Span{.data = event, .dataSize = eventSize});
}
break;
-
case HCI_EVENT_PACKET:
processHCIEvent(event);
break;
@@ 221,7 228,7 @@ namespace bluetooth
}
}
- void HFP::HFPImpl::processHCIEvent(uint8_t *event)
+ void HFP::HFPImpl::processHCIEvent(std::uint8_t *event)
{
switch (hci_event_packet_get_type(event)) {
case HCI_EVENT_SCO_CAN_SEND_NOW:
@@ 240,121 247,122 @@ namespace bluetooth
}
}
- void HFP::HFPImpl::processHFPEvent(uint8_t *event)
+ void HFP::HFPImpl::processHFPEvent(std::uint8_t *event)
{
switch (hci_event_hfp_meta_get_subevent_code(event)) {
- case HFP_SUBEVENT_SERVICE_LEVEL_CONNECTION_ESTABLISHED:
- std::uint8_t status;
- status = hfp_subevent_service_level_connection_established_get_status(event);
- if (status) {
- LOG_DEBUG("Connection failed, status 0x%02x", status);
+ case HFP_SUBEVENT_SERVICE_LEVEL_CONNECTION_ESTABLISHED: {
+ const auto status = hfp_subevent_service_level_connection_established_get_status(event);
+ if (status != ERROR_CODE_SUCCESS) {
+ LOG_ERROR("Connection failed, status: 0x%02X", status);
sendAudioEvent(audio::EventType::BluetoothHFPDeviceState, audio::Event::DeviceState::Disconnected);
break;
}
+
aclHandle = hfp_subevent_service_level_connection_established_get_acl_handle(event);
hfp_subevent_service_level_connection_established_get_bd_addr(event, device.address);
- LOG_DEBUG("Service level connection established to %s", bd_addr_to_str(device.address));
+ LOG_INFO("Service level connection established to %s", bd_addr_to_str(device.address));
+
sendAudioEvent(audio::EventType::BluetoothHFPDeviceState, audio::Event::DeviceState::Connected);
- {
- auto &busProxy = const_cast<sys::Service *>(ownerService)->bus;
- device.deviceState = DeviceState::ConnectedVoice;
- busProxy.sendUnicast(std::make_shared<message::bluetooth::ConnectResult>(device, true),
- service::name::bluetooth);
- // request cellular status indicators for HFP
- busProxy.sendUnicast(std::make_shared<message::bluetooth::RequestStatusIndicatorData>(),
- service::name::bluetooth);
- }
- dump_supported_codecs();
- break;
- case HFP_SUBEVENT_SERVICE_LEVEL_CONNECTION_RELEASED:
- LOG_DEBUG("Service level connection released");
+ device.deviceState = DeviceState::ConnectedVoice;
+
+ ownerService->bus.sendUnicast(std::make_shared<message::bluetooth::ConnectResult>(
+ device, message::bluetooth::ConnectResult::Result::Success),
+ service::name::bluetooth);
+ ownerService->bus.sendUnicast(std::make_shared<message::bluetooth::RequestStatusIndicatorData>(),
+ service::name::bluetooth);
+
+ logSupportedCodecs();
+ } break;
+
+ case HFP_SUBEVENT_SERVICE_LEVEL_CONNECTION_RELEASED: {
aclHandle = HCI_CON_HANDLE_INVALID;
+
sendAudioEvent(audio::EventType::BluetoothHFPDeviceState, audio::Event::DeviceState::Disconnected);
- {
- auto &busProxy = const_cast<sys::Service *>(ownerService)->bus;
- busProxy.sendUnicast(std::make_shared<message::bluetooth::DisconnectResult>(device),
- service::name::bluetooth);
- }
- break;
- case HFP_SUBEVENT_AUDIO_CONNECTION_ESTABLISHED:
- if (hfp_subevent_audio_connection_established_get_status(event)) {
- LOG_DEBUG("Audio connection establishment failed with status %u",
- hfp_subevent_audio_connection_established_get_status(event));
- }
- else {
- scoHandle = hfp_subevent_audio_connection_established_get_sco_handle(event);
- LOG_DEBUG("Audio connection established with SCO handle 0x%04x", scoHandle);
- codec = static_cast<SCOCodec>(hfp_subevent_audio_connection_established_get_negotiated_codec(event));
- dump_supported_codecs();
- audioInterface->startAudioRouting(const_cast<sys::Service *>(ownerService));
- hci_request_sco_can_send_now_event();
- RunLoop::trigger();
+ ownerService->bus.sendUnicast(std::make_shared<message::bluetooth::DisconnectResult>(device),
+ service::name::bluetooth);
+
+ LOG_INFO("Service level connection released");
+ } break;
+
+ case HFP_SUBEVENT_AUDIO_CONNECTION_ESTABLISHED: {
+ const auto status = hfp_subevent_audio_connection_established_get_status(event);
+ if (status != ERROR_CODE_SUCCESS) {
+ LOG_ERROR("Audio connection establishment failed, status: 0x%02X", status);
+ break;
}
- break;
- case HFP_SUBEVENT_AUDIO_CONNECTION_RELEASED:
- LOG_DEBUG("Audio connection released");
+
+ scoHandle = hfp_subevent_audio_connection_established_get_sco_handle(event);
+ LOG_INFO("Audio connection established with SCO handle 0x%04X", scoHandle);
+
+ codec = static_cast<SCOCodec>(hfp_subevent_audio_connection_established_get_negotiated_codec(event));
+ logSupportedCodecs();
+
+ audioInterface->startAudioRouting(ownerService);
+ hci_request_sco_can_send_now_event();
+ RunLoop::trigger();
+ } break;
+
+ case HFP_SUBEVENT_AUDIO_CONNECTION_RELEASED: {
scoHandle = HCI_CON_HANDLE_INVALID;
audioDevice.reset();
- break;
+ LOG_INFO("Audio connection released");
+ } break;
+
case HFP_SUBEVENT_START_RINGING:
- LOG_DEBUG("Start Ringing");
- // todo request here ringtone stream
break;
+
case HFP_SUBEVENT_STOP_RINGING:
- LOG_DEBUG("Stop Ringing");
- // todo stop ringtone stream here
break;
- case HFP_SUBEVENT_PLACE_CALL_WITH_NUMBER: {
- auto receivedNumber = hfp_subevent_place_call_with_number_get_number(event);
- LOG_DEBUG("Requested call from HFP to number %s", receivedNumber);
- currentCallStatus = CallStatus::OutgoingPlacedFromHFP;
- hfp_ag_outgoing_call_accepted();
- cellularInterface->dialNumber(const_cast<sys::Service *>(ownerService), receivedNumber);
- } break;
+
case HFP_SUBEVENT_RING:
- LOG_DEBUG("SUBEVENT_RING called!");
break;
+
+ case HFP_SUBEVENT_PLACE_CALL_WITH_NUMBER: {
+ const auto receivedNumber = hfp_subevent_place_call_with_number_get_number(event);
+ LOG_INFO("Requested call from HFP to number %s", receivedNumber);
+ cellularInterface->dialNumber(ownerService, receivedNumber);
+ } break;
+
case HFP_SUBEVENT_ATTACH_NUMBER_TO_VOICE_TAG:
- // todo has to be feeded with proper phone number from cellular
- // LOG_DEBUG("Attach number to voice tag. Sending '1234567'");
- hfp_ag_send_phone_number_for_voice_tag(aclHandle, "1234567");
break;
+
case HFP_SUBEVENT_TRANSMIT_DTMF_CODES: {
- auto digitStr = hfp_subevent_transmit_dtmf_codes_get_dtmf(event);
+ const auto digitStr = hfp_subevent_transmit_dtmf_codes_get_dtmf(event);
LOG_DEBUG("Send DTMF Codes: '%s'", digitStr);
try {
- cellularInterface->sendDTMFCode(const_cast<sys::Service *>(ownerService), DTMFCode(digitStr));
+ cellularInterface->sendDTMFCode(ownerService, DTMFCode(digitStr));
}
catch (std::out_of_range &e) {
LOG_ERROR("Can't send DTMF code for digit: %s", digitStr);
}
hfp_ag_send_dtmf_code_done(aclHandle);
} break;
- case HFP_SUBEVENT_CALL_ANSWERED:
- LOG_DEBUG("Call answered");
- cellularInterface->answerIncomingCall(const_cast<sys::Service *>(ownerService));
- break;
+
+ case HFP_SUBEVENT_CALL_ANSWERED: {
+ LOG_INFO("Event: call answered");
+ cellularInterface->answerIncomingCall(ownerService);
+ } break;
case HFP_SUBEVENT_SPEAKER_VOLUME: {
const auto volume = hfp_subevent_speaker_volume_get_gain(event);
- auto &busProxy = const_cast<sys::Service *>(ownerService)->bus;
- busProxy.sendUnicast(std::make_shared<message::bluetooth::HFPVolume>(volume), service::name::bluetooth);
- LOG_DEBUG("Received speaker gain change %d", hsp_subevent_speaker_gain_changed_get_gain(event));
+ ownerService->bus.sendUnicast(std::make_shared<message::bluetooth::HFPVolume>(volume),
+ service::name::bluetooth);
+ LOG_INFO("Received speaker gain change to %d", volume);
+ } break;
+
+ case HFP_SUBEVENT_CALL_TERMINATED: {
+ LOG_INFO("Event: call terminated");
+ cellularInterface->hangupCall(ownerService);
} break;
- case HFP_SUBEVENT_CALL_TERMINATED:
- LOG_DEBUG("Call terminated");
- cellularInterface->hangupCall(const_cast<sys::Service *>(ownerService));
- currentCallStatus = CallStatus::Unknown;
- break;
default:
- LOG_DEBUG("Event not handled %u", hci_event_hfp_meta_get_subevent_code(event));
+ LOG_INFO("Event not handled: 0x%02X", hci_event_hfp_meta_get_subevent_code(event));
break;
}
}
static hfp_phone_number_t subscriber_number = {129, "225577"};
- auto HFP::HFPImpl::init() -> Error::Code
+ auto HFP::HFPImpl::init() -> Result::Code
{
sco = std::make_unique<SCO>();
sco->setOwnerService(ownerService);
@@ 366,51 374,58 @@ namespace bluetooth
Profile::initL2cap();
Profile::initSdp();
- serviceBuffer.fill(0);
- uint16_t supported_features = (1 << HFP_AGSF_ESCO_S4) | /* (1 << HFP_AGSF_HF_INDICATORS) | */
- (1 << HFP_AGSF_CODEC_NEGOTIATION) | (1 << HFP_AGSF_EXTENDED_ERROR_RESULT_CODES) |
- (1 << HFP_AGSF_ENHANCED_CALL_CONTROL) | (1 << HFP_AGSF_ENHANCED_CALL_STATUS) |
- (1 << HFP_AGSF_ABILITY_TO_REJECT_A_CALL) /*| (1 << HFP_AGSF_IN_BAND_RING_TONE) |*/
- /* (1 << HFP_AGSF_VOICE_RECOGNITION_FUNCTION) |(1 << HFP_AGSF_THREE_WAY_CALLING)*/;
- int wide_band_speech = 0;
- constexpr std::uint8_t abilityToRejectCall = 1;
- hfp_ag_create_sdp_record(serviceBuffer.data(),
+ std::memset(serviceBuffer, 0, sizeof(serviceBuffer));
+
+ constexpr auto wideBandSpeechEnabled = 0;
+ constexpr auto abilityToRejectCall = 1;
+ constexpr std::uint16_t supportedFeatures =
+ (1 << HFP_AGSF_ESCO_S4) | (1 << HFP_AGSF_CODEC_NEGOTIATION) | (1 << HFP_AGSF_EXTENDED_ERROR_RESULT_CODES) |
+ (1 << HFP_AGSF_ENHANCED_CALL_CONTROL) | (1 << HFP_AGSF_ENHANCED_CALL_STATUS) |
+ (1 << HFP_AGSF_ABILITY_TO_REJECT_A_CALL) | (1 << HFP_AGSF_ATTACH_A_NUMBER_TO_A_VOICE_TAG);
+
+ hfp_ag_create_sdp_record(serviceBuffer,
hfpSdpRecordHandle,
rfcommChannelNr,
- agServiceName.data(),
+ agServiceName,
abilityToRejectCall,
- supported_features,
- wide_band_speech);
-
- if (const auto status = sdp_register_service(serviceBuffer.data()); status != ERROR_CODE_SUCCESS) {
- LOG_ERROR("Can't register service. Status %x", status);
+ supportedFeatures,
+ wideBandSpeechEnabled);
+ if (const auto status = sdp_register_service(serviceBuffer); status != ERROR_CODE_SUCCESS) {
+ LOG_ERROR("Can't register service, status 0x%02X", status);
}
+
rfcomm_init();
+
hfp_ag_init(rfcommChannelNr);
- hfp_ag_init_supported_features(supported_features);
+ hfp_ag_init_supported_features(supportedFeatures);
+
initCodecs();
- hfp_ag_init_ag_indicators(ag_indicators_nr, ag_indicators);
- hfp_ag_init_hf_indicators(hf_indicators_nr, hf_indicators);
- hfp_ag_init_call_hold_services(call_hold_services_nr, call_hold_services);
- hfp_ag_set_subcriber_number_information(&subscriber_number, 1);
- hci_event_callback_registration.callback = &packetHandler;
- hci_add_event_handler(&hci_event_callback_registration);
- hci_register_sco_packet_handler(&packetHandler);
+ hfp_ag_init_ag_indicators(ARRAY_LENGTH(agIndicators), agIndicators);
+ hfp_ag_init_hf_indicators(ARRAY_LENGTH(hfIndicators), hfIndicators);
+
+ hfp_ag_init_call_hold_services(ARRAY_LENGTH(callHoldServices), callHoldServices);
+
+ /* TODO here own number from cellular should be provided */
+ hfp_ag_set_subcriber_number_information(&subscriber_number, 0);
+ hciEventCallbackRegistration.callback = &packetHandler;
+ hci_add_event_handler(&hciEventCallbackRegistration);
+ hci_register_sco_packet_handler(&packetHandler);
hfp_ag_register_packet_handler(&packetHandler);
hfp_ag_set_use_in_band_ring_tone(0);
- LOG_INFO("HFP init done!");
-
- return bluetooth::Error::Success;
+ LOG_INFO("HFP initialized!");
+ return bluetooth::Result::Code::Success;
}
void HFP::HFPImpl::connect()
{
+ /* Disconnect before attempting to connect */
disconnect();
- LOG_DEBUG("Connecting the HFP profile");
+
+ LOG_INFO("Connecting HFP profile");
hfp_ag_establish_service_level_connection(device.address);
hfp_ag_set_speaker_gain(aclHandle, 8);
hfp_ag_set_microphone_gain(aclHandle, 10);
@@ 418,20 433,20 @@ namespace bluetooth
void HFP::HFPImpl::disconnect()
{
+ LOG_INFO("Disconnecting HFP profile");
if (hfp_ag_release_service_level_connection(aclHandle) == ERROR_CODE_SUCCESS) {
- auto &busProxy = const_cast<sys::Service *>(ownerService)->bus;
- busProxy.sendUnicast(std::make_shared<message::bluetooth::DisconnectResult>(device),
- service::name::bluetooth);
+ ownerService->bus.sendUnicast(std::make_shared<message::bluetooth::DisconnectResult>(device),
+ service::name::bluetooth);
}
}
void HFP::HFPImpl::setDevice(Devicei dev)
{
- device = dev;
+ device = std::move(dev);
LOG_DEBUG("Device set!");
}
- void HFP::HFPImpl::setOwnerService(const sys::Service *service)
+ void HFP::HFPImpl::setOwnerService(sys::Service *service)
{
ownerService = service;
}
@@ 453,99 468,111 @@ namespace bluetooth
codecsList.push_back(SCOCodec::mSBC);
break;
}
- hfp_ag_init_codecs(codecsList.size(), reinterpret_cast<uint8_t *>(codecsList.data()));
+ hfp_ag_init_codecs(codecsList.size(), reinterpret_cast<std::uint8_t *>(codecsList.data()));
}
- void HFP::HFPImpl::initializeCall() const noexcept
- {}
- void HFP::HFPImpl::setAudioDevice(std::shared_ptr<bluetooth::BluetoothAudioDevice> audioDevice)
+
+ void HFP::HFPImpl::setAudioDevice(std::shared_ptr<bluetooth::BluetoothAudioDevice> audioDev)
{
- HFP::HFPImpl::audioDevice = std::static_pointer_cast<CVSDAudioDevice>(audioDevice);
+ HFP::HFPImpl::audioDevice = std::static_pointer_cast<CVSDAudioDevice>(audioDev);
HFP::HFPImpl::audioDevice->setAclHandle(aclHandle);
LOG_DEBUG("Audiodevice set!");
}
- void HFP::HFPImpl::startRinging() const noexcept
+
+ auto HFP::HFPImpl::incomingCallStarted() const noexcept -> Result::Code
{
- LOG_DEBUG("Starting incoming call");
- currentCallStatus = CallStatus::Incoming;
+ LOG_DEBUG("Incoming call received");
hfp_ag_incoming_call();
+ return Result::Code::Success;
}
- void HFP::HFPImpl::stopRinging() const noexcept
+
+ auto HFP::HFPImpl::outgoingCallStarted(const std::string &number) const noexcept -> Result::Code
{
- LOG_DEBUG("Stop ringing called!");
+ LOG_DEBUG("Outgoing call placed");
+ hfp_ag_outgoing_call_initiated();
+ hfp_ag_outgoing_call_accepted();
+ hfp_ag_outgoing_call_ringing();
+ hfp_ag_send_phone_number_for_voice_tag(aclHandle, number.c_str());
+ return Result::Code::Success;
}
- auto HFP::HFPImpl::callActive() const noexcept -> Error::Code
+
+ auto HFP::HFPImpl::incomingCallAnswered() const noexcept -> Result::Code
{
- if (currentCallStatus == CallStatus::Incoming) {
- hfp_ag_answer_incoming_call(); // will answer the call if it wasn't answered
- }
- else {
- hfp_ag_outgoing_call_established();
- }
- currentCallStatus = CallStatus::Active;
- return Error::Success;
+ LOG_DEBUG("Incoming call answered");
+ hfp_ag_answer_incoming_call();
+ return Result::Code::Success;
}
- void HFP::HFPImpl::terminateCall() const noexcept
+
+ auto HFP::HFPImpl::outgoingCallAnswered() const noexcept -> Result::Code
{
- if (currentCallStatus == CallStatus::Active) {
- hfp_ag_terminate_call();
- }
- else {
- hfp_ag_call_dropped();
- }
+ LOG_DEBUG("Outgoing call answered");
+ hfp_ag_outgoing_call_established();
+ return Result::Code::Success;
}
- auto HFP::HFPImpl::setIncomingCallNumber(const std::string &num) const noexcept -> Error::Code
+
+ auto HFP::HFPImpl::callTerminated() const noexcept -> Result::Code
{
- hfp_ag_set_clip(129, num.c_str());
- return Error::Success;
+ LOG_DEBUG("Outgoing call terminated");
+ hfp_ag_terminate_call();
+ return Result::Code::Success;
}
- auto HFP::HFPImpl::setSignalStrength(int bars) const noexcept -> Error::Code
+
+ auto HFP::HFPImpl::callMissed() const noexcept -> Result::Code
{
- hfp_ag_set_signal_strength(bars);
- return Error::Success;
+ LOG_DEBUG("Incoming call missed");
+ hfp_ag_terminate_call();
+ return Result::Code::Success;
}
- auto HFP::HFPImpl::setOperatorName(const std::string_view &name) const noexcept -> Error::Code
+ auto HFP::HFPImpl::setIncomingCallNumber(const std::string &num) const noexcept -> Result::Code
{
- auto result = hfp_ag_set_operator_name(HFP::HFPImpl::aclHandle, name.data());
- LOG_DEBUG("Operator set name result: %d", result);
- return Error::Success;
+ LOG_SENSITIVE(LOGDEBUG, "Setting number: %s", num.c_str());
+ hfp_ag_set_clip(129, num.c_str());
+ return Result::Code::Success;
}
- auto HFP::HFPImpl::setBatteryLevel(const BatteryLevel &level) const noexcept -> Error::Code
+
+ auto HFP::HFPImpl::setSignalStrength(int bars) const noexcept -> Result::Code
{
- auto result = hfp_ag_set_battery_level(level.getBatteryLevelBars());
+ const auto result = hfp_ag_set_signal_strength(bars);
+ LOG_INFO("Set RSSI bars: %d/4, result: 0x%02X", bars, result);
+ return Result::Code::Success;
+ }
- LOG_DEBUG("Battery level (bars): %d, set result: %d", level.getBatteryLevelBars(), result);
- return Error::Success;
+ auto HFP::HFPImpl::setOperatorName(const std::string_view &name) const noexcept -> Result::Code
+ {
+ const auto result = hfp_ag_set_operator_name(aclHandle, name.data());
+ LOG_INFO("Set operator name: %s, result: 0x%02X", name.data(), result);
+ return Result::Code::Success;
}
- auto HFP::HFPImpl::callStarted(const std::string &number) const noexcept -> Error::Code
+
+ auto HFP::HFPImpl::setBatteryLevel(const BatteryLevel &level) const noexcept -> Result::Code
{
- if (currentCallStatus != CallStatus::OutgoingPlacedFromHFP) {
- LOG_DEBUG("Started outgoing call from Pure");
- hfp_ag_outgoing_call_initiated();
- hfp_ag_outgoing_call_accepted();
- hfp_ag_outgoing_call_ringing();
- currentCallStatus = CallStatus::OutgoingPlacedFromPure;
- }
- return Error::Success;
+ const auto batteryLevel = level.getBatteryLevelBars();
+ const auto result = hfp_ag_set_battery_level(static_cast<int>(batteryLevel));
+ LOG_INFO("Set battery level: %d, result: 0x%02X", batteryLevel, result);
+ return Result::Code::Success;
}
- auto HFP::HFPImpl::setNetworkRegistrationStatus(bool registered) const noexcept -> Error::Code
+
+ auto HFP::HFPImpl::setNetworkRegistrationStatus(bool registered) const noexcept -> Result::Code
{
- hfp_ag_set_registration_status(registered);
- return Error::Success;
+ const auto result = hfp_ag_set_registration_status(static_cast<int>(registered));
+ LOG_INFO("Set registration status: %s, result 0x%02X", registered ? "online" : "offline", result);
+ return Result::Code::Success;
}
- auto HFP::HFPImpl::setRoamingStatus(bool enabled) const noexcept -> Error::Code
+
+ auto HFP::HFPImpl::setRoamingStatus(bool enabled) const noexcept -> Result::Code
{
- hfp_ag_set_roaming_status(enabled);
- return Error::Success;
+ const auto result = hfp_ag_set_roaming_status(static_cast<int>(enabled));
+ LOG_INFO("Set roaming status: %s, result: 0x%02X", enabled ? "enabled" : "disabled", result);
+ return Result::Code::Success;
}
+
void HFP::HFPImpl::deInit() noexcept
{
- LOG_DEBUG("[HFP] deinit");
sdp_unregister_service(hfpSdpRecordHandle);
-
cellularInterface.reset();
audioInterface.reset();
sco.reset();
- }
+ LOG_INFO("HFP deinitialized!");
+ }
} // namespace bluetooth
M module-bluetooth/Bluetooth/interface/profiles/HFP/HFP.hpp => module-bluetooth/Bluetooth/interface/profiles/HFP/HFP.hpp +15 -24
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
@@ 25,41 25,32 @@ namespace bluetooth
HFP(HFP &&other) noexcept;
auto operator=(HFP &&other) noexcept -> HFP &;
- auto init() -> Error::Code override;
+ auto init() -> Result::Code override;
void setDevice(const Devicei &device) override;
- void setOwnerService(const sys::Service *service) override;
+ void setOwnerService(sys::Service *service) override;
void connect() override;
void disconnect() override;
- /// @brief Starts ring
- /// @return Success
- [[nodiscard]] auto startRinging() const noexcept -> Error::Code override;
- /// @brief Stops ring
- /// @return Success
- [[nodiscard]] auto stopRinging() const noexcept -> Error::Code override;
- /// @brief Initializes bluetooth audio call which is divided into two parts:
- /// - Ring stop
- /// - SCO link establishment
- /// @return Success
- [[nodiscard]] auto initializeCall() const noexcept -> Error::Code override;
- [[nodiscard]] auto terminateCall() const noexcept -> Error::Code override;
- [[nodiscard]] auto callActive() const noexcept -> Error::Code override;
- [[nodiscard]] auto callStarted(const std::string &number) const noexcept -> Error::Code override;
- [[nodiscard]] auto setIncomingCallNumber(const std::string &num) const noexcept -> Error::Code override;
+ [[nodiscard]] auto incomingCallStarted() const noexcept -> Result::Code override;
+ [[nodiscard]] auto outgoingCallStarted(const std::string &number) const noexcept -> Result::Code override;
+ [[nodiscard]] auto incomingCallAnswered() const noexcept -> Result::Code override;
+ [[nodiscard]] auto outgoingCallAnswered() const noexcept -> Result::Code override;
+ [[nodiscard]] auto callTerminated() const noexcept -> Result::Code override;
+ [[nodiscard]] auto callMissed() const noexcept -> Result::Code override;
+ [[nodiscard]] auto setIncomingCallNumber(const std::string &num) const noexcept -> Result::Code override;
/// @brief Sets the signal strength bars data
/// @return Success
- [[nodiscard]] auto setSignalStrength(int bars) const noexcept -> Error::Code override;
- [[nodiscard]] auto setOperatorName(const std::string_view &name) const noexcept -> Error::Code override;
- [[nodiscard]] auto setBatteryLevel(const BatteryLevel &level) const noexcept -> Error::Code override;
- [[nodiscard]] auto setNetworkRegistrationStatus(bool registered) const noexcept -> Error::Code override;
- auto setRoamingStatus(bool enabled) const noexcept -> Error::Code override;
+ [[nodiscard]] auto setSignalStrength(int bars) const noexcept -> Result::Code override;
+ [[nodiscard]] auto setOperatorName(const std::string_view &name) const noexcept -> Result::Code override;
+ [[nodiscard]] auto setBatteryLevel(const BatteryLevel &level) const noexcept -> Result::Code override;
+ [[nodiscard]] auto setNetworkRegistrationStatus(bool registered) const noexcept -> Result::Code override;
+ auto setRoamingStatus(bool enabled) const noexcept -> Result::Code override;
void setAudioDevice(std::shared_ptr<bluetooth::BluetoothAudioDevice> audioDevice) override;
private:
class HFPImpl;
std::unique_ptr<HFPImpl> pimpl;
- const sys::Service *ownerService{};
};
} // namespace bluetooth
M module-bluetooth/Bluetooth/interface/profiles/HFP/HFPImpl.hpp => module-bluetooth/Bluetooth/interface/profiles/HFP/HFPImpl.hpp +44 -48
@@ 1,77 1,73 @@
-// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
+
#include "HFP.hpp"
-#include "Error.hpp"
+#include "Result.hpp"
#include <interface/profiles/SCO/SCO.hpp>
#include <Audio/AudioCommon.hpp>
namespace bluetooth
{
- static constexpr int serviceBufferLength = 150;
- static constexpr int commandBufferLength = 150;
-
- enum class CallStatus
- {
- OutgoingPlacedFromPure,
- OutgoingPlacedFromHFP,
- Incoming,
- Active,
- Unknown
- };
-
class HFP::HFPImpl
{
public:
- static void packetHandler(uint8_t packetType, uint16_t channel, uint8_t *event, uint16_t eventSize);
- auto init() -> Error::Code;
+ static void packetHandler(std::uint8_t packetType,
+ std::uint16_t channel,
+ std::uint8_t *event,
+ std::uint16_t eventSize);
+ auto init() -> Result::Code;
void deInit() noexcept;
- void startRinging() const noexcept;
- void stopRinging() const noexcept;
- void initializeCall() const noexcept;
- void terminateCall() const noexcept;
+ [[nodiscard]] auto incomingCallStarted() const noexcept -> Result::Code;
+ [[nodiscard]] auto outgoingCallStarted(const std::string &number) const noexcept -> Result::Code;
+ [[nodiscard]] auto incomingCallAnswered() const noexcept -> Result::Code;
+ [[nodiscard]] auto outgoingCallAnswered() const noexcept -> Result::Code;
+ [[nodiscard]] auto callTerminated() const noexcept -> Result::Code;
+ [[nodiscard]] auto callMissed() const noexcept -> Result::Code;
void connect();
void disconnect();
void setDevice(Devicei device);
- void setOwnerService(const sys::Service *service);
+ void setOwnerService(sys::Service *service);
void setAudioDevice(std::shared_ptr<bluetooth::BluetoothAudioDevice> audioDevice);
- [[nodiscard]] auto callActive() const noexcept -> Error::Code;
- [[nodiscard]] auto setIncomingCallNumber(const std::string &num) const noexcept -> Error::Code;
- [[nodiscard]] auto setSignalStrength(int bars) const noexcept -> Error::Code;
- [[nodiscard]] auto setOperatorName(const std::string_view &name) const noexcept -> Error::Code;
- [[nodiscard]] auto setBatteryLevel(const BatteryLevel &level) const noexcept -> Error::Code;
- [[nodiscard]] auto setNetworkRegistrationStatus(bool registered) const noexcept -> Error::Code;
- [[nodiscard]] auto setRoamingStatus(bool enabled) const noexcept -> Error::Code;
- [[nodiscard]] auto callStarted(const std::string &number) const noexcept -> Error::Code;
+ [[nodiscard]] auto setIncomingCallNumber(const std::string &num) const noexcept -> Result::Code;
+ [[nodiscard]] auto setSignalStrength(int bars) const noexcept -> Result::Code;
+ [[nodiscard]] auto setOperatorName(const std::string_view &name) const noexcept -> Result::Code;
+ [[nodiscard]] auto setBatteryLevel(const BatteryLevel &level) const noexcept -> Result::Code;
+ [[nodiscard]] auto setNetworkRegistrationStatus(bool registered) const noexcept -> Result::Code;
+ [[nodiscard]] auto setRoamingStatus(bool enabled) const noexcept -> Result::Code;
private:
static void sendAudioEvent(audio::EventType event, audio::Event::DeviceState state);
- static void processHCIEvent(uint8_t *event);
- static void processHFPEvent(uint8_t *event);
+ static void processHCIEvent(std::uint8_t *event);
+ static void processHFPEvent(std::uint8_t *event);
static void initCodecs();
- static void dump_supported_codecs(void);
- static std::array<uint8_t, serviceBufferLength> serviceBuffer;
- static constexpr uint8_t rfcommChannelNr = 1;
- static const std::string_view agServiceName;
+ static void logSupportedCodecs();
+
+ static constexpr auto serviceBufferSize = 150;
+ static constexpr std::uint8_t rfcommChannelNr = 1;
+ static constexpr std::uint32_t hfpSdpRecordHandle = 0x10004;
+
static hci_con_handle_t scoHandle;
static hci_con_handle_t aclHandle;
+
+ static std::uint8_t serviceBuffer[serviceBufferSize];
+
+ static const char *agServiceName;
+
static std::unique_ptr<SCO> sco;
- static std::unique_ptr<CellularInterface> cellularInterface;
- static std::unique_ptr<AudioInterface> audioInterface;
- static const sys::Service *ownerService;
static SCOCodec codec;
- [[maybe_unused]] static int memory_1_enabled;
- static btstack_packet_callback_registration_t hci_event_callback_registration;
- [[maybe_unused]] static int ag_indicators_nr;
- static hfp_ag_indicator_t ag_indicators[7];
- [[maybe_unused]] static int call_hold_services_nr;
- static const char *call_hold_services[5];
- [[maybe_unused]] static int hf_indicators_nr;
- [[maybe_unused]] static hfp_generic_status_indicator_t hf_indicators[2];
- static constexpr std::uint32_t hfpSdpRecordHandle = 0x10004;
static std::shared_ptr<CVSDAudioDevice> audioDevice;
+
+ static std::unique_ptr<CellularInterface> cellularInterface;
+ static std::unique_ptr<AudioInterface> audioInterface;
+
+ static sys::Service *ownerService;
static Devicei device;
- static CallStatus currentCallStatus;
+
+ static btstack_packet_callback_registration_t hciEventCallbackRegistration;
+ static hfp_ag_indicator_t agIndicators[];
+ static const char *callHoldServices[];
+ static hfp_generic_status_indicator_t hfIndicators[];
};
} // namespace bluetooth
M module-bluetooth/Bluetooth/interface/profiles/HSP/HSP.cpp => module-bluetooth/Bluetooth/interface/profiles/HSP/HSP.cpp +204 -180
@@ 5,7 5,7 @@
#include "HSPImpl.hpp"
#include "HSP.hpp"
-#include <Bluetooth/Error.hpp>
+#include <Bluetooth/Result.hpp>
#include <service-evtmgr/Constants.hpp>
#include <BluetoothWorker.hpp>
#include <module-bluetooth/Bluetooth/interface/profiles/SCO/ScoUtils.hpp>
@@ 14,15 14,11 @@
#include <service-bluetooth/messages/AudioVolume.hpp>
#include <service-bluetooth/messages/Connect.hpp>
#include <service-bluetooth/messages/Disconnect.hpp>
-#include <service-cellular/service-cellular/CellularServiceAPI.hpp>
-#include <service-evtmgr/Constants.hpp>
-#include <service-audio/AudioServiceAPI.hpp>
extern "C"
{
#include "btstack.h"
#include "btstack_run_loop_freertos.h"
-#include "btstack_stdin.h"
#include <btstack_defines.h>
}
@@ 43,7 39,7 @@ namespace bluetooth
return *this;
}
- auto HSP::init() -> Error::Code
+ auto HSP::init() -> Result::Code
{
return pimpl->init();
}
@@ 53,9 49,8 @@ namespace bluetooth
pimpl->setDevice(device);
}
- void HSP::setOwnerService(const sys::Service *service)
+ void HSP::setOwnerService(sys::Service *service)
{
- ownerService = service;
pimpl->setOwnerService(service);
}
@@ 69,49 64,102 @@ namespace bluetooth
pimpl->disconnect();
}
- auto HSP::startRinging() const noexcept -> Error::Code
+ void HSP::setAudioDevice(std::shared_ptr<bluetooth::BluetoothAudioDevice> audioDevice)
+ {
+ pimpl->setAudioDevice(audioDevice);
+ }
+
+ auto HSP::setIncomingCallNumber([[maybe_unused]] const std::string &num) const noexcept -> Result::Code
{
- pimpl->startRinging();
- return Error::Success;
+ return Result::Code::Success;
}
- auto HSP::stopRinging() const noexcept -> Error::Code
+ auto HSP::setSignalStrength([[maybe_unused]] int bars) const noexcept -> Result::Code
{
- pimpl->stopRinging();
- return Error::Success;
+ return Result::Code::Success;
}
- auto HSP::initializeCall() const noexcept -> Error::Code
+ auto HSP::setOperatorName([[maybe_unused]] const std::string_view &name) const noexcept -> Result::Code
{
- pimpl->initializeCall();
- return Error::Success;
+ return Result::Code::Success;
+ }
+
+ auto HSP::setBatteryLevel([[maybe_unused]] const BatteryLevel &name) const noexcept -> Result::Code
+ {
+ return Result::Code::Success;
+ }
+
+ auto HSP::incomingCallStarted() const noexcept -> Result::Code
+ {
+ return pimpl->incomingCallStarted();
+ }
+
+ auto HSP::outgoingCallStarted(const std::string &number) const noexcept -> Result::Code
+ {
+ return pimpl->outgoingCallStarted(number);
+ }
+
+ auto HSP::incomingCallAnswered() const noexcept -> Result::Code
+ {
+ return pimpl->incomingCallAnswered();
+ }
+
+ auto HSP::outgoingCallAnswered() const noexcept -> Result::Code
+ {
+ return pimpl->outgoingCallAnswered();
+ }
+
+ auto HSP::callTerminated() const noexcept -> Result::Code
+ {
+ return pimpl->callTerminated();
+ }
+
+ auto HSP::callMissed() const noexcept -> Result::Code
+ {
+ return pimpl->callMissed();
+ }
+
+ auto HSP::setNetworkRegistrationStatus([[maybe_unused]] bool registered) const noexcept -> Result::Code
+ {
+ return Result::Code::Success;
+ }
+
+ auto HSP::setRoamingStatus([[maybe_unused]] bool enabled) const noexcept -> Result::Code
+ {
+ return Result::Code::Success;
}
HSP::~HSP() = default;
- uint16_t HSP::HSPImpl::scoHandle = HCI_CON_HANDLE_INVALID;
- std::array<char, commandBufferLength> HSP::HSPImpl::ATcommandBuffer;
- std::array<uint8_t, serviceBufferLength> HSP::HSPImpl::serviceBuffer;
+ std::uint16_t HSP::HSPImpl::scoHandle = HCI_CON_HANDLE_INVALID;
+ std::uint8_t HSP::HSPImpl::serviceBuffer[serviceBufferSize];
+
+ const char *HSP::HSPImpl::agServiceName = "Mudita Pure HSP";
+
std::unique_ptr<SCO> HSP::HSPImpl::sco;
+ std::shared_ptr<CVSDAudioDevice> HSP::HSPImpl::audioDevice;
+
std::unique_ptr<CellularInterface> HSP::HSPImpl::cellularInterface = nullptr;
std::unique_ptr<AudioInterface> HSP::HSPImpl::audioInterface = nullptr;
- const sys::Service *HSP::HSPImpl::ownerService;
- const std::string_view HSP::HSPImpl::agServiceName = "Mudita Pure HSP";
- bool HSP::HSPImpl::isConnected = false;
- bool HSP::HSPImpl::callAnswered = false;
- bool HSP::HSPImpl::isRinging = false;
- std::shared_ptr<CVSDAudioDevice> HSP::HSPImpl::audioDevice;
+
+ sys::Service *HSP::HSPImpl::ownerService;
Devicei HSP::HSPImpl::device;
- void HSP::HSPImpl::sendAudioEvent(audio::EventType event, audio::Event::DeviceState state)
+ btstack_packet_callback_registration_t HSP::HSPImpl::hciEventCallbackRegistration;
+ char HSP::HSPImpl::ATCommandBuffer[commandBufferSize];
+ HSP::HSPImpl::HSPState HSP::HSPImpl::state = HSPState::RfcommDisconnected;
+
+ void HSP::HSPImpl::sendAudioEvent(audio::EventType event, audio::Event::DeviceState deviceState)
{
- auto evt = std::make_shared<audio::Event>(event, state);
+ auto evt = std::make_shared<audio::Event>(event, deviceState);
auto msg = std::make_shared<AudioEventRequest>(std::move(evt));
- auto &busProxy = const_cast<sys::Service *>(ownerService)->bus;
- busProxy.sendUnicast(std::move(msg), service::name::evt_manager);
+ ownerService->bus.sendUnicast(std::move(msg), service::name::evt_manager);
}
- void HSP::HSPImpl::packetHandler(uint8_t packetType, uint16_t channel, uint8_t *event, uint16_t eventSize)
+ void HSP::HSPImpl::packetHandler(std::uint8_t packetType,
+ [[maybe_unused]] std::uint16_t channel,
+ std::uint8_t *event,
+ std::uint16_t eventSize)
{
switch (packetType) {
case HCI_SCO_DATA_PACKET:
@@ 126,12 174,13 @@ namespace bluetooth
case HCI_EVENT_PACKET:
processHCIEvent(event);
break;
+
default:
break;
}
}
- void HSP::HSPImpl::processHCIEvent(uint8_t *event)
+ void HSP::HSPImpl::processHCIEvent(std::uint8_t *event)
{
switch (hci_event_packet_get_type(event)) {
case HCI_EVENT_SCO_CAN_SEND_NOW:
@@ 142,124 191,123 @@ namespace bluetooth
sco::utils::sendZeros(scoHandle);
}
break;
+
case HCI_EVENT_HSP_META:
processHSPEvent(event);
break;
+
default:
break;
}
}
- void HSP::HSPImpl::processHSPEvent(uint8_t *event)
+ void HSP::HSPImpl::processHSPEvent(std::uint8_t *event)
{
- auto eventDescriptor = event[2];
- switch (eventDescriptor) {
- case HSP_SUBEVENT_RFCOMM_CONNECTION_COMPLETE:
- if (hsp_subevent_rfcomm_connection_complete_get_status(event) != 0u) {
- LOG_DEBUG("RFCOMM connection establishement failed with status %u\n",
+ switch (hci_event_hsp_meta_get_subevent_code(event)) {
+ case HSP_SUBEVENT_RFCOMM_CONNECTION_COMPLETE: {
+ if (hsp_subevent_rfcomm_connection_complete_get_status(event) != ERROR_CODE_SUCCESS) {
+ LOG_ERROR("RFCOMM connection failed, status: 0x%02X",
hsp_subevent_rfcomm_connection_complete_get_status(event));
sendAudioEvent(audio::EventType::BluetoothHSPDeviceState, audio::Event::DeviceState::Disconnected);
- isConnected = false;
+ state = HSPState::RfcommDisconnected;
break;
}
- LOG_DEBUG("RFCOMM connection established.\n");
+
+ LOG_INFO("RFCOMM connection established");
sendAudioEvent(audio::EventType::BluetoothHSPDeviceState, audio::Event::DeviceState::Connected);
- {
- auto &busProxy = const_cast<sys::Service *>(ownerService)->bus;
- device.deviceState = DeviceState::ConnectedVoice;
- busProxy.sendUnicast(std::make_shared<message::bluetooth::ConnectResult>(device, true),
- service::name::bluetooth);
- }
- isConnected = true;
- break;
+ state = HSPState::RfcommConnected;
+ device.deviceState = DeviceState::ConnectedVoice;
+
+ using message::bluetooth::ConnectResult;
+ ownerService->bus.sendUnicast(std::make_shared<ConnectResult>(device, ConnectResult::Result::Success),
+ service::name::bluetooth);
+ } break;
+
case HSP_SUBEVENT_RFCOMM_DISCONNECTION_COMPLETE: {
- LOG_DEBUG("RFCOMM disconnected.\n");
+ LOG_INFO("RFCOMM disconnected");
sendAudioEvent(audio::EventType::BluetoothHSPDeviceState, audio::Event::DeviceState::Disconnected);
- auto &busProxy = const_cast<sys::Service *>(ownerService)->bus;
- busProxy.sendUnicast(std::make_shared<message::bluetooth::DisconnectResult>(device),
- service::name::bluetooth);
-
- isConnected = false;
+ state = HSPState::RfcommDisconnected;
+ ownerService->bus.sendUnicast(std::make_shared<message::bluetooth::DisconnectResult>(device),
+ service::name::bluetooth);
} break;
- case HSP_SUBEVENT_AUDIO_CONNECTION_COMPLETE:
- if (hsp_subevent_audio_connection_complete_get_status(event) != 0u) {
- LOG_DEBUG("Audio connection establishment failed with status %u\n",
- hsp_subevent_audio_connection_complete_get_status(event));
- isConnected = false;
- callAnswered = false;
+
+ case HSP_SUBEVENT_AUDIO_CONNECTION_COMPLETE: {
+ const auto status = hsp_subevent_audio_connection_complete_get_status(event);
+ if (status != ERROR_CODE_SUCCESS) {
+ LOG_ERROR("Audio connection establishment failed, status: 0x%02X", status);
+ state = HSPState::RfcommDisconnected;
audioDevice.reset();
+ break;
}
- else {
- scoHandle = hsp_subevent_audio_connection_complete_get_sco_handle(event);
- LOG_DEBUG("Audio connection established with SCO handle 0x%04x.\n", scoHandle);
- callAnswered = true;
- hci_request_sco_can_send_now_event();
- }
- break;
- case HSP_SUBEVENT_AUDIO_DISCONNECTION_COMPLETE:
- LOG_DEBUG("Audio connection released.\n\n");
- scoHandle = HCI_CON_HANDLE_INVALID;
- callAnswered = false;
- sendAudioEvent(audio::EventType::BluetoothHSPDeviceState, audio::Event::DeviceState::Disconnected);
- break;
- case HSP_SUBEVENT_MICROPHONE_GAIN_CHANGED:
- LOG_DEBUG("Received microphone gain change %d\n", hsp_subevent_microphone_gain_changed_get_gain(event));
- break;
+
+ scoHandle = hsp_subevent_audio_connection_complete_get_sco_handle(event);
+ LOG_INFO("Audio connection established with SCO handle 0x%04X", scoHandle);
+ state = HSPState::Answered;
+
+ audioInterface->startAudioRouting(ownerService);
+ hci_request_sco_can_send_now_event();
+ } break;
+
+ case HSP_SUBEVENT_AUDIO_DISCONNECTION_COMPLETE: {
+ scoHandle = HCI_CON_HANDLE_INVALID;
+ audioDevice.reset();
+ state = HSPState::RfcommConnected;
+ LOG_INFO("Audio disconnected");
+ } break;
+
+ case HSP_SUBEVENT_MICROPHONE_GAIN_CHANGED: {
+ LOG_INFO("Received microphone gain change: %d", hsp_subevent_microphone_gain_changed_get_gain(event));
+ } break;
+
case HSP_SUBEVENT_SPEAKER_GAIN_CHANGED: {
const auto volume = hsp_subevent_speaker_gain_changed_get_gain(event);
- auto &busProxy = const_cast<sys::Service *>(ownerService)->bus;
- busProxy.sendUnicast(std::make_shared<message::bluetooth::HSPVolume>(volume), service::name::bluetooth);
- LOG_DEBUG("Received speaker gain change %d\n", hsp_subevent_speaker_gain_changed_get_gain(event));
+ LOG_INFO("Received speaker gain change: %d", hsp_subevent_speaker_gain_changed_get_gain(event));
+ ownerService->bus.sendUnicast(std::make_shared<message::bluetooth::HSPVolume>(volume),
+ service::name::bluetooth);
} break;
+
case HSP_SUBEVENT_HS_CALL_ANSWER:
- LOG_DEBUG("HSP CALL ANSWER");
- cellularInterface->answerIncomingCall(const_cast<sys::Service *>(ownerService));
+ LOG_INFO("HSP call answer");
+ cellularInterface->answerIncomingCall(ownerService);
break;
+
case HSP_SUBEVENT_HS_CALL_HANGUP:
- LOG_DEBUG("HSP CALL HANGUP");
- cellularInterface->hangupCall(const_cast<sys::Service *>(ownerService));
+ LOG_INFO("HSP call hangup");
+ cellularInterface->hangupCall(ownerService);
break;
+
case HSP_SUBEVENT_HS_COMMAND: {
- ATcommandBuffer.fill(0);
- auto cmd_length = hsp_subevent_hs_command_get_value_length(event);
- auto size = cmd_length <= ATcommandBuffer.size() ? cmd_length : ATcommandBuffer.size();
- auto commandValue = hsp_subevent_hs_command_get_value(event);
- memcpy(ATcommandBuffer.data(), commandValue, size - 1);
- LOG_DEBUG("Received custom command: \"%s\". \nExit code or call hsp_ag_send_result.\n",
- ATcommandBuffer.data());
+ const std::size_t cmdLength = hsp_subevent_hs_command_get_value_length(event);
+ const auto size = std::min(cmdLength, sizeof(ATCommandBuffer));
+ const auto commandValue = hsp_subevent_hs_command_get_value(event);
+
+ std::memset(ATCommandBuffer, 0, sizeof(ATCommandBuffer));
+ std::memcpy(ATCommandBuffer, commandValue, size - 1);
+
+ LOG_INFO("Received custom command: '%s'", ATCommandBuffer);
break;
}
+
case HSP_SUBEVENT_BUTTON_PRESSED: {
- if (scoHandle == HCI_CON_HANDLE_INVALID) {
- if (isRinging) {
- LOG_DEBUG("Button event -> establish audio");
- establishAudioConnection();
- audioInterface->startAudioRouting(const_cast<sys::Service *>(ownerService));
- cellularInterface->answerIncomingCall(const_cast<sys::Service *>(ownerService));
- }
+ if ((scoHandle == HCI_CON_HANDLE_INVALID) && (state == HSPState::Ringing)) {
+ LOG_INFO("Received button event in ringing state, answering call");
+ cellularInterface->answerIncomingCall(ownerService);
break;
}
- LOG_DEBUG("Button event -> release audio");
- isRinging = false;
- if (callAnswered) {
- cellularInterface->hangupCall(const_cast<sys::Service *>(ownerService));
+
+ if (state == HSPState::Answered) {
+ LOG_INFO("Received button event in answered state, hanging up call");
+ cellularInterface->hangupCall(ownerService);
}
- callAnswered = false;
- hsp_ag_release_audio_connection();
} break;
+
default:
- LOG_DEBUG("event not handled %u\n", event[2]);
+ LOG_INFO("Event not handled: 0x%02X", hci_event_hsp_meta_get_subevent_code(event));
break;
}
}
- void HSP::HSPImpl::establishAudioConnection()
- {
- LOG_DEBUG("Establish Audio connection...\n");
- hsp_ag_establish_audio_connection();
- }
-
- auto HSP::HSPImpl::init() -> Error::Code
+ auto HSP::HSPImpl::init() -> Result::Code
{
sco = std::make_unique<SCO>();
sco->setOwnerService(ownerService);
@@ 271,33 319,30 @@ namespace bluetooth
Profile::initL2cap();
Profile::initSdp();
- serviceBuffer.fill(0);
- constexpr uint32_t hspSdpRecordHandle = 0x10004;
- hsp_ag_create_sdp_record(serviceBuffer.data(), hspSdpRecordHandle, rfcommChannelNr, agServiceName.data());
+ std::memset(serviceBuffer, 0, sizeof(serviceBuffer));
+
+ hsp_ag_create_sdp_record(serviceBuffer, hspSdpRecordHandle, rfcommChannelNr, agServiceName);
- if (const auto status = sdp_register_service(serviceBuffer.data()); status != ERROR_CODE_SUCCESS) {
- LOG_ERROR("Can't register service. Status %x", status);
+ if (const auto status = sdp_register_service(serviceBuffer); status != ERROR_CODE_SUCCESS) {
+ LOG_ERROR("Can't register service, status: 0x%02X", status);
}
rfcomm_init();
hsp_ag_init(rfcommChannelNr);
- hsp_ag_register_packet_handler(&packetHandler);
- // register for SCO packets
+ hciEventCallbackRegistration.callback = &packetHandler;
+ hci_add_event_handler(&hciEventCallbackRegistration);
+ hsp_ag_register_packet_handler(&packetHandler);
hci_register_sco_packet_handler(&packetHandler);
- gap_discoverable_control(1);
- gap_set_class_of_device(CLASS_OF_DEVICE);
-
- LOG_INFO("HSP init done!");
-
- return bluetooth::Error::Success;
+ LOG_INFO("HSP initialized!");
+ return bluetooth::Result::Code::Success;
}
void HSP::HSPImpl::connect()
{
- if (isConnected) {
+ if (state != HSPState::RfcommDisconnected) {
disconnect();
}
hsp_ag_connect(device.address);
@@ 307,87 352,66 @@ namespace bluetooth
{
hsp_ag_release_audio_connection();
hsp_ag_disconnect();
- auto &busProxy = const_cast<sys::Service *>(ownerService)->bus;
- busProxy.sendUnicast(std::make_shared<message::bluetooth::DisconnectResult>(device), service::name::bluetooth);
+ ownerService->bus.sendUnicast(std::make_shared<message::bluetooth::DisconnectResult>(device),
+ service::name::bluetooth);
}
void HSP::HSPImpl::setDevice(const Devicei &dev)
{
device = dev;
- LOG_INFO("Device set!");
+ LOG_DEBUG("Device set!");
}
- void HSP::HSPImpl::setOwnerService(const sys::Service *service)
+ void HSP::HSPImpl::setAudioDevice(std::shared_ptr<bluetooth::BluetoothAudioDevice> audioDev)
{
- ownerService = service;
+ HSP::HSPImpl::audioDevice = std::static_pointer_cast<CVSDAudioDevice>(audioDev);
}
- void HSP::HSPImpl::startRinging() const noexcept
+ void HSP::HSPImpl::setOwnerService(sys::Service *service)
{
- LOG_DEBUG("Bluetooth ring started");
- hsp_ag_start_ringing();
- isRinging = true;
+ ownerService = service;
}
- void HSP::HSPImpl::stopRinging() const noexcept
+ auto HSP::HSPImpl::incomingCallStarted() const noexcept -> Result::Code
{
- LOG_DEBUG("Bluetooth ring stopped");
- hsp_ag_stop_ringing();
- isRinging = false;
+ LOG_DEBUG("Incoming call started");
+ hsp_ag_start_ringing();
+ state = HSPState::Ringing;
+ return Result::Code::Success;
}
- void HSP::HSPImpl::initializeCall() const noexcept
+ auto HSP::HSPImpl::outgoingCallStarted([[maybe_unused]] const std::string &number) const noexcept -> Result::Code
{
- stopRinging();
- establishAudioConnection();
+ LOG_DEBUG("Outgoing call started");
+ hsp_ag_establish_audio_connection();
+ return Result::Code::Success;
}
- void HSP::setAudioDevice(std::shared_ptr<bluetooth::BluetoothAudioDevice> audioDevice)
- {
- pimpl->setAudioDevice(audioDevice);
- }
- auto HSP::callActive() const noexcept -> Error::Code
- {
- return Error::Success;
- }
- auto HSP::setIncomingCallNumber(const std::string &num) const noexcept -> Error::Code
- {
- return Error::Success;
- }
- auto HSP::setSignalStrength(int bars) const noexcept -> Error::Code
- {
- return Error::Success;
- }
- auto HSP::setOperatorName(const std::string_view &name) const noexcept -> Error::Code
- {
- return Error::Success;
- }
- auto HSP::setBatteryLevel(const BatteryLevel &name) const noexcept -> Error::Code
- {
- return Error::Success;
- }
- auto HSP::terminateCall() const noexcept -> Error::Code
- {
- return pimpl->terminateCall();
- }
- auto HSP::setNetworkRegistrationStatus(bool registered) const noexcept -> Error::Code
+ auto HSP::HSPImpl::incomingCallAnswered() const noexcept -> Result::Code
{
- return Error::Success;
+ LOG_DEBUG("Incoming call answered");
+ hsp_ag_stop_ringing();
+ hsp_ag_establish_audio_connection();
+ return Result::Code::Success;
}
- auto HSP::setRoamingStatus(bool enabled) const noexcept -> Error::Code
+
+ auto HSP::HSPImpl::outgoingCallAnswered() const noexcept -> Result::Code
{
- return Error::Success;
+ LOG_DEBUG("Outgoing call answered");
+ return Result::Code::Success;
}
- void HSP::HSPImpl::setAudioDevice(std::shared_ptr<bluetooth::BluetoothAudioDevice> audioDevice)
+ auto HSP::HSPImpl::callTerminated() const noexcept -> Result::Code
{
- HSP::HSPImpl::audioDevice = std::static_pointer_cast<CVSDAudioDevice>(audioDevice);
+ LOG_DEBUG("Call terminated");
+ hsp_ag_stop_ringing();
+ hsp_ag_release_audio_connection();
+ state = HSPState::RfcommConnected;
+ return Result::Code::Success;
}
- auto HSP::HSPImpl::terminateCall() const noexcept -> Error::Code
+
+ auto HSP::HSPImpl::callMissed() const noexcept -> Result::Code
{
- stopRinging();
- hsp_ag_release_audio_connection();
- callAnswered = false;
- return Error::Success;
+ return callTerminated();
}
} // namespace bluetooth
M module-bluetooth/Bluetooth/interface/profiles/HSP/HSP.hpp => module-bluetooth/Bluetooth/interface/profiles/HSP/HSP.hpp +15 -26
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
@@ 12,8 12,6 @@ namespace bluetooth
{
class HSP : public CallProfile
{
- static constexpr auto CLASS_OF_DEVICE = 0x400204;
- // Service class: Telephony, Major device class: Phone, Minor device class: Cellular
public:
HSP();
~HSP() override;
@@ 23,44 21,35 @@ namespace bluetooth
HSP(HSP &&other) noexcept;
auto operator=(HSP &&other) noexcept -> HSP &;
- auto init() -> Error::Code override;
+ auto init() -> Result::Code override;
void setDevice(const Devicei &device) override;
- void setOwnerService(const sys::Service *service) override;
+ void setOwnerService(sys::Service *service) override;
void connect() override;
void disconnect() override;
- /// @brief Starts ring
- /// @return Success
- [[nodiscard]] auto startRinging() const noexcept -> Error::Code override;
- /// @brief Stops ring
- /// @return Success
- [[nodiscard]] auto stopRinging() const noexcept -> Error::Code override;
- /// @brief Initializes bluetooth audio call which is divided into two parts:
- /// - Ring stop
- /// - SCO link establishment
- /// @return Success
- [[nodiscard]] auto initializeCall() const noexcept -> Error::Code override;
- [[nodiscard]] auto terminateCall() const noexcept -> Error::Code override;
- [[nodiscard]] auto callActive() const noexcept -> Error::Code override;
- [[nodiscard]] auto setIncomingCallNumber(const std::string &num) const noexcept -> Error::Code override;
+ [[nodiscard]] auto incomingCallStarted() const noexcept -> Result::Code override;
+ [[nodiscard]] auto outgoingCallStarted(const std::string &number) const noexcept -> Result::Code override;
+ [[nodiscard]] auto incomingCallAnswered() const noexcept -> Result::Code override;
+ [[nodiscard]] auto outgoingCallAnswered() const noexcept -> Result::Code override;
+ [[nodiscard]] auto callTerminated() const noexcept -> Result::Code override;
+ [[nodiscard]] auto callMissed() const noexcept -> Result::Code override;
+ [[nodiscard]] auto setIncomingCallNumber(const std::string &num) const noexcept -> Result::Code override;
/// @return Success - ignoring in HSP
- [[nodiscard]] auto setSignalStrength(int bars) const noexcept -> Error::Code override;
+ [[nodiscard]] auto setSignalStrength(int bars) const noexcept -> Result::Code override;
/// @return Success - ignoring in HSP
- [[nodiscard]] auto setOperatorName(const std::string_view &name) const noexcept -> Error::Code override;
+ [[nodiscard]] auto setOperatorName(const std::string_view &name) const noexcept -> Result::Code override;
/// @return Success - ignoring in HSP
- [[nodiscard]] auto setBatteryLevel(const BatteryLevel &level) const noexcept -> Error::Code override;
+ [[nodiscard]] auto setBatteryLevel(const BatteryLevel &level) const noexcept -> Result::Code override;
/// @return Success - ignoring in HSP
- [[nodiscard]] auto setNetworkRegistrationStatus(bool registered) const noexcept -> Error::Code override;
+ [[nodiscard]] auto setNetworkRegistrationStatus(bool registered) const noexcept -> Result::Code override;
/// @return Success - ignoring in HSP
- auto setRoamingStatus(bool enabled) const noexcept -> Error::Code override;
+ auto setRoamingStatus(bool enabled) const noexcept -> Result::Code override;
void setAudioDevice(std::shared_ptr<bluetooth::BluetoothAudioDevice> audioDevice) override;
private:
class HSPImpl;
std::unique_ptr<HSPImpl> pimpl;
- const sys::Service *ownerService{};
- btstack_run_loop *runLoopInstance{};
};
} // namespace bluetooth
M module-bluetooth/Bluetooth/interface/profiles/HSP/HSPImpl.hpp => module-bluetooth/Bluetooth/interface/profiles/HSP/HSPImpl.hpp +45 -25
@@ 1,50 1,70 @@
-// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
+
#include "HSP.hpp"
-#include "Error.hpp"
+#include "Result.hpp"
#include <interface/profiles/SCO/SCO.hpp>
#include <Audio/AudioCommon.hpp>
namespace bluetooth
{
- static constexpr int serviceBufferLength = 150;
- static constexpr int commandBufferLength = 150;
-
class HSP::HSPImpl
{
public:
- static void packetHandler(uint8_t packetType, uint16_t channel, uint8_t *event, uint16_t eventSize);
- auto init() -> Error::Code;
- void startRinging() const noexcept;
- void stopRinging() const noexcept;
- void initializeCall() const noexcept;
- auto terminateCall() const noexcept -> Error::Code;
+ enum class HSPState
+ {
+ RfcommDisconnected,
+ RfcommConnected,
+ Ringing,
+ Answered
+ };
+
+ static void packetHandler(std::uint8_t packetType,
+ std::uint16_t channel,
+ std::uint8_t *event,
+ std::uint16_t eventSize);
+ auto init() -> Result::Code;
+ auto incomingCallStarted() const noexcept -> Result::Code;
+ auto outgoingCallStarted(const std::string &number) const noexcept -> Result::Code;
+ auto incomingCallAnswered() const noexcept -> Result::Code;
+ auto outgoingCallAnswered() const noexcept -> Result::Code;
+ auto callTerminated() const noexcept -> Result::Code;
+ auto callMissed() const noexcept -> Result::Code;
void connect();
void disconnect();
void setDevice(const Devicei &dev);
- void setOwnerService(const sys::Service *service);
+ void setOwnerService(sys::Service *service);
void setAudioDevice(std::shared_ptr<bluetooth::BluetoothAudioDevice> audioDevice);
private:
static void sendAudioEvent(audio::EventType event, audio::Event::DeviceState state);
- static void processHCIEvent(uint8_t *event);
- static void processHSPEvent(uint8_t *event);
- static void establishAudioConnection();
- static std::array<uint8_t, serviceBufferLength> serviceBuffer;
- static constexpr uint8_t rfcommChannelNr = 1;
- static const std::string_view agServiceName;
- static uint16_t scoHandle;
+ static void processHCIEvent(std::uint8_t *event);
+ static void processHSPEvent(std::uint8_t *event);
+
+ static constexpr auto serviceBufferSize = 150;
+ static constexpr auto commandBufferSize = 150;
+ static constexpr std::uint8_t rfcommChannelNr = 1;
+ static constexpr std::uint32_t hspSdpRecordHandle = 0x10004;
+
+ static hci_con_handle_t scoHandle;
+
+ static std::uint8_t serviceBuffer[serviceBufferSize];
+
+ static const char *agServiceName;
+
static std::unique_ptr<SCO> sco;
+ static std::shared_ptr<CVSDAudioDevice> audioDevice;
+
static std::unique_ptr<CellularInterface> cellularInterface;
static std::unique_ptr<AudioInterface> audioInterface;
- static std::array<char, commandBufferLength> ATcommandBuffer;
- static const sys::Service *ownerService;
- static bool isConnected;
- static bool callAnswered;
- static bool isRinging;
- static std::shared_ptr<CVSDAudioDevice> audioDevice;
+
+ static sys::Service *ownerService;
static Devicei device;
+
+ static btstack_packet_callback_registration_t hciEventCallbackRegistration;
+ static char ATCommandBuffer[commandBufferSize];
+ static HSPState state;
};
} // namespace bluetooth
M module-bluetooth/Bluetooth/interface/profiles/Profile.hpp => module-bluetooth/Bluetooth/interface/profiles/Profile.hpp +24 -24
@@ 1,9 1,9 @@
-// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
-#include "Error.hpp"
+#include "Result.hpp"
#include <audio/BluetoothAudioDevice.hpp>
#include <Service/Message.hpp>
@@ 13,14 13,13 @@
namespace bluetooth
{
-
class Profile
{
public:
virtual ~Profile() = default;
- virtual auto init() -> Error::Code = 0;
+ virtual auto init() -> Result::Code = 0;
virtual void setDevice(const Devicei &device) = 0;
- virtual void setOwnerService(const sys::Service *service) = 0;
+ virtual void setOwnerService(sys::Service *service) = 0;
virtual void connect() = 0;
virtual void disconnect() = 0;
virtual void setAudioDevice(std::shared_ptr<bluetooth::BluetoothAudioDevice> audioDevice) = 0;
@@ 44,41 43,42 @@ namespace bluetooth
class CallProfile : public Profile
{
public:
- [[nodiscard]] virtual auto startRinging() const noexcept -> Error::Code = 0;
- /// Stops ringing
+ /// Executed after incoming call has been received
/// @return Error code that determines, whether operation was successful or not
- [[nodiscard]] virtual auto stopRinging() const noexcept -> Error::Code = 0;
- /// Initializes call
+ [[nodiscard]] virtual auto incomingCallStarted() const noexcept -> Result::Code = 0;
+ /// Executed after outgoing call has been placed
+ /// @param outgoing call number
/// @return Error code that determines, whether operation was successful or not
- [[nodiscard]] virtual auto initializeCall() const noexcept -> Error::Code = 0;
- /// Terminates call
+ [[nodiscard]] virtual auto outgoingCallStarted(const std::string &number) const noexcept -> Result::Code = 0;
+ /// Executed after incoming call is answered
/// @return Error code that determines, whether operation was successful or not
- [[nodiscard]] virtual auto terminateCall() const noexcept -> Error::Code = 0;
- /// Executed after the call is answered
+ [[nodiscard]] virtual auto incomingCallAnswered() const noexcept -> Result::Code = 0;
+ /// Executed after outgoing call is answered
/// @return Error code that determines, whether operation was successful or not
- [[nodiscard]] virtual auto callActive() const noexcept -> Error::Code = 0;
- /// Executed after the call has been started
- /// @param outgoing call number
+ [[nodiscard]] virtual auto outgoingCallAnswered() const noexcept -> Result::Code = 0;
+ /// Executed after termination of the ongoing call
/// @return Error code that determines, whether operation was successful or not
- [[nodiscard]] virtual auto callStarted(const std::string &num) const noexcept -> Error::Code = 0;
+ [[nodiscard]] virtual auto callTerminated() const noexcept -> Result::Code = 0;
+ /// Executed after termination of the incoming call that has not yet been answered
+ /// @return Error code that determines, whether operation was successful or not
+ [[nodiscard]] virtual auto callMissed() const noexcept -> Result::Code = 0;
/// Sets the incoming call number
/// @return Error code that determines, whether operation was successful or not
- [[nodiscard]] virtual auto setIncomingCallNumber(const std::string &num) const noexcept -> Error::Code = 0;
+ [[nodiscard]] virtual auto setIncomingCallNumber(const std::string &num) const noexcept -> Result::Code = 0;
/// Sets the signal strength bars data in HFP profile
/// @return Error code that determines, whether operation was successful or not
- [[nodiscard]] virtual auto setSignalStrength(int bars) const noexcept -> Error::Code = 0;
+ [[nodiscard]] virtual auto setSignalStrength(int bars) const noexcept -> Result::Code = 0;
/// Sets the operator name in HFP profile
/// @return Error code that determines, whether operation was successful or not
- [[nodiscard]] virtual auto setOperatorName(const std::string_view &name) const noexcept -> Error::Code = 0;
+ [[nodiscard]] virtual auto setOperatorName(const std::string_view &name) const noexcept -> Result::Code = 0;
/// Sets the operator name in HFP profile
/// @return Error code that determines, whether operation was successful or not
- [[nodiscard]] virtual auto setBatteryLevel(const BatteryLevel &level) const noexcept -> Error::Code = 0;
+ [[nodiscard]] virtual auto setBatteryLevel(const BatteryLevel &level) const noexcept -> Result::Code = 0;
/// Sets the network registration status in HFP profile
/// @return Error code that determines, whether operation was successful or not
- [[nodiscard]] virtual auto setNetworkRegistrationStatus(bool registered) const noexcept -> Error::Code = 0;
+ [[nodiscard]] virtual auto setNetworkRegistrationStatus(bool registered) const noexcept -> Result::Code = 0;
/// Sets the roaming status in HFP profile
/// @return Error code that determines, whether operation was successful or not
- virtual auto setRoamingStatus(bool enabled) const noexcept -> Error::Code = 0;
+ virtual auto setRoamingStatus(bool enabled) const noexcept -> Result::Code = 0;
};
-
} // namespace bluetooth
M module-bluetooth/Bluetooth/interface/profiles/ProfileManager.cpp => module-bluetooth/Bluetooth/interface/profiles/ProfileManager.cpp +53 -46
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include <service-bluetooth/ServiceBluetooth.hpp>
@@ 7,11 7,10 @@
namespace bluetooth
{
-
ProfileManager::ProfileManager(sys::Service *ownerService) : ownerService(ownerService)
{}
- auto ProfileManager::init() -> Error::Code
+ auto ProfileManager::init() -> Result::Code
{
if (!initialized) {
profilesList = {{AudioProfile::A2DP, std::make_shared<bluetooth::A2DP>()},
@@ 34,10 33,10 @@ namespace bluetooth
}
initialized = true;
}
- return Error::Success;
+ return Result::Code::Success;
}
- auto ProfileManager::connect(const Devicei &device) -> Error::Code
+ auto ProfileManager::connect(const Devicei &device) -> Result::Code
{
for (auto &[profileName, ptr] : profilesList) {
if (ptr != nullptr) {
@@ 45,102 44,118 @@ namespace bluetooth
ptr->connect();
}
}
- return Error::Success;
+ return Result::Code::Success;
}
- auto ProfileManager::disconnect() -> Error::Code
+ auto ProfileManager::disconnect() -> Result::Code
{
for (auto &[profileName, ptr] : profilesList) {
if (ptr != nullptr) {
ptr->disconnect();
}
}
- return Error::Success;
+ return Result::Code::Success;
}
- auto ProfileManager::start() -> Error::Code
+ auto ProfileManager::start() -> Result::Code
{
musicProfilePtr->start();
- return Error::Success;
+ return Result::Code::Success;
}
- auto ProfileManager::stop() -> Error::Code
+ auto ProfileManager::stop() -> Result::Code
{
musicProfilePtr->stop();
- return Error::Success;
+ return Result::Code::Success;
}
- auto ProfileManager::startRinging() -> Error::Code
+ auto ProfileManager::incomingCallStarted() -> Result::Code
{
- return callProfilePtr->startRinging();
+ return callProfilePtr->incomingCallStarted();
}
- auto ProfileManager::stopRinging() -> Error::Code
+ auto ProfileManager::outgoingCallStarted(const utils::PhoneNumber &nr) -> Result::Code
{
- return callProfilePtr->stopRinging();
+ if (callProfilePtr) {
+ return callProfilePtr->outgoingCallStarted(nr.getView().getNonEmpty());
+ }
+ LOG_ERROR("No profile, returning!");
+ return Result::Code::NotReady;
}
- auto ProfileManager::initializeCall() -> Error::Code
+ auto ProfileManager::incomingCallAnswered() -> Result::Code
{
- return callProfilePtr->initializeCall();
+ return callProfilePtr->incomingCallAnswered();
}
- auto ProfileManager::terminateCall() -> Error::Code
+
+ auto ProfileManager::outgoingCallAnswered() -> Result::Code
{
- return callProfilePtr->terminateCall();
+ return callProfilePtr->outgoingCallAnswered();
}
- auto ProfileManager::setAudioDevice(std::shared_ptr<BluetoothAudioDevice> device) -> Error::Code
+ auto ProfileManager::callTerminated() -> Result::Code
+ {
+ return callProfilePtr->callTerminated();
+ }
+
+ auto ProfileManager::callMissed() -> Result::Code
+ {
+ return callProfilePtr->callMissed();
+ }
+
+ auto ProfileManager::setAudioDevice(std::shared_ptr<BluetoothAudioDevice> device) -> Result::Code
{
auto profileType = device->getProfileType();
if (profilesList[profileType] == nullptr) {
- return Error::NotReady;
+ return Result::Code::NotReady;
}
profilesList[profileType]->setAudioDevice(device);
LOG_ERROR("AudioDevice for profile: %s set!", magic_enum::enum_name(profileType).data());
- return Error::Success;
- }
- auto ProfileManager::callAnswered() -> Error::Code
- {
- return callProfilePtr->callActive();
+ return Result::Code::Success;
}
- auto ProfileManager::setIncomingCallNumber(const utils::PhoneNumber &nr) -> Error::Code
+
+ auto ProfileManager::setIncomingCallNumber(const utils::PhoneNumber &nr) -> Result::Code
{
if (callProfilePtr) {
return callProfilePtr->setIncomingCallNumber(nr.getView().getE164());
}
LOG_ERROR("No profile, returning!");
- return Error::NotReady;
+ return Result::Code::NotReady;
}
- auto ProfileManager::setSignalStrengthData(const DataVariant &data) -> Error::Code
+
+ auto ProfileManager::setSignalStrengthData(const DataVariant &data) -> Result::Code
{
auto signalData = std::get<Store::SignalStrength>(data);
if (callProfilePtr) {
return callProfilePtr->setSignalStrength(static_cast<int>(signalData.rssiBar));
}
LOG_ERROR("No profile, returning!");
- return Error::NotReady;
+ return Result::Code::NotReady;
}
- auto ProfileManager::setOperatorNameData(const DataVariant &data) -> Error::Code
+
+ auto ProfileManager::setOperatorNameData(const DataVariant &data) -> Result::Code
{
auto operatorName = std::get<OperatorName>(data);
if (callProfilePtr) {
return callProfilePtr->setOperatorName(operatorName.getName());
}
LOG_ERROR("No profile, returning!");
- return Error::NotReady;
+ return Result::Code::NotReady;
}
- auto ProfileManager::setBatteryLevelData(unsigned int level) -> Error::Code
+
+ auto ProfileManager::setBatteryLevelData(unsigned int level) -> Result::Code
{
auto batteryLevel = BatteryLevel(level);
if (callProfilePtr) {
return callProfilePtr->setBatteryLevel(batteryLevel);
}
LOG_ERROR("No profile, returning!");
- return Error::NotReady;
+ return Result::Code::NotReady;
}
- auto ProfileManager::setNetworkStatusData(const DataVariant &data) -> Error::Code
+
+ auto ProfileManager::setNetworkStatusData(const DataVariant &data) -> Result::Code
{
auto status = std::get<Store::Network::Status>(data);
if (callProfilePtr) {
@@ 155,16 170,9 @@ namespace bluetooth
}
}
LOG_ERROR("No profile, returning!");
- return Error::NotReady;
- }
- auto ProfileManager::callStarted(const utils::PhoneNumber &nr) -> Error::Code
- {
- if (callProfilePtr) {
- return callProfilePtr->callStarted(nr.getView().getE164());
- }
- LOG_ERROR("No profile, returning!");
- return Error::NotReady;
+ return Result::Code::NotReady;
}
+
void ProfileManager::deInit()
{
for (auto &[profileName, ptr] : profilesList) {
@@ 178,5 186,4 @@ namespace bluetooth
LOG_DEBUG("ProfileManager deinit done");
}
-
} // namespace bluetooth
M module-bluetooth/Bluetooth/interface/profiles/ProfileManager.hpp => module-bluetooth/Bluetooth/interface/profiles/ProfileManager.hpp +36 -36
@@ 1,10 1,10 @@
-// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
#include <Service/Service.hpp>
-#include <Error.hpp>
+#include "Result.hpp"
#include "Profile.hpp"
#include "AudioProfile.hpp"
#include "interface/profiles/A2DP/A2DP.hpp"
@@ 30,24 30,24 @@ namespace bluetooth
{
public:
virtual ~BaseProfileManager() = default;
- virtual auto init() -> Error::Code = 0;
+ virtual auto init() -> Result::Code = 0;
virtual void deInit() = 0;
- virtual auto connect(const Devicei &device) -> Error::Code = 0;
- virtual auto disconnect() -> Error::Code = 0;
- virtual auto start() -> Error::Code = 0;
- virtual auto stop() -> Error::Code = 0;
- virtual auto startRinging() -> Error::Code = 0;
- virtual auto stopRinging() -> Error::Code = 0;
- virtual auto initializeCall() -> Error::Code = 0;
- virtual auto terminateCall() -> Error::Code = 0;
- virtual auto callAnswered() -> Error::Code = 0;
- virtual auto callStarted(const utils::PhoneNumber &) -> Error::Code = 0;
- virtual auto setIncomingCallNumber(const utils::PhoneNumber &nr) -> Error::Code = 0;
- virtual auto setSignalStrengthData(const DataVariant &data) -> Error::Code = 0;
- virtual auto setOperatorNameData(const DataVariant &data) -> Error::Code = 0;
- virtual auto setBatteryLevelData(unsigned int) -> Error::Code = 0;
- virtual auto setNetworkStatusData(const DataVariant &data) -> Error::Code = 0;
- virtual auto setAudioDevice(std::shared_ptr<BluetoothAudioDevice> device) -> Error::Code = 0;
+ virtual auto connect(const Devicei &device) -> Result::Code = 0;
+ virtual auto disconnect() -> Result::Code = 0;
+ virtual auto start() -> Result::Code = 0;
+ virtual auto stop() -> Result::Code = 0;
+ virtual auto incomingCallStarted() -> Result::Code = 0;
+ virtual auto outgoingCallStarted(const utils::PhoneNumber &) -> Result::Code = 0;
+ virtual auto incomingCallAnswered() -> Result::Code = 0;
+ virtual auto outgoingCallAnswered() -> Result::Code = 0;
+ virtual auto callTerminated() -> Result::Code = 0;
+ virtual auto callMissed() -> Result::Code = 0;
+ virtual auto setIncomingCallNumber(const utils::PhoneNumber &nr) -> Result::Code = 0;
+ virtual auto setSignalStrengthData(const DataVariant &data) -> Result::Code = 0;
+ virtual auto setOperatorNameData(const DataVariant &data) -> Result::Code = 0;
+ virtual auto setBatteryLevelData(unsigned int) -> Result::Code = 0;
+ virtual auto setNetworkStatusData(const DataVariant &data) -> Result::Code = 0;
+ virtual auto setAudioDevice(std::shared_ptr<BluetoothAudioDevice> device) -> Result::Code = 0;
};
class ProfileManager : public BaseProfileManager
@@ 56,25 56,25 @@ namespace bluetooth
explicit ProfileManager(sys::Service *ownerService);
ProfileManager() = delete;
- auto init() -> Error::Code override;
+ auto init() -> Result::Code override;
void deInit() override;
- auto connect(const Devicei &device) -> Error::Code override;
- auto disconnect() -> Error::Code override;
- auto start() -> Error::Code override;
- auto stop() -> Error::Code override;
- auto startRinging() -> Error::Code override;
- auto stopRinging() -> Error::Code override;
- auto initializeCall() -> Error::Code override;
- auto terminateCall() -> Error::Code override;
- auto callAnswered() -> Error::Code override;
- auto callStarted(const utils::PhoneNumber &) -> Error::Code override;
- auto setIncomingCallNumber(const utils::PhoneNumber &nr) -> Error::Code override;
- auto setSignalStrengthData(const DataVariant &data) -> Error::Code override;
- auto setOperatorNameData(const DataVariant &data) -> Error::Code override;
- auto setBatteryLevelData(unsigned int) -> Error::Code override;
- auto setNetworkStatusData(const DataVariant &data) -> Error::Code override;
+ auto connect(const Devicei &device) -> Result::Code override;
+ auto disconnect() -> Result::Code override;
+ auto start() -> Result::Code override;
+ auto stop() -> Result::Code override;
+ auto incomingCallStarted() -> Result::Code override;
+ auto outgoingCallStarted(const utils::PhoneNumber &nr) -> Result::Code override;
+ auto incomingCallAnswered() -> Result::Code override;
+ auto outgoingCallAnswered() -> Result::Code override;
+ auto callTerminated() -> Result::Code override;
+ auto callMissed() -> Result::Code override;
+ auto setIncomingCallNumber(const utils::PhoneNumber &nr) -> Result::Code override;
+ auto setSignalStrengthData(const DataVariant &data) -> Result::Code override;
+ auto setOperatorNameData(const DataVariant &data) -> Result::Code override;
+ auto setBatteryLevelData(unsigned int level) -> Result::Code override;
+ auto setNetworkStatusData(const DataVariant &data) -> Result::Code override;
- auto setAudioDevice(std::shared_ptr<BluetoothAudioDevice> device) -> Error::Code override;
+ auto setAudioDevice(std::shared_ptr<BluetoothAudioDevice> device) -> Result::Code override;
private:
sys::Service *ownerService;
M module-bluetooth/Bluetooth/interface/profiles/SCO/SCO.cpp => module-bluetooth/Bluetooth/interface/profiles/SCO/SCO.cpp +6 -6
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "SCO.hpp"
@@ 46,7 46,7 @@ namespace bluetooth
static const sys::Service *ownerService;
static uint8_t negotiated_codec;
- static auto audioInitialize(int sampleRate) -> Error;
+ static auto audioInitialize(int sampleRate) -> Result;
static void initCvsd();
static void receiveCvsd(uint8_t *packet, uint16_t size);
static void writeToHostEndian(int16_t *buffer, uint8_t *packet, int length);
@@ 110,7 110,7 @@ void SCO::SCOImpl::sendEvent(audio::EventType event, audio::Event::DeviceState s
auto &busProxy = const_cast<sys::Service *>(ownerService)->bus;
busProxy.sendUnicast(std::move(msg), service::name::evt_manager);
}
-auto SCO::SCOImpl::audioInitialize(int sampleRate) -> Error
+auto SCO::SCOImpl::audioInitialize(int sampleRate) -> Result
{
sourceQueue = xQueueCreate(5, sizeof(AudioData_t));
sinkQueue = xQueueCreate(5, sizeof(AudioData_t));
@@ 124,18 124,18 @@ auto SCO::SCOImpl::audioInitialize(int sampleRate) -> Error
if (sourceQueue == nullptr || sinkQueue == nullptr) {
LOG_ERROR("failed to create queue!");
- return Error(Error::SystemError);
+ return Result(Result::Code::SystemError);
}
LOG_INFO("Init done!");
- return Error(Error::Success);
+ return Result(Result::Code::Success);
}
void SCO::SCOImpl::initCvsd()
{
btstack_cvsd_plc_init(&cvsdPlcState);
auto ret = audioInitialize(CVSD_SAMPLE_RATE);
- if (ret.err == Error::Success) {
+ if (ret.result == Result::Code::Success) {
LOG_INFO("CVSD init done!");
}
}
M module-bluetooth/tests/tests-StatefulController.cpp => module-bluetooth/tests/tests-StatefulController.cpp +116 -59
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include <catch2/catch.hpp>
@@ 8,7 8,7 @@
using namespace bluetooth;
-auto InitializerMock = []() { return Error::Success; };
+auto InitializerMock = []() { return Result::Code::Success; };
namespace mock
{
@@ 22,10 22,10 @@ namespace mock
auto driver()
{
fakeit::Mock<AbstractDriver> mock;
- fakeit::When(Method(mock, init)).AlwaysReturn(Error::Code::Success);
- fakeit::When(Method(mock, run)).AlwaysReturn(Error::Code::Success);
- fakeit::When(Method(mock, stop)).AlwaysReturn(Error::Code::Success);
- fakeit::When(Method(mock, scan)).AlwaysReturn(Error::Code::Success);
+ fakeit::When(Method(mock, init)).AlwaysReturn(Result::Code::Success);
+ fakeit::When(Method(mock, run)).AlwaysReturn(Result::Code::Success);
+ fakeit::When(Method(mock, stop)).AlwaysReturn(Result::Code::Success);
+ fakeit::When(Method(mock, scan)).AlwaysReturn(Result());
fakeit::When(Method(mock, stopScan)).AlwaysReturn();
fakeit::When(Method(mock, setVisibility)).AlwaysReturn();
fakeit::When(Method(mock, pair)).AlwaysReturn();
@@ 38,14 38,14 @@ namespace mock
auto handler()
{
fakeit::Mock<AbstractCommandHandler> mock;
- fakeit::When(Method(mock, scan)).AlwaysReturn(Error::Code::Success);
- fakeit::When(Method(mock, stopScan)).AlwaysReturn(Error::Code::Success);
- fakeit::When(Method(mock, setVisibility)).AlwaysReturn(Error::Code::Success);
- fakeit::When(Method(mock, connect)).AlwaysReturn(Error::Code::Success);
- fakeit::When(Method(mock, disconnect)).AlwaysReturn(Error::Code::Success);
- fakeit::When(Method(mock, pair)).AlwaysReturn(Error::Code::Success);
- fakeit::When(Method(mock, unpair)).AlwaysReturn(Error::Code::Success);
- fakeit::When(Method(mock, availableDevices)).AlwaysReturn(Error::Code::Success);
+ fakeit::When(Method(mock, scan)).AlwaysReturn(Result::Code::Success);
+ fakeit::When(Method(mock, stopScan)).AlwaysReturn(Result::Code::Success);
+ fakeit::When(Method(mock, setVisibility)).AlwaysReturn(Result::Code::Success);
+ fakeit::When(Method(mock, connect)).AlwaysReturn(Result::Code::Success);
+ fakeit::When(Method(mock, disconnect)).AlwaysReturn(Result::Code::Success);
+ fakeit::When(Method(mock, pair)).AlwaysReturn(Result::Code::Success);
+ fakeit::When(Method(mock, unpair)).AlwaysReturn(Result::Code::Success);
+ fakeit::When(Method(mock, availableDevices)).AlwaysReturn(Result::Code::Success);
return mock;
};
@@ 65,24 65,24 @@ namespace mock
auto profile()
{
fakeit::Mock<bluetooth::BaseProfileManager> mock;
- fakeit::When(Method(mock, init)).AlwaysReturn(Error::Code::Success);
+ fakeit::When(Method(mock, init)).AlwaysReturn(Result::Code::Success);
fakeit::When(Method(mock, deInit)).AlwaysReturn();
- fakeit::When(Method(mock, connect)).AlwaysReturn(Error::Code::Success);
- fakeit::When(Method(mock, disconnect)).AlwaysReturn(Error::Code::Success);
- fakeit::When(Method(mock, start)).AlwaysReturn(Error::Code::Success);
- fakeit::When(Method(mock, stop)).AlwaysReturn(Error::Code::Success);
- fakeit::When(Method(mock, startRinging)).AlwaysReturn(Error::Code::Success);
- fakeit::When(Method(mock, stopRinging)).AlwaysReturn(Error::Code::Success);
- fakeit::When(Method(mock, initializeCall)).AlwaysReturn(Error::Code::Success);
- fakeit::When(Method(mock, terminateCall)).AlwaysReturn(Error::Code::Success);
- fakeit::When(Method(mock, callAnswered)).AlwaysReturn(Error::Code::Success);
- fakeit::When(Method(mock, callStarted)).AlwaysReturn(Error::Code::Success);
- fakeit::When(Method(mock, setIncomingCallNumber)).AlwaysReturn(Error::Code::Success);
- fakeit::When(Method(mock, setSignalStrengthData)).AlwaysReturn(Error::Code::Success);
- fakeit::When(Method(mock, setOperatorNameData)).AlwaysReturn(Error::Code::Success);
- fakeit::When(Method(mock, setBatteryLevelData)).AlwaysReturn(Error::Code::Success);
- fakeit::When(Method(mock, setNetworkStatusData)).AlwaysReturn(Error::Code::Success);
- fakeit::When(Method(mock, setAudioDevice)).AlwaysReturn(Error::Code::Success);
+ fakeit::When(Method(mock, connect)).AlwaysReturn(Result::Code::Success);
+ fakeit::When(Method(mock, disconnect)).AlwaysReturn(Result::Code::Success);
+ fakeit::When(Method(mock, start)).AlwaysReturn(Result::Code::Success);
+ fakeit::When(Method(mock, stop)).AlwaysReturn(Result::Code::Success);
+ fakeit::When(Method(mock, incomingCallStarted)).AlwaysReturn(Result::Code::Success);
+ fakeit::When(Method(mock, outgoingCallStarted)).AlwaysReturn(Result::Code::Success);
+ fakeit::When(Method(mock, incomingCallAnswered)).AlwaysReturn(Result::Code::Success);
+ fakeit::When(Method(mock, outgoingCallAnswered)).AlwaysReturn(Result::Code::Success);
+ fakeit::When(Method(mock, callTerminated)).AlwaysReturn(Result::Code::Success);
+ fakeit::When(Method(mock, callMissed)).AlwaysReturn(Result::Code::Success);
+ fakeit::When(Method(mock, setIncomingCallNumber)).AlwaysReturn(Result::Code::Success);
+ fakeit::When(Method(mock, setSignalStrengthData)).AlwaysReturn(Result::Code::Success);
+ fakeit::When(Method(mock, setOperatorNameData)).AlwaysReturn(Result::Code::Success);
+ fakeit::When(Method(mock, setBatteryLevelData)).AlwaysReturn(Result::Code::Success);
+ fakeit::When(Method(mock, setNetworkStatusData)).AlwaysReturn(Result::Code::Success);
+ fakeit::When(Method(mock, setAudioDevice)).AlwaysReturn(Result::Code::Success);
return mock;
};
@@ 198,70 198,127 @@ TEST_CASE("call test - incoming call")
REQUIRE(controller.sm.is(state<bluetooth::On>));
auto number = utils::PhoneNumber::View{};
+ SECTION("dropped call with no number event")
+ {
+ REQUIRE(controller.sm.process_event(bluetooth::event::IncomingCallStarted{}));
+ REQUIRE(controller.sm.is<decltype(state<Call>)>("CallRinging"_s));
+ fakeit::Verify(Method(sm.p, incomingCallStarted)).Exactly(1);
+
+ REQUIRE(controller.sm.process_event(bluetooth::event::CallTerminated{}));
+ REQUIRE(controller.sm.is<decltype(state<Call>)>(sml::X));
+ REQUIRE(controller.sm.is(state<bluetooth::On>));
+ fakeit::Verify(Method(sm.p, callTerminated)).Exactly(1);
+ }
+
+ SECTION("answered call with no number event")
+ {
+ REQUIRE(controller.sm.process_event(bluetooth::event::IncomingCallStarted{}));
+ REQUIRE(controller.sm.is<decltype(state<Call>)>("CallRinging"_s));
+ fakeit::Verify(Method(sm.p, incomingCallStarted)).Exactly(1);
+
+ REQUIRE(controller.sm.process_event(bluetooth::event::CallAnswered{}));
+ REQUIRE(controller.sm.is<decltype(state<Call>)>("CallInProgress"_s));
+ fakeit::Verify(Method(sm.p, incomingCallAnswered)).Exactly(1);
+
+ REQUIRE(controller.sm.process_event(bluetooth::event::CallTerminated{}));
+ REQUIRE(controller.sm.is<decltype(state<Call>)>(sml::X));
+ REQUIRE(controller.sm.is(state<bluetooth::On>));
+ fakeit::Verify(Method(sm.p, callTerminated)).Exactly(1);
+ }
+
+ SECTION("missed call with no number event")
+ {
+ REQUIRE(controller.sm.process_event(bluetooth::event::IncomingCallStarted{}));
+ REQUIRE(controller.sm.is<decltype(state<Call>)>("CallRinging"_s));
+ fakeit::Verify(Method(sm.p, incomingCallStarted)).Exactly(1);
+
+ REQUIRE(controller.sm.process_event(bluetooth::event::CallMissed{}));
+ REQUIRE(controller.sm.is<decltype(state<Call>)>(sml::X));
+ REQUIRE(controller.sm.is(state<bluetooth::On>));
+ fakeit::Verify(Method(sm.p, callMissed)).Exactly(1);
+ }
+
+ SECTION("delayed incoming call number event")
+ {
+ REQUIRE(controller.sm.process_event(bluetooth::event::IncomingCallStarted{}));
+ REQUIRE(controller.sm.is<decltype(state<Call>)>("CallRinging"_s));
+ fakeit::Verify(Method(sm.p, incomingCallStarted)).Exactly(1);
+
+ REQUIRE(controller.sm.process_event(bluetooth::event::IncomingCallNumber{number}));
+ REQUIRE(controller.sm.is<decltype(state<Call>)>("CallRinging"_s));
+ fakeit::Verify(Method(sm.p, setIncomingCallNumber)).Exactly(1);
+
+ REQUIRE(controller.sm.process_event(bluetooth::event::CallTerminated{}));
+ REQUIRE(controller.sm.is<decltype(state<Call>)>(sml::X));
+ REQUIRE(controller.sm.is(state<bluetooth::On>));
+ fakeit::Verify(Method(sm.p, callTerminated)).Exactly(1);
+ }
+
SECTION("dropped call")
{
REQUIRE(controller.sm.process_event(bluetooth::event::IncomingCallNumber{number}));
REQUIRE(controller.sm.is<decltype(state<Call>)>("CallRinging"_s));
- fakeit::Verify(Method(sm.p, startRinging)).Exactly(1);
+ fakeit::Verify(Method(sm.p, incomingCallStarted)).Exactly(1);
fakeit::Verify(Method(sm.p, setIncomingCallNumber)).Exactly(1);
REQUIRE(controller.sm.process_event(bluetooth::event::CallTerminated{}));
REQUIRE(controller.sm.is<decltype(state<Call>)>(sml::X));
REQUIRE(controller.sm.is(state<bluetooth::On>));
- fakeit::Verify(Method(sm.p, terminateCall)).Exactly(1);
+ fakeit::Verify(Method(sm.p, callTerminated)).Exactly(1);
}
SECTION("answered call")
{
REQUIRE(controller.sm.process_event(bluetooth::event::IncomingCallNumber{number}));
REQUIRE(controller.sm.is<decltype(state<Call>)>("CallRinging"_s));
- fakeit::Verify(Method(sm.p, startRinging)).Exactly(1);
+ fakeit::Verify(Method(sm.p, incomingCallStarted)).Exactly(1);
fakeit::Verify(Method(sm.p, setIncomingCallNumber)).Exactly(1);
REQUIRE(controller.sm.process_event(bluetooth::event::CallAnswered{}));
REQUIRE(controller.sm.is<decltype(state<Call>)>("CallInProgress"_s));
- fakeit::Verify(Method(sm.p, callAnswered)).Exactly(1);
+ fakeit::Verify(Method(sm.p, incomingCallAnswered)).Exactly(1);
REQUIRE(controller.sm.process_event(bluetooth::event::CallTerminated{}));
REQUIRE(controller.sm.is<decltype(state<Call>)>(sml::X));
REQUIRE(controller.sm.is(state<bluetooth::On>));
- fakeit::Verify(Method(sm.p, terminateCall)).Exactly(1);
+ fakeit::Verify(Method(sm.p, callTerminated)).Exactly(1);
}
SECTION("missed call")
{
REQUIRE(controller.sm.process_event(bluetooth::event::IncomingCallNumber{number}));
REQUIRE(controller.sm.is<decltype(state<Call>)>("CallRinging"_s));
- fakeit::Verify(Method(sm.p, startRinging)).Exactly(1);
+ fakeit::Verify(Method(sm.p, incomingCallStarted)).Exactly(1);
fakeit::Verify(Method(sm.p, setIncomingCallNumber)).Exactly(1);
- REQUIRE(controller.sm.process_event(bluetooth::event::StopRinging{}));
+ REQUIRE(controller.sm.process_event(bluetooth::event::CallMissed{}));
REQUIRE(controller.sm.is<decltype(state<Call>)>(sml::X));
REQUIRE(controller.sm.is(state<bluetooth::On>));
- fakeit::Verify(Method(sm.p, stopRinging)).Exactly(1);
+ fakeit::Verify(Method(sm.p, callMissed)).Exactly(1);
}
+
SECTION("double missed call")
{
LOG_INFO("Double missed call");
REQUIRE(controller.sm.process_event(bluetooth::event::IncomingCallNumber{number}));
REQUIRE(controller.sm.is<decltype(state<Call>)>("CallRinging"_s));
- fakeit::Verify(Method(sm.p, startRinging)).Exactly(1);
+ fakeit::Verify(Method(sm.p, incomingCallStarted)).Exactly(1);
fakeit::Verify(Method(sm.p, setIncomingCallNumber)).Exactly(1);
- REQUIRE(controller.sm.process_event(bluetooth::event::StopRinging{}));
+ REQUIRE(controller.sm.process_event(bluetooth::event::CallMissed{}));
REQUIRE(controller.sm.is<decltype(state<Call>)>(sml::X));
REQUIRE(controller.sm.is(state<bluetooth::On>));
- fakeit::Verify(Method(sm.p, stopRinging)).Exactly(1);
+ fakeit::Verify(Method(sm.p, callMissed)).Exactly(1);
REQUIRE(controller.sm.process_event(bluetooth::event::IncomingCallNumber{number}));
REQUIRE(controller.sm.is<decltype(state<Call>)>("CallRinging"_s));
- fakeit::Verify(Method(sm.p, startRinging)).Exactly(2);
+ fakeit::Verify(Method(sm.p, incomingCallStarted)).Exactly(2);
fakeit::Verify(Method(sm.p, setIncomingCallNumber)).Exactly(2);
- REQUIRE(controller.sm.process_event(bluetooth::event::StopRinging{}));
+ REQUIRE(controller.sm.process_event(bluetooth::event::CallMissed{}));
REQUIRE(controller.sm.is<decltype(state<Call>)>(sml::X));
REQUIRE(controller.sm.is(state<bluetooth::On>));
- fakeit::Verify(Method(sm.p, stopRinging)).Exactly(2);
+ fakeit::Verify(Method(sm.p, callMissed)).Exactly(2);
}
}
@@ 277,49 334,49 @@ TEST_CASE("call test - outgoing call")
SECTION("dropped call")
{
- REQUIRE(controller.sm.process_event(bluetooth::event::CallStarted{number}));
+ REQUIRE(controller.sm.process_event(bluetooth::event::OutgoingCallStarted{number}));
REQUIRE(controller.sm.is<decltype(state<Call>)>("CallInitiated"_s));
- fakeit::Verify(Method(sm.p, callStarted)).Exactly(1);
+ fakeit::Verify(Method(sm.p, outgoingCallStarted)).Exactly(1);
REQUIRE(controller.sm.process_event(bluetooth::event::CallTerminated{}));
REQUIRE(controller.sm.is<decltype(state<Call>)>(sml::X));
REQUIRE(controller.sm.is(state<bluetooth::On>));
- fakeit::Verify(Method(sm.p, terminateCall)).Exactly(1);
+ fakeit::Verify(Method(sm.p, callTerminated)).Exactly(1);
}
SECTION("answered call")
{
- REQUIRE(controller.sm.process_event(bluetooth::event::CallStarted{number}));
+ REQUIRE(controller.sm.process_event(bluetooth::event::OutgoingCallStarted{number}));
REQUIRE(controller.sm.is<decltype(state<Call>)>("CallInitiated"_s));
- fakeit::Verify(Method(sm.p, callStarted)).Exactly(1);
+ fakeit::Verify(Method(sm.p, outgoingCallStarted)).Exactly(1);
REQUIRE(controller.sm.process_event(bluetooth::event::CallAnswered{}));
REQUIRE(controller.sm.is<decltype(state<Call>)>("CallInProgress"_s));
- fakeit::Verify(Method(sm.p, callAnswered)).Exactly(1);
+ fakeit::Verify(Method(sm.p, outgoingCallAnswered)).Exactly(1);
REQUIRE(controller.sm.process_event(bluetooth::event::CallTerminated{}));
REQUIRE(controller.sm.is<decltype(state<Call>)>(sml::X));
REQUIRE(controller.sm.is(state<bluetooth::On>));
- fakeit::Verify(Method(sm.p, terminateCall)).Exactly(1);
+ fakeit::Verify(Method(sm.p, callTerminated)).Exactly(1);
}
SECTION("miss-clicked call")
{
- REQUIRE(controller.sm.process_event(bluetooth::event::CallStarted{number}));
+ REQUIRE(controller.sm.process_event(bluetooth::event::OutgoingCallStarted{number}));
REQUIRE(controller.sm.is<decltype(state<Call>)>("CallInitiated"_s));
- fakeit::Verify(Method(sm.p, callStarted)).Exactly(1);
+ fakeit::Verify(Method(sm.p, outgoingCallStarted)).Exactly(1);
REQUIRE(controller.sm.process_event(bluetooth::event::CallTerminated{}));
REQUIRE(controller.sm.is<decltype(state<Call>)>(sml::X));
REQUIRE(controller.sm.is(state<bluetooth::On>));
- fakeit::Verify(Method(sm.p, terminateCall)).Exactly(1);
+ fakeit::Verify(Method(sm.p, callTerminated)).Exactly(1);
}
}
TEST_CASE("Given StatefulController when error during device registration then turned off")
{
using namespace boost::sml;
- auto sm = mock::SM([]() { return bluetooth::Error::Code::SystemError; });
+ auto sm = mock::SM([]() { return bluetooth::Result::Code::SystemError; });
auto controller = sm.get();
controller.sm.process_event(bluetooth::event::PowerOn{});
@@ 332,7 389,7 @@ TEST_CASE("Given StatefulController when error during driver init then turned of
auto sm = mock::SM();
auto controller = sm.get();
- fakeit::When(Method(sm.d, init)).AlwaysReturn(Error::Code::SystemError);
+ fakeit::When(Method(sm.d, init)).AlwaysReturn(Result::Code::SystemError);
controller.sm.process_event(bluetooth::event::PowerOn{});
REQUIRE(!controller.sm.is(state<bluetooth::On>));
@@ 389,11 446,11 @@ TEST_CASE("Given StatefulController when processing command failed then restarte
auto sm = mock::SM();
auto controller = sm.get();
- fakeit::When(Method(sm.d, init)).AlwaysReturn(Error::Code::SystemError);
+ fakeit::When(Method(sm.d, init)).AlwaysReturn(Result::Code::SystemError);
controller.sm.process_event(bluetooth::event::PowerOn{});
REQUIRE(!controller.sm.is(state<bluetooth::On>));
- fakeit::When(Method(sm.d, init)).AlwaysReturn(Error::Code::Success);
+ fakeit::When(Method(sm.d, init)).AlwaysReturn(Result::Code::Success);
controller.sm.process_event(bluetooth::event::PowerOn{});
REQUIRE(controller.sm.is(state<bluetooth::On>));
}
M module-services/service-bluetooth/ServiceBluetooth.cpp => module-services/service-bluetooth/ServiceBluetooth.cpp +44 -36
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include "service-bluetooth/ServiceBluetooth.hpp"
@@ 11,7 11,6 @@
#include <Service/Message.hpp>
#include <service-db/Settings.hpp>
#include "service-bluetooth/messages/AudioVolume.hpp"
-#include "service-bluetooth/messages/AudioRouting.hpp"
#include "service-bluetooth/messages/Connect.hpp"
#include <service-bluetooth/messages/DeviceName.hpp>
#include "service-bluetooth/messages/Disconnect.hpp"
@@ 44,8 43,7 @@
namespace
{
- constexpr auto BluetoothServiceStackDepth = 2560U;
- inline constexpr auto nameSettings = "ApplicationSettings";
+ constexpr auto BluetoothServiceStackDepth = 1024 * 3;
inline constexpr auto connectionTimeout = std::chrono::minutes{10};
inline constexpr auto btRestartDelay = std::chrono::milliseconds{500};
@@ 95,7 93,6 @@ sys::ReturnCodes ServiceBluetooth::InitHandler()
connectHandler<message::bluetooth::A2DPVolume>();
connectHandler<message::bluetooth::HSPVolume>();
connectHandler<message::bluetooth::HFPVolume>();
- connectHandler<message::bluetooth::StartAudioRouting>();
connectHandler<message::bluetooth::Connect>();
connectHandler<message::bluetooth::ConnectResult>();
connectHandler<message::bluetooth::Disconnect>();
@@ 114,6 111,7 @@ sys::ReturnCodes ServiceBluetooth::InitHandler()
connectHandler<cellular::CallerIdMessage>();
connectHandler<cellular::IncomingCallMessage>();
connectHandler<cellular::CallEndedNotification>();
+ connectHandler<cellular::CallMissedNotification>();
connectHandler<cellular::CallStartedNotification>();
connectHandler<cellular::SignalStrengthUpdateNotification>();
connectHandler<cellular::CurrentOperatorNameNotification>();
@@ 319,7 317,7 @@ auto convertDeviceStateIntoBluetoothState(const DeviceState &state) -> sys::blue
auto ServiceBluetooth::handle(message::bluetooth::ConnectResult *msg) -> std::shared_ptr<sys::Message>
{
- if (msg->isSucceed()) {
+ if (msg->getResult() == message::bluetooth::ConnectResult::Result::Success) {
auto device = msg->getDevice();
bluetoothDevicesModel->mergeInternalDeviceState(device);
@@ 466,6 464,7 @@ auto ServiceBluetooth::handle(message::bluetooth::HSPVolume *msg) -> std::shared
AudioServiceAPI::BluetoothHSPVolumeChanged(this, msg->getVolume());
return sys::MessageNone{};
}
+
auto ServiceBluetooth::handle(message::bluetooth::HFPVolume *msg) -> std::shared_ptr<sys::Message>
{
using namespace message::bluetooth;
@@ 473,26 472,6 @@ auto ServiceBluetooth::handle(message::bluetooth::HFPVolume *msg) -> std::shared
return sys::MessageNone{};
}
-auto ServiceBluetooth::handle(message::bluetooth::StartAudioRouting *msg) -> std::shared_ptr<sys::Message>
-{
- sendWorkerCommand(std::make_unique<bluetooth::event::StartRouting>());
- return std::make_shared<sys::ResponseMessage>();
-}
-
-auto ServiceBluetooth::handle(cellular::CallerIdMessage *msg) -> std::shared_ptr<sys::Message>
-{
- auto number = msg->number;
- auto btOn = std::visit(bluetooth::BoolVisitor(), settingsHolder->getValue(bluetooth::Settings::State));
- LOG_DEBUG("Received caller ID msg! ");
-
- if (btOn) {
- LOG_DEBUG("Sending to profile!");
- sendWorkerCommand(std::make_unique<bluetooth::event::IncomingCallNumber>(number));
- }
-
- return sys::MessageNone{};
-}
-
auto ServiceBluetooth::handle(cellular::SignalStrengthUpdateNotification *msg) -> std::shared_ptr<sys::Message>
{
auto signalStrength = Store::GSM::get()->getSignalStrength();
@@ 531,6 510,7 @@ void ServiceBluetooth::handleTurnOff()
bus.sendMulticast(std::make_shared<sys::bluetooth::BluetoothModeChanged>(sys::bluetooth::BluetoothMode::Disabled),
sys::BusChannel::BluetoothModeChanges);
}
+
void ServiceBluetooth::handleTurnOn()
{
cpuSentinel->HoldMinimumFrequency(bsp::CpuFrequencyMHz::Level_3);
@@ 538,6 518,7 @@ void ServiceBluetooth::handleTurnOn()
bus.sendMulticast(std::make_shared<sys::bluetooth::BluetoothModeChanged>(sys::bluetooth::BluetoothMode::Enabled),
sys::BusChannel::BluetoothModeChanges);
}
+
auto ServiceBluetooth::handle(message::bluetooth::RequestStatusIndicatorData *msg) -> std::shared_ptr<sys::Message>
{
bus.sendUnicast(std::make_shared<cellular::RequestCurrentOperatorNameMessage>(), cellular::service::name);
@@ 549,6 530,7 @@ auto ServiceBluetooth::handle(message::bluetooth::RequestStatusIndicatorData *ms
return sys::MessageNone{};
}
+
auto ServiceBluetooth::handle(sevm::BatteryStatusChangeMessage *msg) -> std::shared_ptr<sys::Message>
{
auto batteryLevel = Store::Battery::get().level;
@@ 556,11 538,7 @@ auto ServiceBluetooth::handle(sevm::BatteryStatusChangeMessage *msg) -> std::sha
sendWorkerCommand(std::make_unique<bluetooth::event::BatteryLevelData>(batteryLevel));
return sys::MessageNone{};
}
-auto ServiceBluetooth::handle(cellular::CallEndedNotification *msg) -> std::shared_ptr<sys::Message>
-{
- sendWorkerCommand(std::make_unique<bluetooth::event::CallTerminated>());
- return sys::MessageNone{};
-}
+
auto ServiceBluetooth::handle(cellular::NetworkStatusUpdateNotification *msg) -> std::shared_ptr<sys::Message>
{
auto status = Store::GSM::get()->getNetwork().status;
@@ 568,19 546,36 @@ auto ServiceBluetooth::handle(cellular::NetworkStatusUpdateNotification *msg) ->
sendWorkerCommand(std::make_unique<bluetooth::event::NetworkStatusData>(status));
return sys::MessageNone{};
}
-auto ServiceBluetooth::handle(cellular::CallStartedNotification *msg) -> std::shared_ptr<sys::Message>
+
+auto ServiceBluetooth::handle(cellular::CallerIdMessage *msg) -> std::shared_ptr<sys::Message>
{
- if (!msg->isCallIncoming()) {
- auto evt = std::make_unique<bluetooth::event::CallStarted>(msg->getNumber());
- sendWorkerCommand(std::move(evt));
+ auto number = msg->number;
+ auto btOn = std::visit(bluetooth::BoolVisitor(), settingsHolder->getValue(bluetooth::Settings::State));
+ LOG_DEBUG("Received caller ID msg! ");
+
+ if (btOn) {
+ LOG_DEBUG("Sending to profile!");
+ sendWorkerCommand(std::make_unique<bluetooth::event::IncomingCallNumber>(number));
}
+
return sys::MessageNone{};
}
+
auto ServiceBluetooth::handle(cellular::IncomingCallMessage *msg) -> std::shared_ptr<sys::Message>
{
- sendWorkerCommand(std::make_unique<bluetooth::event::StartRinging>());
+ sendWorkerCommand(std::make_unique<bluetooth::event::IncomingCallStarted>());
return sys::MessageNone{};
}
+
+auto ServiceBluetooth::handle(cellular::CallStartedNotification *msg) -> std::shared_ptr<sys::Message>
+{
+ if (!msg->isCallIncoming()) {
+ auto evt = std::make_unique<bluetooth::event::OutgoingCallStarted>(msg->getNumber());
+ sendWorkerCommand(std::move(evt));
+ }
+ return sys::MessageNone{};
+}
+
auto ServiceBluetooth::handle(cellular::CallOutgoingAccepted *msg) -> std::shared_ptr<sys::Message>
{
LOG_DEBUG("Outgoing call accepted");
@@ 588,6 583,7 @@ auto ServiceBluetooth::handle(cellular::CallOutgoingAccepted *msg) -> std::share
return sys::MessageNone{};
}
+
auto ServiceBluetooth::handle(cellular::CallActiveNotification *msg) -> std::shared_ptr<sys::Message>
{
LOG_DEBUG("Incoming call accepted");
@@ 595,3 591,15 @@ auto ServiceBluetooth::handle(cellular::CallActiveNotification *msg) -> std::sha
return sys::MessageNone{};
}
+
+auto ServiceBluetooth::handle(cellular::CallEndedNotification *msg) -> std::shared_ptr<sys::Message>
+{
+ sendWorkerCommand(std::make_unique<bluetooth::event::CallTerminated>());
+ return sys::MessageNone{};
+}
+
+auto ServiceBluetooth::handle(cellular::CallMissedNotification *msg) -> std::shared_ptr<sys::Message>
+{
+ sendWorkerCommand(std::make_unique<bluetooth::event::CallMissed>());
+ return sys::MessageNone{};
+}
M module-services/service-bluetooth/service-bluetooth/ServiceBluetooth.hpp => module-services/service-bluetooth/service-bluetooth/ServiceBluetooth.hpp +5 -8
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
@@ 19,11 19,13 @@
#include <Timers/TimerHandle.hpp>
#include <memory> // for unique_ptr
+
namespace message::bluetooth
{
class ResponseAuthenticate;
}
class BluetoothWorker;
+
namespace settings
{
class Settings;
@@ 35,7 37,6 @@ namespace sdesktop
namespace developerMode
{
class DeveloperModeRequest;
- class DeveloperModeMessageWrapper;
} // namespace developerMode
} // namespace sdesktop
@@ 54,9 55,6 @@ namespace message::bluetooth
class A2DPVolume;
class HSPVolume;
class HFPVolume;
- class Ring;
- class StartAudioRouting;
- class GetBluetoothDevicesModel;
class RequestStatusIndicatorData;
} // namespace message::bluetooth
@@ 68,6 66,7 @@ namespace sevm
namespace cellular
{
class CallEndedNotification;
+ class CallMissedNotification;
class CallStartedNotification;
class CallOutgoingAccepted;
class IncomingCallMessage;
@@ 80,7 79,6 @@ namespace cellular
class ServiceBluetooth : public sys::Service
{
-
public:
ServiceBluetooth();
~ServiceBluetooth();
@@ 120,7 118,6 @@ class ServiceBluetooth : public sys::Service
[[nodiscard]] auto handle(message::bluetooth::SetStatus *msg) -> std::shared_ptr<sys::Message>;
[[nodiscard]] auto handle(BluetoothPairMessage *msg) -> std::shared_ptr<sys::Message>;
[[nodiscard]] auto handle(BluetoothPairResultMessage *msg) -> std::shared_ptr<sys::Message>;
-
[[nodiscard]] auto handle(message::bluetooth::Unpair *msg) -> std::shared_ptr<sys::Message>;
[[nodiscard]] auto handle(message::bluetooth::RequestDeviceName *msg) -> std::shared_ptr<sys::Message>;
[[nodiscard]] auto handle(message::bluetooth::SetDeviceName *msg) -> std::shared_ptr<sys::Message>;
@@ 135,7 132,6 @@ class ServiceBluetooth : public sys::Service
[[nodiscard]] auto handle(message::bluetooth::A2DPVolume *msg) -> std::shared_ptr<sys::Message>;
[[nodiscard]] auto handle(message::bluetooth::HSPVolume *msg) -> std::shared_ptr<sys::Message>;
[[nodiscard]] auto handle(message::bluetooth::HFPVolume *msg) -> std::shared_ptr<sys::Message>;
- [[nodiscard]] auto handle(message::bluetooth::StartAudioRouting *msg) -> std::shared_ptr<sys::Message>;
[[nodiscard]] auto handle(message::bluetooth::ResponseAuthenticatePin *msg) -> std::shared_ptr<sys::Message>;
[[nodiscard]] auto handle(message::bluetooth::ResponseAuthenticatePasskey *msg) -> std::shared_ptr<sys::Message>;
[[nodiscard]] auto handle(message::bluetooth::ResponseAuthenticatePairCancel *msg) -> std::shared_ptr<sys::Message>;
@@ 143,6 139,7 @@ class ServiceBluetooth : public sys::Service
[[nodiscard]] auto handle(cellular::CallerIdMessage *msg) -> std::shared_ptr<sys::Message>;
[[nodiscard]] auto handle(cellular::IncomingCallMessage *msg) -> std::shared_ptr<sys::Message>;
[[nodiscard]] auto handle(cellular::CallEndedNotification *msg) -> std::shared_ptr<sys::Message>;
+ [[nodiscard]] auto handle(cellular::CallMissedNotification *msg) -> std::shared_ptr<sys::Message>;
[[nodiscard]] auto handle(cellular::CallStartedNotification *msg) -> std::shared_ptr<sys::Message>;
[[nodiscard]] auto handle(cellular::CallOutgoingAccepted *msg) -> std::shared_ptr<sys::Message>;
[[nodiscard]] auto handle(cellular::SignalStrengthUpdateNotification *msg) -> std::shared_ptr<sys::Message>;
D module-services/service-bluetooth/service-bluetooth/messages/AudioRouting.hpp => module-services/service-bluetooth/service-bluetooth/messages/AudioRouting.hpp +0 -12
@@ 1,12 0,0 @@
-// 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 "service-bluetooth/BluetoothMessage.hpp"
-
-namespace message::bluetooth
-{
- class StartAudioRouting : public BluetoothMessage
- {};
-} // namespace message::bluetooth
M module-services/service-bluetooth/service-bluetooth/messages/Connect.hpp => module-services/service-bluetooth/service-bluetooth/messages/Connect.hpp +11 -5
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
@@ 24,19 24,25 @@ namespace message::bluetooth
class ConnectResult : public BluetoothMessage
{
public:
- explicit ConnectResult(Devicei device, bool succeed) : device(device), succeed(succeed)
+ enum class Result
+ {
+ Success,
+ Failure
+ };
+
+ explicit ConnectResult(Devicei device, Result result) : device(std::move(device)), result(result)
{}
[[nodiscard]] auto getDevice() const -> Devicei
{
return device;
}
- [[nodiscard]] auto isSucceed() const noexcept -> bool
+ [[nodiscard]] auto getResult() const noexcept -> Result
{
- return succeed;
+ return result;
}
private:
Devicei device;
- bool succeed;
+ Result result;
};
} // namespace message::bluetooth
M module-services/service-cellular/QMBNManager.hpp => module-services/service-cellular/QMBNManager.hpp +3 -3
@@ 1,15 1,15 @@
-// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
-#include "Result.hpp"
+#include "at/Result.hpp"
+#include <string>
class DLCChannel;
namespace nv_paths
{
-
auto constexpr voice_domain_pref = "/nv/item_files/modem/mmode/voice_domain_pref";
auto constexpr sms_domain_pref = "/nv/item_files/modem/mmode/sms_domain_pref";
auto constexpr IMS_enable = "/nv/item_files/ims/IMS_enable";
M pure_changelog.md => pure_changelog.md +1 -0
@@ 17,6 17,7 @@
* Fixed unsupported character in several quotes
* Fixed unwanted autolock on template selection window while rejecting call
* Fixed scenario when Alarm not being handled properly during a phone call
+* Fixed handsfree device still ringing after caller has hung up
## [1.7.1 2023-07-13]