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_parser.h"
17
18 #include <cstring>
19
20 #include "hfp_hf_defines.h"
21 #include "packet.h"
22
23 namespace OHOS {
24 namespace bluetooth {
GetInstance()25 HfpHfCommandParser &HfpHfCommandParser::GetInstance()
26 {
27 static HfpHfCommandParser instance;
28 return instance;
29 }
30
Read(HfpHfDataConnection & dataConn,HfpHfCommandProcessor & commandProcessor)31 void HfpHfCommandParser::Read(
32 HfpHfDataConnection &dataConn, HfpHfCommandProcessor &commandProcessor)
33 {
34 Packet *pkt = nullptr;
35 Buffer *buf = nullptr;
36 uint8_t *pData = nullptr;
37
38 dataConn.ReadData(&pkt);
39 if (pkt != nullptr) {
40 auto len = PacketPayloadSize(pkt);
41 buf = PacketContinuousPayload(pkt);
42 pData = (uint8_t *)BufferPtr(buf);
43
44 std::vector<uint8_t> data(pData, pData + len);
45 Parse(dataConn, commandProcessor, data, len);
46 PacketFree(pkt);
47 }
48 }
49
ParseBody(HfpHfDataConnection & dataConn,HfpHfCommandProcessor & commandProcessor,std::vector<uint8_t> & data,size_t & pos,const size_t len)50 void HfpHfCommandParser::ParseBody(HfpHfDataConnection &dataConn,
51 HfpHfCommandProcessor &commandProcessor, std::vector<uint8_t> &data, size_t &pos, const size_t len)
52 {
53 for (auto &it : g_atCmdMap) {
54 if (!strncmp(it.first.c_str(), (char *)(&data[pos]), it.first.length())) {
55 // command body matched
56 size_t bodyPos = pos;
57 while (!(data[pos] == '\r' && data[pos + 1] == '\n')) {
58 pos++;
59 }
60
61 if (pos + 1 < len) {
62 // command tail "\r\n" matched
63 size_t tailPos = pos;
64 pos++;
65 std::string arg {(char *)&data[bodyPos + it.first.length()], tailPos - it.first.length() - bodyPos};
66 LOG_DEBUG("[HFP HF]%{public}s():cmd[%{public}s], arg[%{public}s]",
67 __FUNCTION__, it.first.c_str(), arg.c_str());
68 commandProcessor.ProcessCommand(dataConn, it.first, arg);
69 break;
70 } else {
71 LOG_DEBUG("[HFP HF]%{public}s():Command format invalid!", __FUNCTION__);
72 break;
73 }
74 }
75 }
76 }
77
Parse(HfpHfDataConnection & dataConn,HfpHfCommandProcessor & commandProcessor,std::vector<uint8_t> & data,size_t len)78 void HfpHfCommandParser::Parse(HfpHfDataConnection &dataConn,
79 HfpHfCommandProcessor &commandProcessor, std::vector<uint8_t> &data, size_t len)
80 {
81 if (data.empty() == true) {
82 LOG_DEBUG("[HFP HF]%{public}s():data is nullptr", __FUNCTION__);
83 return;
84 }
85
86 for (size_t pos = 0; pos < len; pos++) {
87 // skip null characters
88 if (data[pos] == '\0') {
89 continue;
90 }
91
92 if (pos + 1 < len && (data[pos] == '\r' && data[pos + 1] == '\n')) {
93 // command head "\r\n" matched, skip it
94 pos += AT_HEAD_SIZE;
95 ParseBody(dataConn, commandProcessor, data, pos, len);
96 }
97 }
98 return;
99 }
100 } // namespace bluetooth
101 } // namespace OHOS