~aleteoryx/muditaos

434a335ef3ea6d661599768e1a53157b08606c01 — Lefucjusz 3 years ago a809565
[MOS-411] Wired headset audio fix

Fixes non-working wired headset audio
during call
M image/user/data/equalizer/headphones_routing.json => image/user/data/equalizer/headphones_routing.json +5 -5
@@ 1,10 1,10 @@
{
  "samplerate": 0,
  "samplerate": 16000,
  "bitWidth": 16,
  "flags": 0,
  "outputVolume": 0,
  "inputGain": 0,
  "inputPath": 2,
  "flags": 5,
  "outputVolume": 10,
  "inputGain": 5,
  "inputPath": 0,
  "outputPath": 0,
  "filterParams": [
    {

M module-audio/Audio/AudioCommon.hpp => module-audio/Audio/AudioCommon.hpp +3 -2
@@ 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


@@ 95,7 95,8 @@ namespace audio
    enum class EventType
    {
        // HW state change notifications
        JackState,               //!< jack input plugged / unplugged event
        JackState,               //!< Jack input plugged / unplugged event
        MicrophoneState,         //!< Microphone presence in headset (3-pole w/o microphone or 4-pole with microphone)
        BlutoothHSPDeviceState,  //!< BT device connected / disconnected event (Headset Profile)
        BlutoothHFPDeviceState,  //!< BT device connected / disconnected event (Headset Profile)
        BlutoothA2DPDeviceState, //!< BT device connected / disconnected event (Advanced Audio Distribution Profile)

M module-audio/Audio/Operation/Operation.cpp => module-audio/Audio/Operation/Operation.cpp +3 -3
@@ 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 "Operation.hpp"


@@ 45,7 45,7 @@ namespace audio
    std::shared_ptr<Profile> Operation::GetProfile(const Profile::Type type)
    {
        auto ret = std::find_if(supportedProfiles.begin(), supportedProfiles.end(), [type](const auto &w) {
            return w.isAvailable == true && w.profile->GetType() == type;
            return w.isAvailable && w.profile->GetType() == type;
        });
        if (ret == supportedProfiles.end()) {
            return nullptr;


@@ 58,7 58,7 @@ namespace audio
    std::optional<Profile::Type> Operation::GetPriorityProfile() const
    {
        for (auto &p : supportedProfiles) {
            if (p.isAvailable == true) {
            if (p.isAvailable) {
                return p.profile->GetType();
            }
        }

M module-audio/Audio/Operation/RouterOperation.cpp => module-audio/Audio/Operation/RouterOperation.cpp +20 -4
@@ 9,6 9,7 @@
#include <Audio/StreamFactory.hpp>
#include <Audio/transcode/TransformFactory.hpp>

#include <bsp/headset/headset.hpp>
#include <log/log.hpp>
#include <mutex.hpp>



@@ 140,6 141,13 @@ namespace audio
            jackState = isAvailable ? JackState::Plugged : JackState::Unplugged;
            SwitchToPriorityProfile();
            break;
        case EventType::MicrophoneState: {
            auto headsetHasMicrophone = isAvailable;
            LOG_DEBUG("Microphone state event has been received, does the headset have a microphone? %s",
                      headsetHasMicrophone ? "Yes" : "No");
            setInputPathForHeadset(headsetHasMicrophone);
            SwitchToPriorityProfile();
        } break;
        case EventType::BlutoothHSPDeviceState:
            SetProfileAvailability({Profile::Type::RoutingBluetoothHSP}, isAvailable);
            SwitchToPriorityProfile();


@@ 182,10 190,6 @@ namespace audio
            return RetCode::UnsupportedProfile;
        }

        if (currentProfile && currentProfile->GetType() == newProfile->GetType()) {
            return RetCode::Success;
        }

        if (callInProgress) {
            Stop();
        }


@@ 234,6 238,18 @@ namespace audio
        return 0.0;
    }

    void RouterOperation::setInputPathForHeadset(bool headsetHasMicrophone)
    {
        const auto inputPath =
            headsetHasMicrophone ? audio::codec::InputPath::Headphones : audio::codec::InputPath::Microphone;
        for (const auto &p : supportedProfiles) {
            if (p.profile->GetType() == Profile::Type::RoutingHeadphones) {
                p.profile->SetInputPath(inputPath);
                return; // Don't check remaining profiles after finding the right one
            }
        }
    }

    RouterOperation::~RouterOperation()
    {
        Stop();

M module-audio/Audio/Operation/RouterOperation.hpp => module-audio/Audio/Operation/RouterOperation.hpp +3 -1
@@ 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


@@ 67,6 67,8 @@ namespace audio
        void Unmute();
        [[nodiscard]] auto IsMuted() const noexcept -> bool;

        void setInputPathForHeadset(bool headsetHasMicrophone);

        std::unique_ptr<AbstractStream> dataStreamOut;
        std::unique_ptr<AbstractStream> dataStreamIn;
        std::shared_ptr<AudioDevice> audioDeviceCellular;

M module-bsp/board/linux/headset/headset.cpp => module-bsp/board/linux/headset/headset.cpp +2 -2
@@ 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 "headset.hpp"


@@ 13,7 13,7 @@ namespace bsp
            return 1;
        }

        HeadsetState headset_get_data(bool &headsetState, uint8_t &keyEvent, uint8_t &keyCode)
        HeadsetState headset_get_data(bool &headsetState, bool &microphoneState, uint8_t &keyEvent, uint8_t &keyCode)
        {
            return HeadsetState::NoChange;
        }

M module-bsp/board/rt1051/bsp/headset/headset.cpp => module-bsp/board/rt1051/bsp/headset/headset.cpp +9 -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 "headset.hpp"


@@ 143,7 143,7 @@ namespace bsp
            }
        }

        HeadsetState headset_get_data(bool &headsetState, uint8_t &keyEvent, uint8_t &keyCode)
        HeadsetState headset_get_data(bool &headsetState, bool &microphoneState, uint8_t &keyEvent, uint8_t &keyCode)
        {
            uint8_t reg;
            uint8_t acc_status              = 0;


@@ 158,7 158,7 @@ namespace bsp

            // Check if jack removed event
            if (((acc_status & static_cast<uint8_t>(HeadsetIQRDetectionResult::DETRES_INSERTION_STATUS)) == 0) &&
                (HeadsetInserted == true)) {
                HeadsetInserted) {
                HeadsetInserted = false;
                MicrophoneInserted = false;



@@ 169,11 169,12 @@ namespace bsp
                i2cAddr.subAddress = HEADSET_DEV_SETTING_1_REG;
                i2c->Modify(i2cAddr, reg, MicrophoneInserted, 1);

                headsetState       = static_cast<uint8_t>(HeadsetInserted);
                headsetState       = HeadsetInserted;
                microphoneState    = MicrophoneInserted;
                headsetStateChange = HeadsetState::Changed;
            }
            else if (((acc_status & static_cast<uint8_t>(HeadsetIQRDetectionResult::DETRES_INSERTION_STATUS)) != 0) &&
                     (HeadsetInserted == false)) {
                     !HeadsetInserted) {
                LOG_INFO("Headset inserted");
                HeadsetInserted = true;



@@ 196,7 197,7 @@ namespace bsp
                    insertedHeadsetType = HeadsetType::TypeCTIA;
                    break;
                default:
                    LOG_INFO("uknown Headset type detected");
                    LOG_INFO("Unknown Headset type detected");
                    MicrophoneInserted  = false;
                    insertedHeadsetType = HeadsetType::TypeDontCare;
                }


@@ 206,7 207,8 @@ namespace bsp
                i2cAddr.subAddress = HEADSET_DEV_SETTING_1_REG;
                i2c->Modify(i2cAddr, reg, MicrophoneInserted, 1);

                headsetState       = static_cast<uint8_t>(HeadsetInserted);
                headsetState       = HeadsetInserted;
                microphoneState    = MicrophoneInserted;
                headsetStateChange = HeadsetState::Changed;
            }
            // Key pressed/released event

M module-bsp/bsp/headset/headset.hpp => module-bsp/bsp/headset/headset.hpp +2 -1
@@ 19,11 19,12 @@ namespace bsp {
    /**
     * @brief This method is responsible for reading state of headset and its keys.
     * @param headsetState headset event (1 - connected, 0 - removed)
     * @param microphoneState headset event (1 - present, 0 - absent)
     * @param keyEvent key event (1 - pressed, 0 - released)
     * @param keyCode key code
     * @note Method returns `HeadsetState::Changed` if state of headset changed (connected -> removed)
     */
    HeadsetState headset_get_data(bool &headsetState, uint8_t &keyEvent, uint8_t &keyCode);
    HeadsetState headset_get_data(bool &headsetState, bool &microphoneState, uint8_t &keyEvent, uint8_t &keyCode);

    bool IsInserted();


M module-services/service-audio/ServiceAudio.cpp => module-services/service-audio/ServiceAudio.cpp +1 -1
@@ 66,7 66,7 @@ static constexpr std::initializer_list<std::pair<audio::DbPathElement, const cha

    {DbPathElement{Setting::Gain, PlaybackType::None, Profile::Type::RoutingEarspeaker}, "3"},
    {DbPathElement{Setting::Gain, PlaybackType::None, Profile::Type::RoutingLoudspeaker}, "10"},
    {DbPathElement{Setting::Gain, PlaybackType::None, Profile::Type::RoutingHeadphones}, "0"},
    {DbPathElement{Setting::Gain, PlaybackType::None, Profile::Type::RoutingHeadphones}, "5"},

    {DbPathElement{Setting::Volume, PlaybackType::None, Profile::Type::RoutingBluetoothHSP}, defaultVolumeHigh},
    {DbPathElement{Setting::Volume, PlaybackType::None, Profile::Type::RoutingBluetoothHFP}, defaultVolumeHigh},

M products/PurePhone/services/evtmgr/WorkerEvent.cpp => products/PurePhone/services/evtmgr/WorkerEvent.cpp +11 -6
@@ 51,16 51,21 @@ bool WorkerEvent::handleMessage(std::uint32_t queueID)
        if (!queue->Dequeue(&notification, 0)) {
            return false;
        }
        bool headsetState = false;
        bool headsetState, microphoneState;
        uint8_t headsetKeyEvent, headsetKeyCode;

        if (bsp::headset::headset_get_data(headsetState, headsetKeyEvent, headsetKeyCode) ==
        if (bsp::headset::headset_get_data(headsetState, microphoneState, headsetKeyEvent, headsetKeyCode) ==
            bsp::headset::HeadsetState::Changed) {

            auto message = std::make_shared<AudioEventRequest>(audio::EventType::JackState,
                                                               headsetState ? audio::Event::DeviceState::Connected
                                                                            : audio::Event::DeviceState::Disconnected);
            service->bus.sendUnicast(message, service::name::evt_manager);
            auto jackStateMessage = std::make_shared<AudioEventRequest>(
                audio::EventType::JackState,
                headsetState ? audio::Event::DeviceState::Connected : audio::Event::DeviceState::Disconnected);
            service->bus.sendUnicast(std::move(jackStateMessage), service::name::evt_manager);

            auto micStateMessage = std::make_shared<AudioEventRequest>(
                audio::EventType::MicrophoneState,
                microphoneState ? audio::Event::DeviceState::Connected : audio::Event::DeviceState::Disconnected);
            service->bus.sendUnicast(std::move(micStateMessage), service::name::evt_manager);
        }
        else if (auto keyCode = headsetKeyToKeyboardKey(headsetKeyCode); keyCode != bsp::KeyCodes::Undefined) {
            WorkerEventCommon::processKeyEvent(static_cast<bsp::KeyEvents>(headsetKeyEvent), keyCode);