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