1 //
2 // Copyright (C) 2020 The Android Open Source Project
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 // http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15
16 #include "host/commands/modem_simulator/sup_service.h"
17
18 namespace cuttlefish {
19
SupService(int32_t service_id,ChannelMonitor * channel_monitor,ThreadLooper * thread_looper)20 SupService::SupService(int32_t service_id, ChannelMonitor* channel_monitor,
21 ThreadLooper* thread_looper)
22 : ModemService(service_id, this->InitializeCommandHandlers(),
23 channel_monitor, thread_looper) {
24 InitializeServiceState();
25 }
26
InitializeCommandHandlers()27 std::vector<CommandHandler> SupService::InitializeCommandHandlers() {
28 std::vector<CommandHandler> command_handlers = {
29 CommandHandler("+CUSD",
30 [this](const Client& client, std::string& cmd) {
31 this->HandleUSSD(client, cmd);
32 }),
33 CommandHandler("+CLIR",
34 [this](const Client& client, std::string& cmd) {
35 this->HandleCLIR(client, cmd);
36 }),
37 CommandHandler("+CCWA",
38 [this](const Client& client, std::string& cmd) {
39 this->HandleCallWaiting(client, cmd);
40 }),
41 CommandHandler(
42 "+CLIP?", [this](const Client& client) { this->HandleCLIP(client); }),
43 CommandHandler("+CCFCU",
44 [this](const Client& client, std::string& cmd) {
45 this->HandleCallForward(client, cmd);
46 }),
47 CommandHandler("+CSSN",
48 [this](const Client& client, std::string& cmd) {
49 this->HandleSuppServiceNotifications(client, cmd);
50 }),
51 };
52 return (command_handlers);
53 }
54
InitializeServiceState()55 void SupService::InitializeServiceState() {
56 call_forward_infos_ = {
57 CallForwardInfo(CallForwardInfo::Reason::CFU),
58 CallForwardInfo(CallForwardInfo::Reason::CFB),
59 CallForwardInfo(CallForwardInfo::Reason::CFNR),
60 CallForwardInfo(CallForwardInfo::Reason::CFNRC)
61 };
62 }
63
64 /**
65 * AT+CUSD
66 * This command allows control of the Unstructured Supplementary Service Data (USSD)
67 * according to 3GPP TS 22.090 [23], 3GPP TS 24.090 [148] and 3GPP TS 24.390 [131].
68 * Both network and mobile initiated operations are supported.
69 *
70 * Command Possible response(s)
71 * +CUSD=[<n>[,<str>[,<dcs>]]] +CME ERROR: <err>
72 * +CUSD? +CUSD: <n>
73 *
74 * <n>: integer type (sets/shows the result code presentation status to the TE).
75 * 0 disable the result code presentation to the TE
76 * 1 enable the result code presentation to the TE
77 * 2 cancel session (not applicable to read command response)
78 * <str>: string type USSD string
79 * when <str> parameter is not given, network is not interrogated
80 * <dcs>: integer type (shows Cell Broadcast Data Coding Scheme, see 3GPP TS 23.038 [25]).
81 * Default value is 0.
82 *
83 * see RIL_REQUEST_SEND_USSD or RIL_REQUEST_CANCEL_USSD in RIL
84 */
HandleUSSD(const Client & client,std::string &)85 void SupService::HandleUSSD(const Client& client, std::string& /*command*/) {
86 client.SendCommandResponse("OK");
87 }
88
89 /**
90 * AT+CLIR
91 * This command refers to CLIR‑service according to 3GPP TS 22.081 that allows
92 * a calling subscriber to enable or disable the presentation of the CLI to the
93 * called party when originating a call.
94 *
95 * Command Possible response(s)
96 * +CLIR: <n>
97 * +CLIR? +CLIR: <n>,<m>
98 *
99 * <n>: integer type (parameter sets the adjustment for outgoing calls).
100 * 0 presentation indicator is used according to the subscription of the CLIR service
101 * 1 CLIR invocation
102 * 2 CLIR suppression
103 * <m>: integer type (parameter shows the subscriber CLIR / OIR service status in the network).
104 * 0 CLIR / OIR not provisioned
105 * 1 CLIR / OIR provisioned in permanent mode
106 * 2 unknown (e.g. no network, etc.)
107 * 3 CLIR / OIR temporary mode presentation restricted
108 * 4 CLIR / OIR temporary mode presentation allowed
109 *
110 * see RIL_REQUEST_SET_CLIR or RIL_REQUEST_GET_CLIR in RIL
111 */
HandleCLIR(const Client & client,std::string & command)112 void SupService::HandleCLIR(const Client& client, std::string& command) {
113 std::vector<std::string> responses;
114 std::stringstream ss;
115
116 CommandParser cmd(command);
117 cmd.SkipPrefix();
118 if (*cmd == "AT+CLIR?") {
119 ss << "+CLIR:" << clir_status_.type << "," << clir_status_.status;
120 responses.push_back(ss.str());
121 } else {
122 clir_status_.type = (ClirStatusInfo::ClirType)cmd.GetNextInt();
123 }
124 responses.push_back("OK");
125 client.SendCommandResponse(responses);
126 }
127
128 /**
129 * AT+CLIP
130 * This command refers to the supplementary service CLIP (Calling Line
131 * Identification Presentation) according to 3GPP TS 22.081 [3] and OIP
132 * (Originating Identification Presentation) according to 3GPP TS 24.607 [119]
133 * that enables a called subscriber to get the calling line identity (CLI) of
134 * the calling party when receiving a mobile terminated call.
135 *
136 * Command Possible response(s)
137 * +CLIP? +CLIP: <n>,<m>
138 *
139 * <n>: integer type (parameter sets/shows the result code presentation status to the TE).
140 * 0 disable
141 * 1 enable
142 * <m>: integer type (parameter shows the subscriber CLIR / OIR service status in the network).
143 * 0 CLIP / OIP not provisioned
144 * 1 CLIP / OIP provisioned
145 * 2 unknown (e.g. no network, etc.)
146 *
147 * see RIL_REQUEST_QUERY_CLIP in RIL
148 */
HandleCLIP(const Client & client)149 void SupService::HandleCLIP(const Client& client) {
150 std::vector<std::string> responses = {"+CLIP: 0, 0", "OK"};
151 client.SendCommandResponse(responses);
152 }
153
154 /**
155 * AT+CSSN
156 * This command refers to supplementary service related network initiated
157 * notifications. The set command enables/disables the presentation of
158 * notification result codes from TA to TE.
159 *
160 * Command Possible response(s)
161 * +CSSN: [<n>[,<m>]]
162 *
163 * <n>: integer type (parameter sets/shows the +CSSI intermediate result code
164 * presentation status to the TE)
165 * 0 disable
166 * 1 enable
167 * <m>: integer type (parameter sets/shows the +CSSU unsolicited result code
168 * presentation status to the TE)
169 * 0 disable
170 * 1 enable
171 *
172 * see RIL_REQUEST_SET_SUPP_SVC_NOTIFICATION in RIL
173 */
HandleSuppServiceNotifications(const Client & client,std::string &)174 void SupService::HandleSuppServiceNotifications(const Client& client, std::string& /*command*/) {
175 client.SendCommandResponse("OK");
176 }
177
178 /**
179 * AT+CCFCU
180 * The command allows control of the communication forwarding supplementary service
181 * according to 3GPP TS 22.072 [31], 3GPP TS 22.082 [4] and 3GPP TS 24.604 [132].
182 *
183 * Command Possible response(s)
184 * +CCFCU=<reason>,<mode> +CME ERROR: <err>
185 * [,<numbertype>,<ton>,<number> when <mode>=2 and command successful:
186 * [,<class>,<ruleset> +CCFCU: <status>,<class1>[,<numbertype>,
187 * [,<subaddr>[,<satype>[,<time>]]]]] <ton>,<number>[,<subaddr>,<satype>[,<time>]]]
188 * [,<class>,<ruleset>
189 *
190 * see SupService::CallForwardInfo
191 *
192 * see RIL_REQUEST_SET_CALL_FORWARD or RIL_REQUEST_QUERY_CALL_FORWARD_STATUS in RIL
193 */
HandleCallForward(const Client & client,std::string & command)194 void SupService::HandleCallForward(const Client& client, std::string& command) {
195 std::vector<std::string> responses;
196 std::stringstream ss;
197
198 CommandParser cmd(command);
199 cmd.SkipPrefix();
200
201 int reason = cmd.GetNextInt();
202 int status = cmd.GetNextInt();
203 int number_type = cmd.GetNextInt();
204 int ton = cmd.GetNextInt();
205 std::string_view number = cmd.GetNextStr();
206 int classx = cmd.GetNextInt();
207
208 switch (reason) {
209 case CallForwardInfo::Reason::ALL_CF: {
210 if (status == CallForwardInfo::CallForwardInfoStatus::INTERROGATE) {
211 auto iter = call_forward_infos_.begin();
212 for (; iter != call_forward_infos_.end(); ++iter) {
213 ss.clear();
214 ss << "+CCFCU: " << iter->status << "," << classx << "," << number_type
215 << "," << ton << ",\"" << iter->number << "\"";
216 if (iter->reason == CallForwardInfo::Reason::CFNR) {
217 ss << ",,," << iter->timeSeconds;
218 }
219 responses.push_back(ss.str());
220 ss.str("");
221 }
222 }
223 break;
224 }
225 case CallForwardInfo::Reason::CFU:
226 case CallForwardInfo::Reason::CFB:
227 case CallForwardInfo::Reason::CFNR:
228 case CallForwardInfo::Reason::CFNRC: {
229 if (status == CallForwardInfo::CallForwardInfoStatus::INTERROGATE) {
230 ss << "+CCFCU: " << call_forward_infos_[reason].status
231 << "," << classx << "," << number_type << "," << ton << ",\""
232 << call_forward_infos_[reason].number << "\"";
233 if (reason == CallForwardInfo::Reason::CFNR) {
234 ss << ",,," << call_forward_infos_[reason].timeSeconds;
235 }
236 responses.push_back(ss.str());
237 } else {
238 if (status == CallForwardInfo::CallForwardInfoStatus::REGISTRATION) {
239 call_forward_infos_[reason].status
240 = CallForwardInfo::CallForwardInfoStatus::ENABLE;
241 } else {
242 call_forward_infos_[reason].status =
243 (CallForwardInfo::CallForwardInfoStatus)status;
244 }
245 call_forward_infos_[reason].number_type = number_type;
246 call_forward_infos_[reason].ton = ton;
247 call_forward_infos_[reason].number = number;
248 if (reason == CallForwardInfo::Reason::CFNR) {
249 cmd.SkipComma();
250 cmd.SkipComma();
251 cmd.SkipComma();
252 call_forward_infos_[reason].timeSeconds = cmd.GetNextInt();
253 }
254 }
255 break;
256 }
257 default:
258 client.SendCommandResponse(kCmeErrorInCorrectParameters);
259 return;
260 }
261
262 responses.push_back("OK");
263 client.SendCommandResponse(responses);
264 }
265
266 /**
267 * AT+CCWA
268 * This command allows control of the supplementary service Call Waiting
269 * according to 3GPP TS 22.083 [5] and Communication Waiting according to
270 * 3GPP TS 24.607 [137]. Activation, deactivation and status query are supported.
271 *
272 * Command Possible response(s)
273 * +CCWA=[<n>[,<mode>[,<class>]]] +CME ERROR: <err>
274 * when <mode>=2 and command successful
275 +CCWA: <status>,<class1>
276 [<CR><LF>+CCWA: <status>,<class2>
277 * <n>: integer type (sets/shows the result code presentation status to the TE).
278 * 0 disable
279 * 1 enable
280 * <mode>: integer type (when <mode> parameter is not given, network is not interrogated).
281 * 0 disable
282 * 1 enable
283 * 2 query status
284 * <classx>: a sum of integers each representing a class of information
285 * (default 7 - voice, data and fax).
286 * <status>: integer type
287 * 0 not active
288 * 1 active
289 *
290 * see RIL_REQUEST_QUERY_CALL_WAITING and RIL_REQUEST_SET_CALL_WAITING in RIL
291 */
HandleCallWaiting(const Client & client,std::string & command)292 void SupService::HandleCallWaiting(const Client& client, std::string& command) {
293 std::vector<std::string> responses;
294 std::stringstream ss;
295
296 CommandParser cmd(command);
297 cmd.SkipPrefix();
298 cmd.SkipComma();
299 int mode = cmd.GetNextInt();
300 int classx = cmd.GetNextInt();
301
302 if (mode == 2) { // Query
303 if (classx == -1) {
304 classx = 7;
305 }
306 ss << "+CCWA: " << call_waiting_info_.mode << "," << classx;
307 responses.push_back(ss.str());
308 } else if (mode == 0 || mode == 1) { // Enable or disable
309 call_waiting_info_.mode = mode;
310 if (classx != -1) {
311 call_waiting_info_.classx = classx;
312 }
313 }
314
315 responses.push_back("OK");
316 client.SendCommandResponse(responses);
317 }
318
319 } // namespace cuttlefish
320