~aleteoryx/muditaos

0f2503e76d95868bd3b4df91cd3b68b054c8e87f — Kuba 5 years ago 844903a
[EGD-4859] Add call forwarding parser

It allows to show proper GUI windows for call forwarding MMI responses.
M module-cellular/at/ErrorCode.hpp => module-cellular/at/ErrorCode.hpp +1 -1
@@ 54,6 54,7 @@ namespace at
        ServiceProvPersPUKRequired    = 45,
        CorporatePersPINRequired      = 46,
        CorporatePersPUKRequired      = 47,
        PhoneBusy                     = 258,
        AudioUnknownError             = 901,
        AudioInvalidParameters        = 902,
        AudioOperationNotSupported    = 903,


@@ 69,7 70,6 @@ namespace at
     */
    enum class NetworkErrorCode : uint32_t
    {

        MEFailure                   = 300,
        SMS_MEReserved              = 301,
        OperationNotAllowed         = 302,

M module-cellular/at/response.cpp => module-cellular/at/response.cpp +96 -0
@@ 424,5 424,101 @@ namespace at
                return message;
            }
        } // namespace clir

        namespace ccfc
        {

            auto parse(std::vector<std::string> response, std::vector<ParsedCcfc> &parsed) -> bool
            {

                auto constexpr toRemove    = "+CCFC: ";
                auto constexpr emptyString = "";
                auto constexpr quote       = "\"";

                parsed.clear();

                for (auto el : response) {

                    if (el.find("OK") != std::string::npos) {
                        return true;
                    }

                    utils::findAndReplaceAll(el, toRemove, emptyString);
                    auto tokens = utils::split(el, ",");

                    if (tokens.size() == serviceDisabledTokenCount) {
                        parsed.push_back(ParsedCcfc(ConnectionClass::None, ForwardingStatus::NotActive, ""));
                    }
                    else if (tokens.size() > serviceDisabledTokenCount) {
                        int statusToken          = 0;
                        int connectionClassToken = 0;

                        if (!utils::toNumeric(tokens[Tokens::Status], statusToken) ||
                            !utils::toNumeric(tokens[Tokens::Class], connectionClassToken)) {
                            return false;
                        }
                        auto status          = static_cast<ForwardingStatus>(statusToken);
                        auto connectionClass = static_cast<ConnectionClass>(connectionClassToken);

                        if (magic_enum::enum_contains<ForwardingStatus>(status) &&
                            magic_enum::enum_contains<ConnectionClass>(connectionClass)) {
                            auto number = tokens[Tokens::Number];
                            utils::findAndReplaceAll(number, quote, emptyString);
                            utils::trim(number);
                            parsed.push_back(ParsedCcfc(connectionClass, status, number));
                        }
                        else {
                            return false;
                        }
                    }
                }
                return true;
            }

            auto getNumbers(std::vector<ParsedCcfc> &parsed) -> CcfcNumbers
            {
                CcfcNumbers numbers;

                for (auto el : parsed) {
                    std::string number = "";
                    if (el.status == ForwardingStatus::Active) {
                        number = el.number;
                    }
                    switch (el.connectionClass) {
                    case ConnectionClass::None:
                        break;
                    case ConnectionClass::Voice:
                        numbers.voice = number;
                        break;
                    case ConnectionClass::Data:
                        break;
                    case ConnectionClass::Fax:
                        numbers.fax = number;
                        break;
                    case ConnectionClass::AllTelephonyExceptSMS:
                        break;
                    case ConnectionClass::ShortMessgeService:
                        break;
                    case ConnectionClass::DataAsync:
                        numbers.async = number;
                        break;
                    case ConnectionClass::DataSync:
                        numbers.sync = number;
                        break;
                    }
                }
                return numbers;
            }

            auto isAnyActive(std::vector<ParsedCcfc> &parsed) -> bool
            {
                for (auto el : parsed) {
                    if (el.status == ForwardingStatus::Active) {
                        return true;
                    }
                }
                return false;
            }
        } // namespace ccfc
    }     // namespace response
} // namespace at

M module-cellular/at/response.hpp => module-cellular/at/response.hpp +56 -0
@@ 278,5 278,61 @@ namespace at
            auto getStatus(const ServiceStatus &status)
                -> app::manager::actions::IMMICustomResultParams::MMIResultMessage;
        } // namespace clir

        namespace ccfc
        {

            enum class ConnectionClass
            {
                None                  = 0,
                Voice                 = 1,
                Data                  = 2,
                Fax                   = 4,
                AllTelephonyExceptSMS = 7,
                ShortMessgeService    = 8,
                DataAsync             = 16,
                DataSync              = 32
            };

            enum class ForwardingStatus
            {
                NotActive,
                Active
            };

            struct ParsedCcfc
            {
                ConnectionClass connectionClass;
                ForwardingStatus status;
                std::string number;

                explicit ParsedCcfc(ConnectionClass connectionClass, ForwardingStatus status, const std::string &number)
                    : connectionClass(connectionClass), status(status), number(number)
                {}
            };

            enum Tokens
            {
                Status,
                Class,
                Number,
                Type
            };

            struct CcfcNumbers
            {
                std::string voice;
                std::string fax;
                std::string sync;
                std::string async;
            };

            auto constexpr serviceDisabledTokenCount = 2;
            auto constexpr serviceEnabledTokenCount  = 4;

            auto parse(std::vector<std::string> response, std::vector<ParsedCcfc> &parsed) -> bool;
            auto getNumbers(std::vector<ParsedCcfc> &parsed) -> CcfcNumbers;
            auto isAnyActive(std::vector<ParsedCcfc> &parsed) -> bool;
        } // namespace ccfc
    }     // namespace response
} // namespace at

M module-services/service-appmgr/data/MmiActionsParams.cpp => module-services/service-appmgr/data/MmiActionsParams.cpp +1 -1
@@ 38,7 38,7 @@ auto MMICallForwardingResult::getData() const -> std::tuple<std::string, std::st
void MMICallForwardingResult::accept(Visitor &v, std::string &displayMessage)
{
    v.visit(*this, displayMessage);
};
}

MMIParams::MMIParams(std::string mmiData) : mmiData{std::move(mmiData)}
{}

M module-services/service-appmgr/service-appmgr/data/MmiActionsParams.hpp => module-services/service-appmgr/service-appmgr/data/MmiActionsParams.hpp +5 -1
@@ 38,6 38,7 @@ namespace app::manager::actions
            NoneSpecifiedSuccess,
            NoneSpecifiedFailed,
            CommonFailure,
            CommonMMINotSupported,
            CommonNoMessage,

            ClirAccordingToSubscription,


@@ 49,6 50,7 @@ namespace app::manager::actions
            ClirTemporaryRestricted,
            ClirTemporaryAllowed,

            // Call forwarding
            RegistrationSuccessful,
            RegistrationFailed,
            ErasureSuccessful,


@@ 56,7 58,9 @@ namespace app::manager::actions
            DisablingSuccessful,
            DisablingFailed,
            EnablingSuccessful,
            EnablingFailed
            EnablingFailed,
            CallForwardingDisabled

        };

        virtual auto getMessage() const -> std::vector<MMIResultMessage> = 0;

M module-services/service-cellular/CellularRequestHandler.cpp => module-services/service-cellular/CellularRequestHandler.cpp +68 -2
@@ 15,10 15,10 @@
#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-appmgr/model/ApplicationManager.hpp>
#include "service-cellular/service-cellular/requests/ClirRequest.hpp"
#include "service-cellular/service-cellular/requests/SupplementaryServicesRequest.hpp"

#include <module-cellular/at/response.hpp>



@@ 118,6 118,72 @@ void CellularRequestHandler::handle(ClirRequest &request, at::Result &result)
    sys::Bus::SendUnicast(msg, app::manager::ApplicationManager::ServiceName, &cellular);
    request.setHandled(requestHandled);
}

void CellularRequestHandler::handle(CallForwardingRequest &request, at::Result &result)
{
    using namespace app::manager::actions;
    using namespace cellular;
    using namespace at::response;

    auto requestHandled = request.checkModemResponse(result);
    std::shared_ptr<MMICustomResultParams> response;
    if (requestHandled) {
        auto procedureType = request.getProcedureType();
        if (procedureType == SupplementaryServicesRequest::ProcedureType::Registration) {
            response =
                std::make_shared<MMICallForwardingResult>(IMMICustomResultParams::MMIType::CallForwardingNotification);
            response->addMessage(IMMICustomResultParams::MMIResultMessage::RegistrationSuccessful);
        }
        else if (procedureType == SupplementaryServicesRequest::ProcedureType::Deactivation) {
            response =
                std::make_shared<MMICallForwardingResult>(IMMICustomResultParams::MMIType::CallForwardingNotification);
            response->addMessage(IMMICustomResultParams::MMIResultMessage::DisablingSuccessful);
        }
        else if (procedureType == SupplementaryServicesRequest::ProcedureType::Erasure) {
            response =
                std::make_shared<MMICallForwardingResult>(IMMICustomResultParams::MMIType::CallForwardingNotification);
            response->addMessage(IMMICustomResultParams::MMIResultMessage::ErasureSuccessful);
        }
        else if (procedureType == SupplementaryServicesRequest::ProcedureType::Interrogation) {
            std::vector<ccfc::ParsedCcfc> parsed;
            if (at::response::ccfc::parse(result.response, parsed)) {
                if (ccfc::isAnyActive(parsed)) {
                    auto numbers = ccfc::getNumbers(parsed);
                    response =
                        std::make_shared<MMICallForwardingResult>(IMMICustomResultParams::MMIType::CallForwardingData,
                                                                  numbers.voice,
                                                                  numbers.fax,
                                                                  numbers.sync,
                                                                  numbers.async);
                }
                else {
                    response = std::make_shared<MMICallForwardingResult>(
                        IMMICustomResultParams::MMIType::CallForwardingNotification);
                    response->addMessage(IMMICustomResultParams::MMIResultMessage::CallForwardingDisabled);
                }
            }
        }
    }

    else {
        if (result.code == at::Result::Code::ERROR &&
            std::get<at::EquipmentErrorCode>(result.errorCode) == at::EquipmentErrorCode::PhoneBusy) {
            response =
                std::make_shared<MMICallForwardingResult>(IMMICustomResultParams::MMIType::CallForwardingNotification);
            response->addMessage(IMMICustomResultParams::MMIResultMessage::CommonMMINotSupported);
        }
    }

    if (response.get() == nullptr) {
        response =
            std::make_shared<MMICallForwardingResult>(IMMICustomResultParams::MMIType::CallForwardingNotification);
        response->addMessage(IMMICustomResultParams::MMIResultMessage::CommonFailure);
    }
    auto msg = std::make_shared<CellularMMIResultMessage>(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;

M module-services/service-cellular/service-cellular/CellularRequestHandler.hpp => module-services/service-cellular/service-cellular/CellularRequestHandler.hpp +1 -0
@@ 19,6 19,7 @@ class CellularRequestHandler : public cellular::RequestHandler
    void handle(cellular::SupplementaryServicesRequest &request, at::Result &result) final;
    void handle(cellular::PinChangeRequest &request, at::Result &result) final;
    void handle(cellular::ClirRequest &request, at::Result &result) final;
    void handle(cellular::CallForwardingRequest &request, at::Result &result) final;

  private:
    ServiceCellular &cellular;

M module-services/service-cellular/service-cellular/RequestHandler.hpp => module-services/service-cellular/service-cellular/RequestHandler.hpp +2 -0
@@ 15,6 15,7 @@ namespace cellular
    class PinChangeRequest;
    class ClipRequest;
    class ClirRequest;
    class CallForwardingRequest;

    class RequestHandler
    {


@@ 26,5 27,6 @@ namespace cellular
        virtual void handle(PinChangeRequest &request, at::Result &result)             = 0;
        virtual void handle(SupplementaryServicesRequest &request, at::Result &result) = 0;
        virtual void handle(ClirRequest &request, at::Result &result)                  = 0;
        virtual void handle(CallForwardingRequest &request, at::Result &result)        = 0;
    };
} // namespace cellular