device/google/cuttlefish/host/commands/modem_simulator/sup_service.cpp

321 lines
12 KiB
C++
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// Copyright (C) 2020 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "host/commands/modem_simulator/sup_service.h"
namespace cuttlefish {
SupService::SupService(int32_t service_id, ChannelMonitor* channel_monitor,
ThreadLooper* thread_looper)
: ModemService(service_id, this->InitializeCommandHandlers(),
channel_monitor, thread_looper) {
InitializeServiceState();
}
std::vector<CommandHandler> SupService::InitializeCommandHandlers() {
std::vector<CommandHandler> command_handlers = {
CommandHandler("+CUSD",
[this](const Client& client, std::string& cmd) {
this->HandleUSSD(client, cmd);
}),
CommandHandler("+CLIR",
[this](const Client& client, std::string& cmd) {
this->HandleCLIR(client, cmd);
}),
CommandHandler("+CCWA",
[this](const Client& client, std::string& cmd) {
this->HandleCallWaiting(client, cmd);
}),
CommandHandler(
"+CLIP?", [this](const Client& client) { this->HandleCLIP(client); }),
CommandHandler("+CCFCU",
[this](const Client& client, std::string& cmd) {
this->HandleCallForward(client, cmd);
}),
CommandHandler("+CSSN",
[this](const Client& client, std::string& cmd) {
this->HandleSuppServiceNotifications(client, cmd);
}),
};
return (command_handlers);
}
void SupService::InitializeServiceState() {
call_forward_infos_ = {
CallForwardInfo(CallForwardInfo::Reason::CFU),
CallForwardInfo(CallForwardInfo::Reason::CFB),
CallForwardInfo(CallForwardInfo::Reason::CFNR),
CallForwardInfo(CallForwardInfo::Reason::CFNRC)
};
}
/**
* AT+CUSD
* This command allows control of the Unstructured Supplementary Service Data (USSD)
* according to 3GPP TS 22.090 [23], 3GPP TS 24.090 [148] and 3GPP TS 24.390 [131].
* Both network and mobile initiated operations are supported.
*
* Command Possible response(s)
* +CUSD=[<n>[,<str>[,<dcs>]]] +CME ERROR: <err>
* +CUSD? +CUSD: <n>
*
* <n>: integer type (sets/shows the result code presentation status to the TE).
* 0 disable the result code presentation to the TE
* 1 enable the result code presentation to the TE
* 2 cancel session (not applicable to read command response)
* <str>: string type USSD string
* when <str> parameter is not given, network is not interrogated
* <dcs>: integer type (shows Cell Broadcast Data Coding Scheme, see 3GPP TS 23.038 [25]).
* Default value is 0.
*
* see RIL_REQUEST_SEND_USSD or RIL_REQUEST_CANCEL_USSD in RIL
*/
void SupService::HandleUSSD(const Client& client, std::string& /*command*/) {
client.SendCommandResponse("OK");
}
/**
* AT+CLIR
* This command refers to CLIRservice according to 3GPP TS 22.081 that allows
* a calling subscriber to enable or disable the presentation of the CLI to the
* called party when originating a call.
*
* Command Possible response(s)
* +CLIR: <n>
* +CLIR? +CLIR: <n>,<m>
*
* <n>: integer type (parameter sets the adjustment for outgoing calls).
* 0 presentation indicator is used according to the subscription of the CLIR service
* 1 CLIR invocation
* 2 CLIR suppression
* <m>: integer type (parameter shows the subscriber CLIR / OIR service status in the network).
* 0 CLIR / OIR not provisioned
* 1 CLIR / OIR provisioned in permanent mode
* 2 unknown (e.g. no network, etc.)
* 3 CLIR / OIR temporary mode presentation restricted
* 4 CLIR / OIR temporary mode presentation allowed
*
* see RIL_REQUEST_SET_CLIR or RIL_REQUEST_GET_CLIR in RIL
*/
void SupService::HandleCLIR(const Client& client, std::string& command) {
std::vector<std::string> responses;
std::stringstream ss;
CommandParser cmd(command);
cmd.SkipPrefix();
if (*cmd == "AT+CLIR?") {
ss << "+CLIR:" << clir_status_.type << "," << clir_status_.status;
responses.push_back(ss.str());
} else {
clir_status_.type = (ClirStatusInfo::ClirType)cmd.GetNextInt();
}
responses.push_back("OK");
client.SendCommandResponse(responses);
}
/**
* AT+CLIP
* This command refers to the supplementary service CLIP (Calling Line
* Identification Presentation) according to 3GPP TS 22.081 [3] and OIP
* (Originating Identification Presentation) according to 3GPP TS 24.607 [119]
* that enables a called subscriber to get the calling line identity (CLI) of
* the calling party when receiving a mobile terminated call.
*
* Command Possible response(s)
* +CLIP? +CLIP: <n>,<m>
*
* <n>: integer type (parameter sets/shows the result code presentation status to the TE).
* 0 disable
* 1 enable
* <m>: integer type (parameter shows the subscriber CLIR / OIR service status in the network).
* 0 CLIP / OIP not provisioned
* 1 CLIP / OIP provisioned
* 2 unknown (e.g. no network, etc.)
*
* see RIL_REQUEST_QUERY_CLIP in RIL
*/
void SupService::HandleCLIP(const Client& client) {
std::vector<std::string> responses = {"+CLIP: 0, 0", "OK"};
client.SendCommandResponse(responses);
}
/**
* AT+CSSN
* This command refers to supplementary service related network initiated
* notifications. The set command enables/disables the presentation of
* notification result codes from TA to TE.
*
* Command Possible response(s)
* +CSSN: [<n>[,<m>]]
*
* <n>: integer type (parameter sets/shows the +CSSI intermediate result code
* presentation status to the TE)
* 0 disable
* 1 enable
* <m>: integer type (parameter sets/shows the +CSSU unsolicited result code
* presentation status to the TE)
* 0 disable
* 1 enable
*
* see RIL_REQUEST_SET_SUPP_SVC_NOTIFICATION in RIL
*/
void SupService::HandleSuppServiceNotifications(const Client& client, std::string& /*command*/) {
client.SendCommandResponse("OK");
}
/**
* AT+CCFCU
* The command allows control of the communication forwarding supplementary service
* according to 3GPP TS 22.072 [31], 3GPP TS 22.082 [4] and 3GPP TS 24.604 [132].
*
* Command Possible response(s)
* +CCFCU=<reason>,<mode> +CME ERROR: <err>
* [,<numbertype>,<ton>,<number> when <mode>=2 and command successful:
* [,<class>,<ruleset> +CCFCU: <status>,<class1>[,<numbertype>,
* [,<subaddr>[,<satype>[,<time>]]]]] <ton>,<number>[,<subaddr>,<satype>[,<time>]]]
* [,<class>,<ruleset>
*
* see SupService::CallForwardInfo
*
* see RIL_REQUEST_SET_CALL_FORWARD or RIL_REQUEST_QUERY_CALL_FORWARD_STATUS in RIL
*/
void SupService::HandleCallForward(const Client& client, std::string& command) {
std::vector<std::string> responses;
std::stringstream ss;
CommandParser cmd(command);
cmd.SkipPrefix();
int reason = cmd.GetNextInt();
int status = cmd.GetNextInt();
int number_type = cmd.GetNextInt();
int ton = cmd.GetNextInt();
std::string_view number = cmd.GetNextStr();
int classx = cmd.GetNextInt();
switch (reason) {
case CallForwardInfo::Reason::ALL_CF: {
if (status == CallForwardInfo::CallForwardInfoStatus::INTERROGATE) {
auto iter = call_forward_infos_.begin();
for (; iter != call_forward_infos_.end(); ++iter) {
ss.clear();
ss << "+CCFCU: " << iter->status << "," << classx << "," << number_type
<< "," << ton << ",\"" << iter->number << "\"";
if (iter->reason == CallForwardInfo::Reason::CFNR) {
ss << ",,," << iter->timeSeconds;
}
responses.push_back(ss.str());
ss.str("");
}
}
break;
}
case CallForwardInfo::Reason::CFU:
case CallForwardInfo::Reason::CFB:
case CallForwardInfo::Reason::CFNR:
case CallForwardInfo::Reason::CFNRC: {
if (status == CallForwardInfo::CallForwardInfoStatus::INTERROGATE) {
ss << "+CCFCU: " << call_forward_infos_[reason].status
<< "," << classx << "," << number_type << "," << ton << ",\""
<< call_forward_infos_[reason].number << "\"";
if (reason == CallForwardInfo::Reason::CFNR) {
ss << ",,," << call_forward_infos_[reason].timeSeconds;
}
responses.push_back(ss.str());
} else {
if (status == CallForwardInfo::CallForwardInfoStatus::REGISTRATION) {
call_forward_infos_[reason].status
= CallForwardInfo::CallForwardInfoStatus::ENABLE;
} else {
call_forward_infos_[reason].status =
(CallForwardInfo::CallForwardInfoStatus)status;
}
call_forward_infos_[reason].number_type = number_type;
call_forward_infos_[reason].ton = ton;
call_forward_infos_[reason].number = number;
if (reason == CallForwardInfo::Reason::CFNR) {
cmd.SkipComma();
cmd.SkipComma();
cmd.SkipComma();
int timeSeconds = cmd.GetNextInt();
call_forward_infos_[reason].timeSeconds = timeSeconds >= 0 ? timeSeconds : 0;
}
}
break;
}
default:
client.SendCommandResponse(kCmeErrorInCorrectParameters);
return;
}
responses.push_back("OK");
client.SendCommandResponse(responses);
}
/**
* AT+CCWA
* This command allows control of the supplementary service Call Waiting
* according to 3GPP TS 22.083 [5] and Communication Waiting according to
* 3GPP TS 24.607 [137]. Activation, deactivation and status query are supported.
*
* Command Possible response(s)
* +CCWA=[<n>[,<mode>[,<class>]]] +CME ERROR: <err>
* when <mode>=2 and command successful
+CCWA: <status>,<class1>
[<CR><LF>+CCWA: <status>,<class2>
* <n>: integer type (sets/shows the result code presentation status to the TE).
* 0 disable
* 1 enable
* <mode>: integer type (when <mode> parameter is not given, network is not interrogated).
* 0 disable
* 1 enable
* 2 query status
* <classx>: a sum of integers each representing a class of information
* (default 7 - voice, data and fax).
* <status>: integer type
* 0 not active
* 1 active
*
* see RIL_REQUEST_QUERY_CALL_WAITING and RIL_REQUEST_SET_CALL_WAITING in RIL
*/
void SupService::HandleCallWaiting(const Client& client, std::string& command) {
std::vector<std::string> responses;
std::stringstream ss;
CommandParser cmd(command);
cmd.SkipPrefix();
cmd.SkipComma();
int mode = cmd.GetNextInt();
int classx = cmd.GetNextInt();
if (mode == 2) { // Query
if (classx == -1) {
classx = 7;
}
ss << "+CCWA: " << call_waiting_info_.mode << "," << classx;
responses.push_back(ss.str());
} else if (mode == 0 || mode == 1) { // Enable or disable
call_waiting_info_.mode = mode;
if (classx != -1) {
call_waiting_info_.classx = classx;
}
}
responses.push_back("OK");
client.SendCommandResponse(responses);
}
} // namespace cuttlefish