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 discovery functions 22 * 23 ******************************************************************************/ 24 25 #include <stdio.h> 26 #include <stdlib.h> 27 #include <string.h> 28 29 #include "bt_common.h" 30 #include "bt_target.h" 31 #include "btm_api.h" 32 #include "btu.h" 33 #include "hcidefs.h" 34 #include "hcimsgs.h" 35 #include "l2cdefs.h" 36 #include "log/log.h" 37 #include "sdp_api.h" 38 #include "sdpint.h" 39 40 using bluetooth::Uuid; 41 42 #ifndef SDP_DEBUG_RAW 43 #define SDP_DEBUG_RAW false 44 #endif 45 46 /******************************************************************************/ 47 /* L O C A L F U N C T I O N P R O T O T Y P E S */ 48 /******************************************************************************/ 49 static void process_service_search_rsp(tCONN_CB* p_ccb, uint8_t* p_reply, 50 uint8_t* p_reply_end); 51 static void process_service_attr_rsp(tCONN_CB* p_ccb, uint8_t* p_reply, 52 uint8_t* p_reply_end); 53 static void process_service_search_attr_rsp(tCONN_CB* p_ccb, uint8_t* p_reply, 54 uint8_t* p_reply_end); 55 static uint8_t* save_attr_seq(tCONN_CB* p_ccb, uint8_t* p, uint8_t* p_msg_end); 56 static tSDP_DISC_REC* add_record(tSDP_DISCOVERY_DB* p_db, 57 const RawAddress& p_bda); 58 static uint8_t* add_attr(uint8_t* p, tSDP_DISCOVERY_DB* p_db, 59 tSDP_DISC_REC* p_rec, uint16_t attr_id, 60 tSDP_DISC_ATTR* p_parent_attr, uint8_t nest_level); 61 62 /* Safety check in case we go crazy */ 63 #define MAX_NEST_LEVELS 5 64 65 /******************************************************************************* 66 * 67 * Function sdpu_build_uuid_seq 68 * 69 * Description This function builds a UUID sequence from the list of 70 * passed UUIDs. It is also passed the address of the output 71 * buffer. 72 * 73 * Returns Pointer to next byte in the output buffer. 74 * 75 ******************************************************************************/ 76 static uint8_t* sdpu_build_uuid_seq(uint8_t* p_out, uint16_t num_uuids, 77 Uuid* p_uuid_list) { 78 uint16_t xx; 79 uint8_t* p_len; 80 81 /* First thing is the data element header */ 82 UINT8_TO_BE_STREAM(p_out, (DATA_ELE_SEQ_DESC_TYPE << 3) | SIZE_IN_NEXT_BYTE); 83 84 /* Remember where the length goes. Leave space for it. */ 85 p_len = p_out; 86 p_out += 1; 87 88 /* Now, loop through and put in all the UUID(s) */ 89 for (xx = 0; xx < num_uuids; xx++, p_uuid_list++) { 90 int len = p_uuid_list->GetShortestRepresentationSize(); 91 if (len == Uuid::kNumBytes16) { 92 UINT8_TO_BE_STREAM(p_out, (UUID_DESC_TYPE << 3) | SIZE_TWO_BYTES); 93 UINT16_TO_BE_STREAM(p_out, p_uuid_list->As16Bit()); 94 } else if (len == Uuid::kNumBytes32) { 95 UINT8_TO_BE_STREAM(p_out, (UUID_DESC_TYPE << 3) | SIZE_FOUR_BYTES); 96 UINT32_TO_BE_STREAM(p_out, p_uuid_list->As32Bit()); 97 } else if (len == Uuid::kNumBytes128) { 98 UINT8_TO_BE_STREAM(p_out, (UUID_DESC_TYPE << 3) | SIZE_SIXTEEN_BYTES); 99 ARRAY_TO_BE_STREAM(p_out, p_uuid_list->To128BitBE(), 100 (int)Uuid::kNumBytes128); 101 } else { 102 DCHECK(0) << "SDP: Passed UUID has invalid length " << len; 103 } 104 } 105 106 /* Now, put in the length */ 107 xx = (uint16_t)(p_out - p_len - 1); 108 UINT8_TO_BE_STREAM(p_len, xx); 109 110 return (p_out); 111 } 112 113 /******************************************************************************* 114 * 115 * Function sdp_snd_service_search_req 116 * 117 * Description Send a service search request to the SDP server. 118 * 119 * Returns void 120 * 121 ******************************************************************************/ 122 static void sdp_snd_service_search_req(tCONN_CB* p_ccb, uint8_t cont_len, 123 uint8_t* p_cont) { 124 uint8_t *p, *p_start, *p_param_len; 125 BT_HDR* p_cmd = (BT_HDR*)osi_malloc(SDP_DATA_BUF_SIZE); 126 uint16_t param_len; 127 128 /* Prepare the buffer for sending the packet to L2CAP */ 129 p_cmd->offset = L2CAP_MIN_OFFSET; 130 p = p_start = (uint8_t*)(p_cmd + 1) + L2CAP_MIN_OFFSET; 131 132 /* Build a service search request packet */ 133 UINT8_TO_BE_STREAM(p, SDP_PDU_SERVICE_SEARCH_REQ); 134 UINT16_TO_BE_STREAM(p, p_ccb->transaction_id); 135 p_ccb->transaction_id++; 136 137 /* Skip the length, we need to add it at the end */ 138 p_param_len = p; 139 p += 2; 140 141 /* Build the UID sequence. */ 142 #if (SDP_BROWSE_PLUS == TRUE) 143 p = sdpu_build_uuid_seq(p, 1, 144 &p_ccb->p_db->uuid_filters[p_ccb->cur_uuid_idx]); 145 #else 146 p = sdpu_build_uuid_seq(p, p_ccb->p_db->num_uuid_filters, 147 p_ccb->p_db->uuid_filters); 148 #endif 149 150 /* Set max service record count */ 151 UINT16_TO_BE_STREAM(p, sdp_cb.max_recs_per_search); 152 153 /* Set continuation state */ 154 UINT8_TO_BE_STREAM(p, cont_len); 155 156 /* if this is not the first request */ 157 if (cont_len && p_cont) { 158 memcpy(p, p_cont, cont_len); 159 p += cont_len; 160 } 161 162 /* Go back and put the parameter length into the buffer */ 163 param_len = (uint16_t)(p - p_param_len - 2); 164 UINT16_TO_BE_STREAM(p_param_len, param_len); 165 166 p_ccb->disc_state = SDP_DISC_WAIT_HANDLES; 167 168 /* Set the length of the SDP data in the buffer */ 169 p_cmd->len = (uint16_t)(p - p_start); 170 171 #if (SDP_DEBUG_RAW == TRUE) 172 SDP_TRACE_WARNING("sdp_snd_service_search_req cont_len :%d disc_state:%d", 173 cont_len, p_ccb->disc_state); 174 #endif 175 176 L2CA_DataWrite(p_ccb->connection_id, p_cmd); 177 178 /* Start inactivity timer */ 179 alarm_set_on_mloop(p_ccb->sdp_conn_timer, SDP_INACT_TIMEOUT_MS, 180 sdp_conn_timer_timeout, p_ccb); 181 } 182 183 /******************************************************************************* 184 * 185 * Function sdp_disc_connected 186 * 187 * Description This function is called when an SDP discovery attempt is 188 * connected. 189 * 190 * Returns void 191 * 192 ******************************************************************************/ 193 void sdp_disc_connected(tCONN_CB* p_ccb) { 194 if (p_ccb->is_attr_search) { 195 p_ccb->disc_state = SDP_DISC_WAIT_SEARCH_ATTR; 196 197 process_service_search_attr_rsp(p_ccb, NULL, NULL); 198 } else { 199 /* First step is to get a list of the handles from the server. */ 200 /* We are not searching for a specific attribute, so we will */ 201 /* first search for the service, then get all attributes of it */ 202 203 p_ccb->num_handles = 0; 204 sdp_snd_service_search_req(p_ccb, 0, NULL); 205 } 206 } 207 208 /******************************************************************************* 209 * 210 * Function sdp_disc_server_rsp 211 * 212 * Description This function is called when there is a response from 213 * the server. 214 * 215 * Returns void 216 * 217 ******************************************************************************/ 218 void sdp_disc_server_rsp(tCONN_CB* p_ccb, BT_HDR* p_msg) { 219 uint8_t *p, rsp_pdu; 220 bool invalid_pdu = true; 221 222 #if (SDP_DEBUG_RAW == TRUE) 223 SDP_TRACE_WARNING("sdp_disc_server_rsp disc_state:%d", p_ccb->disc_state); 224 #endif 225 226 /* stop inactivity timer when we receive a response */ 227 alarm_cancel(p_ccb->sdp_conn_timer); 228 229 /* Got a reply!! Check what we got back */ 230 p = (uint8_t*)(p_msg + 1) + p_msg->offset; 231 uint8_t* p_end = p + p_msg->len; 232 233 BE_STREAM_TO_UINT8(rsp_pdu, p); 234 235 p_msg->len--; 236 237 switch (rsp_pdu) { 238 case SDP_PDU_SERVICE_SEARCH_RSP: 239 if (p_ccb->disc_state == SDP_DISC_WAIT_HANDLES) { 240 process_service_search_rsp(p_ccb, p, p_end); 241 invalid_pdu = false; 242 } 243 break; 244 245 case SDP_PDU_SERVICE_ATTR_RSP: 246 if (p_ccb->disc_state == SDP_DISC_WAIT_ATTR) { 247 process_service_attr_rsp(p_ccb, p, p_end); 248 invalid_pdu = false; 249 } 250 break; 251 252 case SDP_PDU_SERVICE_SEARCH_ATTR_RSP: 253 if (p_ccb->disc_state == SDP_DISC_WAIT_SEARCH_ATTR) { 254 process_service_search_attr_rsp(p_ccb, p, p_end); 255 invalid_pdu = false; 256 } 257 break; 258 } 259 260 if (invalid_pdu) { 261 SDP_TRACE_WARNING("SDP - Unexp. PDU: %d in state: %d", rsp_pdu, 262 p_ccb->disc_state); 263 sdp_disconnect(p_ccb, SDP_GENERIC_ERROR); 264 } 265 } 266 267 /****************************************************************************** 268 * 269 * Function process_service_search_rsp 270 * 271 * Description This function is called when there is a search response from 272 * the server. 273 * 274 * Returns void 275 * 276 ******************************************************************************/ 277 static void process_service_search_rsp(tCONN_CB* p_ccb, uint8_t* p_reply, 278 uint8_t* p_reply_end) { 279 uint16_t xx; 280 uint16_t total, cur_handles, orig; 281 uint8_t cont_len; 282 283 /* Skip transaction, and param len */ 284 p_reply += 4; 285 BE_STREAM_TO_UINT16(total, p_reply); 286 BE_STREAM_TO_UINT16(cur_handles, p_reply); 287 288 orig = p_ccb->num_handles; 289 p_ccb->num_handles += cur_handles; 290 if (p_ccb->num_handles == 0) { 291 SDP_TRACE_WARNING("SDP - Rcvd ServiceSearchRsp, no matches"); 292 sdp_disconnect(p_ccb, SDP_NO_RECS_MATCH); 293 return; 294 } 295 296 /* Save the handles that match. We will can only process a certain number. */ 297 if (total > sdp_cb.max_recs_per_search) total = sdp_cb.max_recs_per_search; 298 if (p_ccb->num_handles > sdp_cb.max_recs_per_search) 299 p_ccb->num_handles = sdp_cb.max_recs_per_search; 300 301 for (xx = orig; xx < p_ccb->num_handles; xx++) 302 BE_STREAM_TO_UINT32(p_ccb->handles[xx], p_reply); 303 304 BE_STREAM_TO_UINT8(cont_len, p_reply); 305 if (cont_len != 0) { 306 if (cont_len > SDP_MAX_CONTINUATION_LEN) { 307 sdp_disconnect(p_ccb, SDP_INVALID_CONT_STATE); 308 return; 309 } 310 if (p_reply + cont_len > p_reply_end) { 311 android_errorWriteLog(0x534e4554, "68161546"); 312 sdp_disconnect(p_ccb, SDP_INVALID_CONT_STATE); 313 return; 314 } 315 /* stay in the same state */ 316 sdp_snd_service_search_req(p_ccb, cont_len, p_reply); 317 } else { 318 /* change state */ 319 p_ccb->disc_state = SDP_DISC_WAIT_ATTR; 320 321 /* Kick off the first attribute request */ 322 process_service_attr_rsp(p_ccb, NULL, NULL); 323 } 324 } 325 326 /******************************************************************************* 327 * 328 * Function sdp_copy_raw_data 329 * 330 * Description copy the raw data 331 * 332 * 333 * Returns void 334 * 335 ******************************************************************************/ 336 #if (SDP_RAW_DATA_INCLUDED == TRUE) 337 static void sdp_copy_raw_data(tCONN_CB* p_ccb, bool offset) { 338 unsigned int cpy_len, rem_len; 339 uint32_t list_len; 340 uint8_t* p; 341 uint8_t type; 342 343 #if (SDP_DEBUG_RAW == TRUE) 344 uint8_t num_array[SDP_MAX_LIST_BYTE_COUNT]; 345 uint32_t i; 346 347 for (i = 0; i < p_ccb->list_len; i++) { 348 snprintf((char*)&num_array[i * 2], sizeof(num_array) - i * 2, "%02X", 349 (uint8_t)(p_ccb->rsp_list[i])); 350 } 351 SDP_TRACE_WARNING("result :%s", num_array); 352 #endif 353 354 if (p_ccb->p_db->raw_data) { 355 cpy_len = p_ccb->p_db->raw_size - p_ccb->p_db->raw_used; 356 list_len = p_ccb->list_len; 357 p = &p_ccb->rsp_list[0]; 358 359 if (offset) { 360 type = *p++; 361 p = sdpu_get_len_from_type(p, type, &list_len); 362 } 363 if (list_len < cpy_len) { 364 cpy_len = list_len; 365 } 366 rem_len = SDP_MAX_LIST_BYTE_COUNT - (unsigned int)(p - &p_ccb->rsp_list[0]); 367 if (cpy_len > rem_len) { 368 SDP_TRACE_WARNING("rem_len :%d less than cpy_len:%d", rem_len, cpy_len); 369 cpy_len = rem_len; 370 } 371 SDP_TRACE_WARNING( 372 "%s: list_len:%d cpy_len:%d p:%p p_ccb:%p p_db:%p raw_size:%d " 373 "raw_used:%d raw_data:%p", 374 __func__, list_len, cpy_len, p, p_ccb, p_ccb->p_db, 375 p_ccb->p_db->raw_size, p_ccb->p_db->raw_used, p_ccb->p_db->raw_data); 376 memcpy(&p_ccb->p_db->raw_data[p_ccb->p_db->raw_used], p, cpy_len); 377 p_ccb->p_db->raw_used += cpy_len; 378 } 379 } 380 #endif 381 382 /******************************************************************************* 383 * 384 * Function process_service_attr_rsp 385 * 386 * Description This function is called when there is a attribute response 387 * from the server. 388 * 389 * Returns void 390 * 391 ******************************************************************************/ 392 static void process_service_attr_rsp(tCONN_CB* p_ccb, uint8_t* p_reply, 393 uint8_t* p_reply_end) { 394 uint8_t *p_start, *p_param_len; 395 uint16_t param_len, list_byte_count; 396 bool cont_request_needed = false; 397 398 #if (SDP_DEBUG_RAW == TRUE) 399 SDP_TRACE_WARNING("process_service_attr_rsp raw inc:%d", 400 SDP_RAW_DATA_INCLUDED); 401 #endif 402 /* If p_reply is NULL, we were called after the records handles were read */ 403 if (p_reply) { 404 #if (SDP_DEBUG_RAW == TRUE) 405 SDP_TRACE_WARNING("ID & len: 0x%02x-%02x-%02x-%02x", p_reply[0], p_reply[1], 406 p_reply[2], p_reply[3]); 407 #endif 408 /* Skip transaction ID and length */ 409 p_reply += 4; 410 411 BE_STREAM_TO_UINT16(list_byte_count, p_reply); 412 #if (SDP_DEBUG_RAW == TRUE) 413 SDP_TRACE_WARNING("list_byte_count:%d", list_byte_count); 414 #endif 415 416 /* Copy the response to the scratchpad. First, a safety check on the length 417 */ 418 if ((p_ccb->list_len + list_byte_count) > SDP_MAX_LIST_BYTE_COUNT) { 419 sdp_disconnect(p_ccb, SDP_INVALID_PDU_SIZE); 420 return; 421 } 422 423 #if (SDP_DEBUG_RAW == TRUE) 424 SDP_TRACE_WARNING("list_len: %d, list_byte_count: %d", p_ccb->list_len, 425 list_byte_count); 426 #endif 427 if (p_ccb->rsp_list == NULL) 428 p_ccb->rsp_list = (uint8_t*)osi_malloc(SDP_MAX_LIST_BYTE_COUNT); 429 memcpy(&p_ccb->rsp_list[p_ccb->list_len], p_reply, list_byte_count); 430 p_ccb->list_len += list_byte_count; 431 p_reply += list_byte_count; 432 #if (SDP_DEBUG_RAW == TRUE) 433 SDP_TRACE_WARNING("list_len: %d(attr_rsp)", p_ccb->list_len); 434 435 /* Check if we need to request a continuation */ 436 SDP_TRACE_WARNING("*p_reply:%d(%d)", *p_reply, SDP_MAX_CONTINUATION_LEN); 437 #endif 438 if (*p_reply) { 439 if (*p_reply > SDP_MAX_CONTINUATION_LEN) { 440 sdp_disconnect(p_ccb, SDP_INVALID_CONT_STATE); 441 return; 442 } 443 cont_request_needed = true; 444 } else { 445 #if (SDP_RAW_DATA_INCLUDED == TRUE) 446 SDP_TRACE_WARNING("process_service_attr_rsp"); 447 sdp_copy_raw_data(p_ccb, false); 448 #endif 449 450 /* Save the response in the database. Stop on any error */ 451 if (!save_attr_seq(p_ccb, &p_ccb->rsp_list[0], 452 &p_ccb->rsp_list[p_ccb->list_len])) { 453 sdp_disconnect(p_ccb, SDP_DB_FULL); 454 return; 455 } 456 p_ccb->list_len = 0; 457 p_ccb->cur_handle++; 458 } 459 } 460 461 /* Now, ask for the next handle. Re-use the buffer we just got. */ 462 if (p_ccb->cur_handle < p_ccb->num_handles) { 463 BT_HDR* p_msg = (BT_HDR*)osi_malloc(SDP_DATA_BUF_SIZE); 464 uint8_t* p; 465 466 p_msg->offset = L2CAP_MIN_OFFSET; 467 p = p_start = (uint8_t*)(p_msg + 1) + L2CAP_MIN_OFFSET; 468 469 /* Get all the attributes from the server */ 470 UINT8_TO_BE_STREAM(p, SDP_PDU_SERVICE_ATTR_REQ); 471 UINT16_TO_BE_STREAM(p, p_ccb->transaction_id); 472 p_ccb->transaction_id++; 473 474 /* Skip the length, we need to add it at the end */ 475 p_param_len = p; 476 p += 2; 477 478 UINT32_TO_BE_STREAM(p, p_ccb->handles[p_ccb->cur_handle]); 479 480 /* Max attribute byte count */ 481 UINT16_TO_BE_STREAM(p, sdp_cb.max_attr_list_size); 482 483 /* If no attribute filters, build a wildcard attribute sequence */ 484 if (p_ccb->p_db->num_attr_filters) 485 p = sdpu_build_attrib_seq(p, p_ccb->p_db->attr_filters, 486 p_ccb->p_db->num_attr_filters); 487 else 488 p = sdpu_build_attrib_seq(p, NULL, 0); 489 490 /* Was this a continuation request ? */ 491 if (cont_request_needed) { 492 if ((p_reply + *p_reply + 1) <= p_reply_end) { 493 memcpy(p, p_reply, *p_reply + 1); 494 p += *p_reply + 1; 495 } else { 496 android_errorWriteLog(0x534e4554, "68161546"); 497 } 498 } else 499 UINT8_TO_BE_STREAM(p, 0); 500 501 /* Go back and put the parameter length into the buffer */ 502 param_len = (uint16_t)(p - p_param_len - 2); 503 UINT16_TO_BE_STREAM(p_param_len, param_len); 504 505 /* Set the length of the SDP data in the buffer */ 506 p_msg->len = (uint16_t)(p - p_start); 507 508 L2CA_DataWrite(p_ccb->connection_id, p_msg); 509 510 /* Start inactivity timer */ 511 alarm_set_on_mloop(p_ccb->sdp_conn_timer, SDP_INACT_TIMEOUT_MS, 512 sdp_conn_timer_timeout, p_ccb); 513 } else { 514 sdp_disconnect(p_ccb, SDP_SUCCESS); 515 return; 516 } 517 } 518 519 /******************************************************************************* 520 * 521 * Function process_service_search_attr_rsp 522 * 523 * Description This function is called when there is a search attribute 524 * response from the server. 525 * 526 * Returns void 527 * 528 ******************************************************************************/ 529 static void process_service_search_attr_rsp(tCONN_CB* p_ccb, uint8_t* p_reply, 530 uint8_t* p_reply_end) { 531 uint8_t *p, *p_start, *p_end, *p_param_len; 532 uint8_t type; 533 uint32_t seq_len; 534 uint16_t param_len, lists_byte_count = 0; 535 bool cont_request_needed = false; 536 537 #if (SDP_DEBUG_RAW == TRUE) 538 SDP_TRACE_WARNING("process_service_search_attr_rsp"); 539 #endif 540 /* If p_reply is NULL, we were called for the initial read */ 541 if (p_reply) { 542 if (p_reply + 4 /* transaction ID and length */ + sizeof(lists_byte_count) > 543 p_reply_end) { 544 android_errorWriteLog(0x534e4554, "79884292"); 545 sdp_disconnect(p_ccb, SDP_INVALID_PDU_SIZE); 546 return; 547 } 548 549 #if (SDP_DEBUG_RAW == TRUE) 550 SDP_TRACE_WARNING("ID & len: 0x%02x-%02x-%02x-%02x", p_reply[0], p_reply[1], 551 p_reply[2], p_reply[3]); 552 #endif 553 /* Skip transaction ID and length */ 554 p_reply += 4; 555 556 BE_STREAM_TO_UINT16(lists_byte_count, p_reply); 557 #if (SDP_DEBUG_RAW == TRUE) 558 SDP_TRACE_WARNING("lists_byte_count:%d", lists_byte_count); 559 #endif 560 561 /* Copy the response to the scratchpad. First, a safety check on the length 562 */ 563 if ((p_ccb->list_len + lists_byte_count) > SDP_MAX_LIST_BYTE_COUNT) { 564 sdp_disconnect(p_ccb, SDP_INVALID_PDU_SIZE); 565 return; 566 } 567 568 #if (SDP_DEBUG_RAW == TRUE) 569 SDP_TRACE_WARNING("list_len: %d, list_byte_count: %d", p_ccb->list_len, 570 lists_byte_count); 571 #endif 572 573 if (p_reply + lists_byte_count + 1 /* continuation */ > p_reply_end) { 574 android_errorWriteLog(0x534e4554, "79884292"); 575 sdp_disconnect(p_ccb, SDP_INVALID_PDU_SIZE); 576 return; 577 } 578 579 if (p_ccb->rsp_list == NULL) 580 p_ccb->rsp_list = (uint8_t*)osi_malloc(SDP_MAX_LIST_BYTE_COUNT); 581 memcpy(&p_ccb->rsp_list[p_ccb->list_len], p_reply, lists_byte_count); 582 p_ccb->list_len += lists_byte_count; 583 p_reply += lists_byte_count; 584 #if (SDP_DEBUG_RAW == TRUE) 585 SDP_TRACE_WARNING("list_len: %d(search_attr_rsp)", p_ccb->list_len); 586 587 /* Check if we need to request a continuation */ 588 SDP_TRACE_WARNING("*p_reply:%d(%d)", *p_reply, SDP_MAX_CONTINUATION_LEN); 589 #endif 590 if (*p_reply) { 591 if (*p_reply > SDP_MAX_CONTINUATION_LEN) { 592 sdp_disconnect(p_ccb, SDP_INVALID_CONT_STATE); 593 return; 594 } 595 596 cont_request_needed = true; 597 } 598 } 599 600 #if (SDP_DEBUG_RAW == TRUE) 601 SDP_TRACE_WARNING("cont_request_needed:%d", cont_request_needed); 602 #endif 603 /* If continuation request (or first time request) */ 604 if ((cont_request_needed) || (!p_reply)) { 605 BT_HDR* p_msg = (BT_HDR*)osi_malloc(SDP_DATA_BUF_SIZE); 606 uint8_t* p; 607 608 p_msg->offset = L2CAP_MIN_OFFSET; 609 p = p_start = (uint8_t*)(p_msg + 1) + L2CAP_MIN_OFFSET; 610 611 /* Build a service search request packet */ 612 UINT8_TO_BE_STREAM(p, SDP_PDU_SERVICE_SEARCH_ATTR_REQ); 613 UINT16_TO_BE_STREAM(p, p_ccb->transaction_id); 614 p_ccb->transaction_id++; 615 616 /* Skip the length, we need to add it at the end */ 617 p_param_len = p; 618 p += 2; 619 620 /* Build the UID sequence. */ 621 #if (SDP_BROWSE_PLUS == TRUE) 622 p = sdpu_build_uuid_seq(p, 1, 623 &p_ccb->p_db->uuid_filters[p_ccb->cur_uuid_idx]); 624 #else 625 p = sdpu_build_uuid_seq(p, p_ccb->p_db->num_uuid_filters, 626 p_ccb->p_db->uuid_filters); 627 #endif 628 629 /* Max attribute byte count */ 630 UINT16_TO_BE_STREAM(p, sdp_cb.max_attr_list_size); 631 632 /* If no attribute filters, build a wildcard attribute sequence */ 633 if (p_ccb->p_db->num_attr_filters) 634 p = sdpu_build_attrib_seq(p, p_ccb->p_db->attr_filters, 635 p_ccb->p_db->num_attr_filters); 636 else 637 p = sdpu_build_attrib_seq(p, NULL, 0); 638 639 /* No continuation for first request */ 640 if (p_reply) { 641 if ((p_reply + *p_reply + 1) <= p_reply_end) { 642 memcpy(p, p_reply, *p_reply + 1); 643 p += *p_reply + 1; 644 } else { 645 android_errorWriteLog(0x534e4554, "68161546"); 646 } 647 } else 648 UINT8_TO_BE_STREAM(p, 0); 649 650 /* Go back and put the parameter length into the buffer */ 651 param_len = p - p_param_len - 2; 652 UINT16_TO_BE_STREAM(p_param_len, param_len); 653 654 /* Set the length of the SDP data in the buffer */ 655 p_msg->len = p - p_start; 656 657 L2CA_DataWrite(p_ccb->connection_id, p_msg); 658 659 /* Start inactivity timer */ 660 alarm_set_on_mloop(p_ccb->sdp_conn_timer, SDP_INACT_TIMEOUT_MS, 661 sdp_conn_timer_timeout, p_ccb); 662 663 return; 664 } 665 666 /*******************************************************************/ 667 /* We now have the full response, which is a sequence of sequences */ 668 /*******************************************************************/ 669 670 #if (SDP_RAW_DATA_INCLUDED == TRUE) 671 SDP_TRACE_WARNING("process_service_search_attr_rsp"); 672 sdp_copy_raw_data(p_ccb, true); 673 #endif 674 675 p = &p_ccb->rsp_list[0]; 676 677 /* The contents is a sequence of attribute sequences */ 678 type = *p++; 679 680 if ((type >> 3) != DATA_ELE_SEQ_DESC_TYPE) { 681 SDP_TRACE_WARNING("SDP - Wrong type: 0x%02x in attr_rsp", type); 682 return; 683 } 684 p = sdpu_get_len_from_type(p, type, &seq_len); 685 686 p_end = &p_ccb->rsp_list[p_ccb->list_len]; 687 688 if ((p + seq_len) != p_end) { 689 sdp_disconnect(p_ccb, SDP_INVALID_CONT_STATE); 690 return; 691 } 692 693 while (p < p_end) { 694 p = save_attr_seq(p_ccb, p, &p_ccb->rsp_list[p_ccb->list_len]); 695 if (!p) { 696 sdp_disconnect(p_ccb, SDP_DB_FULL); 697 return; 698 } 699 } 700 701 /* Since we got everything we need, disconnect the call */ 702 sdp_disconnect(p_ccb, SDP_SUCCESS); 703 } 704 705 /******************************************************************************* 706 * 707 * Function save_attr_seq 708 * 709 * Description This function is called when there is a response from 710 * the server. 711 * 712 * Returns pointer to next byte or NULL if error 713 * 714 ******************************************************************************/ 715 static uint8_t* save_attr_seq(tCONN_CB* p_ccb, uint8_t* p, uint8_t* p_msg_end) { 716 uint32_t seq_len, attr_len; 717 uint16_t attr_id; 718 uint8_t type, *p_seq_end; 719 tSDP_DISC_REC* p_rec; 720 721 type = *p++; 722 723 if ((type >> 3) != DATA_ELE_SEQ_DESC_TYPE) { 724 SDP_TRACE_WARNING("SDP - Wrong type: 0x%02x in attr_rsp", type); 725 return (NULL); 726 } 727 728 p = sdpu_get_len_from_type(p, type, &seq_len); 729 if ((p + seq_len) > p_msg_end) { 730 SDP_TRACE_WARNING("SDP - Bad len in attr_rsp %d", seq_len); 731 return (NULL); 732 } 733 734 /* Create a record */ 735 p_rec = add_record(p_ccb->p_db, p_ccb->device_address); 736 if (!p_rec) { 737 SDP_TRACE_WARNING("SDP - DB full add_record"); 738 return (NULL); 739 } 740 741 p_seq_end = p + seq_len; 742 743 while (p < p_seq_end) { 744 /* First get the attribute ID */ 745 type = *p++; 746 p = sdpu_get_len_from_type(p, type, &attr_len); 747 if (((type >> 3) != UINT_DESC_TYPE) || (attr_len != 2)) { 748 SDP_TRACE_WARNING("SDP - Bad type: 0x%02x or len: %d in attr_rsp", type, 749 attr_len); 750 return (NULL); 751 } 752 BE_STREAM_TO_UINT16(attr_id, p); 753 754 /* Now, add the attribute value */ 755 p = add_attr(p, p_ccb->p_db, p_rec, attr_id, NULL, 0); 756 757 if (!p) { 758 SDP_TRACE_WARNING("SDP - DB full add_attr"); 759 return (NULL); 760 } 761 } 762 763 return (p); 764 } 765 766 /******************************************************************************* 767 * 768 * Function add_record 769 * 770 * Description This function allocates space for a record from the DB. 771 * 772 * Returns pointer to next byte in data stream 773 * 774 ******************************************************************************/ 775 tSDP_DISC_REC* add_record(tSDP_DISCOVERY_DB* p_db, const RawAddress& p_bda) { 776 tSDP_DISC_REC* p_rec; 777 778 /* See if there is enough space in the database */ 779 if (p_db->mem_free < sizeof(tSDP_DISC_REC)) return (NULL); 780 781 p_rec = (tSDP_DISC_REC*)p_db->p_free_mem; 782 p_db->p_free_mem += sizeof(tSDP_DISC_REC); 783 p_db->mem_free -= sizeof(tSDP_DISC_REC); 784 785 p_rec->p_first_attr = NULL; 786 p_rec->p_next_rec = NULL; 787 788 p_rec->remote_bd_addr = p_bda; 789 790 /* Add the record to the end of chain */ 791 if (!p_db->p_first_rec) 792 p_db->p_first_rec = p_rec; 793 else { 794 tSDP_DISC_REC* p_rec1 = p_db->p_first_rec; 795 796 while (p_rec1->p_next_rec) p_rec1 = p_rec1->p_next_rec; 797 798 p_rec1->p_next_rec = p_rec; 799 } 800 801 return (p_rec); 802 } 803 804 #define SDP_ADDITIONAL_LIST_MASK 0x80 805 /******************************************************************************* 806 * 807 * Function add_attr 808 * 809 * Description This function allocates space for an attribute from the DB 810 * and copies the data into it. 811 * 812 * Returns pointer to next byte in data stream 813 * 814 ******************************************************************************/ 815 static uint8_t* add_attr(uint8_t* p, tSDP_DISCOVERY_DB* p_db, 816 tSDP_DISC_REC* p_rec, uint16_t attr_id, 817 tSDP_DISC_ATTR* p_parent_attr, uint8_t nest_level) { 818 tSDP_DISC_ATTR* p_attr; 819 uint32_t attr_len; 820 uint32_t total_len; 821 uint16_t attr_type; 822 uint16_t id; 823 uint8_t type; 824 uint8_t* p_end; 825 uint8_t is_additional_list = nest_level & SDP_ADDITIONAL_LIST_MASK; 826 827 nest_level &= ~(SDP_ADDITIONAL_LIST_MASK); 828 829 type = *p++; 830 p = sdpu_get_len_from_type(p, type, &attr_len); 831 832 attr_len &= SDP_DISC_ATTR_LEN_MASK; 833 attr_type = (type >> 3) & 0x0f; 834 835 /* See if there is enough space in the database */ 836 if (attr_len > 4) 837 total_len = attr_len - 4 + (uint16_t)sizeof(tSDP_DISC_ATTR); 838 else 839 total_len = sizeof(tSDP_DISC_ATTR); 840 841 /* Ensure it is a multiple of 4 */ 842 total_len = (total_len + 3) & ~3; 843 844 /* See if there is enough space in the database */ 845 if (p_db->mem_free < total_len) return (NULL); 846 847 p_attr = (tSDP_DISC_ATTR*)p_db->p_free_mem; 848 p_attr->attr_id = attr_id; 849 p_attr->attr_len_type = (uint16_t)attr_len | (attr_type << 12); 850 p_attr->p_next_attr = NULL; 851 852 /* Store the attribute value */ 853 switch (attr_type) { 854 case UINT_DESC_TYPE: 855 if ((is_additional_list != 0) && (attr_len == 2)) { 856 BE_STREAM_TO_UINT16(id, p); 857 if (id != ATTR_ID_PROTOCOL_DESC_LIST) 858 p -= 2; 859 else { 860 /* Reserve the memory for the attribute now, as we need to add 861 * sub-attributes */ 862 p_db->p_free_mem += sizeof(tSDP_DISC_ATTR); 863 p_db->mem_free -= sizeof(tSDP_DISC_ATTR); 864 p_end = p + attr_len; 865 total_len = 0; 866 867 /* SDP_TRACE_DEBUG ("SDP - attr nest level:%d(list)", nest_level); */ 868 if (nest_level >= MAX_NEST_LEVELS) { 869 SDP_TRACE_ERROR("SDP - attr nesting too deep"); 870 return (p_end); 871 } 872 873 /* Now, add the list entry */ 874 p = add_attr(p, p_db, p_rec, ATTR_ID_PROTOCOL_DESC_LIST, p_attr, 875 (uint8_t)(nest_level + 1)); 876 877 break; 878 } 879 } 880 /* Case falls through */ 881 882 case TWO_COMP_INT_DESC_TYPE: 883 switch (attr_len) { 884 case 1: 885 p_attr->attr_value.v.u8 = *p++; 886 break; 887 case 2: 888 BE_STREAM_TO_UINT16(p_attr->attr_value.v.u16, p); 889 break; 890 case 4: 891 BE_STREAM_TO_UINT32(p_attr->attr_value.v.u32, p); 892 break; 893 default: 894 BE_STREAM_TO_ARRAY(p, p_attr->attr_value.v.array, (int32_t)attr_len); 895 break; 896 } 897 break; 898 899 case UUID_DESC_TYPE: 900 switch (attr_len) { 901 case 2: 902 BE_STREAM_TO_UINT16(p_attr->attr_value.v.u16, p); 903 break; 904 case 4: 905 BE_STREAM_TO_UINT32(p_attr->attr_value.v.u32, p); 906 if (p_attr->attr_value.v.u32 < 0x10000) { 907 attr_len = 2; 908 p_attr->attr_len_type = (uint16_t)attr_len | (attr_type << 12); 909 p_attr->attr_value.v.u16 = (uint16_t)p_attr->attr_value.v.u32; 910 } 911 break; 912 case 16: 913 /* See if we can compress his UUID down to 16 or 32bit UUIDs */ 914 if (sdpu_is_base_uuid(p)) { 915 if ((p[0] == 0) && (p[1] == 0)) { 916 p_attr->attr_len_type = 917 (p_attr->attr_len_type & ~SDP_DISC_ATTR_LEN_MASK) | 2; 918 p += 2; 919 BE_STREAM_TO_UINT16(p_attr->attr_value.v.u16, p); 920 p += Uuid::kNumBytes128 - 4; 921 } else { 922 p_attr->attr_len_type = 923 (p_attr->attr_len_type & ~SDP_DISC_ATTR_LEN_MASK) | 4; 924 BE_STREAM_TO_UINT32(p_attr->attr_value.v.u32, p); 925 p += Uuid::kNumBytes128 - 4; 926 } 927 } else { 928 BE_STREAM_TO_ARRAY(p, p_attr->attr_value.v.array, 929 (int32_t)attr_len); 930 } 931 break; 932 default: 933 SDP_TRACE_WARNING("SDP - bad len in UUID attr: %d", attr_len); 934 return (p + attr_len); 935 } 936 break; 937 938 case DATA_ELE_SEQ_DESC_TYPE: 939 case DATA_ELE_ALT_DESC_TYPE: 940 /* Reserve the memory for the attribute now, as we need to add 941 * sub-attributes */ 942 p_db->p_free_mem += sizeof(tSDP_DISC_ATTR); 943 p_db->mem_free -= sizeof(tSDP_DISC_ATTR); 944 p_end = p + attr_len; 945 total_len = 0; 946 947 /* SDP_TRACE_DEBUG ("SDP - attr nest level:%d", nest_level); */ 948 if (nest_level >= MAX_NEST_LEVELS) { 949 SDP_TRACE_ERROR("SDP - attr nesting too deep"); 950 return (p_end); 951 } 952 if (is_additional_list != 0 || 953 attr_id == ATTR_ID_ADDITION_PROTO_DESC_LISTS) 954 nest_level |= SDP_ADDITIONAL_LIST_MASK; 955 /* SDP_TRACE_DEBUG ("SDP - attr nest level:0x%x(finish)", nest_level); */ 956 957 while (p < p_end) { 958 /* Now, add the list entry */ 959 p = add_attr(p, p_db, p_rec, 0, p_attr, (uint8_t)(nest_level + 1)); 960 961 if (!p) return (NULL); 962 } 963 break; 964 965 case TEXT_STR_DESC_TYPE: 966 case URL_DESC_TYPE: 967 BE_STREAM_TO_ARRAY(p, p_attr->attr_value.v.array, (int32_t)attr_len); 968 break; 969 970 case BOOLEAN_DESC_TYPE: 971 switch (attr_len) { 972 case 1: 973 p_attr->attr_value.v.u8 = *p++; 974 break; 975 default: 976 SDP_TRACE_WARNING("SDP - bad len in boolean attr: %d", attr_len); 977 return (p + attr_len); 978 } 979 break; 980 981 default: /* switch (attr_type) */ 982 break; 983 } 984 985 p_db->p_free_mem += total_len; 986 p_db->mem_free -= total_len; 987 988 /* Add the attribute to the end of the chain */ 989 if (!p_parent_attr) { 990 if (!p_rec->p_first_attr) 991 p_rec->p_first_attr = p_attr; 992 else { 993 tSDP_DISC_ATTR* p_attr1 = p_rec->p_first_attr; 994 995 while (p_attr1->p_next_attr) p_attr1 = p_attr1->p_next_attr; 996 997 p_attr1->p_next_attr = p_attr; 998 } 999 } else { 1000 if (!p_parent_attr->attr_value.v.p_sub_attr) { 1001 p_parent_attr->attr_value.v.p_sub_attr = p_attr; 1002 /* SDP_TRACE_DEBUG ("parent:0x%x(id:%d), ch:0x%x(id:%d)", 1003 p_parent_attr, p_parent_attr->attr_id, p_attr, p_attr->attr_id); */ 1004 } else { 1005 tSDP_DISC_ATTR* p_attr1 = p_parent_attr->attr_value.v.p_sub_attr; 1006 /* SDP_TRACE_DEBUG ("parent:0x%x(id:%d), ch1:0x%x(id:%d)", 1007 p_parent_attr, p_parent_attr->attr_id, p_attr1, p_attr1->attr_id); */ 1008 1009 while (p_attr1->p_next_attr) p_attr1 = p_attr1->p_next_attr; 1010 1011 p_attr1->p_next_attr = p_attr; 1012 /* SDP_TRACE_DEBUG ("new ch:0x%x(id:%d)", p_attr, p_attr->attr_id); */ 1013 } 1014 } 1015 1016 return (p); 1017 } 1018