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