321 lines
12 KiB
C++
321 lines
12 KiB
C++
|
//
|
|||
|
// 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 CLIR‑service 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
|