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