1 /*
2 * Copyright (C) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "hfp_ag_command_processor.h"
17
18 #include <algorithm>
19 #include <regex>
20 #include <string>
21
22 #include "hfp_ag_audio_connection.h"
23 #include "hfp_ag_defines.h"
24 #include "hfp_ag_profile_event_sender.h"
25 #include "log_util.h"
26 #include "packet.h"
27 #include "securec.h"
28
29 namespace OHOS {
30 namespace bluetooth {
31 std::unordered_map<std::string, HfpAgCommandProcessor::HfpAgAtHandler> HfpAgCommandProcessor::g_atCmdMap = {
32 std::make_pair<std::string, HfpAgAtHandler>("AT+BRSF", {&HfpAgCommandProcessor::AtEmptyFn,
33 &HfpAgCommandProcessor::BrsfSetter,
34 &HfpAgCommandProcessor::AtEmptyFn,
35 &HfpAgCommandProcessor::AtEmptyFn}),
36 std::make_pair<std::string, HfpAgAtHandler>("AT+CCWA", {&HfpAgCommandProcessor::AtEmptyFn,
37 &HfpAgCommandProcessor::CcwaSetter,
38 &HfpAgCommandProcessor::AtEmptyFn,
39 &HfpAgCommandProcessor::AtEmptyFn}),
40 std::make_pair<std::string, HfpAgAtHandler>("AT+CLIP", {&HfpAgCommandProcessor::AtEmptyFn,
41 &HfpAgCommandProcessor::ClipSetter,
42 &HfpAgCommandProcessor::AtEmptyFn,
43 &HfpAgCommandProcessor::AtEmptyFn}),
44 std::make_pair<std::string, HfpAgAtHandler>("AT+CMER", {&HfpAgCommandProcessor::AtEmptyFn,
45 &HfpAgCommandProcessor::CmerSetter,
46 &HfpAgCommandProcessor::AtEmptyFn,
47 &HfpAgCommandProcessor::AtEmptyFn}),
48 std::make_pair<std::string, HfpAgAtHandler>("AT+CMEE", {&HfpAgCommandProcessor::AtEmptyFn,
49 &HfpAgCommandProcessor::CmeeSetter,
50 &HfpAgCommandProcessor::AtEmptyFn,
51 &HfpAgCommandProcessor::AtEmptyFn}),
52 std::make_pair<std::string, HfpAgAtHandler>("AT+BCC", {&HfpAgCommandProcessor::AtEmptyFn,
53 &HfpAgCommandProcessor::AtEmptyFn,
54 &HfpAgCommandProcessor::AtEmptyFn,
55 &HfpAgCommandProcessor::BccExecuter}),
56 std::make_pair<std::string, HfpAgAtHandler>("ATA", {&HfpAgCommandProcessor::AtEmptyFn,
57 &HfpAgCommandProcessor::AtEmptyFn,
58 &HfpAgCommandProcessor::AtEmptyFn,
59 &HfpAgCommandProcessor::AtaExecuter}),
60 std::make_pair<std::string, HfpAgAtHandler>("ATD", {&HfpAgCommandProcessor::AtEmptyFn,
61 &HfpAgCommandProcessor::AtEmptyFn,
62 &HfpAgCommandProcessor::AtEmptyFn,
63 &HfpAgCommandProcessor::AtdExecuter}),
64 std::make_pair<std::string, HfpAgAtHandler>("AT+VGS", {&HfpAgCommandProcessor::AtEmptyFn,
65 &HfpAgCommandProcessor::VgsSetter,
66 &HfpAgCommandProcessor::AtEmptyFn,
67 &HfpAgCommandProcessor::AtEmptyFn}),
68 std::make_pair<std::string, HfpAgAtHandler>("AT+VGM", {&HfpAgCommandProcessor::AtEmptyFn,
69 &HfpAgCommandProcessor::VgmSetter,
70 &HfpAgCommandProcessor::AtEmptyFn,
71 &HfpAgCommandProcessor::AtEmptyFn}),
72 std::make_pair<std::string, HfpAgAtHandler>("AT+CHLD", {&HfpAgCommandProcessor::AtEmptyFn,
73 &HfpAgCommandProcessor::ChldSetter,
74 &HfpAgCommandProcessor::ChldTester,
75 &HfpAgCommandProcessor::AtEmptyFn}),
76 std::make_pair<std::string, HfpAgAtHandler>("AT+CHUP", {&HfpAgCommandProcessor::AtEmptyFn,
77 &HfpAgCommandProcessor::AtEmptyFn,
78 &HfpAgCommandProcessor::AtEmptyFn,
79 &HfpAgCommandProcessor::ChupExecuter}),
80 std::make_pair<std::string, HfpAgAtHandler>("AT+CIND", {&HfpAgCommandProcessor::CindGetter,
81 &HfpAgCommandProcessor::AtEmptyFn,
82 &HfpAgCommandProcessor::CindTester,
83 &HfpAgCommandProcessor::AtEmptyFn}),
84 std::make_pair<std::string, HfpAgAtHandler>("AT+VTS", {&HfpAgCommandProcessor::AtEmptyFn,
85 &HfpAgCommandProcessor::VtsSetter,
86 &HfpAgCommandProcessor::AtEmptyFn,
87 &HfpAgCommandProcessor::AtEmptyFn}),
88 std::make_pair<std::string, HfpAgAtHandler>("AT+BLDN", {&HfpAgCommandProcessor::AtEmptyFn,
89 &HfpAgCommandProcessor::AtEmptyFn,
90 &HfpAgCommandProcessor::AtEmptyFn,
91 &HfpAgCommandProcessor::BldnExecuter}),
92 std::make_pair<std::string, HfpAgAtHandler>("AT+BVRA", {&HfpAgCommandProcessor::AtEmptyFn,
93 &HfpAgCommandProcessor::BvraSetter,
94 &HfpAgCommandProcessor::AtEmptyFn,
95 &HfpAgCommandProcessor::AtEmptyFn}),
96 std::make_pair<std::string, HfpAgAtHandler>("AT+NREC", {&HfpAgCommandProcessor::AtEmptyFn,
97 &HfpAgCommandProcessor::NrecSetter,
98 &HfpAgCommandProcessor::AtEmptyFn,
99 &HfpAgCommandProcessor::AtEmptyFn}),
100 std::make_pair<std::string, HfpAgAtHandler>("AT+CNUM", {&HfpAgCommandProcessor::AtEmptyFn,
101 &HfpAgCommandProcessor::AtEmptyFn,
102 &HfpAgCommandProcessor::AtEmptyFn,
103 &HfpAgCommandProcessor::CnumExecuter}),
104 std::make_pair<std::string, HfpAgAtHandler>("AT+CLCC", {&HfpAgCommandProcessor::AtEmptyFn,
105 &HfpAgCommandProcessor::AtEmptyFn,
106 &HfpAgCommandProcessor::AtEmptyFn,
107 &HfpAgCommandProcessor::ClccExecuter}),
108 std::make_pair<std::string, HfpAgAtHandler>("AT+COPS", {&HfpAgCommandProcessor::CopsGetter,
109 &HfpAgCommandProcessor::CopsSetter,
110 &HfpAgCommandProcessor::AtEmptyFn,
111 &HfpAgCommandProcessor::AtEmptyFn}),
112 std::make_pair<std::string, HfpAgAtHandler>("AT+BIA", {&HfpAgCommandProcessor::AtEmptyFn,
113 &HfpAgCommandProcessor::BiaSetter,
114 &HfpAgCommandProcessor::AtEmptyFn,
115 &HfpAgCommandProcessor::AtEmptyFn}),
116 std::make_pair<std::string, HfpAgAtHandler>("AT+BCS", {&HfpAgCommandProcessor::AtEmptyFn,
117 &HfpAgCommandProcessor::BcsSetter,
118 &HfpAgCommandProcessor::AtEmptyFn,
119 &HfpAgCommandProcessor::AtEmptyFn}),
120 std::make_pair<std::string, HfpAgAtHandler>("AT+BIND", {&HfpAgCommandProcessor::BindGetter,
121 &HfpAgCommandProcessor::BindSetter,
122 &HfpAgCommandProcessor::BindTester,
123 &HfpAgCommandProcessor::AtEmptyFn}),
124 std::make_pair<std::string, HfpAgAtHandler>("AT+BIEV", {&HfpAgCommandProcessor::AtEmptyFn,
125 &HfpAgCommandProcessor::BievSetter,
126 &HfpAgCommandProcessor::AtEmptyFn,
127 &HfpAgCommandProcessor::AtEmptyFn}),
128 std::make_pair<std::string, HfpAgAtHandler>("AT+BAC", {&HfpAgCommandProcessor::AtEmptyFn,
129 &HfpAgCommandProcessor::BacSetter,
130 &HfpAgCommandProcessor::AtEmptyFn,
131 &HfpAgCommandProcessor::AtEmptyFn}),
132 std::make_pair<std::string, HfpAgAtHandler>("AT+BTRH", {&HfpAgCommandProcessor::BtrhGetter,
133 &HfpAgCommandProcessor::BtrhSetter,
134 &HfpAgCommandProcessor::AtEmptyFn,
135 &HfpAgCommandProcessor::AtEmptyFn}),
136 std::make_pair<std::string, HfpAgAtHandler>("AT+CKPD", {&HfpAgCommandProcessor::AtEmptyFn,
137 &HfpAgCommandProcessor::CkpdSetter,
138 &HfpAgCommandProcessor::AtEmptyFn,
139 &HfpAgCommandProcessor::AtEmptyFn}),
140 std::make_pair<std::string, HfpAgAtHandler>("AT+BINP", {&HfpAgCommandProcessor::AtEmptyFn,
141 &HfpAgCommandProcessor::BinpSetter,
142 &HfpAgCommandProcessor::AtEmptyFn,
143 &HfpAgCommandProcessor::AtEmptyFn}),
144 };
145
StoiTryCatch(HfpAgDataConnection & dataConn,const std::string & arg)146 int HfpAgCommandProcessor::StoiTryCatch(HfpAgDataConnection &dataConn, const std::string &arg)
147 {
148 try {
149 return std::stoi(arg);
150 } catch (std::exception &e) {
151 LOG_ERROR("[HFP AG]%{public}s():Catch exception %{public}s", __FUNCTION__, e.what());
152 SendErrorCode(dataConn, HFP_AG_ERROR_AG_FAILURE);
153 return 0;
154 }
155 }
156
GetInstance()157 HfpAgCommandProcessor &HfpAgCommandProcessor::GetInstance()
158 {
159 static HfpAgCommandProcessor instance;
160 return instance;
161 }
162
SendErrorCode(const HfpAgDataConnection & dataConn,int errorCode)163 void HfpAgCommandProcessor::SendErrorCode(const HfpAgDataConnection &dataConn, int errorCode)
164 {
165 if (dataConn.cmeeEnabled_) {
166 SendAtCommand(dataConn, "+CME ERROR: " + std::to_string(errorCode));
167 } else {
168 SendAtCommand(dataConn, "ERROR");
169 }
170 }
171
SendAtCommand(const HfpAgDataConnection & dataConn,const std::string & command)172 void HfpAgCommandProcessor::SendAtCommand(const HfpAgDataConnection &dataConn, const std::string &command)
173 {
174 LOG_INFO("[HFP AG]%{public}s():Send Command[%{public}s]", __FUNCTION__, command.c_str());
175 std::string fullCommand(HEAD + command + TAIL);
176 std::size_t cmdLength = fullCommand.length();
177 Packet *packet = PacketMalloc(0, 0, cmdLength);
178 Buffer *buf = PacketContinuousPayload(packet);
179 void *data = BufferPtr(buf);
180 (void)memcpy_s(data, cmdLength, fullCommand.c_str(), cmdLength);
181 dataConn.WriteData(*packet);
182 PacketFree(packet);
183 }
184
Handle(HfpAgDataConnection & dataConn,const std::string & cmd,const std::string & arg,int cmdType)185 void HfpAgCommandProcessor::Handle(
186 HfpAgDataConnection &dataConn, const std::string &cmd, const std::string &arg, int cmdType)
187 {
188 LOG_INFO("[HFP AG]%{public}s():cmd[%{public}s], arg[%{public}s], Type[%{public}d]", __FUNCTION__,
189 cmd.c_str(), arg.c_str(), cmdType);
190 auto it = g_atCmdMap.find(cmd);
191 if (it == g_atCmdMap.end()) {
192 SendErrorCode(dataConn, HFP_AG_ERROR_AG_FAILURE);
193 LOG_ERROR("[HFP AG]%{public}s():%{public}s command handler not found", __FUNCTION__, cmd.c_str());
194 return;
195 }
196
197 switch (cmdType) {
198 case HFP_AG_CMD_SET:
199 (this->*(it->second.setter))(dataConn, arg);
200 break;
201 case HFP_AG_CMD_GET:
202 (this->*(it->second.getter))(dataConn, arg);
203 break;
204 case HFP_AG_CMD_TEST:
205 (this->*(it->second.tester))(dataConn, arg);
206 break;
207 case HFP_AG_CMD_EXEC:
208 (this->*(it->second.executer))(dataConn, arg);
209 break;
210 case HFP_AG_CMD_UNKNOWN:
211 LOG_INFO("[HFP AG]%{public}s():HFP_AG_CMD_UNKNOWN", __FUNCTION__);
212 break;
213 default:
214 LOG_INFO("[HFP AG]%{public}s():default", __FUNCTION__);
215 break;
216 }
217 return;
218 }
219
AtEmptyFn(HfpAgDataConnection & dataConn,const std::string & arg)220 void HfpAgCommandProcessor::AtEmptyFn(HfpAgDataConnection &dataConn, const std::string &arg)
221 {
222 LOG_WARN("[HFP AG]%{public}s():Unsupported at command arg[%{public}s]", __FUNCTION__, arg.c_str());
223 SendErrorCode(dataConn, HFP_AG_ERROR_AG_FAILURE);
224 }
225
AtaExecuter(HfpAgDataConnection & dataConn,const std::string & arg)226 void HfpAgCommandProcessor::AtaExecuter(HfpAgDataConnection &dataConn, const std::string &arg)
227 {
228 SendAtCommand(dataConn, OK);
229 HfpAgProfileEventSender::GetInstance().AnswerCall(dataConn.remoteAddr_);
230 }
231
AtdExecuter(HfpAgDataConnection & dataConn,const std::string & arg)232 void HfpAgCommandProcessor::AtdExecuter(HfpAgDataConnection &dataConn, const std::string &arg)
233 {
234 std::string number = arg;
235 number.erase(remove_if(number.begin(), number.end(), isspace), number.end());
236 int type = HFP_AG_NUMBER_DIAL;
237
238 if (number.length() <= ATD_VALID_LENGTH) { // number should contains a number and a ';'
239 SendErrorCode(dataConn, HFP_AG_ERROR_INVALID_CHARS_IN_DIAL_STRING);
240 return;
241 }
242
243 if (number.at(0) == '>') { // ATD> memory dial
244 const std::regex baseRegex("[^\\d>;]");
245 if (std::regex_search(number, baseRegex) || number.at(number.length() - 1) != ';') {
246 SendErrorCode(dataConn, HFP_AG_ERROR_INVALID_CHARS_IN_DIAL_STRING);
247 return;
248 }
249
250 type = HFP_AG_MEMORY_DIAL;
251 number = number.substr(1, number.length() - ATD_VALID_LENGTH);
252 } else { // specific number dial
253 const std::regex baseRegex("[^\\d*#+;]");
254 if (std::regex_search(number, baseRegex) || number.at(number.length() - 1) != ';') {
255 SendErrorCode(dataConn, HFP_AG_ERROR_INVALID_CHARS_IN_DIAL_STRING);
256 return;
257 }
258 number = number.substr(0, number.length() - 1);
259 }
260 HfpAgProfileEventSender::GetInstance().DialOutCall(dataConn.remoteAddr_, number, type);
261 }
262
VgsSetter(HfpAgDataConnection & dataConn,const std::string & arg)263 void HfpAgCommandProcessor::VgsSetter(HfpAgDataConnection &dataConn, const std::string &arg)
264 {
265 int val = StoiTryCatch(dataConn, arg);
266 SendAtCommand(dataConn, OK);
267 HfpAgProfileEventSender::GetInstance().HfVolumeChanged(dataConn.remoteAddr_, HFP_AG_VOLUME_TYPE_SPK, val);
268 }
VgmSetter(HfpAgDataConnection & dataConn,const std::string & arg)269 void HfpAgCommandProcessor::VgmSetter(HfpAgDataConnection &dataConn, const std::string &arg)
270 {
271 int val = StoiTryCatch(dataConn, arg);
272 SendAtCommand(dataConn, OK);
273 HfpAgProfileEventSender::GetInstance().HfVolumeChanged(dataConn.remoteAddr_, HFP_AG_VOLUME_TYPE_MIC, val);
274 }
275
CcwaSetter(HfpAgDataConnection & dataConn,const std::string & arg)276 void HfpAgCommandProcessor::CcwaSetter(HfpAgDataConnection &dataConn, const std::string &arg)
277 {
278 dataConn.ccwaEnabled_ = StoiTryCatch(dataConn, arg);
279 SendAtCommand(dataConn, OK);
280 }
281
ChldSetter(HfpAgDataConnection & dataConn,const std::string & arg)282 void HfpAgCommandProcessor::ChldSetter(HfpAgDataConnection &dataConn, const std::string &arg)
283 {
284 int chld = StoiTryCatch(dataConn, arg);
285 LOG_INFO("[HFP AG] ChldSetter chld = %{public}d, arg = %{public}s", chld, arg.c_str());
286 if (!(dataConn.g_localFeatures & HFP_AG_FEATURES_ENHANCED_CALL_CONTROL) &&
287 (dataConn.remoteFeatures_ & HFP_AG_HF_FEATURES_ENHANCED_CALL_CONTROL)) {
288 if (chld != CHLD_RELEASE_ALL_HELD_CALLS && chld != CHLD_RELEASE_ACTIVE_ACCPET_OTHER &&
289 chld != CHLD_RELEASE_HOLD_ACCPET_OTHER && chld != CHLD_ADD_CALL_TO_CONVERSATION &&
290 chld != CHLD_CONNECT_TWO_CALL && chld != CHLD_RELEASE_INDEX_ONE && chld != CHLD_RELEASE_INDEX_TWO &&
291 chld != CHLD_CONSULTATION_INDEX_ONE && chld != CHLD_CONSULTATION_INDEX_TWO) {
292 // we does not support enhanced call control(AT+CHLD=1<idx> / AT+CHLD=2<idx>)
293 SendErrorCode(dataConn, HFP_AG_ERROR_AG_FAILURE);
294 return;
295 }
296 }
297
298 HfpAgProfileEventSender::GetInstance().HoldCall(dataConn.remoteAddr_, chld);
299 }
300
ChldTester(HfpAgDataConnection & dataConn,const std::string & arg)301 void HfpAgCommandProcessor::ChldTester(HfpAgDataConnection &dataConn, const std::string &arg)
302 {
303 if ((dataConn.sdpInfo_.remoteVersion >= HFP_AG_HFP_VERSION_1_5) &&
304 (dataConn.g_localFeatures & HFP_AG_FEATURES_ENHANCED_CALL_CONTROL) &&
305 (dataConn.remoteFeatures_ & HFP_AG_HF_FEATURES_ENHANCED_CALL_CONTROL)) {
306 SendAtCommand(dataConn, "+CHLD: " + HfpAgDataConnection::CHLD_ECC_SETTINGS);
307 } else {
308 SendAtCommand(dataConn, "+CHLD: " + HfpAgDataConnection::CHLD_SETTINGS);
309 }
310
311 if (!dataConn.slcConnected_ && !((dataConn.g_localFeatures & HFP_AG_FEATURES_HF_INDICATORS) &&
312 (dataConn.remoteFeatures_ & HFP_AG_HF_FEATURES_HF_INDICATORS))) {
313 dataConn.SetSlcConnectState(true);
314 HfpAgProfileEventSender::GetInstance().UpdateConnectState(dataConn.remoteAddr_, HFP_AG_SLC_ESTABLISHED_EVT);
315 }
316 SendAtCommand(dataConn, OK);
317 }
318
ChupExecuter(HfpAgDataConnection & dataConn,const std::string & arg)319 void HfpAgCommandProcessor::ChupExecuter(HfpAgDataConnection &dataConn, const std::string &arg)
320 {
321 if (HfpAgAudioConnection::GetActiveDevice().compare(dataConn.remoteAddr_) != 0) {
322 HILOGI("[HFP AG] AT+CHUP failed because of device is not active, activeAddr[%{public}s], "
323 "remoteAddr_[%{public}s]", GetEncryptAddr(HfpAgAudioConnection::GetActiveDevice()).c_str(),
324 GetEncryptAddr(dataConn.remoteAddr_).c_str());
325 SendErrorCode(dataConn, HFP_AG_ERROR_OPERATION_NOT_ALLOWED);
326 } else {
327 SendAtCommand(dataConn, OK);
328 HfpAgProfileEventSender::GetInstance().HangupCall(dataConn.remoteAddr_);
329 }
330 }
331
CindGetter(HfpAgDataConnection & dataConn,const std::string & arg)332 void HfpAgCommandProcessor::CindGetter(HfpAgDataConnection &dataConn, const std::string &arg)
333 {
334 HfpAgProfileEventSender::GetInstance().GetAgIndicator(dataConn.remoteAddr_);
335 }
336
CindTester(HfpAgDataConnection & dataConn,const std::string & arg)337 void HfpAgCommandProcessor::CindTester(HfpAgDataConnection &dataConn, const std::string &arg)
338 {
339 SendAtCommand(dataConn, "+CIND: " + HfpAgDataConnection::CIND_SETTINGS);
340 SendAtCommand(dataConn, OK);
341 }
342
ClipSetter(HfpAgDataConnection & dataConn,const std::string & arg)343 void HfpAgCommandProcessor::ClipSetter(HfpAgDataConnection &dataConn, const std::string &arg)
344 {
345 dataConn.clipEnabled_ = StoiTryCatch(dataConn, arg);
346 SendAtCommand(dataConn, OK);
347 }
348
CmerSetter(HfpAgDataConnection & dataConn,const std::string & arg)349 void HfpAgCommandProcessor::CmerSetter(HfpAgDataConnection &dataConn, const std::string &arg)
350 {
351 int data[CMER_ELEMENTS_NUMBER] = {-1, -1, -1, -1};
352 int offset = 0;
353
354 int res = sscanf_s(arg.c_str(), "%d,%d,%d,%d%n", &data[CMER_MODE_INDEX], &data[CMER_KEYP_INDEX],
355 &data[CMER_DISP_INDEX], &data[CMER_IND_INDEX], &offset);
356 HILOGI("[HFP AG]CmerSetter:(%{public}d,%{public}d,%{public}d,%{public}d), res:%{public}d), offset:%{public}d",
357 data[CMER_MODE_INDEX], data[CMER_KEYP_INDEX], data[CMER_DISP_INDEX], data[CMER_IND_INDEX], res, offset);
358 if (res != CMER_ELEMENTS_NUMBER || offset == 0) {
359 goto error;
360 } else {
361 if (data[CMER_MODE_INDEX] == CMER_MODE_FOR_HFP && data[CMER_IND_INDEX] == 1) {
362 dataConn.cmerEnabled_ = true;
363 } else if (data[CMER_MODE_INDEX] == CMER_MODE_FOR_HFP && data[CMER_IND_INDEX] == 0) {
364 dataConn.cmerEnabled_ = false;
365 } else {
366 goto error;
367 }
368 }
369
370 if (!dataConn.slcConnected_ && !((dataConn.g_localFeatures & HFP_AG_FEATURES_THREE_WAY) &&
371 (dataConn.remoteFeatures_ & HFP_AG_HF_FEATURES_THREE_WAY))) {
372 dataConn.SetSlcConnectState(true);
373 HfpAgProfileEventSender::GetInstance().UpdateConnectState(dataConn.remoteAddr_, HFP_AG_SLC_ESTABLISHED_EVT);
374 }
375 SendAtCommand(dataConn, OK);
376 return;
377
378 error:
379 SendAtCommand(dataConn, ERROR);
380 }
381
VtsSetter(HfpAgDataConnection & dataConn,const std::string & arg)382 void HfpAgCommandProcessor::VtsSetter(HfpAgDataConnection &dataConn, const std::string &arg)
383 {
384 if (arg.length() == 1) {
385 uint8_t code = arg[0];
386 if ((code >= '0' && code <= '9') || code == '*' || code == '#') {
387 HfpAgProfileEventSender::GetInstance().SendDtmf(dataConn.remoteAddr_, code);
388 } else {
389 goto error;
390 }
391 } else {
392 goto error;
393 }
394 return;
395
396 error:
397 SendErrorCode(dataConn, HFP_AG_ERROR_AG_FAILURE);
398 LOG_ERROR("[HFP HF]%{public}s():receive invalid dtmf code", __FUNCTION__);
399 }
400
BldnExecuter(HfpAgDataConnection & dataConn,const std::string & arg)401 void HfpAgCommandProcessor::BldnExecuter(HfpAgDataConnection &dataConn, const std::string &arg)
402 {
403 HfpAgProfileEventSender::GetInstance().DialOutCall(dataConn.remoteAddr_, "", HFP_AG_LAST_NUMBER_REDIAL);
404 }
405
BvraSetter(HfpAgDataConnection & dataConn,const std::string & arg)406 void HfpAgCommandProcessor::BvraSetter(HfpAgDataConnection &dataConn, const std::string &arg)
407 {
408 int bvra = StoiTryCatch(dataConn, arg);
409 HfpAgProfileEventSender::GetInstance().VoiceRecognitionStateChanged(dataConn.remoteAddr_, bvra);
410 }
411
BrsfSetter(HfpAgDataConnection & dataConn,const std::string & arg)412 void HfpAgCommandProcessor::BrsfSetter(HfpAgDataConnection &dataConn, const std::string &arg)
413 {
414 dataConn.remoteFeatures_ = StoiTryCatch(dataConn, arg);
415 uint32_t features = dataConn.g_localFeatures;
416 if (dataConn.sdpInfo_.remoteVersion < HFP_AG_HFP_VERSION_1_7) {
417 features &= HFP_AG_1_6_FEATURES_MASK;
418 }
419
420 std::string cmd = "+BRSF: " + std::to_string(features);
421 SendAtCommand(dataConn, cmd);
422 SendAtCommand(dataConn, OK);
423 }
424
NrecSetter(HfpAgDataConnection & dataConn,const std::string & arg)425 void HfpAgCommandProcessor::NrecSetter(HfpAgDataConnection &dataConn, const std::string &arg)
426 {
427 if (dataConn.g_localFeatures & HFP_AG_FEATURES_ECNR) {
428 int nrec = StoiTryCatch(dataConn, arg);
429 if (nrec == 0 || nrec == 1) {
430 SendAtCommand(dataConn, OK);
431 HfpAgProfileEventSender::GetInstance().EnableNoiseReduction(dataConn.remoteAddr_, nrec);
432 } else {
433 SendErrorCode(dataConn, HFP_AG_ERROR_AG_FAILURE);
434 }
435 } else {
436 SendErrorCode(dataConn, HFP_AG_ERROR_OPERATION_NOT_SUPPORTED);
437 }
438 }
439
CnumExecuter(HfpAgDataConnection & dataConn,const std::string & arg)440 void HfpAgCommandProcessor::CnumExecuter(HfpAgDataConnection &dataConn, const std::string &arg)
441 {
442 HfpAgProfileEventSender::GetInstance().GetSubscriberNumber(dataConn.remoteAddr_);
443 }
444
ClccExecuter(HfpAgDataConnection & dataConn,const std::string & arg)445 void HfpAgCommandProcessor::ClccExecuter(HfpAgDataConnection &dataConn, const std::string &arg)
446 {
447 if (!(dataConn.g_localFeatures & HFP_AG_FEATURES_ENHANCED_CALL_STATUS)) {
448 SendErrorCode(dataConn, HFP_AG_ERROR_AG_FAILURE);
449 return;
450 }
451 HfpAgProfileEventSender::GetInstance().GetCurrentCalls(dataConn.remoteAddr_);
452 }
453
CopsGetter(HfpAgDataConnection & dataConn,const std::string & arg)454 void HfpAgCommandProcessor::CopsGetter(HfpAgDataConnection &dataConn, const std::string &arg)
455 {
456 HfpAgProfileEventSender::GetInstance().GetNetworkOperater(dataConn.remoteAddr_);
457 }
458
CopsSetter(HfpAgDataConnection & dataConn,const std::string & arg)459 void HfpAgCommandProcessor::CopsSetter(HfpAgDataConnection &dataConn, const std::string &arg)
460 {
461 if (arg == "3,0") { // set name format to long alphanumeric
462 SendAtCommand(dataConn, OK);
463 } else {
464 SendErrorCode(dataConn, HFP_AG_ERROR_AG_FAILURE);
465 }
466 }
467
CmeeSetter(HfpAgDataConnection & dataConn,const std::string & arg)468 void HfpAgCommandProcessor::CmeeSetter(HfpAgDataConnection &dataConn, const std::string &arg)
469 {
470 if (dataConn.g_localFeatures & HFP_AG_FEATURES_EXTEND_ERROR_CODE) {
471 int cmee = StoiTryCatch(dataConn, arg);
472 dataConn.cmeeEnabled_ = static_cast<bool>(cmee);
473 SendAtCommand(dataConn, OK);
474 } else {
475 SendErrorCode(dataConn, HFP_AG_ERROR_OPERATION_NOT_SUPPORTED);
476 }
477 }
478
BiaSetter(HfpAgDataConnection & dataConn,const std::string & arg)479 void HfpAgCommandProcessor::BiaSetter(HfpAgDataConnection &dataConn, const std::string &arg)
480 {
481 size_t i;
482 int indId;
483 size_t len = arg.length();
484 int biaMaskOut = dataConn.biaMaskOut_;
485 for (i = 0, indId = 1; i < len && indId <= MAX_AG_INDICATORS; i++) {
486 if (arg.c_str()[i] == ',') {
487 indId++;
488 continue;
489 }
490
491 if (arg.c_str()[i] == '0') {
492 biaMaskOut |= 1 << indId;
493 } else if (arg.c_str()[i] == '1') {
494 biaMaskOut &= ~(1 << indId);
495 } else {
496 break;
497 }
498
499 if (i + 1 < len) {
500 if (arg.c_str()[i + 1] != ',') {
501 break;
502 }
503 } else {
504 continue;
505 }
506 }
507
508 LOG_INFO("[HFP AG]%{public}s(): i[%zu], indId[%{public}d], len[%zu]", __FUNCTION__, i, indId, len);
509
510 if (i == len) {
511 SendAtCommand(dataConn, OK);
512
513 dataConn.biaMaskOut_ = biaMaskOut;
514 bool service = !(biaMaskOut & (1 << HFP_AG_INDICATOR_SERVICE));
515 bool roam = !(biaMaskOut & (1 << HFP_AG_INDICATOR_ROAMING_STATE));
516 bool signal = !(biaMaskOut & (1 << HFP_AG_INDICATOR_SIGNAL_STRENGTH));
517 bool battery = !(biaMaskOut & (1 << HFP_AG_INDICATOR_BATTERY_LEVEL));
518
519 HfpAgTransferData data = {service, roam, signal, battery};
520 HfpAgProfileEventSender::GetInstance().ProcessAtBia(dataConn.remoteAddr_, data);
521 } else {
522 SendErrorCode(dataConn, HFP_AG_ERROR_INVALID_INDEX);
523 }
524 }
525
BccExecuter(HfpAgDataConnection & dataConn,const std::string & arg)526 void HfpAgCommandProcessor::BccExecuter(HfpAgDataConnection &dataConn, const std::string &arg)
527 {
528 if (HfpAgAudioConnection::GetActiveDevice().compare(dataConn.remoteAddr_) != 0) {
529 SendErrorCode(dataConn, HFP_AG_ERROR_OPERATION_NOT_ALLOWED);
530 HILOGI("[HFP AG] AT+BCC be rejected because activeAddr[%{public}s], remoteAddr[%{public}s]",
531 GetEncryptAddr(HfpAgAudioConnection::GetActiveDevice()).c_str(),
532 GetEncryptAddr(dataConn.remoteAddr_).c_str());
533 } else {
534 SendAtCommand(dataConn, OK);
535 HfpAgProfileEventSender::GetInstance().ProcessAtBcc(dataConn.remoteAddr_);
536 }
537 }
538
BcsSetter(HfpAgDataConnection & dataConn,const std::string & arg)539 void HfpAgCommandProcessor::BcsSetter(HfpAgDataConnection &dataConn, const std::string &arg)
540 {
541 dataConn.remoteSelectedCodec_ = StoiTryCatch(dataConn, arg);
542 dataConn.codecNegotiating_ = false;
543 if (dataConn.remoteSelectedCodec_ == dataConn.localSelectedCodec_) {
544 dataConn.inUseCodec_ = dataConn.remoteSelectedCodec_;
545 SendAtCommand(dataConn, OK);
546 HfpAgProfileEventSender::GetInstance().ProcessAtBcs(dataConn.remoteAddr_);
547 } else {
548 LOG_ERROR("[HFP AG]%{public}s():Setup code connection failed", __FUNCTION__);
549 SendErrorCode(dataConn, HFP_AG_ERROR_AG_FAILURE);
550 }
551 }
552
BindGetter(HfpAgDataConnection & dataConn,const std::string & arg)553 void HfpAgCommandProcessor::BindGetter(HfpAgDataConnection &dataConn, const std::string &arg)
554 {
555 std::string cmd;
556 for (auto &indicator : dataConn.localHfIndicators_) {
557 if (indicator.isSupported) {
558 cmd = "+BIND: " + std::to_string(indicator.anum) + "," + std::to_string(indicator.isEnabled);
559 SendAtCommand(dataConn, cmd);
560 }
561 }
562
563 if (!dataConn.slcConnected_) {
564 dataConn.SetSlcConnectState(true);
565 HfpAgProfileEventSender::GetInstance().UpdateConnectState(dataConn.remoteAddr_, HFP_AG_SLC_ESTABLISHED_EVT);
566 }
567 SendAtCommand(dataConn, OK);
568 }
569
BindSetter(HfpAgDataConnection & dataConn,const std::string & arg)570 void HfpAgCommandProcessor::BindSetter(HfpAgDataConnection &dataConn, const std::string &arg)
571 {
572 bool isFirst = true;
573 std::string event;
574 std::regex regex("\\,");
575 std::vector<std::string> out(
576 std::sregex_token_iterator(arg.begin(), arg.end(), regex, -1), std::sregex_token_iterator());
577 for (auto &s : out) {
578 HfpAgDataConnection::HfIndicator indicator;
579 indicator.anum = StoiTryCatch(dataConn, s);
580 dataConn.remoteHfIndicators_.push_back(indicator);
581 if (isFirst) {
582 event = event + std::to_string(indicator.anum);
583 } else {
584 event = "," + event + std::to_string(indicator.anum);
585 }
586 isFirst = false;
587 }
588
589 SendAtCommand(dataConn, OK);
590 HfpAgProfileEventSender::GetInstance().ProcessATBind(dataConn.remoteAddr_, event);
591 }
592
BindTester(HfpAgDataConnection & dataConn,const std::string & arg)593 void HfpAgCommandProcessor::BindTester(HfpAgDataConnection &dataConn, const std::string &arg)
594 {
595 bool isFirst = true;
596 std::string cmd;
597
598 for (auto &indicator : dataConn.localHfIndicators_) {
599 if (indicator.isSupported) {
600 if (isFirst) {
601 cmd = cmd + std::to_string(indicator.anum);
602 } else {
603 cmd = cmd + "," + std::to_string(indicator.anum);
604 }
605 isFirst = false;
606 }
607 }
608
609 cmd = "(" + cmd + ")";
610 cmd = "+BIND: " + cmd;
611 SendAtCommand(dataConn, cmd);
612 SendAtCommand(dataConn, OK);
613 }
614
BievSetter(HfpAgDataConnection & dataConn,const std::string & arg)615 void HfpAgCommandProcessor::BievSetter(HfpAgDataConnection &dataConn, const std::string &arg)
616 {
617 int index;
618 int anumOut;
619 uint16_t anum;
620 uint16_t value;
621 std::regex regex("\\,");
622 std::vector<std::string> out(
623 std::sregex_token_iterator(arg.begin(), arg.end(), regex, -1), std::sregex_token_iterator());
624 if (out.size() != BIEV_ARGS_VALID_LENGTH) {
625 goto INDEX_ERROR;
626 }
627
628 anumOut = StoiTryCatch(dataConn, out[0]);
629 if (anumOut <= 0 || anumOut > LOCAL_HF_IND_NUM) {
630 goto INDEX_ERROR;
631 } else {
632 anum = anumOut;
633 }
634
635 for (index = 0; index < static_cast<int>(dataConn.localHfIndicators_.size()); index++) {
636 if (anum == dataConn.localHfIndicators_[index].anum) {
637 break;
638 }
639 }
640
641 if (index == static_cast<int>(dataConn.localHfIndicators_.size()) ||
642 !dataConn.localHfIndicators_[index].isEnabled || !dataConn.localHfIndicators_[index].isSupported) {
643 goto INDEX_ERROR;
644 }
645
646 value = StoiTryCatch(dataConn, out[1]);
647 if (value < dataConn.localHfIndicators_[index].minVal || value > dataConn.localHfIndicators_[index].maxVal) {
648 SendErrorCode(dataConn, HFP_AG_ERROR_AG_FAILURE);
649 return;
650 } else {
651 SendAtCommand(dataConn, OK);
652 HfpAgProfileEventSender::GetInstance().SendHfIndicator(dataConn.remoteAddr_, ++index, value);
653 return;
654 }
655
656 INDEX_ERROR:
657 SendErrorCode(dataConn, HFP_AG_ERROR_INVALID_INDEX);
658 return;
659 }
660
BacSetter(HfpAgDataConnection & dataConn,const std::string & arg)661 void HfpAgCommandProcessor::BacSetter(HfpAgDataConnection &dataConn, const std::string &arg)
662 {
663 std::regex regex("\\,");
664 std::vector<std::string> out(
665 std::sregex_token_iterator(arg.begin(), arg.end(), regex, -1), std::sregex_token_iterator());
666
667 int currentRemoteCodec = HFP_AG_CODEC_NONE;
668 for (auto &s : out) {
669 if (s.find("1") != std::string::npos) {
670 currentRemoteCodec |= HFP_AG_CODEC_CVSD;
671 }
672 if (s.find("2") != std::string::npos) {
673 currentRemoteCodec |= HFP_AG_CODEC_MSBC;
674 }
675 }
676
677 if (currentRemoteCodec != dataConn.remoteSupportCodecs_) {
678 LOG_INFO("[HFP AG]%{public}s():Remote support codecs updated, currentRemoteCodec[%{public}d], "
679 "remoteSupportCodecs_[%{public}d]", __FUNCTION__, currentRemoteCodec, dataConn.remoteSupportCodecs_);
680 dataConn.remoteSupportCodecsUpdated_ = true;
681 }
682 dataConn.remoteSupportCodecs_ = currentRemoteCodec;
683
684 SendAtCommand(dataConn, OK);
685
686 // If no AT+BCS is received, but instead an AT+BAC is received after sending +BCS,
687 // the procedure shall end but may be restarted by the AG after re-selecting codec ID
688 // based on the information in the just received AT+BAC.
689 if (dataConn.codecNegotiating_) {
690 LOG_INFO("[HFP AG]%{public}s():Codec negotiation failed", __FUNCTION__);
691 HfpAgProfileEventSender::GetInstance().UpdateScoConnectState(
692 dataConn.remoteAddr_, HFP_AG_CODEC_NEGOTIATION_FAILED);
693 }
694 }
695
BtrhGetter(HfpAgDataConnection & dataConn,const std::string & arg)696 void HfpAgCommandProcessor::BtrhGetter(HfpAgDataConnection &dataConn, const std::string &arg)
697 {
698 LOG_INFO("[HFP AG]%{public}s():BtrhGetter arg = %{public}s", __FUNCTION__, arg.c_str());
699 HfpAgProfileEventSender::GetInstance().GetResponseHoldState(dataConn.remoteAddr_, HFP_AG_GET_BTRH_EVT);
700 }
701
BtrhSetter(HfpAgDataConnection & dataConn,const std::string & arg)702 void HfpAgCommandProcessor::BtrhSetter(HfpAgDataConnection &dataConn, const std::string &arg)
703 {
704 LOG_INFO("[HFP AG]%{public}s():BtrhSetter arg = %{public}s", __FUNCTION__, arg.c_str());
705 int btrh = StoiTryCatch(dataConn, arg);
706 HfpAgProfileEventSender::GetInstance().SetResponseHoldState(dataConn.remoteAddr_, HFP_AG_GET_BTRH_EVT, btrh);
707 }
708
BinpSetter(HfpAgDataConnection & dataConn,const std::string & arg)709 void HfpAgCommandProcessor::BinpSetter(HfpAgDataConnection &dataConn, const std::string &arg)
710 {
711 LOG_INFO("[HFP AG]%{public}s():BinpGetter arg = %{public}s", __FUNCTION__, arg.c_str());
712 HfpAgProfileEventSender::GetInstance().GetVoiceTagNumber(dataConn.remoteAddr_);
713 }
714
CkpdSetter(HfpAgDataConnection & dataConn,const std::string & arg)715 void HfpAgCommandProcessor::CkpdSetter(HfpAgDataConnection &dataConn, const std::string &arg)
716 {
717 SendAtCommand(dataConn, OK);
718 HfpAgProfileEventSender::GetInstance().ProcessCKpdEvent(dataConn.remoteAddr_);
719 }
720 } // namespace bluetooth
721 } // namespace OHOS