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 the main SDP functions 22 * 23 ******************************************************************************/ 24 25#include <stdlib.h> 26#include <string.h> 27#include <stdio.h> 28 29#include "bt_target.h" 30#include "bt_utils.h" 31#include "gki.h" 32#include "l2cdefs.h" 33#include "hcidefs.h" 34#include "hcimsgs.h" 35 36#include "l2c_api.h" 37#include "l2cdefs.h" 38 39#include "btu.h" 40#include "btm_api.h" 41 42#include "sdp_api.h" 43#include "sdpint.h" 44 45 46/********************************************************************************/ 47/* G L O B A L S D P D A T A */ 48/********************************************************************************/ 49#if SDP_DYNAMIC_MEMORY == FALSE 50tSDP_CB sdp_cb; 51#endif 52 53/********************************************************************************/ 54/* L O C A L F U N C T I O N P R O T O T Y P E S */ 55/********************************************************************************/ 56static void sdp_connect_ind (BD_ADDR bd_addr, UINT16 l2cap_cid, UINT16 psm, 57 UINT8 l2cap_id); 58static void sdp_config_ind (UINT16 l2cap_cid, tL2CAP_CFG_INFO *p_cfg); 59static void sdp_config_cfm (UINT16 l2cap_cid, tL2CAP_CFG_INFO *p_cfg); 60static void sdp_disconnect_ind (UINT16 l2cap_cid, BOOLEAN ack_needed); 61static void sdp_data_ind (UINT16 l2cap_cid, BT_HDR *p_msg); 62 63#if SDP_CLIENT_ENABLED == TRUE 64static void sdp_connect_cfm (UINT16 l2cap_cid, UINT16 result); 65static void sdp_disconnect_cfm (UINT16 l2cap_cid, UINT16 result); 66#else 67#define sdp_connect_cfm NULL 68#define sdp_disconnect_cfm NULL 69#endif 70 71 72/******************************************************************************* 73** 74** Function sdp_init 75** 76** Description This function initializes the SDP unit. 77** 78** Returns void 79** 80*******************************************************************************/ 81void sdp_init (void) 82{ 83 /* Clears all structures and local SDP database (if Server is enabled) */ 84 memset (&sdp_cb, 0, sizeof (tSDP_CB)); 85 86 /* Initialize the L2CAP configuration. We only care about MTU and flush */ 87 sdp_cb.l2cap_my_cfg.mtu_present = TRUE; 88 sdp_cb.l2cap_my_cfg.mtu = SDP_MTU_SIZE; 89 sdp_cb.l2cap_my_cfg.flush_to_present = TRUE; 90 sdp_cb.l2cap_my_cfg.flush_to = SDP_FLUSH_TO; 91 92 sdp_cb.max_attr_list_size = SDP_MTU_SIZE - 16; 93 sdp_cb.max_recs_per_search = SDP_MAX_DISC_SERVER_RECS; 94 95#if SDP_SERVER_ENABLED == TRUE 96 /* Register with Security Manager for the specific security level */ 97 if (!BTM_SetSecurityLevel (FALSE, SDP_SERVICE_NAME, BTM_SEC_SERVICE_SDP_SERVER, 98 SDP_SECURITY_LEVEL, SDP_PSM, 0, 0)) 99 { 100 SDP_TRACE_ERROR ("Security Registration Server failed"); 101 return; 102 } 103#endif 104 105#if SDP_CLIENT_ENABLED == TRUE 106 /* Register with Security Manager for the specific security level */ 107 if (!BTM_SetSecurityLevel (TRUE, SDP_SERVICE_NAME, BTM_SEC_SERVICE_SDP_SERVER, 108 SDP_SECURITY_LEVEL, SDP_PSM, 0, 0)) 109 { 110 SDP_TRACE_ERROR ("Security Registration for Client failed"); 111 return; 112 } 113#endif 114 115#if defined(SDP_INITIAL_TRACE_LEVEL) 116 sdp_cb.trace_level = SDP_INITIAL_TRACE_LEVEL; 117#else 118 sdp_cb.trace_level = BT_TRACE_LEVEL_NONE; /* No traces */ 119#endif 120 121 sdp_cb.reg_info.pL2CA_ConnectInd_Cb = sdp_connect_ind; 122 sdp_cb.reg_info.pL2CA_ConnectCfm_Cb = sdp_connect_cfm; 123 sdp_cb.reg_info.pL2CA_ConnectPnd_Cb = NULL; 124 sdp_cb.reg_info.pL2CA_ConfigInd_Cb = sdp_config_ind; 125 sdp_cb.reg_info.pL2CA_ConfigCfm_Cb = sdp_config_cfm; 126 sdp_cb.reg_info.pL2CA_DisconnectInd_Cb = sdp_disconnect_ind; 127 sdp_cb.reg_info.pL2CA_DisconnectCfm_Cb = sdp_disconnect_cfm; 128 sdp_cb.reg_info.pL2CA_QoSViolationInd_Cb = NULL; 129 sdp_cb.reg_info.pL2CA_DataInd_Cb = sdp_data_ind; 130 sdp_cb.reg_info.pL2CA_CongestionStatus_Cb = NULL; 131 sdp_cb.reg_info.pL2CA_TxComplete_Cb = NULL; 132 133 /* Now, register with L2CAP */ 134 if (!L2CA_Register (SDP_PSM, &sdp_cb.reg_info)) 135 { 136 SDP_TRACE_ERROR ("SDP Registration failed"); 137 } 138} 139 140#if (defined(SDP_DEBUG) && SDP_DEBUG == TRUE) 141/******************************************************************************* 142** 143** Function sdp_set_max_attr_list_size 144** 145** Description This function sets the max attribute list size to use 146** 147** Returns void 148** 149*******************************************************************************/ 150UINT16 sdp_set_max_attr_list_size (UINT16 max_size) 151{ 152 if (max_size > (sdp_cb.l2cap_my_cfg.mtu - 16) ) 153 max_size = sdp_cb.l2cap_my_cfg.mtu - 16; 154 155 sdp_cb.max_attr_list_size = max_size; 156 157 return sdp_cb.max_attr_list_size; 158} 159#endif 160 161/******************************************************************************* 162** 163** Function sdp_connect_ind 164** 165** Description This function handles an inbound connection indication 166** from L2CAP. This is the case where we are acting as a 167** server. 168** 169** Returns void 170** 171*******************************************************************************/ 172static void sdp_connect_ind (BD_ADDR bd_addr, UINT16 l2cap_cid, UINT16 psm, UINT8 l2cap_id) 173{ 174 UNUSED(psm); 175#if SDP_SERVER_ENABLED == TRUE 176 tCONN_CB *p_ccb; 177 178 /* Allocate a new CCB. Return if none available. */ 179 if ((p_ccb = sdpu_allocate_ccb()) == NULL) 180 return; 181 182 /* Transition to the next appropriate state, waiting for config setup. */ 183 p_ccb->con_state = SDP_STATE_CFG_SETUP; 184 185 /* Save the BD Address and Channel ID. */ 186 memcpy (&p_ccb->device_address[0], bd_addr, sizeof (BD_ADDR)); 187 p_ccb->connection_id = l2cap_cid; 188 189 /* Send response to the L2CAP layer. */ 190 L2CA_ConnectRsp (bd_addr, l2cap_id, l2cap_cid, L2CAP_CONN_OK, L2CAP_CONN_OK); 191 { 192 tL2CAP_CFG_INFO cfg = sdp_cb.l2cap_my_cfg; 193 194 if (cfg.fcr_present) 195 { 196 SDP_TRACE_DEBUG("sdp_connect_ind: mode %u, txwinsz %u, max_trans %u, rtrans_tout %u, mon_tout %u, mps %u", 197 cfg.fcr.mode, cfg.fcr.tx_win_sz, cfg.fcr.max_transmit, 198 cfg.fcr.rtrans_tout,cfg.fcr.mon_tout, cfg.fcr.mps); 199 } 200 201 if ((!L2CA_ConfigReq (l2cap_cid, &cfg)) && cfg.fcr_present 202 && cfg.fcr.mode != L2CAP_FCR_BASIC_MODE) 203 { 204 /* FCR not desired; try again in basic mode */ 205 cfg.fcr.mode = L2CAP_FCR_BASIC_MODE; 206 cfg.fcr_present = FALSE; 207 L2CA_ConfigReq (l2cap_cid, &cfg); 208 } 209 } 210 211 SDP_TRACE_EVENT ("SDP - Rcvd L2CAP conn ind, sent config req, CID 0x%x", p_ccb->connection_id); 212#else /* No server */ 213 /* Reject the connection */ 214 L2CA_ConnectRsp (bd_addr, l2cap_id, l2cap_cid, L2CAP_CONN_NO_PSM, 0); 215#endif 216} 217 218#if SDP_CLIENT_ENABLED == TRUE 219/******************************************************************************* 220** 221** Function sdp_connect_cfm 222** 223** Description This function handles the connect confirm events 224** from L2CAP. This is the case when we are acting as a 225** client and have sent a connect request. 226** 227** Returns void 228** 229*******************************************************************************/ 230static void sdp_connect_cfm (UINT16 l2cap_cid, UINT16 result) 231{ 232 tCONN_CB *p_ccb; 233 tL2CAP_CFG_INFO cfg; 234 235 /* Find CCB based on CID */ 236 if ((p_ccb = sdpu_find_ccb_by_cid (l2cap_cid)) == NULL) 237 { 238 SDP_TRACE_WARNING ("SDP - Rcvd conn cnf for unknown CID 0x%x", l2cap_cid); 239 return; 240 } 241 242 /* If the connection response contains success status, then */ 243 /* Transition to the next state and startup the timer. */ 244 if ((result == L2CAP_CONN_OK) && (p_ccb->con_state == SDP_STATE_CONN_SETUP)) 245 { 246 p_ccb->con_state = SDP_STATE_CFG_SETUP; 247 248 cfg = sdp_cb.l2cap_my_cfg; 249 250 if (cfg.fcr_present) 251 { 252 SDP_TRACE_DEBUG("sdp_connect_cfm: mode %u, txwinsz %u, max_trans %u, rtrans_tout %u, mon_tout %u, mps %u", 253 cfg.fcr.mode, cfg.fcr.tx_win_sz, cfg.fcr.max_transmit, 254 cfg.fcr.rtrans_tout,cfg.fcr.mon_tout, cfg.fcr.mps); 255 } 256 257 if ((!L2CA_ConfigReq (l2cap_cid, &cfg)) && cfg.fcr_present 258 && cfg.fcr.mode != L2CAP_FCR_BASIC_MODE) 259 { 260 /* FCR not desired; try again in basic mode */ 261 cfg.fcr_present = FALSE; 262 cfg.fcr.mode = L2CAP_FCR_BASIC_MODE; 263 L2CA_ConfigReq (l2cap_cid, &cfg); 264 } 265 266 SDP_TRACE_EVENT ("SDP - got conn cnf, sent cfg req, CID: 0x%x", p_ccb->connection_id); 267 } 268 else 269 { 270 SDP_TRACE_WARNING ("SDP - Rcvd conn cnf with error: 0x%x CID 0x%x", result, p_ccb->connection_id); 271 272 /* Tell the user if he has a callback */ 273 if (p_ccb->p_cb || p_ccb->p_cb2) 274 { 275 UINT16 err = -1; 276 if ((result == HCI_ERR_HOST_REJECT_SECURITY) 277 || (result == HCI_ERR_AUTH_FAILURE) 278 || (result == HCI_ERR_PAIRING_NOT_ALLOWED) 279 || (result == HCI_ERR_PAIRING_WITH_UNIT_KEY_NOT_SUPPORTED) 280 || (result == HCI_ERR_KEY_MISSING)) 281 err = SDP_SECURITY_ERR; 282 else if (result == HCI_ERR_HOST_REJECT_DEVICE) 283 err = SDP_CONN_REJECTED; 284 else 285 err = SDP_CONN_FAILED; 286 if(p_ccb->p_cb) 287 (*p_ccb->p_cb)(err); 288 else if(p_ccb->p_cb2) 289 (*p_ccb->p_cb2)(err, p_ccb->user_data); 290 291 } 292 sdpu_release_ccb (p_ccb); 293 } 294} 295#endif /* SDP_CLIENT_ENABLED == TRUE */ 296 297 298/******************************************************************************* 299** 300** Function sdp_config_ind 301** 302** Description This function processes the L2CAP configuration indication 303** event. 304** 305** Returns void 306** 307*******************************************************************************/ 308static void sdp_config_ind (UINT16 l2cap_cid, tL2CAP_CFG_INFO *p_cfg) 309{ 310 tCONN_CB *p_ccb; 311 312 /* Find CCB based on CID */ 313 if ((p_ccb = sdpu_find_ccb_by_cid (l2cap_cid)) == NULL) 314 { 315 SDP_TRACE_WARNING ("SDP - Rcvd L2CAP cfg ind, unknown CID: 0x%x", l2cap_cid); 316 return; 317 } 318 319 /* Remember the remote MTU size */ 320 if (!p_cfg->mtu_present) 321 { 322 /* use min(L2CAP_DEFAULT_MTU,SDP_MTU_SIZE) for GKI buffer size reasons */ 323 p_ccb->rem_mtu_size = (L2CAP_DEFAULT_MTU > SDP_MTU_SIZE)?SDP_MTU_SIZE:L2CAP_DEFAULT_MTU; 324 } 325 else 326 { 327 if (p_cfg->mtu > SDP_MTU_SIZE) 328 p_ccb->rem_mtu_size = SDP_MTU_SIZE; 329 else 330 p_ccb->rem_mtu_size = p_cfg->mtu; 331 } 332 333 /* For now, always accept configuration from the other side */ 334 p_cfg->flush_to_present = FALSE; 335 p_cfg->mtu_present = FALSE; 336 p_cfg->result = L2CAP_CFG_OK; 337 338 /* Check peer config request against our rfcomm configuration */ 339 if (p_cfg->fcr_present) 340 { 341 /* Reject the window size if it is bigger than we want it to be */ 342 if (p_cfg->fcr.mode != L2CAP_FCR_BASIC_MODE) 343 { 344 if (sdp_cb.l2cap_my_cfg.fcr.mode != L2CAP_FCR_BASIC_MODE 345 && p_cfg->fcr.tx_win_sz > sdp_cb.l2cap_my_cfg.fcr.tx_win_sz) 346 { 347 p_cfg->fcr.tx_win_sz = sdp_cb.l2cap_my_cfg.fcr.tx_win_sz; 348 p_cfg->result = L2CAP_CFG_UNACCEPTABLE_PARAMS; 349 SDP_TRACE_DEBUG("sdp_config_ind(CONFIG) -> Please try again with SMALLER TX WINDOW"); 350 } 351 352 /* Reject if locally we want basic and they don't */ 353 if (sdp_cb.l2cap_my_cfg.fcr.mode == L2CAP_FCR_BASIC_MODE) 354 { 355 /* Ask for a new setup */ 356 p_cfg->fcr.mode = L2CAP_FCR_BASIC_MODE; 357 p_cfg->result = L2CAP_CFG_UNACCEPTABLE_PARAMS; 358 SDP_TRACE_DEBUG("sdp_config_ind(CONFIG) -> Please try again with BASIC mode"); 359 } 360 /* Remain in configure state and give the peer our desired configuration */ 361 if (p_cfg->result != L2CAP_CFG_OK) 362 { 363 SDP_TRACE_WARNING ("SDP - Rcvd cfg ind, Unacceptable Parameters sent cfg cfm, CID: 0x%x", l2cap_cid); 364 L2CA_ConfigRsp (l2cap_cid, p_cfg); 365 return; 366 } 367 } 368 else /* We agree with peer's request */ 369 p_cfg->fcr_present = FALSE; 370 } 371 372 L2CA_ConfigRsp (l2cap_cid, p_cfg); 373 374 SDP_TRACE_EVENT ("SDP - Rcvd cfg ind, sent cfg cfm, CID: 0x%x", l2cap_cid); 375 376 p_ccb->con_flags |= SDP_FLAGS_HIS_CFG_DONE; 377 378 if (p_ccb->con_flags & SDP_FLAGS_MY_CFG_DONE) 379 { 380 p_ccb->con_state = SDP_STATE_CONNECTED; 381 382 if (p_ccb->con_flags & SDP_FLAGS_IS_ORIG) 383 sdp_disc_connected (p_ccb); 384 else 385 /* Start inactivity timer */ 386 btu_start_timer (&p_ccb->timer_entry, BTU_TTYPE_SDP, SDP_INACT_TIMEOUT); 387 } 388 389} 390 391 392/******************************************************************************* 393** 394** Function sdp_config_cfm 395** 396** Description This function processes the L2CAP configuration confirmation 397** event. 398** 399** Returns void 400** 401*******************************************************************************/ 402static void sdp_config_cfm (UINT16 l2cap_cid, tL2CAP_CFG_INFO *p_cfg) 403{ 404 tCONN_CB *p_ccb; 405 406 SDP_TRACE_EVENT ("SDP - Rcvd cfg cfm, CID: 0x%x Result: %d", l2cap_cid, p_cfg->result); 407 408 /* Find CCB based on CID */ 409 if ((p_ccb = sdpu_find_ccb_by_cid (l2cap_cid)) == NULL) 410 { 411 SDP_TRACE_WARNING ("SDP - Rcvd L2CAP cfg ind, unknown CID: 0x%x", l2cap_cid); 412 return; 413 } 414 415 /* For now, always accept configuration from the other side */ 416 if (p_cfg->result == L2CAP_CFG_OK) 417 { 418 p_ccb->con_flags |= SDP_FLAGS_MY_CFG_DONE; 419 420 if (p_ccb->con_flags & SDP_FLAGS_HIS_CFG_DONE) 421 { 422 p_ccb->con_state = SDP_STATE_CONNECTED; 423 424 if (p_ccb->con_flags & SDP_FLAGS_IS_ORIG) 425 sdp_disc_connected (p_ccb); 426 else 427 /* Start inactivity timer */ 428 btu_start_timer (&p_ccb->timer_entry, BTU_TTYPE_SDP, SDP_INACT_TIMEOUT); 429 } 430 } 431 else 432 { 433 /* If peer has rejected FCR and suggested basic then try basic */ 434 if (p_cfg->fcr_present) 435 { 436 tL2CAP_CFG_INFO cfg = sdp_cb.l2cap_my_cfg; 437 cfg.fcr_present = FALSE; 438 L2CA_ConfigReq (l2cap_cid, &cfg); 439 440 /* Remain in configure state */ 441 return; 442 } 443 444#if SDP_CLIENT_ENABLED == TRUE 445 sdp_disconnect(p_ccb, SDP_CFG_FAILED); 446#endif 447 } 448} 449 450/******************************************************************************* 451** 452** Function sdp_disconnect_ind 453** 454** Description This function handles a disconnect event from L2CAP. If 455** requested to, we ack the disconnect before dropping the CCB 456** 457** Returns void 458** 459*******************************************************************************/ 460static void sdp_disconnect_ind (UINT16 l2cap_cid, BOOLEAN ack_needed) 461{ 462 tCONN_CB *p_ccb; 463 464 /* Find CCB based on CID */ 465 if ((p_ccb = sdpu_find_ccb_by_cid (l2cap_cid)) == NULL) 466 { 467 SDP_TRACE_WARNING ("SDP - Rcvd L2CAP disc, unknown CID: 0x%x", l2cap_cid); 468 return; 469 } 470 471 if (ack_needed) 472 L2CA_DisconnectRsp (l2cap_cid); 473 474 SDP_TRACE_EVENT ("SDP - Rcvd L2CAP disc, CID: 0x%x", l2cap_cid); 475#if SDP_CLIENT_ENABLED == TRUE 476 /* Tell the user if he has a callback */ 477 if (p_ccb->p_cb) 478 (*p_ccb->p_cb) ((UINT16) ((p_ccb->con_state == SDP_STATE_CONNECTED) ? 479 SDP_SUCCESS : SDP_CONN_FAILED)); 480 else if (p_ccb->p_cb2) 481 (*p_ccb->p_cb2) ((UINT16) ((p_ccb->con_state == SDP_STATE_CONNECTED) ? 482 SDP_SUCCESS : SDP_CONN_FAILED), p_ccb->user_data); 483 484#endif 485 sdpu_release_ccb (p_ccb); 486} 487 488/******************************************************************************* 489** 490** Function sdp_data_ind 491** 492** Description This function is called when data is received from L2CAP. 493** if we are the originator of the connection, we are the SDP 494** client, and the received message is queued up for the client. 495** 496** If we are the destination of the connection, we are the SDP 497** server, so the message is passed to the server processing 498** function. 499** 500** Returns void 501** 502*******************************************************************************/ 503static void sdp_data_ind (UINT16 l2cap_cid, BT_HDR *p_msg) 504{ 505 tCONN_CB *p_ccb; 506 507 /* Find CCB based on CID */ 508 if ((p_ccb = sdpu_find_ccb_by_cid (l2cap_cid)) != NULL) 509 { 510 if (p_ccb->con_state == SDP_STATE_CONNECTED) 511 { 512 if (p_ccb->con_flags & SDP_FLAGS_IS_ORIG) 513 sdp_disc_server_rsp (p_ccb, p_msg); 514 else 515 sdp_server_handle_client_req (p_ccb, p_msg); 516 } 517 else 518 { 519 SDP_TRACE_WARNING ("SDP - Ignored L2CAP data while in state: %d, CID: 0x%x", 520 p_ccb->con_state, l2cap_cid); 521 } 522 } 523 else 524 { 525 SDP_TRACE_WARNING ("SDP - Rcvd L2CAP data, unknown CID: 0x%x", l2cap_cid); 526 } 527 528 GKI_freebuf (p_msg); 529} 530 531 532#if SDP_CLIENT_ENABLED == TRUE 533/******************************************************************************* 534** 535** Function sdp_conn_originate 536** 537** Description This function is called from the API to originate a 538** connection. 539** 540** Returns void 541** 542*******************************************************************************/ 543tCONN_CB* sdp_conn_originate (UINT8 *p_bd_addr) 544{ 545 tCONN_CB *p_ccb; 546 UINT16 cid; 547 548 /* Allocate a new CCB. Return if none available. */ 549 if ((p_ccb = sdpu_allocate_ccb()) == NULL) 550 { 551 SDP_TRACE_WARNING ("SDP - no spare CCB for orig"); 552 return (NULL); 553 } 554 555 SDP_TRACE_EVENT ("SDP - Originate started"); 556 557 /* We are the originator of this connection */ 558 p_ccb->con_flags |= SDP_FLAGS_IS_ORIG; 559 560 /* Save the BD Address and Channel ID. */ 561 memcpy (&p_ccb->device_address[0], p_bd_addr, sizeof (BD_ADDR)); 562 563 /* Transition to the next appropriate state, waiting for connection confirm. */ 564 p_ccb->con_state = SDP_STATE_CONN_SETUP; 565 566// btla-specific ++ 567#ifndef ANDROID_APP_INCLUDED /* Skip for Android: Do not need to set out_service for sdp, since sdp does not use sec. Prevents over-writing service_rec of a connection already in progress */ 568 BTM_SetOutService(p_bd_addr, BTM_SEC_SERVICE_SDP_SERVER, 0); 569#endif 570// btla-specific -- 571 572 cid = L2CA_ConnectReq (SDP_PSM, p_bd_addr); 573 574 /* Check if L2CAP started the connection process */ 575 if (cid != 0) 576 { 577 p_ccb->connection_id = cid; 578 579 return (p_ccb); 580 } 581 else 582 { 583 SDP_TRACE_WARNING ("SDP - Originate failed"); 584 sdpu_release_ccb (p_ccb); 585 return (NULL); 586 } 587} 588 589/******************************************************************************* 590** 591** Function sdp_disconnect 592** 593** Description This function disconnects a connection. 594** 595** Returns void 596** 597*******************************************************************************/ 598void sdp_disconnect (tCONN_CB*p_ccb, UINT16 reason) 599{ 600#if (defined(SDP_BROWSE_PLUS) && SDP_BROWSE_PLUS == TRUE) 601 602 /* If we are browsing for multiple UUIDs ... */ 603 if ((p_ccb->con_state == SDP_STATE_CONNECTED) 604 && (p_ccb->con_flags & SDP_FLAGS_IS_ORIG) 605 && ((reason == SDP_SUCCESS) || (reason == SDP_NO_RECS_MATCH))) 606 { 607 /* If the browse found something, do no more searching */ 608 if ((p_ccb->cur_uuid_idx == 0) && (p_ccb->p_db->p_first_rec)) 609 p_ccb->cur_uuid_idx = p_ccb->p_db->num_uuid_filters; 610 611 while (++p_ccb->cur_uuid_idx < p_ccb->p_db->num_uuid_filters) 612 { 613 /* Check we have not already found the UUID (maybe through browse) */ 614 if ((p_ccb->p_db->uuid_filters[p_ccb->cur_uuid_idx].len == 2) 615 && (SDP_FindServiceInDb (p_ccb->p_db, 616 p_ccb->p_db->uuid_filters[p_ccb->cur_uuid_idx].uu.uuid16, 617 NULL))) 618 continue; 619 620 if ((p_ccb->p_db->uuid_filters[p_ccb->cur_uuid_idx].len > 2) 621 && (SDP_FindServiceUUIDInDb (p_ccb->p_db, 622 &p_ccb->p_db->uuid_filters[p_ccb->cur_uuid_idx], NULL))) 623 continue; 624 625 p_ccb->cur_handle = 0; 626 627 SDP_TRACE_EVENT ("SDP - looking for for more, CID: 0x%x", 628 p_ccb->connection_id); 629 630 sdp_disc_connected (p_ccb); 631 return; 632 } 633 } 634 635 if ((reason == SDP_NO_RECS_MATCH) && (p_ccb->p_db->p_first_rec)) 636 reason = SDP_SUCCESS; 637 638#endif 639 640 SDP_TRACE_EVENT ("SDP - disconnect CID: 0x%x", p_ccb->connection_id); 641 642 /* Check if we have a connection ID */ 643 if (p_ccb->connection_id != 0) 644 { 645 L2CA_DisconnectReq (p_ccb->connection_id); 646 p_ccb->disconnect_reason = reason; 647 } 648 649 /* If at setup state, we may not get callback ind from L2CAP */ 650 /* Call user callback immediately */ 651 if (p_ccb->con_state == SDP_STATE_CONN_SETUP) 652 { 653 /* Tell the user if he has a callback */ 654 if (p_ccb->p_cb) 655 (*p_ccb->p_cb) (reason); 656 else if (p_ccb->p_cb2) 657 (*p_ccb->p_cb2) (reason, p_ccb->user_data); 658 659 sdpu_release_ccb (p_ccb); 660 } 661 662} 663 664/******************************************************************************* 665** 666** Function sdp_disconnect_cfm 667** 668** Description This function handles a disconnect confirm event from L2CAP. 669** 670** Returns void 671** 672*******************************************************************************/ 673static void sdp_disconnect_cfm (UINT16 l2cap_cid, UINT16 result) 674{ 675 tCONN_CB *p_ccb; 676 UNUSED(result); 677 678 /* Find CCB based on CID */ 679 if ((p_ccb = sdpu_find_ccb_by_cid (l2cap_cid)) == NULL) 680 { 681 SDP_TRACE_WARNING ("SDP - Rcvd L2CAP disc cfm, unknown CID: 0x%x", l2cap_cid); 682 return; 683 } 684 685 SDP_TRACE_EVENT ("SDP - Rcvd L2CAP disc cfm, CID: 0x%x", l2cap_cid); 686 687 /* Tell the user if he has a callback */ 688 if (p_ccb->p_cb) 689 (*p_ccb->p_cb) (p_ccb->disconnect_reason); 690 else if (p_ccb->p_cb2) 691 (*p_ccb->p_cb2) (p_ccb->disconnect_reason, p_ccb->user_data); 692 693 694 sdpu_release_ccb (p_ccb); 695} 696 697#endif /* SDP_CLIENT_ENABLED == TRUE */ 698 699/******************************************************************************* 700** 701** Function sdp_conn_timeout 702** 703** Description This function processes a timeout. Currently, we simply send 704** a disconnect request to L2CAP. 705** 706** Returns void 707** 708*******************************************************************************/ 709void sdp_conn_timeout (tCONN_CB*p_ccb) 710{ 711 SDP_TRACE_EVENT ("SDP - CCB timeout in state: %d CID: 0x%x", 712 p_ccb->con_state, p_ccb->connection_id); 713 714 L2CA_DisconnectReq (p_ccb->connection_id); 715#if SDP_CLIENT_ENABLED == TRUE 716 /* Tell the user if he has a callback */ 717 if (p_ccb->p_cb) 718 (*p_ccb->p_cb) (SDP_CONN_FAILED); 719 else if (p_ccb->p_cb2) 720 (*p_ccb->p_cb2) (SDP_CONN_FAILED, p_ccb->user_data); 721#endif 722 sdpu_release_ccb (p_ccb); 723} 724 725 726 727 728