[EGD-4414] Add support for call barring MMI (#1057) * cover MMI requests with following codes: 33,331,332,35,351,330,333,353 * moved logic of building command string to base class
11 files changed, 299 insertions(+), 72 deletions(-) M changelog.md M module-services/service-cellular/CMakeLists.txt A module-services/service-cellular/requests/CallBarringRequest.cpp M module-services/service-cellular/requests/CallForwardingRequest.cpp M module-services/service-cellular/requests/CallWaitingRequest.cpp M module-services/service-cellular/requests/PasswordRegistrationRequest.cpp M module-services/service-cellular/requests/Request.cpp M module-services/service-cellular/requests/SupplementaryServicesRequest.cpp A module-services/service-cellular/service-cellular/requests/CallBarringRequest.hpp M module-services/service-cellular/service-cellular/requests/Request.hpp M module-services/service-cellular/tests/unittest_mmi.cpp
M changelog.md => changelog.md +2 -2
@@ 4,8 4,8 @@ ### Added * `[gui][desktop]` Added SIM PIN basic flow implementation. * `[cellular]` Added CLIR, CLIP, COLP, and call-waiting MMI support. * `[gui][desktop]` Added SIM PIN basic flow implementation * `[cellular]` Added CLIR, CLIP, COLP, call waiting, call barring MMIs support ### Fixed
M module-services/service-cellular/CMakeLists.txt => module-services/service-cellular/CMakeLists.txt +1 -1
@@ 22,7 22,7 @@ set(SOURCES requests/ClirRequest.cpp requests/ColpRequest.cpp requests/CallWaitingRequest.cpp ) requests/CallBarringRequest.cpp) add_library(${PROJECT_NAME} STATIC ${SOURCES})
A module-services/service-cellular/requests/CallBarringRequest.cpp => module-services/service-cellular/requests/CallBarringRequest.cpp +76 -0
@@ 0,0 1,76 @@ // Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #include <string> #include <at/Commands.hpp> #include <Utils.hpp> #include "service-cellular/requests/CallBarringRequest.hpp" namespace cellular { std::unique_ptr<SupplementaryServicesRequest> CallBarringRequest::create(const std::string &serviceCode, const std::string &data, GroupMatch matchGroups) { for (auto &it : barringServiceToFacility) { if (it.first == serviceCode) { return std::make_unique<CallBarringRequest>(std::string(it.second), data, matchGroups); } } return nullptr; } auto CallBarringRequest::command() -> std::string { std::vector<commandBuilderFunc> commandParts = { [this]() { return getCommandFacility(); }, [this]() { return getCommandMode(); }, [this]() { return getCommandPassword(); }, [this]() { return getCommandClass(); }, }; return buildCommand(at::AT::CLCK, commandParts); } auto CallBarringRequest::getCommandFacility() const -> std::string { return "\"" + facility + "\""; } auto CallBarringRequest::getCommandMode() const -> std::string { return utils::to_string(magic_enum::enum_integer(procedureType)); } auto CallBarringRequest::getCommandPassword() const -> std::string { return password.empty() ? std::string() : "\"" + password + "\""; } auto CallBarringRequest::getCommandClass() const -> std::string { if (basicServiceGroup.empty()) { return std::string(); } return getCommandInformationClass(basicServiceGroup).value_or(std::string()); } void CallBarringRequest::handle(RequestHandler &h, at::Result &result) { h.handle(*this, result); } auto CallBarringRequest::isValid() const noexcept -> bool { if (!getCommandInformationClass(basicServiceGroup).has_value()) { return false; } return procedureType != ProcedureType::Registration && procedureType != ProcedureType::Erasure; } } // namespace cellular
M module-services/service-cellular/requests/CallForwardingRequest.cpp => module-services/service-cellular/requests/CallForwardingRequest.cpp +5 -16
@@ 37,24 37,13 @@ namespace cellular auto CallForwardingRequest::command() -> std::string { std::array<std::function<std::string()>, 3> commandParts = { [this]() { return this->getCommandReason(); }, [this]() { return this->getCommandMode(); }, [this]() { return this->getCommandNumber(); }, std::vector<commandBuilderFunc> commandParts = { [this]() { return getCommandReason(); }, [this]() { return getCommandMode(); }, [this]() { return getCommandNumber(); }, }; std::string cmd(at::factory(at::AT::CCFC)); bool formatFirst = true; for (auto &cmdPart : commandParts) { auto partStr = cmdPart(); if (partStr.empty()) { continue; } cmd.append(formatFirst ? partStr : "," + partStr); formatFirst = false; } return cmd; return buildCommand(at::AT::CCFC, commandParts); } auto CallForwardingRequest::getCommandReason() const -> std::string
M module-services/service-cellular/requests/CallWaitingRequest.cpp => module-services/service-cellular/requests/CallWaitingRequest.cpp +5 -20
@@ 25,28 25,13 @@ namespace cellular auto CallWaitingRequest::command() -> std::string { if (!isValid()) { return std::string(); } std::array<std::function<std::string()>, 3> commandParts = { [this]() { return this->getCommandPresentation(); }, [this]() { return this->getCommandMode(); }, [this]() { return this->getCommandClass(); }, std::vector<commandBuilderFunc> commandParts = { [this]() { return getCommandPresentation(); }, [this]() { return getCommandMode(); }, [this]() { return getCommandClass(); }, }; std::string cmd(at::factory(at::AT::CCWA)); bool formatFirst = true; for (auto &cmdPart : commandParts) { auto partStr = cmdPart(); if (partStr.empty()) { continue; } cmd.append(formatFirst ? partStr : "," + partStr); formatFirst = false; } return cmd; return buildCommand(at::AT::CCWA, commandParts); } auto CallWaitingRequest::getCommandPresentation() const noexcept -> std::string
M module-services/service-cellular/requests/PasswordRegistrationRequest.cpp => module-services/service-cellular/requests/PasswordRegistrationRequest.cpp +14 -33
@@ 7,22 7,7 @@ #include <Utils.hpp> #include "service-cellular/requests/PasswordRegistrationRequest.hpp" namespace { // according to EC25&EC21_AT_Commands_Manual_V1.3 const std::map<std::string, std::string> barringServiceToFacilityMap = {{ {"33", "AO"}, // BAOC (Bar All Outgoing Calls) {"331", "OI"}, // BOIC (Bar Outgoing International Calls) {"332", "OX"}, // BOIC-exHC (Bar Outgoing International Calls except to home country) {"35", "AI"}, // BAIC (Bar All Incoming Calls) {"351", "IR"}, // BIC-Roam (Bar Incoming Calls when Roaming outside the home country) {"330", "AB"}, // All barring services {"333", "AG"}, // All outgoing barring services {"353", "AC"}, // All incoming barring services {"", "AB"}, // All incoming barring services (According to 3GPP TS 22.030 V16.0.0 ) }}; } // namespace #include "service-cellular/requests/CallBarringRequest.hpp" // for barringServiceToFacility map namespace { @@ 40,29 25,25 @@ namespace cellular auto PasswordRegistrationRequest::command() -> std::string { std::array<std::function<std::string()>, 3> commandParts = { [this]() { return this->getCommandFacility(); }, [this]() { return "," + this->getOldPassword(); }, [this]() { return "," + this->getNewPassword(); }, std::vector<commandBuilderFunc> commandParts = { [this]() { return getCommandFacility(); }, [this]() { return getOldPassword(); }, [this]() { return getNewPassword(); }, }; if (!isValid()) { return std::string(); } std::string cmd(at::factory(at::AT::CPWD)); for (auto &cmdPart : commandParts) { cmd.append(cmdPart()); } return cmd; return buildCommand(at::AT::CPWD, commandParts); } auto PasswordRegistrationRequest::getCommandFacility() const noexcept -> std::string { if (auto it = barringServiceToFacilityMap.find(requestBarringService); it != barringServiceToFacilityMap.end()) { return "\"" + it->second + "\""; if (requestBarringService.empty()) { return "\"" + std::string(CallBarringRequest::allBarringServicesFacilityString) + "\""; //(According to 3GPP TS 22.030 V16.0.0 ) } for (auto &it : CallBarringRequest::barringServiceToFacility) { if (it.first == requestBarringService) { return "\"" + std::string(it.second) + "\""; } } return std::string(); }
M module-services/service-cellular/requests/Request.cpp => module-services/service-cellular/requests/Request.cpp +23 -0
@@ 15,16 15,39 @@ namespace cellular { isRequestHandled = handled; } bool Request::isHandled() const noexcept { return isRequestHandled; } bool Request::checkModemResponse(const at::Result &result) { return result.code == at::Result::Code::OK; } bool Request::isValid() const noexcept { return true; } std::string Request::buildCommand(at::AT atCommand, const std::vector<commandBuilderFunc> &builderFunctions) const { if (!isValid()) { return std::string(); } std::string cmd(at::factory(atCommand)); bool formatFirst = true; for (auto &cmdPart : builderFunctions) { auto partStr = cmdPart(); if (partStr.empty()) { continue; } cmd.append(formatFirst ? partStr : "," + partStr); formatFirst = false; } return cmd; } }; // namespace cellular
M module-services/service-cellular/requests/SupplementaryServicesRequest.cpp => module-services/service-cellular/requests/SupplementaryServicesRequest.cpp +2 -0
@@ 13,6 13,7 @@ #include "service-cellular/requests/ClirRequest.hpp" #include "service-cellular/requests/ColpRequest.hpp" #include "service-cellular/requests/CallWaitingRequest.hpp" #include "service-cellular/requests/CallBarringRequest.hpp" namespace { @@ 55,6 56,7 @@ namespace cellular auto factoryList = { CallForwardingRequest::create, CallWaitingRequest::create, CallBarringRequest::create, ClipRequest::create, ClirRequest::create, ColpRequest::create,
A module-services/service-cellular/service-cellular/requests/CallBarringRequest.hpp => module-services/service-cellular/service-cellular/requests/CallBarringRequest.hpp +49 -0
@@ 0,0 1,49 @@ // Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. // For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md #pragma once #include "SupplementaryServicesRequest.hpp" namespace cellular { class CallBarringRequest : public SupplementaryServicesRequest { public: // according to EC25&EC21_AT_Commands_Manual_V1.3 static constexpr auto allBarringServicesFacilityString = "AB"; static constexpr std::array<std::pair<std::string_view, std::string_view>, 8> barringServiceToFacility = {{ {"33", "AO"}, // BAOC (Bar All Outgoing Calls) {"331", "OI"}, // BOIC (Bar Outgoing International Calls) {"332", "OX"}, // BOIC-exHC (Bar Outgoing International Calls except to home country) {"35", "AI"}, // BAIC (Bar All Incoming Calls) {"351", "IR"}, // BIC-Roam (Bar Incoming Calls when Roaming outside the home country) {"330", allBarringServicesFacilityString}, // All barring services {"333", "AG"}, // All outgoing barring services {"353", "AC"}, // All incoming barring services }}; CallBarringRequest(const std::string &facility, const std::string &data, GroupMatch matchGroups) : SupplementaryServicesRequest(data, matchGroups), facility(facility) {} static std::unique_ptr<SupplementaryServicesRequest> create(const std::string &serviceCode, const std::string &data, GroupMatch matchGroups); auto command() -> std::string final; void handle(RequestHandler &h, at::Result &result) final; auto isValid() const noexcept -> bool; private: std::string facility; std::string &password = supplementaryInfoA; std::string &basicServiceGroup = supplementaryInfoB; // command decomposition according to EC25&EC21_AT_Commands_Manual_V1.3 auto getCommandFacility() const -> std::string; auto getCommandMode() const -> std::string; auto getCommandPassword() const -> std::string; auto getCommandClass() const -> std::string; }; }; // namespace cellular
M module-services/service-cellular/service-cellular/requests/Request.hpp => module-services/service-cellular/service-cellular/requests/Request.hpp +10 -0
@@ 4,6 4,7 @@ #pragma once #include <at/Result.hpp> #include <at/Commands.hpp> #include "service-cellular/RequestHandler.hpp" namespace cellular @@ 34,6 35,15 @@ namespace cellular bool isValid() const noexcept override; protected: using commandBuilderFunc = std::function<std::string()>; /** * Helper command for building output command * @param atCommand * @param builderFunctions functions that build parts of the output command in order of execution * @return formatted command or empty string if input is invalid */ auto buildCommand(at::AT atCommand, const std::vector<commandBuilderFunc> &builderFunctions) const -> std::string; bool isRequestHandled = false; std::string request; };
M module-services/service-cellular/tests/unittest_mmi.cpp => module-services/service-cellular/tests/unittest_mmi.cpp +112 -0
@@ 7,6 7,7 @@ #include <service-cellular/RequestFactory.hpp> #include <service-cellular/requests/CallForwardingRequest.hpp> #include <service-cellular/requests/CallWaitingRequest.hpp> #include <service-cellular/requests/CallBarringRequest.hpp> #include <service-cellular/requests/PasswordRegistrationRequest.hpp> #include <service-cellular/requests/PinChangeRequest.hpp> #include <service-cellular/requests/ImeiRequest.hpp> @@ 71,6 72,117 @@ TEST_CASE("MMI requests") // bad procedure type {R"(**76#)", std::string(), typeid(ColpRequest), false}, /// CallBarringRequest // BAOC (Bar All Outgoing Calls) {R"(*33#)", R"(AT+CLCK="AO",1)", typeid(CallBarringRequest)}, // lock {R"(*33*1111#)", R"(AT+CLCK="AO",1,"1111")", typeid(CallBarringRequest)}, // lock with pass {R"(*33*1111*10#)", R"(AT+CLCK="AO",1,"1111",13)", typeid(CallBarringRequest)}, // lock with pass and BS {R"(#33#)", R"(AT+CLCK="AO",0)", typeid(CallBarringRequest)}, // unlock {R"(#33*1111#)", R"(AT+CLCK="AO",0,"1111")", typeid(CallBarringRequest)}, // unlock with pass {R"(#33*1111*11#)", R"(AT+CLCK="AO",0,"1111",1)", typeid(CallBarringRequest)}, // unlock with pass and BS {R"(*#33#)", R"(AT+CLCK="AO",2)", typeid(CallBarringRequest)}, // query {R"(*#33*1111#)", R"(AT+CLCK="AO",2,"1111")", typeid(CallBarringRequest)}, // query with pass {R"(*#33*1111*12#)", R"(AT+CLCK="AO",2,"1111",12)", typeid(CallBarringRequest)}, // query with pass and BS {R"(**33#)", std::string(), typeid(CallBarringRequest), false}, // bad procedure - register {R"(##33#)", std::string(), typeid(CallBarringRequest), false}, // bad procedure - erasure {R"(*#33*1111*17#)", std::string(), typeid(CallBarringRequest), false}, // unsupported BS - Voice Group Call Service {R"(*#33*1111*18#)", std::string(), typeid(CallBarringRequest), false}, // unsupported BS - Voice Broadcast Service {R"(*#33*1111*99#)", std::string(), typeid(CallBarringRequest), false}, // unsupported BS - All GPRS bearer services {R"(*#33*1111*45#)", std::string(), typeid(CallBarringRequest), false}, // unsupported BS - random /// BOIC (Bar Outgoing International Calls) {R"(*331#)", R"(AT+CLCK="OI",1)", typeid(CallBarringRequest)}, // lock {R"(*331*2222#)", R"(AT+CLCK="OI",1,"2222")", typeid(CallBarringRequest)}, // lock with pass {R"(*331*2222*13#)", R"(AT+CLCK="OI",1,"2222",4)", typeid(CallBarringRequest)}, // lock with pass and BS {R"(#331#)", R"(AT+CLCK="OI",0)", typeid(CallBarringRequest)}, // unlock {R"(#331*2222#)", R"(AT+CLCK="OI",0,"2222")", typeid(CallBarringRequest)}, // unlock with pass {R"(#331*2222*16#)", R"(AT+CLCK="OI",0,"2222",8)", typeid(CallBarringRequest)}, // unlock with pass and BS {R"(*#331#)", R"(AT+CLCK="OI",2)", typeid(CallBarringRequest)}, // query {R"(*#331*2222#)", R"(AT+CLCK="OI",2,"2222")", typeid(CallBarringRequest)}, // query with pass {R"(*#331*2222*19#)", R"(AT+CLCK="OI",2,"2222",5)", typeid(CallBarringRequest)}, // query with pass and BS {R"(**331#)", std::string(), typeid(CallBarringRequest), false}, // bad procedure - register {R"(##331#)", std::string(), typeid(CallBarringRequest), false}, // bad procedure - erasure /// BOIC-exHC (Bar Outgoing International Calls except to home country) {R"(*332#)", R"(AT+CLCK="OX",1)", typeid(CallBarringRequest)}, // lock {R"(*332*3333#)", R"(AT+CLCK="OX",1,"3333")", typeid(CallBarringRequest)}, // lock {R"(*332*2222*20#)", R"(AT+CLCK="OX",1,"2222",50)", typeid(CallBarringRequest)}, // lock with pass {R"(#332#)", R"(AT+CLCK="OX",0)", typeid(CallBarringRequest)}, // unlock with pass and BS {R"(#332*3333#)", R"(AT+CLCK="OX",0,"3333")", typeid(CallBarringRequest)}, // unlock {R"(#332*2222*21#)", R"(AT+CLCK="OX",0,"2222",32)", typeid(CallBarringRequest)}, // unlock with pass {R"(*#332#)", R"(AT+CLCK="OX",2)", typeid(CallBarringRequest)}, // query with pass and BS {R"(*#332*3333#)", R"(AT+CLCK="OX",2,"3333")", typeid(CallBarringRequest)}, // query with pass {R"(*#332*2222*22#)", R"(AT+CLCK="OX",2,"2222",16)", typeid(CallBarringRequest)}, // query with pass and BS {R"(**332#)", std::string(), typeid(CallBarringRequest), false}, // bad procedure - register {R"(##332#)", std::string(), typeid(CallBarringRequest), false}, // bad procedure - erasure /// BAIC (Bar All Incoming Calls) {R"(*35#)", R"(AT+CLCK="AI",1)", typeid(CallBarringRequest)}, // lock {R"(*35*1234#)", R"(AT+CLCK="AI",1,"1234")", typeid(CallBarringRequest)}, // lock with pass {R"(*35*2222*24#)", R"(AT+CLCK="AI",1,"2222",16)", typeid(CallBarringRequest)}, // lock with pass and BS {R"(#35#)", R"(AT+CLCK="AI",0)", typeid(CallBarringRequest)}, // unlock {R"(#35*1234#)", R"(AT+CLCK="AI",0,"1234")", typeid(CallBarringRequest)}, // unlock with pass {R"(#35*2222*25#)", R"(AT+CLCK="AI",0,"2222",32)", typeid(CallBarringRequest)}, // unlock with pass and BS {R"(*#35#)", R"(AT+CLCK="AI",2)", typeid(CallBarringRequest)}, // query {R"(*#35*1234#)", R"(AT+CLCK="AI",2,"1234")", typeid(CallBarringRequest)}, // query with pass {R"(*#35*2222*26#)", R"(AT+CLCK="AI",2,"2222",17)", typeid(CallBarringRequest)}, // query with pass and BS {R"(**35#)", std::string(), typeid(CallBarringRequest), false}, // bad procedure - register {R"(##35#)", std::string(), typeid(CallBarringRequest), false}, // bad procedure - erasure /// BIC-Roam (Bar Incoming Calls when Roaming outside the home country) {R"(*351#)", R"(AT+CLCK="IR",1)", typeid(CallBarringRequest)}, // lock {R"(*351*1234#)", R"(AT+CLCK="IR",1,"1234")", typeid(CallBarringRequest)}, // lock with pass {R"(*351*2222*10#)", R"(AT+CLCK="IR",1,"2222",13)", typeid(CallBarringRequest)}, // lock with pass and BS {R"(#351#)", R"(AT+CLCK="IR",0)", typeid(CallBarringRequest)}, // unlock {R"(#351*1234#)", R"(AT+CLCK="IR",0,"1234")", typeid(CallBarringRequest)}, // unlock with pass {R"(#351*2222*11#)", R"(AT+CLCK="IR",0,"2222",1)", typeid(CallBarringRequest)}, // unlock with pass and BS {R"(*#351#)", R"(AT+CLCK="IR",2)", typeid(CallBarringRequest)}, // query {R"(*#351*1234#)", R"(AT+CLCK="IR",2,"1234")", typeid(CallBarringRequest)}, // query with pass {R"(*#351*2222*12#)", R"(AT+CLCK="IR",2,"2222",12)", typeid(CallBarringRequest)}, // query with pass and BS {R"(**351#)", std::string(), typeid(CallBarringRequest), false}, // bad procedure - register {R"(##351#)", std::string(), typeid(CallBarringRequest), false}, // bad procedure - erasure /// All barring services {R"(*330#)", R"(AT+CLCK="AB",1)", typeid(CallBarringRequest)}, // lock {R"(*330*1234#)", R"(AT+CLCK="AB",1,"1234")", typeid(CallBarringRequest)}, // lock with pass {R"(*330*2222*13#)", R"(AT+CLCK="AB",1,"2222",4)", typeid(CallBarringRequest)}, // lock with pass and BS {R"(#330#)", R"(AT+CLCK="AB",0)", typeid(CallBarringRequest)}, // unlock {R"(#330*1234#)", R"(AT+CLCK="AB",0,"1234")", typeid(CallBarringRequest)}, // unlock with pass {R"(#330*2222*16#)", R"(AT+CLCK="AB",0,"2222",8)", typeid(CallBarringRequest)}, // unlock with pass and BS {R"(*#330#)", R"(AT+CLCK="AB",2)", typeid(CallBarringRequest)}, // query {R"(*#330*1234#)", R"(AT+CLCK="AB",2,"1234")", typeid(CallBarringRequest)}, // query with pass {R"(*#330*2222*19#)", R"(AT+CLCK="AB",2,"2222",5)", typeid(CallBarringRequest)}, // query with pass and BS {R"(**330#)", std::string(), typeid(CallBarringRequest), false}, // bad procedure - register {R"(##330#)", std::string(), typeid(CallBarringRequest), false}, // bad procedure - erasure /// All outgoing barring services {R"(*333#)", R"(AT+CLCK="AG",1)", typeid(CallBarringRequest)}, // lock {R"(*333*1234#)", R"(AT+CLCK="AG",1,"1234")", typeid(CallBarringRequest)}, // lock with pass {R"(*333*2222*20#)", R"(AT+CLCK="AG",1,"2222",50)", typeid(CallBarringRequest)}, // lock with pass and BS {R"(#333#)", R"(AT+CLCK="AG",0)", typeid(CallBarringRequest)}, // unlock {R"(#333*1234#)", R"(AT+CLCK="AG",0,"1234")", typeid(CallBarringRequest)}, // unlock with pass {R"(#333*2222*21#)", R"(AT+CLCK="AG",0,"2222",32)", typeid(CallBarringRequest)}, // unlock with pass and BS {R"(*#333#)", R"(AT+CLCK="AG",2)", typeid(CallBarringRequest)}, // query {R"(*#333*1234#)", R"(AT+CLCK="AG",2,"1234")", typeid(CallBarringRequest)}, // query with pass {R"(*#333*2222*22#)", R"(AT+CLCK="AG",2,"2222",16)", typeid(CallBarringRequest)}, // query with pass and BS {R"(**333#)", std::string(), typeid(CallBarringRequest), false}, // bad procedure - register {R"(##333#)", std::string(), typeid(CallBarringRequest), false}, // bad procedure - erasure /// All incoming barring services {R"(*353#)", R"(AT+CLCK="AC",1)", typeid(CallBarringRequest)}, // lock {R"(*353*1234#)", R"(AT+CLCK="AC",1,"1234")", typeid(CallBarringRequest)}, // lock with pass {R"(*353*2222*24#)", R"(AT+CLCK="AC",1,"2222",16)", typeid(CallBarringRequest)}, // lock with pass and BS {R"(#353#)", R"(AT+CLCK="AC",0)", typeid(CallBarringRequest)}, // unlock {R"(#353*1234#)", R"(AT+CLCK="AC",0,"1234")", typeid(CallBarringRequest)}, // unlock with pass {R"(#353*2222*25#)", R"(AT+CLCK="AC",0,"2222",32)", typeid(CallBarringRequest)}, // unlock with pass and BS {R"(*#353#)", R"(AT+CLCK="AC",2)", typeid(CallBarringRequest)}, // query {R"(*#353*1234#)", R"(AT+CLCK="AC",2,"1234")", typeid(CallBarringRequest)}, // query with pass {R"(*#353*2222*10#)", R"(AT+CLCK="AC",2,"2222",13)", typeid(CallBarringRequest)}, // query with pass and BS {R"(**353#)", std::string(), typeid(CallBarringRequest), false}, // bad procedure - register {R"(##353#)", std::string(), typeid(CallBarringRequest), false}, // bad procedure - erasure /// CallWaitingRequest // enable all {R"(*43#)", R"(AT+CCWA=1,1)", typeid(CallWaitingRequest)},