1 /*
2  * Copyright (C) 2022 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 <cstring>
17 
18 #include "hid_host_service.h"
19 #include "hid_host_sdp_client.h"
20 
21 namespace OHOS {
22 namespace bluetooth {
HidHostSdpClient(std::string address)23 HidHostSdpClient::HidHostSdpClient(std::string address)
24 {
25     currentAddr_ = address;
26 }
27 
~HidHostSdpClient()28 HidHostSdpClient::~HidHostSdpClient()
29 {
30 }
31 
SdpCallback(const BtAddr * addr,const SdpService * serviceAry,uint16_t serviceNum,void * context)32 void HidHostSdpClient::SdpCallback(const BtAddr *addr, const SdpService *serviceAry, uint16_t serviceNum, void *context)
33 {
34     int result = HID_HOST_SDP_FAILD;
35     std::string address = RawAddress::ConvertToString(addr->addr).GetAddress();
36     if (context == nullptr) {
37         HidHostMessage event(HID_HOST_SDP_CMPL_EVT, result);
38         event.dev_ = address;
39         HidHostService::GetService()->PostEvent(event);
40         return;
41     }
42     HidHostSdpClient *sdpClient = static_cast<HidHostSdpClient *>(context);
43     sdpClient->SdpCallback_(addr, serviceAry, serviceNum);
44 }
45 
SdpCallback_(const BtAddr * addr,const SdpService * serviceAry,uint16_t serviceNum)46 void HidHostSdpClient::SdpCallback_(const BtAddr *addr, const SdpService *serviceAry, uint16_t serviceNum)
47 {
48     LOG_DEBUG("[HIDH SDP]%{public}s()", __FUNCTION__);
49     int result = HID_HOST_SDP_FAILD;
50     std::string address = RawAddress::ConvertToString(addr->addr).GetAddress();
51     if (serviceNum > 0) {
52         if (serviceAry[0].serviceName != nullptr) {
53             hidInf_.serviceName = serviceAry[0].serviceName;
54         } else {
55             hidInf_.serviceName = "";
56         }
57         if (serviceAry[0].serviceDescription != nullptr) {
58             hidInf_.serviceDescription = serviceAry[0].serviceDescription;
59         } else {
60             hidInf_.serviceDescription = "";
61         }
62         if (serviceAry[0].providerName != nullptr) {
63             hidInf_.providerName = serviceAry[0].providerName;
64         } else {
65             hidInf_.providerName = "";
66         }
67         if (!ParseHidDescInfo(serviceAry)) {
68             return;
69         }
70         for (uint16_t i = 0; i < serviceAry[0].attributeNumber; i++) {
71             SdpAttribute attribute = serviceAry[0].attribute[i];
72             if (attribute.attributeId == ATTR_ID_HID_COUNTRY_CODE &&
73                 attribute.attributeValueLength == HID_HOST_ATTRIBUTE_LENGTH_UINT8) {
74                 hidInf_.ctryCode = *static_cast<uint8_t*>(serviceAry[0].attribute[i].attributeValue);
75             } else {
76                 LOG_ERROR("[HIDH SDP]%{public}s() attribute length is error!", __FUNCTION__);
77             }
78         }
79         result = HID_HOST_SDP_SUCCESS;
80         isSdpDone_ = true;
81         printHidSdpInfo();
82     }
83     SendSdpComplete(result);
84 }
85 
ParseHidDescInfo(const SdpService * serviceAry)86 bool HidHostSdpClient::ParseHidDescInfo(const SdpService *serviceAry)
87 {
88     int result = HID_HOST_SDP_FAILD;
89     for (uint16_t i = 0; i < serviceAry[0].sequenceAttributeNumber; i++) {
90         SdpSequenceAttribute attribute = serviceAry[0].sequenceAttribute[i];
91         uint8_t offset = CheckAttributeValueLengthAvalid(attribute);
92         if (offset != 0) {
93             uint8_t *attributeValue = attribute.attributeValue + offset;
94             uint8_t type = attributeValue[0] >> HID_SDP_DESCRIPTOR_SIZE_BIT;
95             uint8_t size = attributeValue[0] & SDP_SIZE_MASK;
96             uint16_t descLength = 0;
97             if ((type  == SDP_DE_TYPE_STRING) && (size == SDP_DE_SIZE_VAR_8)) {
98                 descLength = attributeValue[1];
99                 offset = SDP_UINT8_LENGTH + 1;
100             } else if ((type  == SDP_DE_TYPE_STRING) && (size == SDP_DE_SIZE_VAR_16)) {
101                 offset = 1;
102                 descLength = (attributeValue[offset] << ONE_BYTE_OFFSET) | attributeValue[offset + 1];
103                 offset = SDP_UINT16_LENGTH + 1;
104             } else {
105                 LOG_ERROR("[HIDH SDP]%{public}s() error type or size!", __FUNCTION__);
106                 SendSdpComplete(result);
107                 offset = 0;
108                 return false;
109             }
110             if (descLength <= 0) {
111                 LOG_ERROR("[HIDH SDP]%{public}s() length is 0!", __FUNCTION__);
112                 SendSdpComplete(result);
113                 offset = 0;
114                 return false;
115             }
116             hidInf_.descInfo = std::make_unique<uint8_t[]>(descLength);
117             if (memcpy_s(hidInf_.descInfo.get(), descLength, attributeValue + offset, descLength) != EOK) {
118                 LOG_ERROR("[HIDH SDP]%{public}s() memcpy error", __FUNCTION__);
119                 SendSdpComplete(result);
120                 return false;
121             }
122             hidInf_.descLength = descLength;
123             return true;
124         }
125     }
126     LOG_ERROR("[HIDH SDP]%{public}s() not find hid descriptor list!", __FUNCTION__);
127     SendSdpComplete(result);
128     return false;
129 }
130 
CheckAttributeValueLengthAvalid(SdpSequenceAttribute attribute)131 uint8_t HidHostSdpClient::CheckAttributeValueLengthAvalid(SdpSequenceAttribute attribute)
132 {
133     int result = HID_HOST_SDP_FAILD;
134     uint8_t offset = 0;
135     if (attribute.attributeId == ATTR_ID_HID_DESCRIPTOR_LIST) {
136         if (attribute.attributeValueLength > DESCRIPTOR_LIST_SDP_HEAD_LENGTH) {
137             if ((attribute.attributeValue[0] & SDP_SIZE_MASK) == SDP_DE_SIZE_VAR_8) {
138                 offset = DESCRIPTOR_LIST_SDP_OFFSET;
139             } else if ((attribute.attributeValue[0] & SDP_SIZE_MASK) == SDP_DE_SIZE_VAR_16) {
140                 offset = DESCRIPTOR_LIST_SDP_OFFSET + 1;
141             } else {
142                 LOG_ERROR("[HIDH SDP]%{public}s() first error size!", __FUNCTION__);
143                 SendSdpComplete(result);
144                 return offset;
145             }
146         } else {
147             LOG_ERROR("[HIDH SDP]%{public}s() attribute length is error!", __FUNCTION__);
148             SendSdpComplete(result);
149             return offset;
150         }
151     } else {
152         LOG_ERROR("[HIDH SDP]%{public}s() attribute id is invalid!", __FUNCTION__);
153     }
154     return offset;
155 }
156 
SendSdpComplete(int result)157 void HidHostSdpClient::SendSdpComplete(int result)
158 {
159     HidHostMessage event(HID_HOST_SDP_CMPL_EVT, result);
160     event.dev_ = currentAddr_;
161     HidHostService::GetService()->PostEvent(event);
162 }
163 
printHidSdpInfo()164 void HidHostSdpClient::printHidSdpInfo()
165 {
166     LOG_DEBUG("[HIDH SDP]%{public}s()", __FUNCTION__);
167     LOG_DEBUG("[HIDH SDP]supTimeout:0x%{public}x,MaxLatency:0x%{public}x,MinTout:0x%{public}x,hparsVer:0x%{public}x",
168         hidInf_.supTimeout, hidInf_.ssrMaxLatency, hidInf_.ssrMinTout, hidInf_.hparsVer);
169     LOG_DEBUG("[HIDH SDP]relNum:0x%{public}x,ctryCode:0x%{public}x,subClass:0x%{public}x,descLength:%{public}d",
170         hidInf_.relNum, hidInf_.ctryCode, hidInf_.subClass, hidInf_.descLength);
171     LOG_DEBUG("[HIDH SDP]serviceName:%{public}s,serviceDescription:%{public}s,providerName:%{public}s",
172         hidInf_.serviceName.c_str(), hidInf_.serviceDescription.c_str(), hidInf_.providerName.c_str());
173 }
174 
SdpPnpCallback(const BtAddr * addr,const SdpService * serviceAry,uint16_t serviceNum,void * context)175 void HidHostSdpClient::SdpPnpCallback(const BtAddr *addr, const SdpService *serviceAry,
176     uint16_t serviceNum, void *context)
177 {
178     std::string address = RawAddress::ConvertToString(addr->addr).GetAddress();
179     int result = HID_HOST_SDP_FAILD;
180     if (context == nullptr) {
181         HidHostMessage event(HID_HOST_SDP_CMPL_EVT, result);
182         event.dev_ = address;
183         HidHostService::GetService()->PostEvent(event);
184         return;
185     }
186     HidHostSdpClient *sdpClient = static_cast<HidHostSdpClient *>(context);
187     sdpClient->SdpPnpCallback_(addr, serviceAry, serviceNum);
188 }
189 
SdpPnpCallback_(const BtAddr * addr,const SdpService * serviceAry,uint16_t serviceNum)190 void HidHostSdpClient::SdpPnpCallback_(const BtAddr *addr, const SdpService *serviceAry, uint16_t serviceNum)
191 {
192     LOG_DEBUG("[HIDH SDP]%{public}s()", __FUNCTION__);
193     std::string address = RawAddress::ConvertToString(addr->addr).GetAddress();
194     int result = HID_HOST_SDP_FAILD;
195 
196     if (serviceNum > 0) {
197         for (uint16_t i = 0; i < serviceAry[0].attributeNumber; i++) {
198             SdpAttribute attribute = serviceAry[0].attribute[i];
199             if (attribute.attributeId == SDP_ATTRIBUTE_VENDOR_ID &&
200                 attribute.attributeValueLength == HID_HOST_ATTRIBUTE_LENGTH_UINT16) {
201                 pnpInf_.vendorId = *static_cast<uint16_t*>(serviceAry[0].attribute[i].attributeValue);
202                 LOG_DEBUG("[HIDH SDP]%{public}s():vendorId = 0x%{public}x", __FUNCTION__, pnpInf_.vendorId);
203             }
204 
205             if (attribute.attributeId == SDP_ATTRIBUTE_PRODUCT_ID &&
206                 attribute.attributeValueLength == HID_HOST_ATTRIBUTE_LENGTH_UINT16) {
207                 pnpInf_.productId = *static_cast<uint16_t*>(serviceAry[0].attribute[i].attributeValue);
208                 LOG_DEBUG("[HIDH SDP]%{public}s():productId = 0x%{public}x", __FUNCTION__, pnpInf_.productId);
209             }
210 
211             if (attribute.attributeId == SDP_ATTRIBUTE_VERSION &&
212                 attribute.attributeValueLength == HID_HOST_ATTRIBUTE_LENGTH_UINT16) {
213                 pnpInf_.version = *static_cast<uint16_t*>(serviceAry[0].attribute[i].attributeValue);
214                 LOG_DEBUG("[HIDH SDP]%{public}s():version = 0x%{public}x", __FUNCTION__, pnpInf_.version);
215             }
216         }
217         result = HID_HOST_SDP_SUCCESS;
218         isPnpSdpDone_ = true;
219     }
220     HidHostMessage event(HID_HOST_SDP_CMPL_EVT, result);
221     event.dev_ = currentAddr_;
222     HidHostService::GetService()->PostEvent(event);
223 }
224 
DoDiscovery(const std::string & remoteAddr)225 int HidHostSdpClient::DoDiscovery(const std::string &remoteAddr)
226 {
227     if (isPnpSdpDone_) {
228         return DoHidDiscovery(remoteAddr);
229     }
230     return DoPnpDiscovery(remoteAddr);
231 }
232 
DoPnpDiscovery(const std::string & remoteAddr)233 int HidHostSdpClient::DoPnpDiscovery(const std::string &remoteAddr)
234 {
235     BtAddr address;
236     address.type = BT_PUBLIC_DEVICE_ADDRESS;
237     RawAddress rawAddr(remoteAddr);
238     rawAddr.ConvertToUint8(address.addr);
239 
240     BtUuid classid[HID_HOST_CLASSID_NUM];
241     classid[0].type = BT_UUID_16;
242     classid[0].uuid16 = HID_HOST_UUID_SERVCLASS_PNP;
243     SdpUuid sdpUUid;
244     sdpUUid.uuidNum = HID_HOST_CLASSID_NUM;
245     sdpUUid.uuid = &classid[0];
246 
247     SdpAttributeIdList attributeIdList;
248     attributeIdList.type = SDP_TYPE_RANGE;
249     attributeIdList.attributeIdRange.start = 0x0000;
250     attributeIdList.attributeIdRange.end = 0xFFFF;
251 
252     int ret = SDP_ServiceSearchAttribute(&address, &sdpUUid, attributeIdList, this, SdpPnpCallback);
253     if (ret != BT_SUCCESS) {
254         LOG_ERROR("[HIDH SDP]%{public}s():SDP_ServiceSearchAttribute failed!", __FUNCTION__);
255     }
256     currentAddr_ = remoteAddr;
257     return ret;
258 }
259 
DoHidDiscovery(const std::string & remoteAddr)260 int HidHostSdpClient::DoHidDiscovery(const std::string &remoteAddr)
261 {
262     BtAddr address;
263     address.type = BT_PUBLIC_DEVICE_ADDRESS;
264     RawAddress rawAddr(remoteAddr);
265     rawAddr.ConvertToUint8(address.addr);
266 
267     BtUuid classid[HID_HOST_CLASSID_NUM];
268     classid[0].type = BT_UUID_16;
269     classid[0].uuid16 = HID_HOST_UUID_SERVCLASS_HID;
270     SdpUuid sdpUUid;
271     sdpUUid.uuidNum = HID_HOST_CLASSID_NUM;
272     sdpUUid.uuid = &classid[0];
273 
274     SdpAttributeIdList attributeIdList;
275     attributeIdList.type = SDP_TYPE_LIST;
276     int attributeIdNumber = 0;
277     attributeIdList.attributeIdList.attributeId[attributeIdNumber++] =
278         SDP_ATTRIBUTE_PRIMARY_LANGUAGE_BASE + SDP_ATTRIBUTE_PROVIDER_NAME;
279     attributeIdList.attributeIdList.attributeId[attributeIdNumber++] =
280         SDP_ATTRIBUTE_PRIMARY_LANGUAGE_BASE + SDP_ATTRIBUTE_SERVICE_NAME;
281     attributeIdList.attributeIdList.attributeId[attributeIdNumber++] =
282         SDP_ATTRIBUTE_PRIMARY_LANGUAGE_BASE + SDP_ATTRIBUTE_DESCRIPTOR;
283     attributeIdList.attributeIdList.attributeId[attributeIdNumber++] = ATTR_ID_HID_COUNTRY_CODE;
284     attributeIdList.attributeIdList.attributeId[attributeIdNumber++] = ATTR_ID_HID_DESCRIPTOR_LIST;
285     attributeIdList.attributeIdList.attributeIdNumber = attributeIdNumber;
286 
287     int ret = SDP_ServiceSearchAttribute(&address, &sdpUUid, attributeIdList, this, SdpCallback);
288     if (ret != BT_SUCCESS) {
289         LOG_ERROR("[HIDH SDP]%{public}s():SDP_ServiceSearchAttribute failed!", __FUNCTION__);
290     }
291     return ret;
292 }
293 
CheckIsSdpDone()294 bool HidHostSdpClient::CheckIsSdpDone()
295 {
296     return isSdpDone_;
297 }
298 
GetRemoteSdpPnpInfo()299 PnpInformation& HidHostSdpClient::GetRemoteSdpPnpInfo()
300 {
301     return pnpInf_;
302 }
303 
GetRemoteSdpHidInfo()304 HidInformation& HidHostSdpClient::GetRemoteSdpHidInfo()
305 {
306     return hidInf_;
307 }
308 }  // namespace bluetooth
309 }  // namespace OHOS
310