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