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