From d59ac56d516cdb04cca7c0a9824e5e69c4fbb84d Mon Sep 17 00:00:00 2001 From: Bartosz Cichocki Date: Wed, 20 Apr 2022 10:17:38 +0200 Subject: [PATCH] [MOS-347] Separate A2DP from HFP in ProfileManager Now, both profiles can operate separately. Additonally, minor fixes has been applied to allow calling via car audio system. Some infotainment systems still don't work though. --- .../Audio/Operation/RouterOperation.cpp | 3 +- module-bluetooth/Bluetooth/CommandHandler.cpp | 18 +----- module-bluetooth/Bluetooth/CommandHandler.hpp | 1 - .../Bluetooth/command/Command.hpp | 2 +- .../interface/BluetoothDriverImpl.cpp | 6 +- .../interface/profiles/A2DP/A2DP.cpp | 44 ------------- .../interface/profiles/A2DP/A2DP.hpp | 19 +----- .../Bluetooth/interface/profiles/GAP/GAP.cpp | 3 +- .../Bluetooth/interface/profiles/HFP/HFP.cpp | 45 +++++++------- .../Bluetooth/interface/profiles/HFP/HFP.hpp | 5 +- .../interface/profiles/HFP/HFPImpl.hpp | 3 +- .../Bluetooth/interface/profiles/HSP/HSP.cpp | 33 ++++------ .../Bluetooth/interface/profiles/HSP/HSP.hpp | 5 +- .../interface/profiles/HSP/HSPImpl.hpp | 5 +- .../interface/profiles/PhoneInterface.cpp | 4 ++ .../interface/profiles/PhoneInterface.hpp | 2 + .../Bluetooth/interface/profiles/Profile.hpp | 35 +++++++---- .../interface/profiles/ProfileManager.cpp | 62 +++++++------------ .../interface/profiles/ProfileManager.hpp | 10 +-- module-bluetooth/lib/btstack | 2 +- .../service-audio/ServiceAudio.cpp | 9 +-- .../service-bluetooth/ServiceBluetooth.cpp | 10 ++- .../service-bluetooth/BluetoothMessage.hpp | 1 - .../service-bluetooth/ServiceBluetooth.hpp | 5 ++ module-utils/log/Logger.cpp | 1 - 25 files changed, 123 insertions(+), 210 deletions(-) diff --git a/module-audio/Audio/Operation/RouterOperation.cpp b/module-audio/Audio/Operation/RouterOperation.cpp index b051808fbc6295a568ff6a5107e0c3bd045996c3..af77ceefae72a5369e42f6a7d1b42cd569e5414c 100644 --- a/module-audio/Audio/Operation/RouterOperation.cpp +++ b/module-audio/Audio/Operation/RouterOperation.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. +// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #include "RouterOperation.hpp" @@ -80,6 +80,7 @@ namespace audio // enable audio connections voiceOutputConnection->enable(); if (!IsMuted()) { + LOG_DEBUG("Voice input not muted"); voiceInputConnection->enable(); } diff --git a/module-bluetooth/Bluetooth/CommandHandler.cpp b/module-bluetooth/Bluetooth/CommandHandler.cpp index 9beb41b5188572f5dbe35b256ab17bbf60403277..3569e43fbd4628f0b58259ce24af1e3b6ee49c66 100644 --- a/module-bluetooth/Bluetooth/CommandHandler.cpp +++ b/module-bluetooth/Bluetooth/CommandHandler.cpp @@ -64,8 +64,6 @@ namespace bluetooth return disconnectAudioConnection(); case bluetooth::Command::PowerOff: return Error::Success; - case bluetooth::Command::SwitchProfile: - return switchAudioProfile(); case bluetooth::Command::None: return Error::Success; case Command::StartRinging: @@ -76,6 +74,8 @@ namespace bluetooth return profileManager->initializeCall(); case Command::CallAnswered: return profileManager->callAnswered(); + case Command::CallTerminated: + return profileManager->terminateCall(); case Command::IncomingCallNumber: return profileManager->setIncomingCallNumber(command.getData()); case Command::SignalStrengthData: @@ -143,20 +143,6 @@ namespace bluetooth LOG_INFO("Pairing result: %s", magic_enum::enum_name(errorCode).data()); return errorCode; } - Error::Code CommandHandler::switchAudioProfile() - { - static auto profile = AudioProfile::A2DP; - if (profile == AudioProfile::A2DP) { - profile = AudioProfile::HSP; - LOG_INFO("New profile: HSP"); - } - else { - profile = AudioProfile::A2DP; - LOG_INFO("New profile: A2DP"); - } - profileManager->switchProfile(profile); - return Error::Success; - } Error::Code CommandHandler::unpair(const DataVariant &data) { auto device = std::get(data); diff --git a/module-bluetooth/Bluetooth/CommandHandler.hpp b/module-bluetooth/Bluetooth/CommandHandler.hpp index 9edcf4637e4a39759509fad06b1b877389ef10aa..ba92034c48be07097581631360328b505b4600d8 100644 --- a/module-bluetooth/Bluetooth/CommandHandler.hpp +++ b/module-bluetooth/Bluetooth/CommandHandler.hpp @@ -49,7 +49,6 @@ namespace bluetooth Error::Code pair(const DataVariant &data); Error::Code unpair(const DataVariant &data); Error::Code availableDevices(); - Error::Code switchAudioProfile(); sys::Service *service; std::shared_ptr settings; std::shared_ptr profileManager; diff --git a/module-bluetooth/Bluetooth/command/Command.hpp b/module-bluetooth/Bluetooth/command/Command.hpp index a8294b5f087e8fbbfcd11c41749aa7c0830d55fb..984f262e6d23011d216ea5535dad402b6b8fb136 100644 --- a/module-bluetooth/Bluetooth/command/Command.hpp +++ b/module-bluetooth/Bluetooth/command/Command.hpp @@ -28,8 +28,8 @@ namespace bluetooth StartRouting, StartStream, StopStream, - SwitchProfile, CallAnswered, + CallTerminated, IncomingCallNumber, SignalStrengthData, OperatorNameData, diff --git a/module-bluetooth/Bluetooth/interface/BluetoothDriverImpl.cpp b/module-bluetooth/Bluetooth/interface/BluetoothDriverImpl.cpp index f79ac6ee29846b6575a7c0b19df02963c967d9d7..81f6ea53eccead720d3afc7166f18f67849ac345 100644 --- a/module-bluetooth/Bluetooth/interface/BluetoothDriverImpl.cpp +++ b/module-bluetooth/Bluetooth/interface/BluetoothDriverImpl.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. +// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #include "BluetoothDriverImpl.hpp" @@ -83,8 +83,10 @@ namespace bluetooth hci_event_callback_registration.callback = &hci_packet_handler; hci_add_event_handler(&hci_event_callback_registration); - gap_ssp_set_io_capability(SSP_IO_CAPABILITY_KEYBOARD_ONLY); + gap_ssp_set_io_capability(SSP_IO_CAPABILITY_DISPLAY_YES_NO); gap_ssp_set_auto_accept(false); + + gap_set_class_of_device(0x64020C); LOG_DEBUG("BT worker run success"); return Error::Success; } diff --git a/module-bluetooth/Bluetooth/interface/profiles/A2DP/A2DP.cpp b/module-bluetooth/Bluetooth/interface/profiles/A2DP/A2DP.cpp index 896d095895659e7028dc0cb29b56c30babafcc30..94c53b5c2119c3411d7e88c88e4467bf380c1e62 100644 --- a/module-bluetooth/Bluetooth/interface/profiles/A2DP/A2DP.cpp +++ b/module-bluetooth/Bluetooth/interface/profiles/A2DP/A2DP.cpp @@ -94,49 +94,10 @@ namespace bluetooth pimpl->stop(); } - auto A2DP::startRinging() const noexcept -> Error::Code - { - LOG_ERROR("Can't ring in A2DP profile"); - return Error::SystemError; - } - - auto A2DP::stopRinging() const noexcept -> Error::Code - { - return Error::SystemError; - } - - auto A2DP::initializeCall() const noexcept -> Error::Code - { - return Error::SystemError; - } - void A2DP::setAudioDevice(std::shared_ptr audioDevice) { pimpl->setAudioDevice(std::move(audioDevice)); } - auto A2DP::callAnswered() const noexcept -> Error::Code - { - return Error::SystemError; - } - auto A2DP::setIncomingCallNumber(const std::string &num) const noexcept -> Error::Code - { - LOG_INFO("Setting number in A2DP - ignoring"); - return Error::Success; - } - auto A2DP::setSignalStrength(int bars) const noexcept -> Error::Code - { - LOG_INFO("Setting signal bars in A2DP - ignoring"); - return Error::Success; - } - auto A2DP::setOperatorName(const std::string_view &name) const noexcept -> Error::Code - { - LOG_INFO("Setting operator name in A2DP - ignoring"); - return Error::Success; - } - auto A2DP::setBatteryLevel(const BatteryLevel &level) const noexcept -> Error::Code - { - return Error::Success; - } const sys::Service *A2DP::A2DPImpl::ownerService; QueueHandle_t A2DP::A2DPImpl::sourceQueue = nullptr; @@ -222,11 +183,6 @@ namespace bluetooth LOG_ERROR("Can't register service. Status %x", status); } - // 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 - // up and starts talking to a Bluetooth module. - gap_set_class_of_device(0x200408); - // Register for HCI events. hciEventCallbackRegistration.callback = &hciPacketHandler; hci_add_event_handler(&hciEventCallbackRegistration); diff --git a/module-bluetooth/Bluetooth/interface/profiles/A2DP/A2DP.hpp b/module-bluetooth/Bluetooth/interface/profiles/A2DP/A2DP.hpp index 3616c3d7c6c33f6b0d60caa7db8ece7b83ca756a..c29db9604b59956c55832cce29a2d976428e6b5a 100644 --- a/module-bluetooth/Bluetooth/interface/profiles/A2DP/A2DP.hpp +++ b/module-bluetooth/Bluetooth/interface/profiles/A2DP/A2DP.hpp @@ -11,7 +11,7 @@ namespace bluetooth { - class A2DP : public Profile + class A2DP : public MusicProfile { public: A2DP(); @@ -30,23 +30,6 @@ namespace bluetooth void disconnect() override; void start() override; void stop() override; - /// @return SystemError - it's not posible to start ringing while there's A2DP active - [[nodiscard]] auto startRinging() const noexcept -> Error::Code override; - /// @return SystemError - it's not posible to stop ringing while there's A2DP active - [[nodiscard]] auto stopRinging() const noexcept -> Error::Code override; - /// @return SystemError - it's not posible to start routing while there's A2DP active - [[nodiscard]] auto initializeCall() const noexcept -> Error::Code override; - /// @return SystemError - it's not posible to handle call answered while there's A2DP active - [[nodiscard]] auto callAnswered() const noexcept -> Error::Code override; - /// @return Success - ignoring in A2DP - [[nodiscard]] auto setIncomingCallNumber(const std::string &num) const noexcept -> Error::Code override; - /// @return Success - ignoring in A2DP - [[nodiscard]] auto setSignalStrength(int bars) const noexcept -> Error::Code override; - /// @return Success - ignoring in A2DP - [[nodiscard]] auto setOperatorName(const std::string_view &name) const noexcept -> Error::Code override; - /// @return Success - ignoring in A2DP - [[nodiscard]] auto setBatteryLevel(const BatteryLevel &level) const noexcept -> Error::Code override; - void setAudioDevice(std::shared_ptr audioDevice) override; private: diff --git a/module-bluetooth/Bluetooth/interface/profiles/GAP/GAP.cpp b/module-bluetooth/Bluetooth/interface/profiles/GAP/GAP.cpp index 1108f01f5fde7da146896b2141b378365e36389b..60df487541f116c45acdfe93caa977eaee2425f9 100644 --- a/module-bluetooth/Bluetooth/interface/profiles/GAP/GAP.cpp +++ b/module-bluetooth/Bluetooth/interface/profiles/GAP/GAP.cpp @@ -226,7 +226,8 @@ namespace bluetooth void GAP::activeStateHandler(std::uint8_t eventType, std::uint8_t *packet, std::uint16_t size) { if (not(eventType == HCI_EVENT_TRANSPORT_PACKET_SENT || eventType == HCI_EVENT_COMMAND_STATUS || - eventType == HCI_EVENT_INQUIRY_COMPLETE || eventType == HCI_EVENT_COMMAND_COMPLETE)) { + eventType == HCI_EVENT_INQUIRY_COMPLETE || eventType == HCI_EVENT_COMMAND_COMPLETE || + eventType == HCI_EVENT_NUMBER_OF_COMPLETED_PACKETS)) { LOG_DEBUG("event: 0x%02X - %s - size: %" PRIu16, eventType, evt_cstr(eventType), size); } switch (eventType) { diff --git a/module-bluetooth/Bluetooth/interface/profiles/HFP/HFP.cpp b/module-bluetooth/Bluetooth/interface/profiles/HFP/HFP.cpp index 99479dc7acdd117785c272efcf6f6b9c9cc5988f..f64786210b9e235456e037f8fa131ddf7897bc73 100644 --- a/module-bluetooth/Bluetooth/interface/profiles/HFP/HFP.cpp +++ b/module-bluetooth/Bluetooth/interface/profiles/HFP/HFP.cpp @@ -66,16 +66,6 @@ namespace bluetooth { pimpl->disconnect(); } - - void HFP::start() - { - pimpl->start(); - } - - void HFP::stop() - { - pimpl->stop(); - } auto HFP::startRinging() const noexcept -> Error::Code { pimpl->startRinging(); @@ -91,6 +81,11 @@ namespace bluetooth pimpl->initializeCall(); return Error::Success; } + auto HFP::terminateCall() const noexcept -> Error::Code + { + pimpl->terminateCall(); + return Error::Success; + } void HFP::setAudioDevice(std::shared_ptr audioDevice) { pimpl->setAudioDevice(audioDevice); @@ -217,6 +212,9 @@ namespace bluetooth if (audioDevice != nullptr) { audioDevice->onDataSend(scoHandle); } + else { + LOG_DEBUG("Audiodevice nullptr :("); + } break; case HCI_EVENT_HFP_META: processHFPEvent(event); @@ -285,6 +283,7 @@ namespace bluetooth LOG_DEBUG("Audio connection established with SCO handle 0x%04x.\n", scoHandle); codec = static_cast(hfp_subevent_audio_connection_established_get_negotiated_codec(event)); dump_supported_codecs(); + audioInterface->startAudioRouting(const_cast(ownerService)); hci_request_sco_can_send_now_event(); RunLoop::trigger(); } @@ -292,6 +291,7 @@ namespace bluetooth case HFP_SUBEVENT_AUDIO_CONNECTION_RELEASED: LOG_DEBUG("Audio connection released"); scoHandle = HCI_CON_HANDLE_INVALID; + audioInterface->stopAudioRouting(const_cast(ownerService)); audioDevice.reset(); break; case HFP_SUBEVENT_START_RINGING: @@ -304,6 +304,8 @@ namespace bluetooth break; case HFP_SUBEVENT_PLACE_CALL_WITH_NUMBER: break; + case HFP_SUBEVENT_RING: + break; case HFP_SUBEVENT_ATTACH_NUMBER_TO_VOICE_TAG: // todo has to be feeded with proper phone number from cellular @@ -351,7 +353,7 @@ namespace bluetooth serviceBuffer.fill(0); constexpr std::uint32_t hspSdpRecordHandle = 0x10004; - uint16_t supported_features = (1 << HFP_AGSF_ESCO_S4) /*| (1 << HFP_AGSF_HF_INDICATORS) */ | + 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) |*/ @@ -397,6 +399,8 @@ namespace bluetooth } LOG_DEBUG("Connecting the HFP profile"); hfp_ag_establish_service_level_connection(device.address); + hfp_ag_set_speaker_gain(aclHandle, 8); + hfp_ag_set_microphone_gain(aclHandle, 10); } void HFP::HFPImpl::disconnect() @@ -422,18 +426,10 @@ namespace bluetooth return sco->getStreamData(); } - void HFP::HFPImpl::start() - { - if (!isConnected) { - connect(); - } - hfp_ag_set_speaker_gain(aclHandle, 8); - hfp_ag_set_microphone_gain(aclHandle, 10); - } - - void HFP::HFPImpl::stop() + void HFP::HFPImpl::terminateCall() const noexcept { hfp_ag_terminate_call(); + hfp_ag_release_audio_connection(aclHandle); isCallInitialized = false; isIncomingCall = false; } @@ -470,6 +466,7 @@ namespace bluetooth { HFP::HFPImpl::audioDevice = std::static_pointer_cast(audioDevice); HFP::HFPImpl::audioDevice->setAclHandle(aclHandle); + LOG_DEBUG("Audiodevice set!"); } void HFP::HFPImpl::startRinging() const noexcept { @@ -492,13 +489,15 @@ namespace bluetooth audioInterface->startAudioRouting(const_cast(ownerService)); hfp_ag_outgoing_call_established(); } - LOG_DEBUG("Establishing HFP audio connection"); - hfp_ag_establish_audio_connection(aclHandle); return Error::Success; } auto HFP::HFPImpl::setIncomingCallNumber(const std::string &num) const noexcept -> Error::Code { + if (!isIncomingCall) { + isIncomingCall = true; + hfp_ag_incoming_call(); + } hfp_ag_set_clip(129, num.c_str()); return Error::Success; } diff --git a/module-bluetooth/Bluetooth/interface/profiles/HFP/HFP.hpp b/module-bluetooth/Bluetooth/interface/profiles/HFP/HFP.hpp index d9f0c0270e15d74a4fe9899a6d0035e7d39ead75..4112e5900e2baae443090832e6c6fdbab697dc42 100644 --- a/module-bluetooth/Bluetooth/interface/profiles/HFP/HFP.hpp +++ b/module-bluetooth/Bluetooth/interface/profiles/HFP/HFP.hpp @@ -12,7 +12,7 @@ namespace bluetooth { - class HFP : public Profile + class HFP : public CallProfile { // static constexpr auto CLASS_OF_DEVICE = 0x400204; // Service class: Telephony, Major device class: Phone, Minor device class: Cellular @@ -31,8 +31,6 @@ namespace bluetooth void connect() override; void disconnect() override; - void start() override; - void stop() override; /// @brief Starts ring /// @return Success [[nodiscard]] auto startRinging() const noexcept -> Error::Code override; @@ -44,6 +42,7 @@ namespace bluetooth /// - SCO link establishment /// @return Success [[nodiscard]] auto initializeCall() const noexcept -> Error::Code override; + [[nodiscard]] auto terminateCall() const noexcept -> Error::Code override; [[nodiscard]] auto callAnswered() const noexcept -> Error::Code override; [[nodiscard]] auto setIncomingCallNumber(const std::string &num) const noexcept -> Error::Code override; /// @brief Sets the signal strength bars data diff --git a/module-bluetooth/Bluetooth/interface/profiles/HFP/HFPImpl.hpp b/module-bluetooth/Bluetooth/interface/profiles/HFP/HFPImpl.hpp index c18ddecb47b49c5202de3f5c921f5ab838ca62c0..53e0922725a5a3df81be2ce6e649b011752afc47 100644 --- a/module-bluetooth/Bluetooth/interface/profiles/HFP/HFPImpl.hpp +++ b/module-bluetooth/Bluetooth/interface/profiles/HFP/HFPImpl.hpp @@ -17,11 +17,10 @@ namespace bluetooth public: static void packetHandler(uint8_t packetType, uint16_t channel, uint8_t *event, uint16_t eventSize); auto init() -> Error::Code; - void start(); - void stop(); void startRinging() const noexcept; void stopRinging() const noexcept; void initializeCall() const noexcept; + void terminateCall() const noexcept; void connect(); void disconnect(); void setDevice(Devicei device); diff --git a/module-bluetooth/Bluetooth/interface/profiles/HSP/HSP.cpp b/module-bluetooth/Bluetooth/interface/profiles/HSP/HSP.cpp index 6dd8298cdd1575e74c65577e717afe65917e1ac2..90da835cd3cf300e12648a841271f305669aba8a 100644 --- a/module-bluetooth/Bluetooth/interface/profiles/HSP/HSP.cpp +++ b/module-bluetooth/Bluetooth/interface/profiles/HSP/HSP.cpp @@ -69,16 +69,6 @@ namespace bluetooth pimpl->disconnect(); } - void HSP::start() - { - pimpl->start(); - } - - void HSP::stop() - { - pimpl->stop(); - } - auto HSP::startRinging() const noexcept -> Error::Code { pimpl->startRinging(); @@ -336,18 +326,6 @@ namespace bluetooth { return sco->getStreamData(); } - void HSP::HSPImpl::start() - { - if (!isConnected) { - connect(); - } - } - void HSP::HSPImpl::stop() - { - stopRinging(); - hsp_ag_release_audio_connection(); - callAnswered = false; - } void HSP::HSPImpl::startRinging() const noexcept { @@ -393,9 +371,20 @@ namespace bluetooth { return Error::Success; } + auto HSP::terminateCall() const noexcept -> Error::Code + { + return pimpl->terminateCall(); + } void HSP::HSPImpl::setAudioDevice(std::shared_ptr audioDevice) { HSP::HSPImpl::audioDevice = std::static_pointer_cast(audioDevice); } + auto HSP::HSPImpl::terminateCall() const noexcept -> Error::Code + { + stopRinging(); + hsp_ag_release_audio_connection(); + callAnswered = false; + return Error::Success; + } } // namespace bluetooth diff --git a/module-bluetooth/Bluetooth/interface/profiles/HSP/HSP.hpp b/module-bluetooth/Bluetooth/interface/profiles/HSP/HSP.hpp index da9445e5a2df87beac1220dd7e43d6b2aec62cb6..4a63a1f60915aff66f1586acf608e195e73a805e 100644 --- a/module-bluetooth/Bluetooth/interface/profiles/HSP/HSP.hpp +++ b/module-bluetooth/Bluetooth/interface/profiles/HSP/HSP.hpp @@ -10,7 +10,7 @@ namespace bluetooth { - class HSP : public Profile + class HSP : public CallProfile { static constexpr auto CLASS_OF_DEVICE = 0x400204; // Service class: Telephony, Major device class: Phone, Minor device class: Cellular @@ -29,8 +29,6 @@ namespace bluetooth void connect() override; void disconnect() override; - void start() override; - void stop() override; /// @brief Starts ring /// @return Success [[nodiscard]] auto startRinging() const noexcept -> Error::Code override; @@ -42,6 +40,7 @@ namespace bluetooth /// - SCO link establishment /// @return Success [[nodiscard]] auto initializeCall() const noexcept -> Error::Code override; + [[nodiscard]] auto terminateCall() const noexcept -> Error::Code override; [[nodiscard]] auto callAnswered() const noexcept -> Error::Code override; [[nodiscard]] auto setIncomingCallNumber(const std::string &num) const noexcept -> Error::Code override; /// @return Success - ignoring in HSP diff --git a/module-bluetooth/Bluetooth/interface/profiles/HSP/HSPImpl.hpp b/module-bluetooth/Bluetooth/interface/profiles/HSP/HSPImpl.hpp index ca3fe393bd122dd820858723d3003bbafcd405d5..a7188be1fa077b93fcf7e1fad6cd25d828b64bad 100644 --- a/module-bluetooth/Bluetooth/interface/profiles/HSP/HSPImpl.hpp +++ b/module-bluetooth/Bluetooth/interface/profiles/HSP/HSPImpl.hpp @@ -1,4 +1,4 @@ -// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved. +// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #pragma once @@ -17,11 +17,10 @@ namespace bluetooth public: static void packetHandler(uint8_t packetType, uint16_t channel, uint8_t *event, uint16_t eventSize); auto init() -> Error::Code; - void start(); - void stop(); void startRinging() const noexcept; void stopRinging() const noexcept; void initializeCall() const noexcept; + auto terminateCall() const noexcept -> Error::Code; void connect(); void disconnect(); void setDevice(const Devicei &dev); diff --git a/module-bluetooth/Bluetooth/interface/profiles/PhoneInterface.cpp b/module-bluetooth/Bluetooth/interface/profiles/PhoneInterface.cpp index 2c56f1d121abb8df1f3259a4f90a374f9023941f..15f0e3ed2641f34b9dc947c07d009f2945229eae 100644 --- a/module-bluetooth/Bluetooth/interface/profiles/PhoneInterface.cpp +++ b/module-bluetooth/Bluetooth/interface/profiles/PhoneInterface.cpp @@ -21,4 +21,8 @@ namespace bluetooth { return AudioServiceAPI::RoutingStart(service); } + bool AudioInterfaceImpl::stopAudioRouting(sys::Service *service) + { + return AudioServiceAPI::StopAll(service); + } } // namespace bluetooth diff --git a/module-bluetooth/Bluetooth/interface/profiles/PhoneInterface.hpp b/module-bluetooth/Bluetooth/interface/profiles/PhoneInterface.hpp index d6313d0b659c5fefdcd28d1d81398967fb1bc107..9ff2e76a4d8d6c037f9b54a42038f68ef05d6ef2 100644 --- a/module-bluetooth/Bluetooth/interface/profiles/PhoneInterface.hpp +++ b/module-bluetooth/Bluetooth/interface/profiles/PhoneInterface.hpp @@ -27,10 +27,12 @@ namespace bluetooth public: virtual ~AudioInterface() = default; virtual bool startAudioRouting(sys::Service *service) = 0; + virtual bool stopAudioRouting(sys::Service *service) = 0; }; class AudioInterfaceImpl : public AudioInterface { public: bool startAudioRouting(sys::Service *service) override; + bool stopAudioRouting(sys::Service *service) override; }; } // namespace bluetooth diff --git a/module-bluetooth/Bluetooth/interface/profiles/Profile.hpp b/module-bluetooth/Bluetooth/interface/profiles/Profile.hpp index ab405e09aed0f24207d5f5036b4f7c202a820aba..9cfd43dab40a164849e58efb4b269b2e75e55073 100644 --- a/module-bluetooth/Bluetooth/interface/profiles/Profile.hpp +++ b/module-bluetooth/Bluetooth/interface/profiles/Profile.hpp @@ -21,12 +21,28 @@ namespace bluetooth virtual void setDevice(const Devicei &device) = 0; virtual void setOwnerService(const sys::Service *service) = 0; virtual void connect() = 0; - virtual void start() = 0; - virtual void stop() = 0; virtual void disconnect() = 0; virtual void setAudioDevice(std::shared_ptr audioDevice) = 0; - /// Starts ringing - /// @return Error code that determines, whether operation was successful or not + + protected: + static void initSdp(); + static void initL2cap(); + + private: + static bool isL2CapInitialized; + static bool isSdpInitialized; + }; + + class MusicProfile : public Profile + { + public: + virtual void start() = 0; + virtual void stop() = 0; + }; + + class CallProfile : public Profile + { + public: [[nodiscard]] virtual auto startRinging() const noexcept -> Error::Code = 0; /// Stops ringing /// @return Error code that determines, whether operation was successful or not @@ -34,6 +50,9 @@ namespace bluetooth /// Initializes call /// @return Error code that determines, whether operation was successful or not [[nodiscard]] virtual auto initializeCall() const noexcept -> Error::Code = 0; + /// Terminates call + /// @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 /// @return Error code that determines, whether operation was successful or not [[nodiscard]] virtual auto callAnswered() const noexcept -> Error::Code = 0; @@ -49,14 +68,6 @@ namespace bluetooth /// 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; - - protected: - static void initSdp(); - static void initL2cap(); - - private: - static bool isL2CapInitialized; - static bool isSdpInitialized; }; } // namespace bluetooth diff --git a/module-bluetooth/Bluetooth/interface/profiles/ProfileManager.cpp b/module-bluetooth/Bluetooth/interface/profiles/ProfileManager.cpp index 8e75cb324d3c4cdb154c901f0454608aaafa3457..e3443703521caf2f8a90ed4e9525adc673aaa288 100644 --- a/module-bluetooth/Bluetooth/interface/profiles/ProfileManager.cpp +++ b/module-bluetooth/Bluetooth/interface/profiles/ProfileManager.cpp @@ -25,11 +25,9 @@ namespace bluetooth ptr->init(); } } - // TODO profile selection based on capabilities and priority? - // audio & capa cell & HSP & HFP & A2DP-> HFP - // audio & capa cell & HSP & A2DP-> HSP - // audio & HSP & HFP & A2DP -> A2DP - currentProfilePtr = profilesList[AudioProfile::A2DP].get(); + + musicProfilePtr = dynamic_cast(profilesList[AudioProfile::A2DP].get()); + callProfilePtr = dynamic_cast(profilesList[AudioProfile::HFP].get()); if (auto serviceBt = dynamic_cast(ownerService); serviceBt != nullptr) { serviceBt->profileManagerPtr = this; @@ -60,70 +58,58 @@ namespace bluetooth return Error::Success; } - auto ProfileManager::switchProfile(AudioProfile profile) -> Error::Code - { - if (profilesList[profile] == nullptr) { - LOG_ERROR("Invalid profile!"); - return Error::SystemError; - } - if (currentProfilePtr == profilesList[profile].get()) { - return Error::Success; - } - stop(); - currentProfilePtr = profilesList[profile].get(); - start(); - return Error::Success; - } - auto ProfileManager::start() -> Error::Code { - currentProfilePtr->start(); + musicProfilePtr->start(); return Error::Success; } auto ProfileManager::stop() -> Error::Code { - currentProfilePtr->stop(); + musicProfilePtr->stop(); return Error::Success; } auto ProfileManager::startRinging() -> Error::Code { - switchProfile(AudioProfile::HFP); - return currentProfilePtr->startRinging(); + return callProfilePtr->startRinging(); } auto ProfileManager::stopRinging() -> Error::Code { - return currentProfilePtr->stopRinging(); + return callProfilePtr->stopRinging(); } auto ProfileManager::initializeCall() -> Error::Code { - switchProfile(AudioProfile::HFP); - return currentProfilePtr->initializeCall(); + return callProfilePtr->initializeCall(); + } + auto ProfileManager::terminateCall() -> Error::Code + { + return callProfilePtr->terminateCall(); } auto ProfileManager::setAudioDevice(std::shared_ptr device) -> Error::Code { auto profileType = device->getProfileType(); - if (currentProfilePtr == nullptr || profilesList[profileType] == nullptr) { + if (profilesList[profileType] == nullptr) { return Error::NotReady; } profilesList[profileType]->setAudioDevice(device); - return switchProfile(profileType); + LOG_ERROR("AudioDevice for profile: %s set!", magic_enum::enum_name(profileType).data()); + return Error::Success; } auto ProfileManager::callAnswered() -> Error::Code { - return currentProfilePtr->callAnswered(); + return callProfilePtr->callAnswered(); } auto ProfileManager::setIncomingCallNumber(const DataVariant &data) -> Error::Code { auto number = std::get(data); - if (currentProfilePtr) { - return currentProfilePtr->setIncomingCallNumber(number.getE164()); + if (callProfilePtr) { + return callProfilePtr->setIncomingCallNumber(number.getE164()); } LOG_ERROR("No profile, returning!"); return Error::NotReady; @@ -131,8 +117,8 @@ namespace bluetooth auto ProfileManager::setSignalStrengthData(const DataVariant &data) -> Error::Code { auto signalData = std::get(data); - if (currentProfilePtr) { - return currentProfilePtr->setSignalStrength(static_cast(signalData.rssiBar)); + if (callProfilePtr) { + return callProfilePtr->setSignalStrength(static_cast(signalData.rssiBar)); } LOG_ERROR("No profile, returning!"); return Error::NotReady; @@ -140,8 +126,8 @@ namespace bluetooth auto ProfileManager::setOperatorNameData(const DataVariant &data) -> Error::Code { auto operatorName = std::get(data); - if (currentProfilePtr) { - return currentProfilePtr->setOperatorName(operatorName.getName()); + if (callProfilePtr) { + return callProfilePtr->setOperatorName(operatorName.getName()); } LOG_ERROR("No profile, returning!"); return Error::NotReady; @@ -149,8 +135,8 @@ namespace bluetooth auto ProfileManager::setBatteryLevelData(const DataVariant &data) -> Error::Code { auto batteryLevel = std::get(data); - if (currentProfilePtr) { - return currentProfilePtr->setBatteryLevel(batteryLevel); + if (callProfilePtr) { + return callProfilePtr->setBatteryLevel(batteryLevel); } LOG_ERROR("No profile, returning!"); return Error::NotReady; diff --git a/module-bluetooth/Bluetooth/interface/profiles/ProfileManager.hpp b/module-bluetooth/Bluetooth/interface/profiles/ProfileManager.hpp index a026f7e44c53066d3af1ff28be5a166c625062e2..82a80c11e9bab4cb46307a2150774771c33cccce 100644 --- a/module-bluetooth/Bluetooth/interface/profiles/ProfileManager.hpp +++ b/module-bluetooth/Bluetooth/interface/profiles/ProfileManager.hpp @@ -32,30 +32,26 @@ namespace bluetooth explicit ProfileManager(sys::Service *ownerService); auto init() -> Error::Code; - auto connect(const Devicei &device) -> Error::Code; - auto disconnect() -> Error::Code; - - auto switchProfile(AudioProfile profile) -> Error::Code; - auto start() -> Error::Code; auto stop() -> Error::Code; auto startRinging() -> Error::Code; auto stopRinging() -> Error::Code; auto initializeCall() -> Error::Code; + auto terminateCall() -> Error::Code; auto callAnswered() -> Error::Code; auto setIncomingCallNumber(const DataVariant &data) -> Error::Code; auto setSignalStrengthData(const DataVariant &data) -> Error::Code; auto setOperatorNameData(const DataVariant &data) -> Error::Code; auto setBatteryLevelData(const DataVariant &data) -> Error::Code; - auto setAudioDevice(std::shared_ptr device) -> Error::Code; private: sys::Service *ownerService; ProfileList profilesList; - bluetooth::Profile *currentProfilePtr = nullptr; + bluetooth::MusicProfile *musicProfilePtr = nullptr; + bluetooth::CallProfile *callProfilePtr = nullptr; bool initialized = false; }; } // namespace bluetooth diff --git a/module-bluetooth/lib/btstack b/module-bluetooth/lib/btstack index 6a217e2cc9aa1a4d900f3a26af8c934c980ae145..49c8d45475aa9cad1b853df2c10883ce037161cb 160000 --- a/module-bluetooth/lib/btstack +++ b/module-bluetooth/lib/btstack @@ -1 +1 @@ -Subproject commit 6a217e2cc9aa1a4d900f3a26af8c934c980ae145 +Subproject commit 49c8d45475aa9cad1b853df2c10883ce037161cb diff --git a/module-services/service-audio/ServiceAudio.cpp b/module-services/service-audio/ServiceAudio.cpp index eb6a8e162f004a7fa3d80b738766369edd84bd12..9a066e0731888f72e5c6e79b7b29179974297fd7 100644 --- a/module-services/service-audio/ServiceAudio.cpp +++ b/module-services/service-audio/ServiceAudio.cpp @@ -423,8 +423,7 @@ std::unique_ptr ServiceAudio::HandleStart(const Operation: if (opType == Operation::Type::Playback) { auto input = audioMux.GetPlaybackInput(playbackType); - if (playbackType == audio::PlaybackType::CallRingtone && bluetoothVoiceProfileConnected && input && - (*input)->audio->GetPriorityPlaybackProfile() == Profile::Type::PlaybackBluetoothA2DP) { + if (playbackType == audio::PlaybackType::CallRingtone && bluetoothVoiceProfileConnected && input) { LOG_DEBUG("Sending Bluetooth start ringing"); bus.sendUnicast(std::make_shared(message::bluetooth::Ring::State::Enable), service::name::bluetooth); @@ -448,10 +447,6 @@ std::unique_ptr ServiceAudio::HandleStart(const Operation: } else if (opType == Operation::Type::Router) { auto input = audioMux.GetRoutingInput(true); - if (bluetoothVoiceProfileConnected) { - LOG_DEBUG("Sending Bluetooth start routing"); - bus.sendUnicast(std::make_shared(), service::name::bluetooth); - } AudioStart(input); return std::make_unique(retCode, retToken); } @@ -527,7 +522,7 @@ std::unique_ptr ServiceAudio::HandleStop(const std::vector } // stop bluetooth stream if available - if (bluetoothA2DPConnected || bluetoothVoiceProfileConnected) { + if (bluetoothA2DPConnected) { LOG_DEBUG("Sending Bluetooth stop request"); bus.sendUnicast(std::make_shared(BluetoothMessage::Request::Stop), service::name::bluetooth); } diff --git a/module-services/service-bluetooth/ServiceBluetooth.cpp b/module-services/service-bluetooth/ServiceBluetooth.cpp index 3566eb47476ba70715348d26a04c8aa0f9b9052e..0718b0fa0a4a8268028ecd5ad4576434d1e9ca6d 100644 --- a/module-services/service-bluetooth/ServiceBluetooth.cpp +++ b/module-services/service-bluetooth/ServiceBluetooth.cpp @@ -118,6 +118,7 @@ sys::ReturnCodes ServiceBluetooth::InitHandler() connectHandler(); connectHandler(); connectHandler(); + connectHandler(); connectHandler(); connectHandler(); connectHandler(); @@ -419,9 +420,6 @@ auto ServiceBluetooth::handle(BluetoothMessage *msg) -> std::shared_ptr std::shared auto ServiceBluetooth::handle(message::bluetooth::Ring *msg) -> std::shared_ptr { + LOG_DEBUG("Start ringing from audio"); const auto enableRing = msg->enabled(); sendWorkerCommand(enableRing ? bluetooth::Command::Type::StartRinging : bluetooth::Command::Type::StopRinging); @@ -570,3 +569,8 @@ auto ServiceBluetooth::handle(sevm::BatteryStatusChangeMessage *msg) -> std::sha sendWorkerCommand(bluetooth::Command::Type::BatteryLevelData, std::move(commandData)); return sys::MessageNone{}; } +auto ServiceBluetooth::handle(cellular::CallEndedNotification *msg) -> std::shared_ptr +{ + sendWorkerCommand(bluetooth::Command::Type::CallTerminated); + return sys::MessageNone{}; +} diff --git a/module-services/service-bluetooth/service-bluetooth/BluetoothMessage.hpp b/module-services/service-bluetooth/service-bluetooth/BluetoothMessage.hpp index 0aa759e8acd5a66edb92acce20e318b30abc9c67..af740b49a9b657f70c11bdf1143e1438929ca75a 100644 --- a/module-services/service-bluetooth/service-bluetooth/BluetoothMessage.hpp +++ b/module-services/service-bluetooth/service-bluetooth/BluetoothMessage.hpp @@ -37,7 +37,6 @@ class BluetoothMessage : public sys::DataMessage getDevicesAvailable, Visible, Play, - SwitchProfile, Stop, Disconnect }; diff --git a/module-services/service-bluetooth/service-bluetooth/ServiceBluetooth.hpp b/module-services/service-bluetooth/service-bluetooth/ServiceBluetooth.hpp index 5e32508aad4464b2efcf27a394dbf2a93fab5595..5db1240c5aae7c4af5c404ef21cdb4fe28f45645 100644 --- a/module-services/service-bluetooth/service-bluetooth/ServiceBluetooth.hpp +++ b/module-services/service-bluetooth/service-bluetooth/ServiceBluetooth.hpp @@ -67,6 +67,10 @@ class CellularCallerIdMessage; class CellularCallActiveNotification; class CellularSignalStrengthUpdateNotification; class CellularCurrentOperatorNameNotification; +namespace cellular +{ + class CallEndedNotification; +} class ServiceBluetooth : public sys::Service { @@ -129,6 +133,7 @@ class ServiceBluetooth : public sys::Service [[nodiscard]] auto handle(message::bluetooth::RequestStatusIndicatorData *msg) -> std::shared_ptr; [[nodiscard]] auto handle(CellularCallerIdMessage *msg) -> std::shared_ptr; [[nodiscard]] auto handle(CellularCallActiveNotification *msg) -> std::shared_ptr; + [[nodiscard]] auto handle(cellular::CallEndedNotification *msg) -> std::shared_ptr; [[nodiscard]] auto handle(CellularSignalStrengthUpdateNotification *msg) -> std::shared_ptr; [[nodiscard]] auto handle(CellularCurrentOperatorNameNotification *msg) -> std::shared_ptr; [[nodiscard]] auto handle(sevm::BatteryStatusChangeMessage *msg) -> std::shared_ptr; diff --git a/module-utils/log/Logger.cpp b/module-utils/log/Logger.cpp index 222fc283133c232e49d929a7c8d27fdac59c13cb..9ea48fbcec8017d127ac9c341a32dc8832a2c881 100644 --- a/module-utils/log/Logger.cpp +++ b/module-utils/log/Logger.cpp @@ -40,7 +40,6 @@ namespace Log {CRIT_STR, logger_level::LOGTRACE}, {IRQ_STR, logger_level::LOGTRACE}, {"FileIndexer", logger_level::LOGINFO}, - {"ServiceAudio", logger_level::LOGERROR}, {"EventManager", logger_level::LOGINFO} }; }