1 /******************************************************************************
2 *
3 * Copyright 1999-2012 Broadcom Corporation
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 ******************************************************************************/
18
19 /******************************************************************************
20 *
21 * This file contains SDP utility functions
22 *
23 ******************************************************************************/
24
25 #include <stdio.h>
26 #include <string.h>
27 #include <utility>
28 #include <vector>
29
30 #include "bt_common.h"
31 #include "bt_types.h"
32 #include "btif_config.h"
33
34 #include "sdp_api.h"
35 #include "sdpint.h"
36
37 #include "common/metrics.h"
38
39 using bluetooth::Uuid;
40 static const uint8_t sdp_base_uuid[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
41 0x10, 0x00, 0x80, 0x00, 0x00, 0x80,
42 0x5F, 0x9B, 0x34, 0xFB};
43
44 template <typename T>
to_little_endian_array(T x)45 static std::array<char, sizeof(T)> to_little_endian_array(T x) {
46 static_assert(std::is_integral<T>::value,
47 "to_little_endian_array parameter must be integral.");
48 std::array<char, sizeof(T)> array = {};
49 for (size_t i = 0; i < array.size(); i++) {
50 array[i] = static_cast<char>((x >> (8 * i)) & 0xFF);
51 }
52 return array;
53 }
54
55 /**
56 * Find the list of profile versions from Bluetooth Profile Descriptor list
57 * attribute in a SDP record
58 *
59 * @param p_rec SDP record to search
60 * @return a vector of <UUID, VERSION> pairs, empty if not found
61 */
sdpu_find_profile_version(tSDP_DISC_REC * p_rec)62 static std::vector<std::pair<uint16_t, uint16_t>> sdpu_find_profile_version(
63 tSDP_DISC_REC* p_rec) {
64 std::vector<std::pair<uint16_t, uint16_t>> result;
65 for (tSDP_DISC_ATTR* p_attr = p_rec->p_first_attr; p_attr != nullptr;
66 p_attr = p_attr->p_next_attr) {
67 // Find the profile descriptor list */
68 if (p_attr->attr_id != ATTR_ID_BT_PROFILE_DESC_LIST ||
69 SDP_DISC_ATTR_TYPE(p_attr->attr_len_type) != DATA_ELE_SEQ_DESC_TYPE) {
70 continue;
71 }
72 // Walk through the protocol descriptor list
73 for (tSDP_DISC_ATTR* p_sattr = p_attr->attr_value.v.p_sub_attr;
74 p_sattr != nullptr; p_sattr = p_sattr->p_next_attr) {
75 // Safety check - each entry should itself be a sequence
76 if (SDP_DISC_ATTR_TYPE(p_sattr->attr_len_type) !=
77 DATA_ELE_SEQ_DESC_TYPE) {
78 LOG(WARNING) << __func__ << ": Descriptor type is not sequence: "
79 << loghex(SDP_DISC_ATTR_TYPE(p_sattr->attr_len_type));
80 return std::vector<std::pair<uint16_t, uint16_t>>();
81 }
82 // Now, see if the entry contains the profile UUID we are interested in
83 for (tSDP_DISC_ATTR* p_ssattr = p_sattr->attr_value.v.p_sub_attr;
84 p_ssattr != nullptr; p_ssattr = p_ssattr->p_next_attr) {
85 if (SDP_DISC_ATTR_TYPE(p_ssattr->attr_len_type) != UUID_DESC_TYPE ||
86 SDP_DISC_ATTR_LEN(p_ssattr->attr_len_type) != 2) {
87 continue;
88 }
89 uint16_t uuid = p_ssattr->attr_value.v.u16;
90 // Next attribute should be the version attribute
91 tSDP_DISC_ATTR* version_attr = p_ssattr->p_next_attr;
92 if (SDP_DISC_ATTR_TYPE(version_attr->attr_len_type) != UINT_DESC_TYPE ||
93 SDP_DISC_ATTR_LEN(version_attr->attr_len_type) != 2) {
94 LOG(WARNING) << __func__ << ": Bad version type "
95 << loghex(
96 SDP_DISC_ATTR_TYPE(version_attr->attr_len_type))
97 << ", or length "
98 << SDP_DISC_ATTR_LEN(version_attr->attr_len_type);
99 return std::vector<std::pair<uint16_t, uint16_t>>();
100 }
101 // High order 8 bits is the major number, low order is the
102 // minor number (big endian)
103 uint16_t version = version_attr->attr_value.v.u16;
104 result.emplace_back(uuid, version);
105 }
106 }
107 }
108 return result;
109 }
110
111 /**
112 * Find the most specific 16-bit service uuid represented by a SDP record
113 *
114 * @param p_rec pointer to a SDP record
115 * @return most specific 16-bit service uuid, 0 if not found
116 */
sdpu_find_most_specific_service_uuid(tSDP_DISC_REC * p_rec)117 static uint16_t sdpu_find_most_specific_service_uuid(tSDP_DISC_REC* p_rec) {
118 for (tSDP_DISC_ATTR* p_attr = p_rec->p_first_attr; p_attr != nullptr;
119 p_attr = p_attr->p_next_attr) {
120 if (p_attr->attr_id == ATTR_ID_SERVICE_CLASS_ID_LIST &&
121 SDP_DISC_ATTR_TYPE(p_attr->attr_len_type) == DATA_ELE_SEQ_DESC_TYPE) {
122 tSDP_DISC_ATTR* p_first_attr = p_attr->attr_value.v.p_sub_attr;
123 if (SDP_DISC_ATTR_TYPE(p_first_attr->attr_len_type) == UUID_DESC_TYPE &&
124 SDP_DISC_ATTR_LEN(p_first_attr->attr_len_type) == 2) {
125 return p_first_attr->attr_value.v.u16;
126 } else if (SDP_DISC_ATTR_TYPE(p_first_attr->attr_len_type) ==
127 DATA_ELE_SEQ_DESC_TYPE) {
128 // Workaround for Toyota G Block car kit:
129 // It incorrectly puts an extra data element sequence in this attribute
130 for (tSDP_DISC_ATTR* p_extra_sattr =
131 p_first_attr->attr_value.v.p_sub_attr;
132 p_extra_sattr != nullptr;
133 p_extra_sattr = p_extra_sattr->p_next_attr) {
134 // Return the first UUID data element
135 if (SDP_DISC_ATTR_TYPE(p_extra_sattr->attr_len_type) ==
136 UUID_DESC_TYPE &&
137 SDP_DISC_ATTR_LEN(p_extra_sattr->attr_len_type) == 2) {
138 return p_extra_sattr->attr_value.v.u16;
139 }
140 }
141 } else {
142 LOG(WARNING) << __func__ << ": Bad Service Class ID list attribute";
143 return 0;
144 }
145 } else if (p_attr->attr_id == ATTR_ID_SERVICE_ID) {
146 if (SDP_DISC_ATTR_TYPE(p_attr->attr_len_type) == UUID_DESC_TYPE &&
147 SDP_DISC_ATTR_LEN(p_attr->attr_len_type) == 2) {
148 return p_attr->attr_value.v.u16;
149 }
150 }
151 }
152 return 0;
153 }
154
sdpu_log_attribute_metrics(const RawAddress & bda,tSDP_DISCOVERY_DB * p_db)155 void sdpu_log_attribute_metrics(const RawAddress& bda,
156 tSDP_DISCOVERY_DB* p_db) {
157 CHECK_NE(p_db, nullptr);
158 bool has_di_record = false;
159 for (tSDP_DISC_REC* p_rec = p_db->p_first_rec; p_rec != nullptr;
160 p_rec = p_rec->p_next_rec) {
161 uint16_t service_uuid = sdpu_find_most_specific_service_uuid(p_rec);
162 if (service_uuid == 0) {
163 LOG(INFO) << __func__ << ": skipping record without service uuid " << bda;
164 continue;
165 }
166 // Log the existence of a profile role
167 // This can be different from Bluetooth Profile Descriptor List
168 bluetooth::common::LogSdpAttribute(bda, service_uuid, 0, 0, nullptr);
169 // Log profile version from Bluetooth Profile Descriptor List
170 auto uuid_version_array = sdpu_find_profile_version(p_rec);
171 for (const auto& uuid_version_pair : uuid_version_array) {
172 uint16_t profile_uuid = uuid_version_pair.first;
173 uint16_t version = uuid_version_pair.second;
174 auto version_array = to_little_endian_array(version);
175 bluetooth::common::LogSdpAttribute(
176 bda, profile_uuid, ATTR_ID_BT_PROFILE_DESC_LIST, version_array.size(),
177 version_array.data());
178 }
179 // Log protocol version from Protocol Descriptor List
180 uint16_t protocol_uuid = 0;
181 switch (service_uuid) {
182 case UUID_SERVCLASS_AUDIO_SOURCE:
183 case UUID_SERVCLASS_AUDIO_SINK:
184 protocol_uuid = UUID_PROTOCOL_AVDTP;
185 break;
186 case UUID_SERVCLASS_AV_REMOTE_CONTROL:
187 case UUID_SERVCLASS_AV_REM_CTRL_CONTROL:
188 case UUID_SERVCLASS_AV_REM_CTRL_TARGET:
189 protocol_uuid = UUID_PROTOCOL_AVCTP;
190 break;
191 case UUID_SERVCLASS_PANU:
192 case UUID_SERVCLASS_GN:
193 protocol_uuid = UUID_PROTOCOL_BNEP;
194 break;
195 }
196 if (protocol_uuid != 0) {
197 tSDP_PROTOCOL_ELEM protocol_elements = {};
198 if (SDP_FindProtocolListElemInRec(p_rec, protocol_uuid,
199 &protocol_elements)) {
200 if (protocol_elements.num_params >= 1) {
201 uint16_t version = protocol_elements.params[0];
202 auto version_array = to_little_endian_array(version);
203 bluetooth::common::LogSdpAttribute(
204 bda, protocol_uuid, ATTR_ID_PROTOCOL_DESC_LIST,
205 version_array.size(), version_array.data());
206 }
207 }
208 }
209 // Log profile supported features from various supported feature attributes
210 switch (service_uuid) {
211 case UUID_SERVCLASS_AG_HANDSFREE:
212 case UUID_SERVCLASS_HF_HANDSFREE:
213 case UUID_SERVCLASS_AV_REMOTE_CONTROL:
214 case UUID_SERVCLASS_AV_REM_CTRL_CONTROL:
215 case UUID_SERVCLASS_AV_REM_CTRL_TARGET:
216 case UUID_SERVCLASS_AUDIO_SOURCE:
217 case UUID_SERVCLASS_AUDIO_SINK: {
218 tSDP_DISC_ATTR* p_attr =
219 SDP_FindAttributeInRec(p_rec, ATTR_ID_SUPPORTED_FEATURES);
220 if (p_attr == nullptr) {
221 break;
222 }
223 uint16_t supported_features = p_attr->attr_value.v.u16;
224 auto version_array = to_little_endian_array(supported_features);
225 bluetooth::common::LogSdpAttribute(
226 bda, service_uuid, ATTR_ID_SUPPORTED_FEATURES, version_array.size(),
227 version_array.data());
228 break;
229 }
230 case UUID_SERVCLASS_MESSAGE_NOTIFICATION:
231 case UUID_SERVCLASS_MESSAGE_ACCESS: {
232 tSDP_DISC_ATTR* p_attr =
233 SDP_FindAttributeInRec(p_rec, ATTR_ID_MAP_SUPPORTED_FEATURES);
234 if (p_attr == nullptr) {
235 break;
236 }
237 uint32_t map_supported_features = p_attr->attr_value.v.u32;
238 auto features_array = to_little_endian_array(map_supported_features);
239 bluetooth::common::LogSdpAttribute(
240 bda, service_uuid, ATTR_ID_MAP_SUPPORTED_FEATURES,
241 features_array.size(), features_array.data());
242 break;
243 }
244 case UUID_SERVCLASS_PBAP_PCE:
245 case UUID_SERVCLASS_PBAP_PSE: {
246 tSDP_DISC_ATTR* p_attr =
247 SDP_FindAttributeInRec(p_rec, ATTR_ID_PBAP_SUPPORTED_FEATURES);
248 if (p_attr == nullptr) {
249 break;
250 }
251 uint32_t pbap_supported_features = p_attr->attr_value.v.u32;
252 auto features_array = to_little_endian_array(pbap_supported_features);
253 bluetooth::common::LogSdpAttribute(
254 bda, service_uuid, ATTR_ID_PBAP_SUPPORTED_FEATURES,
255 features_array.size(), features_array.data());
256 break;
257 }
258 }
259 if (service_uuid == UUID_SERVCLASS_PNP_INFORMATION) {
260 has_di_record = true;
261 }
262 }
263 // Log the first DI record if there is one
264 if (has_di_record) {
265 tSDP_DI_GET_RECORD di_record = {};
266 if (SDP_GetDiRecord(1, &di_record, p_db) == SDP_SUCCESS) {
267 auto version_array = to_little_endian_array(di_record.spec_id);
268 bluetooth::common::LogSdpAttribute(
269 bda, UUID_SERVCLASS_PNP_INFORMATION, ATTR_ID_SPECIFICATION_ID,
270 version_array.size(), version_array.data());
271 std::stringstream ss;
272 // [N - native]::SDP::[DIP - Device ID Profile]
273 ss << "N:SDP::DIP::" << loghex(di_record.rec.vendor_id_source);
274 bluetooth::common::LogManufacturerInfo(
275 bda, android::bluetooth::DeviceInfoSrcEnum::DEVICE_INFO_INTERNAL,
276 ss.str(), loghex(di_record.rec.vendor), loghex(di_record.rec.product),
277 loghex(di_record.rec.version), "");
278
279 std::string bda_string = bda.ToString();
280 // write manufacturer, model, HW version to config
281 btif_config_set_int(bda_string, BT_CONFIG_KEY_SDP_DI_MANUFACTURER,
282 di_record.rec.vendor);
283 btif_config_set_int(bda_string, BT_CONFIG_KEY_SDP_DI_MODEL,
284 di_record.rec.product);
285 btif_config_set_int(bda_string, BT_CONFIG_KEY_SDP_DI_HW_VERSION,
286 di_record.rec.version);
287 btif_config_set_int(bda_string, BT_CONFIG_KEY_SDP_DI_VENDOR_ID_SRC,
288 di_record.rec.vendor_id_source);
289 }
290 }
291 }
292
293 /*******************************************************************************
294 *
295 * Function sdpu_find_ccb_by_cid
296 *
297 * Description This function searches the CCB table for an entry with the
298 * passed CID.
299 *
300 * Returns the CCB address, or NULL if not found.
301 *
302 ******************************************************************************/
sdpu_find_ccb_by_cid(uint16_t cid)303 tCONN_CB* sdpu_find_ccb_by_cid(uint16_t cid) {
304 uint16_t xx;
305 tCONN_CB* p_ccb;
306
307 /* Look through each connection control block */
308 for (xx = 0, p_ccb = sdp_cb.ccb; xx < SDP_MAX_CONNECTIONS; xx++, p_ccb++) {
309 if ((p_ccb->con_state != SDP_STATE_IDLE) && (p_ccb->connection_id == cid))
310 return (p_ccb);
311 }
312
313 /* If here, not found */
314 return (NULL);
315 }
316
317 /*******************************************************************************
318 *
319 * Function sdpu_find_ccb_by_db
320 *
321 * Description This function searches the CCB table for an entry with the
322 * passed discovery db.
323 *
324 * Returns the CCB address, or NULL if not found.
325 *
326 ******************************************************************************/
sdpu_find_ccb_by_db(tSDP_DISCOVERY_DB * p_db)327 tCONN_CB* sdpu_find_ccb_by_db(tSDP_DISCOVERY_DB* p_db) {
328 uint16_t xx;
329 tCONN_CB* p_ccb;
330
331 if (p_db) {
332 /* Look through each connection control block */
333 for (xx = 0, p_ccb = sdp_cb.ccb; xx < SDP_MAX_CONNECTIONS; xx++, p_ccb++) {
334 if ((p_ccb->con_state != SDP_STATE_IDLE) && (p_ccb->p_db == p_db))
335 return (p_ccb);
336 }
337 }
338 /* If here, not found */
339 return (NULL);
340 }
341
342 /*******************************************************************************
343 *
344 * Function sdpu_allocate_ccb
345 *
346 * Description This function allocates a new CCB.
347 *
348 * Returns CCB address, or NULL if none available.
349 *
350 ******************************************************************************/
sdpu_allocate_ccb(void)351 tCONN_CB* sdpu_allocate_ccb(void) {
352 uint16_t xx;
353 tCONN_CB* p_ccb;
354
355 /* Look through each connection control block for a free one */
356 for (xx = 0, p_ccb = sdp_cb.ccb; xx < SDP_MAX_CONNECTIONS; xx++, p_ccb++) {
357 if (p_ccb->con_state == SDP_STATE_IDLE) {
358 alarm_t* alarm = p_ccb->sdp_conn_timer;
359 memset(p_ccb, 0, sizeof(tCONN_CB));
360 p_ccb->sdp_conn_timer = alarm;
361 return (p_ccb);
362 }
363 }
364
365 /* If here, no free CCB found */
366 return (NULL);
367 }
368
369 /*******************************************************************************
370 *
371 * Function sdpu_release_ccb
372 *
373 * Description This function releases a CCB.
374 *
375 * Returns void
376 *
377 ******************************************************************************/
sdpu_release_ccb(tCONN_CB * p_ccb)378 void sdpu_release_ccb(tCONN_CB* p_ccb) {
379 /* Ensure timer is stopped */
380 alarm_cancel(p_ccb->sdp_conn_timer);
381
382 /* Drop any response pointer we may be holding */
383 p_ccb->con_state = SDP_STATE_IDLE;
384 p_ccb->is_attr_search = false;
385
386 /* Free the response buffer */
387 if (p_ccb->rsp_list) SDP_TRACE_DEBUG("releasing SDP rsp_list");
388 osi_free_and_reset((void**)&p_ccb->rsp_list);
389 }
390
391 /*******************************************************************************
392 *
393 * Function sdpu_build_attrib_seq
394 *
395 * Description This function builds an attribute sequence from the list of
396 * passed attributes. It is also passed the address of the
397 * output buffer.
398 *
399 * Returns Pointer to next byte in the output buffer.
400 *
401 ******************************************************************************/
sdpu_build_attrib_seq(uint8_t * p_out,uint16_t * p_attr,uint16_t num_attrs)402 uint8_t* sdpu_build_attrib_seq(uint8_t* p_out, uint16_t* p_attr,
403 uint16_t num_attrs) {
404 uint16_t xx;
405
406 /* First thing is the data element header. See if the length fits 1 byte */
407 /* If no attributes, assume a 4-byte wildcard */
408 if (!p_attr)
409 xx = 5;
410 else
411 xx = num_attrs * 3;
412
413 if (xx > 255) {
414 UINT8_TO_BE_STREAM(p_out,
415 (DATA_ELE_SEQ_DESC_TYPE << 3) | SIZE_IN_NEXT_WORD);
416 UINT16_TO_BE_STREAM(p_out, xx);
417 } else {
418 UINT8_TO_BE_STREAM(p_out,
419 (DATA_ELE_SEQ_DESC_TYPE << 3) | SIZE_IN_NEXT_BYTE);
420 UINT8_TO_BE_STREAM(p_out, xx);
421 }
422
423 /* If there are no attributes specified, assume caller wants wildcard */
424 if (!p_attr) {
425 UINT8_TO_BE_STREAM(p_out, (UINT_DESC_TYPE << 3) | SIZE_FOUR_BYTES);
426 UINT16_TO_BE_STREAM(p_out, 0);
427 UINT16_TO_BE_STREAM(p_out, 0xFFFF);
428 } else {
429 /* Loop through and put in all the attributes(s) */
430 for (xx = 0; xx < num_attrs; xx++, p_attr++) {
431 UINT8_TO_BE_STREAM(p_out, (UINT_DESC_TYPE << 3) | SIZE_TWO_BYTES);
432 UINT16_TO_BE_STREAM(p_out, *p_attr);
433 }
434 }
435
436 return (p_out);
437 }
438
439 /*******************************************************************************
440 *
441 * Function sdpu_build_attrib_entry
442 *
443 * Description This function builds an attribute entry from the passed
444 * attribute record. It is also passed the address of the
445 * output buffer.
446 *
447 * Returns Pointer to next byte in the output buffer.
448 *
449 ******************************************************************************/
sdpu_build_attrib_entry(uint8_t * p_out,tSDP_ATTRIBUTE * p_attr)450 uint8_t* sdpu_build_attrib_entry(uint8_t* p_out, tSDP_ATTRIBUTE* p_attr) {
451 /* First, store the attribute ID. Goes as a UINT */
452 UINT8_TO_BE_STREAM(p_out, (UINT_DESC_TYPE << 3) | SIZE_TWO_BYTES);
453 UINT16_TO_BE_STREAM(p_out, p_attr->id);
454
455 /* the attribute is in the db record.
456 * assuming the attribute len is less than SDP_MAX_ATTR_LEN */
457 switch (p_attr->type) {
458 case TEXT_STR_DESC_TYPE: /* 4 */
459 case DATA_ELE_SEQ_DESC_TYPE: /* 6 */
460 case DATA_ELE_ALT_DESC_TYPE: /* 7 */
461 case URL_DESC_TYPE: /* 8 */
462 #if (SDP_MAX_ATTR_LEN > 0xFFFF)
463 if (p_attr->len > 0xFFFF) {
464 UINT8_TO_BE_STREAM(p_out, (p_attr->type << 3) | SIZE_IN_NEXT_LONG);
465 UINT32_TO_BE_STREAM(p_out, p_attr->len);
466 } else
467 #endif /* 0xFFFF - 0xFF */
468 #if (SDP_MAX_ATTR_LEN > 0xFF)
469 if (p_attr->len > 0xFF) {
470 UINT8_TO_BE_STREAM(p_out, (p_attr->type << 3) | SIZE_IN_NEXT_WORD);
471 UINT16_TO_BE_STREAM(p_out, p_attr->len);
472 } else
473 #endif /* 0xFF and less*/
474 {
475 UINT8_TO_BE_STREAM(p_out, (p_attr->type << 3) | SIZE_IN_NEXT_BYTE);
476 UINT8_TO_BE_STREAM(p_out, p_attr->len);
477 }
478
479 if (p_attr->value_ptr != NULL) {
480 ARRAY_TO_BE_STREAM(p_out, p_attr->value_ptr, (int)p_attr->len);
481 }
482
483 return (p_out);
484 }
485
486 /* Now, store the attribute value */
487 switch (p_attr->len) {
488 case 1:
489 UINT8_TO_BE_STREAM(p_out, (p_attr->type << 3) | SIZE_ONE_BYTE);
490 break;
491 case 2:
492 UINT8_TO_BE_STREAM(p_out, (p_attr->type << 3) | SIZE_TWO_BYTES);
493 break;
494 case 4:
495 UINT8_TO_BE_STREAM(p_out, (p_attr->type << 3) | SIZE_FOUR_BYTES);
496 break;
497 case 8:
498 UINT8_TO_BE_STREAM(p_out, (p_attr->type << 3) | SIZE_EIGHT_BYTES);
499 break;
500 case 16:
501 UINT8_TO_BE_STREAM(p_out, (p_attr->type << 3) | SIZE_SIXTEEN_BYTES);
502 break;
503 default:
504 UINT8_TO_BE_STREAM(p_out, (p_attr->type << 3) | SIZE_IN_NEXT_BYTE);
505 UINT8_TO_BE_STREAM(p_out, p_attr->len);
506 break;
507 }
508
509 if (p_attr->value_ptr != NULL) {
510 ARRAY_TO_BE_STREAM(p_out, p_attr->value_ptr, (int)p_attr->len);
511 }
512
513 return (p_out);
514 }
515
516 /*******************************************************************************
517 *
518 * Function sdpu_build_n_send_error
519 *
520 * Description This function builds and sends an error packet.
521 *
522 * Returns void
523 *
524 ******************************************************************************/
sdpu_build_n_send_error(tCONN_CB * p_ccb,uint16_t trans_num,uint16_t error_code,char * p_error_text)525 void sdpu_build_n_send_error(tCONN_CB* p_ccb, uint16_t trans_num,
526 uint16_t error_code, char* p_error_text) {
527 uint8_t *p_rsp, *p_rsp_start, *p_rsp_param_len;
528 uint16_t rsp_param_len;
529 BT_HDR* p_buf = (BT_HDR*)osi_malloc(SDP_DATA_BUF_SIZE);
530
531 SDP_TRACE_WARNING("SDP - sdpu_build_n_send_error code: 0x%x CID: 0x%x",
532 error_code, p_ccb->connection_id);
533
534 /* Send the packet to L2CAP */
535 p_buf->offset = L2CAP_MIN_OFFSET;
536 p_rsp = p_rsp_start = (uint8_t*)(p_buf + 1) + L2CAP_MIN_OFFSET;
537
538 UINT8_TO_BE_STREAM(p_rsp, SDP_PDU_ERROR_RESPONSE);
539 UINT16_TO_BE_STREAM(p_rsp, trans_num);
540
541 /* Skip the parameter length, we need to add it at the end */
542 p_rsp_param_len = p_rsp;
543 p_rsp += 2;
544
545 UINT16_TO_BE_STREAM(p_rsp, error_code);
546
547 /* Unplugfest example traces do not have any error text */
548 if (p_error_text)
549 ARRAY_TO_BE_STREAM(p_rsp, p_error_text, (int)strlen(p_error_text));
550
551 /* Go back and put the parameter length into the buffer */
552 rsp_param_len = p_rsp - p_rsp_param_len - 2;
553 UINT16_TO_BE_STREAM(p_rsp_param_len, rsp_param_len);
554
555 /* Set the length of the SDP data in the buffer */
556 p_buf->len = p_rsp - p_rsp_start;
557
558 /* Send the buffer through L2CAP */
559 L2CA_DataWrite(p_ccb->connection_id, p_buf);
560 }
561
562 /*******************************************************************************
563 *
564 * Function sdpu_extract_uid_seq
565 *
566 * Description This function extracts a UUID sequence from the passed input
567 * buffer, and puts it into the passed output list.
568 *
569 * Returns Pointer to next byte in the input buffer after the sequence.
570 *
571 ******************************************************************************/
sdpu_extract_uid_seq(uint8_t * p,uint16_t param_len,tSDP_UUID_SEQ * p_seq)572 uint8_t* sdpu_extract_uid_seq(uint8_t* p, uint16_t param_len,
573 tSDP_UUID_SEQ* p_seq) {
574 uint8_t* p_seq_end;
575 uint8_t descr, type, size;
576 uint32_t seq_len, uuid_len;
577
578 /* Assume none found */
579 p_seq->num_uids = 0;
580
581 /* A UID sequence is composed of a bunch of UIDs. */
582 if (sizeof(descr) > param_len) return (NULL);
583 param_len -= sizeof(descr);
584
585 BE_STREAM_TO_UINT8(descr, p);
586 type = descr >> 3;
587 size = descr & 7;
588
589 if (type != DATA_ELE_SEQ_DESC_TYPE) return (NULL);
590
591 switch (size) {
592 case SIZE_TWO_BYTES:
593 seq_len = 2;
594 break;
595 case SIZE_FOUR_BYTES:
596 seq_len = 4;
597 break;
598 case SIZE_SIXTEEN_BYTES:
599 seq_len = 16;
600 break;
601 case SIZE_IN_NEXT_BYTE:
602 if (sizeof(uint8_t) > param_len) return (NULL);
603 param_len -= sizeof(uint8_t);
604 BE_STREAM_TO_UINT8(seq_len, p);
605 break;
606 case SIZE_IN_NEXT_WORD:
607 if (sizeof(uint16_t) > param_len) return (NULL);
608 param_len -= sizeof(uint16_t);
609 BE_STREAM_TO_UINT16(seq_len, p);
610 break;
611 case SIZE_IN_NEXT_LONG:
612 if (sizeof(uint32_t) > param_len) return (NULL);
613 param_len -= sizeof(uint32_t);
614 BE_STREAM_TO_UINT32(seq_len, p);
615 break;
616 default:
617 return (NULL);
618 }
619
620 if (seq_len > param_len) return (NULL);
621
622 p_seq_end = p + seq_len;
623
624 /* Loop through, extracting the UIDs */
625 for (; p < p_seq_end;) {
626 BE_STREAM_TO_UINT8(descr, p);
627 type = descr >> 3;
628 size = descr & 7;
629
630 if (type != UUID_DESC_TYPE) return (NULL);
631
632 switch (size) {
633 case SIZE_TWO_BYTES:
634 uuid_len = 2;
635 break;
636 case SIZE_FOUR_BYTES:
637 uuid_len = 4;
638 break;
639 case SIZE_SIXTEEN_BYTES:
640 uuid_len = 16;
641 break;
642 case SIZE_IN_NEXT_BYTE:
643 if (p + sizeof(uint8_t) > p_seq_end) return NULL;
644 BE_STREAM_TO_UINT8(uuid_len, p);
645 break;
646 case SIZE_IN_NEXT_WORD:
647 if (p + sizeof(uint16_t) > p_seq_end) return NULL;
648 BE_STREAM_TO_UINT16(uuid_len, p);
649 break;
650 case SIZE_IN_NEXT_LONG:
651 if (p + sizeof(uint32_t) > p_seq_end) return NULL;
652 BE_STREAM_TO_UINT32(uuid_len, p);
653 break;
654 default:
655 return (NULL);
656 }
657
658 /* If UUID length is valid, copy it across */
659 if (((uuid_len == 2) || (uuid_len == 4) || (uuid_len == 16)) &&
660 (p + uuid_len <= p_seq_end)) {
661 p_seq->uuid_entry[p_seq->num_uids].len = (uint16_t)uuid_len;
662 BE_STREAM_TO_ARRAY(p, p_seq->uuid_entry[p_seq->num_uids].value,
663 (int)uuid_len);
664 p_seq->num_uids++;
665 } else
666 return (NULL);
667
668 /* We can only do so many */
669 if (p_seq->num_uids >= MAX_UUIDS_PER_SEQ) return (NULL);
670 }
671
672 if (p != p_seq_end) return (NULL);
673
674 return (p);
675 }
676
677 /*******************************************************************************
678 *
679 * Function sdpu_extract_attr_seq
680 *
681 * Description This function extracts an attribute sequence from the passed
682 * input buffer, and puts it into the passed output list.
683 *
684 * Returns Pointer to next byte in the input buffer after the sequence.
685 *
686 ******************************************************************************/
sdpu_extract_attr_seq(uint8_t * p,uint16_t param_len,tSDP_ATTR_SEQ * p_seq)687 uint8_t* sdpu_extract_attr_seq(uint8_t* p, uint16_t param_len,
688 tSDP_ATTR_SEQ* p_seq) {
689 uint8_t* p_end_list;
690 uint8_t descr, type, size;
691 uint32_t list_len, attr_len;
692
693 /* Assume none found */
694 p_seq->num_attr = 0;
695
696 /* Get attribute sequence info */
697 if (param_len < sizeof(descr)) return NULL;
698 param_len -= sizeof(descr);
699 BE_STREAM_TO_UINT8(descr, p);
700 type = descr >> 3;
701 size = descr & 7;
702
703 if (type != DATA_ELE_SEQ_DESC_TYPE) return NULL;
704
705 switch (size) {
706 case SIZE_IN_NEXT_BYTE:
707 if (param_len < sizeof(uint8_t)) return NULL;
708 param_len -= sizeof(uint8_t);
709 BE_STREAM_TO_UINT8(list_len, p);
710 break;
711
712 case SIZE_IN_NEXT_WORD:
713 if (param_len < sizeof(uint16_t)) return NULL;
714 param_len -= sizeof(uint16_t);
715 BE_STREAM_TO_UINT16(list_len, p);
716 break;
717
718 case SIZE_IN_NEXT_LONG:
719 if (param_len < sizeof(uint32_t)) return NULL;
720 param_len -= sizeof(uint32_t);
721 BE_STREAM_TO_UINT32(list_len, p);
722 break;
723
724 default:
725 return NULL;
726 }
727
728 if (list_len > param_len) return NULL;
729
730 p_end_list = p + list_len;
731
732 /* Loop through, extracting the attribute IDs */
733 for (; p < p_end_list;) {
734 BE_STREAM_TO_UINT8(descr, p);
735 type = descr >> 3;
736 size = descr & 7;
737
738 if (type != UINT_DESC_TYPE) return NULL;
739
740 switch (size) {
741 case SIZE_TWO_BYTES:
742 attr_len = 2;
743 break;
744 case SIZE_FOUR_BYTES:
745 attr_len = 4;
746 break;
747 case SIZE_IN_NEXT_BYTE:
748 if (p + sizeof(uint8_t) > p_end_list) return NULL;
749 BE_STREAM_TO_UINT8(attr_len, p);
750 break;
751 case SIZE_IN_NEXT_WORD:
752 if (p + sizeof(uint16_t) > p_end_list) return NULL;
753 BE_STREAM_TO_UINT16(attr_len, p);
754 break;
755 case SIZE_IN_NEXT_LONG:
756 if (p + sizeof(uint32_t) > p_end_list) return NULL;
757 BE_STREAM_TO_UINT32(attr_len, p);
758 break;
759 default:
760 return NULL;
761 break;
762 }
763
764 /* Attribute length must be 2-bytes or 4-bytes for a paired entry. */
765 if (p + attr_len > p_end_list) return NULL;
766 if (attr_len == 2) {
767 BE_STREAM_TO_UINT16(p_seq->attr_entry[p_seq->num_attr].start, p);
768 p_seq->attr_entry[p_seq->num_attr].end =
769 p_seq->attr_entry[p_seq->num_attr].start;
770 } else if (attr_len == 4) {
771 BE_STREAM_TO_UINT16(p_seq->attr_entry[p_seq->num_attr].start, p);
772 BE_STREAM_TO_UINT16(p_seq->attr_entry[p_seq->num_attr].end, p);
773 } else
774 return (NULL);
775
776 /* We can only do so many */
777 if (++p_seq->num_attr >= MAX_ATTR_PER_SEQ) return (NULL);
778 }
779
780 return (p);
781 }
782
783 /*******************************************************************************
784 *
785 * Function sdpu_get_len_from_type
786 *
787 * Description This function gets the length
788 *
789 * Returns void
790 *
791 ******************************************************************************/
sdpu_get_len_from_type(uint8_t * p,uint8_t * p_end,uint8_t type,uint32_t * p_len)792 uint8_t* sdpu_get_len_from_type(uint8_t* p, uint8_t* p_end, uint8_t type,
793 uint32_t* p_len) {
794 uint8_t u8;
795 uint16_t u16;
796 uint32_t u32;
797
798 switch (type & 7) {
799 case SIZE_ONE_BYTE:
800 *p_len = 1;
801 break;
802 case SIZE_TWO_BYTES:
803 *p_len = 2;
804 break;
805 case SIZE_FOUR_BYTES:
806 *p_len = 4;
807 break;
808 case SIZE_EIGHT_BYTES:
809 *p_len = 8;
810 break;
811 case SIZE_SIXTEEN_BYTES:
812 *p_len = 16;
813 break;
814 case SIZE_IN_NEXT_BYTE:
815 if (p + 1 > p_end) {
816 *p_len = 0;
817 return NULL;
818 }
819 BE_STREAM_TO_UINT8(u8, p);
820 *p_len = u8;
821 break;
822 case SIZE_IN_NEXT_WORD:
823 if (p + 2 > p_end) {
824 *p_len = 0;
825 return NULL;
826 }
827 BE_STREAM_TO_UINT16(u16, p);
828 *p_len = u16;
829 break;
830 case SIZE_IN_NEXT_LONG:
831 if (p + 4 > p_end) {
832 *p_len = 0;
833 return NULL;
834 }
835 BE_STREAM_TO_UINT32(u32, p);
836 *p_len = (uint16_t)u32;
837 break;
838 }
839
840 return (p);
841 }
842
843 /*******************************************************************************
844 *
845 * Function sdpu_is_base_uuid
846 *
847 * Description This function checks a 128-bit UUID with the base to see if
848 * it matches. Only the last 12 bytes are compared.
849 *
850 * Returns true if matched, else false
851 *
852 ******************************************************************************/
sdpu_is_base_uuid(uint8_t * p_uuid)853 bool sdpu_is_base_uuid(uint8_t* p_uuid) {
854 uint16_t xx;
855
856 for (xx = 4; xx < Uuid::kNumBytes128; xx++)
857 if (p_uuid[xx] != sdp_base_uuid[xx]) return (false);
858
859 /* If here, matched */
860 return (true);
861 }
862
863 /*******************************************************************************
864 *
865 * Function sdpu_compare_uuid_arrays
866 *
867 * Description This function compares 2 BE UUIDs. If needed, they are
868 * expanded to 128-bit UUIDs, then compared.
869 *
870 * NOTE it is assumed that the arrays are in Big Endian format
871 *
872 * Returns true if matched, else false
873 *
874 ******************************************************************************/
sdpu_compare_uuid_arrays(uint8_t * p_uuid1,uint32_t len1,uint8_t * p_uuid2,uint16_t len2)875 bool sdpu_compare_uuid_arrays(uint8_t* p_uuid1, uint32_t len1, uint8_t* p_uuid2,
876 uint16_t len2) {
877 uint8_t nu1[Uuid::kNumBytes128];
878 uint8_t nu2[Uuid::kNumBytes128];
879
880 if (((len1 != 2) && (len1 != 4) && (len1 != 16)) ||
881 ((len2 != 2) && (len2 != 4) && (len2 != 16))) {
882 SDP_TRACE_ERROR("%s: invalid length", __func__);
883 return false;
884 }
885
886 /* If lengths match, do a straight compare */
887 if (len1 == len2) {
888 if (len1 == 2)
889 return ((p_uuid1[0] == p_uuid2[0]) && (p_uuid1[1] == p_uuid2[1]));
890 if (len1 == 4)
891 return ((p_uuid1[0] == p_uuid2[0]) && (p_uuid1[1] == p_uuid2[1]) &&
892 (p_uuid1[2] == p_uuid2[2]) && (p_uuid1[3] == p_uuid2[3]));
893 else
894 return (memcmp(p_uuid1, p_uuid2, (size_t)len1) == 0);
895 } else if (len1 > len2) {
896 /* If the len1 was 4-byte, (so len2 is 2-byte), compare on the fly */
897 if (len1 == 4) {
898 return ((p_uuid1[0] == 0) && (p_uuid1[1] == 0) &&
899 (p_uuid1[2] == p_uuid2[0]) && (p_uuid1[3] == p_uuid2[1]));
900 } else {
901 /* Normalize UUIDs to 16-byte form, then compare. Len1 must be 16 */
902 memcpy(nu1, p_uuid1, Uuid::kNumBytes128);
903 memcpy(nu2, sdp_base_uuid, Uuid::kNumBytes128);
904
905 if (len2 == 4)
906 memcpy(nu2, p_uuid2, len2);
907 else if (len2 == 2)
908 memcpy(nu2 + 2, p_uuid2, len2);
909
910 return (memcmp(nu1, nu2, Uuid::kNumBytes128) == 0);
911 }
912 } else {
913 /* len2 is greater than len1 */
914 /* If the len2 was 4-byte, (so len1 is 2-byte), compare on the fly */
915 if (len2 == 4) {
916 return ((p_uuid2[0] == 0) && (p_uuid2[1] == 0) &&
917 (p_uuid2[2] == p_uuid1[0]) && (p_uuid2[3] == p_uuid1[1]));
918 } else {
919 /* Normalize UUIDs to 16-byte form, then compare. Len1 must be 16 */
920 memcpy(nu2, p_uuid2, Uuid::kNumBytes128);
921 memcpy(nu1, sdp_base_uuid, Uuid::kNumBytes128);
922
923 if (len1 == 4)
924 memcpy(nu1, p_uuid1, (size_t)len1);
925 else if (len1 == 2)
926 memcpy(nu1 + 2, p_uuid1, (size_t)len1);
927
928 return (memcmp(nu1, nu2, Uuid::kNumBytes128) == 0);
929 }
930 }
931 }
932
933 /*******************************************************************************
934 *
935 * Function sdpu_compare_uuid_with_attr
936 *
937 * Description This function compares a BT UUID structure with the UUID in
938 * an SDP attribute record. If needed, they are expanded to
939 * 128-bit UUIDs, then compared.
940 *
941 * NOTE - it is assumed that BT UUID structures are compressed to the
942 * smallest possible UUIDs (by removing the base SDP UUID).
943 * - it is also assumed that the discovery atribute is compressed
944 * to the smallest possible
945 *
946 * Returns true if matched, else false
947 *
948 ******************************************************************************/
sdpu_compare_uuid_with_attr(const Uuid & uuid,tSDP_DISC_ATTR * p_attr)949 bool sdpu_compare_uuid_with_attr(const Uuid& uuid, tSDP_DISC_ATTR* p_attr) {
950 int len = uuid.GetShortestRepresentationSize();
951 if (len == 2) return uuid.As16Bit() == p_attr->attr_value.v.u16;
952 if (len == 4) return uuid.As32Bit() == p_attr->attr_value.v.u32;
953 if (memcmp(uuid.To128BitBE().data(), (void*)p_attr->attr_value.v.array,
954 Uuid::kNumBytes128) == 0)
955 return (true);
956
957 return (false);
958 }
959
960 /*******************************************************************************
961 *
962 * Function sdpu_sort_attr_list
963 *
964 * Description sorts a list of attributes in numeric order from lowest to
965 * highest to conform to SDP specification
966 *
967 * Returns void
968 *
969 ******************************************************************************/
sdpu_sort_attr_list(uint16_t num_attr,tSDP_DISCOVERY_DB * p_db)970 void sdpu_sort_attr_list(uint16_t num_attr, tSDP_DISCOVERY_DB* p_db) {
971 uint16_t i;
972 uint16_t x;
973
974 /* Done if no attributes to sort */
975 if (num_attr <= 1) {
976 return;
977 } else if (num_attr > SDP_MAX_ATTR_FILTERS) {
978 num_attr = SDP_MAX_ATTR_FILTERS;
979 }
980
981 num_attr--; /* for the for-loop */
982 for (i = 0; i < num_attr;) {
983 if (p_db->attr_filters[i] > p_db->attr_filters[i + 1]) {
984 /* swap the attribute IDs and start from the beginning */
985 x = p_db->attr_filters[i];
986 p_db->attr_filters[i] = p_db->attr_filters[i + 1];
987 p_db->attr_filters[i + 1] = x;
988
989 i = 0;
990 } else
991 i++;
992 }
993 }
994
995 /*******************************************************************************
996 *
997 * Function sdpu_get_list_len
998 *
999 * Description gets the total list length in the sdp database for a given
1000 * uid sequence and attr sequence
1001 *
1002 * Returns void
1003 *
1004 ******************************************************************************/
sdpu_get_list_len(tSDP_UUID_SEQ * uid_seq,tSDP_ATTR_SEQ * attr_seq)1005 uint16_t sdpu_get_list_len(tSDP_UUID_SEQ* uid_seq, tSDP_ATTR_SEQ* attr_seq) {
1006 tSDP_RECORD* p_rec;
1007 uint16_t len = 0;
1008 uint16_t len1;
1009
1010 for (p_rec = sdp_db_service_search(NULL, uid_seq); p_rec;
1011 p_rec = sdp_db_service_search(p_rec, uid_seq)) {
1012 len += 3;
1013
1014 len1 = sdpu_get_attrib_seq_len(p_rec, attr_seq);
1015
1016 if (len1 != 0)
1017 len += len1;
1018 else
1019 len -= 3;
1020 }
1021 return len;
1022 }
1023
1024 /*******************************************************************************
1025 *
1026 * Function sdpu_get_attrib_seq_len
1027 *
1028 * Description gets the length of the specific attributes in a given
1029 * sdp record
1030 *
1031 * Returns void
1032 *
1033 ******************************************************************************/
sdpu_get_attrib_seq_len(tSDP_RECORD * p_rec,tSDP_ATTR_SEQ * attr_seq)1034 uint16_t sdpu_get_attrib_seq_len(tSDP_RECORD* p_rec, tSDP_ATTR_SEQ* attr_seq) {
1035 tSDP_ATTRIBUTE* p_attr;
1036 uint16_t len1 = 0;
1037 uint16_t xx;
1038 bool is_range = false;
1039 uint16_t start_id = 0, end_id = 0;
1040
1041 for (xx = 0; xx < attr_seq->num_attr; xx++) {
1042 if (!is_range) {
1043 start_id = attr_seq->attr_entry[xx].start;
1044 end_id = attr_seq->attr_entry[xx].end;
1045 }
1046 p_attr = sdp_db_find_attr_in_rec(p_rec, start_id, end_id);
1047 if (p_attr) {
1048 len1 += sdpu_get_attrib_entry_len(p_attr);
1049
1050 /* If doing a range, stick with this one till no more attributes found */
1051 if (start_id != end_id) {
1052 /* Update for next time through */
1053 start_id = p_attr->id + 1;
1054 xx--;
1055 is_range = true;
1056 } else
1057 is_range = false;
1058 } else
1059 is_range = false;
1060 }
1061 return len1;
1062 }
1063
1064 /*******************************************************************************
1065 *
1066 * Function sdpu_get_attrib_entry_len
1067 *
1068 * Description gets the length of a specific attribute
1069 *
1070 * Returns void
1071 *
1072 ******************************************************************************/
sdpu_get_attrib_entry_len(tSDP_ATTRIBUTE * p_attr)1073 uint16_t sdpu_get_attrib_entry_len(tSDP_ATTRIBUTE* p_attr) {
1074 uint16_t len = 3;
1075
1076 /* the attribute is in the db record.
1077 * assuming the attribute len is less than SDP_MAX_ATTR_LEN */
1078 switch (p_attr->type) {
1079 case TEXT_STR_DESC_TYPE: /* 4 */
1080 case DATA_ELE_SEQ_DESC_TYPE: /* 6 */
1081 case DATA_ELE_ALT_DESC_TYPE: /* 7 */
1082 case URL_DESC_TYPE: /* 8 */
1083 #if (SDP_MAX_ATTR_LEN > 0xFFFF)
1084 if (p_attr->len > 0xFFFF) {
1085 len += 5;
1086 } else
1087 #endif /* 0xFFFF - 0xFF */
1088 #if (SDP_MAX_ATTR_LEN > 0xFF)
1089 if (p_attr->len > 0xFF) {
1090 len += 3;
1091 } else
1092 #endif /* 0xFF and less*/
1093 {
1094 len += 2;
1095 }
1096 len += p_attr->len;
1097 return len;
1098 }
1099
1100 /* Now, the attribute value */
1101 switch (p_attr->len) {
1102 case 1:
1103 case 2:
1104 case 4:
1105 case 8:
1106 case 16:
1107 len += 1;
1108 break;
1109 default:
1110 len += 2;
1111 break;
1112 }
1113
1114 len += p_attr->len;
1115 return len;
1116 }
1117
1118 /*******************************************************************************
1119 *
1120 * Function sdpu_build_partial_attrib_entry
1121 *
1122 * Description This function fills a buffer with partial attribute. It is
1123 * assumed that the maximum size of any attribute is 256 bytes.
1124 *
1125 * p_out: output buffer
1126 * p_attr: attribute to be copied partially into p_out
1127 * rem_len: num bytes to copy into p_out
1128 * offset: current start offset within the attr that needs to
1129 * be copied
1130 *
1131 * Returns Pointer to next byte in the output buffer.
1132 * offset is also updated
1133 *
1134 ******************************************************************************/
sdpu_build_partial_attrib_entry(uint8_t * p_out,tSDP_ATTRIBUTE * p_attr,uint16_t len,uint16_t * offset)1135 uint8_t* sdpu_build_partial_attrib_entry(uint8_t* p_out, tSDP_ATTRIBUTE* p_attr,
1136 uint16_t len, uint16_t* offset) {
1137 uint8_t* p_attr_buff =
1138 (uint8_t*)osi_malloc(sizeof(uint8_t) * SDP_MAX_ATTR_LEN);
1139 sdpu_build_attrib_entry(p_attr_buff, p_attr);
1140
1141 uint16_t attr_len = sdpu_get_attrib_entry_len(p_attr);
1142
1143 if (len > SDP_MAX_ATTR_LEN) {
1144 SDP_TRACE_ERROR("%s len %d exceeds SDP_MAX_ATTR_LEN", __func__, len);
1145 len = SDP_MAX_ATTR_LEN;
1146 }
1147
1148 size_t len_to_copy =
1149 ((attr_len - *offset) < len) ? (attr_len - *offset) : len;
1150 memcpy(p_out, &p_attr_buff[*offset], len_to_copy);
1151
1152 p_out = &p_out[len_to_copy];
1153 *offset += len_to_copy;
1154
1155 osi_free(p_attr_buff);
1156 return p_out;
1157 }
1158