// 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