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