~aleteoryx/muditaos

5e57914cc3a66c3159553b09c4d1855094871c0e — Lefucjusz 3 years ago 2c08432
[MOS-353][MOS-387] HFP profile fixes

Fixes for the HFP-related problems - lack of the
sound from caller's phone in HF speakers and
not working BT device's hardware hangup button
M module-bluetooth/Bluetooth/interface/profiles/HFP/HFP.cpp => module-bluetooth/Bluetooth/interface/profiles/HFP/HFP.cpp +32 -34
@@ 97,7 97,7 @@ namespace bluetooth
    }
    auto HFP::callAnswered() const noexcept -> Error::Code
    {
        return pimpl->callAnswered();
        return pimpl->setupCall();
    }
    auto HFP::setIncomingCallNumber(const std::string &num) const noexcept -> Error::Code
    {


@@ 153,9 153,9 @@ namespace bluetooth
        {2, 1},
    };
    Devicei HFP::HFPImpl::device;
    bool HFP::HFPImpl::isAudioRouted                = false;
    bool HFP::HFPImpl::isConnected                  = false;
    bool HFP::HFPImpl::isAudioConnectionEstablished = false;
    bool HFP::HFPImpl::isIncomingCall               = false;
    bool HFP::HFPImpl::isCallInitialized            = false;

    void HFP::HFPImpl::dump_supported_codecs(void)
    {


@@ 279,23 279,19 @@ namespace bluetooth
            if (hfp_subevent_audio_connection_established_get_status(event)) {
                LOG_DEBUG("Audio connection establishment failed with status %u\n",
                          hfp_subevent_audio_connection_established_get_status(event));
                isAudioConnectionEstablished = false;
            }
            else {
                scoHandle = hfp_subevent_audio_connection_established_get_sco_handle(event);
                LOG_DEBUG("Audio connection established with SCO handle 0x%04x.\n", scoHandle);
                codec = static_cast<SCOCodec>(hfp_subevent_audio_connection_established_get_negotiated_codec(event));
                isAudioConnectionEstablished = true;
                dump_supported_codecs();
                hci_request_sco_can_send_now_event();
                RunLoop::trigger();
            }
            break;
        case HFP_SUBEVENT_AUDIO_CONNECTION_RELEASED:
            LOG_DEBUG("Audio connection released\n");
            LOG_DEBUG("Audio connection released");
            scoHandle = HCI_CON_HANDLE_INVALID;
            isAudioRouted                = false;
            isAudioConnectionEstablished = false;
            audioDevice.reset();
            break;
        case HFP_SUBEVENT_START_RINGING:


@@ 307,7 303,6 @@ namespace bluetooth
            // todo stop ringtone stream here
            break;
        case HFP_SUBEVENT_PLACE_CALL_WITH_NUMBER:
            hfp_ag_outgoing_call_accepted();
            break;

        case HFP_SUBEVENT_ATTACH_NUMBER_TO_VOICE_TAG:


@@ 320,12 315,8 @@ namespace bluetooth
            hfp_ag_send_dtmf_code_done(aclHandle);
            break;
        case HFP_SUBEVENT_CALL_ANSWERED:
            LOG_DEBUG("Call answered by HF\n");
            LOG_DEBUG("Call answered");
            cellularInterface->answerIncomingCall(const_cast<sys::Service *>(ownerService));
            if (!isAudioRouted) {
                audioInterface->startAudioRouting(const_cast<sys::Service *>(ownerService));
                isAudioRouted = true;
            }
            break;

        case HFP_SUBEVENT_SPEAKER_VOLUME: {


@@ 336,7 327,7 @@ namespace bluetooth
        } break;

        case HFP_SUBEVENT_CALL_TERMINATED:
            LOG_DEBUG("Call terminated by HF\n");
            LOG_DEBUG("Call terminated");
            cellularInterface->hangupCall(const_cast<sys::Service *>(ownerService));
            break;
        default:


@@ 345,13 336,6 @@ namespace bluetooth
        }
    }

    void HFP::HFPImpl::establishAudioConnection()
    {
        if (!isAudioConnectionEstablished) {
            LOG_DEBUG("Establish Audio connection to %s...\n", bd_addr_to_str(device.address));
            hfp_ag_establish_audio_connection(aclHandle);
        }
    }
    static hfp_phone_number_t subscriber_number = {129, "225577"};
    auto HFP::HFPImpl::init() -> Error::Code
    {


@@ 437,6 421,7 @@ namespace bluetooth
    {
        return sco->getStreamData();
    }

    void HFP::HFPImpl::start()
    {
        if (!isConnected) {


@@ 445,9 430,12 @@ namespace bluetooth
        hfp_ag_set_speaker_gain(aclHandle, 8);
        hfp_ag_set_microphone_gain(aclHandle, 10);
    }

    void HFP::HFPImpl::stop()
    {
        hfp_ag_call_dropped();
        hfp_ag_terminate_call();
        isCallInitialized = false;
        isIncomingCall    = false;
    }

    void HFP::HFPImpl::initCodecs()


@@ 471,9 459,11 @@ namespace bluetooth
    }
    void HFP::HFPImpl::initializeCall() const noexcept
    {
        if (!isAudioRouted) {
            LOG_DEBUG("Phone number is unused in BT stack - mocking");
            hfp_ag_outgoing_call_initiated("1234567");
        if (!isCallInitialized && !isIncomingCall) {
            LOG_DEBUG("Initializing outgoing call");
            constexpr auto mockNumber = "1234567"; // Mocking phone number - it is not used in stack
            hfp_ag_outgoing_call_initiated(mockNumber);
            isCallInitialized = true;
        }
    }
    void HFP::HFPImpl::setAudioDevice(std::shared_ptr<bluetooth::BluetoothAudioDevice> audioDevice)


@@ 483,20 473,28 @@ namespace bluetooth
    }
    void HFP::HFPImpl::startRinging() const noexcept
    {
        LOG_DEBUG("Starting incoming call");
        isIncomingCall = true;
        hfp_ag_incoming_call();
    }
    void HFP::HFPImpl::stopRinging() const noexcept
    {}
    auto HFP::HFPImpl::callAnswered() const noexcept -> Error::Code
    {
        LOG_DEBUG("Call answered!");
        hfp_ag_answer_incoming_call();
        establishAudioConnection();
        if (!isAudioRouted) {
            LOG_DEBUG("Routing unrouted audio after answering call");
        LOG_DEBUG("Stop ringing called!");
    }
    auto HFP::HFPImpl::setupCall() const noexcept -> Error::Code
    {
        if (isIncomingCall) {
            LOG_DEBUG("Answering incoming call");
            hfp_ag_answer_incoming_call();
        }
        else {
            LOG_DEBUG("Establishing outgoing call");
            audioInterface->startAudioRouting(const_cast<sys::Service *>(ownerService));
            isAudioRouted = true;
            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

M module-bluetooth/Bluetooth/interface/profiles/HFP/HFPImpl.hpp => module-bluetooth/Bluetooth/interface/profiles/HFP/HFPImpl.hpp +3 -4
@@ 28,7 28,7 @@ namespace bluetooth
        void setOwnerService(const sys::Service *service);
        auto getStreamData() -> std::shared_ptr<BluetoothStreamData>;
        void setAudioDevice(std::shared_ptr<bluetooth::BluetoothAudioDevice> audioDevice);
        [[nodiscard]] auto callAnswered() const noexcept -> Error::Code;
        [[nodiscard]] auto setupCall() 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;


@@ 38,7 38,6 @@ namespace bluetooth
        static void sendAudioEvent(audio::EventType event, audio::Event::DeviceState state);
        static void processHCIEvent(uint8_t *event);
        static void processHFPEvent(uint8_t *event);
        static void establishAudioConnection();
        static void initCodecs();
        static void dump_supported_codecs(void);
        static std::array<uint8_t, serviceBufferLength> serviceBuffer;


@@ 61,8 60,8 @@ namespace bluetooth
        [[maybe_unused]] static hfp_generic_status_indicator_t hf_indicators[2];
        static std::shared_ptr<CVSDAudioDevice> audioDevice;
        static Devicei device;
        static bool isAudioRouted;
        static bool isConnected;
        static bool isAudioConnectionEstablished;
        static bool isIncomingCall;
        static bool isCallInitialized;
    };
} // namespace bluetooth

M module-bluetooth/Bluetooth/interface/profiles/PhoneInterface.cpp => module-bluetooth/Bluetooth/interface/profiles/PhoneInterface.cpp +2 -7
@@ 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 "PhoneInterface.hpp"


@@ 9,17 9,12 @@ namespace bluetooth
{
    bool CellularInterfaceImpl::answerIncomingCall(sys::Service *service)
    {
        callActive = true;
        return CellularServiceAPI::AnswerIncomingCall(service);
    }

    bool CellularInterfaceImpl::hangupCall(sys::Service *service)
    {
        if (callActive) {
            callActive = false;
            return CellularServiceAPI::HangupCall(service);
        }
        return true;
        return CellularServiceAPI::HangupCall(service);
    }

    bool AudioInterfaceImpl::startAudioRouting(sys::Service *service)

M module-bluetooth/Bluetooth/interface/profiles/PhoneInterface.hpp => module-bluetooth/Bluetooth/interface/profiles/PhoneInterface.hpp +1 -4
@@ 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


@@ 20,9 20,6 @@ namespace bluetooth
      public:
        bool answerIncomingCall(sys::Service *service) override;
        bool hangupCall(sys::Service *service) override;

      private:
        bool callActive = false;
    };

    class AudioInterface

M module-bluetooth/Bluetooth/interface/profiles/SCO/ScoUtils.cpp => module-bluetooth/Bluetooth/interface/profiles/SCO/ScoUtils.cpp +10 -6
@@ 1,8 1,8 @@
// 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 "ScoUtils.hpp"
#include <algorithm>
#include <log/log.hpp>

extern "C"
{


@@ 15,19 15,23 @@ namespace bluetooth::sco::utils
    void sendZeros(hci_con_handle_t scoHandle)
    {
        if (scoHandle == HCI_CON_HANDLE_INVALID) {
            LOG_ERROR("Invalid scoHandle!");
            return;
        }
        constexpr auto offset         = 3;
        constexpr auto packetDataOffset = 3;
        constexpr auto lengthPosition = 2;
        const auto scoPacketLength    = hci_get_sco_packet_length();
        const auto scoPayloadLength   = scoPacketLength - offset;
        const auto scoPayloadLength     = scoPacketLength - packetDataOffset;

        hci_reserve_packet_buffer();
        auto *scoPacket = hci_get_outgoing_packet_buffer();
        std::fill(scoPacket + offset, scoPacket + sizeof(scoPacket), 0);
        auto scoPacket     = hci_get_outgoing_packet_buffer();
        auto scoPayloadPtr = scoPacket + packetDataOffset;

        memset(scoPayloadPtr, 0, scoPayloadLength); // zero-fill the payload

        little_endian_store_16(scoPacket, 0, scoHandle);
        scoPacket[lengthPosition] = scoPayloadLength;

        hci_send_sco_packet_buffer(scoPacketLength);
        hci_request_sco_can_send_now_event();
    }

M module-bluetooth/lib/btstack => module-bluetooth/lib/btstack +1 -1
@@ 1,1 1,1 @@
Subproject commit edeaa6ceebef69dd66aff31f8ad3100c8c1f435f
Subproject commit 6a217e2cc9aa1a4d900f3a26af8c934c980ae145