1 /* 2 * Copyright (C) 2014 BlueKitchen GmbH 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. Neither the name of the copyright holders nor the names of 14 * contributors may be used to endorse or promote products derived 15 * from this software without specific prior written permission. 16 * 4. Any redistribution, use, or modification is done solely for 17 * personal benefit and not for any commercial purpose or for 18 * monetary gain. 19 * 20 * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS 24 * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 27 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 28 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 30 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * Please inquire about commercial licensing options at 34 * [email protected] 35 * 36 */ 37 38 #define __BTSTACK_FILE__ "sdp_client.c" 39 40 /* 41 * sdp_client.c 42 */ 43 44 #include "bluetooth_sdp.h" 45 #include "btstack_config.h" 46 #include "btstack_debug.h" 47 #include "btstack_event.h" 48 #include "classic/core.h" 49 #include "classic/sdp_client.h" 50 #include "classic/sdp_server.h" 51 #include "classic/sdp_util.h" 52 #include "hci_cmd.h" 53 #include "l2cap.h" 54 55 // Types SDP Parser - Data Element stream helper 56 typedef enum { 57 GET_LIST_LENGTH = 1, 58 GET_RECORD_LENGTH, 59 GET_ATTRIBUTE_ID_HEADER_LENGTH, 60 GET_ATTRIBUTE_ID, 61 GET_ATTRIBUTE_VALUE_LENGTH, 62 GET_ATTRIBUTE_VALUE 63 } sdp_parser_state_t; 64 65 // Types SDP Client 66 typedef enum { 67 INIT, W4_CONNECT, W2_SEND, W4_RESPONSE, QUERY_COMPLETE 68 } sdp_client_state_t; 69 70 71 // Prototypes SDP Parser 72 void sdp_parser_init(btstack_packet_handler_t callback); 73 void sdp_parser_handle_chunk(uint8_t * data, uint16_t size); 74 void sdp_parser_handle_done(uint8_t status); 75 void sdp_parser_init_service_attribute_search(void); 76 void sdp_parser_init_service_search(void); 77 void sdp_parser_handle_service_search(uint8_t * data, uint16_t total_count, uint16_t record_handle_count); 78 79 // Prototypes SDP Client 80 void sdp_client_reset(void); 81 void sdp_client_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size); 82 static uint16_t sdp_client_setup_service_search_attribute_request(uint8_t * data); 83 #ifdef ENABLE_SDP_EXTRA_QUERIES 84 static uint16_t sdp_client_setup_service_search_request(uint8_t * data); 85 static uint16_t sdp_client_setup_service_attribute_request(uint8_t * data); 86 static void sdp_client_parse_service_search_response(uint8_t* packet, uint16_t size); 87 static void sdp_client_parse_service_attribute_response(uint8_t* packet, uint16_t size); 88 #endif 89 90 static uint8_t des_attributeIDList[] = { 0x35, 0x05, 0x0A, 0x00, 0x01, 0xff, 0xff}; // Attribute: 0x0001 - 0x0100 91 92 // State DES Parser 93 static de_state_t de_header_state; 94 95 // State SDP Parser 96 static sdp_parser_state_t state = GET_LIST_LENGTH; 97 static uint16_t attribute_id = 0; 98 static uint16_t attribute_bytes_received = 0; 99 static uint16_t attribute_bytes_delivered = 0; 100 static uint16_t list_offset = 0; 101 static uint16_t list_size; 102 static uint16_t record_offset = 0; 103 static uint16_t record_size; 104 static uint16_t attribute_value_size; 105 static int record_counter = 0; 106 static btstack_packet_handler_t sdp_parser_callback; 107 108 // State SDP Client 109 static uint16_t mtu; 110 static uint16_t sdp_cid = 0x40; 111 static const uint8_t * service_search_pattern; 112 static const uint8_t * attribute_id_list; 113 static uint16_t transactionID = 0; 114 static uint8_t continuationState[16]; 115 static uint8_t continuationStateLen; 116 static sdp_client_state_t sdp_client_state = INIT; 117 static SDP_PDU_ID_t PDU_ID = SDP_Invalid; 118 #ifdef ENABLE_SDP_EXTRA_QUERIES 119 static uint32_t serviceRecordHandle; 120 static uint32_t record_handle; 121 #endif 122 123 // DES Parser 124 void de_state_init(de_state_t * de_state){ 125 de_state->in_state_GET_DE_HEADER_LENGTH = 1; 126 de_state->addon_header_bytes = 0; 127 de_state->de_size = 0; 128 de_state->de_offset = 0; 129 } 130 131 int de_state_size(uint8_t eventByte, de_state_t *de_state){ 132 if (de_state->in_state_GET_DE_HEADER_LENGTH){ 133 de_state->addon_header_bytes = de_get_header_size(&eventByte) - 1; 134 de_state->de_size = 0; 135 de_state->de_offset = 0; 136 137 if (de_state->addon_header_bytes == 0){ 138 de_state->de_size = de_get_data_size(&eventByte); 139 if (de_state->de_size == 0) { 140 log_error(" ERROR: ID size is zero"); 141 } 142 // log_info("Data element payload is %d bytes.", de_state->de_size); 143 return 1; 144 } 145 de_state->in_state_GET_DE_HEADER_LENGTH = 0; 146 return 0; 147 } 148 149 if (de_state->addon_header_bytes > 0){ 150 de_state->de_size = (de_state->de_size << 8) | eventByte; 151 de_state->addon_header_bytes--; 152 } 153 if (de_state->addon_header_bytes > 0) return 0; 154 // log_info("Data element payload is %d bytes.", de_state->de_size); 155 de_state->in_state_GET_DE_HEADER_LENGTH = 1; 156 return 1; 157 } 158 159 // SDP Parser 160 static void sdp_parser_emit_value_byte(uint8_t event_byte){ 161 uint8_t event[11]; 162 event[0] = SDP_EVENT_QUERY_ATTRIBUTE_VALUE; 163 event[1] = 9; 164 little_endian_store_16(event, 2, record_counter); 165 little_endian_store_16(event, 4, attribute_id); 166 little_endian_store_16(event, 6, attribute_value_size); 167 little_endian_store_16(event, 8, attribute_bytes_delivered); 168 event[10] = event_byte; 169 (*sdp_parser_callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); 170 } 171 172 static void sdp_parser_process_byte(uint8_t eventByte){ 173 // count all bytes 174 list_offset++; 175 record_offset++; 176 177 // log_info(" parse BYTE_RECEIVED %02x", eventByte); 178 switch(state){ 179 case GET_LIST_LENGTH: 180 if (!de_state_size(eventByte, &de_header_state)) break; 181 list_offset = de_header_state.de_offset; 182 list_size = de_header_state.de_size; 183 // log_info("parser: List offset %u, list size %u", list_offset, list_size); 184 185 record_counter = 0; 186 state = GET_RECORD_LENGTH; 187 break; 188 189 case GET_RECORD_LENGTH: 190 // check size 191 if (!de_state_size(eventByte, &de_header_state)) break; 192 // log_info("parser: Record payload is %d bytes.", de_header_state.de_size); 193 record_offset = de_header_state.de_offset; 194 record_size = de_header_state.de_size; 195 state = GET_ATTRIBUTE_ID_HEADER_LENGTH; 196 break; 197 198 case GET_ATTRIBUTE_ID_HEADER_LENGTH: 199 if (!de_state_size(eventByte, &de_header_state)) break; 200 attribute_id = 0; 201 log_debug("ID data is stored in %d bytes.", (int) de_header_state.de_size); 202 state = GET_ATTRIBUTE_ID; 203 break; 204 205 case GET_ATTRIBUTE_ID: 206 attribute_id = (attribute_id << 8) | eventByte; 207 de_header_state.de_size--; 208 if (de_header_state.de_size > 0) break; 209 log_debug("parser: Attribute ID: %04x.", attribute_id); 210 211 state = GET_ATTRIBUTE_VALUE_LENGTH; 212 attribute_bytes_received = 0; 213 attribute_bytes_delivered = 0; 214 attribute_value_size = 0; 215 de_state_init(&de_header_state); 216 break; 217 218 case GET_ATTRIBUTE_VALUE_LENGTH: 219 attribute_bytes_received++; 220 sdp_parser_emit_value_byte(eventByte); 221 attribute_bytes_delivered++; 222 if (!de_state_size(eventByte, &de_header_state)) break; 223 224 attribute_value_size = de_header_state.de_size + attribute_bytes_received; 225 226 state = GET_ATTRIBUTE_VALUE; 227 break; 228 229 case GET_ATTRIBUTE_VALUE: 230 attribute_bytes_received++; 231 sdp_parser_emit_value_byte(eventByte); 232 attribute_bytes_delivered++; 233 // log_debug("paser: attribute_bytes_received %u, attribute_value_size %u", attribute_bytes_received, attribute_value_size); 234 235 if (attribute_bytes_received < attribute_value_size) break; 236 // log_debug("parser: Record offset %u, record size %u", record_offset, record_size); 237 if (record_offset != record_size){ 238 state = GET_ATTRIBUTE_ID_HEADER_LENGTH; 239 // log_debug("Get next attribute"); 240 break; 241 } 242 record_offset = 0; 243 // log_debug("parser: List offset %u, list size %u", list_offset, list_size); 244 245 if (list_size > 0 && list_offset != list_size){ 246 record_counter++; 247 state = GET_RECORD_LENGTH; 248 log_debug("parser: END_OF_RECORD"); 249 break; 250 } 251 list_offset = 0; 252 de_state_init(&de_header_state); 253 state = GET_LIST_LENGTH; 254 record_counter = 0; 255 log_debug("parser: END_OF_RECORD & DONE"); 256 break; 257 default: 258 break; 259 } 260 } 261 262 void sdp_parser_init(btstack_packet_handler_t callback){ 263 // init 264 sdp_parser_callback = callback; 265 de_state_init(&de_header_state); 266 state = GET_LIST_LENGTH; 267 list_offset = 0; 268 record_offset = 0; 269 record_counter = 0; 270 } 271 272 void sdp_parser_handle_chunk(uint8_t * data, uint16_t size){ 273 int i; 274 for (i=0;i<size;i++){ 275 sdp_parser_process_byte(data[i]); 276 } 277 } 278 279 #ifdef ENABLE_SDP_EXTRA_QUERIES 280 void sdp_parser_init_service_attribute_search(void){ 281 // init 282 de_state_init(&de_header_state); 283 state = GET_RECORD_LENGTH; 284 list_offset = 0; 285 record_offset = 0; 286 record_counter = 0; 287 } 288 289 void sdp_parser_init_service_search(void){ 290 record_offset = 0; 291 } 292 293 void sdp_parser_handle_service_search(uint8_t * data, uint16_t total_count, uint16_t record_handle_count){ 294 int i; 295 for (i=0;i<record_handle_count;i++){ 296 record_handle = big_endian_read_32(data, i*4); 297 record_counter++; 298 uint8_t event[10]; 299 event[0] = SDP_EVENT_QUERY_SERVICE_RECORD_HANDLE; 300 event[1] = 8; 301 little_endian_store_16(event, 2, total_count); 302 little_endian_store_16(event, 4, record_counter); 303 little_endian_store_32(event, 6, record_handle); 304 (*sdp_parser_callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); 305 } 306 } 307 #endif 308 309 void sdp_parser_handle_done(uint8_t status){ 310 uint8_t event[3]; 311 event[0] = SDP_EVENT_QUERY_COMPLETE; 312 event[1] = 1; 313 event[2] = status; 314 (*sdp_parser_callback)(HCI_EVENT_PACKET, 0, event, sizeof(event)); 315 } 316 317 // SDP Client 318 319 // TODO: inline if not needed (des(des)) 320 321 static void sdp_client_parse_attribute_lists(uint8_t* packet, uint16_t length){ 322 sdp_parser_handle_chunk(packet, length); 323 } 324 325 326 static void sdp_client_send_request(uint16_t channel){ 327 328 if (sdp_client_state != W2_SEND) return; 329 330 l2cap_reserve_packet_buffer(); 331 uint8_t * data = l2cap_get_outgoing_buffer(); 332 uint16_t request_len = 0; 333 334 switch (PDU_ID){ 335 #ifdef ENABLE_SDP_EXTRA_QUERIES 336 case SDP_ServiceSearchResponse: 337 request_len = sdp_client_setup_service_search_request(data); 338 break; 339 case SDP_ServiceAttributeResponse: 340 request_len = sdp_client_setup_service_attribute_request(data); 341 break; 342 #endif 343 case SDP_ServiceSearchAttributeResponse: 344 request_len = sdp_client_setup_service_search_attribute_request(data); 345 break; 346 default: 347 log_error("SDP Client sdp_client_send_request :: PDU ID invalid. %u", PDU_ID); 348 return; 349 } 350 351 // prevent re-entrance 352 sdp_client_state = W4_RESPONSE; 353 PDU_ID = SDP_Invalid; 354 l2cap_send_prepared(channel, request_len); 355 } 356 357 358 static void sdp_client_parse_service_search_attribute_response(uint8_t* packet, uint16_t size){ 359 360 uint16_t offset = 3; 361 if (offset + 2 + 2 > size) return; // parameterLength + attributeListByteCount 362 uint16_t parameterLength = big_endian_read_16(packet,offset); 363 offset+=2; 364 if (offset + parameterLength > size) return; 365 366 // AttributeListByteCount <= mtu 367 uint16_t attributeListByteCount = big_endian_read_16(packet,offset); 368 offset+=2; 369 if (attributeListByteCount > mtu){ 370 log_error("Error parsing ServiceSearchAttributeResponse: Number of bytes in found attribute list is larger then the MaximumAttributeByteCount."); 371 return; 372 } 373 374 // AttributeLists 375 if (offset + attributeListByteCount > size) return; 376 sdp_client_parse_attribute_lists(packet+offset, attributeListByteCount); 377 offset+=attributeListByteCount; 378 379 // continuation state len 380 if (offset + 1 > size) return; 381 continuationStateLen = packet[offset]; 382 offset++; 383 if (continuationStateLen > 16){ 384 continuationStateLen = 0; 385 log_error("Error parsing ServiceSearchAttributeResponse: Number of bytes in continuation state exceedes 16."); 386 return; 387 } 388 389 // continuation state 390 if (offset + continuationStateLen > size) return; 391 memcpy(continuationState, packet+offset, continuationStateLen); 392 // offset+=continuationStateLen; 393 } 394 395 void sdp_client_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){ 396 397 // uint16_t handle; 398 if (packet_type == L2CAP_DATA_PACKET){ 399 if (size < 3) return; 400 uint16_t responseTransactionID = big_endian_read_16(packet,1); 401 if (responseTransactionID != transactionID){ 402 log_error("Mismatching transaction ID, expected %u, found %u.", transactionID, responseTransactionID); 403 return; 404 } 405 406 PDU_ID = (SDP_PDU_ID_t)packet[0]; 407 switch (PDU_ID){ 408 case SDP_ErrorResponse: 409 log_error("Received error response with code %u, disconnecting", packet[2]); 410 l2cap_disconnect(sdp_cid, 0); 411 return; 412 #ifdef ENABLE_SDP_EXTRA_QUERIES 413 case SDP_ServiceSearchResponse: 414 sdp_client_parse_service_search_response(packet, size); 415 break; 416 case SDP_ServiceAttributeResponse: 417 sdp_client_parse_service_attribute_response(packet, size); 418 break; 419 #endif 420 case SDP_ServiceSearchAttributeResponse: 421 sdp_client_parse_service_search_attribute_response(packet, size); 422 break; 423 default: 424 log_error("PDU ID %u unexpected/invalid", PDU_ID); 425 return; 426 } 427 428 // continuation set or DONE? 429 if (continuationStateLen == 0){ 430 log_debug("SDP Client Query DONE! "); 431 sdp_client_state = QUERY_COMPLETE; 432 l2cap_disconnect(sdp_cid, 0); 433 return; 434 } 435 // prepare next request and send 436 sdp_client_state = W2_SEND; 437 l2cap_request_can_send_now_event(sdp_cid); 438 return; 439 } 440 441 if (packet_type != HCI_EVENT_PACKET) return; 442 443 switch(hci_event_packet_get_type(packet)){ 444 case L2CAP_EVENT_CHANNEL_OPENED: 445 if (sdp_client_state != W4_CONNECT) break; 446 // data: event (8), len(8), status (8), address(48), handle (16), psm (16), local_cid(16), remote_cid (16), local_mtu(16), remote_mtu(16) 447 if (packet[2]) { 448 log_info("SDP Client Connection failed, status 0x%02x.", packet[2]); 449 sdp_client_state = INIT; 450 sdp_parser_handle_done(packet[2]); 451 break; 452 } 453 sdp_cid = channel; 454 mtu = little_endian_read_16(packet, 17); 455 // handle = little_endian_read_16(packet, 9); 456 log_debug("SDP Client Connected, cid %x, mtu %u.", sdp_cid, mtu); 457 458 sdp_client_state = W2_SEND; 459 l2cap_request_can_send_now_event(sdp_cid); 460 break; 461 462 case L2CAP_EVENT_CAN_SEND_NOW: 463 if(l2cap_event_can_send_now_get_local_cid(packet) == sdp_cid){ 464 sdp_client_send_request(sdp_cid); 465 } 466 break; 467 case L2CAP_EVENT_CHANNEL_CLOSED: { 468 if (sdp_cid != little_endian_read_16(packet, 2)) { 469 // log_info("Received L2CAP_EVENT_CHANNEL_CLOSED for cid %x, current cid %x\n", little_endian_read_16(packet, 2),sdp_cid); 470 break; 471 } 472 log_info("SDP Client disconnected."); 473 uint8_t status = sdp_client_state == QUERY_COMPLETE ? 0 : SDP_QUERY_INCOMPLETE; 474 sdp_client_state = INIT; 475 sdp_parser_handle_done(status); 476 break; 477 } 478 default: 479 break; 480 } 481 } 482 483 484 static uint16_t sdp_client_setup_service_search_attribute_request(uint8_t * data){ 485 486 uint16_t offset = 0; 487 transactionID++; 488 // uint8_t SDP_PDU_ID_t.SDP_ServiceSearchRequest; 489 data[offset++] = SDP_ServiceSearchAttributeRequest; 490 // uint16_t transactionID 491 big_endian_store_16(data, offset, transactionID); 492 offset += 2; 493 494 // param legnth 495 offset += 2; 496 497 // parameters: 498 // Service_search_pattern - DES (min 1 UUID, max 12) 499 uint16_t service_search_pattern_len = de_get_len(service_search_pattern); 500 memcpy(data + offset, service_search_pattern, service_search_pattern_len); 501 offset += service_search_pattern_len; 502 503 // MaximumAttributeByteCount - uint16_t 0x0007 - 0xffff -> mtu 504 big_endian_store_16(data, offset, mtu); 505 offset += 2; 506 507 // AttibuteIDList 508 uint16_t attribute_id_list_len = de_get_len(attribute_id_list); 509 memcpy(data + offset, attribute_id_list, attribute_id_list_len); 510 offset += attribute_id_list_len; 511 512 // ContinuationState - uint8_t number of cont. bytes N<=16 513 data[offset++] = continuationStateLen; 514 // - N-bytes previous response from server 515 memcpy(data + offset, continuationState, continuationStateLen); 516 offset += continuationStateLen; 517 518 // uint16_t paramLength 519 big_endian_store_16(data, 3, offset - 5); 520 521 return offset; 522 } 523 524 #ifdef ENABLE_SDP_EXTRA_QUERIES 525 void sdp_client_parse_service_record_handle_list(uint8_t* packet, uint16_t total_count, uint16_t current_count){ 526 sdp_parser_handle_service_search(packet, total_count, current_count); 527 } 528 529 static uint16_t sdp_client_setup_service_search_request(uint8_t * data){ 530 uint16_t offset = 0; 531 transactionID++; 532 // uint8_t SDP_PDU_ID_t.SDP_ServiceSearchRequest; 533 data[offset++] = SDP_ServiceSearchRequest; 534 // uint16_t transactionID 535 big_endian_store_16(data, offset, transactionID); 536 offset += 2; 537 538 // param legnth 539 offset += 2; 540 541 // parameters: 542 // Service_search_pattern - DES (min 1 UUID, max 12) 543 uint16_t service_search_pattern_len = de_get_len(service_search_pattern); 544 memcpy(data + offset, service_search_pattern, service_search_pattern_len); 545 offset += service_search_pattern_len; 546 547 // MaximumAttributeByteCount - uint16_t 0x0007 - 0xffff -> mtu 548 big_endian_store_16(data, offset, mtu); 549 offset += 2; 550 551 // ContinuationState - uint8_t number of cont. bytes N<=16 552 data[offset++] = continuationStateLen; 553 // - N-bytes previous response from server 554 memcpy(data + offset, continuationState, continuationStateLen); 555 offset += continuationStateLen; 556 557 // uint16_t paramLength 558 big_endian_store_16(data, 3, offset - 5); 559 560 return offset; 561 } 562 563 564 static uint16_t sdp_client_setup_service_attribute_request(uint8_t * data){ 565 566 uint16_t offset = 0; 567 transactionID++; 568 // uint8_t SDP_PDU_ID_t.SDP_ServiceSearchRequest; 569 data[offset++] = SDP_ServiceAttributeRequest; 570 // uint16_t transactionID 571 big_endian_store_16(data, offset, transactionID); 572 offset += 2; 573 574 // param legnth 575 offset += 2; 576 577 // parameters: 578 // ServiceRecordHandle 579 big_endian_store_32(data, offset, serviceRecordHandle); 580 offset += 4; 581 582 // MaximumAttributeByteCount - uint16_t 0x0007 - 0xffff -> mtu 583 big_endian_store_16(data, offset, mtu); 584 offset += 2; 585 586 // AttibuteIDList 587 uint16_t attribute_id_list_len = de_get_len(attribute_id_list); 588 memcpy(data + offset, attribute_id_list, attribute_id_list_len); 589 offset += attribute_id_list_len; 590 591 // ContinuationState - uint8_t number of cont. bytes N<=16 592 data[offset++] = continuationStateLen; 593 // - N-bytes previous response from server 594 memcpy(data + offset, continuationState, continuationStateLen); 595 offset += continuationStateLen; 596 597 // uint16_t paramLength 598 big_endian_store_16(data, 3, offset - 5); 599 600 return offset; 601 } 602 603 static void sdp_client_parse_service_search_response(uint8_t* packet, uint16_t size){ 604 605 uint16_t offset = 3; 606 if (offset + 2 + 2 + 2 > size) return; // parameterLength, totalServiceRecordCount, currentServiceRecordCount 607 608 uint16_t parameterLength = big_endian_read_16(packet,offset); 609 offset+=2; 610 if (offset + parameterLength > size) return; 611 612 uint16_t totalServiceRecordCount = big_endian_read_16(packet,offset); 613 offset+=2; 614 615 uint16_t currentServiceRecordCount = big_endian_read_16(packet,offset); 616 offset+=2; 617 if (currentServiceRecordCount > totalServiceRecordCount){ 618 log_error("CurrentServiceRecordCount is larger then TotalServiceRecordCount."); 619 return; 620 } 621 622 if (offset + currentServiceRecordCount * 4 > size) return; 623 sdp_client_parse_service_record_handle_list(packet+offset, totalServiceRecordCount, currentServiceRecordCount); 624 offset+= currentServiceRecordCount * 4; 625 626 if (offset + 1 > size) return; 627 continuationStateLen = packet[offset]; 628 offset++; 629 if (continuationStateLen > 16){ 630 continuationStateLen = 0; 631 log_error("Error parsing ServiceSearchResponse: Number of bytes in continuation state exceedes 16."); 632 return; 633 } 634 if (offset + continuationStateLen > size) return; 635 memcpy(continuationState, packet+offset, continuationStateLen); 636 // offset+=continuationStateLen; 637 } 638 639 static void sdp_client_parse_service_attribute_response(uint8_t* packet, uint16_t size){ 640 641 uint16_t offset = 3; 642 if (offset + 2 + 2 > size) return; // parameterLength, attributeListByteCount 643 uint16_t parameterLength = big_endian_read_16(packet,offset); 644 offset+=2; 645 if (offset+parameterLength > size) return; 646 647 // AttributeListByteCount <= mtu 648 uint16_t attributeListByteCount = big_endian_read_16(packet,offset); 649 offset+=2; 650 if (attributeListByteCount > mtu){ 651 log_error("Error parsing ServiceSearchAttributeResponse: Number of bytes in found attribute list is larger then the MaximumAttributeByteCount."); 652 return; 653 } 654 655 // AttributeLists 656 if (offset+attributeListByteCount > size) return; 657 sdp_client_parse_attribute_lists(packet+offset, attributeListByteCount); 658 offset+=attributeListByteCount; 659 660 // continuationStateLen 661 if (offset + 1 > size) return; 662 continuationStateLen = packet[offset]; 663 offset++; 664 if (continuationStateLen > 16){ 665 continuationStateLen = 0; 666 log_error("Error parsing ServiceAttributeResponse: Number of bytes in continuation state exceedes 16."); 667 return; 668 } 669 if (offset + continuationStateLen > size) return; 670 memcpy(continuationState, packet+offset, continuationStateLen); 671 // offset+=continuationStateLen; 672 } 673 #endif 674 675 // for testing only 676 void sdp_client_reset(void){ 677 sdp_client_state = INIT; 678 } 679 680 // Public API 681 682 int sdp_client_ready(void){ 683 return sdp_client_state == INIT; 684 } 685 686 uint8_t sdp_client_query(btstack_packet_handler_t callback, bd_addr_t remote, const uint8_t * des_service_search_pattern, const uint8_t * des_attribute_id_list){ 687 if (!sdp_client_ready()) return SDP_QUERY_BUSY; 688 689 sdp_parser_init(callback); 690 service_search_pattern = des_service_search_pattern; 691 attribute_id_list = des_attribute_id_list; 692 continuationStateLen = 0; 693 PDU_ID = SDP_ServiceSearchAttributeResponse; 694 695 sdp_client_state = W4_CONNECT; 696 return l2cap_create_channel(sdp_client_packet_handler, remote, BLUETOOTH_PROTOCOL_SDP, l2cap_max_mtu(), NULL); 697 } 698 699 uint8_t sdp_client_query_uuid16(btstack_packet_handler_t callback, bd_addr_t remote, uint16_t uuid){ 700 if (!sdp_client_ready()) return SDP_QUERY_BUSY; 701 return sdp_client_query(callback, remote, sdp_service_search_pattern_for_uuid16(uuid), des_attributeIDList); 702 } 703 704 uint8_t sdp_client_query_uuid128(btstack_packet_handler_t callback, bd_addr_t remote, const uint8_t* uuid){ 705 if (!sdp_client_ready()) return SDP_QUERY_BUSY; 706 return sdp_client_query(callback, remote, sdp_service_search_pattern_for_uuid128(uuid), des_attributeIDList); 707 } 708 709 #ifdef ENABLE_SDP_EXTRA_QUERIES 710 uint8_t sdp_client_service_attribute_search(btstack_packet_handler_t callback, bd_addr_t remote, uint32_t search_service_record_handle, const uint8_t * des_attribute_id_list){ 711 if (!sdp_client_ready()) return SDP_QUERY_BUSY; 712 713 sdp_parser_init(callback); 714 serviceRecordHandle = search_service_record_handle; 715 attribute_id_list = des_attribute_id_list; 716 continuationStateLen = 0; 717 PDU_ID = SDP_ServiceAttributeResponse; 718 719 sdp_client_state = W4_CONNECT; 720 l2cap_create_channel(sdp_client_packet_handler, remote, BLUETOOTH_PROTOCOL_SDP, l2cap_max_mtu(), NULL); 721 return 0; 722 } 723 724 uint8_t sdp_client_service_search(btstack_packet_handler_t callback, bd_addr_t remote, const uint8_t * des_service_search_pattern){ 725 726 if (!sdp_client_ready()) return SDP_QUERY_BUSY; 727 728 sdp_parser_init(callback); 729 service_search_pattern = des_service_search_pattern; 730 continuationStateLen = 0; 731 PDU_ID = SDP_ServiceSearchResponse; 732 733 sdp_client_state = W4_CONNECT; 734 l2cap_create_channel(sdp_client_packet_handler, remote, BLUETOOTH_PROTOCOL_SDP, l2cap_max_mtu(), NULL); 735 return 0; 736 } 737 #endif 738 739