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 30 #include "bt_common.h" 31 #include "bt_types.h" 32 33 #include "hcidefs.h" 34 #include "hcimsgs.h" 35 #include "l2cdefs.h" 36 37 #include "sdp_api.h" 38 #include "sdpint.h" 39 40 #include "btu.h" 41 42 using bluetooth::Uuid; 43 static const uint8_t sdp_base_uuid[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 44 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 45 0x5F, 0x9B, 0x34, 0xFB}; 46 47 /******************************************************************************* 48 * 49 * Function sdpu_find_ccb_by_cid 50 * 51 * Description This function searches the CCB table for an entry with the 52 * passed CID. 53 * 54 * Returns the CCB address, or NULL if not found. 55 * 56 ******************************************************************************/ 57 tCONN_CB* sdpu_find_ccb_by_cid(uint16_t cid) { 58 uint16_t xx; 59 tCONN_CB* p_ccb; 60 61 /* Look through each connection control block */ 62 for (xx = 0, p_ccb = sdp_cb.ccb; xx < SDP_MAX_CONNECTIONS; xx++, p_ccb++) { 63 if ((p_ccb->con_state != SDP_STATE_IDLE) && (p_ccb->connection_id == cid)) 64 return (p_ccb); 65 } 66 67 /* If here, not found */ 68 return (NULL); 69 } 70 71 /******************************************************************************* 72 * 73 * Function sdpu_find_ccb_by_db 74 * 75 * Description This function searches the CCB table for an entry with the 76 * passed discovery db. 77 * 78 * Returns the CCB address, or NULL if not found. 79 * 80 ******************************************************************************/ 81 tCONN_CB* sdpu_find_ccb_by_db(tSDP_DISCOVERY_DB* p_db) { 82 uint16_t xx; 83 tCONN_CB* p_ccb; 84 85 if (p_db) { 86 /* Look through each connection control block */ 87 for (xx = 0, p_ccb = sdp_cb.ccb; xx < SDP_MAX_CONNECTIONS; xx++, p_ccb++) { 88 if ((p_ccb->con_state != SDP_STATE_IDLE) && (p_ccb->p_db == p_db)) 89 return (p_ccb); 90 } 91 } 92 /* If here, not found */ 93 return (NULL); 94 } 95 96 /******************************************************************************* 97 * 98 * Function sdpu_allocate_ccb 99 * 100 * Description This function allocates a new CCB. 101 * 102 * Returns CCB address, or NULL if none available. 103 * 104 ******************************************************************************/ 105 tCONN_CB* sdpu_allocate_ccb(void) { 106 uint16_t xx; 107 tCONN_CB* p_ccb; 108 109 /* Look through each connection control block for a free one */ 110 for (xx = 0, p_ccb = sdp_cb.ccb; xx < SDP_MAX_CONNECTIONS; xx++, p_ccb++) { 111 if (p_ccb->con_state == SDP_STATE_IDLE) { 112 alarm_t* alarm = p_ccb->sdp_conn_timer; 113 memset(p_ccb, 0, sizeof(tCONN_CB)); 114 p_ccb->sdp_conn_timer = alarm; 115 return (p_ccb); 116 } 117 } 118 119 /* If here, no free CCB found */ 120 return (NULL); 121 } 122 123 /******************************************************************************* 124 * 125 * Function sdpu_release_ccb 126 * 127 * Description This function releases a CCB. 128 * 129 * Returns void 130 * 131 ******************************************************************************/ 132 void sdpu_release_ccb(tCONN_CB* p_ccb) { 133 /* Ensure timer is stopped */ 134 alarm_cancel(p_ccb->sdp_conn_timer); 135 136 /* Drop any response pointer we may be holding */ 137 p_ccb->con_state = SDP_STATE_IDLE; 138 p_ccb->is_attr_search = false; 139 140 /* Free the response buffer */ 141 if (p_ccb->rsp_list) SDP_TRACE_DEBUG("releasing SDP rsp_list"); 142 osi_free_and_reset((void**)&p_ccb->rsp_list); 143 } 144 145 /******************************************************************************* 146 * 147 * Function sdpu_build_attrib_seq 148 * 149 * Description This function builds an attribute sequence from the list of 150 * passed attributes. It is also passed the address of the 151 * output buffer. 152 * 153 * Returns Pointer to next byte in the output buffer. 154 * 155 ******************************************************************************/ 156 uint8_t* sdpu_build_attrib_seq(uint8_t* p_out, uint16_t* p_attr, 157 uint16_t num_attrs) { 158 uint16_t xx; 159 160 /* First thing is the data element header. See if the length fits 1 byte */ 161 /* If no attributes, assume a 4-byte wildcard */ 162 if (!p_attr) 163 xx = 5; 164 else 165 xx = num_attrs * 3; 166 167 if (xx > 255) { 168 UINT8_TO_BE_STREAM(p_out, 169 (DATA_ELE_SEQ_DESC_TYPE << 3) | SIZE_IN_NEXT_WORD); 170 UINT16_TO_BE_STREAM(p_out, xx); 171 } else { 172 UINT8_TO_BE_STREAM(p_out, 173 (DATA_ELE_SEQ_DESC_TYPE << 3) | SIZE_IN_NEXT_BYTE); 174 UINT8_TO_BE_STREAM(p_out, xx); 175 } 176 177 /* If there are no attributes specified, assume caller wants wildcard */ 178 if (!p_attr) { 179 UINT8_TO_BE_STREAM(p_out, (UINT_DESC_TYPE << 3) | SIZE_FOUR_BYTES); 180 UINT16_TO_BE_STREAM(p_out, 0); 181 UINT16_TO_BE_STREAM(p_out, 0xFFFF); 182 } else { 183 /* Loop through and put in all the attributes(s) */ 184 for (xx = 0; xx < num_attrs; xx++, p_attr++) { 185 UINT8_TO_BE_STREAM(p_out, (UINT_DESC_TYPE << 3) | SIZE_TWO_BYTES); 186 UINT16_TO_BE_STREAM(p_out, *p_attr); 187 } 188 } 189 190 return (p_out); 191 } 192 193 /******************************************************************************* 194 * 195 * Function sdpu_build_attrib_entry 196 * 197 * Description This function builds an attribute entry from the passed 198 * attribute record. It is also passed the address of the 199 * output buffer. 200 * 201 * Returns Pointer to next byte in the output buffer. 202 * 203 ******************************************************************************/ 204 uint8_t* sdpu_build_attrib_entry(uint8_t* p_out, tSDP_ATTRIBUTE* p_attr) { 205 /* First, store the attribute ID. Goes as a UINT */ 206 UINT8_TO_BE_STREAM(p_out, (UINT_DESC_TYPE << 3) | SIZE_TWO_BYTES); 207 UINT16_TO_BE_STREAM(p_out, p_attr->id); 208 209 /* the attribute is in the db record. 210 * assuming the attribute len is less than SDP_MAX_ATTR_LEN */ 211 switch (p_attr->type) { 212 case TEXT_STR_DESC_TYPE: /* 4 */ 213 case DATA_ELE_SEQ_DESC_TYPE: /* 6 */ 214 case DATA_ELE_ALT_DESC_TYPE: /* 7 */ 215 case URL_DESC_TYPE: /* 8 */ 216 #if (SDP_MAX_ATTR_LEN > 0xFFFF) 217 if (p_attr->len > 0xFFFF) { 218 UINT8_TO_BE_STREAM(p_out, (p_attr->type << 3) | SIZE_IN_NEXT_LONG); 219 UINT32_TO_BE_STREAM(p_out, p_attr->len); 220 } else 221 #endif /* 0xFFFF - 0xFF */ 222 #if (SDP_MAX_ATTR_LEN > 0xFF) 223 if (p_attr->len > 0xFF) { 224 UINT8_TO_BE_STREAM(p_out, (p_attr->type << 3) | SIZE_IN_NEXT_WORD); 225 UINT16_TO_BE_STREAM(p_out, p_attr->len); 226 } else 227 #endif /* 0xFF and less*/ 228 { 229 UINT8_TO_BE_STREAM(p_out, (p_attr->type << 3) | SIZE_IN_NEXT_BYTE); 230 UINT8_TO_BE_STREAM(p_out, p_attr->len); 231 } 232 233 if (p_attr->value_ptr != NULL) { 234 ARRAY_TO_BE_STREAM(p_out, p_attr->value_ptr, (int)p_attr->len); 235 } 236 237 return (p_out); 238 } 239 240 /* Now, store the attribute value */ 241 switch (p_attr->len) { 242 case 1: 243 UINT8_TO_BE_STREAM(p_out, (p_attr->type << 3) | SIZE_ONE_BYTE); 244 break; 245 case 2: 246 UINT8_TO_BE_STREAM(p_out, (p_attr->type << 3) | SIZE_TWO_BYTES); 247 break; 248 case 4: 249 UINT8_TO_BE_STREAM(p_out, (p_attr->type << 3) | SIZE_FOUR_BYTES); 250 break; 251 case 8: 252 UINT8_TO_BE_STREAM(p_out, (p_attr->type << 3) | SIZE_EIGHT_BYTES); 253 break; 254 case 16: 255 UINT8_TO_BE_STREAM(p_out, (p_attr->type << 3) | SIZE_SIXTEEN_BYTES); 256 break; 257 default: 258 UINT8_TO_BE_STREAM(p_out, (p_attr->type << 3) | SIZE_IN_NEXT_BYTE); 259 UINT8_TO_BE_STREAM(p_out, p_attr->len); 260 break; 261 } 262 263 if (p_attr->value_ptr != NULL) { 264 ARRAY_TO_BE_STREAM(p_out, p_attr->value_ptr, (int)p_attr->len); 265 } 266 267 return (p_out); 268 } 269 270 /******************************************************************************* 271 * 272 * Function sdpu_build_n_send_error 273 * 274 * Description This function builds and sends an error packet. 275 * 276 * Returns void 277 * 278 ******************************************************************************/ 279 void sdpu_build_n_send_error(tCONN_CB* p_ccb, uint16_t trans_num, 280 uint16_t error_code, char* p_error_text) { 281 uint8_t *p_rsp, *p_rsp_start, *p_rsp_param_len; 282 uint16_t rsp_param_len; 283 BT_HDR* p_buf = (BT_HDR*)osi_malloc(SDP_DATA_BUF_SIZE); 284 285 SDP_TRACE_WARNING("SDP - sdpu_build_n_send_error code: 0x%x CID: 0x%x", 286 error_code, p_ccb->connection_id); 287 288 /* Send the packet to L2CAP */ 289 p_buf->offset = L2CAP_MIN_OFFSET; 290 p_rsp = p_rsp_start = (uint8_t*)(p_buf + 1) + L2CAP_MIN_OFFSET; 291 292 UINT8_TO_BE_STREAM(p_rsp, SDP_PDU_ERROR_RESPONSE); 293 UINT16_TO_BE_STREAM(p_rsp, trans_num); 294 295 /* Skip the parameter length, we need to add it at the end */ 296 p_rsp_param_len = p_rsp; 297 p_rsp += 2; 298 299 UINT16_TO_BE_STREAM(p_rsp, error_code); 300 301 /* Unplugfest example traces do not have any error text */ 302 if (p_error_text) 303 ARRAY_TO_BE_STREAM(p_rsp, p_error_text, (int)strlen(p_error_text)); 304 305 /* Go back and put the parameter length into the buffer */ 306 rsp_param_len = p_rsp - p_rsp_param_len - 2; 307 UINT16_TO_BE_STREAM(p_rsp_param_len, rsp_param_len); 308 309 /* Set the length of the SDP data in the buffer */ 310 p_buf->len = p_rsp - p_rsp_start; 311 312 /* Send the buffer through L2CAP */ 313 L2CA_DataWrite(p_ccb->connection_id, p_buf); 314 } 315 316 /******************************************************************************* 317 * 318 * Function sdpu_extract_uid_seq 319 * 320 * Description This function extracts a UUID sequence from the passed input 321 * buffer, and puts it into the passed output list. 322 * 323 * Returns Pointer to next byte in the input buffer after the sequence. 324 * 325 ******************************************************************************/ 326 uint8_t* sdpu_extract_uid_seq(uint8_t* p, uint16_t param_len, 327 tSDP_UUID_SEQ* p_seq) { 328 uint8_t* p_seq_end; 329 uint8_t descr, type, size; 330 uint32_t seq_len, uuid_len; 331 332 /* Assume none found */ 333 p_seq->num_uids = 0; 334 335 /* A UID sequence is composed of a bunch of UIDs. */ 336 if (sizeof(descr) > param_len) return (NULL); 337 param_len -= sizeof(descr); 338 339 BE_STREAM_TO_UINT8(descr, p); 340 type = descr >> 3; 341 size = descr & 7; 342 343 if (type != DATA_ELE_SEQ_DESC_TYPE) return (NULL); 344 345 switch (size) { 346 case SIZE_TWO_BYTES: 347 seq_len = 2; 348 break; 349 case SIZE_FOUR_BYTES: 350 seq_len = 4; 351 break; 352 case SIZE_SIXTEEN_BYTES: 353 seq_len = 16; 354 break; 355 case SIZE_IN_NEXT_BYTE: 356 if (sizeof(uint8_t) > param_len) return (NULL); 357 param_len -= sizeof(uint8_t); 358 BE_STREAM_TO_UINT8(seq_len, p); 359 break; 360 case SIZE_IN_NEXT_WORD: 361 if (sizeof(uint16_t) > param_len) return (NULL); 362 param_len -= sizeof(uint16_t); 363 BE_STREAM_TO_UINT16(seq_len, p); 364 break; 365 case SIZE_IN_NEXT_LONG: 366 if (sizeof(uint32_t) > param_len) return (NULL); 367 param_len -= sizeof(uint32_t); 368 BE_STREAM_TO_UINT32(seq_len, p); 369 break; 370 default: 371 return (NULL); 372 } 373 374 if (seq_len > param_len) return (NULL); 375 376 p_seq_end = p + seq_len; 377 378 /* Loop through, extracting the UIDs */ 379 for (; p < p_seq_end;) { 380 BE_STREAM_TO_UINT8(descr, p); 381 type = descr >> 3; 382 size = descr & 7; 383 384 if (type != UUID_DESC_TYPE) return (NULL); 385 386 switch (size) { 387 case SIZE_TWO_BYTES: 388 uuid_len = 2; 389 break; 390 case SIZE_FOUR_BYTES: 391 uuid_len = 4; 392 break; 393 case SIZE_SIXTEEN_BYTES: 394 uuid_len = 16; 395 break; 396 case SIZE_IN_NEXT_BYTE: 397 if (p + sizeof(uint8_t) > p_seq_end) return NULL; 398 BE_STREAM_TO_UINT8(uuid_len, p); 399 break; 400 case SIZE_IN_NEXT_WORD: 401 if (p + sizeof(uint16_t) > p_seq_end) return NULL; 402 BE_STREAM_TO_UINT16(uuid_len, p); 403 break; 404 case SIZE_IN_NEXT_LONG: 405 if (p + sizeof(uint32_t) > p_seq_end) return NULL; 406 BE_STREAM_TO_UINT32(uuid_len, p); 407 break; 408 default: 409 return (NULL); 410 } 411 412 /* If UUID length is valid, copy it across */ 413 if (((uuid_len == 2) || (uuid_len == 4) || (uuid_len == 16)) && 414 (p + uuid_len <= p_seq_end)) { 415 p_seq->uuid_entry[p_seq->num_uids].len = (uint16_t)uuid_len; 416 BE_STREAM_TO_ARRAY(p, p_seq->uuid_entry[p_seq->num_uids].value, 417 (int)uuid_len); 418 p_seq->num_uids++; 419 } else 420 return (NULL); 421 422 /* We can only do so many */ 423 if (p_seq->num_uids >= MAX_UUIDS_PER_SEQ) return (NULL); 424 } 425 426 if (p != p_seq_end) return (NULL); 427 428 return (p); 429 } 430 431 /******************************************************************************* 432 * 433 * Function sdpu_extract_attr_seq 434 * 435 * Description This function extracts an attribute sequence from the passed 436 * input buffer, and puts it into the passed output list. 437 * 438 * Returns Pointer to next byte in the input buffer after the sequence. 439 * 440 ******************************************************************************/ 441 uint8_t* sdpu_extract_attr_seq(uint8_t* p, uint16_t param_len, 442 tSDP_ATTR_SEQ* p_seq) { 443 uint8_t* p_end_list; 444 uint8_t descr, type, size; 445 uint32_t list_len, attr_len; 446 447 /* Assume none found */ 448 p_seq->num_attr = 0; 449 450 /* Get attribute sequence info */ 451 if (param_len < sizeof(descr)) return NULL; 452 param_len -= sizeof(descr); 453 BE_STREAM_TO_UINT8(descr, p); 454 type = descr >> 3; 455 size = descr & 7; 456 457 if (type != DATA_ELE_SEQ_DESC_TYPE) return NULL; 458 459 switch (size) { 460 case SIZE_IN_NEXT_BYTE: 461 if (param_len < sizeof(uint8_t)) return NULL; 462 param_len -= sizeof(uint8_t); 463 BE_STREAM_TO_UINT8(list_len, p); 464 break; 465 466 case SIZE_IN_NEXT_WORD: 467 if (param_len < sizeof(uint16_t)) return NULL; 468 param_len -= sizeof(uint16_t); 469 BE_STREAM_TO_UINT16(list_len, p); 470 break; 471 472 case SIZE_IN_NEXT_LONG: 473 if (param_len < sizeof(uint32_t)) return NULL; 474 param_len -= sizeof(uint32_t); 475 BE_STREAM_TO_UINT32(list_len, p); 476 break; 477 478 default: 479 return NULL; 480 } 481 482 if (list_len > param_len) return NULL; 483 484 p_end_list = p + list_len; 485 486 /* Loop through, extracting the attribute IDs */ 487 for (; p < p_end_list;) { 488 BE_STREAM_TO_UINT8(descr, p); 489 type = descr >> 3; 490 size = descr & 7; 491 492 if (type != UINT_DESC_TYPE) return NULL; 493 494 switch (size) { 495 case SIZE_TWO_BYTES: 496 attr_len = 2; 497 break; 498 case SIZE_FOUR_BYTES: 499 attr_len = 4; 500 break; 501 case SIZE_IN_NEXT_BYTE: 502 if (p + sizeof(uint8_t) > p_end_list) return NULL; 503 BE_STREAM_TO_UINT8(attr_len, p); 504 break; 505 case SIZE_IN_NEXT_WORD: 506 if (p + sizeof(uint16_t) > p_end_list) return NULL; 507 BE_STREAM_TO_UINT16(attr_len, p); 508 break; 509 case SIZE_IN_NEXT_LONG: 510 if (p + sizeof(uint32_t) > p_end_list) return NULL; 511 BE_STREAM_TO_UINT32(attr_len, p); 512 break; 513 default: 514 return NULL; 515 break; 516 } 517 518 /* Attribute length must be 2-bytes or 4-bytes for a paired entry. */ 519 if (p + attr_len > p_end_list) return NULL; 520 if (attr_len == 2) { 521 BE_STREAM_TO_UINT16(p_seq->attr_entry[p_seq->num_attr].start, p); 522 p_seq->attr_entry[p_seq->num_attr].end = 523 p_seq->attr_entry[p_seq->num_attr].start; 524 } else if (attr_len == 4) { 525 BE_STREAM_TO_UINT16(p_seq->attr_entry[p_seq->num_attr].start, p); 526 BE_STREAM_TO_UINT16(p_seq->attr_entry[p_seq->num_attr].end, p); 527 } else 528 return (NULL); 529 530 /* We can only do so many */ 531 if (++p_seq->num_attr >= MAX_ATTR_PER_SEQ) return (NULL); 532 } 533 534 return (p); 535 } 536 537 /******************************************************************************* 538 * 539 * Function sdpu_get_len_from_type 540 * 541 * Description This function gets the length 542 * 543 * Returns void 544 * 545 ******************************************************************************/ 546 uint8_t* sdpu_get_len_from_type(uint8_t* p, uint8_t type, uint32_t* p_len) { 547 uint8_t u8; 548 uint16_t u16; 549 uint32_t u32; 550 551 switch (type & 7) { 552 case SIZE_ONE_BYTE: 553 *p_len = 1; 554 break; 555 case SIZE_TWO_BYTES: 556 *p_len = 2; 557 break; 558 case SIZE_FOUR_BYTES: 559 *p_len = 4; 560 break; 561 case SIZE_EIGHT_BYTES: 562 *p_len = 8; 563 break; 564 case SIZE_SIXTEEN_BYTES: 565 *p_len = 16; 566 break; 567 case SIZE_IN_NEXT_BYTE: 568 BE_STREAM_TO_UINT8(u8, p); 569 *p_len = u8; 570 break; 571 case SIZE_IN_NEXT_WORD: 572 BE_STREAM_TO_UINT16(u16, p); 573 *p_len = u16; 574 break; 575 case SIZE_IN_NEXT_LONG: 576 BE_STREAM_TO_UINT32(u32, p); 577 *p_len = (uint16_t)u32; 578 break; 579 } 580 581 return (p); 582 } 583 584 /******************************************************************************* 585 * 586 * Function sdpu_is_base_uuid 587 * 588 * Description This function checks a 128-bit UUID with the base to see if 589 * it matches. Only the last 12 bytes are compared. 590 * 591 * Returns true if matched, else false 592 * 593 ******************************************************************************/ 594 bool sdpu_is_base_uuid(uint8_t* p_uuid) { 595 uint16_t xx; 596 597 for (xx = 4; xx < Uuid::kNumBytes128; xx++) 598 if (p_uuid[xx] != sdp_base_uuid[xx]) return (false); 599 600 /* If here, matched */ 601 return (true); 602 } 603 604 /******************************************************************************* 605 * 606 * Function sdpu_compare_uuid_arrays 607 * 608 * Description This function compares 2 BE UUIDs. If needed, they are 609 * expanded to 128-bit UUIDs, then compared. 610 * 611 * NOTE it is assumed that the arrays are in Big Endian format 612 * 613 * Returns true if matched, else false 614 * 615 ******************************************************************************/ 616 bool sdpu_compare_uuid_arrays(uint8_t* p_uuid1, uint32_t len1, uint8_t* p_uuid2, 617 uint16_t len2) { 618 uint8_t nu1[Uuid::kNumBytes128]; 619 uint8_t nu2[Uuid::kNumBytes128]; 620 621 if (((len1 != 2) && (len1 != 4) && (len1 != 16)) || 622 ((len2 != 2) && (len2 != 4) && (len2 != 16))) { 623 SDP_TRACE_ERROR("%s: invalid length", __func__); 624 return false; 625 } 626 627 /* If lengths match, do a straight compare */ 628 if (len1 == len2) { 629 if (len1 == 2) 630 return ((p_uuid1[0] == p_uuid2[0]) && (p_uuid1[1] == p_uuid2[1])); 631 if (len1 == 4) 632 return ((p_uuid1[0] == p_uuid2[0]) && (p_uuid1[1] == p_uuid2[1]) && 633 (p_uuid1[2] == p_uuid2[2]) && (p_uuid1[3] == p_uuid2[3])); 634 else 635 return (memcmp(p_uuid1, p_uuid2, (size_t)len1) == 0); 636 } else if (len1 > len2) { 637 /* If the len1 was 4-byte, (so len2 is 2-byte), compare on the fly */ 638 if (len1 == 4) { 639 return ((p_uuid1[0] == 0) && (p_uuid1[1] == 0) && 640 (p_uuid1[2] == p_uuid2[0]) && (p_uuid1[3] == p_uuid2[1])); 641 } else { 642 /* Normalize UUIDs to 16-byte form, then compare. Len1 must be 16 */ 643 memcpy(nu1, p_uuid1, Uuid::kNumBytes128); 644 memcpy(nu2, sdp_base_uuid, Uuid::kNumBytes128); 645 646 if (len2 == 4) 647 memcpy(nu2, p_uuid2, len2); 648 else if (len2 == 2) 649 memcpy(nu2 + 2, p_uuid2, len2); 650 651 return (memcmp(nu1, nu2, Uuid::kNumBytes128) == 0); 652 } 653 } else { 654 /* len2 is greater than len1 */ 655 /* If the len2 was 4-byte, (so len1 is 2-byte), compare on the fly */ 656 if (len2 == 4) { 657 return ((p_uuid2[0] == 0) && (p_uuid2[1] == 0) && 658 (p_uuid2[2] == p_uuid1[0]) && (p_uuid2[3] == p_uuid1[1])); 659 } else { 660 /* Normalize UUIDs to 16-byte form, then compare. Len1 must be 16 */ 661 memcpy(nu2, p_uuid2, Uuid::kNumBytes128); 662 memcpy(nu1, sdp_base_uuid, Uuid::kNumBytes128); 663 664 if (len1 == 4) 665 memcpy(nu1, p_uuid1, (size_t)len1); 666 else if (len1 == 2) 667 memcpy(nu1 + 2, p_uuid1, (size_t)len1); 668 669 return (memcmp(nu1, nu2, Uuid::kNumBytes128) == 0); 670 } 671 } 672 } 673 674 /******************************************************************************* 675 * 676 * Function sdpu_compare_uuid_with_attr 677 * 678 * Description This function compares a BT UUID structure with the UUID in 679 * an SDP attribute record. If needed, they are expanded to 680 * 128-bit UUIDs, then compared. 681 * 682 * NOTE - it is assumed that BT UUID structures are compressed to the 683 * smallest possible UUIDs (by removing the base SDP UUID). 684 * - it is also assumed that the discovery atribute is compressed 685 * to the smallest possible 686 * 687 * Returns true if matched, else false 688 * 689 ******************************************************************************/ 690 bool sdpu_compare_uuid_with_attr(const Uuid& uuid, tSDP_DISC_ATTR* p_attr) { 691 int len = uuid.GetShortestRepresentationSize(); 692 if (len == 2) return uuid.As16Bit() == p_attr->attr_value.v.u16; 693 if (len == 4) return uuid.As32Bit() == p_attr->attr_value.v.u32; 694 if (memcmp(uuid.To128BitBE().data(), (void*)p_attr->attr_value.v.array, 695 Uuid::kNumBytes128) == 0) 696 return (true); 697 698 return (false); 699 } 700 701 /******************************************************************************* 702 * 703 * Function sdpu_sort_attr_list 704 * 705 * Description sorts a list of attributes in numeric order from lowest to 706 * highest to conform to SDP specification 707 * 708 * Returns void 709 * 710 ******************************************************************************/ 711 void sdpu_sort_attr_list(uint16_t num_attr, tSDP_DISCOVERY_DB* p_db) { 712 uint16_t i; 713 uint16_t x; 714 715 /* Done if no attributes to sort */ 716 if (num_attr <= 1) { 717 return; 718 } else if (num_attr > SDP_MAX_ATTR_FILTERS) { 719 num_attr = SDP_MAX_ATTR_FILTERS; 720 } 721 722 num_attr--; /* for the for-loop */ 723 for (i = 0; i < num_attr;) { 724 if (p_db->attr_filters[i] > p_db->attr_filters[i + 1]) { 725 /* swap the attribute IDs and start from the beginning */ 726 x = p_db->attr_filters[i]; 727 p_db->attr_filters[i] = p_db->attr_filters[i + 1]; 728 p_db->attr_filters[i + 1] = x; 729 730 i = 0; 731 } else 732 i++; 733 } 734 } 735 736 /******************************************************************************* 737 * 738 * Function sdpu_get_list_len 739 * 740 * Description gets the total list length in the sdp database for a given 741 * uid sequence and attr sequence 742 * 743 * Returns void 744 * 745 ******************************************************************************/ 746 uint16_t sdpu_get_list_len(tSDP_UUID_SEQ* uid_seq, tSDP_ATTR_SEQ* attr_seq) { 747 tSDP_RECORD* p_rec; 748 uint16_t len = 0; 749 uint16_t len1; 750 751 for (p_rec = sdp_db_service_search(NULL, uid_seq); p_rec; 752 p_rec = sdp_db_service_search(p_rec, uid_seq)) { 753 len += 3; 754 755 len1 = sdpu_get_attrib_seq_len(p_rec, attr_seq); 756 757 if (len1 != 0) 758 len += len1; 759 else 760 len -= 3; 761 } 762 return len; 763 } 764 765 /******************************************************************************* 766 * 767 * Function sdpu_get_attrib_seq_len 768 * 769 * Description gets the length of the specific attributes in a given 770 * sdp record 771 * 772 * Returns void 773 * 774 ******************************************************************************/ 775 uint16_t sdpu_get_attrib_seq_len(tSDP_RECORD* p_rec, tSDP_ATTR_SEQ* attr_seq) { 776 tSDP_ATTRIBUTE* p_attr; 777 uint16_t len1 = 0; 778 uint16_t xx; 779 bool is_range = false; 780 uint16_t start_id = 0, end_id = 0; 781 782 for (xx = 0; xx < attr_seq->num_attr; xx++) { 783 if (!is_range) { 784 start_id = attr_seq->attr_entry[xx].start; 785 end_id = attr_seq->attr_entry[xx].end; 786 } 787 p_attr = sdp_db_find_attr_in_rec(p_rec, start_id, end_id); 788 if (p_attr) { 789 len1 += sdpu_get_attrib_entry_len(p_attr); 790 791 /* If doing a range, stick with this one till no more attributes found */ 792 if (start_id != end_id) { 793 /* Update for next time through */ 794 start_id = p_attr->id + 1; 795 xx--; 796 is_range = true; 797 } else 798 is_range = false; 799 } else 800 is_range = false; 801 } 802 return len1; 803 } 804 805 /******************************************************************************* 806 * 807 * Function sdpu_get_attrib_entry_len 808 * 809 * Description gets the length of a specific attribute 810 * 811 * Returns void 812 * 813 ******************************************************************************/ 814 uint16_t sdpu_get_attrib_entry_len(tSDP_ATTRIBUTE* p_attr) { 815 uint16_t len = 3; 816 817 /* the attribute is in the db record. 818 * assuming the attribute len is less than SDP_MAX_ATTR_LEN */ 819 switch (p_attr->type) { 820 case TEXT_STR_DESC_TYPE: /* 4 */ 821 case DATA_ELE_SEQ_DESC_TYPE: /* 6 */ 822 case DATA_ELE_ALT_DESC_TYPE: /* 7 */ 823 case URL_DESC_TYPE: /* 8 */ 824 #if (SDP_MAX_ATTR_LEN > 0xFFFF) 825 if (p_attr->len > 0xFFFF) { 826 len += 5; 827 } else 828 #endif /* 0xFFFF - 0xFF */ 829 #if (SDP_MAX_ATTR_LEN > 0xFF) 830 if (p_attr->len > 0xFF) { 831 len += 3; 832 } else 833 #endif /* 0xFF and less*/ 834 { 835 len += 2; 836 } 837 len += p_attr->len; 838 return len; 839 } 840 841 /* Now, the attribute value */ 842 switch (p_attr->len) { 843 case 1: 844 case 2: 845 case 4: 846 case 8: 847 case 16: 848 len += 1; 849 break; 850 default: 851 len += 2; 852 break; 853 } 854 855 len += p_attr->len; 856 return len; 857 } 858 859 /******************************************************************************* 860 * 861 * Function sdpu_build_partial_attrib_entry 862 * 863 * Description This function fills a buffer with partial attribute. It is 864 * assumed that the maximum size of any attribute is 256 bytes. 865 * 866 * p_out: output buffer 867 * p_attr: attribute to be copied partially into p_out 868 * rem_len: num bytes to copy into p_out 869 * offset: current start offset within the attr that needs to 870 * be copied 871 * 872 * Returns Pointer to next byte in the output buffer. 873 * offset is also updated 874 * 875 ******************************************************************************/ 876 uint8_t* sdpu_build_partial_attrib_entry(uint8_t* p_out, tSDP_ATTRIBUTE* p_attr, 877 uint16_t len, uint16_t* offset) { 878 uint8_t* p_attr_buff = 879 (uint8_t*)osi_malloc(sizeof(uint8_t) * SDP_MAX_ATTR_LEN); 880 sdpu_build_attrib_entry(p_attr_buff, p_attr); 881 882 uint16_t attr_len = sdpu_get_attrib_entry_len(p_attr); 883 884 if (len > SDP_MAX_ATTR_LEN) { 885 SDP_TRACE_ERROR("%s len %d exceeds SDP_MAX_ATTR_LEN", __func__, len); 886 len = SDP_MAX_ATTR_LEN; 887 } 888 889 size_t len_to_copy = 890 ((attr_len - *offset) < len) ? (attr_len - *offset) : len; 891 memcpy(p_out, &p_attr_buff[*offset], len_to_copy); 892 893 p_out = &p_out[len_to_copy]; 894 *offset += len_to_copy; 895 896 osi_free(p_attr_buff); 897 return p_out; 898 } 899