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_hf_command_processor.h"
17
18 #include <regex>
19
20 #include "adapter_config.h"
21 #include "hfp_hf_profile_event_sender.h"
22 #include "log.h"
23 #include "securec.h"
24
25 namespace OHOS {
26 namespace bluetooth {
27 std::unordered_map<std::string, HfpHfCommandProcessor::HfpHfAtHandler> HfpHfCommandProcessor::g_atCmdMap = {
28 std::make_pair<std::string, HfpHfAtHandler>("OK", {&HfpHfCommandProcessor::ProcessOK}),
29 std::make_pair<std::string, HfpHfAtHandler>("ERROR", {&HfpHfCommandProcessor::ProcessErrorCmd}),
30 std::make_pair<std::string, HfpHfAtHandler>("+CME ERROR:", {&HfpHfCommandProcessor::ProcessCmeError}),
31 std::make_pair<std::string, HfpHfAtHandler>("RING", {&HfpHfCommandProcessor::ProcessRing}),
32 std::make_pair<std::string, HfpHfAtHandler>("+CLIP:", {&HfpHfCommandProcessor::ProcessClip}),
33 std::make_pair<std::string, HfpHfAtHandler>("+BRSF:", {&HfpHfCommandProcessor::ProcessBrsf}),
34 std::make_pair<std::string, HfpHfAtHandler>("+CIND:", {&HfpHfCommandProcessor::ProcessCind}),
35 std::make_pair<std::string, HfpHfAtHandler>("+CHLD:", {&HfpHfCommandProcessor::ProcessChld}),
36 std::make_pair<std::string, HfpHfAtHandler>("+BIND:", {&HfpHfCommandProcessor::ProcessBind}),
37 std::make_pair<std::string, HfpHfAtHandler>("+CIEV:", {&HfpHfCommandProcessor::ProcessCiev}),
38 std::make_pair<std::string, HfpHfAtHandler>("+CCWA:", {&HfpHfCommandProcessor::ProcessCcwa}),
39 std::make_pair<std::string, HfpHfAtHandler>("+BCS:", {&HfpHfCommandProcessor::ProcessBcs}),
40 std::make_pair<std::string, HfpHfAtHandler>("+CLCC:", {&HfpHfCommandProcessor::ProcessClcc}),
41 std::make_pair<std::string, HfpHfAtHandler>("+BSIR:", {&HfpHfCommandProcessor::ProcessBsir}),
42 std::make_pair<std::string, HfpHfAtHandler>("+BVRA:", {&HfpHfCommandProcessor::ProcessBvra}),
43 std::make_pair<std::string, HfpHfAtHandler>("+CNUM:", {&HfpHfCommandProcessor::ProcessCnum}),
44 std::make_pair<std::string, HfpHfAtHandler>("+VGM:", {&HfpHfCommandProcessor::ProcessVgm}),
45 std::make_pair<std::string, HfpHfAtHandler>("+VGS:", {&HfpHfCommandProcessor::ProcessVgs}),
46 std::make_pair<std::string, HfpHfAtHandler>("+COPS:", {&HfpHfCommandProcessor::ProcessCops}),
47 std::make_pair<std::string, HfpHfAtHandler>("+BTRH:", {&HfpHfCommandProcessor::ProcessBtrh}),
48 std::make_pair<std::string, HfpHfAtHandler>("BUSY", {&HfpHfCommandProcessor::ProcessBusy}),
49 std::make_pair<std::string, HfpHfAtHandler>("DELAYED", {&HfpHfCommandProcessor::ProcessDelayed}),
50 std::make_pair<std::string, HfpHfAtHandler>("NO CARRIER", {&HfpHfCommandProcessor::ProcessNoCarrier}),
51 std::make_pair<std::string, HfpHfAtHandler>("NO ANSWER", {&HfpHfCommandProcessor::ProcessNoAnswer}),
52 std::make_pair<std::string, HfpHfAtHandler>("BLOCKLISTED", {&HfpHfCommandProcessor::ProcessBlocklisted}),
53 };
54
GetAtCmdMap()55 std::unordered_map<std::string, HfpHfCommandProcessor::HfpHfAtHandler> &HfpHfCommandProcessor::GetAtCmdMap()
56 {
57 return g_atCmdMap;
58 }
59
StoiTryCatch(const std::string & arg)60 int HfpHfCommandProcessor::StoiTryCatch(const std::string &arg)
61 {
62 try {
63 return std::stoi(arg);
64 } catch (std::exception &e) {
65 LOG_ERROR("[HFP HF]%{public}s():Catch exception %{public}s", __FUNCTION__, e.what());
66 return 0;
67 }
68 }
69
Init(const std::string & address)70 void HfpHfCommandProcessor::Init(const std::string& address)
71 {
72 this->address_ = address;
73 AdapterConfig::GetInstance()->GetValue(HSP_HS_STATE_SECTION_NAME, HSP_HS_STATE_PROPERY_NAME, hspState_);
74 respTimer_ = std::make_unique<utility::Timer>(std::bind(&HfpHfCommandProcessor::RespondTimeout, this));
75 }
76
ProcessCommand(HfpHfDataConnection & dataConn,const std::string & cmd,const std::string & arg)77 void HfpHfCommandProcessor::ProcessCommand(
78 HfpHfDataConnection &dataConn, const std::string &cmd, const std::string &arg)
79 {
80 LOG_DEBUG("[HFP HF]%{public}s():command[%{public}s], arg[%{public}s]", __FUNCTION__, cmd.c_str(), arg.c_str());
81
82 auto it = g_atCmdMap.find(cmd);
83 if (it == g_atCmdMap.end()) {
84 LOG_ERROR("[HFP HF]%{public}s():%{public}s command handler not found", __FUNCTION__, cmd.c_str());
85 return;
86 }
87
88 auto newArg = arg;
89 newArg.erase(remove_if(newArg.begin(), newArg.end(), isspace), newArg.end());
90
91 (this->*(it->second.fn))(dataConn, newArg);
92 }
93
ProcessOK(HfpHfDataConnection & dataConn,const std::string & arg)94 void HfpHfCommandProcessor::ProcessOK(HfpHfDataConnection &dataConn, const std::string &arg)
95 {
96 respTimer_->Stop();
97
98 if (!dataConn.slcConnected_) {
99 ConnectSlc(dataConn);
100 return;
101 }
102
103 HfpHfProfileEventSender &sender = HfpHfProfileEventSender::GetInstance();
104 switch (currentCommand_) {
105 case AT_COMMAND_NONE:
106 case AT_BIA_SETTER:
107 case AT_BCC_EXECUTER:
108 case AT_CLIP_SETTER:
109 case AT_BCS_SETTER:
110 break;
111 case AT_CLCC_EXECUTER:
112 sender.CurrentCallsReplyDone(dataConn.remoteAddr_);
113 break;
114 case AT_BVRA_1_SETTER:
115 sender.OpenVoiceRecognitionResult(dataConn.remoteAddr_, HFP_HF_AT_RESULT_OK);
116 break;
117 case AT_BVRA_0_SETTER:
118 sender.CloseVoiceRecognitionResult(dataConn.remoteAddr_, HFP_HF_AT_RESULT_OK);
119 break;
120 default:
121 sender.AtCmdResultReply(dataConn.remoteAddr_, HFP_HF_AT_RESULT_OK, 0);
122 break;
123 }
124
125 currentCommand_ = AT_COMMAND_NONE;
126 SendQueuedAtCommand(dataConn);
127 }
128
ProcessCmeError(HfpHfDataConnection & dataConn,const std::string & arg)129 void HfpHfCommandProcessor::ProcessCmeError(HfpHfDataConnection &dataConn, const std::string &arg)
130 {
131 const std::regex baseRegex("[^\\d]");
132 if (!std::regex_search(arg, baseRegex)) {
133 int errorCode = StoiTryCatch(arg);
134 if (errorCode != INVALID_CME_ERROR_CODE) {
135 ProcessErrorCode(dataConn, errorCode);
136 } else {
137 LOG_ERROR("[HFP HF]%{public}s():Invalid error code[%{public}s]", __FUNCTION__, arg.c_str());
138 }
139 } else {
140 LOG_ERROR("[HFP HF]%{public}s():Invalid error code[%{public}s]", __FUNCTION__, arg.c_str());
141 }
142 }
143
ProcessErrorCmd(HfpHfDataConnection & dataConn,const std::string & arg)144 void HfpHfCommandProcessor::ProcessErrorCmd(HfpHfDataConnection &dataConn, const std::string &arg)
145 {
146 ProcessErrorCode(dataConn, INVALID_CME_ERROR_CODE);
147 }
148
ProcessErrorCode(HfpHfDataConnection & dataConn,int errorCode)149 void HfpHfCommandProcessor::ProcessErrorCode(HfpHfDataConnection &dataConn, int errorCode)
150 {
151 respTimer_->Stop();
152
153 if (!dataConn.slcConnected_) {
154 ConnectSlc(dataConn);
155 return;
156 }
157
158 HfpHfProfileEventSender &sender = HfpHfProfileEventSender::GetInstance();
159 switch (currentCommand_) {
160 case AT_BIA_SETTER:
161 case AT_BCC_EXECUTER:
162 case AT_BCS_SETTER:
163 case AT_CLIP_SETTER:
164 break;
165 default:
166 if (errorCode == INVALID_CME_ERROR_CODE) {
167 sender.AtCmdResultReply(dataConn.remoteAddr_, HFP_HF_AT_RESULT_ERROR, 0);
168 } else {
169 sender.AtCmdResultReply(dataConn.remoteAddr_, HFP_HF_AT_RESULT_CME, errorCode);
170 }
171 break;
172 }
173
174 currentCommand_ = AT_COMMAND_NONE;
175 SendQueuedAtCommand(dataConn);
176 }
177
ProcessCops(HfpHfDataConnection & dataConn,const std::string & arg)178 void HfpHfCommandProcessor::ProcessCops(HfpHfDataConnection &dataConn, const std::string &arg)
179 {
180 uint8_t mode = 0;
181 char operatorName[OPERATOR_NAME_MAX_LEN] = {0}; // Operator name max length is 16
182
183 int res = sscanf_s(arg.c_str(), "%hhi,0,\"%16[^\"]\"", &mode, operatorName, sizeof(operatorName));
184 if (res < COPS_ARGS_NUMBER) {
185 LOG_WARN("[HFP HF]%{public}s():Invalid command format arg[%{public}s]", __FUNCTION__, arg.c_str());
186 return;
187 }
188
189 std::string name = std::string(operatorName);
190 HfpHfProfileEventSender::GetInstance().CurrentOperatorReply(dataConn.remoteAddr_, name);
191 }
192
ProcessBtrh(HfpHfDataConnection & dataConn,const std::string & arg)193 void HfpHfCommandProcessor::ProcessBtrh(HfpHfDataConnection &dataConn, const std::string &arg)
194 {
195 int response = 0;
196
197 int res = sscanf_s(arg.c_str(), "%d", &response);
198 if (res < 1) {
199 HILOGE("[HFP HF]ProcessBtrh failed, res:%{public}d, arg:%{public}s", res, arg.c_str());
200 return;
201 }
202
203 HfpHfProfileEventSender::GetInstance().HoldResultReply(dataConn.remoteAddr_, response);
204 }
205
ProcessBusy(HfpHfDataConnection & dataConn,const std::string & arg)206 void HfpHfCommandProcessor::ProcessBusy(HfpHfDataConnection &dataConn, const std::string &arg)
207 {
208 HfpHfProfileEventSender::GetInstance().AtCmdResultReply(
209 dataConn.remoteAddr_, HFP_HF_AT_RESULT_BUSY, INVALID_CME_ERROR_CODE);
210 }
211
ProcessDelayed(HfpHfDataConnection & dataConn,const std::string & arg)212 void HfpHfCommandProcessor::ProcessDelayed(HfpHfDataConnection &dataConn, const std::string &arg)
213 {
214 HfpHfProfileEventSender::GetInstance().AtCmdResultReply(
215 dataConn.remoteAddr_, HFP_HF_AT_RESULT_DELAYED, INVALID_CME_ERROR_CODE);
216 }
217
ProcessNoCarrier(HfpHfDataConnection & dataConn,const std::string & arg)218 void HfpHfCommandProcessor::ProcessNoCarrier(HfpHfDataConnection &dataConn, const std::string &arg)
219 {
220 HfpHfProfileEventSender::GetInstance().AtCmdResultReply(
221 dataConn.remoteAddr_, HFP_HF_AT_RESULT_NO_CARRIER, INVALID_CME_ERROR_CODE);
222 }
223
ProcessNoAnswer(HfpHfDataConnection & dataConn,const std::string & arg)224 void HfpHfCommandProcessor::ProcessNoAnswer(HfpHfDataConnection &dataConn, const std::string &arg)
225 {
226 HfpHfProfileEventSender::GetInstance().AtCmdResultReply(
227 dataConn.remoteAddr_, HFP_HF_AT_RESULT_NO_ANSWER, INVALID_CME_ERROR_CODE);
228 }
229
ProcessBlocklisted(HfpHfDataConnection & dataConn,const std::string & arg)230 void HfpHfCommandProcessor::ProcessBlocklisted(HfpHfDataConnection &dataConn, const std::string &arg)
231 {
232 HfpHfProfileEventSender::GetInstance().AtCmdResultReply(
233 dataConn.remoteAddr_, HFP_HF_AT_RESULT_BLOCKLISTED, INVALID_CME_ERROR_CODE);
234 }
235
ProcessRing(HfpHfDataConnection & dataConn,const std::string & arg)236 void HfpHfCommandProcessor::ProcessRing(HfpHfDataConnection &dataConn, const std::string &arg)
237 {
238 HfpHfProfileEventSender::GetInstance().RingIndicationNotify(dataConn.remoteAddr_);
239 }
240
ProcessClip(HfpHfDataConnection & dataConn,const std::string & arg)241 void HfpHfCommandProcessor::ProcessClip(HfpHfDataConnection &dataConn, const std::string &arg)
242 {
243 HfpHfProfileEventSender::GetInstance().Callinglineidentification(dataConn.remoteAddr_, arg);
244 }
245
ProcessBrsf(HfpHfDataConnection & dataConn,const std::string & arg)246 void HfpHfCommandProcessor::ProcessBrsf(HfpHfDataConnection &dataConn, const std::string &arg)
247 {
248 dataConn.remoteFeatures_ = StoiTryCatch(arg);
249 }
250
ProcessCindTester(HfpHfDataConnection & dataConn,std::string arg)251 void HfpHfCommandProcessor::ProcessCindTester(HfpHfDataConnection &dataConn, std::string arg)
252 {
253 int offset = 0;
254 uint32_t min = 0;
255 uint32_t max = 0;
256 uint32_t index = 0;
257 char name[INDICATOR_NAME_MAX_LEN] = {0};
258 const char *buf = arg.c_str();
259
260 for (; ;) {
261 auto res = sscanf_s(buf, "(\"%16[^\"]\",(%u%*[-,]%u))%n", name, sizeof(name), &min, &max, &offset);
262 LOG_DEBUG("[HFP HF]%{public}s():name[%{public}s], min[%u], max[%u], offset[%{public}d], res[%{public}d]",
263 __FUNCTION__, name, min, max, offset, res);
264 if (res != CHLD_TEST_ARGS_NUMBER) {
265 LOG_WARN("[HFP HF]%{public}s():invalid command name[%{public}s], min[%u], max[%u], offset[%{public}d], "
266 "res[%{public}d]", __FUNCTION__, name, min, max, offset, res);
267 return;
268 }
269
270 HfpHfDataConnection::AgIndicator indicator {name, ++index, min, max, 0, true};
271 dataConn.remoteAgIndicators_.push_back(indicator);
272
273 buf += offset;
274 if (*buf != ',') {
275 break;
276 }
277 buf++;
278 }
279 }
280
ProcessClcc(HfpHfDataConnection & dataConn,const std::string & arg)281 void HfpHfCommandProcessor::ProcessClcc(HfpHfDataConnection &dataConn, const std::string &arg)
282 {
283 uint16_t idx = 0;
284 uint16_t dir = 0;
285 uint16_t status = 0;
286 uint16_t mode = 0;
287 uint16_t mprty = 0;
288 char number[PHONE_NUMBER_MAX_LEN] = {0};
289 uint16_t type = 0;
290 int offset = 0;
291
292 const char *buf = arg.c_str();
293 int res = sscanf_s(buf, "%hu,%hu,%hu,%hu,%hu%n", &idx, &dir, &status, &mode, &mprty, &offset);
294 if (res < CLCC_ARGS_NUMBER || offset == 0) {
295 LOG_WARN("[HFP HF]%{public}s():Invalid command format arg[%{public}s]", __FUNCTION__, arg.c_str());
296 return;
297 }
298
299 buf += offset;
300 offset = 0;
301
302 /* check number and type */
303 if (*buf == ',') {
304 int res2 = sscanf_s(buf, ",\"%32[^\"]\",%hu%n", number, sizeof(number), &type, &offset);
305 if (res2 < 0) {
306 return;
307 }
308
309 if (res2 == 0) {
310 res2 = sscanf_s(buf, ",\"\",%hu%n", &type, &offset);
311 if (res2 < 0) {
312 return;
313 }
314
315 /* number match failed */
316 res2++;
317 number[0] = '\0';
318 }
319
320 if (res2 >= CHLD_SUB_ARGS_NUMBER) {
321 res += res2;
322 if (offset == 0) {
323 LOG_WARN("[HFP HF]%{public}s():Invalid command format arg[%{public}s]", __FUNCTION__, arg.c_str());
324 return;
325 }
326 }
327 }
328
329 HfpHfCurrentCallData callData {idx, dir, status, mode, mprty, "", 0};
330 if (res > CLCC_ARGS_NUMBER + 1) {
331 callData.number = number;
332 callData.type = type;
333 }
334 HfpHfProfileEventSender::GetInstance().CurrentCallsReply(dataConn.remoteAddr_, callData);
335 }
336
ProcessBsir(HfpHfDataConnection & dataConn,const std::string & arg)337 void HfpHfCommandProcessor::ProcessBsir(HfpHfDataConnection &dataConn, const std::string &arg)
338 {
339 int inBand = (arg.length() == 1) ? StoiTryCatch(arg) : 0;
340 HfpHfProfileEventSender::GetInstance().SetInBandRing(dataConn.remoteAddr_, inBand, false);
341 }
342
ProcessBvra(HfpHfDataConnection & dataConn,const std::string & arg)343 void HfpHfCommandProcessor::ProcessBvra(HfpHfDataConnection &dataConn, const std::string &arg)
344 {
345 int bvra = (arg.length() == 1) ? StoiTryCatch(arg) : 0;
346 HfpHfProfileEventSender::GetInstance().VoiceRecognitionChanged(dataConn.remoteAddr_, bvra);
347 }
348
ProcessCnum(HfpHfDataConnection & dataConn,const std::string & arg)349 void HfpHfCommandProcessor::ProcessCnum(HfpHfDataConnection &dataConn, const std::string &arg)
350 {
351 char number[PHONE_NUMBER_MAX_LEN] = {0};
352 uint16_t type;
353 // Indicates which service this phone number relates to. Shall be either 4 (voice) or 5 (fax).
354 uint16_t service = 0;
355
356 int res = sscanf_s(arg.c_str(), ",\"%32[^\"]\",%hu,,%hu", number, sizeof(number), &type, &service);
357 if (res < CNUM_ARGS_NUMBER) {
358 LOG_WARN("[HFP HF]%{public}s():Invalid command format arg[%{public}s]", __FUNCTION__, arg.c_str());
359 return;
360 }
361
362 HfpHfProfileEventSender::GetInstance().SubscriberNumberReply(dataConn.remoteAddr_, number, type);
363 }
364
ProcessCindGetter(HfpHfDataConnection & dataConn,std::string arg)365 void HfpHfCommandProcessor::ProcessCindGetter(HfpHfDataConnection &dataConn, std::string arg)
366 {
367 size_t index = 0;
368 uint32_t value = 0;
369 int offset = 0;
370 const char *buf = arg.c_str();
371
372 for (; ;) {
373 auto res = sscanf_s(buf, "%u%n", &value, &offset);
374 if (res != 1) {
375 LOG_WARN("[HFP HF]%{public}s():invalid command buf[%{public}s]", __FUNCTION__, buf);
376 return;
377 }
378
379 auto size = dataConn.remoteAgIndicators_.size();
380 if (index < size) {
381 if ((value >= dataConn.remoteAgIndicators_[index].minVal) &&
382 (value <= dataConn.remoteAgIndicators_[index].maxVal)) {
383 dataConn.remoteAgIndicators_[index].value = value;
384 } else {
385 dataConn.remoteAgIndicators_[index].value = dataConn.remoteAgIndicators_[index].minVal;
386 }
387 }
388
389 buf += offset;
390 if (*buf != ',') {
391 break;
392 }
393
394 index++;
395 buf++;
396 }
397
398 for (auto it = dataConn.remoteAgIndicators_.begin(); it != dataConn.remoteAgIndicators_.end(); ++it) {
399 ProcessIndicator(dataConn, *it, it->value);
400 }
401 }
402
ProcessCind(HfpHfDataConnection & dataConn,const std::string & arg)403 void HfpHfCommandProcessor::ProcessCind(HfpHfDataConnection &dataConn, const std::string &arg)
404 {
405 if (arg.at(0) == '(') {
406 // List items
407 ProcessCindTester(dataConn, arg);
408 } else {
409 // Get values
410 ProcessCindGetter(dataConn, arg);
411 }
412 }
413
ProcessChld(HfpHfDataConnection & dataConn,const std::string & arg)414 void HfpHfCommandProcessor::ProcessChld(HfpHfDataConnection &dataConn, const std::string &arg)
415 {
416 if (arg.length() < CHLD_ARGS_MIN_LENGTH) {
417 LOG_WARN("[HFP HF]%{public}s():Invalid Chld command [%{public}s] from Ag!", __FUNCTION__, arg.c_str());
418 }
419
420 std::string tmpStr = arg.substr(1, arg.length() - (CHLD_ARGS_MIN_LENGTH - 1));
421 std::regex regex("\\,");
422 std::vector<std::string> out(
423 std::sregex_token_iterator(tmpStr.begin(), tmpStr.end(), regex, -1), std::sregex_token_iterator());
424 for (auto s = out.begin(); s != out.end(); s++) {
425 if (*s == "0") {
426 dataConn.remoteChldFeatures_ |= CHLD_RELEASE_ALL;
427 } else if (*s == "1") {
428 dataConn.remoteChldFeatures_ |= CHLD_RELEASE_ALL_AND_ACCPET;
429 } else if (*s == "1x") {
430 dataConn.remoteChldFeatures_ |= CHLD_RELEASE_SPECIFIC;
431 } else if (*s == "2") {
432 dataConn.remoteChldFeatures_ |= CHLD_HOLD_ALL_AND_ACCPET;
433 } else if (*s == "2x") {
434 dataConn.remoteChldFeatures_ |= CHLD_HOLD_ALL_AND_PRIVATE;
435 } else if (*s == "3") {
436 dataConn.remoteChldFeatures_ |= CHLD_MERGE;
437 } else if (*s == "4") {
438 dataConn.remoteChldFeatures_ |= CHLD_EXPLICT_CALL_TRANSFER;
439 } else {
440 LOG_DEBUG("[HFP HF]%{public}s():Invalid Chld command [%{public}s] from Ag!", __FUNCTION__, (*s).c_str());
441 }
442 }
443 }
444
ProcessListHfIndicators(HfpHfDataConnection & dataConn,const std::string & arg)445 void HfpHfCommandProcessor::ProcessListHfIndicators(
446 HfpHfDataConnection &dataConn, const std::string &arg)
447 {
448 char anums[HF_INDICATOR_MAX] = {0}; // assume peer device support 20 hf indicators at most.
449
450 int res = sscanf_s(arg.c_str(), "(%20[^)]", anums, sizeof(anums));
451 if (res < 1) {
452 LOG_WARN("[HFP HF]%{public}s():invalid command arg[%{public}s]", __FUNCTION__, arg.c_str());
453 }
454
455 std::string tmpStr = anums;
456 std::regex regex("\\,");
457 std::vector<std::string> out(
458 std::sregex_token_iterator(tmpStr.begin(), tmpStr.end(), regex, -1), std::sregex_token_iterator());
459 for (auto &s : out) {
460 bool isExist = false;
461 uint16_t anum = StoiTryCatch(s);
462
463 auto it = std::find_if(dataConn.remoteHfIndicators_.begin(),
464 dataConn.remoteHfIndicators_.end(),
465 [&anum](const HfpHfDataConnection::HfIndicator &indicator) {
466 return indicator.anum == anum;
467 });
468
469 if (it != dataConn.remoteHfIndicators_.end()) {
470 isExist = true;
471 }
472
473 if (!isExist) {
474 HfpHfDataConnection::HfIndicator hfIndicator = {anum, 0, 0, 0, true, true};
475 dataConn.remoteHfIndicators_.push_back(hfIndicator);
476 }
477 }
478 }
479
ProcessChangeIndicatorState(HfpHfDataConnection & dataConn,const std::string & arg)480 void HfpHfCommandProcessor::ProcessChangeIndicatorState(
481 HfpHfDataConnection &dataConn, const std::string &arg)
482 {
483 uint16_t anum = 0;
484 uint16_t value = 0;
485
486 int res = sscanf_s(arg.c_str(), "%hu,%hu", &anum, &value);
487 if (res != BIND_SET_ARGS_NUMBER) {
488 LOG_WARN("[HFP HF]%{public}s():invalid command arg[%{public}s]", __FUNCTION__, arg.c_str());
489 }
490
491 for (auto &indicator : dataConn.remoteHfIndicators_) {
492 if (indicator.anum == anum) {
493 if (indicator.isEnabled == false && value == 1) {
494 std::string cmd = "AT+BIEV=" + std::to_string(anum) + "," +
495 std::to_string(dataConn.localHfIndicators_[anum - 1].value);
496 SendAtCommand(dataConn, cmd, HfpHfCommandProcessor::AT_BIEV_SETTER);
497 }
498 indicator.isEnabled = value;
499 }
500 }
501 }
502
ProcessBind(HfpHfDataConnection & dataConn,const std::string & arg)503 void HfpHfCommandProcessor::ProcessBind(HfpHfDataConnection &dataConn, const std::string &arg)
504 {
505 if (arg.length() >= 1 && arg[0] == '(') {
506 // List hf indicators
507 ProcessListHfIndicators(dataConn, arg);
508 } else {
509 // Enable/Disable hf indicator
510 ProcessChangeIndicatorState(dataConn, arg);
511 }
512 }
513
ProcessIndicator(HfpHfDataConnection & dataConn,HfpHfDataConnection::AgIndicator & it,uint32_t value)514 void HfpHfCommandProcessor::ProcessIndicator(
515 HfpHfDataConnection &dataConn, HfpHfDataConnection::AgIndicator &it, uint32_t value)
516 {
517 HfpHfProfileEventSender &sender = HfpHfProfileEventSender::GetInstance();
518
519 if ((value >= it.minVal) && (value <= it.maxVal)) {
520 auto valueOrgi = it.value;
521 it.value = value;
522 if (it.name == "service") {
523 sender.NetworkStateChanged(dataConn.remoteAddr_, value);
524 } else if (it.name == "call") {
525 sender.CallStateNotify(dataConn.remoteAddr_, value);
526 } else if (it.name == "callsetup") {
527 sender.CallSetupStateNotify(dataConn.remoteAddr_, value);
528 } else if (it.name == "callheld") {
529 sender.CallHeldStateNotify(dataConn.remoteAddr_, value);
530 } else if (it.name == "signal") {
531 sender.NetworkSignalChanged(dataConn.remoteAddr_, value);
532 } else if (it.name == "roam") {
533 sender.NetworkRoamingChanged(dataConn.remoteAddr_, value);
534 } else if (it.name == "battchg") {
535 sender.BatteryLevelChanged(dataConn.remoteAddr_, value);
536 } else {
537 it.value = valueOrgi;
538 LOG_WARN("[HFP HF]%{public}s():Invalid indicator name [%{public}s]", __FUNCTION__, it.name.c_str());
539 }
540 } else {
541 LOG_WARN("[HFP HF]%{public}s():Indicator value is not valid indicator[%{public}s], value[%u]",
542 __FUNCTION__,
543 it.name.c_str(),
544 value);
545 }
546 }
547
ProcessCiev(HfpHfDataConnection & dataConn,const std::string & arg)548 void HfpHfCommandProcessor::ProcessCiev(HfpHfDataConnection &dataConn, const std::string &arg)
549 {
550 uint32_t index = 0;
551 uint32_t value = 0;
552
553 int res = sscanf_s(arg.c_str(), "%u,%u", &index, &value);
554 if (res < CIEV_ARGS_NUMBER) {
555 LOG_WARN("[HFP HF]%{public}s():invalid command arg[%{public}s]", __FUNCTION__, arg.c_str());
556 }
557
558 auto it = std::find_if(dataConn.remoteAgIndicators_.begin(),
559 dataConn.remoteAgIndicators_.end(),
560 [&index](const HfpHfDataConnection::AgIndicator &indicator) {
561 return indicator.index == index;
562 });
563
564 if (it != dataConn.remoteAgIndicators_.end()) {
565 ProcessIndicator(dataConn, *it, value);
566 }
567 }
568
ProcessCcwa(HfpHfDataConnection & dataConn,const std::string & arg)569 void HfpHfCommandProcessor::ProcessCcwa(HfpHfDataConnection &dataConn, const std::string &arg)
570 {
571 char number[PHONE_NUMBER_MAX_LEN] = {0};
572 uint32_t type = 0;
573
574 int res = sscanf_s(arg.c_str(), "\"%32[^\"]\",%u", number, sizeof(number), &type);
575 if (res < CCWA_ARGS_NUMBER) {
576 LOG_WARN("[HFP HF]%{public}s():invalid command format arg[%{public}s]", __FUNCTION__, arg.c_str());
577 return;
578 }
579
580 HfpHfProfileEventSender::GetInstance().CallWaitingNotify(dataConn.remoteAddr_, std::string(number));
581 }
582
ProcessVgm(HfpHfDataConnection & dataConn,const std::string & arg)583 void HfpHfCommandProcessor::ProcessVgm(HfpHfDataConnection &dataConn, const std::string &arg)
584 {
585 int val = StoiTryCatch(arg);
586 HfpHfProfileEventSender::GetInstance().SetVolume(dataConn.remoteAddr_, HFP_HF_VOLUME_TYPE_MIC, val);
587 }
588
ProcessVgs(HfpHfDataConnection & dataConn,const std::string & arg)589 void HfpHfCommandProcessor::ProcessVgs(HfpHfDataConnection &dataConn, const std::string &arg)
590 {
591 int val = StoiTryCatch(arg);
592 HfpHfProfileEventSender::GetInstance().SetVolume(dataConn.remoteAddr_, HFP_HF_VOLUME_TYPE_SPK, val);
593 }
594
ProcessSlcBrsf(HfpHfDataConnection & dataConn)595 void HfpHfCommandProcessor::ProcessSlcBrsf(HfpHfDataConnection &dataConn)
596 {
597 if ((dataConn.g_localFeatures & HFP_HF_FEATURES_CODEC_NEGOTIATION) &&
598 (dataConn.remoteFeatures_ & HFP_HF_AG_FEATURES_CODEC_NEGOTIATION)) {
599 SendAtBacSetter(dataConn);
600 } else {
601 SendAtCindTester(dataConn);
602 }
603 }
ProcessSlcCmer(HfpHfDataConnection & dataConn)604 void HfpHfCommandProcessor::ProcessSlcCmer(HfpHfDataConnection &dataConn)
605 {
606 if ((dataConn.g_localFeatures & HFP_HF_FEATURES_THREE_WAY) &&
607 (dataConn.remoteFeatures_ & HFP_HF_AG_FEATURES_THREE_WAY)) {
608 SendAtChldTester(dataConn);
609 } else {
610 ProcessSlcConnected(dataConn);
611 }
612 }
ProcessSlcChld(HfpHfDataConnection & dataConn)613 void HfpHfCommandProcessor::ProcessSlcChld(HfpHfDataConnection &dataConn)
614 {
615 if ((dataConn.g_localFeatures & HFP_HF_FEATURES_HF_INDICATORS) &&
616 (dataConn.remoteFeatures_ & HFP_HF_AG_FEATURES_HF_INDICATORS)) {
617 SendAtBindSetter(dataConn);
618 } else {
619 ProcessSlcConnected(dataConn);
620 }
621 }
622
ProcessSlcConnected(HfpHfDataConnection & dataConn)623 void HfpHfCommandProcessor::ProcessSlcConnected(HfpHfDataConnection &dataConn)
624 {
625 HfpHfProfileEventSender &sender = HfpHfProfileEventSender::GetInstance();
626 dataConn.SetSlcConnectState(true);
627 sender.UpdateConnectState(dataConn.remoteAddr_, HFP_HF_SLC_ESTABLISHED_EVT);
628 currentCommand_ = AT_COMMAND_NONE;
629
630 if (dataConn.remoteFeatures_ & HFP_HF_AG_FEATURES_IN_BAND_RING) {
631 sender.SetInBandRing(dataConn.remoteAddr_, 1, true);
632 }
633
634 SendAtCommand(dataConn, "AT+COPS=3,0", HfpHfCommandProcessor::AT_COPS_SETTER);
635 SendAtBiaSetter(dataConn);
636 SendAtCommand(dataConn, "AT+CLIP=1", HfpHfCommandProcessor::AT_CLIP_SETTER);
637 SendAtCommand(dataConn, "AT+CCWA=1", HfpHfCommandProcessor::AT_CCWA_SETTER);
638 SendAtCommand(dataConn, "AT+CMEE=1", HfpHfCommandProcessor::AT_CCME_SETTER);
639
640 LOG_DEBUG("[HFP HF]%{public}s():Service level connection established!!!", __FUNCTION__);
641 }
642
ConnectSlc(HfpHfDataConnection & dataConn)643 void HfpHfCommandProcessor::ConnectSlc(HfpHfDataConnection &dataConn)
644 {
645 if (dataConn.slcConnected_) {
646 LOG_WARN("[HFP HF]%{public}s():Service level Connection already connected!!!", __FUNCTION__);
647 return;
648 }
649
650 LOG_DEBUG("[HFP HF]%{public}s():currentCommand_[%{public}d]", __FUNCTION__, currentCommand_);
651 switch (currentCommand_) {
652 case AT_COMMAND_NONE:
653 SendAtBrsfSetter(dataConn);
654 break;
655 case AT_BRSF_SETTER:
656 ProcessSlcBrsf(dataConn);
657 break;
658 case AT_BAC_SETTER:
659 SendAtCindTester(dataConn);
660 break;
661 case AT_CIND_TESTER:
662 SendAtCindGetter(dataConn);
663 break;
664 case AT_CIND_GETTER:
665 SendAtCmerSetter(dataConn);
666 break;
667 case AT_CMER_EXECUTER:
668 ProcessSlcCmer(dataConn);
669 break;
670 case AT_CHLD_TESTER:
671 ProcessSlcChld(dataConn);
672 break;
673 case AT_BIND_SETTER:
674 SendAtBindTester(dataConn);
675 break;
676 case AT_BIND_TESTER:
677 SendAtBindGetter(dataConn);
678 break;
679 case AT_BIND_GETTER:
680 ProcessSlcConnected(dataConn);
681 break;
682 default:
683 LOG_ERROR("[HFP HF]%{public}s():invalid commandId[%{public}d] in slc connection command",
684 __FUNCTION__, currentCommand_);
685 HfpHfProfileEventSender::GetInstance().UpdateConnectState(dataConn.remoteAddr_, HFP_HF_DISCONNECT_EVT);
686 break;
687 }
688 }
689
ProcessBcs(HfpHfDataConnection & dataConn,const std::string & arg)690 void HfpHfCommandProcessor::ProcessBcs(HfpHfDataConnection &dataConn, const std::string &arg)
691 {
692 dataConn.remoteSelectedCodec_ = StoiTryCatch(arg);
693 if (dataConn.remoteSelectedCodec_ & dataConn.g_localSupportCodecs) {
694 dataConn.inUseCodec_ = dataConn.remoteSelectedCodec_;
695 SendAtCommand(dataConn, "AT+BCS=" + arg, AT_BCS_SETTER);
696 } else {
697 /* Hfp profile 4.11.3
698 The AG shall always respond with OK if the ID received in AT+BCS is the same as the one sent,
699 and with ERROR otherwise. If no AT+BCS is received, but instead an AT+BAC is received after sending +BCS,
700 the procedure shall end but may be restarted by the AG after re-selecting codec ID based on the information
701 in the just received AT+BAC. */
702 SendAtBacSetter(dataConn);
703 LOG_ERROR("[HFP HF]%{public}s():Setup code connection failed, send BAC again!", __FUNCTION__);
704 }
705 }
706
SendAtBrsfSetter(HfpHfDataConnection & dataConn)707 void HfpHfCommandProcessor::SendAtBrsfSetter(HfpHfDataConnection &dataConn)
708 {
709 LOG_DEBUG("[HFP HF]%{public}s()", __FUNCTION__);
710 std::string cmd = "AT+BRSF=" + std::to_string(dataConn.g_localFeatures);
711 SendAtCommand(dataConn, cmd, AT_BRSF_SETTER);
712 }
713
SendAtBacSetter(HfpHfDataConnection & dataConn)714 void HfpHfCommandProcessor::SendAtBacSetter(HfpHfDataConnection &dataConn)
715 {
716 LOG_DEBUG("[HFP HF]%{public}s()", __FUNCTION__);
717 std::string cmd = "AT+BAC=";
718 if (dataConn.g_localFeatures & HFP_HF_FEATURES_CODEC_NEGOTIATION) {
719 cmd = cmd + "1,2";
720 } else {
721 cmd = cmd + "1";
722 }
723 SendAtCommand(dataConn, cmd, AT_BAC_SETTER);
724 }
725
SendAtCindTester(HfpHfDataConnection & dataConn)726 void HfpHfCommandProcessor::SendAtCindTester(HfpHfDataConnection &dataConn)
727 {
728 LOG_DEBUG("[HFP HF]%{public}s()", __FUNCTION__);
729 std::string cmd = "AT+CIND=?";
730 SendAtCommand(dataConn, cmd, AT_CIND_TESTER);
731 }
732
SendAtCindGetter(HfpHfDataConnection & dataConn)733 void HfpHfCommandProcessor::SendAtCindGetter(HfpHfDataConnection &dataConn)
734 {
735 LOG_DEBUG("[HFP HF]%{public}s()", __FUNCTION__);
736 std::string cmd = "AT+CIND?";
737 SendAtCommand(dataConn, cmd, AT_CIND_GETTER);
738 }
739
SendAtCmerSetter(HfpHfDataConnection & dataConn)740 void HfpHfCommandProcessor::SendAtCmerSetter(HfpHfDataConnection &dataConn)
741 {
742 LOG_DEBUG("[HFP HF]%{public}s()", __FUNCTION__);
743 std::string cmd = "AT+CMER=3,0,0,1";
744 SendAtCommand(dataConn, cmd, AT_CMER_EXECUTER);
745 }
746
SendAtChldTester(HfpHfDataConnection & dataConn)747 void HfpHfCommandProcessor::SendAtChldTester(HfpHfDataConnection &dataConn)
748 {
749 LOG_DEBUG("[HFP HF]%{public}s()", __FUNCTION__);
750 std::string cmd = "AT+CHLD=?";
751 SendAtCommand(dataConn, cmd, AT_CHLD_TESTER);
752 }
753
SendAtBindSetter(HfpHfDataConnection & dataConn)754 void HfpHfCommandProcessor::SendAtBindSetter(HfpHfDataConnection &dataConn)
755 {
756 LOG_DEBUG("[HFP HF]%{public}s()", __FUNCTION__);
757 std::string cmd = "AT+BIND=" + HfpHfDataConnection::BIND_SETTINGS;
758 SendAtCommand(dataConn, cmd, AT_BIND_SETTER);
759 }
760
SendAtBindGetter(HfpHfDataConnection & dataConn)761 void HfpHfCommandProcessor::SendAtBindGetter(HfpHfDataConnection &dataConn)
762 {
763 LOG_DEBUG("[HFP HF]%{public}s()", __FUNCTION__);
764 std::string cmd = "AT+BIND?";
765 SendAtCommand(dataConn, cmd, AT_BIND_GETTER);
766 }
767
SendAtBiaSetter(HfpHfDataConnection & dataConn)768 void HfpHfCommandProcessor::SendAtBiaSetter(HfpHfDataConnection &dataConn)
769 {
770 LOG_DEBUG("[HFP HF]%{public}s()", __FUNCTION__);
771
772 std::string cmd("AT+BIA=");
773 auto size = dataConn.remoteAgIndicators_.size();
774 for (size_t i = 0; i < size; i++) {
775 auto it = std::find_if(dataConn.remoteAgIndicators_.begin(),
776 dataConn.remoteAgIndicators_.end(),
777 [&i](const HfpHfDataConnection::AgIndicator &indicator) {
778 return i == indicator.index;
779 });
780
781 int value = 0;
782 if (it != dataConn.remoteAgIndicators_.end()) {
783 value = it->isEnabled ? 1 : 0;
784 }
785
786 if (i < size - 1) {
787 cmd.append(std::to_string(value) + ",");
788 } else {
789 cmd.append(std::to_string(value));
790 }
791 }
792 SendAtCommand(dataConn, cmd, HfpHfCommandProcessor::AT_BIA_SETTER);
793 }
794
SendAtBindTester(HfpHfDataConnection & dataConn)795 void HfpHfCommandProcessor::SendAtBindTester(HfpHfDataConnection &dataConn)
796 {
797 LOG_DEBUG("[HFP HF]%{public}s()", __FUNCTION__);
798 std::string cmd = "AT+BIND=?";
799 SendAtCommand(dataConn, cmd, AT_BIND_TESTER);
800 }
801
RespondTimeout()802 void HfpHfCommandProcessor::RespondTimeout()
803 {
804 LOG_DEBUG("[HFP HF]%{public}s()", __FUNCTION__);
805 if (hspState_ == HSP_HS_STATE_HSP) {
806 LOG_INFO("[HFP HF] hsp only remove time out");
807 return;
808 }
809 HfpHfProfileEventSender& instance = HfpHfProfileEventSender::GetInstance();
810 instance.GetDispatchter()->PostTask(
811 std::bind(&HfpHfProfileEventSender::UpdateConnectState, &instance, address_, HFP_HF_DISCONNECT_EVT));
812 }
813
SendAtCommand(HfpHfDataConnection & dataConn,const std::string & command,int commandId)814 void HfpHfCommandProcessor::SendAtCommand(
815 HfpHfDataConnection &dataConn, const std::string &command, int commandId)
816 {
817 std::string fullCommand(command + "\r");
818 if (currentCommand_ == AT_COMMAND_NONE || !dataConn.slcConnected_ || (hspState_ == HSP_HS_STATE_HSP)) {
819 LOG_DEBUG("[HFP HF]%{public}s(): commandId[%{public}d], command[%{public}s]",
820 __FUNCTION__, commandId, command.c_str());
821 currentCommand_ = commandId;
822 std::size_t cmdLength = fullCommand.length();
823 Packet *packet = PacketMalloc(0, 0, cmdLength);
824 Buffer *buf = PacketContinuousPayload(packet);
825 void *data = BufferPtr(buf);
826 if (memcpy_s(data, cmdLength, fullCommand.c_str(), cmdLength) != EOK) {
827 LOG_DEBUG("[HFP HF]%{public}s(): memcpy_s fail", __FUNCTION__);
828 return;
829 }
830 dataConn.WriteData(*packet);
831 PacketFree(packet);
832 respTimer_->Start(RESPOND_TIMEOUT_MS, false);
833 } else {
834 commandQueue_.push(std::make_tuple(command, commandId));
835 }
836 }
837
SendQueuedAtCommand(HfpHfDataConnection & dataConn)838 void HfpHfCommandProcessor::SendQueuedAtCommand(HfpHfDataConnection &dataConn)
839 {
840 if (commandQueue_.size() == 0) {
841 return;
842 }
843
844 auto command = commandQueue_.front();
845 commandQueue_.pop();
846 LOG_DEBUG(
847 "[HFP HF]%{public}s() commandId[%{public}d], command[%{public}s]",
848 __FUNCTION__, std::get<1>(command), std::get<0>(command).c_str());
849 SendAtCommand(dataConn, std::get<0>(command), std::get<1>(command));
850 }
851
CleanUp()852 void HfpHfCommandProcessor::CleanUp()
853 {
854 respTimer_->Stop();
855 commandQueue_ = {};
856 currentCommand_ = AT_COMMAND_NONE;
857 }
858 } // namespace bluetooth
859 } // namespace OHOS