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