From 20c7efdd71eeab2f740b063d40280bf0cb2983c4 Mon Sep 17 00:00:00 2001 From: Kuba Date: Thu, 28 Jan 2021 15:42:51 +0100 Subject: [PATCH] [EGD-4861] Call waiting response parser It allows to show proper GUI windows for call waiting MMI responses. --- module-cellular/at/response.cpp | 102 ++++++++++++++++ module-cellular/at/response.hpp | 32 +++++ module-cellular/test/unittest_response.cpp | 115 ++++++++++++++++++ .../service-appmgr/data/MmiActionsParams.cpp | 10 ++ .../service-appmgr/data/MmiActionsParams.hpp | 19 ++- .../CellularRequestHandler.cpp | 51 +++++++- .../CellularRequestHandler.hpp | 1 + .../service-cellular/RequestHandler.hpp | 2 + 8 files changed, 328 insertions(+), 4 deletions(-) diff --git a/module-cellular/at/response.cpp b/module-cellular/at/response.cpp index 6499c175fefa67897adb9997b1aa94ca09d76a87..8eb82024473ad200f9c253bdee230f225da66255 100644 --- a/module-cellular/at/response.cpp +++ b/module-cellular/at/response.cpp @@ -685,5 +685,107 @@ namespace at return message; } } // namespace clip + + namespace ccwa + { + auto parse(const std::vector &data, std::vector &parsed) noexcept -> bool + { + + auto constexpr toRemove = "+CCWA: "; + auto constexpr emptyString = ""; + auto constexpr tokenCount = 2; + parsed.clear(); + + for (auto el : data) { + + if (el.find("OK") != std::string::npos) { + return true; + } + + if (el.find(toRemove) == std::string::npos) { + parsed.clear(); + return false; + } + + utils::findAndReplaceAll(el, toRemove, emptyString); + auto tokens = utils::split(el, ","); + if (tokens.size() != tokenCount) { + parsed.clear(); + return false; + } + + for (auto &t : tokens) { + t = utils::trim(t); + } + int statusToken = 0; + int serviceClassToken = 0; + + if (!utils::toNumeric(tokens[0], statusToken) || !utils::toNumeric(tokens[1], serviceClassToken)) { + parsed.clear(); + return false; + } + auto status = static_cast(statusToken); + auto serviceClass = static_cast(serviceClassToken); + + if (magic_enum::enum_contains(status) && + magic_enum::enum_contains(serviceClass)) { + parsed.push_back(CcwaParsed(status, serviceClass)); + } + else { + parsed.clear(); + return false; + } + } + + return true; + } + + auto getStatus(const Status &status) noexcept + -> app::manager::actions::IMMICustomResultParams::MMIResultMessage + { + using namespace app::manager::actions; + + auto message = IMMICustomResultParams::MMIResultMessage::CommonNoMessage; + switch (status) { + case Status::Disable: + message = IMMICustomResultParams::MMIResultMessage::CallWaitingDeactivated; + break; + case Status::Enable: + message = IMMICustomResultParams::MMIResultMessage::CallWaitingActivated; + break; + } + return message; + } + + auto getClass(const ServiceClass &serviceClass) noexcept + -> app::manager::actions::IMMICustomResultParams::MMIResultMessage + { + using namespace app::manager::actions; + + auto message = IMMICustomResultParams::MMIResultMessage::CommonNoMessage; + switch (serviceClass) { + case ServiceClass::Voice: + message = IMMICustomResultParams::MMIResultMessage::CommonVoice; + break; + case ServiceClass::Data: + message = IMMICustomResultParams::MMIResultMessage::CommonData; + break; + case ServiceClass::Fax: + message = IMMICustomResultParams::MMIResultMessage::CommonFax; + break; + case ServiceClass::DataSync: + message = IMMICustomResultParams::MMIResultMessage::CommonSync; + break; + case ServiceClass::DataAsync: + message = IMMICustomResultParams::MMIResultMessage::CommonAsync; + break; + case ServiceClass::AllDisabled: + message = IMMICustomResultParams::MMIResultMessage::CommonAllDisabled; + break; + } + return message; + } + + } // namespace ccwa } // namespace response } // namespace at diff --git a/module-cellular/at/response.hpp b/module-cellular/at/response.hpp index 1830fdfe863e507c766cd9a897e8911b33620cb1..dde8a921b495b8a72df713d9944d6bca26331bac 100644 --- a/module-cellular/at/response.hpp +++ b/module-cellular/at/response.hpp @@ -404,5 +404,37 @@ namespace at auto getStatus(const Status &status) noexcept -> app::manager::actions::IMMICustomResultParams::MMIResultMessage; } // namespace clck + + namespace ccwa + { + enum class Status + { + Disable, + Enable + }; + enum class ServiceClass + { + Voice = 1, + Data = 2, + Fax = 4, + DataSync = 16, + DataAsync = 32, + AllDisabled = 255 + }; + + struct CcwaParsed + { + Status status; + ServiceClass serviceClass; + explicit CcwaParsed(const Status status, const ServiceClass serviceClass) + : status(status), serviceClass(serviceClass){}; + }; + + auto parse(const std::vector &data, std::vector &parsed) noexcept -> bool; + auto getStatus(const Status &status) noexcept + -> app::manager::actions::IMMICustomResultParams::MMIResultMessage; + auto getClass(const ServiceClass &serviceClass) noexcept + -> app::manager::actions::IMMICustomResultParams::MMIResultMessage; + } // namespace ccwa } // namespace response } // namespace at diff --git a/module-cellular/test/unittest_response.cpp b/module-cellular/test/unittest_response.cpp index 1dfffcf9a5673b248b448df530246aefb56b5fd6..52bfccd7118d0b7b8dc9c3991e4cc5a32fb74e52 100644 --- a/module-cellular/test/unittest_response.cpp +++ b/module-cellular/test/unittest_response.cpp @@ -434,3 +434,118 @@ TEST_CASE("Response CLCK") REQUIRE(ret.size() == 0); } } + +TEST_CASE("Response CCWA?") +{ + SECTION("OK CCWA? - all disabled") + { + + at::Result resp; + resp.code = at::Result::Code::OK; + std::vector ret; + resp.response.push_back("+CCWA: 0,255"); + resp.response.push_back("OK"); + + REQUIRE(resp.code == at::Result::Code::OK); + REQUIRE(at::response::ccwa::parse(resp.response, ret) == true); + REQUIRE(ret.size() == 1); + REQUIRE(ret[0].status == at::response::ccwa::Status::Disable); + REQUIRE(ret[0].serviceClass == at::response::ccwa::ServiceClass::AllDisabled); + } + + SECTION("OK CCWA? - voice, fax enabled") + { + + at::Result resp; + resp.code = at::Result::Code::OK; + std::vector ret; + resp.response.push_back("+CCWA: 1,1"); + resp.response.push_back("+CCWA: 1,4"); + resp.response.push_back("OK"); + + REQUIRE(resp.code == at::Result::Code::OK); + REQUIRE(at::response::ccwa::parse(resp.response, ret) == true); + REQUIRE(ret.size() == 2); + + REQUIRE(ret[0].status == at::response::ccwa::Status::Enable); + REQUIRE(ret[0].serviceClass == at::response::ccwa::ServiceClass::Voice); + + REQUIRE(ret[1].status == at::response::ccwa::Status::Enable); + REQUIRE(ret[1].serviceClass == at::response::ccwa::ServiceClass::Fax); + } + + SECTION("WRONG CCWA? - invalid status") + { + + at::Result resp; + resp.code = at::Result::Code::OK; + std::vector ret; + resp.response.push_back("+CCWA: 9,1"); + resp.response.push_back("+CCWA: 1,4"); + resp.response.push_back("OK"); + + REQUIRE(resp.code == at::Result::Code::OK); + REQUIRE(at::response::ccwa::parse(resp.response, ret) == false); + REQUIRE(ret.size() == 0); + } + + SECTION("WRONG CCWA? - invalid class") + { + + at::Result resp; + resp.code = at::Result::Code::OK; + std::vector ret; + resp.response.push_back("+CCWA: 1,1"); + resp.response.push_back("+CCWA: 1,66"); + resp.response.push_back("OK"); + + REQUIRE(resp.code == at::Result::Code::OK); + REQUIRE(at::response::ccwa::parse(resp.response, ret) == false); + REQUIRE(ret.size() == 0); + } + + SECTION("WRONG CCWA? - invalid token") + { + + at::Result resp; + resp.code = at::Result::Code::OK; + std::vector ret; + resp.response.push_back("+CCW: 1,1"); + resp.response.push_back("+CCWA: 1,66"); + resp.response.push_back("OK"); + + REQUIRE(resp.code == at::Result::Code::OK); + REQUIRE(at::response::ccwa::parse(resp.response, ret) == false); + REQUIRE(ret.size() == 0); + } + + SECTION("WRONG CCWA? - to little tokens") + { + + at::Result resp; + resp.code = at::Result::Code::OK; + std::vector ret; + resp.response.push_back("+CCWA: 1,1"); + resp.response.push_back("+CCWA: 1"); + resp.response.push_back("OK"); + + REQUIRE(resp.code == at::Result::Code::OK); + REQUIRE(at::response::ccwa::parse(resp.response, ret) == false); + REQUIRE(ret.size() == 0); + } + + SECTION("WRONG CCWA? - to many tokens") + { + + at::Result resp; + resp.code = at::Result::Code::OK; + std::vector ret; + resp.response.push_back("+CCWA: 1,1,9"); + resp.response.push_back("+CCWA: 1,4"); + resp.response.push_back("OK"); + + REQUIRE(resp.code == at::Result::Code::OK); + REQUIRE(at::response::ccwa::parse(resp.response, ret) == false); + REQUIRE(ret.size() == 0); + } +} diff --git a/module-services/service-appmgr/data/MmiActionsParams.cpp b/module-services/service-appmgr/data/MmiActionsParams.cpp index 193ea9dd3308e320e1bcea6fa58e2df4392d22f6..18968cf89c18522e7c01ee811962bd0e5af2ab1b 100644 --- a/module-services/service-appmgr/data/MmiActionsParams.cpp +++ b/module-services/service-appmgr/data/MmiActionsParams.cpp @@ -77,3 +77,13 @@ auto MMIImeiResult::getImei() const noexcept -> std::string { return imei; } + +void MMICallWaitingResult::addMessages(const std::pair &message) +{ + messages.push_back(message); +} + +auto MMICallWaitingResult::getMessages() const noexcept -> std::vector> +{ + return messages; +} diff --git a/module-services/service-appmgr/service-appmgr/data/MmiActionsParams.hpp b/module-services/service-appmgr/service-appmgr/data/MmiActionsParams.hpp index 5f5fa2c0a5024d9a82707c44cb8116a12b5c516f..4bae677c2ee975cc97a07b41d86981535e6cab0f 100644 --- a/module-services/service-appmgr/service-appmgr/data/MmiActionsParams.hpp +++ b/module-services/service-appmgr/service-appmgr/data/MmiActionsParams.hpp @@ -34,7 +34,9 @@ namespace app::manager::actions Clip, Imei, CallBarringNotification, - CallBarringData + CallBarringData, + CallWaitingNotification, + CallWaitingData }; enum class MMIResultMessage @@ -85,6 +87,9 @@ namespace app::manager::actions ClipProvisioned, ClipUnknown, + CallWaitingActivated, + CallWaitingDeactivated, + }; virtual auto getMessage() const -> std::vector = 0; @@ -204,4 +209,16 @@ namespace app::manager::actions private: std::string imei; }; + + class MMICallWaitingResult : public MMICustomResultParams + { + public: + explicit MMICallWaitingResult(const MMIType type) : MMICustomResultParams(type) + {} + void addMessages(const std::pair &message); + auto getMessages() const noexcept -> std::vector>; + + private: + std::vector> messages; + }; } // namespace app::manager::actions diff --git a/module-services/service-cellular/CellularRequestHandler.cpp b/module-services/service-cellular/CellularRequestHandler.cpp index 09312239df193a8c68b510ee99d6a7dcb6b2cf27..cfc82bec7f4b71cb977a496a3346bde0179b2469 100644 --- a/module-services/service-cellular/CellularRequestHandler.cpp +++ b/module-services/service-cellular/CellularRequestHandler.cpp @@ -15,15 +15,13 @@ #include "service-cellular/requests/PinChangeRequest.hpp" #include "service-cellular/requests/ImeiRequest.hpp" #include "service-cellular/requests/UssdRequest.hpp" -#include "service-cellular/service-cellular/requests/ClirRequest.hpp" #include "service-cellular/requests/CallForwardingRequest.hpp" #include "service-cellular/requests/CallBarringRequest.hpp" #include "service-cellular/requests/ClirRequest.hpp" #include "service-cellular/requests/ClipRequest.hpp" +#include "service-cellular/requests/CallWaitingRequest.hpp" #include -#include "service-cellular/service-cellular/requests/ClirRequest.hpp" -#include "service-cellular/service-cellular/requests/SupplementaryServicesRequest.hpp" #include @@ -281,6 +279,53 @@ void CellularRequestHandler::handle(cellular::ClipRequest &request, at::Result & request.setHandled(requestHandled); } +void CellularRequestHandler::handle(cellular::CallWaitingRequest &request, at::Result &result) +{ + using namespace app::manager::actions; + using namespace cellular; + using namespace at::response; + auto requestHandled = request.checkModemResponse(result); + + std::shared_ptr response; + if (requestHandled) { + auto procedureType = request.getProcedureType(); + if (procedureType == SupplementaryServicesRequest::ProcedureType::Activation) { + response = std::make_shared(IMMICustomResultParams::MMIType::CallWaitingNotification); + response->addMessage(IMMICustomResultParams::MMIResultMessage::CallWaitingActivated); + } + else if (procedureType == SupplementaryServicesRequest::ProcedureType::Deactivation) { + response = std::make_shared(IMMICustomResultParams::MMIType::CallWaitingNotification); + response->addMessage(IMMICustomResultParams::MMIResultMessage::CallWaitingDeactivated); + } + else if (procedureType == SupplementaryServicesRequest::ProcedureType::Interrogation) { + std::vector parsed; + if (ccwa::parse(result.response, parsed)) { + MMICallWaitingResult resp = MMICallWaitingResult(IMMICustomResultParams::MMIType::CallWaitingData); + for (auto el : parsed) { + resp.addMessages(std::make_pair(ccwa::getClass(el.serviceClass), ccwa::getStatus(el.status))); + } + response = std::make_shared(resp); + } + else { + response = + std::make_shared(IMMICustomResultParams::MMIType::CallWaitingNotification); + response->addMessage(IMMICustomResultParams::MMIResultMessage::CommonFailure); + } + } + else { + response = std::make_shared(IMMICustomResultParams::MMIType::CallWaitingNotification); + response->addMessage(IMMICustomResultParams::MMIResultMessage::CommonMMINotSupported); + } + } + else { + response = std::make_shared(IMMICustomResultParams::MMIType::CallWaitingNotification); + response->addMessage(IMMICustomResultParams::MMIResultMessage::CommonFailure); + } + auto msg = std::make_shared(MMIResultParams::MMIResult::Success, response); + sys::Bus::SendUnicast(msg, app::manager::ApplicationManager::ServiceName, &cellular); + request.setHandled(requestHandled); +} + void CellularRequestHandler::sendMmiResult(bool result) { using namespace app::manager::actions; diff --git a/module-services/service-cellular/service-cellular/CellularRequestHandler.hpp b/module-services/service-cellular/service-cellular/CellularRequestHandler.hpp index 5e84cb15fa97446cfdc2e4b1235b1a35d09cf1ca..eabb68dfd4c0acd78a4889cbfee1523322cf6da2 100644 --- a/module-services/service-cellular/service-cellular/CellularRequestHandler.hpp +++ b/module-services/service-cellular/service-cellular/CellularRequestHandler.hpp @@ -22,6 +22,7 @@ class CellularRequestHandler : public cellular::RequestHandler void handle(cellular::ClipRequest &request, at::Result &result) final; void handle(cellular::CallForwardingRequest &request, at::Result &result) final; void handle(cellular::CallBarringRequest &request, at::Result &result) final; + void handle(cellular::CallWaitingRequest &request, at::Result &result) final; private: ServiceCellular &cellular; diff --git a/module-services/service-cellular/service-cellular/RequestHandler.hpp b/module-services/service-cellular/service-cellular/RequestHandler.hpp index f4f630c5a05d312ed0dd63aea8895f512d3ef70b..2924987f1110a9930c60cb49b057bd2554fa9722 100644 --- a/module-services/service-cellular/service-cellular/RequestHandler.hpp +++ b/module-services/service-cellular/service-cellular/RequestHandler.hpp @@ -17,6 +17,7 @@ namespace cellular class ClirRequest; class CallForwardingRequest; class CallBarringRequest; + class CallWaitingRequest; class RequestHandler { @@ -31,5 +32,6 @@ namespace cellular virtual void handle(ClipRequest &request, at::Result &result) = 0; virtual void handle(CallForwardingRequest &request, at::Result &result) = 0; virtual void handle(CallBarringRequest &request, at::Result &result) = 0; + virtual void handle(CallWaitingRequest &request, at::Result &result) = 0; }; } // namespace cellular