From c5e533f94f68cd4e2924e8d3d3e485612214082f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcin=20Zieli=C5=84ski?= Date: Fri, 21 Oct 2022 15:38:55 +0200 Subject: [PATCH] [MOS-770] Replace VoLTE state switching mechanism Introduced the new implementation. --- module-apps/CMakeLists.txt | 5 ++ .../service-cellular/CMakeLists.txt | 1 + .../service-cellular/ServiceCellular.cpp | 14 ++- .../src/ServiceCellularPriv.hpp | 4 + .../service-cellular/src/VolteHandler.hpp | 88 +++++++++++++++++++ .../service-cellular/src/VolteHandlerImpl.cpp | 28 ++++++ .../service-cellular/src/VolteHandlerImpl.hpp | 17 ++++ 7 files changed, 156 insertions(+), 1 deletion(-) create mode 100644 module-services/service-cellular/src/VolteHandler.hpp create mode 100644 module-services/service-cellular/src/VolteHandlerImpl.cpp create mode 100644 module-services/service-cellular/src/VolteHandlerImpl.hpp diff --git a/module-apps/CMakeLists.txt b/module-apps/CMakeLists.txt index 7c35e07aed6d371cca7688bf6abea1598c55bcc0..a958f78979851fd84ca32cf0867b8e78cba6c5ee 100644 --- a/module-apps/CMakeLists.txt +++ b/module-apps/CMakeLists.txt @@ -58,6 +58,11 @@ if (${CMAKE_BUILD_TYPE} STREQUAL "Debug") endforeach() endif() +option(ENABLE_VOLTE "Enable VoLTE" OFF) +if(${ENABLE_VOLTE}) + target_compile_definitions(${PROJECT_NAME} PUBLIC ENABLE_VOLTE=1) +endif() + option(DISABLED_SETTINGS_OPTIONS "Enable Disabled Settings Options" OFF) if(${DISABLED_SETTINGS_OPTIONS}) target_compile_definitions(${PROJECT_NAME} PUBLIC DISABLED_SETTINGS_OPTIONS=1) diff --git a/module-services/service-cellular/CMakeLists.txt b/module-services/service-cellular/CMakeLists.txt index ea6738e4015ec1842083f0f745d2cf14cad26e1e..a7a2eea970d1dc4dd164d7d4339762e3d7b09d05 100644 --- a/module-services/service-cellular/CMakeLists.txt +++ b/module-services/service-cellular/CMakeLists.txt @@ -13,6 +13,7 @@ set(SOURCES src/TerhetingHandler.cpp src/ModemResetHandler.cpp src/URCCounter.cpp + src/VolteHandlerImpl.cpp src/CSQHandler.cpp DTMFCode.cpp diff --git a/module-services/service-cellular/ServiceCellular.cpp b/module-services/service-cellular/ServiceCellular.cpp index e2d5bee7280045273520c9920cee0a0b2367da6d..6276c885a3c682c59fec0d0f0dad021af1b55bc7 100644 --- a/module-services/service-cellular/ServiceCellular.cpp +++ b/module-services/service-cellular/ServiceCellular.cpp @@ -870,7 +870,19 @@ bool ServiceCellular::handle_cellular_priv_init() priv->simContacts->setChannel(channel); priv->imeiGetHandler->setChannel(channel); - if (!priv->tetheringHandler->configure()) { +#if ENABLE_VOLTE == 1 + constexpr bool enableVolte = true; +#else + constexpr bool enableVolte = false; +#endif + bool needReset = false; + try { + needReset = !priv->tetheringHandler->configure() || !priv->volteHandler->switchVolte(*channel, enableVolte); + } + catch (std::runtime_error const &exc) { + LOG_ERROR("%s", exc.what()); + } + if (needReset) { priv->modemResetHandler->performHardReset(); return true; } diff --git a/module-services/service-cellular/src/ServiceCellularPriv.hpp b/module-services/service-cellular/src/ServiceCellularPriv.hpp index edff1120997385d49a0479d9c629a45c7c4dd687..99fec1d9dfe512024a4ecd31a73d3bd365f362bf 100644 --- a/module-services/service-cellular/src/ServiceCellularPriv.hpp +++ b/module-services/service-cellular/src/ServiceCellularPriv.hpp @@ -12,6 +12,8 @@ #include "SimContacts.hpp" #include "ImeiGetHandler.hpp" #include "TetheringHandler.hpp" +#include "VolteHandler.hpp" +#include "VolteHandlerImpl.hpp" #include "ModemResetHandler.hpp" #include "CSQHandler.hpp" @@ -24,6 +26,7 @@ namespace cellular::internal using service::SimContacts; using service::State; using service::TetheringHandler; + using service::VolteHandler; class ServiceCellularPriv { @@ -36,6 +39,7 @@ namespace cellular::internal std::unique_ptr simContacts; std::unique_ptr imeiGetHandler; std::unique_ptr tetheringHandler; + std::unique_ptr> volteHandler; std::unique_ptr modemResetHandler; std::unique_ptr csqHandler; diff --git a/module-services/service-cellular/src/VolteHandler.hpp b/module-services/service-cellular/src/VolteHandler.hpp new file mode 100644 index 0000000000000000000000000000000000000000..d094d826176f9ebd44835ad5ad5973b887e64f88 --- /dev/null +++ b/module-services/service-cellular/src/VolteHandler.hpp @@ -0,0 +1,88 @@ +// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#pragma once + +#include +#include +#include +#include +#include + +namespace +{ + struct NonCopyable + { + explicit NonCopyable() = default; + ~NonCopyable() = default; + NonCopyable(NonCopyable const &) = delete; + NonCopyable &operator=(NonCopyable const &) = delete; + NonCopyable(NonCopyable &&) = default; + NonCopyable &operator=(NonCopyable &&) = default; + }; +} // namespace + +namespace cellular::service +{ + using namespace at; + + struct QcfgImsResult : Result + { + QcfgImsResult(Result &rhs) : Result{std::move(rhs)} + {} + }; + + template + struct VolteHandler : private NonCopyable + { + bool switchVolte(CmuxChannel &channel, bool enable) const + { + ModemResponseParser const parser; + + if (enable) { + // according to Quectel, this setting doesn't have to be reset when disabling + constexpr std::uint8_t voiceDomainPacketSwitchedPreferred = 0x03; + auto voiceDomainAnswer = + channel.cmd(factory(at::AT::QNVFW) + "\"/nv/item_files/modem/mmode/voice_domain_pref\"," + + utils::byteToHex(voiceDomainPacketSwitchedPreferred)); + if (!voiceDomainAnswer) { + throw std::runtime_error("[VoLTE] failed to set voice domain before trying to enable VoLTE"); + } + + // can be left as always on: doesn't disturb when VoLTE disabled + auto qmbnAnswer = + channel.cmd(factory(at::AT::QMBNCFG) + std::string("\"autosel\",1")); + if (!qmbnAnswer) { + throw std::runtime_error("[VoLTE] failed to enable MBN auto-select before trying to enable VoLTE"); + } + } + + auto imsCheckAnswer = channel.cmd(factory(AT::QCFG_IMS)); + bool alreadyConfigured; + try { + alreadyConfigured = parser(QcfgImsResult{imsCheckAnswer}, enable); + } + catch (std::runtime_error const &exc) { + throw std::runtime_error(std::string("[VoLTE] while checking IMS configuration state: ") + exc.what()); + } + + if (!alreadyConfigured) { + using namespace response::qcfg_ims; + auto imsToggleAnswer = channel.cmd(factory(AT::QCFG_IMS) + "," + + imsStateToString(enable ? IMSState::Enable : IMSState::Disable)); + if (!imsToggleAnswer) { + throw std::runtime_error("[VoLTE] failed to " + std::string(enable ? "enable" : "disable") + + " IMS"); + } + } + + return alreadyConfigured; + } + + private: + std::string imsStateToString(response::qcfg_ims::IMSState imsState) const + { + return std::to_string(magic_enum::enum_integer(imsState)); + } + }; +} // namespace cellular::service diff --git a/module-services/service-cellular/src/VolteHandlerImpl.cpp b/module-services/service-cellular/src/VolteHandlerImpl.cpp new file mode 100644 index 0000000000000000000000000000000000000000..a41a8fd0b9d5f2b26ee72bf2fa95fe32720ed798 --- /dev/null +++ b/module-services/service-cellular/src/VolteHandlerImpl.cpp @@ -0,0 +1,28 @@ +// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#include "VolteHandlerImpl.hpp" + +namespace cellular::internal +{ + bool ModemResponseParserImpl::operator()(QcfgImsResult const &response, bool requestedState) const + { + using namespace at::response::qcfg_ims; + + if (!response) { + throw std::runtime_error("[VoLTE] modem responded with error to QCFG_IMS"); + } + + std::pair parsed; + if (!at::response::parseQCFG_IMS(response, parsed)) { + throw std::runtime_error("[VoLTE] unable to parse modem's response to QCFG_IMS"); + } + + auto const &ims = parsed.first; + bool stateMatchesRequest = (ims != IMSState::Disable) == requestedState; + LOG_INFO("[VoLTE] current IMS state: %s which %s expectation", + magic_enum::enum_name(ims).data(), + ((stateMatchesRequest) ? "matches" : "doesn't match")); + return stateMatchesRequest; + } +} // namespace cellular::internal diff --git a/module-services/service-cellular/src/VolteHandlerImpl.hpp b/module-services/service-cellular/src/VolteHandlerImpl.hpp new file mode 100644 index 0000000000000000000000000000000000000000..b826565e35f782819e72140dcbdbe3c8800a5222 --- /dev/null +++ b/module-services/service-cellular/src/VolteHandlerImpl.hpp @@ -0,0 +1,17 @@ +// Copyright (c) 2017-2022, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#pragma once + +#include "VolteHandler.hpp" +#include + +namespace cellular::internal +{ + using namespace cellular::service; + + struct ModemResponseParserImpl + { + bool operator()(QcfgImsResult const &, bool) const; + }; +} // namespace cellular::internal